text: 'use strict';
  
  Object.defineProperty(exports, '__esModule', { value: true });
  
  function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
  
  var universalUserAgent = require('universal-user-agent');
  var request = require('@octokit/request');
  var authOauthDevice = require('@octokit/auth-oauth-device');
  var oauthMethods = require('@octokit/oauth-methods');
  var btoa = _interopDefault(require('btoa-lite'));
  
  function ownKeys(object, enumerableOnly) {
    var keys = Object.keys(object);
  
    if (Object.getOwnPropertySymbols) {
      var symbols = Object.getOwnPropertySymbols(object);
  
      if (enumerableOnly) {
        symbols = symbols.filter(function (sym) {
          return Object.getOwnPropertyDescriptor(object, sym).enumerable;
        });
      }
  
      keys.push.apply(keys, symbols);
    }
  
    return keys;
  }
  
  function _objectSpread2(target) {
    for (var i = 1; i < arguments.length; i++) {
      var source = arguments[i] != null ? arguments[i] : {};
  
      if (i % 2) {
        ownKeys(Object(source), true).forEach(function (key) {
          _defineProperty(target, key, source[key]);
        });
      } else if (Object.getOwnPropertyDescriptors) {
        Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
      } else {
        ownKeys(Object(source)).forEach(function (key) {
          Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
        });
      }
    }
  
    return target;
  }
  
  function _defineProperty(obj, key, value) {
    if (key in obj) {
      Object.defineProperty(obj, key, {
        value: value,
        enumerable: true,
        configurable: true,
        writable: true
      });
    } else {
      obj[key] = value;
    }
  
    return obj;
  }
  
  function _objectWithoutPropertiesLoose(source, excluded) {
    if (source == null) return {};
    var target = {};
    var sourceKeys = Object.keys(source);
    var key, i;
  
    for (i = 0; i < sourceKeys.length; i++) {
      key = sourceKeys[i];
      if (excluded.indexOf(key) >= 0) continue;
      target[key] = source[key];
    }
  
    return target;
  }
  
  function _objectWithoutProperties(source, excluded) {
    if (source == null) return {};
  
    var target = _objectWithoutPropertiesLoose(source, excluded);
  
    var key, i;
  
    if (Object.getOwnPropertySymbols) {
      var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
  
      for (i = 0; i < sourceSymbolKeys.length; i++) {
        key = sourceSymbolKeys[i];
        if (excluded.indexOf(key) >= 0) continue;
        if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
        target[key] = source[key];
      }
    }
  
    return target;
  }
  
  const VERSION = "1.3.0";
  
  async function getAuthentication(state) {
    // handle code exchange form OAuth Web Flow
    if ("code" in state.strategyOptions) {
      const {
        authentication
      } = await oauthMethods.exchangeWebFlowCode(_objectSpread2(_objectSpread2({
        clientId: state.clientId,
        clientSecret: state.clientSecret,
        clientType: state.clientType
      }, state.strategyOptions), {}, {
        request: state.request
      }));
      return _objectSpread2({
        type: "token",
        tokenType: "oauth"
      }, authentication);
    } // handle OAuth device flow
  
  
    if ("onVerification" in state.strategyOptions) {
      const deviceAuth = authOauthDevice.createOAuthDeviceAuth(_objectSpread2(_objectSpread2({
        clientType: state.clientType,
        clientId: state.clientId
      }, state.strategyOptions), {}, {
        request: state.request
      }));
      const authentication = await deviceAuth({
        type: "oauth"
      });
      return _objectSpread2({
        clientSecret: state.clientSecret
      }, authentication);
    } // use existing authentication
  
  
    if ("token" in state.strategyOptions) {
      return _objectSpread2({
        type: "token",
        tokenType: "oauth",
        clientId: state.clientId,
        clientSecret: state.clientSecret,
        clientType: state.clientType
      }, state.strategyOptions);
    }
  
    throw new Error("[@octokit/auth-oauth-user] Invalid strategy options");
  }
  
  async function auth(state, options = {}) {
    if (!state.authentication) {
      // This is what TS makes us do ¯\_(ツ)_/¯
      state.authentication = state.clientType === "oauth-app" ? await getAuthentication(state) : await getAuthentication(state);
    }
  
    if (state.authentication.invalid) {
      throw new Error("[@octokit/auth-oauth-user] Token is invalid");
    }
  
    const currentAuthentication = state.authentication; // (auto) refresh for user-to-server tokens
  
    if ("expiresAt" in currentAuthentication) {
      if (options.type === "refresh" || new Date(currentAuthentication.expiresAt) < new Date()) {
        const {
          authentication
        } = await oauthMethods.refreshToken({
          clientType: "github-app",
          clientId: state.clientId,
          clientSecret: state.clientSecret,
          refreshToken: currentAuthentication.refreshToken,
          request: state.request
        });
        state.authentication = _objectSpread2({
          tokenType: "oauth",
          type: "token"
        }, authentication);
      }
    } // throw error for invalid refresh call
  
  
    if (options.type === "refresh") {
      if (state.clientType === "oauth-app") {
        throw new Error("[@octokit/auth-oauth-user] OAuth Apps do not support expiring tokens");
      }
  
      if (!currentAuthentication.hasOwnProperty("expiresAt")) {
        throw new Error("[@octokit/auth-oauth-user] Refresh token missing");
      }
    } // check or reset token
  
  
    if (options.type === "check" || options.type === "reset") {
      const method = options.type === "check" ? oauthMethods.checkToken : oauthMethods.resetToken;
  
      try {
        const {
          authentication
        } = await method({
          // @ts-expect-error making TS happy would require unnecessary code so no
          clientType: state.clientType,
          clientId: state.clientId,
          clientSecret: state.clientSecret,
          token: state.authentication.token,
          request: state.request
        });
        state.authentication = _objectSpread2({
          tokenType: "oauth",
          type: "token"
        }, authentication);
        return state.authentication;
      } catch (error) {
        // istanbul ignore else
        if (error.status === 404) {
          error.message = "[@octokit/auth-oauth-user] Token is invalid"; // @ts-expect-error TBD
  
          state.authentication.invalid = true;
        }
  
        throw error;
      }
    } // invalidate
  
  
    if (options.type === "delete" || options.type === "deleteAuthorization") {
      const method = options.type === "delete" ? oauthMethods.deleteToken : oauthMethods.deleteAuthorization;
  
      try {
        await method({
          // @ts-expect-error making TS happy would require unnecessary code so no
          clientType: state.clientType,
          clientId: state.clientId,
          clientSecret: state.clientSecret,
          token: state.authentication.token,
          request: state.request
        });
      } catch (error) {
        // istanbul ignore if
        if (error.status !== 404) throw error;
      }
  
      state.authentication.invalid = true;
      return state.authentication;
    }
  
    return state.authentication;
  }
  
  /**
   * The following endpoints require an OAuth App to authenticate using its client_id and client_secret.
   *
   * - [`POST /applications/{client_id}/token`](https://docs.github.com/en/rest/reference/apps#check-a-token) - Check a token
   * - [`PATCH /applications/{client_id}/token`](https://docs.github.com/en/rest/reference/apps#reset-a-token) - Reset a token
   * - [`POST /applications/{client_id}/token/scoped`](https://docs.github.com/en/rest/reference/apps#create-a-scoped-access-token) - Create a scoped access token
   * - [`DELETE /applications/{client_id}/token`](https://docs.github.com/en/rest/reference/apps#delete-an-app-token) - Delete an app token
   * - [`DELETE /applications/{client_id}/grant`](https://docs.github.com/en/rest/reference/apps#delete-an-app-authorization) - Delete an app authorization
   *
   * deprecated:
   *
   * - [`GET /applications/{client_id}/tokens/{access_token}`](https://docs.github.com/en/rest/reference/apps#check-an-authorization) - Check an authorization
   * - [`POST /applications/{client_id}/tokens/{access_token}`](https://docs.github.com/en/rest/reference/apps#reset-an-authorization) - Reset an authorization
   * - [`DELETE /applications/{client_id}/tokens/{access_token}`](https://docs.github.com/en/rest/reference/apps#revoke-an-authorization-for-an-application) - Revoke an authorization for an application
   * - [`DELETE /applications/{client_id}/grants/{access_token}`](https://docs.github.com/en/rest/reference/apps#revoke-a-grant-for-an-application) - Revoke a grant for an application
   */
  const ROUTES_REQUIRING_BASIC_AUTH = /\/applications\/[^/]+\/(token|grant)s?/;
  function requiresBasicAuth(url) {
    return url && ROUTES_REQUIRING_BASIC_AUTH.test(url);
  }
  
  async function hook(state, request, route, parameters = {}) {
    const endpoint = request.endpoint.merge(route, parameters); // Do not intercept OAuth Web/Device flow request
  
    if (/\/login\/(oauth\/access_token|device\/code)$/.test(endpoint.url)) {
      return request(endpoint);
    }
  
    if (requiresBasicAuth(endpoint.url)) {
      const credentials = btoa(`${state.clientId}:${state.clientSecret}`);
      endpoint.headers.authorization = `basic ${credentials}`;
      return request(endpoint);
    } // TS makes us do this ¯\_(ツ)_/¯
  
  
    const {
      token
    } = state.clientType === "oauth-app" ? await auth(_objectSpread2(_objectSpread2({}, state), {}, {
      request
    })) : await auth(_objectSpread2(_objectSpread2({}, state), {}, {
      request
    }));
    endpoint.headers.authorization = "token " + token;
    return request(endpoint);
  }
  
  const _excluded = ["clientId", "clientSecret", "clientType", "request"];
  function createOAuthUserAuth(_ref) {
    let {
      clientId,
      clientSecret,
      clientType = "oauth-app",
      request: request$1 = request.request.defaults({
        headers: {
          "user-agent": `octokit-auth-oauth-app.js/${VERSION} ${universalUserAgent.getUserAgent()}`
        }
      })
    } = _ref,
        strategyOptions = _objectWithoutProperties(_ref, _excluded);
  
    const state = Object.assign({
      clientType,
      clientId,
      clientSecret,
      strategyOptions,
      request: request$1
    }); // @ts-expect-error not worth the extra code needed to appease TS
  
    return Object.assign(auth.bind(null, state), {
      // @ts-expect-error not worth the extra code needed to appease TS
      hook: hook.bind(null, state)
    });
  }
  createOAuthUserAuth.VERSION = VERSION;
  
  exports.createOAuthUserAuth = createOAuthUserAuth;
  exports.requiresBasicAuth = requiresBasicAuth;
  //# sourceMappingURL=index.js.map
  