{"version":3,"sources":["../src/index.ts","../src/error.ts","../src/utils/axios.ts","../src/utils/package.ts","../src/types/scope.ts"],"sourcesContent":["import process from 'node:process'\n\nimport {AxiosError} from 'axios'\nimport {type RequireExactlyOne} from 'type-fest'\n\nimport {SellingPartnerApiAuthError} from './error.js'\nimport {type AccessTokenData, type AccessTokenQuery} from './types/access-token.js'\nimport {type AuthorizationScope} from './types/scope.js'\nimport {axios} from './utils/axios.js'\n\n/**\n * Configuration parameters for Selling Partner API authentication.\n *\n * Both `clientId` and `clientSecret` fall back to the `LWA_CLIENT_ID` and\n * `LWA_CLIENT_SECRET` environment variables when omitted.\n * `refreshToken` falls back to `LWA_REFRESH_TOKEN`.\n */\nexport interface SellingPartnerAuthParameters {\n  /** LWA client identifier. Defaults to the `LWA_CLIENT_ID` environment variable. */\n  clientId?: string\n  /** LWA client secret. Defaults to the `LWA_CLIENT_SECRET` environment variable. */\n  clientSecret?: string\n  /** LWA refresh token. Defaults to the `LWA_REFRESH_TOKEN` environment variable. Mutually exclusive with `scopes`. */\n  refreshToken?: string\n  /** Authorization scopes for grantless operations. Mutually exclusive with `refreshToken`. */\n  scopes?: AuthorizationScope[]\n}\n\n/**\n * Handles Login with Amazon (LWA) OAuth token management for the Selling Partner API.\n *\n * Supports both refresh-token and grantless (scope-based) authentication flows.\n * Tokens are cached and automatically refreshed when expired. Concurrent calls\n * to {@link getAccessToken} are deduplicated into a single request.\n */\nexport class SellingPartnerApiAuth {\n  private readonly clientId: string\n  private readonly clientSecret: string\n  private readonly refreshToken?: string\n  private readonly scopes?: AuthorizationScope[]\n\n  #accessToken?: string\n  #accessTokenExpiration?: Date\n  #pendingTokenRequest?: Promise<string>\n\n  constructor(\n    parameters: RequireExactlyOne<SellingPartnerAuthParameters, 'refreshToken' | 'scopes'>,\n  ) {\n    const clientId = parameters.clientId ?? process.env.LWA_CLIENT_ID\n    const clientSecret = parameters.clientSecret ?? process.env.LWA_CLIENT_SECRET\n    const refreshToken = parameters.refreshToken ?? process.env.LWA_REFRESH_TOKEN\n\n    if (!clientId) {\n      throw new Error('Missing required `clientId` configuration value')\n    }\n\n    if (!clientSecret) {\n      throw new Error('Missing required `clientSecret` configuration value')\n    }\n\n    if (!refreshToken && !parameters.scopes) {\n      throw new TypeError('Either `refreshToken` or `scopes` must be specified')\n    }\n\n    this.clientId = clientId\n    this.clientSecret = clientSecret\n\n    this.refreshToken = refreshToken\n    this.scopes = parameters.scopes\n  }\n\n  /**\n   * Returns a valid LWA access token, refreshing it if expired.\n   *\n   * Concurrent calls while a refresh is in progress share the same request.\n   *\n   * @returns The access token string.\n   */\n  async getAccessToken() {\n    if (\n      this.#accessToken &&\n      (!this.#accessTokenExpiration || Date.now() < this.#accessTokenExpiration.getTime())\n    ) {\n      return this.#accessToken\n    }\n\n    // Deduplicate concurrent calls: share the same in-flight request\n    if (this.#pendingTokenRequest) {\n      return this.#pendingTokenRequest\n    }\n\n    this.#pendingTokenRequest = this.#refreshAccessToken()\n\n    try {\n      return await this.#pendingTokenRequest\n    } finally {\n      this.#pendingTokenRequest = undefined\n    }\n  }\n\n  async #refreshAccessToken() {\n    const body: AccessTokenQuery = {\n      client_id: this.clientId,\n      client_secret: this.clientSecret,\n      ...(this.refreshToken\n        ? {\n            grant_type: 'refresh_token',\n            refresh_token: this.refreshToken,\n          }\n        : {\n            grant_type: 'client_credentials',\n            scope: this.scopes!.join(' '),\n          }),\n    }\n\n    try {\n      const expiration = new Date()\n\n      const {data} = await axios.post<AccessTokenData>('/o2/token', body)\n\n      expiration.setSeconds(expiration.getSeconds() + data.expires_in)\n\n      this.#accessToken = data.access_token\n      this.#accessTokenExpiration = expiration\n\n      return data.access_token\n    } catch (error: unknown) {\n      if (error instanceof AxiosError) {\n        throw new SellingPartnerApiAuthError(error)\n      }\n\n      throw error\n    }\n  }\n\n  /**\n   * Expiration date of the currently cached access token, or `undefined` if no token has been fetched yet.\n   */\n  protected get accessTokenExpiration() {\n    return this.#accessTokenExpiration\n  }\n}\n\nexport {SellingPartnerApiAuthError} from './error.js'\nexport {AuthorizationScope} from './types/scope.js'\n","import {AxiosError} from 'axios'\n\nimport type {AccessTokenData, AccessTokenQuery} from './types/access-token.js'\n\n/**\n * Error thrown when an LWA token request fails.\n *\n * Wraps the underlying Axios error with a human-readable message that includes\n * the HTTP status code (or \"No response\" for network errors).\n */\nexport class SellingPartnerApiAuthError extends AxiosError<AccessTokenData, AccessTokenQuery> {\n  /** The original error message from the failed HTTP request. */\n  public readonly innerMessage: string\n\n  constructor(error: AxiosError<AccessTokenData, AccessTokenQuery>) {\n    const message = error.response\n      ? `access-token error: Response code ${error.response.status}`\n      : 'access-token error: No response'\n\n    super(message, error.code, error.config, error.request, error.response)\n\n    this.innerMessage = error.message\n    this.name = this.constructor.name\n  }\n}\n","import globalAxios from 'axios'\n\nimport {packageJson} from './package.js'\n\nexport const axios = globalAxios.create({\n  baseURL: 'https://api.amazon.com/auth/',\n  timeout: 30_000,\n  headers: {\n    'user-agent': `${packageJson.name}/${packageJson.version}`,\n  },\n})\n","import {type NormalizedPackageJson, sync as readPackageJson} from 'read-pkg-up'\n\nconst result = readPackageJson()\n\nexport const packageJson: NormalizedPackageJson = result?.packageJson ?? {\n  _id: '',\n  readme: '',\n  name: '@sp-api-sdk/auth',\n  version: 'unknown',\n}\n","/** Authorization scopes for grantless Selling Partner API operations. */\nexport enum AuthorizationScope {\n  /** Scope for the Notifications API. */\n  NOTIFICATIONS = 'sellingpartnerapi::notifications',\n  /** Scope for rotating application client credentials. */\n  CLIENT_CREDENTIAL_ROTATION = 'sellingpartnerapi::client_credential:rotation',\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,0BAAoB;AAEpB,IAAAA,gBAAyB;;;ACFzB,mBAAyB;AAUlB,IAAM,6BAAN,cAAyC,wBAA8C;AAAA;AAAA,EAE5E;AAAA,EAEhB,YAAY,OAAsD;AAChE,UAAM,UAAU,MAAM,WAClB,qCAAqC,MAAM,SAAS,MAAM,KAC1D;AAEJ,UAAM,SAAS,MAAM,MAAM,MAAM,QAAQ,MAAM,SAAS,MAAM,QAAQ;AAEtE,SAAK,eAAe,MAAM;AAC1B,SAAK,OAAO,KAAK,YAAY;AAAA,EAC/B;AACF;;;ACxBA,IAAAC,gBAAwB;;;ACAxB,yBAAkE;AAElE,IAAM,aAAS,mBAAAC,MAAgB;AAExB,IAAM,cAAqC,QAAQ,eAAe;AAAA,EACvE,KAAK;AAAA,EACL,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,SAAS;AACX;;;ADLO,IAAM,QAAQ,cAAAC,QAAY,OAAO;AAAA,EACtC,SAAS;AAAA,EACT,SAAS;AAAA,EACT,SAAS;AAAA,IACP,cAAc,GAAG,YAAY,IAAI,IAAI,YAAY,OAAO;AAAA,EAC1D;AACF,CAAC;;;AETM,IAAK,qBAAL,kBAAKC,wBAAL;AAEL,EAAAA,oBAAA,mBAAgB;AAEhB,EAAAA,oBAAA,gCAA6B;AAJnB,SAAAA;AAAA,GAAA;;;AJkCL,IAAM,wBAAN,MAA4B;AAAA,EAChB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEjB;AAAA,EACA;AAAA,EACA;AAAA,EAEA,YACE,YACA;AACA,UAAM,WAAW,WAAW,YAAY,oBAAAC,QAAQ,IAAI;AACpD,UAAM,eAAe,WAAW,gBAAgB,oBAAAA,QAAQ,IAAI;AAC5D,UAAM,eAAe,WAAW,gBAAgB,oBAAAA,QAAQ,IAAI;AAE5D,QAAI,CAAC,UAAU;AACb,YAAM,IAAI,MAAM,iDAAiD;AAAA,IACnE;AAEA,QAAI,CAAC,cAAc;AACjB,YAAM,IAAI,MAAM,qDAAqD;AAAA,IACvE;AAEA,QAAI,CAAC,gBAAgB,CAAC,WAAW,QAAQ;AACvC,YAAM,IAAI,UAAU,qDAAqD;AAAA,IAC3E;AAEA,SAAK,WAAW;AAChB,SAAK,eAAe;AAEpB,SAAK,eAAe;AACpB,SAAK,SAAS,WAAW;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,iBAAiB;AACrB,QACE,KAAK,iBACJ,CAAC,KAAK,0BAA0B,KAAK,IAAI,IAAI,KAAK,uBAAuB,QAAQ,IAClF;AACA,aAAO,KAAK;AAAA,IACd;AAGA,QAAI,KAAK,sBAAsB;AAC7B,aAAO,KAAK;AAAA,IACd;AAEA,SAAK,uBAAuB,KAAK,oBAAoB;AAErD,QAAI;AACF,aAAO,MAAM,KAAK;AAAA,IACpB,UAAE;AACA,WAAK,uBAAuB;AAAA,IAC9B;AAAA,EACF;AAAA,EAEA,MAAM,sBAAsB;AAC1B,UAAM,OAAyB;AAAA,MAC7B,WAAW,KAAK;AAAA,MAChB,eAAe,KAAK;AAAA,MACpB,GAAI,KAAK,eACL;AAAA,QACE,YAAY;AAAA,QACZ,eAAe,KAAK;AAAA,MACtB,IACA;AAAA,QACE,YAAY;AAAA,QACZ,OAAO,KAAK,OAAQ,KAAK,GAAG;AAAA,MAC9B;AAAA,IACN;AAEA,QAAI;AACF,YAAM,aAAa,oBAAI,KAAK;AAE5B,YAAM,EAAC,KAAI,IAAI,MAAM,MAAM,KAAsB,aAAa,IAAI;AAElE,iBAAW,WAAW,WAAW,WAAW,IAAI,KAAK,UAAU;AAE/D,WAAK,eAAe,KAAK;AACzB,WAAK,yBAAyB;AAE9B,aAAO,KAAK;AAAA,IACd,SAAS,OAAgB;AACvB,UAAI,iBAAiB,0BAAY;AAC/B,cAAM,IAAI,2BAA2B,KAAK;AAAA,MAC5C;AAEA,YAAM;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,IAAc,wBAAwB;AACpC,WAAO,KAAK;AAAA,EACd;AACF;","names":["import_axios","import_axios","readPackageJson","globalAxios","AuthorizationScope","process"]}