@sp-api-sdk/common
Version:
Selling Parner API common library
1 lines • 13.6 kB
Source Map (JSON)
{"version":3,"sources":["../src/index.ts","../src/regions.ts","../src/axios.ts","../src/errors.ts","../src/utils/package.ts"],"sourcesContent":["export * from './regions.js'\nexport * from './axios.js'\nexport * from './errors.js'\n","/** Selling Partner API region identifier. */\nexport type SellingPartnerRegion = 'na' | 'eu' | 'fe'\n\ninterface RegionConfiguration {\n awsRegion: string\n endpoints: {\n production: string\n sandbox: string\n }\n}\n\n/** AWS region and endpoint mapping for each Selling Partner API region. */\nexport const sellingPartnerRegions: Record<SellingPartnerRegion, RegionConfiguration> = {\n na: {\n awsRegion: 'us-east-1',\n endpoints: {\n production: 'https://sellingpartnerapi-na.amazon.com',\n sandbox: 'https://sandbox.sellingpartnerapi-na.amazon.com',\n },\n },\n eu: {\n awsRegion: 'eu-west-1',\n endpoints: {\n production: 'https://sellingpartnerapi-eu.amazon.com',\n sandbox: 'https://sandbox.sellingpartnerapi-eu.amazon.com',\n },\n },\n fe: {\n awsRegion: 'us-west-2',\n endpoints: {\n production: 'https://sellingpartnerapi-fe.amazon.com',\n sandbox: 'https://sandbox.sellingpartnerapi-fe.amazon.com',\n },\n },\n}\n","import axios, {type AxiosError, isAxiosError, type Method} from 'axios'\nimport {errorLogger, requestLogger, responseLogger} from 'axios-logger'\nimport axiosRetry from 'axios-retry'\n\nimport {type SellingPartnerApiAuth, SellingPartnerApiAuthError} from '@sp-api-sdk/auth'\n\nimport {SellingPartnerApiError} from './errors.js'\nimport {type SellingPartnerRegion, sellingPartnerRegions} from './regions.js'\nimport {packageJson} from './utils/package.js'\n\ntype RequestLogConfig = Exclude<Parameters<typeof requestLogger>[1], undefined>\ntype ResponseLogConfig = Exclude<Parameters<typeof responseLogger>[1], undefined>\ntype ErrorLogConfig = Exclude<Parameters<typeof errorLogger>[1], undefined>\n\n/** Per-endpoint rate limit definition used for retry delay calculation. */\nexport interface RateLimit {\n /** Regular expression matched against the request URL pathname. */\n urlRegex: RegExp\n /** Sustained request rate in requests per second. */\n rate: number\n /** Maximum burst size (number of requests allowed before throttling). */\n burst: number\n /** HTTP method this rate limit applies to. */\n method: Method\n}\n\n/** Parameters passed to the {@link ClientConfiguration.rateLimiting} `onRetry` callback. */\nexport interface OnRetryParameters {\n /** Delay in milliseconds before the next retry attempt. */\n delay: number\n /** Rate limit (requests per second) used to calculate the delay, if available. */\n rateLimit?: number\n /** Number of retry attempts so far. */\n retryCount: number\n /** The Axios error that triggered the retry. */\n error: AxiosError\n}\n\n/** Configuration options for creating a Selling Partner API Axios instance. */\nexport interface ClientConfiguration {\n /** Authentication handler that provides LWA access tokens. */\n auth: SellingPartnerApiAuth\n /** Restricted Data Token to use instead of the standard access token. */\n restrictedDataToken?: string\n /** Selling Partner API region to send requests to. */\n region: SellingPartnerRegion\n /** Custom `User-Agent` header value. */\n userAgent?: string\n /** When `true`, requests are sent to the sandbox endpoint. Defaults to `false`. */\n sandbox?: boolean\n /** Rate-limiting and retry configuration for 429 responses. */\n rateLimiting?: {\n /** When `true`, automatically retries throttled (HTTP 429) requests. */\n retry: boolean\n /** Optional callback invoked before each retry attempt. */\n onRetry?: (retryInfo: OnRetryParameters) => void\n }\n /** Axios request/response/error logging configuration. Pass `true` to use defaults. */\n logging?: {\n /** Log outgoing requests. */\n request?: RequestLogConfig | true\n /** Log incoming responses. */\n response?: ResponseLogConfig | true\n /** Log request errors. */\n error?: ErrorLogConfig | true\n }\n}\n\n/**\n * Creates a pre-configured Axios instance for a Selling Partner API client.\n *\n * The instance handles authentication, rate-limit retries, error wrapping,\n * and optional request/response logging.\n *\n * @param configuration - Client configuration options.\n * @param rateLimits - Per-endpoint rate limits used for retry delay calculation.\n * @returns An object containing the configured Axios instance and the resolved API endpoint.\n */\nexport function createAxiosInstance(\n {\n auth,\n restrictedDataToken,\n region,\n userAgent = `${packageJson.name}/${packageJson.version}`,\n sandbox = false,\n rateLimiting,\n logging,\n }: ClientConfiguration,\n rateLimits: RateLimit[],\n) {\n const regionConfiguration = sellingPartnerRegions[region]\n if (!regionConfiguration) {\n throw new TypeError(`Unknown or unsupported region: ${region}`)\n }\n\n const instance = axios.create({\n headers: {\n 'user-agent': userAgent,\n },\n })\n\n const endpoint = regionConfiguration.endpoints[sandbox ? 'sandbox' : 'production']\n\n if (rateLimiting?.retry) {\n axiosRetry(instance, {\n retryCondition: (error) => error.response?.status === 429,\n retryDelay(retryCount, error) {\n const url = new URL(error.config!.url!)\n const method = error.config!.method?.toLowerCase()\n const amznRateLimit = Number.parseFloat(\n error.response?.headers['x-amzn-ratelimit-limit'] ?? '',\n )\n\n const rateLimit = Number.isNaN(amznRateLimit)\n ? rateLimits.find(\n (rateLimit) =>\n rateLimit.method.toLowerCase() === method && rateLimit.urlRegex.exec(url.pathname),\n )?.rate\n : amznRateLimit\n\n const delay = rateLimit ? (1 / rateLimit) * 1000 + 1500 : 60 * 1000\n\n if (rateLimiting.onRetry) {\n rateLimiting.onRetry({delay, rateLimit, retryCount, error})\n }\n\n return delay\n },\n })\n }\n\n // Set x-amz-access-token to each request\n instance.interceptors.request.use(async (config) => {\n config.headers['x-amz-access-token'] = restrictedDataToken ?? (await auth.getAccessToken())\n\n return config\n })\n\n instance.interceptors.response.use(\n async (response) => response,\n async (error: unknown) => {\n if (isAxiosError(error) && !(error instanceof SellingPartnerApiAuthError)) {\n throw new SellingPartnerApiError(error)\n }\n\n throw error\n },\n )\n\n if (logging?.request) {\n const requestLoggerOptions = logging.request === true ? undefined : logging.request\n\n if (requestLoggerOptions?.headers) {\n console.warn(\n 'WARNING: You have enabled logging of request headers, this can leak authentication information, you should disable in production.',\n )\n }\n\n instance.interceptors.request.use((config) => {\n const logger = requestLogger(config, {\n prefixText: `sp-api-sdk/${region}`,\n dateFormat: 'isoDateTime',\n method: true,\n url: true,\n params: false,\n data: true,\n headers: false,\n logger: console.info,\n ...requestLoggerOptions,\n })\n\n return {\n ...logger,\n headers: config.headers,\n }\n })\n }\n\n if (logging?.response) {\n const responseLoggerOptions = logging.response === true ? undefined : logging.response\n\n instance.interceptors.response.use((response) =>\n responseLogger(response, {\n prefixText: `sp-api-sdk/${region}`,\n dateFormat: 'isoDateTime',\n status: true,\n statusText: false,\n params: false,\n data: false,\n headers: true,\n logger: console.info,\n ...responseLoggerOptions,\n }),\n )\n }\n\n if (logging?.error) {\n const errorLoggerOptions = logging.error === true ? undefined : logging.error\n\n instance.interceptors.response.use(\n (response) => response,\n async (error) =>\n errorLogger(error, {\n prefixText: `sp-api-sdk/${region}`,\n dateFormat: 'isoDateTime',\n status: true,\n statusText: false,\n params: false,\n data: false,\n headers: true,\n logger: console.error,\n ...errorLoggerOptions,\n }),\n )\n }\n\n return {axios: instance, endpoint}\n}\n","import {URL} from 'node:url'\n\nimport {AxiosError} from 'axios'\n\n/**\n * Error thrown when a Selling Partner API request fails.\n *\n * Wraps the underlying Axios error with a message that includes the API name,\n * version, and HTTP status code (or \"No response\" for network errors).\n */\nexport class SellingPartnerApiError<T = unknown, D = any> extends AxiosError<T, D> {\n /** The original error message from the failed HTTP request. */\n public readonly innerMessage: string\n /** The API name extracted from the request URL path (e.g. `\"orders\"`). */\n public readonly apiName?: string\n /** The API version extracted from the request URL path (e.g. `\"v0\"`). */\n public readonly apiVersion?: string\n\n constructor(error: AxiosError<T, D>) {\n super('Unknown error', error.code, error.config, error.request, error.response)\n\n this.innerMessage = error.message\n\n if (error.config!.url) {\n const [apiName, apiVersion] = new URL(error.config!.url).pathname.split('/').slice(1)\n const apiPrefix = `${apiName} (${apiVersion})`\n\n this.apiName = apiName\n this.apiVersion = apiVersion\n this.message = error.response\n ? `${apiPrefix} error: Response code ${error.response.status}`\n : `${apiPrefix} error: No response`\n }\n\n this.name = this.constructor.name\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/common',\n version: 'unknown',\n}\n"],"mappings":"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","names":["import_axios","readPackageJson","axios","axiosRetry","rateLimit"]}