@api-wrappers/api-core 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,755 @@
1
+ //#region src/types/common.d.ts
2
+ type MaybePromise<T> = T | Promise<T>;
3
+ type HttpMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "HEAD" | "OPTIONS";
4
+ type QueryPrimitive = string | number | boolean;
5
+ type QueryValue = QueryPrimitive | null | undefined | readonly (QueryPrimitive | null | undefined)[];
6
+ type QueryParams = Record<string, QueryValue>;
7
+ //#endregion
8
+ //#region src/context/RequestContext.d.ts
9
+ interface RequestContext {
10
+ url: string;
11
+ method: HttpMethod;
12
+ headers: Record<string, string>;
13
+ body?: unknown;
14
+ query?: QueryParams;
15
+ signal?: AbortSignal;
16
+ meta: Record<string, unknown>;
17
+ cacheKey?: string;
18
+ tags?: string[];
19
+ /**
20
+ * Number of retry attempts still available after this one.
21
+ * Equals `maxAttempts - 1 - attempt`, so it counts down from
22
+ * `maxAttempts - 1` on the first attempt to `0` on the last.
23
+ * Read-only from a plugin's perspective; set by BaseHttpClient.
24
+ */
25
+ retryCount: number;
26
+ /** Zero-based index of the current attempt (0 = first try). */
27
+ attempt: number;
28
+ timeoutMs?: number;
29
+ /**
30
+ * When set by a plugin during `beforeRequest`, `BaseHttpClient` will use
31
+ * this response directly and skip calling the transport altogether.
32
+ * Plugins that short-circuit the network (e.g. cache hits) should populate
33
+ * this field instead of relying solely on `meta`.
34
+ */
35
+ syntheticResponse?: Response;
36
+ }
37
+ //#endregion
38
+ //#region src/graphql/types.d.ts
39
+ /**
40
+ * The shape of a single error object inside a GraphQL `errors` array,
41
+ * as specified by the GraphQL over HTTP specification.
42
+ */
43
+ interface GraphQLErrorDetail {
44
+ /** Human-readable error message. */
45
+ message: string;
46
+ /**
47
+ * Path into the response `data` tree where the error occurred.
48
+ * Each element is a field name (string) or list index (number).
49
+ */
50
+ path?: (string | number)[];
51
+ /** Source locations in the document that triggered the error. */
52
+ locations?: {
53
+ line: number;
54
+ column: number;
55
+ }[];
56
+ /** Arbitrary extension data attached by the server. */
57
+ extensions?: Record<string, unknown>;
58
+ }
59
+ /**
60
+ * Raw response envelope returned by any spec-compliant GraphQL server.
61
+ * `data` is absent on a request-level failure; `errors` is absent on
62
+ * a fully successful response.
63
+ */
64
+ interface GraphQLResponse<TData = unknown> {
65
+ data?: TData;
66
+ errors?: GraphQLErrorDetail[];
67
+ extensions?: Record<string, unknown>;
68
+ }
69
+ /**
70
+ * Options for {@link BaseHttpClient.graphql}.
71
+ *
72
+ * @typeParam TVariables - Shape of the variables object. Defaults to
73
+ * `Record<string, unknown>`. Provide a specific type for compile-time
74
+ * variable checking.
75
+ */
76
+ interface GraphQLRequestOptions<TVariables extends Record<string, unknown> = Record<string, unknown>> {
77
+ /**
78
+ * The GraphQL query or mutation document string.
79
+ * @example `query GetUser($id: ID!) { user(id: $id) { name } }`
80
+ */
81
+ query: string;
82
+ /** Variables to substitute into the document. */
83
+ variables?: TVariables;
84
+ /**
85
+ * Name of the operation to execute when the document contains multiple
86
+ * named operations.
87
+ */
88
+ operationName?: string;
89
+ /**
90
+ * Additional headers merged on top of `ClientConfig.defaultHeaders` for
91
+ * this request only. `content-type: application/json` is always set.
92
+ */
93
+ headers?: Record<string, string>;
94
+ /**
95
+ * Per-request timeout override in milliseconds. Throws
96
+ * {@link TimeoutError} when exceeded.
97
+ */
98
+ timeoutMs?: number;
99
+ /**
100
+ * Explicit cache key for {@link createCachePlugin}. The cache plugin
101
+ * skips POST requests by default — provide this to opt a specific
102
+ * operation into caching.
103
+ * @example `"gql:GetUser:${userId}"`
104
+ */
105
+ cacheKey?: string;
106
+ /**
107
+ * Arbitrary string tags passed through to the `RequestContext`. Useful
108
+ * for metrics grouping or cache invalidation in custom plugins.
109
+ */
110
+ tags?: string[];
111
+ }
112
+ //#endregion
113
+ //#region src/context/ResponseContext.d.ts
114
+ /**
115
+ * Represents the result of an HTTP request as it flows through the
116
+ * `afterResponse` plugin chain.
117
+ *
118
+ * Plugins may return a mutated copy to transform `parsedBody` or attach
119
+ * state to `meta`. The final `parsedBody` value is what `client.request`
120
+ * returns to the caller.
121
+ */
122
+ interface ResponseContext {
123
+ /** The request context that produced this response. */
124
+ request: RequestContext;
125
+ /** The raw `Response` object returned by the transport. */
126
+ response: Response;
127
+ /**
128
+ * Body parsed from the response. JSON responses are parsed with
129
+ * `response.json()`; everything else is returned as a string via
130
+ * `response.text()`. Plugins may replace this with a transformed value.
131
+ */
132
+ parsedBody?: unknown;
133
+ /**
134
+ * Arbitrary key/value store for plugins to attach response-scoped state
135
+ * without polluting `parsedBody`. Keys should be namespaced by plugin
136
+ * name (e.g. `"cache.served"`, `"logger.durationMs"`).
137
+ */
138
+ meta: Record<string, unknown>;
139
+ }
140
+ //#endregion
141
+ //#region src/plugin/types.d.ts
142
+ interface ApiPlugin {
143
+ /** Unique display name for debugging. */
144
+ name: string;
145
+ /** Optional stable identifier, useful if names are duplicated. */
146
+ id?: string;
147
+ /**
148
+ * Execution order for beforeRequest (ascending) and afterResponse
149
+ * (descending). Defaults to 100. Plugins with equal priority run
150
+ * in registration order.
151
+ */
152
+ priority?: number;
153
+ /** When false the plugin is skipped entirely. Defaults to true. */
154
+ enabled?: boolean;
155
+ /** Called once when the client initializes. */
156
+ setup?(client: unknown): MaybePromise<void>;
157
+ /**
158
+ * Called before the transport executes. Return a mutated context
159
+ * or void to keep the existing one.
160
+ */
161
+ beforeRequest?(ctx: RequestContext): MaybePromise<RequestContext | void>;
162
+ /**
163
+ * Called after a successful transport response. Return a mutated
164
+ * context or void to keep the existing one.
165
+ */
166
+ afterResponse?(ctx: ResponseContext): MaybePromise<ResponseContext | void>;
167
+ /** Called when the request pipeline throws. */
168
+ onError?(error: unknown, ctx: RequestContext): MaybePromise<void>;
169
+ /** Called when the client is disposed. */
170
+ dispose?(): MaybePromise<void>;
171
+ }
172
+ //#endregion
173
+ //#region src/transport/types.d.ts
174
+ interface Transport {
175
+ execute(ctx: RequestContext): Promise<Response>;
176
+ }
177
+ //#endregion
178
+ //#region src/client/types.d.ts
179
+ /**
180
+ * Minimal logger interface accepted by {@link ClientConfig.logger} and
181
+ * {@link PluginManager}. Compatible with `console` out of the box.
182
+ */
183
+ interface LoggerInterface {
184
+ info(message: string, ...args: unknown[]): void;
185
+ warn(message: string, ...args: unknown[]): void;
186
+ error(message: string, ...args: unknown[]): void;
187
+ }
188
+ /**
189
+ * Retry behaviour applied to every request made by this client.
190
+ * Per-request overrides are possible via {@link createRetryPlugin}.
191
+ */
192
+ interface RetryConfig {
193
+ /**
194
+ * Maximum total attempts, including the first. A value of `1` means no
195
+ * retries (the default when `retry` is omitted from {@link ClientConfig}).
196
+ */
197
+ maxAttempts: number;
198
+ /** Base delay in ms between attempts before exponential backoff. Defaults to `500`. */
199
+ delayMs?: number;
200
+ /**
201
+ * When `true`, a random multiplier in `[0.5, 1)` is applied on top of
202
+ * exponential backoff so parallel clients don't all retry simultaneously.
203
+ * Defaults to `true`.
204
+ */
205
+ jitter?: boolean;
206
+ /**
207
+ * HTTP status codes that trigger a retry. `429` also reads the
208
+ * `retry-after` header. Defaults to `[429, 500, 502, 503, 504]`.
209
+ */
210
+ retriableStatusCodes?: number[];
211
+ }
212
+ /** Configuration passed to {@link BaseHttpClient} or {@link createClient}. */
213
+ interface ClientConfig {
214
+ /**
215
+ * Base URL prepended to every `path` argument. No trailing slash;
216
+ * paths should start with `/`.
217
+ * @example "https://api.example.com/v1"
218
+ */
219
+ baseUrl: string;
220
+ /**
221
+ * Headers merged into every request. Per-request `headers` take
222
+ * precedence. `content-type: application/json` is always present as the
223
+ * lowest-priority default.
224
+ */
225
+ defaultHeaders?: Record<string, string>;
226
+ /** Plugins registered for the lifetime of this client. */
227
+ plugins?: ApiPlugin[];
228
+ /**
229
+ * Transport implementation for executing requests. Defaults to
230
+ * {@link fetchTransport}. Swap in tests to avoid real network calls.
231
+ * When both `transport` and `fetch` are provided, `transport` wins.
232
+ */
233
+ transport?: Transport;
234
+ /**
235
+ * Custom `fetch` implementation used by the default {@link fetchTransport}.
236
+ * Useful for polyfills or interceptors (e.g. `node-fetch`, `undici`).
237
+ * Ignored when a custom `transport` is provided.
238
+ * @example `import fetch from "node-fetch"; createClient({ fetch })`
239
+ */
240
+ fetch?: typeof globalThis.fetch;
241
+ /**
242
+ * Default request timeout in ms. Overridable per-request via
243
+ * `RequestOptions.timeoutMs`. Throws {@link TimeoutError} when exceeded.
244
+ */
245
+ timeoutMs?: number;
246
+ /**
247
+ * Global retry policy. Omitting means no retries (`maxAttempts: 1`).
248
+ * Per-request overrides via {@link createRetryPlugin}.
249
+ */
250
+ retry?: RetryConfig;
251
+ /**
252
+ * Logger used for internal diagnostics (e.g. plugin `onError` handler
253
+ * failures). Defaults to `console`. Pass a no-op logger to silence all
254
+ * internal output; pass a structured logger for production observability.
255
+ * @example `{ info: () => {}, warn: () => {}, error: () => {} }`
256
+ */
257
+ logger?: LoggerInterface;
258
+ }
259
+ //#endregion
260
+ //#region src/plugin/PluginManager.d.ts
261
+ declare class PluginManager {
262
+ private readonly plugins;
263
+ private readonly logger;
264
+ /**
265
+ * @param logger - Logger used when an `onError` handler itself throws.
266
+ * Defaults to `console`. Pass a no-op object to silence all output.
267
+ */
268
+ constructor(logger?: LoggerInterface);
269
+ register(plugin: ApiPlugin): void;
270
+ getAll(): readonly ApiPlugin[];
271
+ setup(client: unknown): Promise<void>;
272
+ /**
273
+ * Runs `beforeRequest` in ascending priority order (lowest first).
274
+ * Each plugin may return a mutated context.
275
+ */
276
+ beforeRequest(ctx: RequestContext): Promise<RequestContext>;
277
+ /**
278
+ * Runs `afterResponse` in descending priority order (highest first).
279
+ * Each plugin may return a mutated context.
280
+ */
281
+ afterResponse(ctx: ResponseContext): Promise<ResponseContext>;
282
+ /**
283
+ * Runs `onError` on all plugins in registration order. A plugin throwing
284
+ * here is caught and logged via the configured logger but does not
285
+ * interrupt other `onError` handlers.
286
+ */
287
+ onError(error: unknown, ctx: RequestContext): Promise<void>;
288
+ dispose(): Promise<void>;
289
+ }
290
+ //#endregion
291
+ //#region src/client/BaseHttpClient.d.ts
292
+ /** Per-request options passed to {@link BaseHttpClient.request} and the convenience methods. */
293
+ interface RequestOptions {
294
+ /** HTTP method. Defaults to `"GET"`. */
295
+ method?: HttpMethod;
296
+ /**
297
+ * Additional headers merged on top of `ClientConfig.defaultHeaders`.
298
+ * These take precedence; `content-type: application/json` is always
299
+ * present and is the lowest-priority default.
300
+ */
301
+ headers?: Record<string, string>;
302
+ /** Request body. Serialised to JSON by {@link fetchTransport}. Ignored for GET and HEAD. */
303
+ body?: unknown;
304
+ /**
305
+ * Query string parameters appended to the URL. `undefined` values are
306
+ * omitted. Numbers and booleans are coerced to strings. Array values are
307
+ * emitted as repeated query parameters.
308
+ */
309
+ query?: QueryParams;
310
+ /** Optional caller-provided abort signal. Composes with `timeoutMs`. */
311
+ signal?: AbortSignal;
312
+ /**
313
+ * Per-request timeout override in milliseconds. Takes precedence over
314
+ * `ClientConfig.timeoutMs`. Throws {@link TimeoutError} when exceeded.
315
+ */
316
+ timeoutMs?: number;
317
+ /**
318
+ * Explicit cache key used by {@link createCachePlugin}. When omitted the
319
+ * plugin derives a key from the method, URL, and query string.
320
+ */
321
+ cacheKey?: string;
322
+ /**
323
+ * Arbitrary string tags attached to the request context. Plugins may use
324
+ * these for cache invalidation, metrics grouping, or filtering.
325
+ */
326
+ tags?: string[];
327
+ }
328
+ interface ApiResponse<T = unknown> {
329
+ data: T;
330
+ response: Response;
331
+ request: RequestContext;
332
+ meta: Record<string, unknown>;
333
+ }
334
+ /**
335
+ * Core HTTP client. Manages the plugin lifecycle, retry loop, and transport
336
+ * dispatch for all requests.
337
+ *
338
+ * Plugins are initialised lazily on the first call to {@link request} (or any
339
+ * convenience method). Call {@link dispose} when the client is no longer
340
+ * needed so plugins can release timers, connections, or cache handles.
341
+ *
342
+ * Extend this class to add domain-specific methods while keeping the plugin
343
+ * and transport infrastructure intact.
344
+ *
345
+ * @example
346
+ * ```ts
347
+ * // Prefer createClient() in application code:
348
+ * const client = createClient({ baseUrl: "https://api.example.com/v1" });
349
+ *
350
+ * // Or subclass for wrapper packages:
351
+ * class MyApiClient extends BaseHttpClient {
352
+ * getUser(id: string) { return this.get<User>(`/users/${id}`); }
353
+ * }
354
+ * ```
355
+ */
356
+ declare class BaseHttpClient {
357
+ protected readonly config: ClientConfig;
358
+ protected readonly pluginManager: PluginManager;
359
+ private initialized;
360
+ private initPromise;
361
+ constructor(config: ClientConfig);
362
+ /** Initializes all plugins. Called lazily on first request. */
363
+ init(): Promise<void>;
364
+ /** Disposes all plugins. Call when the client is no longer needed. */
365
+ dispose(): Promise<void>;
366
+ /**
367
+ * Executes an HTTP request through the full plugin pipeline.
368
+ *
369
+ * Lifecycle per attempt:
370
+ * 1. Build `RequestContext` with merged headers, query, and retry state.
371
+ * 2. Run `beforeRequest` hooks (ascending priority). A plugin may set
372
+ * `ctx.syntheticResponse` to skip the transport entirely (e.g. cache hit).
373
+ * 3. Merge any `retry.*` meta written by {@link createRetryPlugin}.
374
+ * 4. Call transport (skipped when `syntheticResponse` is set).
375
+ * 5. Parse the response body (JSON or text).
376
+ * 6. Run `afterResponse` hooks (descending priority).
377
+ * 7. Retry on retriable status codes; throw on terminal failures.
378
+ *
379
+ * @param path - Path appended to `ClientConfig.baseUrl`. Should start with `/`.
380
+ * @param options - Per-request overrides for method, headers, body, query, etc.
381
+ * @returns The parsed response body cast to `T`.
382
+ * @throws {@link ApiError} for non-2xx responses.
383
+ * @throws {@link RateLimitError} for 429 responses.
384
+ * @throws {@link TimeoutError} when `timeoutMs` is exceeded.
385
+ */
386
+ request<T = unknown>(path: string, options?: RequestOptions): Promise<T>;
387
+ /**
388
+ * Executes a request and returns the parsed body plus the final response
389
+ * context. Use this in wrappers that need response headers, status, or
390
+ * plugin metadata while keeping the same error/retry behaviour as
391
+ * {@link request}.
392
+ */
393
+ requestWithResponse<T = unknown>(path: string, options?: RequestOptions): Promise<ApiResponse<T>>;
394
+ /** Sends a GET request. The response body is not cached unless a cache plugin is registered. */
395
+ get<T = unknown>(path: string, options?: Omit<RequestOptions, "method">): Promise<T>;
396
+ post<T = unknown>(path: string, body?: unknown, options?: Omit<RequestOptions, "method" | "body">): Promise<T>;
397
+ put<T = unknown>(path: string, body?: unknown, options?: Omit<RequestOptions, "method" | "body">): Promise<T>;
398
+ patch<T = unknown>(path: string, body?: unknown, options?: Omit<RequestOptions, "method" | "body">): Promise<T>;
399
+ delete<T = unknown>(path: string, options?: Omit<RequestOptions, "method">): Promise<T>;
400
+ head<T = unknown>(path: string, options?: Omit<RequestOptions, "method">): Promise<T>;
401
+ options<T = unknown>(path: string, options?: Omit<RequestOptions, "method">): Promise<T>;
402
+ /**
403
+ * Executes a GraphQL query or mutation against a single endpoint path.
404
+ *
405
+ * The request is a `POST` with `content-type: application/json` carrying
406
+ * `{ query, variables?, operationName? }` as the body. It flows through
407
+ * the full plugin lifecycle (beforeRequest → transport → afterResponse →
408
+ * onError) and respects all retry configuration, exactly like REST calls.
409
+ *
410
+ * **Error handling:**
411
+ * - HTTP-level failures (429, 500, timeout) throw the same error classes
412
+ * as REST requests (`RateLimitError`, `ApiError`, `TimeoutError`).
413
+ * - A successful HTTP 200 that contains a non-empty `errors` array throws
414
+ * {@link GraphQLRequestError}, which extends `ApiError`.
415
+ *
416
+ * **Caching:**
417
+ * The cache plugin skips `POST` requests by default. Pass an explicit
418
+ * `cacheKey` in options to opt a specific operation into caching.
419
+ *
420
+ * @typeParam TData - Shape of the `data` field in the GraphQL response.
421
+ * @typeParam TVariables - Shape of the `variables` object. Defaults to
422
+ * `Record<string, unknown>`.
423
+ * @param path - Endpoint path, e.g. `"/graphql"`. Appended to `baseUrl`.
424
+ * @param options - Query document, variables, and optional per-request overrides.
425
+ * @returns The `data` field from the GraphQL response envelope.
426
+ * @throws {@link GraphQLRequestError} when `response.errors` is non-empty.
427
+ * @throws {@link ApiError} / {@link RateLimitError} / {@link TimeoutError} on
428
+ * HTTP-level failures.
429
+ *
430
+ * @example
431
+ * ```ts
432
+ * const data = await client.graphql<GetUserQuery, GetUserQueryVariables>(
433
+ * "/graphql",
434
+ * { query: GET_USER, variables: { id: "123" } },
435
+ * );
436
+ * ```
437
+ */
438
+ graphql<TData = unknown, TVariables extends Record<string, unknown> = Record<string, unknown>>(path: string, options: GraphQLRequestOptions<TVariables>): Promise<TData>;
439
+ private waitForRetry;
440
+ }
441
+ //#endregion
442
+ //#region src/client/createClient.d.ts
443
+ /**
444
+ * Factory function that creates a {@link BaseHttpClient} from the given
445
+ * config. Prefer this over `new BaseHttpClient(config)` in application code
446
+ * so that the concrete class stays an implementation detail.
447
+ *
448
+ * @example
449
+ * ```ts
450
+ * const client = createClient({
451
+ * baseUrl: "https://api.example.com/v1",
452
+ * defaultHeaders: { "x-api-key": "secret" },
453
+ * retry: { maxAttempts: 3, delayMs: 300 },
454
+ * plugins: [createLoggerPlugin(), createCachePlugin({ ttlMs: 60_000 })],
455
+ * });
456
+ * ```
457
+ */
458
+ declare function createClient(config: ClientConfig): BaseHttpClient;
459
+ //#endregion
460
+ //#region src/errors/ApiError.d.ts
461
+ declare class ApiError extends Error {
462
+ readonly status: number;
463
+ readonly responseBody: unknown;
464
+ readonly cause: unknown;
465
+ constructor(message: string, status: number, responseBody?: unknown, cause?: unknown);
466
+ }
467
+ //#endregion
468
+ //#region src/errors/RateLimitError.d.ts
469
+ declare class RateLimitError extends ApiError {
470
+ readonly retryAfterMs: number | undefined;
471
+ constructor(retryAfterMs?: number, responseBody?: unknown, cause?: unknown);
472
+ }
473
+ //#endregion
474
+ //#region src/errors/TimeoutError.d.ts
475
+ declare class TimeoutError extends Error {
476
+ readonly cause: unknown;
477
+ constructor(message?: string, cause?: unknown);
478
+ }
479
+ //#endregion
480
+ //#region src/plugins/auth/types.d.ts
481
+ interface AuthPluginOptions {
482
+ /**
483
+ * Returns the token to attach to each request. Called per request so
484
+ * wrappers can refresh credentials without rebuilding the client.
485
+ */
486
+ getToken: () => MaybePromise<string | null | undefined>;
487
+ /** Header name to set. Defaults to `authorization`. */
488
+ headerName?: string;
489
+ /**
490
+ * Token scheme prefix. Defaults to `Bearer`. Pass `null` to write the raw
491
+ * token value without a scheme.
492
+ */
493
+ scheme?: string | null;
494
+ }
495
+ //#endregion
496
+ //#region src/plugins/auth/authPlugin.d.ts
497
+ type TokenInput = string | (() => MaybePromise<string | null | undefined>) | AuthPluginOptions;
498
+ /**
499
+ * Adds an auth token header before each request. The token can be static or
500
+ * loaded asynchronously per request, which covers wrappers with refreshable
501
+ * access tokens.
502
+ */
503
+ declare function createAuthPlugin(input: TokenInput): ApiPlugin;
504
+ //#endregion
505
+ //#region src/plugins/cache/types.d.ts
506
+ interface CacheStore {
507
+ get(key: string): MaybePromise<unknown | undefined>;
508
+ set(key: string, value: unknown, ttlMs?: number): MaybePromise<void>;
509
+ delete(key: string): MaybePromise<void>;
510
+ clear(): MaybePromise<void>;
511
+ }
512
+ interface CachePluginOptions {
513
+ store?: CacheStore;
514
+ ttlMs?: number;
515
+ methods?: HttpMethod[];
516
+ generateKey?: (ctx: RequestContext) => string;
517
+ }
518
+ /**
519
+ * The object returned by {@link createCachePlugin}. Extends {@link ApiPlugin}
520
+ * with first-class cache invalidation methods.
521
+ */
522
+ interface CachePlugin extends ApiPlugin {
523
+ /**
524
+ * Removes a single entry from the cache by its exact key.
525
+ * The key is either the auto-generated `"METHOD:url?query"` string or the
526
+ * explicit `cacheKey` passed in `RequestOptions`.
527
+ */
528
+ invalidate(key: string): Promise<void>;
529
+ /**
530
+ * Removes all cache entries that were stored with the given tag.
531
+ * Tags are attached to requests via `RequestOptions.tags`. Only entries
532
+ * cached after this plugin was registered will have tag associations.
533
+ */
534
+ invalidateByTag(tag: string): Promise<void>;
535
+ }
536
+ //#endregion
537
+ //#region src/plugins/cache/cachePlugin.d.ts
538
+ declare function createCachePlugin(options?: CachePluginOptions): CachePlugin;
539
+ //#endregion
540
+ //#region src/plugins/cache/memoryStore.d.ts
541
+ declare class MemoryStore implements CacheStore {
542
+ private readonly store;
543
+ get(key: string): unknown | undefined;
544
+ set(key: string, value: unknown, ttlMs?: number): void;
545
+ delete(key: string): void;
546
+ clear(): void;
547
+ }
548
+ //#endregion
549
+ //#region src/plugins/logger/types.d.ts
550
+ interface LoggerInterface$1 {
551
+ info(message: string, data?: unknown): void;
552
+ warn?(message: string, data?: unknown): void;
553
+ error(message: string, data?: unknown): void;
554
+ }
555
+ interface LoggerPluginOptions {
556
+ logRequest?: boolean;
557
+ logResponse?: boolean;
558
+ logError?: boolean;
559
+ logger?: LoggerInterface$1;
560
+ }
561
+ //#endregion
562
+ //#region src/plugins/logger/loggerPlugin.d.ts
563
+ /**
564
+ * Creates a plugin that logs request start, response status, and errors.
565
+ *
566
+ * Log lines are prefixed with `[api-core]` and include the HTTP method, URL,
567
+ * attempt number (on `beforeRequest`), and status code (on `afterResponse`).
568
+ *
569
+ * Priority `10` means it runs _after_ auth or header-mutation plugins
570
+ * (priority < 10) so the logged URL and headers reflect the final request,
571
+ * but _before_ the cache plugin (priority `20`) so cache hits are still
572
+ * visible in the log.
573
+ *
574
+ * @example
575
+ * ```ts
576
+ * createClient({
577
+ * baseUrl: "https://api.example.com",
578
+ * plugins: [createLoggerPlugin({ logRequest: true, logResponse: true })],
579
+ * });
580
+ * ```
581
+ */
582
+ declare function createLoggerPlugin(options?: LoggerPluginOptions): ApiPlugin;
583
+ //#endregion
584
+ //#region src/plugins/rateLimit/types.d.ts
585
+ interface RateLimitPluginOptions {
586
+ /**
587
+ * Maximum number of requests allowed to run at the same time.
588
+ * Defaults to `Infinity`.
589
+ */
590
+ maxConcurrent?: number;
591
+ /**
592
+ * Minimum delay between request starts. Defaults to `0`.
593
+ */
594
+ minTimeMs?: number;
595
+ /**
596
+ * Maximum number of request starts allowed during `intervalMs`.
597
+ * Both fields must be provided to enable windowed limiting.
598
+ */
599
+ maxRequestsPerInterval?: number;
600
+ intervalMs?: number;
601
+ }
602
+ //#endregion
603
+ //#region src/plugins/rateLimit/rateLimitPlugin.d.ts
604
+ /**
605
+ * Throttles request starts before they reach the transport. Supports
606
+ * concurrency, minimum spacing, and fixed-window request budgets.
607
+ */
608
+ declare function createRateLimitPlugin(options?: RateLimitPluginOptions): ApiPlugin;
609
+ //#endregion
610
+ //#region src/plugins/retry/types.d.ts
611
+ interface RetryPluginOptions {
612
+ maxAttempts?: number;
613
+ delayMs?: number;
614
+ jitter?: boolean;
615
+ retriableStatusCodes?: number[];
616
+ }
617
+ //#endregion
618
+ //#region src/plugins/retry/retryPlugin.d.ts
619
+ /**
620
+ * Writes retry configuration into request context meta so the
621
+ * BaseHttpClient retry loop can read it. Use this when you need
622
+ * per-request retry overrides rather than global ClientConfig.retry.
623
+ */
624
+ declare function createRetryPlugin(options?: RetryPluginOptions): ApiPlugin;
625
+ //#endregion
626
+ //#region src/plugins/timeout/types.d.ts
627
+ interface TimeoutPluginOptions {
628
+ /**
629
+ * Request timeout in milliseconds. Overrides `ClientConfig.timeoutMs` and
630
+ * any per-request `timeoutMs` set before this plugin runs.
631
+ * The abort and {@link TimeoutError} are handled by the transport.
632
+ */
633
+ timeoutMs: number;
634
+ }
635
+ //#endregion
636
+ //#region src/plugins/timeout/timeoutPlugin.d.ts
637
+ /**
638
+ * Sets `ctx.timeoutMs` on every request so all requests made by this client
639
+ * abort after the configured duration. The actual abort and
640
+ * {@link TimeoutError} are handled by {@link fetchTransport}.
641
+ *
642
+ * Priority `1` ensures the timeout is stamped before any other plugin (e.g.
643
+ * logger, cache) runs — plugins that read `ctx.timeoutMs` will always see it.
644
+ * Use a `beforeRequest` hook with a lower priority to override per-request.
645
+ *
646
+ * Prefer `ClientConfig.timeoutMs` for a static global timeout. Use this
647
+ * plugin when you need to set or change the timeout through the plugin
648
+ * pipeline (e.g. from environment config loaded asynchronously in `setup`).
649
+ *
650
+ * @example
651
+ * ```ts
652
+ * createClient({
653
+ * baseUrl: "https://api.example.com",
654
+ * plugins: [createTimeoutPlugin({ timeoutMs: 5_000 })],
655
+ * });
656
+ * ```
657
+ */
658
+ declare function createTimeoutPlugin(options: TimeoutPluginOptions): ApiPlugin;
659
+ //#endregion
660
+ //#region src/graphql/GraphQLRequestError.d.ts
661
+ /**
662
+ * Thrown when a GraphQL server returns a well-formed HTTP 200 response that
663
+ * contains a non-empty `errors` array.
664
+ *
665
+ * Extends {@link ApiError} so that code catching `ApiError` also catches
666
+ * GraphQL-level failures. Callers that need to inspect the individual error
667
+ * objects can narrow with `instanceof GraphQLRequestError` and read
668
+ * `graphqlErrors`.
669
+ *
670
+ * When the server returns both `data` and `errors` (partial result), the
671
+ * partial data is available on `partialData` but the error is still thrown —
672
+ * callers must explicitly opt in to consuming partial results.
673
+ *
674
+ * @example
675
+ * ```ts
676
+ * import { GraphQLRequestError } from "@api-wrappers/api-core";
677
+ *
678
+ * try {
679
+ * const data = await client.graphql<MyQuery>("/graphql", { query: QUERY });
680
+ * } catch (err) {
681
+ * if (err instanceof GraphQLRequestError) {
682
+ * for (const e of err.graphqlErrors) {
683
+ * console.error(e.message, e.path);
684
+ * }
685
+ * }
686
+ * }
687
+ * ```
688
+ */
689
+ declare class GraphQLRequestError extends ApiError {
690
+ /** The errors array from the GraphQL response envelope. */
691
+ readonly graphqlErrors: readonly GraphQLErrorDetail[];
692
+ /**
693
+ * Partial `data` returned alongside `errors`, if any. `undefined` when
694
+ * the server returned no `data` field.
695
+ */
696
+ readonly partialData: unknown;
697
+ constructor(errors: GraphQLErrorDetail[], partialData?: unknown, cause?: unknown);
698
+ }
699
+ //#endregion
700
+ //#region src/transport/fetchTransport.d.ts
701
+ /**
702
+ * Creates a {@link Transport} backed by the provided `fetch` function.
703
+ * Use this when you need a polyfill or a custom fetch interceptor:
704
+ *
705
+ * ```ts
706
+ * import nodeFetch from "node-fetch";
707
+ * createClient({ fetch: nodeFetch as typeof globalThis.fetch });
708
+ * // — or set it directly on the transport:
709
+ * const transport = createFetchTransport(nodeFetch as typeof globalThis.fetch);
710
+ * ```
711
+ */
712
+ declare function createFetchTransport(fetchFn?: typeof globalThis.fetch): Transport;
713
+ /**
714
+ * Default {@link Transport} backed by the global `fetch` API.
715
+ *
716
+ * Behaviour:
717
+ * - Builds the final URL from `ctx.url` + `ctx.query` via {@link buildUrl}.
718
+ * - Serialises `ctx.body` to JSON for non-GET/HEAD requests.
719
+ * - Wires an `AbortController` when `ctx.timeoutMs` is set; throws
720
+ * {@link TimeoutError} on abort.
721
+ *
722
+ * Replace this with a custom {@link Transport} in tests, or provide a custom
723
+ * `fetch` function via {@link ClientConfig.fetch}.
724
+ */
725
+ declare const fetchTransport: Transport;
726
+ //#endregion
727
+ //#region src/utils/buildUrl.d.ts
728
+ /**
729
+ * Appends a query string to a URL. Skips nullish values and repeats keys for
730
+ * array values so APIs like TMDB can accept `with_genres=1&with_genres=2`.
731
+ */
732
+ declare function buildUrl(base: string, query?: QueryParams): string;
733
+ //#endregion
734
+ //#region src/utils/isPlainObject.d.ts
735
+ declare function isPlainObject(value: unknown): value is Record<string, unknown>;
736
+ //#endregion
737
+ //#region src/utils/mergeHeaders.d.ts
738
+ /**
739
+ * Merges header objects left to right. Keys are normalized to
740
+ * lowercase so merging is case-insensitive. Later sources win.
741
+ */
742
+ declare function mergeHeaders(...sources: (Record<string, string> | undefined)[]): Record<string, string>;
743
+ //#endregion
744
+ //#region src/utils/resolveUrl.d.ts
745
+ /**
746
+ * Joins a client base URL and request path without requiring callers to keep
747
+ * slashes perfectly aligned. Absolute request URLs are returned unchanged.
748
+ */
749
+ declare function resolveUrl(baseUrl: string, path: string): string;
750
+ //#endregion
751
+ //#region src/utils/sleep.d.ts
752
+ declare function sleep(ms: number): Promise<void>;
753
+ //#endregion
754
+ export { ApiError, type ApiPlugin, type ApiResponse, type AuthPluginOptions, BaseHttpClient, type CachePlugin, type CachePluginOptions, type CacheStore, type ClientConfig, type GraphQLErrorDetail, GraphQLRequestError, type GraphQLRequestOptions, type GraphQLResponse, type HttpMethod, type LoggerInterface, type LoggerPluginOptions, type MaybePromise, MemoryStore, PluginManager, type QueryParams, type QueryPrimitive, type QueryValue, RateLimitError, type RateLimitPluginOptions, type RequestContext, type RequestOptions, type ResponseContext, type RetryConfig, type RetryPluginOptions, TimeoutError, type TimeoutPluginOptions, type Transport, buildUrl, createAuthPlugin, createCachePlugin, createClient, createFetchTransport, createLoggerPlugin, createRateLimitPlugin, createRetryPlugin, createTimeoutPlugin, fetchTransport, isPlainObject, mergeHeaders, resolveUrl, sleep };
755
+ //# sourceMappingURL=index.d.mts.map