UNPKG

bc-api-client

Version:

A client for the BigCommerce management API and app authentication

1,055 lines 54.7 kB
import { HTTPError, KyRequest, Options, TimeoutError } from "ky"; import { LimitFunction } from "p-limit"; //#region src/lib/common.d.ts type ConcurrencyOptions = { /** Max concurrent requests. Must be 1–1000. `false` for sequential. Defaults to 10. */ concurrency?: number | false; /** * Divisor (or `(concurrency, status) => number` function) applied to concurrency on * non-429 error responses. Defaults to 2. */ backoff?: ((concurrency: number, status: number) => number) | number; /** Concurrency cap applied when a 429 response is received. Defaults to 1. */ rateLimitBackoff?: number; /** * Amount (or `(concurrency) => number` function) added to concurrency per successful * response while below the configured max. Defaults to 1. */ backoffRecover?: ((concurrency: number) => number) | number; /** * A p-limit instance to reuse across calls. When provided, `batchStream` uses it instead of * creating a new one, allowing callers to observe and react to live concurrency changes. */ pLimit?: LimitFunction; }; /** * Configuration options for the BigCommerce client. */ interface ClientConfig extends Omit<Options, 'throwHttpErrors' | 'parseJson' | 'method' | 'body' | 'json' | 'searchParams'>, ConcurrencyOptions { storeHash: string; accessToken: string; logger?: Logger | LogLevel | boolean; } //#endregion //#region src/lib/logger.d.ts /** * Logging interface for the BigCommerce client. * * Implement this interface to provide custom logging. The client passes context data * as the first argument, making it compatible with structured loggers. */ interface Logger { debug(data: Record<string, unknown>, message?: string): void; info(data: Record<string, unknown>, message?: string): void; warn(data: Record<string, unknown>, message?: string): void; error(data: Record<string, unknown>, message?: string): void; } type PowertoolsLikeLogger = { debug(message: string, ...data: Record<string, unknown>[]): void; info(message: string, ...data: Record<string, unknown>[]): void; warn(message: string, ...data: Record<string, unknown>[]): void; error(message: string, ...data: Record<string, unknown>[]): void; }; /** @internal */ declare const LOG_LEVELS: readonly ["debug", "info", "warn", "error"]; /** Supported log levels. */ type LogLevel = (typeof LOG_LEVELS)[number]; /** * Adapts an AWS Lambda Powertools logger to the {@link Logger} interface expected by * {@link BigCommerceClient} and {@link BigCommerceAuth}. * * Powertools loggers use `(message, ...data)` argument order whereas this library uses * `(data, message)`. This adapter swaps the arguments. * * @param logger - An AWS Lambda Powertools (or any {@link PowertoolsLikeLogger}-compatible) logger. * @returns A {@link Logger} wrapper suitable for `config.logger`. */ declare const fromAwsPowertoolsLogger: (logger: PowertoolsLikeLogger) => Logger; /** * Console-based {@link Logger} that filters messages below a minimum level. * * Used automatically when `config.logger` is `true`, `undefined`, or a {@link LogLevel} string. * Can also be instantiated directly for custom log level control. * * @example * ```ts * new BigCommerceClient({ ..., logger: new FallbackLogger('debug') }); * ``` */ declare class FallbackLogger implements Logger { readonly level: LogLevel; /** * @param level - Minimum level to output. Messages below this level are silently dropped. */ constructor(level: LogLevel); debug(data: Record<string, unknown>, message?: string): void; info(data: Record<string, unknown>, message?: string): void; warn(data: Record<string, unknown>, message?: string): void; error(data: Record<string, unknown>, message?: string): void; private log; } //#endregion //#region src/auth.d.ts /** * Configuration options for BigCommerce authentication */ type BigCommerceAuthConfig = { /** The OAuth client ID from BigCommerce */ clientId: string; /** The OAuth client secret from BigCommerce */ secret: string; /** The redirect URI registered with BigCommerce */ redirectUri: string; /** Optional array of scopes to validate during auth callback */ scopes?: string[]; /** Optional logger instance */ logger?: Logger | LogLevel | boolean; }; /** * Query parameters received from BigCommerce auth callback */ type BigCommerceAuthQuery = { /** The authorization code from BigCommerce */ code: string; /** The granted OAuth scopes */ scope: string; /** The store context */ context: string; }; /** * User information returned from BigCommerce */ type User = { /** The user's ID */ id: number; /** The user's username */ username: string; /** The user's email address */ email: string; }; /** * Response from BigCommerce token endpoint */ type TokenResponse = { /** The OAuth access token */ access_token: string; /** The granted OAuth scopes */ scope: string; /** Information about the authenticated user */ user: User; /** Information about the store owner */ owner: User; /** The store context */ context: string; /** The BigCommerce account UUID */ account_uuid: string; }; /** * JWT claims from BigCommerce */ type Claims = { /** JWT audience */ aud: string; /** JWT issuer */ iss: string; /** JWT issued at timestamp */ iat: number; /** JWT not before timestamp */ nbf: number; /** JWT expiration timestamp */ exp: number; /** JWT unique identifier */ jti: string; /** JWT subject */ sub: string; /** Information about the authenticated user */ user: { id: number; email: string; locale: string; }; /** Information about the store owner */ owner: { id: number; email: string; }; /** The store URL */ url: string; /** The channel ID (if applicable) */ channel_id: number | null; }; /** * Handles authentication with BigCommerce OAuth */ declare class BigCommerceAuth { private readonly config; private readonly logger; private readonly client; /** * Creates a new BigCommerceAuth instance for handling OAuth authentication * @param config - Configuration options for BigCommerce authentication * @param config.clientId - The OAuth client ID from BigCommerce * @param config.secret - The OAuth client secret from BigCommerce * @param config.redirectUri - The redirect URI registered with BigCommerce * @param config.scopes - Optional array of scopes to validate during auth callback * @param config.logger - Optional logger instance for debugging and error tracking * @throws {BCAuthInvalidRedirectUriError} If the redirect URI is invalid */ constructor(config: BigCommerceAuthConfig); /** * Exchanges an OAuth authorization code for an access token. * * @param data - The auth callback payload: a raw query string, `URLSearchParams`, or a * pre-parsed object with `code`, `scope`, and `context`. * @returns The token response including `access_token`, `user`, and `context`. * @throws {@link BCAuthMissingParamError} if `code`, `scope`, or `context` are absent. * @throws {@link BCAuthScopeMismatchError} if the granted scopes don't include all `config.scopes`. * @throws {@link BCApiError} on HTTP error responses from the token endpoint. * @throws {@link BCTimeoutError} if the token request times out. * @throws {@link BCClientError} on any other error. */ requestToken(data: string | BigCommerceAuthQuery | URLSearchParams): Promise<TokenResponse>; /** * Verifies a JWT payload from BigCommerce * @param jwtPayload - The JWT string to verify * @param storeHash - The store hash for the BigCommerce store * @returns Promise resolving to the verified JWT claims * @throws {BCAuthInvalidJwtError} If the JWT is invalid */ verify(jwtPayload: string, storeHash: string): Promise<Claims>; /** * Parses and validates a query string from BigCommerce auth callback * @param queryString - The query string to parse * @returns The parsed auth query parameters * @throws {BCAuthMissingParamError} If required parameters are missing */ private parseQueryString; /** * Validates that the granted scopes match the expected scopes * @param scopes - Space-separated list of granted scopes * @throws {BCAuthScopeMismatchError} If the scopes don't match the expected scopes */ private validateScopes; } //#endregion //#region src/lib/standard-schema.d.ts /** The Standard Schema interface. */ interface StandardSchemaV1<Input = unknown, Output = Input> { /** The Standard Schema properties. */ readonly '~standard': StandardSchemaV1.Props<Input, Output>; } declare namespace StandardSchemaV1 { /** The Standard Schema properties interface. */ interface Props<Input = unknown, Output = Input> { /** The version number of the standard. */ readonly version: 1; /** The vendor name of the schema library. */ readonly vendor: string; /** Validates unknown input values. */ readonly validate: (value: unknown, options?: StandardSchemaV1.Options | undefined) => Result<Output> | Promise<Result<Output>>; /** Inferred types associated with the schema. */ readonly types?: Types<Input, Output> | undefined; } /** The result interface of the validate function. */ type Result<Output> = SuccessResult<Output> | FailureResult; /** The result interface if validation succeeds. */ interface SuccessResult<Output> { /** The typed output value. */ readonly value: Output; /** A falsy value for `issues` indicates success. */ readonly issues?: undefined; } interface Options { /** Explicit support for additional vendor-specific parameters, if needed. */ readonly libraryOptions?: Record<string, unknown> | undefined; } /** The result interface if validation fails. */ interface FailureResult { /** The issues of failed validation. */ readonly issues: ReadonlyArray<Issue>; } /** The issue interface of the failure output. */ interface Issue { /** The error message of the issue. */ readonly message: string; /** The path of the issue, if any. */ readonly path?: ReadonlyArray<PropertyKey | PathSegment> | undefined; } /** The path segment interface of the issue. */ interface PathSegment { /** The key representing a path segment. */ readonly key: PropertyKey; } /** The Standard Schema types interface. */ interface Types<Input = unknown, Output = Input> { /** The input type of the schema. */ readonly input: Input; /** The output type of the schema. */ readonly output: Output; } /** Infers the input type of a Standard Schema. */ type InferInput<Schema extends StandardSchemaV1> = NonNullable<Schema['~standard']['types']>['input']; /** Infers the output type of a Standard Schema. */ type InferOutput<Schema extends StandardSchemaV1> = NonNullable<Schema['~standard']['types']>['output']; } //#endregion //#region src/lib/request.d.ts /** BigCommerce API versions supported by the client. */ type ApiVersion = 'v3' | 'v2'; /** Valid query parameter value types. */ type QueryValue = string | number | Array<string | number>; /** Query parameter object for API requests. */ type Query = Record<string, QueryValue>; /** Supported HTTP methods for API requests. */ type HttpMethod = 'POST' | 'GET' | 'PUT' | 'DELETE'; /** @internal */ type BaseKyRequest = Omit<Options, 'json' | 'method' | 'searchQueryParams' | 'body' | 'throwHttpErrors' | 'parseJson'>; /** @internal */ type QuerySchemaOptions<TQuery extends Query> = /** Query parameters to send with the request. */ { query: TQuery; querySchema: StandardSchemaV1<TQuery>; } | { query?: TQuery; querySchema?: never; }; /** @internal */ type BodySchemaOptions<TBody> = /** Request body, serialized as JSON. */ { body: TBody; bodySchema: StandardSchemaV1<TBody>; } | { body?: TBody; bodySchema?: never; }; /** * Full request options for direct API calls. * @see {@link GetOptions}, {@link PostOptions}, {@link PutOptions}, {@link DeleteOptions} */ type RequestOptions<TBody, TRes, TQuery extends Query> = BaseKyRequest & QuerySchemaOptions<TQuery> & BodySchemaOptions<TBody> & { /** HTTP method for the request. */ method: HttpMethod; /** API version to use. Defaults to `'v3'`. */ version?: ApiVersion; /** Schema to validate the response body. */ responseSchema?: StandardSchemaV1<TRes>; }; /** Options for GET requests. */ type GetOptions<TRes, TQuery extends Query> = Omit<RequestOptions<never, TRes, TQuery>, 'body' | 'bodySchema' | 'method'>; /** Options for POST requests. */ type PostOptions<TBody, TRes, TQuery extends Query> = Omit<RequestOptions<TBody, TRes, TQuery>, 'method'>; /** Options for PUT requests. */ type PutOptions<TBody, TRes, TQuery extends Query> = PostOptions<TBody, TRes, TQuery>; /** Options for DELETE requests. */ type DeleteOptions<TQuery extends Query> = Omit<RequestOptions<never, never, TQuery>, 'body' | 'bodySchema' | 'method' | 'responseSchema'>; /** * Request descriptor for batch operations. * Use the {@link req} helpers to construct these. */ type BatchRequestOptions<TBody, TRes, TQuery extends Query> = { path: string; } & RequestOptions<TBody, TRes, TQuery>; /** * Helpers for building typed request descriptors to pass to * {@link BigCommerceClient.batchSafe} or {@link BigCommerceClient.batchStream}. * * @example * ```ts * const results = await client.batchSafe([ * req.get('catalog/products/1'), * req.post('catalog/products', { body: { name: 'Widget' } }), * ]); * ``` */ declare const req: { /** * Builds a GET request descriptor. * @param path - API path relative to the store's versioned base URL. * @param options - Optional query params, schemas, and ky options. */ get: <TRes, TQuery extends Query = Query>(path: string, options?: GetOptions<TRes, TQuery>) => BatchRequestOptions<never, TRes, TQuery>; /** * Builds a POST request descriptor. * @param path - API path relative to the store's versioned base URL. * @param options - Optional body, query params, schemas, and ky options. */ post: <TRes, TBody = unknown, TQuery extends Query = Query>(path: string, options?: PostOptions<TBody, TRes, TQuery>) => BatchRequestOptions<TBody, TRes, TQuery>; /** * Builds a PUT request descriptor. * @param path - API path relative to the store's versioned base URL. * @param options - Optional body, query params, schemas, and ky options. */ put: <TRes, TBody = unknown, TQuery extends Query = Query>(path: string, options?: PutOptions<TBody, TRes, TQuery>) => BatchRequestOptions<TBody, TRes, TQuery>; /** * Builds a DELETE request descriptor. * @param path - API path relative to the store's versioned base URL. * @param options - Optional query params and ky options. */ delete: <TQuery extends Query = Query>(path: string, options?: DeleteOptions<TQuery>) => BatchRequestOptions<never, never, TQuery>; }; /** * Options for v3 paginated collection operations ({@link BigCommerceClient.collect}, {@link BigCommerceClient.stream}). */ type CollectOptions<TItem, TQuery extends Query> = ConcurrencyOptions & Omit<GetOptions<TItem, TQuery>, 'responseSchema' | 'version'> & { /** Schema to validate each item in the response. */ itemSchema?: StandardSchemaV1<TItem>; }; type BlindOptions<TItem, TQuery extends Query> = Omit<CollectOptions<TItem, TQuery>, 'version'> & { maxPages?: number; }; /** * Options for v2 paginated operations with known count ({@link BigCommerceClient.collectCount}, {@link BigCommerceClient.streamCount}). */ type CountedCollectOptions<TItem, TQuery extends Query> = CollectOptions<TItem, TQuery> & { /** Total number of items expected (for v2 endpoints without pagination metadata). */ count?: number; }; /** * Options for query-based filtering operations ({@link BigCommerceClient.query}, {@link BigCommerceClient.queryStream}). */ type QueryOptions<TItem, TQuery extends Query> = CollectOptions<TItem, TQuery> & { /** Query parameter name for value filtering (e.g., `'id:in'`). */ key: string; /** Values to filter by. Automatically chunked across multiple requests. */ values: (string | number)[]; }; //#endregion //#region src/lib/errors.d.ts type ErrorContext = Record<string, unknown>; /** * Abstract base class for all library errors. Carries a typed `context` object with * structured diagnostic data and a machine-readable `code` string. * * Use `instanceof` checks against specific subclasses rather than this base class. */ declare abstract class BaseError<TContext extends ErrorContext = ErrorContext> extends Error { readonly context: TContext; /** Machine-readable error code. Unique per subclass. */ abstract readonly code: string; constructor(message: string, context: TContext, options?: ErrorOptions); /** @internal */ toJSON(): { name: string; code: string; message: string; context: TContext; cause: unknown; }; } /** Catch-all for unexpected client-side errors not covered by a more specific subclass. */ declare class BCClientError extends BaseError<Record<string, unknown>> { code: string; constructor(message: string, context?: Record<string, unknown>, cause?: unknown); } /** Thrown by the {@link BigCommerceClient} constructor when credentials or config are invalid. */ declare class BCCredentialsError extends BaseError<{ errors: string[]; }> { code: string; constructor(errors: string[]); } /** Thrown before a request is sent when the constructed URL exceeds 2048 characters. */ declare class BCUrlTooLongError extends BaseError<{ url: string; max: number; len: number; }> { code: string; constructor(url: string, max: number); } /** * Thrown during retry when a 429 response is received but the expected * `X-Rate-Limit-*` headers are absent, making it impossible to determine the backoff delay. */ declare class BCRateLimitNoHeadersError extends BaseError<{ url: string; method: string; attempts: number; }> { code: string; constructor(request: KyRequest, attempts: number); } /** * Thrown during retry when a 429 response specifies a reset window that exceeds * `config.retry.maxRetryAfter`, preventing an unbounded wait. */ declare class BCRateLimitDelayTooLongError extends BaseError<{ url: string; method: string; attempts: number; maxDelay: number; delay: number; }> { code: string; constructor(request: KyRequest, attempts: number, maxDelay: number, delay: number); } /** * Abstract base for all StandardSchema validation errors. Carries the raw `data` that failed * validation and the schema `error` result. Use specific subclasses for `instanceof` checks. */ declare abstract class BCSchemaValidationError extends BaseError<{ method: string; path: string; data: unknown; error: StandardSchemaV1.FailureResult; }> { constructor(message: string, method: string, path: string, data: unknown, error: StandardSchemaV1.FailureResult); } /** Thrown when `options.querySchema` validation fails before a request is sent. */ declare class BCQueryValidationError extends BCSchemaValidationError { code: string; } /** Thrown when `options.bodySchema` validation fails before a request is sent. */ declare class BCRequestBodyValidationError extends BCSchemaValidationError { code: string; } /** Thrown when `options.responseSchema` validation fails after a response is received. */ declare class BCResponseValidationError extends BCSchemaValidationError { code: string; } /** Thrown or yielded when `options.itemSchema` validation fails for an item in a page response. */ declare class BCPaginatedItemValidationError extends BCSchemaValidationError { code: string; } /** * Thrown when the BigCommerce API returns a non-2xx HTTP response. * `context.status` and `context.responseBody` are the most useful fields for debugging. */ declare class BCApiError extends BaseError<{ method: string; url: string; status: number; statusMessage: string; headers: Record<string, string>; requestBody: string; responseBody: unknown; }> { code: string; constructor(err: HTTPError, requestBody: string); } /** Thrown when a request exceeds the configured timeout (default 120 s). */ declare class BCTimeoutError extends BaseError<{ method: string; url: string; }> { code: string; constructor(err: TimeoutError); } /** * Thrown when the response body cannot be read or parsed as JSON. * `context.rawBody` contains the raw text that failed to parse (empty string if the body was empty). */ declare class BCResponseParseError extends BaseError<{ method: string; status: number; path: string; query?: Query; rawBody?: string; }> { code: string; constructor(method: string, path: string, status: number, cause: unknown, query?: Query, rawBody?: string); } /** * Thrown when a pagination option (`limit`, `page`, or `count`) is not a positive number. * `context.option` names the offending field; `context.value` is the value that was passed. */ declare class BCPaginatedOptionError extends BaseError<{ path: string; option: string; value: unknown; }> { code: string; constructor(path: string, value: unknown, option: string); } /** * Thrown or yielded when a paginated response is missing required v3 envelope fields * (`data`, `meta.pagination`, etc.). Usually means the path is not a v3 collection endpoint. */ declare class BCPaginatedResponseError extends BaseError<{ path: string; data: unknown; reason: string; }> { code: string; constructor(path: string, data: unknown, reason: string); } /** Thrown by {@link BigCommerceAuth} constructor when `config.redirectUri` is not a valid URL. */ declare class BCAuthInvalidRedirectUriError extends BaseError<{ redirectUri: string; }> { code: string; constructor(redirectUri: string, cause: unknown); } /** Thrown by {@link BigCommerceAuth.requestToken} when a required OAuth callback param is absent. */ declare class BCAuthMissingParamError extends BaseError<{ param: string; }> { code: string; constructor(param: string); } /** * Thrown by {@link BigCommerceAuth.requestToken} when the scopes granted by BigCommerce * do not include all scopes listed in `config.scopes`. * `context.missing` lists the scopes that were expected but not granted. */ declare class BCAuthScopeMismatchError extends BaseError<{ granted: string[]; expected: string[]; missing: string[]; }> { code: string; constructor(granted: string[], expected: string[], missing: string[]); } /** Thrown by {@link BigCommerceAuth.verify} when the JWT signature, audience, issuer, or subject is invalid. */ declare class BCAuthInvalidJwtError extends BaseError<{ storeHash: string; }> { code: string; constructor(storeHash: string, cause: unknown); } //#endregion //#region src/lib/result.d.ts type Ok<T> = { ok: true; data: T; err: undefined; }; type Err<E> = { ok: false; data: undefined; err: E; }; type Result$1<T, E> = Ok<T> | Err<E>; /** * A {@link Result} extended with the zero-based index of the originating request in the input * array passed to {@link BigCommerceClient.batchStream} or {@link BigCommerceClient.batchSafe}. * * Because concurrent requests complete out of insertion order, `index` is the only reliable way * to correlate a result back to its input. * * @example * ```ts * const requests = ids.map(id => req.get(`catalog/products/${id}`)); * for await (const { index, err, data } of client.batchStream(requests)) { * const originalId = ids[index]; * if (err) { console.error(originalId, err); continue; } * console.log(originalId, data); * } * ``` */ type BatchResult<T, E> = Result$1<T, E> & { index: number; }; /** * A {@link Result} extended with the one-based page number from which the item was fetched. * * Because concurrent requests complete out of page order, `page` is the only reliable way * to correlate a result back to its source page when using {@link BigCommerceClient.stream} * or {@link BigCommerceClient.streamBlind}. * * @example * ```ts * for await (const { page, err, data } of client.stream('catalog/products')) { * if (err) { console.error(`page ${page}:`, err); continue; } * console.log(`page ${page}:`, data); * } * ``` */ type PageResult<T, E> = Result$1<T, E> & { page: number; }; /** * Creates a successful {@link Result}. Check `result.ok` or `result.err` before accessing `data`. * @param data - The success value. */ declare const Ok: <T, E>(data: T) => Result$1<T, E>; /** * Creates a failed {@link Result}. Check `result.ok` or `result.err` before accessing `err`. * @param err - The error value. */ declare const Err: <T, E>(err: E) => Result$1<T, E>; //#endregion //#region src/client.d.ts declare class BigCommerceClient { private readonly config; private readonly logger?; private readonly client; private readonly storeHash; /** * Creates a new BigCommerceClient. * * @param config - Client configuration. Ky options (e.g. `prefix`, `timeout`, `retry`, * `hooks`) are forwarded to the underlying ky instance. * @param config.storeHash - BigCommerce store hash. Must be a non-empty string. * @param config.accessToken - BigCommerce API access token. Must be a non-empty string. * @param config.logger - A {@link Logger} instance, a log level string * (`'debug' | 'info' | 'warn' | 'error'`), `true` to enable console logging at `'info'` * level, or `false` to disable logging entirely. Omitting also defaults to `'info'` level. * @param config.concurrency - Default max concurrent requests for batch/stream operations. * Must be between 1 and 1000. Pass `false` to disable concurrency (sequential execution). * Defaults to 10. * @param config.rateLimitBackoff - Concurrency cap applied when a 429 response is received. * Defaults to 1. * @param config.backoff - Divisor (or `(concurrency, status) => number` function) applied to * concurrency on non-429 error responses. Defaults to 2. * @param config.backoffRecover - Amount (or `(concurrency) => number` function) added to * concurrency per successful response while below the configured max. Defaults to 1. * * @throws {@link BCCredentialsError} if `storeHash` or `accessToken` are missing. * @throws {@link BCClientError} if `prefix` is not a valid URL or `concurrency` is out of range. */ constructor(config: ClientConfig); /** * Sends a GET request to the given path. * * @param path - API path relative to the store's versioned base URL (e.g. `catalog/products`). * @param options - Ky options are forwarded to the underlying request. * @param options.version - API version segment inserted into the URL. Defaults to `'v3'`. * @param options.query - Query parameters to append to the URL. * @param options.querySchema - StandardSchemaV1 schema to validate `query` before the request * is sent. Requires `query` to be provided. * @param options.responseSchema - StandardSchemaV1 schema to validate the parsed response body. * * @returns Parsed and optionally validated response body. * * @throws {@link BCApiError} on HTTP error responses. * @throws {@link BCTimeoutError} if the request times out. * @throws {@link BCResponseParseError} if the response body cannot be parsed. * @throws {@link BCUrlTooLongError} if the constructed URL exceeds 2048 characters. * @throws {@link BCRateLimitNoHeadersError} if a 429 is received without rate-limit headers. * @throws {@link BCRateLimitDelayTooLongError} if the rate-limit reset window exceeds * `config.retry.maxRetryAfter`. * @throws {@link BCQueryValidationError} if `querySchema` validation fails. * @throws {@link BCResponseValidationError} if `responseSchema` validation fails. * @throws {@link BCClientError} on any other ky or unknown error. */ get<TRes = unknown, TQuery extends Query = Query>(path: string, options?: GetOptions<TRes, TQuery>): Promise<TRes>; /** * Sends a POST request to the given path. * * @param path - API path relative to the store's versioned base URL. * @param options - Ky options are forwarded to the underlying request. * @param options.version - API version segment inserted into the URL. Defaults to `'v3'`. * @param options.body - Request body, serialized as JSON. * @param options.bodySchema - StandardSchemaV1 schema to validate `body` before the request * is sent. Requires `body` to be provided. * @param options.query - Query parameters to append to the URL. * @param options.querySchema - StandardSchemaV1 schema to validate `query` before the request * is sent. Requires `query` to be provided. * @param options.responseSchema - StandardSchemaV1 schema to validate the parsed response body. * * @returns Parsed and optionally validated response body. * * @throws {@link BCApiError} on HTTP error responses. * @throws {@link BCTimeoutError} if the request times out. * @throws {@link BCResponseParseError} if the response body cannot be parsed. * @throws {@link BCUrlTooLongError} if the constructed URL exceeds 2048 characters. * @throws {@link BCRateLimitNoHeadersError} if a 429 is received without rate-limit headers. * @throws {@link BCRateLimitDelayTooLongError} if the rate-limit reset window exceeds * `config.retry.maxRetryAfter`. * @throws {@link BCQueryValidationError} if `querySchema` validation fails. * @throws {@link BCRequestBodyValidationError} if `bodySchema` validation fails. * @throws {@link BCResponseValidationError} if `responseSchema` validation fails. * @throws {@link BCClientError} on any other ky or unknown error. */ post<TRes = unknown, TBody = unknown, TQuery extends Query = Query>(path: string, options?: PostOptions<TBody, TRes, TQuery>): Promise<TRes>; /** * Sends a PUT request to the given path. * * @param path - API path relative to the store's versioned base URL. * @param options - Ky options are forwarded to the underlying request. * @param options.version - API version segment inserted into the URL. Defaults to `'v3'`. * @param options.body - Request body, serialized as JSON. * @param options.bodySchema - StandardSchemaV1 schema to validate `body` before the request * is sent. Requires `body` to be provided. * @param options.query - Query parameters to append to the URL. * @param options.querySchema - StandardSchemaV1 schema to validate `query` before the request * is sent. Requires `query` to be provided. * @param options.responseSchema - StandardSchemaV1 schema to validate the parsed response body. * * @returns Parsed and optionally validated response body. * * @throws {@link BCApiError} on HTTP error responses. * @throws {@link BCTimeoutError} if the request times out. * @throws {@link BCResponseParseError} if the response body cannot be parsed. * @throws {@link BCUrlTooLongError} if the constructed URL exceeds 2048 characters. * @throws {@link BCRateLimitNoHeadersError} if a 429 is received without rate-limit headers. * @throws {@link BCRateLimitDelayTooLongError} if the rate-limit reset window exceeds * `config.retry.maxRetryAfter`. * @throws {@link BCQueryValidationError} if `querySchema` validation fails. * @throws {@link BCRequestBodyValidationError} if `bodySchema` validation fails. * @throws {@link BCResponseValidationError} if `responseSchema` validation fails. * @throws {@link BCClientError} on any other ky or unknown error. */ put<TRes = unknown, TBody = unknown, TQuery extends Query = Query>(path: string, options?: PutOptions<TBody, TRes, TQuery>): Promise<TRes>; /** * Sends a DELETE request to the given path. * * Silently suppresses 404 responses (resource already gone) and empty response bodies. * * @param path - API path relative to the store's versioned base URL. * @param options - Ky options are forwarded to the underlying request. * @param options.version - API version segment inserted into the URL. Defaults to `'v3'`. * @param options.query - Query parameters to append to the URL. * @param options.querySchema - StandardSchemaV1 schema to validate `query` before the request * is sent. Requires `query` to be provided. * * @throws {@link BCApiError} on non-404 HTTP error responses. * @throws {@link BCTimeoutError} if the request times out. * @throws {@link BCResponseParseError} if the response body is non-empty and cannot be parsed. * @throws {@link BCUrlTooLongError} if the constructed URL exceeds 2048 characters. * @throws {@link BCRateLimitNoHeadersError} if a 429 is received without rate-limit headers. * @throws {@link BCRateLimitDelayTooLongError} if the rate-limit reset window exceeds * `config.retry.maxRetryAfter`. * @throws {@link BCQueryValidationError} if `querySchema` validation fails. * @throws {@link BCClientError} on any other ky or unknown error. */ delete<TRes = never, TQuery extends Query = Query>(path: string, options?: DeleteOptions<TQuery>): Promise<void>; /** * Fetches items from a v3 paginated endpoint by splitting `values` across multiple requests * using the given `key` query param, chunking to stay within URL length limits. * * Collects all results into an array. Use {@link queryStream} to process items lazily. * * **Sorting and concurrency:** when `concurrency > 1`, chunks complete out of order so * sorted output is not preserved across the full result set. Pass `concurrency: false` * if sort order matters. * * @param path - API path relative to the store's versioned base URL. * @param options - Query options including `key`, `values`, pagination params, and concurrency * controls. * @param options.key - Query parameter name used for value filtering (e.g. `'id:in'`). * @param options.values - Values to filter by. Automatically chunked across multiple requests * to keep each URL under 2048 characters. * @param options.query - Additional query parameters. `query.limit` controls page size * (default 250, must be > 0). If `options.key` is present in `query` it will be ignored. * @param options.querySchema - StandardSchemaV1 schema to validate `query`. Requires `query` * to be provided. * @param options.itemSchema - StandardSchemaV1 schema to validate each returned item. * @param options.concurrency - Max concurrent chunk requests. Must be 1–1000. `false` for * sequential. Defaults to `config.concurrency`, or 10 if not set on the client. * @param options.rateLimitBackoff - Concurrency cap on 429 responses. Defaults to * `config.rateLimitBackoff`, or 1 if not set on the client. * @param options.backoff - Divisor (or function) applied to concurrency on error responses. * Defaults to `config.backoff`, or 2 if not set on the client. * @param options.backoffRecover - Amount (or function) added to concurrency per successful * response. Defaults to `config.backoffRecover`, or 1 if not set on the client. * * @returns All matching items across all chunked requests. * @throws {@link BCPaginatedOptionError} if `query.limit` is not a positive number. * @throws {@link BCQueryValidationError} if `querySchema` validation fails. * @throws {@link BCApiError} on HTTP error responses. * @throws {@link BCTimeoutError} if a request times out. * @throws {@link BCResponseParseError} if a response body cannot be parsed. * @throws {@link BCUrlTooLongError} if a constructed URL exceeds 2048 characters. * @throws {@link BCRateLimitNoHeadersError} if a 429 is received without rate-limit headers. * @throws {@link BCRateLimitDelayTooLongError} if the rate-limit reset window exceeds * `config.retry.maxRetryAfter`. * @throws {@link BCPaginatedResponseError} if a page response has an unexpected shape. * @throws {@link BCPaginatedItemValidationError} if `itemSchema` validation fails for an item. * @throws {@link BCClientError} on any other ky or unknown error. */ query<TItem = unknown, TQuery extends Query = Query>(path: string, options: QueryOptions<TItem, TQuery>): Promise<TItem[]>; /** * Streaming variant of {@link query}. Yields each item individually as results arrive, * splitting `values` into URL-length-safe chunks across concurrent requests. * * Each yielded value is a {@link Result} — check `err` before using `data`. * * **Sorting and concurrency:** when `concurrency > 1`, chunks complete out of order so * sorted output is not preserved across the full result set. Pass `concurrency: false` * if sort order matters. * * @param path - API path relative to the store's versioned base URL. * @param options - Query options including `key`, `values`, pagination params, and concurrency * controls. * @param options.key - Query parameter name used for value filtering (e.g. `'id:in'`). * @param options.values - Values to filter by. Automatically chunked across multiple requests * to keep each URL under 2048 characters. * @param options.query - Additional query parameters. `query.limit` controls page size * (default 250, must be > 0). If `options.key` is present in `query` it will be ignored. * @param options.querySchema - StandardSchemaV1 schema to validate `query`. Requires `query` * to be provided. * @param options.itemSchema - StandardSchemaV1 schema to validate each returned item. * @param options.concurrency - Max concurrent chunk requests. Must be 1–1000. `false` for * sequential. Defaults to `config.concurrency`, or 10 if not set on the client. * @param options.rateLimitBackoff - Concurrency cap on 429 responses. Defaults to * `config.rateLimitBackoff`, or 1 if not set on the client. * @param options.backoff - Divisor (or function) applied to concurrency on error responses. * Defaults to `config.backoff`, or 2 if not set on the client. * @param options.backoffRecover - Amount (or function) added to concurrency per successful * response. Defaults to `config.backoffRecover`, or 1 if not set on the client. * @throws {@link BCPaginatedOptionError} if `query.limit` is not a positive number. * @throws {@link BCQueryValidationError} if `querySchema` validation fails. */ queryStream<TItem = unknown, TQuery extends Query = Query>(path: string, options: QueryOptions<TItem, TQuery>): AsyncGenerator<Result$1<TItem, BaseError>>; /** * Fetches all pages from a v3 paginated endpoint and collects items into an array. * * Use {@link stream} to process items lazily without buffering the full result set. * * **Sorting and concurrency:** the first page is fetched sequentially; remaining pages are * fetched concurrently and may complete out of order. When `concurrency > 1`, sort order * is not preserved across pages. Pass `concurrency: false` if sort order matters. * * @param path - API path relative to the store's versioned base URL. * @param options - Ky options are forwarded to page requests. * @param options.query - Query parameters. `query.limit` controls page size (default 250, * must be > 0). `query.page` sets the starting page (default 1, must be > 0). * @param options.querySchema - StandardSchemaV1 schema to validate `query`. Requires `query` * to be provided. * @param options.itemSchema - StandardSchemaV1 schema to validate each returned item. * @param options.concurrency - Max concurrent page requests for pages after the first. * Must be 1–1000. `false` for sequential. Defaults to `config.concurrency`, or 10 if not * set on the client. * @param options.rateLimitBackoff - Concurrency cap on 429 responses. Defaults to * `config.rateLimitBackoff`, or 1 if not set on the client. * @param options.backoff - Divisor (or function) applied to concurrency on error responses. * Defaults to `config.backoff`, or 2 if not set on the client. * @param options.backoffRecover - Amount (or function) added to concurrency per successful * response. Defaults to `config.backoffRecover`, or 1 if not set on the client. * @returns All items across all pages. * * @throws {@link BCPaginatedOptionError} if `query.limit` or `query.page` is not a positive number. * @throws {@link BCQueryValidationError} if `querySchema` validation fails. * @throws {@link BCApiError} on HTTP error responses. * @throws {@link BCTimeoutError} if a request times out. * @throws {@link BCResponseParseError} if a response body cannot be parsed. * @throws {@link BCUrlTooLongError} if a constructed URL exceeds 2048 characters. * @throws {@link BCRateLimitNoHeadersError} if a 429 is received without rate-limit headers. * @throws {@link BCRateLimitDelayTooLongError} if the rate-limit reset window exceeds * `config.retry.maxRetryAfter`. * @throws {@link BCPaginatedResponseError} if a page response has an unexpected shape. * @throws {@link BCPaginatedItemValidationError} if `itemSchema` validation fails for an item. * @throws {@link BCClientError} on any other ky or unknown error. */ collect<TItem = unknown, TQuery extends Query = Query>(path: string, options?: CollectOptions<TItem, TQuery>): Promise<TItem[]>; /** * Fetches all pages from a v2 flat-array endpoint and collects items into an array. * * Pagination is discovered dynamically — pages are fetched in batches until an empty page, * a 404, or a 204 response is received. No prior knowledge of total count is required. * * Use {@link streamBlind} to process items lazily without buffering the full result set. * * **Sorting and concurrency:** pages within each batch are fetched concurrently and may * complete out of order. When `concurrency > 1`, sort order is not preserved across pages. * Pass `concurrency: false` if sort order matters. * * @param path - API path relative to the store's versioned base URL (always requests v2). * @param options - Ky options are forwarded to page requests. * @param options.query - Query parameters. `query.limit` controls page size (default 250, * must be > 0). `query.page` sets the starting page (default 1, must be > 0). * @param options.querySchema - StandardSchemaV1 schema to validate `query`. Requires `query` * to be provided. * @param options.itemSchema - StandardSchemaV1 schema to validate each returned item. * @param options.maxPages - Maximum number of pages to fetch before stopping (default 500, * must be > 0). A warning is logged if this limit is reached. * @param options.concurrency - Max concurrent page requests per batch. Must be 1–1000. * `false` for sequential. Defaults to `config.concurrency`, or 10 if not set on the client. * @param options.rateLimitBackoff - Concurrency cap on 429 responses. Defaults to * `config.rateLimitBackoff`, or 1 if not set on the client. * @param options.backoff - Divisor (or function) applied to concurrency on error responses. * Defaults to `config.backoff`, or 2 if not set on the client. * @param options.backoffRecover - Amount (or function) added to concurrency per successful * response. Defaults to `config.backoffRecover`, or 1 if not set on the client. * @returns All items across all pages. * * @throws {@link BCPaginatedOptionError} if `query.limit`, `query.page`, or `maxPages` is not a positive number. * @throws {@link BCQueryValidationError} if `querySchema` validation fails. * @throws {@link BCPaginatedItemValidationError} if `itemSchema` validation fails for an item. * @throws {@link BCClientError} if a page returns a non-array response, or on any other error. * @throws {@link BCApiError} on non-terminating HTTP error responses. * @throws {@link BCTimeoutError} if a request times out. * @throws {@link BCResponseParseError} if a response body cannot be parsed. */ collectBlind<TItem = unknown, TQuery extends Query = Query>(path: string, options?: BlindOptions<TItem, TQuery>): Promise<TItem[]>; /** * Lazily streams items from a v2 flat-array endpoint, page by page. * * Pagination is discovered dynamically — pages are fetched in concurrent batches until an * empty page, a 404, or a 204 response is received. No prior knowledge of total count is * required. Each item is yielded as a {@link PageResult}: `Ok(item)` on success or * `Err(error)` for item-level validation failures and non-terminating page errors. * Use `page` to correlate the item back to its source page. * * Use {@link collectBlind} to buffer all results into an array (throws on any error). * * **Sorting and concurrency:** pages within each batch are fetched concurrently and may * complete out of order. When `concurrency > 1`, sort order is not preserved across pages. * Pass `concurrency: false` if sort order matters. * * @param path - API path relative to the store's versioned base URL (always requests v2). * @param options - Ky options are forwarded to page requests. * @param options.query - Query parameters. `query.limit` controls page size (default 250, * must be > 0). `query.page` sets the starting page (default 1, must be > 0). * @param options.querySchema - StandardSchemaV1 schema to validate `query`. Requires `query` * to be provided. * @param options.itemSchema - StandardSchemaV1 schema to validate each returned item. * @param options.maxPages - Maximum number of pages to fetch before stopping (default 500, * must be > 0). A warning is logged if this limit is reached. * @param options.concurrency - Max concurrent page requests per batch. Must be 1–1000. * `false` for sequential. Defaults to `config.concurrency`, or 10 if not set on the client. * @param options.rateLimitBackoff - Concurrency cap on 429 responses. Defaults to * `config.rateLimitBackoff`, or 1 if not set on the client. * @param options.backoff - Divisor (or function) applied to concurrency on error responses. * Defaults to `config.backoff`, or 2 if not set on the client. * @param options.backoffRecover - Amount (or function) added to concurrency per successful * response. Defaults to `config.backoffRecover`, or 1 if not set on the client. * * @throws {@link BCPaginatedOptionError} if `query.limit`, `query.page`, or `maxPages` is not a positive number. * @throws {@link BCQueryValidationError} if `querySchema` validation fails. * * @yields `Ok(item)` for each successfully fetched and validated item. * @yields `Err(BCPaginatedItemValidationError)` when `itemSchema` rejects an item. * @yields `Err(BCClientError)` when a page returns a non-array response. * @yields `Err(error)` for non-terminating page errors (e.g. non-404/204 HTTP errors). */ streamBlind<TItem = unknown, TQuery extends Query = Query>(path: string, options?: BlindOptions<TItem, TQuery>): AsyncGenerator<PageResult<TItem, BaseError>>; /** * Executes multiple requests concurrently and returns all results as {@link BatchResult} * values, never throwing. Errors from individual requests are captured as `Err` results. * * Results arrive in completion order, not input order. Use the `index` field on each * {@link BatchResult} to correlate a result back to its position in the `requests` array. * * Use {@link batchStream} to process results as they arrive rather than waiting for all. * * @param requests - Array of request descriptors built with the {@link req} helpers. * @param options.concurrency - Max concurrent requests. Must be 1–1000. `false` for * sequential. Defaults to `config.concurrency`, or 10 if not set on the client. * @param options.rateLimitBackoff - Concurrency cap on 429 responses. Defaults to * `config.rateLimitBackoff`, or 1 if not set on the client. * @param options.backoff - Divisor (or function) applied to concurrency on error responses. * Defaults to `config.backoff`, or 2 if not set on the client. * @param options.backoffRecover - Amount (or function) added to concurrency per successful * response. Defaults to `config.backoffRecover`, or 1 if not set on the client. * * @returns {@link BatchResult} array in the order requests completed (not input order). */ batchSafe<TRes = unknown, TBody = unknown, TQuery extends Query = Query>(requests: BatchRequestOptions<TBody, TRes, TQuery>[], options?: ConcurrencyOptions): Promise<BatchResult<TRes, BaseError>[]>; /** * Streams all items from a v3 paginated endpoint, fetching the first page sequentially * and remaining pages concurrently via {@link batchStream}. * * Each yielded value is a {@link PageResult} — check `err` before using `data`, and use * `page` to correlate the item back to its source page. Use * {@link collect} to gather all items into an array. * * **Sorting and concurrency:** the first page is fetched sequentially; remaining pages are * fetched concurrently and may complete out of order. When `concurrency > 1`, sort order * is not preserved across pages. Pass `concurrency: false` if sort order matters. * * @param path - API path relative to the store's versioned base URL. * @param options - Ky options are forwarded to page requests. * @param options.query - Query parameters. `query.limit` controls page size (default 250, * must be > 0). `query.page` sets the starting page (default 1, must be > 0). If the API * enforces a different limit, the actual `per_page` from the first response is used for * subsequent pages. * @param options.querySchema - StandardSchemaV1 schema to validate `query`. Requires `query` * to be provided. * @param options.itemSchema - StandardSchemaV1 schema to validate each returned item. * @param options.concurrency - Max concurrent page requests for pages after the first. * Must be 1–1000. `false` for sequ