UNPKG

@sp-api-sdk/auth

Version:

Login with Amazon (LWA) authentication for the Amazon Selling Partner API (SP-API)

362 lines (293 loc) 12 kB
import { AxiosError } from "axios"; //#region ../../node_modules/.pnpm/type-fest@5.8.0/node_modules/type-fest/source/is-any.d.ts /** Returns a boolean for whether the given type is `any`. @link https://stackoverflow.com/a/49928360/1490091 Useful in type utilities, such as disallowing `any`s to be passed to a function. @example ``` import type {IsAny} from 'type-fest'; const typedObject = {a: 1, b: 2} as const; const anyObject: any = {a: 1, b: 2}; function get<O extends (IsAny<O> extends true ? {} : Record<string, number>), K extends keyof O = keyof O>(object: O, key: K) { return object[key]; } const typedA = get(typedObject, 'a'); //=> 1 const anyA = get(anyObject, 'a'); //=> any ``` @category Type Guard @category Utilities */ type IsAny<T> = 0 extends 1 & NoInfer<T> ? true : false; //#endregion //#region ../../node_modules/.pnpm/type-fest@5.8.0/node_modules/type-fest/source/is-never.d.ts /** Returns a boolean for whether the given type is `never`. @link https://github.com/microsoft/TypeScript/issues/31751#issuecomment-498526919 @link https://stackoverflow.com/a/53984913/10292952 @link https://www.zhenghao.io/posts/ts-never Useful in type utilities, such as checking if something does not occur. @example ``` import type {IsNever, And} from 'type-fest'; type A = IsNever<never>; //=> true type B = IsNever<any>; //=> false type C = IsNever<unknown>; //=> false type D = IsNever<never[]>; //=> false type E = IsNever<object>; //=> false type F = IsNever<string>; //=> false ``` @example ``` import type {IsNever} from 'type-fest'; type IsTrue<T> = T extends true ? true : false; // When a distributive conditional is instantiated with `never`, the entire conditional results in `never`. type A = IsTrue<never>; //=> never // If you don't want that behaviour, you can explicitly add an `IsNever` check before the distributive conditional. type IsTrueFixed<T> = IsNever<T> extends true ? false : T extends true ? true : false; type B = IsTrueFixed<never>; //=> false ``` @category Type Guard @category Utilities */ type IsNever<T> = [T] extends [never] ? true : false; //#endregion //#region ../../node_modules/.pnpm/type-fest@5.8.0/node_modules/type-fest/source/if.d.ts /** An if-else-like type that resolves depending on whether the given `boolean` type is `true` or `false`. Use-cases: - You can use this in combination with `Is*` types to create an if-else-like experience. For example, `If<IsAny<any>, 'is any', 'not any'>`. Note: - Returns a union of if branch and else branch if the given type is `boolean` or `any`. For example, `If<boolean, 'Y', 'N'>` will return `'Y' | 'N'`. - Returns the else branch if the given type is `never`. For example, `If<never, 'Y', 'N'>` will return `'N'`. @example ``` import type {If} from 'type-fest'; type A = If<true, 'yes', 'no'>; //=> 'yes' type B = If<false, 'yes', 'no'>; //=> 'no' type C = If<boolean, 'yes', 'no'>; //=> 'yes' | 'no' type D = If<any, 'yes', 'no'>; //=> 'yes' | 'no' type E = If<never, 'yes', 'no'>; //=> 'no' ``` @example ``` import type {If, IsAny, IsNever} from 'type-fest'; type A = If<IsAny<unknown>, 'is any', 'not any'>; //=> 'not any' type B = If<IsNever<never>, 'is never', 'not never'>; //=> 'is never' ``` @example ``` import type {If, IsEqual} from 'type-fest'; type IfEqual<T, U, IfBranch, ElseBranch> = If<IsEqual<T, U>, IfBranch, ElseBranch>; type A = IfEqual<string, string, 'equal', 'not equal'>; //=> 'equal' type B = IfEqual<string, number, 'equal', 'not equal'>; //=> 'not equal' ``` Note: Sometimes using the `If` type can make an implementation non–tail-recursive, which can impact performance. In such cases, it’s better to use a conditional directly. Refer to the following example: @example ``` import type {If, IsEqual, StringRepeat} from 'type-fest'; type HundredZeroes = StringRepeat<'0', 100>; // The following implementation is not tail recursive type Includes<S extends string, Char extends string> = S extends `${infer First}${infer Rest}` ? If<IsEqual<First, Char>, 'found', Includes<Rest, Char>> : 'not found'; // Hence, instantiations with long strings will fail // @ts-expect-error type Fails = Includes<HundredZeroes, '1'>; // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Error: Type instantiation is excessively deep and possibly infinite. // However, if we use a simple conditional instead of `If`, the implementation becomes tail-recursive type IncludesWithoutIf<S extends string, Char extends string> = S extends `${infer First}${infer Rest}` ? IsEqual<First, Char> extends true ? 'found' : IncludesWithoutIf<Rest, Char> : 'not found'; // Now, instantiations with long strings will work type Works = IncludesWithoutIf<HundredZeroes, '1'>; //=> 'not found' ``` @category Type Guard @category Utilities */ type If<Type extends boolean, IfBranch, ElseBranch> = IsNever<Type> extends true ? ElseBranch : Type extends true ? IfBranch : ElseBranch; //#endregion //#region ../../node_modules/.pnpm/type-fest@5.8.0/node_modules/type-fest/source/internal/type.d.ts /** An if-else-like type that resolves depending on whether the given type is `any` or `never`. @example ``` // When `T` is neither `any` nor `never` (like `string`) => Returns `IfNot` branch type A = IfNotAnyOrNever<string, {ifNot: 'VALID'; ifAny: 'IS_ANY'; ifNever: 'IS_NEVER'}>; //=> 'VALID' // When `T` is `any` => Returns `IfAny` branch type B = IfNotAnyOrNever<any, {ifNot: 'VALID'; ifAny: 'IS_ANY'; ifNever: 'IS_NEVER'}>; //=> 'IS_ANY' // When `T` is `never` => Returns `IfNever` branch type C = IfNotAnyOrNever<never, {ifNot: 'VALID'; ifAny: 'IS_ANY'; ifNever: 'IS_NEVER'}>; //=> 'IS_NEVER' ``` Note: Wrapping a tail-recursive type with `IfNotAnyOrNever` makes the implementation non-tail-recursive. To fix this, move the recursion into a helper type. Refer to the following example: @example ```ts import type {StringRepeat} from 'type-fest'; type NineHundredNinetyNineSpaces = StringRepeat<' ', 999>; // The following implementation is not tail recursive type TrimLeft<S extends string> = IfNotAnyOrNever<S, {ifNot: S extends ` ${infer R}` ? TrimLeft<R> : S}>; // Hence, instantiations with long strings will fail // @ts-expect-error type T1 = TrimLeft<NineHundredNinetyNineSpaces>; // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Error: Type instantiation is excessively deep and possibly infinite. // To fix this, move the recursion into a helper type type TrimLeftOptimised<S extends string> = IfNotAnyOrNever<S, {ifNot: _TrimLeftOptimised<S>}>; type _TrimLeftOptimised<S extends string> = S extends ` ${infer R}` ? _TrimLeftOptimised<R> : S; type T2 = TrimLeftOptimised<NineHundredNinetyNineSpaces>; //=> '' ``` */ type IfNotAnyOrNever<T, Cases extends { ifNot: unknown; ifAny?: unknown; ifNever?: unknown; }> = IsAny<T> extends true ? 'ifAny' extends keyof Cases ? Cases['ifAny'] : any : IsNever<T> extends true ? 'ifNever' extends keyof Cases ? Cases['ifNever'] : never : Cases['ifNot']; //#endregion //#region ../../node_modules/.pnpm/type-fest@5.8.0/node_modules/type-fest/source/require-exactly-one.d.ts /** Create a type that requires exactly one of the given keys and disallows more, while keeping the remaining keys as is. Use-cases: - Creating interfaces for components that only need one of the keys to display properly. - Declaring generic keys in a single place for a single use-case that gets narrowed down via `RequireExactlyOne`. The caveat with `RequireExactlyOne` is that TypeScript doesn't always know at compile time every key that will exist at runtime. Therefore `RequireExactlyOne` can't do anything to prevent extra keys it doesn't know about. @example ``` import type {RequireExactlyOne} from 'type-fest'; type Responder = { text: () => string; json: () => string; secure: boolean; }; const responder: RequireExactlyOne<Responder, 'text' | 'json'> = { // Adding a `text` key here would cause a compile error. json: () => '{"message": "ok"}', secure: true, }; ``` @category Object */ type RequireExactlyOne<ObjectType, KeysType extends keyof ObjectType = keyof ObjectType> = IfNotAnyOrNever<ObjectType, { ifNot: If<IsNever<KeysType>, never, _RequireExactlyOne<ObjectType, If<IsAny<KeysType>, keyof ObjectType, KeysType>>>; }>; type _RequireExactlyOne<ObjectType, KeysType extends keyof ObjectType> = { [Key in KeysType]: (Required<Pick<ObjectType, Key>> & Partial<Record<Exclude<KeysType, Key>, never>>); }[KeysType] & Omit<ObjectType, KeysType>; //#endregion //#region src/types/scope.d.ts /** Authorization scopes for grantless Selling Partner API operations. */ declare enum AuthorizationScope { /** Scope for the Notifications API. */ NOTIFICATIONS = "sellingpartnerapi::notifications", /** Scope for rotating application client credentials. */ CLIENT_CREDENTIAL_ROTATION = "sellingpartnerapi::client_credential:rotation" } //#endregion //#region src/types/access-token.d.ts interface BaseAccessTokenQuery { client_id: string; client_secret: string; } type RefreshTokenAccessTokenQuery = { grant_type: 'refresh_token'; refresh_token: string; } & BaseAccessTokenQuery; type ClientCredentialsAccessTokenQuery = { grant_type: 'client_credentials'; scope: string; } & BaseAccessTokenQuery; /** Request body for the LWA token endpoint. */ type AccessTokenQuery = RefreshTokenAccessTokenQuery | ClientCredentialsAccessTokenQuery; /** Response body from the LWA token endpoint. */ interface AccessTokenData { access_token: string; refresh_token?: string; token_type: string; expires_in: number; } //#endregion //#region src/error.d.ts /** Error thrown when an LWA token request fails. Wraps the underlying Axios error with a human-readable message that includes the HTTP status code (or "No response" for network errors). */ declare class SellingPartnerApiAuthError extends AxiosError<AccessTokenData, AccessTokenQuery> { /** The original error message from the failed HTTP request. */ readonly innerMessage: string; constructor(error: AxiosError<AccessTokenData, AccessTokenQuery>); } //#endregion //#region src/index.d.ts /** Configuration parameters for Selling Partner API authentication. Both `clientId` and `clientSecret` fall back to the `LWA_CLIENT_ID` and `LWA_CLIENT_SECRET` environment variables when omitted. `refreshToken` falls back to `LWA_REFRESH_TOKEN`. */ interface SellingPartnerAuthParameters { /** LWA client identifier. Defaults to the `LWA_CLIENT_ID` environment variable. */ clientId?: string; /** LWA client secret. Defaults to the `LWA_CLIENT_SECRET` environment variable. */ clientSecret?: string; /** LWA refresh token. Defaults to the `LWA_REFRESH_TOKEN` environment variable. Mutually exclusive with `scopes`. */ refreshToken?: string; /** Authorization scopes for grantless operations. Mutually exclusive with `refreshToken`. */ scopes?: AuthorizationScope[]; } /** Handles Login with Amazon (LWA) OAuth token management for the Selling Partner API. Supports both refresh-token and grantless (scope-based) authentication flows. Tokens are cached and automatically refreshed when expired. Concurrent calls to {@link getAccessToken} are deduplicated into a single request. */ declare class SellingPartnerApiAuth { #private; private readonly clientId; private readonly clientSecret; private readonly refreshToken?; private readonly scopes?; constructor(parameters: RequireExactlyOne<SellingPartnerAuthParameters, 'refreshToken' | 'scopes'>); /** Returns a valid LWA access token, refreshing it if expired. Concurrent calls while a refresh is in progress share the same request. @returns The access token string. */ getAccessToken(): Promise<string>; /** Expiration date of the currently cached access token, or `undefined` if no token has been fetched yet. */ protected get accessTokenExpiration(): Date | undefined; } //#endregion export { AuthorizationScope, SellingPartnerApiAuth, SellingPartnerApiAuthError, SellingPartnerAuthParameters }; //# sourceMappingURL=index.d.cts.map