{"version":3,"sources":["../src/index.ts","../src/errors/TokenError.ts","../src/errors/InvalidTokenError.ts","../src/utils/base64.ts","../src/jwtDecode.ts","../src/utils/camelCaseToSnakeCase.ts","../src/utils/extractIssuer.ts","../src/utils/mapKeys.ts","../src/revoke.ts","../src/utils/hasOwner.ts","../src/utils/snakeCaseToCamelCase.ts","../src/authenticate.ts","../src/apiCredentials/dedupConcurrentCalls.ts","../src/apiCredentials/apiCredentials.ts","../src/apiCredentials/storage.ts","../src/apiCredentials/index.ts","../src/errors/TokenExpiredError.ts","../src/getCoreApiBaseEndpoint.ts","../src/getProvisioningApiBaseEndpoint.ts","../src/getTokenType.ts","../src/jwtEncode.ts","../src/utils/hasExpired.ts","../src/jwtVerify.ts"],"sourcesContent":["export {\n  type ApiCredentialsAuthorization,\n  createCompositeStorage,\n  makeIntegration,\n  makeSalesChannel,\n  type Storage,\n  type StorageValue,\n} from \"./apiCredentials/index.js\"\nexport { authenticate } from \"./authenticate.js\"\nexport { InvalidTokenError } from \"./errors/InvalidTokenError.js\"\nexport { TokenError } from \"./errors/TokenError.js\"\nexport { TokenExpiredError } from \"./errors/TokenExpiredError.js\"\nexport { getCoreApiBaseEndpoint } from \"./getCoreApiBaseEndpoint.js\"\nexport { getProvisioningApiBaseEndpoint } from \"./getProvisioningApiBaseEndpoint.js\"\nexport { getTokenType, type TokenType } from \"./getTokenType.js\"\nexport {\n  type CommerceLayerJWT,\n  type JWTDashboard,\n  type JWTIntegration,\n  type JWTSalesChannel,\n  type JWTUser,\n  type JWTWebApp,\n  jwtDecode,\n  jwtIsDashboard,\n  jwtIsIntegration,\n  jwtIsSalesChannel,\n  jwtIsUser,\n  jwtIsWebApp,\n} from \"./jwtDecode.js\"\nexport { createAssertion } from \"./jwtEncode.js\"\nexport { jwtVerify } from \"./jwtVerify.js\"\nexport { revoke } from \"./revoke.js\"\nexport type {\n  AuthenticateOptions,\n  AuthenticateReturn,\n  GrantType,\n  RevokeOptions,\n  RevokeReturn,\n} from \"./types/index.js\"\n","/**\n * A token error occurred.\n */\nexport class TokenError extends Error {\n  constructor(message: string) {\n    super(message)\n    this.name = \"TokenError\"\n  }\n}\n","import { TokenError } from \"./TokenError.js\"\n\n/**\n * The token is not valid.\n */\nexport class InvalidTokenError extends TokenError {\n  constructor(message: string) {\n    super(message)\n    this.name = \"InvalidTokenError\"\n  }\n}\n","/**\n * Creates a [Base64](https://developer.mozilla.org/en-US/docs/Glossary/Base64) URL safe encoded [ASCII](https://developer.mozilla.org/en-US/docs/Glossary/ASCII)\n * string from a _binary string_ (i.e., a string in which each character in the string is treated as a byte of binary data).\n *\n * The \"Base64 URL safe\" omits the padding `=` and replaces `+/` with `-_` to avoid characters that might cause problems in URL path segments or query parameters.\n *\n * This method works both in Node.js and browsers.\n *\n * @param stringToEncode The binary string to encode.\n * @returns An ASCII string containing the Base64 URL safe representation of `stringToEncode`.\n */\nexport function encodeBase64URLSafe(\n  stringToEncode: string,\n  encoding: \"utf-8\" | \"binary\",\n): string {\n  if (typeof btoa !== \"undefined\") {\n    let utf8String = stringToEncode\n\n    if (encoding === \"utf-8\") {\n      // Encode the string as UTF-8\n      const utf8Bytes = new TextEncoder().encode(stringToEncode)\n\n      // Convert the UTF-8 bytes to a Base64 string\n      utf8String = String.fromCharCode(...utf8Bytes)\n    }\n\n    return (\n      btoa(utf8String)\n        // Remove padding equal characters\n        .replaceAll(\"=\", \"\")\n        // Replace characters according to base64url specifications\n        .replaceAll(\"+\", \"-\")\n        .replaceAll(\"/\", \"_\")\n    )\n  }\n\n  return Buffer.from(stringToEncode, encoding).toString(\"base64url\")\n}\n\n/**\n * Decodes a string of data\n * which has been encoded using [Base64](https://developer.mozilla.org/en-US/docs/Glossary/Base64) URL safe encoding.\n *\n * The \"Base64 URL safe\" omits the padding `=` and replaces `+/` with `-_` to avoid characters that might cause problems in URL path segments or query parameters.\n *\n * This method works both in Node.js and browsers.\n *\n * @param encodedData A binary string (i.e., a string in which each character in the string is treated as a byte of binary data) containing Base64 URL safe -encoded data.\n * @returns An ASCII string containing decoded data from `encodedData`.\n */\nexport function decodeBase64URLSafe(\n  encodedData: string,\n  encoding: \"utf-8\" | \"binary\",\n): string {\n  if (typeof atob !== \"undefined\") {\n    const decoded = atob(\n      encodedData\n        // Replace characters according to base64url specifications\n        .replaceAll(\"-\", \"+\")\n        .replaceAll(\"_\", \"/\")\n        // Add padding if necessary\n        .padEnd(encodedData.length + ((4 - (encodedData.length % 4)) % 4), \"=\"),\n    )\n\n    if (encoding === \"utf-8\") {\n      // Decode the Base64 string into bytes\n      const byteArray = new Uint8Array(\n        [...decoded].map((char) => char.charCodeAt(0)),\n      )\n\n      // Convert the bytes back to a UTF-8 string\n      return new TextDecoder().decode(byteArray)\n    }\n\n    return decoded\n  }\n\n  return Buffer.from(encodedData, \"base64url\").toString(encoding)\n}\n","import { InvalidTokenError } from \"./errors/InvalidTokenError.js\"\nimport { decodeBase64URLSafe } from \"./utils/base64.js\"\n\n/**\n * Decode a Commerce Layer access token without verifying if the signature is valid.\n *\n * _You should not use this for untrusted messages, since this helper method does not verify whether the signature is valid.\n * If you need to verify the access token before decoding, you can use `jwtVerify` instead._\n */\nexport function jwtDecode(accessToken: string): CommerceLayerJWT {\n  const [encodedHeader, encodedPayload, signature] = `${accessToken}`.split(\".\")\n\n  if (encodedHeader == null || encodedPayload == null || signature == null) {\n    throw new InvalidTokenError(\"Invalid token format\")\n  }\n\n  return {\n    header: JSON.parse(decodeBase64URLSafe(encodedHeader, \"binary\")),\n    payload: JSON.parse(decodeBase64URLSafe(encodedPayload, \"utf-8\")),\n    signature,\n  }\n}\n\n/**\n * A Commerce Layer JWT.\n */\nexport interface CommerceLayerJWT {\n  /** The header typically consists of two parts: the type of the token, which is JWT, and the signing algorithm being used, such as HMAC SHA256 or RSA. */\n  header: {\n    /** Signing algorithm being used (e.g. `HMAC`, `SHA256`, `RSA`, `RS512`). */\n    alg: string\n    /** Type of the token (usually `JWT`). */\n    typ?: string\n    /** Key ID */\n    kid: string\n  }\n\n  payload: Payload\n\n  signature: string\n}\n\ntype Payload =\n  | JWTDashboard\n  | JWTUser\n  | JWTSalesChannel\n  | JWTIntegration\n  | JWTWebApp\n\ninterface JWTBase {\n  /** The type of credentials you're using to authenticate to the APIs. */\n  application: {\n    id: string\n    public: boolean\n    client_id: string\n    /** Whether the application is confidential (`true` when the `client_secret` is provided). */\n    confidential: boolean\n  }\n\n  /** Scope used to restrict access to a specific active market and/or stock location. */\n  scope: string\n  /** The token expiration time, expressed as an [epoch](https://www.epoch101.com/). */\n  exp: number\n  /** The environment type (true for test mode, false for live mode). */\n  test: boolean\n  /** A randomly generated number, less than one. */\n  rand: number\n  /** Issued at (seconds since Unix epoch). */\n  iat: number\n  /** Who created and signed this token (e.g. `\"https://auth.commercelayer.io\"`). */\n  iss: string\n}\n\n/**\n * A JWT payload that represents a `user`.\n */\nexport type JWTUser = JWTBase & {\n  /** The type of credentials you're using to authenticate to the APIs. */\n  application: {\n    kind: \"user\"\n  }\n  /** The authenticated user. */\n  user: {\n    id: string\n  }\n}\n\n/**\n * A JWT payload that represents a `dashboard`.\n */\nexport type JWTDashboard = JWTBase & {\n  /** The type of credentials you're using to authenticate to the APIs. */\n  application: {\n    kind: \"dashboard\"\n  }\n  /** The authenticated user. */\n  user: {\n    id: string\n  }\n}\n\nexport type JWTOrganizationBase = JWTBase & {\n  /** The organization in scope. */\n  organization: {\n    id: string\n    slug: string\n    enterprise: boolean\n    region: string\n  }\n  /** The owner (if any) authenticating to the APIs. */\n  owner?: {\n    id: string\n    type: \"Customer\" | \"User\"\n  }\n  /**\n   * Any other information (key/value pairs) you want to enrich the token with,\n   * when using the [JWT Bearer flow](https://docs.commercelayer.io/core/authentication/jwt-bearer).\n   */\n  custom_claim?: Record<string, string>\n  /**\n   * The market(s) in scope.\n   * This is available only when the scope is defined in the request.\n   */\n  market?: {\n    id: string[]\n    stock_location_ids: string[]\n    geocoder_id: string | null\n    allows_external_prices: boolean\n  }\n}\n\n/**\n * A JWT payload that represents a `webapp`.\n */\nexport type JWTWebApp = SetRequired<JWTOrganizationBase, \"owner\"> & {\n  /** The type of credentials you're using to authenticate to the APIs. */\n  application: {\n    kind: \"webapp\"\n  }\n}\n\n/** Create a type that makes the given keys required. The remaining keys are kept as is. */\ntype SetRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] }\n\n/**\n * A JWT payload that represents a `sales_channel`.\n */\nexport type JWTSalesChannel = JWTOrganizationBase & {\n  /** The type of credentials you're using to authenticate to the APIs. */\n  application: {\n    kind: \"sales_channel\"\n  }\n}\n\n/**\n * A JWT payload that represents an `integration`.\n */\nexport type JWTIntegration = JWTOrganizationBase & {\n  /** The type of credentials you're using to authenticate to the APIs. */\n  application: {\n    kind: \"integration\"\n  }\n}\n\n/**\n * Checks if the provided payload represents a `user`.\n * @param payload The payload to be checked.\n * @returns\n */\nexport function jwtIsUser(payload: Payload): payload is JWTUser {\n  return payload.application.kind === \"user\"\n}\n\n/**\n * Checks if the provided payload represents a `dashboard`.\n * @param payload The payload to be checked.\n * @returns\n */\nexport function jwtIsDashboard(payload: Payload): payload is JWTDashboard {\n  return payload.application.kind === \"dashboard\"\n}\n\n/**\n * Checks if the provided payload represents an `integration`.\n * @param payload The payload to be checked.\n * @returns\n */\nexport function jwtIsIntegration(payload: Payload): payload is JWTIntegration {\n  return payload.application.kind === \"integration\"\n}\n\n/**\n * Checks if the provided payload represents a `sales_channel`.\n * @param payload The payload to be checked.\n * @returns\n */\nexport function jwtIsSalesChannel(\n  payload: Payload,\n): payload is JWTSalesChannel {\n  return payload.application.kind === \"sales_channel\"\n}\n\n/**\n * Checks if the provided payload represents a `webapp`.\n * @param payload The payload to be checked.\n * @returns\n */\nexport function jwtIsWebApp(payload: Payload): payload is JWTWebApp {\n  return payload.application.kind === \"webapp\"\n}\n","export type CamelCaseToSnakeCase<\n  T extends string,\n  P extends string = \"\",\n> = string extends T\n  ? string\n  : T extends `${infer C}${infer R}`\n    ? CamelCaseToSnakeCase<\n        R,\n        `${P}${C extends Lowercase<C> ? \"\" : \"_\"}${Lowercase<C>}`\n      >\n    : P\n\nexport function camelCaseToSnakeCase<S extends string>(\n  str: S,\n): CamelCaseToSnakeCase<S> {\n  return str.replace(\n    /[A-Z]/g,\n    (letter) => `_${letter.toLowerCase()}`,\n  ) as CamelCaseToSnakeCase<S>\n}\n","import type { CommerceLayerJWT } from \"src/jwtDecode.js\"\n\n/**\n * Extract the `iss` from the decoded JWT.\n *\n * This is not as simple as `decodedJWT.payload.iss` because:\n * - at the beginning the `iss` was not required.\n * - the value can be `https://commercelayer.io` is old tokens.\n */\nexport function extractIssuer(\n  decodedJWT: CommerceLayerJWT,\n): `https://auth.${string}` {\n  return decodedJWT?.payload?.iss?.startsWith(\"https://auth.\")\n    ? (decodedJWT.payload.iss as `https://auth.${string}`)\n    : \"https://auth.commercelayer.io\"\n}\n","export function mapKeys(\n  obj: Record<string, unknown>,\n  fn: (key: string) => string,\n): Record<string, unknown> {\n  return Object.keys(obj).reduce((acc: Record<string, unknown>, key) => {\n    const camelKey = fn(key)\n    acc[camelKey] = obj[key]\n    return acc\n  }, {})\n}\n","import { jwtDecode } from \"./jwtDecode.js\"\nimport type { RevokeOptions, RevokeReturn } from \"./types/index.js\"\n\nimport { camelCaseToSnakeCase } from \"./utils/camelCaseToSnakeCase.js\"\nimport { extractIssuer } from \"./utils/extractIssuer.js\"\nimport { mapKeys } from \"./utils/mapKeys.js\"\n\n/**\n * Revoke a previously generated access token (refresh tokens included) before its natural expiration date.\n *\n * @param options Revoke options\n * @returns\n * @example\n * ```ts\n * await revoke({\n *   clientId: '{{ integrationClientId }}',\n *   clientSecret: '{{ integrationClientSecret }}',\n *   token: authenticateResponse.accessToken\n * })\n * ```\n */\nexport async function revoke(options: RevokeOptions): Promise<RevokeReturn> {\n  const body = mapKeys(options, camelCaseToSnakeCase)\n  const decodedJWT = jwtDecode(options.token)\n  const issuer = extractIssuer(decodedJWT)\n\n  const response = await fetch(`${issuer}/oauth/revoke`, {\n    method: \"POST\",\n    cache: \"no-store\",\n    headers: {\n      \"Content-Type\": \"application/json\",\n      Accept: \"application/json\",\n    },\n    body: JSON.stringify(body),\n  })\n\n  return (await response.json()) as RevokeReturn\n}\n","import type { CommerceLayerJWT, JWTOrganizationBase } from \"src/jwtDecode.js\"\n\n/**\n * Checks if the payload contains an owner field, which indicates that it is a customer token.\n */\nexport function hasOwner(\n  payload: CommerceLayerJWT[\"payload\"],\n): payload is PayloadWithOwner {\n  return \"owner\" in payload && payload.owner?.id != null\n}\n\ntype PayloadWithOwner = Extract<\n  CommerceLayerJWT[\"payload\"],\n  JWTOrganizationBase\n> & {\n  owner: NonNullable<JWTOrganizationBase[\"owner\"]>\n}\n","export type SnakeCaseToCamelCase<S extends string> =\n  S extends `${infer T}_${infer U}`\n    ? `${Lowercase<T>}${Capitalize<SnakeCaseToCamelCase<U>>}`\n    : S\n\nexport function snakeCaseToCamelCase<S extends string>(\n  str: S,\n): SnakeCaseToCamelCase<S> {\n  return str.replace(/([-_][a-z])/g, (group) =>\n    group.toUpperCase().replace(\"-\", \"\").replace(\"_\", \"\"),\n  ) as SnakeCaseToCamelCase<S>\n}\n","import type {\n  AuthenticateOptions,\n  AuthenticateReturn,\n  GrantType,\n} from \"./types/index.js\"\n\nimport { camelCaseToSnakeCase } from \"./utils/camelCaseToSnakeCase.js\"\nimport { mapKeys } from \"./utils/mapKeys.js\"\nimport { snakeCaseToCamelCase } from \"./utils/snakeCaseToCamelCase.js\"\n\ninterface TokenJson {\n  errors?: unknown\n  expires: Date\n  expires_in: number\n  [key: string]: unknown\n}\n\n/**\n * Authenticate helper used to get the access token.\n *\n * _Please note that the authentication endpoint is subject to a [rate limit](https://docs.commercelayer.io/core/rate-limits)\n * of **max 30 reqs / 1 min** both in live and test mode._\n * @param grantType The type of OAuth 2.0 grant being used for authentication.\n * @param options Authenticate options\n * @returns\n * @example\n * ```ts\n * import { authenticate } from '@commercelayer/js-auth'\n *\n * const auth = await authenticate('client_credentials', {\n *   clientId: '{{ clientId }}',\n *   scope: 'market:id:DGzAouppwn'\n * })\n *\n * console.log(auth.accessToken)\n * ```\n */\nexport async function authenticate<TGrantType extends GrantType>(\n  grantType: TGrantType,\n  {\n    domain = \"commercelayer.io\",\n    headers,\n    ...options\n  }: AuthenticateOptions<TGrantType>,\n): Promise<AuthenticateReturn<TGrantType>> {\n  const body = mapKeys(\n    {\n      grant_type: grantType,\n      ...options,\n    },\n    camelCaseToSnakeCase,\n  )\n\n  const response = await fetch(`https://auth.${domain}/oauth/token`, {\n    method: \"POST\",\n    cache: \"no-store\",\n    headers: {\n      \"Content-Type\": \"application/json\",\n      Accept: \"application/json\",\n      ...headers,\n    },\n    body: JSON.stringify(body),\n  })\n\n  const json: TokenJson = await response.json()\n\n  if (json.errors == null) {\n    json.expires = new Date(Date.now() + json.expires_in * 1000)\n  }\n\n  if (json.errors != null && !Array.isArray(json.errors)) {\n    json.errors = [json.errors]\n  }\n\n  return mapKeys(\n    json,\n    snakeCaseToCamelCase,\n  ) as unknown as AuthenticateReturn<TGrantType>\n}\n","/**\n * Deduplicates concurrent calls to a function with the same arguments.\n * If multiple calls are made with the same arguments, only the first call\n * will be executed, and all subsequent calls will receive the same result\n * once it resolves. This is useful for preventing duplicate API calls or\n * expensive operations that are called simultaneously with the same parameters.\n */\n// biome-ignore lint/suspicious/noExplicitAny: It accepts any function type.\nexport const dedupConcurrentCalls = <T extends (...args: any[]) => any>(\n  fn: T,\n): ((...args: Parameters<T>) => Promise<Awaited<ReturnType<T>>>) => {\n  type Return = Awaited<ReturnType<T>>\n  type Args = Parameters<T>\n\n  const ongoingCalls = new Map<\n    string,\n    {\n      requestQueue: Array<{\n        resolve: (value: Return) => void\n        reject: Parameters<ConstructorParameters<typeof Promise>[0]>[1]\n      }>\n    }\n  >()\n\n  return function (this: unknown, ...args: Args): Promise<Return> {\n    return new Promise((resolve, reject) => {\n      const argsKey = JSON.stringify(args)\n      const current = ongoingCalls.get(argsKey)\n\n      if (current === undefined) {\n        ongoingCalls.set(argsKey, { requestQueue: [] })\n\n        void Promise.resolve(fn.apply(this, args))\n          .then((result) => {\n            const query = ongoingCalls.get(argsKey)?.requestQueue ?? []\n            ongoingCalls.delete(argsKey)\n\n            resolve(result)\n            for (const item of query) {\n              item.resolve(result)\n            }\n          })\n          .catch((error) => {\n            const query = ongoingCalls.get(argsKey)?.requestQueue ?? []\n            ongoingCalls.delete(argsKey)\n\n            reject(error)\n            for (const item of query) {\n              item.reject(error)\n            }\n          })\n      } else {\n        current.requestQueue.push({\n          resolve,\n          reject,\n        })\n      }\n    })\n  }\n}\n","import { authenticate } from \"../authenticate.js\"\nimport { jwtDecode } from \"../jwtDecode.js\"\nimport { hasOwner } from \"../utils/hasOwner.js\"\nimport { dedupConcurrentCalls } from \"./dedupConcurrentCalls.js\"\nimport type { StorageValue, StoreOptions } from \"./storage.js\"\nimport type {\n  ApiCredentialsAuthorization,\n  AuthOptions,\n  SetRequired,\n} from \"./types.js\"\n\ntype MakeAuthReturn = {\n  options: AuthOptions\n  getAuthorization: () => Promise<ApiCredentialsAuthorization>\n  setAuthorization: (\n    auth: SetAuthorizationOptions,\n  ) => Promise<ApiCredentialsAuthorization>\n  removeAuthorization: (\n    type: ApiCredentialsAuthorization[\"ownerType\"],\n  ) => Promise<void>\n}\n\nfunction enhanceStorage<\n  Storage extends StoreOptions[\"storage\"] | StoreOptions[\"customerStorage\"],\n>(storage?: Storage): Storage {\n  if (storage === undefined) {\n    return storage as Storage\n  }\n\n  const originalGetItem = storage.getItem.bind(storage)\n\n  return {\n    ...storage,\n    async getItem(key: string) {\n      const value = await originalGetItem(key)\n      return value != null\n        ? {\n            ...value,\n            storageName: value.storageName ?? storage.name,\n          }\n        : null\n    },\n  }\n}\n\nfunction enhanceStoreOptions(store: StoreOptions): StoreOptions {\n  return {\n    ...store,\n    storage: enhanceStorage(store.storage),\n    customerStorage: enhanceStorage(store.customerStorage),\n  }\n}\n\nexport function makeAuth(\n  options: AuthOptions,\n  _store: StoreOptions,\n  {\n    logPrefix,\n    guestOnly = false,\n  }: {\n    logPrefix: string\n    /**\n     * Whether to allow only guest authorizations.\n     * If set to `true`, the helper will only return guest authorizations\n     * and will not attempt to read or refresh customer authorizations.\n     * This is useful for integrations that do not require customer authentication,\n     * such as backend integrations or public APIs.\n     * @default false\n     */\n    guestOnly?: boolean\n  },\n): MakeAuthReturn {\n  const authOptions: SetRequired<AuthOptions, \"scope\"> = {\n    ...options,\n    scope: options.scope ?? \"market:all\",\n  }\n\n  const store = enhanceStoreOptions(_store)\n\n  function log(\n    storageName: string | undefined,\n    message: string,\n    ...args: unknown[]\n  ) {\n    if (authOptions.debug === true) {\n      console.log(\n        `[CommerceLayer • auth.js] [${logPrefix}]${storageName != null ? ` [${storageName}]` : \"\"} ${message}`,\n        ...args,\n      )\n    }\n  }\n\n  const getStorageKey =\n    store.getKey ??\n    ((configuration, type) => {\n      return `cl_${type}-${configuration.clientId}-${configuration.scope}`\n    })\n\n  const getAuthorization: MakeAuthReturn[\"getAuthorization\"] = async () => {\n    /**\n     * Threshold duration before token expiration, in seconds.\n     *\n     * When `authorization.expiresIn` drops below this value,\n     * a new token will be requested to prevent usage of a nearly expired token.\n     *\n     * According to the Commerce Layer documentation, a new token is issued\n     * 15 minutes (900 seconds) before the previous token expires.\n     * During this overlap window, both tokens are valid.\n     *\n     * @example\n     * 600 seconds (10 minutes)\n     */\n    const expirationThreshold = 10 * 60\n\n    try {\n      if (guestOnly === false) {\n        // read `customer` authorization\n        const customerKey = await getStorageKey(\n          {\n            clientId: authOptions.clientId,\n            scope: authOptions.scope,\n          },\n          \"customer\",\n        )\n\n        const storage = store.customerStorage ?? store.storage\n\n        log(storage.name, \"Checking for customer key:\", customerKey)\n\n        const storedValue = await storage.getItem(customerKey)\n        const customerAuthorization = toAuthorization(storedValue)\n\n        if (customerAuthorization?.ownerType === \"customer\") {\n          if (customerAuthorization.expiresIn >= expirationThreshold) {\n            log(\n              storedValue?.storageName,\n              'Found \"customer\" authorization in storage',\n              customerAuthorization,\n            )\n\n            return customerAuthorization\n          }\n\n          log(\n            storedValue?.storageName,\n            \"Customer authorization expired\",\n            customerAuthorization,\n          )\n\n          if (customerAuthorization.refreshToken != null) {\n            const refreshTokenResponse = await authenticate(\"refresh_token\", {\n              ...authOptions,\n              refreshToken: customerAuthorization.refreshToken,\n            })\n\n            const authorization = await setAuthorization({\n              accessToken: refreshTokenResponse.accessToken,\n              scope: refreshTokenResponse.scope,\n              refreshToken: refreshTokenResponse.refreshToken,\n            })\n\n            log(\n              storedValue?.storageName,\n              \"Refreshed customer authorization\",\n              authorization,\n            )\n\n            return authorization\n          }\n\n          log(\n            storedValue?.storageName,\n            \"Customer authorization expired and has no refresh token, removing stale authorization\",\n          )\n\n          await storage.removeItem(customerKey).catch((error) => {\n            log(\n              storedValue?.storageName,\n              \"Unable to remove stale customer authorization\",\n              error,\n            )\n          })\n        }\n      }\n\n      // read `guest` authorization\n      const guestKey = await getStorageKey(\n        {\n          clientId: authOptions.clientId,\n          scope: authOptions.scope,\n        },\n        \"guest\",\n      )\n\n      const storage = store.storage\n\n      log(storage.name, \"Checking for guest key:\", guestKey)\n\n      const storedValue = await storage.getItem(guestKey)\n      const guestAuthorization = toAuthorization(storedValue)\n\n      if (\n        guestAuthorization?.ownerType === \"guest\" &&\n        guestAuthorization.expiresIn >= expirationThreshold\n      ) {\n        log(\n          storedValue?.storageName,\n          'Found \"guest\" authorization in storage',\n          guestAuthorization,\n        )\n\n        return guestAuthorization\n      }\n\n      // requesting a new token\n\n      log(\n        storage.name,\n        \"No valid authorization found, requesting a new guest token\",\n      )\n\n      // create `guest` authorization\n      const clientCredentialsResponse = await authenticate(\n        \"client_credentials\",\n        authOptions,\n      )\n\n      const authorization = await setAuthorization({\n        accessToken: clientCredentialsResponse.accessToken,\n        scope: clientCredentialsResponse.scope,\n      })\n\n      return authorization\n    } catch (error) {\n      log(undefined, \"Error getting the authorization.\", error)\n      throw error\n    }\n  }\n\n  const setAuthorization: MakeAuthReturn[\"setAuthorization\"] = async (auth) => {\n    const authorization = toAuthorization(auth)\n\n    const key = await getStorageKey(\n      { clientId: authOptions.clientId, scope: auth.scope },\n      authorization.ownerType,\n    )\n\n    const value: StorageValue = {\n      accessToken: authorization.accessToken,\n      scope: authorization.scope,\n      refreshToken:\n        authorization.ownerType === \"customer\"\n          ? authorization.refreshToken\n          : undefined,\n    }\n\n    const storage =\n      authorization.ownerType === \"customer\"\n        ? (store.customerStorage ?? store.storage)\n        : store.storage\n\n    log(\n      storage.name,\n      `Storing \"${authorization.ownerType}\" authorization with key:`,\n      key,\n    )\n\n    await storage.setItem(key, value)\n\n    log(\n      storage.name,\n      `Stored \"${authorization.ownerType}\" authorization to storage`,\n      authorization,\n    )\n\n    return authorization\n  }\n\n  const removeAuthorization: MakeAuthReturn[\"removeAuthorization\"] = async (\n    type,\n  ) => {\n    const key = await getStorageKey(\n      { clientId: authOptions.clientId, scope: authOptions.scope },\n      type,\n    )\n\n    const storage =\n      type === \"customer\"\n        ? (store.customerStorage ?? store.storage)\n        : store.storage\n\n    await storage.removeItem(key)\n\n    log(storage.name, `Removed \"${type}\" authorization with key:`, key)\n  }\n\n  return {\n    options: authOptions,\n    getAuthorization: dedupConcurrentCalls(getAuthorization),\n    setAuthorization,\n    removeAuthorization,\n  }\n}\n\n/**\n * Converts the `SetAuthorizationOptions` into an `Authorization` object.\n */\nfunction toAuthorization<Options extends SetAuthorizationOptions | null>(\n  options: Options,\n): Options extends null\n  ? ApiCredentialsAuthorization | null\n  : ApiCredentialsAuthorization {\n  if (options == null) {\n    return null as Options extends null\n      ? ApiCredentialsAuthorization | null\n      : ApiCredentialsAuthorization\n  }\n\n  const decodedJWT = jwtDecode(options.accessToken)\n\n  if (\n    hasOwner(decodedJWT.payload) &&\n    decodedJWT.payload.owner.type.toLowerCase() !== \"customer\"\n  ) {\n    throw new Error(\n      \"The provided access token does not contain a valid customer owner.\",\n    )\n  }\n\n  const type = hasOwner(decodedJWT.payload)\n    ? ({\n        ownerType: \"customer\",\n        ownerId: decodedJWT.payload.owner.id,\n        refreshToken: options.refreshToken,\n      } as const)\n    : ({ ownerType: \"guest\" } as const)\n\n  const expiresIn = Math.round(decodedJWT.payload.exp - Date.now() / 1000)\n\n  const authorization: ApiCredentialsAuthorization = {\n    ...type,\n    tokenType: \"bearer\",\n    createdAt: decodedJWT.payload.iat,\n    scope: options.scope,\n    accessToken: options.accessToken,\n    expiresIn,\n    expires: new Date(Date.now() + expiresIn * 1000),\n  }\n\n  return authorization\n}\n\ntype SetAuthorizationOptions = StorageValue\n","import type { AuthenticateReturn } from \"../types/index.js\"\nimport type { ApiCredentialsAuthorization } from \"./types.js\"\n\n/**\n * Creates a composite storage that combines multiple storages.\n *\n * When retrieving an item, it returns the first non-null value from the configured storages.\n *\n * The order of the configured storages is important, as it determines priority. The first storage in the array is checked first, followed by the second, and so on.\n *\n * Using a composite storage can be useful for reducing the load on the underlying storage.\n * For example, if you want to use Redis but avoid hitting it on every request, you can use a memory storage as the first storage and Redis as the second.\n * This way, the memory storage is checked first, and if the item is not found there, it falls back to Redis and is then saved to memory for subsequent requests.\n *\n * When setting or removing an item, the operation is performed on all configured storages to ensure consistency.\n *\n * @param options - An object containing an array of storage instances to combine and optionally a name.\n * @returns A composite storage instance.\n *\n * @example\n * const compositeStorage = createCompositeStorage({\n *   name: \"composite-storage\",\n *   storages: [memoryStorage, redisStorage]\n * });\n *\n * const value = await compositeStorage.getItem('myKey');\n *\n * // If you set the `name` property on the individual storages,\n * // the returned value will include the `storageName` indicating which storage provided the value.\n */\nexport function createCompositeStorage(options: {\n  storages: Storage[]\n  name?: string\n}): Storage\n\n/**\n * Creates a composite storage that combines multiple storages.\n *\n * @deprecated Use `createCompositeStorage` with options object instead.\n */\nexport function createCompositeStorage(storages: Storage[]): Storage\n// TODO: remember to remove the deprecated overload in the next major release\n\nexport function createCompositeStorage(\n  // TODO: remember to remove the deprecated overload in the next major release\n  storagesOrOptions: Storage[] | { storages: Storage[]; name?: string },\n): Storage {\n  // TODO: remember to remove the deprecated overload in the next major release\n  const options = Array.isArray(storagesOrOptions)\n    ? { storages: storagesOrOptions }\n    : storagesOrOptions\n\n  return {\n    name: options.name,\n\n    async getItem(key: string) {\n      for (const storage of options.storages) {\n        const value = await storage.getItem(key)\n\n        if (value !== null) {\n          for (const previousStorage of options.storages.slice(\n            0,\n            options.storages.indexOf(storage),\n          )) {\n            await previousStorage.setItem(key, value)\n          }\n\n          return {\n            ...value,\n            storageName: storage.name,\n          }\n        }\n      }\n      return null\n    },\n\n    async setItem(key: string, value: StorageValue) {\n      await Promise.all(\n        options.storages.map((storage) => storage.setItem(key, value)),\n      )\n    },\n\n    async removeItem(key: string) {\n      await Promise.all(\n        options.storages.map((storage) => storage.removeItem(key)),\n      )\n    },\n\n    async dispose() {\n      await Promise.all(options.storages.map((storage) => storage.dispose?.()))\n    },\n  }\n}\n\nexport type StoreOptions = {\n  /**\n   * Function to get the key for storing the authorization in the storage.\n   * This function receives the configuration and the type of authorization\n   * and should return a unique key for that authorization.\n   */\n  getKey?: (\n    configuration: {\n      clientId: string\n      scope: string\n    },\n    type: ApiCredentialsAuthorization[\"ownerType\"],\n  ) => Promise<string>\n  /**\n   * Storage instance for storing authorizations.\n   * This storage will be used for both \"guest\" and \"customer\" authorizations.\n   *\n   * If you need to use a different store for \"customer\" authorizations,\n   * you can provide a different storage instance using `customerStorage` option.\n   */\n  storage: Storage\n  /**\n   * Storage instance for storing \"customer\" authorizations.\n   * If not provided, the `storage` option will be used.\n   *\n   * This is useful if you want to separate guest and customer authorizations,\n   * for example, using `localStorage` for guest authorizations\n   * and `sessionStorage` for customer authorizations.\n   */\n  customerStorage?: Storage\n}\n\n/**\n * Storage interface for managing key/value pairs.\n *\n * This interface is used to abstract the storage mechanism, allowing for different implementations (e.g., localStorage, sessionStorage, in-memory storage).\n *\n * **Naming Best Practice**: It's highly recommended to provide a `name` for your storage instances.\n * This enables better observability in debug logs, especially when using composite storages,\n * as it allows you to trace which storage layer (memory, Redis, localStorage, etc.) provided each value.\n *\n * @example\n * ```typescript\n * const memoryStorage = {\n *   name: \"memory\",\n *   async getItem(key: string) { ... },\n *   async setItem(key: string, value: StorageValue) { ... },\n *   ...\n * }\n *\n * ```\n */\nexport interface Storage {\n  /**\n   * Optional name of the storage for identification purposes.\n   *\n   * **Recommended**: Provide a descriptive name (e.g., \"memory-cache\", \"redis\", \"localStorage\")\n   * to improve debug log traceability, especially when using composite storages.\n   */\n  name?: string\n\n  /**\n   * Returns the current value associated with the given key, or null if the given key does not exist.\n   */\n  getItem: (key: string) => Promise<\n    | (StorageValue & {\n        /**\n         * The name of the storage from which the item was retrieved.\n         */\n        storageName?: string\n      })\n    | null\n  >\n\n  /**\n   * Sets the value of the pair identified by key to value, creating a new key/value pair if none existed for key previously.\n   */\n  setItem: (key: string, value: StorageValue) => Promise<void>\n\n  /**\n   * Removes the key/value pair with the given key, if a key/value pair with the given key exists.\n   */\n  removeItem: (key: string) => Promise<void>\n\n  /**\n   * Disposes all mounted storages to ensure there are no open-handles left.\n   * Call it before exiting process.\n   */\n  dispose?: () => Promise<void>\n}\n\nexport type StorageValue = Pick<\n  AuthenticateReturn<\"password\">,\n  \"accessToken\" | \"scope\"\n> & {\n  /**\n   * The refresh token. If present, it can be used to obtain a new access token.\n   */\n  refreshToken?: string\n}\n","import { jwtDecode } from \"../jwtDecode.js\"\nimport { revoke } from \"../revoke.js\"\nimport type { RevokeReturn } from \"../types/index.js\"\nimport { hasOwner } from \"../utils/hasOwner.js\"\nimport { makeAuth } from \"./apiCredentials.js\"\nimport type { StorageValue, StoreOptions } from \"./storage.js\"\nimport type {\n  ApiCredentialsAuthorization,\n  AuthOptions,\n  SetRequired,\n} from \"./types.js\"\n\nexport {\n  createCompositeStorage,\n  type Storage,\n  type StorageValue,\n} from \"./storage.js\"\nexport type { ApiCredentialsAuthorization } from \"./types.js\"\n\n/**\n * [**Integrations**](https://docs.commercelayer.io/core/api-credentials#integration) are used\n * to develop backend integrations with any 3rd-party system.\n *\n * This helper manages the caching mechanism to avoid unnecessary API calls.\n */\nexport function makeIntegration(\n  options: SetRequired<AuthOptions, \"clientSecret\">,\n  store: Omit<StoreOptions, \"customerStorage\">,\n): {\n  options: SetRequired<AuthOptions, \"clientSecret\">\n  /**\n   * Get the current integration authorization.\n   *\n   * This will return the authorization from configured storage.\n   * If the authorization is not found or expired, it will fetch a new one.\n   */\n  getAuthorization: ReturnType<typeof makeAuth>[\"getAuthorization\"]\n  /**\n   * Remove the authorization from configured storages.\n   *\n   * This is particularly useful when you want to get a fresh authorization.\n   * **Note:** This will not revoke the token.\n   */\n  removeAuthorization: (type?: \"all\") => Promise<void>\n  /**\n   * Revoke the current integration authorization.\n   *\n   * This will remove the authorization from memory and storage, and revoke the access token.\n   */\n  revokeAuthorization: () => Promise<RevokeReturn>\n} {\n  const auth = makeAuth(options, store, {\n    logPrefix: \"integration\",\n    guestOnly: true,\n  })\n\n  return {\n    options,\n    getAuthorization: auth.getAuthorization,\n    removeAuthorization: async () => {\n      return await auth.removeAuthorization(\"guest\")\n    },\n    revokeAuthorization: async () => {\n      const { ownerType: type, accessToken } = await auth.getAuthorization()\n\n      if (type === \"guest\") {\n        await auth.removeAuthorization(\"guest\")\n\n        return await revoke({\n          clientId: options.clientId,\n          clientSecret: options.clientSecret,\n          token: accessToken,\n        })\n      }\n\n      return {}\n    },\n  }\n}\n\n/**\n * [**Sales channels**](https://docs.commercelayer.io/core/api-credentials#sales-channel) are used\n * to build any customer touchpoint (e.g. your storefront with a fully-functional shopping cart and checkout flow).\n *\n * This helper manages the caching mechanism to avoid unnecessary API calls\n * and provides methods to set and remove customer authorizations.\n */\nexport function makeSalesChannel(\n  options: Omit<AuthOptions, \"clientSecret\">,\n  store: StoreOptions,\n): {\n  options: Omit<AuthOptions, \"clientSecret\">\n  /**\n   * Get the current sales channel authorization.\n   *\n   * This will return the authorization from the configured storage.\n   * If the authorization is not found or expired, it will fetch a new one.\n   * If the customer is logged in with a `refreshToken`, it will also attempt to refresh the token when expired.\n   */\n  getAuthorization: ReturnType<typeof makeAuth>[\"getAuthorization\"]\n  /**\n   * Remove the authorization from configured storages.\n   *\n   * This is particularly useful when you want to get a fresh authorization.\n   * **Note:** This will not revoke the token.\n   */\n  removeAuthorization: (\n    type?: \"all\" | ApiCredentialsAuthorization[\"ownerType\"],\n  ) => Promise<void>\n  /**\n   * Sets the customer authorization.\n   * This will store the authorization in memory and storage.\n   * It will also validate the access token to ensure it contains a valid customer owner.\n   *\n   * The option `refreshToken` is optional and can be used to set a refresh token for the customer (e.g. \"remember me\" functionality).\n   * It will be used to refresh the access token when it expires.\n   */\n  setCustomer: (options: StorageValue) => Promise<ApiCredentialsAuthorization>\n  /**\n   * Logs out the current customer.\n   *\n   * This will remove the customer authorization from memory and storage, and revoke the access token.\n   */\n  logoutCustomer: () => Promise<RevokeReturn>\n} {\n  const auth = makeAuth(options, store, {\n    logPrefix: \"sales_channel\",\n  })\n\n  return {\n    options,\n    getAuthorization: auth.getAuthorization,\n    removeAuthorization: async (type = \"all\") => {\n      if (type === \"all\") {\n        await auth.removeAuthorization(\"customer\")\n        await auth.removeAuthorization(\"guest\")\n        return\n      }\n\n      return auth.removeAuthorization(type)\n    },\n    setCustomer: async (options) => {\n      const decodedJWT = jwtDecode(options.accessToken)\n\n      if (hasOwner(decodedJWT.payload)) {\n        return await auth.setAuthorization(options)\n      }\n\n      throw new Error(\n        \"The provided access token does not contain a valid customer owner.\",\n      )\n    },\n    logoutCustomer: async () => {\n      const { ownerType: type, accessToken } = await auth.getAuthorization()\n\n      if (type === \"customer\") {\n        await auth.removeAuthorization(\"customer\")\n\n        return await revoke({\n          clientId: options.clientId,\n          token: accessToken,\n        })\n      }\n\n      return {}\n    },\n  }\n}\n","import { TokenError } from \"./TokenError.js\"\n\n/**\n * The token expired.\n */\nexport class TokenExpiredError extends TokenError {\n  constructor() {\n    super(\"Token expired\")\n    this.name = \"TokenExpiredError\"\n  }\n}\n","import { InvalidTokenError } from \"./errors/InvalidTokenError.js\"\nimport { jwtDecode } from \"./jwtDecode.js\"\nimport { extractIssuer } from \"./utils/extractIssuer.js\"\n\n/**\n * Derives the [Core API base endpoint](https://docs.commercelayer.io/core/api-specification#base-endpoint) given a valid access token.\n *\n * @example\n * ```ts\n * getCoreApiBaseEndpoint('eyJhbGciOiJS...') //= \"https://yourdomain.commercelayer.io\"\n * ```\n *\n * The method requires a valid access token with an `organization` in the payload.\n *\n * @param accessToken - The access token to decode.\n * @param options - An options object to configure behavior.\n * @returns The core API base endpoint as a string, or `null` if the token is invalid and `shouldThrow` is `false`.\n * @throws InvalidTokenError - If the token is invalid and `shouldThrow` is true.\n */\nexport function getCoreApiBaseEndpoint(\n  accessToken: string,\n  options?: {\n    /**\n     * Whether to throw an error if the token is invalid.\n     * @default true\n     */\n    shouldThrow?: true\n  },\n): string\n\n/**\n * Derives the [Core API base endpoint](https://docs.commercelayer.io/core/api-specification#base-endpoint) given a valid access token.\n *\n * @example\n * ```ts\n * getCoreApiBaseEndpoint('eyJhbGciOiJS...') //= \"https://yourdomain.commercelayer.io\"\n * ```\n *\n * The method requires a valid access token with an `organization` in the payload.\n *\n * @param accessToken - The access token to decode.\n * @param options - An options object to configure behavior.\n * @returns The core API base endpoint as a string, or `null` if the token is invalid and `shouldThrow` is `false`.\n * @throws InvalidTokenError - If the token is invalid and `shouldThrow` is true.\n */\nexport function getCoreApiBaseEndpoint(\n  accessToken: string,\n  options: {\n    /**\n     * Whether to throw an error if the token is invalid.\n     * @default true\n     */\n    shouldThrow: false\n  },\n): string | null\n\nexport function getCoreApiBaseEndpoint(\n  accessToken: string,\n  options: {\n    shouldThrow?: boolean\n  } = {},\n): string | null {\n  const { shouldThrow = true } = options\n  const decodedJWT = jwtDecode(accessToken)\n\n  if (!(\"organization\" in decodedJWT.payload)) {\n    if (shouldThrow) {\n      throw new InvalidTokenError(\"Invalid token format\")\n    }\n\n    return null\n  }\n\n  return extractIssuer(decodedJWT).replace(\n    \"auth\",\n    decodedJWT.payload.organization.slug,\n  )\n}\n","import { InvalidTokenError } from \"./errors/InvalidTokenError.js\"\nimport { jwtDecode } from \"./jwtDecode.js\"\nimport { extractIssuer } from \"./utils/extractIssuer.js\"\n\n/**\n * Returns the [Provisioning API base endpoint](https://docs.commercelayer.io/provisioning/getting-started/api-specification#base-endpoint) given a valid access token.\n *\n * @example\n * ```ts\n * getProvisioningApiBaseEndpoint('eyJhbGciOiJS...') //= \"https://provisioning.commercelayer.io\"\n * ```\n *\n * The method requires a valid access token for Provisioning API.\n *\n * @param accessToken - The access token to decode.\n * @param options - An options object to configure behavior.\n * @returns The provisioning API base endpoint as a string, or `null` if the token is invalid and `shouldThrow` is `false`.\n * @throws InvalidTokenError - If the token is invalid and `shouldThrow` is true.\n */\nexport function getProvisioningApiBaseEndpoint(\n  accessToken: string,\n  options?: {\n    /**\n     * Whether to throw an error if the token is invalid.\n     * @default true\n     */\n    shouldThrow?: true\n  },\n): string\n\n/**\n * Returns the [Provisioning API base endpoint](https://docs.commercelayer.io/provisioning/getting-started/api-specification#base-endpoint) given a valid access token.\n *\n * @example\n * ```ts\n * getProvisioningApiBaseEndpoint('eyJhbGciOiJS...') //= \"https://provisioning.commercelayer.io\"\n * ```\n *\n * The method requires a valid access token for Provisioning API.\n *\n * @param accessToken - The access token to decode.\n * @param options - An options object to configure behavior.\n * @returns The provisioning API base endpoint as a string, or `null` if the token is invalid and `shouldThrow` is `false`.\n * @throws InvalidTokenError - If the token is invalid and `shouldThrow` is true.\n */\nexport function getProvisioningApiBaseEndpoint(\n  accessToken: string,\n  options: {\n    /**\n     * Whether to throw an error if the token is invalid.\n     * @default true\n     */\n    shouldThrow: false\n  },\n): string | null\n\nexport function getProvisioningApiBaseEndpoint(\n  accessToken: string,\n  options: {\n    shouldThrow?: boolean\n  } = {},\n): string | null {\n  const { shouldThrow = true } = options\n  const decodedJWT = jwtDecode(accessToken)\n\n  if (!decodedJWT?.payload?.scope?.includes(\"provisioning-api\")) {\n    if (shouldThrow) {\n      throw new InvalidTokenError(\"Invalid token format\")\n    }\n\n    return null\n  }\n\n  return extractIssuer(decodedJWT).replace(\"auth\", \"provisioning\")\n}\n","import type { CommerceLayerJWT } from \"./jwtDecode.js\"\n\n/**\n * Return a normalized token type from the provided payload.\n *\n * The token type is a string in the format `{applicationKind}:{ownerType}`, where:\n * - `applicationKind` is the kind of application used to authenticate (e.g. `dashboard`, `user`, `sales_channel`, `integration`, `webapp`).\n * - `ownerType` is the lowercased type of the token owner (e.g. `customer`, `user`), or `guest` when no owner is present.\n *\n * This is useful for quick authorization checks in any context, for example allowing only `integration:*`\n * tokens, or only storefront tokens such as `sales_channel:guest` and `sales_channel:customer`.\n *\n * @param payload The JWT payload to inspect.\n * @returns The token type string in the form `{applicationKind}:{ownerType}`.\n */\nexport function getTokenType(payload: CommerceLayerJWT[\"payload\"]): TokenType {\n  const applicationKind = payload.application.kind\n  const ownerType =\n    \"owner\" in payload && payload.owner != null\n      ? (payload.owner.type.toLowerCase() as Lowercase<\n          typeof payload.owner.type\n        >)\n      : \"guest\"\n\n  return `${applicationKind}:${ownerType}`\n}\n\n/**\n * Token classification string returned by {@link getTokenType}.\n *\n * It combines the application kind and owner type as `{applicationKind}:{ownerType}`\n * (for example `integration:user` or `sales_channel:guest`).\n */\nexport type TokenType = `${ApplicationKind}:${OwnerType}`\n\n/**\n * Supported application kinds extracted from Commerce Layer JWT payloads.\n */\ntype ApplicationKind = Extract<\n  CommerceLayerJWT[\"payload\"],\n  { application: { kind: string } }\n>[\"application\"][\"kind\"]\n\n/**\n * Supported owner types extracted from Commerce Layer JWT payloads.\n *\n * The value is normalized to lowercase, and includes `guest` for tokens that\n * do not have an owner.\n */\ntype OwnerType =\n  | Lowercase<\n      NonNullable<\n        Extract<\n          CommerceLayerJWT[\"payload\"],\n          { owner?: { type: string } }\n        >[\"owner\"]\n      >[\"type\"]\n    >\n  | \"guest\"\n","import { encodeBase64URLSafe } from \"./utils/base64.js\"\n\ninterface Owner {\n  type: \"User\" | \"Customer\"\n  id: string\n}\n\n/**\n * Create a JWT assertion as the first step of the [JWT bearer token authorization grant flow](https://docs.commercelayer.io/core/authentication/jwt-bearer).\n *\n * The JWT assertion is a digitally signed JSON object containing information\n * about the client and the user on whose behalf the access token is being requested.\n *\n * This JWT assertion can include information such as the issuer (typically the client),\n * the owner (the user on whose behalf the request is made), and any other relevant claims.\n *\n * @example\n * ```ts\n * const assertion = await createAssertion({\n *   payload: {\n *     'https://commercelayer.io/claims': {\n *       owner: {\n *         type: 'Customer',\n *         id: '4tepftJsT2'\n *       },\n *       custom_claim: {\n *         customer: {\n *           first_name: 'John',\n *           last_name: 'Doe'\n *         }\n *       }\n *     }\n *   }\n * })\n * ```\n */\nexport async function createAssertion({ payload }: Assertion): Promise<string> {\n  return await jwtEncode(payload, \"cl\")\n}\n\n/** RequireAtLeastOne helps create a type where at least one of the properties of an interface (can be any property) is required to exist. */\ntype RequireAtLeastOne<T> = {\n  [K in keyof T]-?: Required<Pick<T, K>> & Partial<Pick<T, Exclude<keyof T, K>>>\n}[keyof T]\n\ninterface Assertion {\n  /** Assertion payload. */\n  payload: {\n    /** At least one of `owner` or `custom_claim` is required. You cannot use an empty object. */\n    \"https://commercelayer.io/claims\": RequireAtLeastOne<{\n      /** The customer or user you want to make the calls on behalf of. */\n      owner?: Owner\n      /** Any other information (key/value pairs) you want to enrich the token with. */\n      custom_claim?: Record<string, unknown>\n    }>\n  }\n}\n\nasync function jwtEncode(\n  payload: Record<string, unknown>,\n  secret: string,\n): Promise<string> {\n  const header = { alg: \"HS512\", typ: \"JWT\" }\n\n  const encodedHeader = encodeBase64URLSafe(JSON.stringify(header), \"binary\")\n\n  const encodedPayload = encodeBase64URLSafe(\n    JSON.stringify({\n      ...payload,\n      iat: Math.floor(Date.now() / 1000),\n    }),\n    \"utf-8\",\n  )\n\n  const unsignedToken = `${encodedHeader}.${encodedPayload}`\n\n  const signature = await createSignature(unsignedToken, secret)\n\n  return `${unsignedToken}.${signature}`\n}\n\nasync function createSignature(data: string, secret: string): Promise<string> {\n  const enc = new TextEncoder()\n  const algorithm = { name: \"HMAC\", hash: \"SHA-512\" }\n\n  const key = await crypto.subtle.importKey(\n    \"raw\",\n    enc.encode(secret),\n    algorithm,\n    false,\n    [\"sign\", \"verify\"],\n  )\n\n  const signature = await crypto.subtle.sign(\n    algorithm.name,\n    key,\n    enc.encode(data),\n  )\n\n  return encodeBase64URLSafe(\n    String.fromCharCode(...new Uint8Array(signature)),\n    \"binary\",\n  )\n}\n","import type { CommerceLayerJWT } from \"src/jwtDecode.js\"\n\n/**\n * Check if a Commerce Layer JWT has expired.\n *\n * @param decodedJWT - The decoded JWT to check.\n * @returns `true` if the JWT has expired, `false` otherwise.\n */\nexport function hasExpired(decodedJWT: CommerceLayerJWT): boolean {\n  return Date.now() >= decodedJWT.payload.exp * 1000\n}\n","import { InvalidTokenError } from \"./errors/InvalidTokenError.js\"\nimport { TokenError } from \"./errors/TokenError.js\"\nimport { TokenExpiredError } from \"./errors/TokenExpiredError.js\"\nimport { type CommerceLayerJWT, jwtDecode } from \"./jwtDecode.js\"\nimport { decodeBase64URLSafe } from \"./utils/base64.js\"\nimport { extractIssuer } from \"./utils/extractIssuer.js\"\nimport { hasExpired } from \"./utils/hasExpired.js\"\n\n/**\n * Validate the integrity and authenticity of the JWT.\n * It checks if the token is valid by verifying the signature against the public key used to create it.\n * This is useful to ensure that the token hasn't been tampered with and originates from Commerce Layer.\n *\n * When the verification succeeds, it resolves to the decoded access token, it rejects otherwise.\n */\nexport async function jwtVerify(\n  accessToken: string,\n  { ignoreExpiration = false, jwk }: JwtVerifyOptions = {},\n): Promise<CommerceLayerJWT> {\n  const decodedJWT = jwtDecode(accessToken)\n\n  const jsonWebKey = jwk ?? (await getJsonWebKey(decodedJWT))\n\n  if (jsonWebKey == null || jsonWebKey.kid !== decodedJWT.header.kid) {\n    throw new InvalidTokenError('Invalid token \"kid\"')\n  }\n\n  if (!ignoreExpiration && hasExpired(decodedJWT)) {\n    throw new TokenExpiredError()\n  }\n\n  const algorithm: RsaHashedImportParams = {\n    name: \"RSASSA-PKCS1-v1_5\",\n    hash: \"SHA-512\",\n  }\n\n  const publicKey = await crypto.subtle.importKey(\n    \"jwk\",\n    jsonWebKey,\n    algorithm,\n    true,\n    [\"verify\"],\n  )\n\n  const rawSignature = new Uint8Array(\n    Array.from(decodeBase64URLSafe(decodedJWT.signature, \"binary\"), (c) =>\n      c.charCodeAt(0),\n    ),\n  )\n\n  const rawData = new TextEncoder().encode(\n    accessToken.split(\".\").slice(0, 2).join(\".\"),\n  )\n\n  const isValid = await crypto.subtle.verify(\n    algorithm,\n    publicKey,\n    rawSignature,\n    rawData,\n  )\n\n  if (!isValid) {\n    throw new InvalidTokenError(\"Invalid signature\")\n  }\n\n  return decodedJWT\n}\n\ntype CommerceLayerJsonWebKey = JsonWebKey & { kid: string }\n\ninterface JwtVerifyOptions {\n  /**\n   * Do not validate the token expiration when set to `true`.\n   * @default false\n   */\n  ignoreExpiration?: boolean\n\n  /**\n   * Json Web Key used to verify the signature.\n   *\n   * The `kid` must match the `kid` from decoded accessToken.\n   *\n   * By default, we pick the jwk from https://auth.commercelayer.io/.well-known/jwks.json using the `kid` from the accessToken.\n   */\n  jwk?: CommerceLayerJsonWebKey\n}\n\n/** JWKS in-memory cache. */\nconst JWKSCache: Record<string, CommerceLayerJsonWebKey | undefined> = {}\n\n/**\n * Get the `JsonWebKey` given a key identifier.\n * @param kid Key identifier.\n * @returns\n */\nasync function getJsonWebKey(\n  jwt: CommerceLayerJWT,\n): Promise<CommerceLayerJsonWebKey | undefined> {\n  const { kid } = jwt.header\n\n  if (JWKSCache[kid] != null) {\n    return JWKSCache[kid]\n  }\n\n  const keys = await getJsonWebKeys(jwt)\n\n  JWKSCache[kid] = keys.find((key) => key.kid === kid)\n\n  return JWKSCache[kid]\n}\n\n/**\n * Retrieve RSA public keys from our JWKS (JSON Web Key Set) endpoint.\n * @returns\n */\nasync function getJsonWebKeys(\n  jwt: CommerceLayerJWT,\n): Promise<CommerceLayerJsonWebKey[]> {\n  const jwksUrl = `${extractIssuer(jwt)}/.well-known/jwks.json`\n\n  const response = await fetch(jwksUrl).then<{\n    keys: CommerceLayerJsonWebKey[] | undefined\n  }>(async (res) => await res.json())\n\n  if (response.keys == null) {\n    throw new TokenError(\n      `Invalid jwks response from \"${jwksUrl}\": ${JSON.stringify(response)}`,\n    )\n  }\n\n  return response.keys\n}\n"],"mappings":"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","names":["index_exports","__export","InvalidTokenError","TokenError","TokenExpiredError","authenticate","createAssertion","createCompositeStorage","getCoreApiBaseEndpoint","getProvisioningApiBaseEndpoint","getTokenType","jwtDecode","jwtIsDashboard","jwtIsIntegration","jwtIsSalesChannel","jwtIsUser","jwtIsWebApp","jwtVerify","makeIntegration","makeSalesChannel","revoke","__toCommonJS","TokenError","message","InvalidTokenError","TokenError","message","encodeBase64URLSafe","stringToEncode","encoding","utf8String","utf8Bytes","decodeBase64URLSafe","encodedData","decoded","byteArray","char","jwtDecode","accessToken","encodedHeader","encodedPayload","signature","InvalidTokenError","decodeBase64URLSafe","jwtIsUser","payload","jwtIsDashboard","jwtIsIntegration","jwtIsSalesChannel","jwtIsWebApp","camelCaseToSnakeCase","str","letter","extractIssuer","decodedJWT","mapKeys","obj","fn","acc","key","camelKey","revoke","options","body","mapKeys","camelCaseToSnakeCase","decodedJWT","jwtDecode","issuer","extractIssuer","hasOwner","payload","snakeCaseToCamelCase","str","group","authenticate","grantType","domain","headers","options","body","mapKeys","camelCaseToSnakeCase","json","snakeCaseToCamelCase","dedupConcurrentCalls","fn","ongoingCalls","args","resolve","reject","argsKey","current","result","query","item","error","enhanceStorage","storage","originalGetItem","key","value","enhanceStoreOptions","store","makeAuth","options","_store","logPrefix","guestOnly","authOptions","log","storageName","message","args","getStorageKey","configuration","type","getAuthorization","customerKey","storedValue","customerAuthorization","toAuthorization","refreshTokenResponse","authenticate","authorization","setAuthorization","error","guestKey","guestAuthorization","clientCredentialsResponse","auth","removeAuthorization","dedupConcurrentCalls","decodedJWT","jwtDecode","hasOwner","expiresIn","createCompositeStorage","storagesOrOptions","options","key","storage","value","previousStorage","makeIntegration","options","store","auth","makeAuth","type","accessToken","revoke","makeSalesChannel","decodedJWT","jwtDecode","hasOwner","TokenExpiredError","TokenError","getCoreApiBaseEndpoint","accessToken","options","shouldThrow","decodedJWT","jwtDecode","InvalidTokenError","extractIssuer","getProvisioningApiBaseEndpoint","accessToken","options","shouldThrow","decodedJWT","jwtDecode","InvalidTokenError","extractIssuer","getTokenType","payload","applicationKind","ownerType","createAssertion","payload","jwtEncode","secret","encodedHeader","encodeBase64URLSafe","encodedPayload","unsignedToken","signature","createSignature","data","enc","algorithm","key","hasExpired","decodedJWT","jwtVerify","accessToken","ignoreExpiration","jwk","decodedJWT","jwtDecode","jsonWebKey","getJsonWebKey","InvalidTokenError","hasExpired","TokenExpiredError","algorithm","publicKey","rawSignature","decodeBase64URLSafe","c","rawData","JWKSCache","jwt","kid","keys","getJsonWebKeys","key","jwksUrl","extractIssuer","response","res","TokenError"]}