@routar/core 1.2.1 → 1.4.0
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.
- package/dist/index.cjs +168 -106
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +117 -134
- package/dist/index.d.ts +117 -134
- package/dist/index.js +167 -103
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.cts
CHANGED
|
@@ -6,7 +6,7 @@ interface ExecuteOptions {
|
|
|
6
6
|
params?: Record<string, unknown>;
|
|
7
7
|
body?: unknown;
|
|
8
8
|
/**
|
|
9
|
-
* Per-request headers injected by
|
|
9
|
+
* Per-request headers injected by a plugin's `onRequest` hook.
|
|
10
10
|
* Headers cannot be set from `createApi` call sites directly — use middleware
|
|
11
11
|
* to add dynamic headers such as `Authorization` or `X-Request-Id`.
|
|
12
12
|
*/
|
|
@@ -22,21 +22,51 @@ interface Executor {
|
|
|
22
22
|
execute(options: ExecuteOptions): Promise<unknown>;
|
|
23
23
|
}
|
|
24
24
|
/**
|
|
25
|
-
*
|
|
25
|
+
* A named, composable unit of executor behavior.
|
|
26
26
|
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
27
|
+
* Each lifecycle hook is optional — implement only what you need.
|
|
28
|
+
* Related concerns (e.g. auth header injection + 401 refresh) can be
|
|
29
|
+
* bundled into a single plugin.
|
|
30
30
|
*
|
|
31
|
-
* @example
|
|
31
|
+
* @example Auth plugin
|
|
32
32
|
* ```ts
|
|
33
|
-
* const
|
|
34
|
-
*
|
|
35
|
-
*
|
|
33
|
+
* const authPlugin: ExecutorPlugin = {
|
|
34
|
+
* name: 'auth',
|
|
35
|
+
* onRequest: async (opts) => ({
|
|
36
|
+
* ...opts,
|
|
37
|
+
* headers: { ...opts.headers, Authorization: `Bearer ${await getToken()}` },
|
|
38
|
+
* }),
|
|
39
|
+
* onError: async (err) => {
|
|
40
|
+
* if (isUnauthorized(err)) await refreshToken();
|
|
41
|
+
* throw err;
|
|
42
|
+
* },
|
|
36
43
|
* };
|
|
37
44
|
* ```
|
|
38
45
|
*/
|
|
39
|
-
|
|
46
|
+
interface ExecutorPlugin {
|
|
47
|
+
/** Optional name — used for introspection and `eject`. */
|
|
48
|
+
name?: string;
|
|
49
|
+
/** Runs before the request is sent. Return modified opts to transform the request. */
|
|
50
|
+
onRequest?: (opts: ExecuteOptions) => ExecuteOptions | Promise<ExecuteOptions>;
|
|
51
|
+
/** Runs after a successful response. Return a modified value to transform the response. */
|
|
52
|
+
onResponse?: (response: unknown, opts: ExecuteOptions) => unknown | Promise<unknown>;
|
|
53
|
+
/** Runs when the request throws. Must re-throw (or throw a different error). */
|
|
54
|
+
onError?: (error: unknown, opts: ExecuteOptions) => never | Promise<never>;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Options for {@link createExecutor}.
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* ```ts
|
|
61
|
+
* const executor = createExecutor(transport, {
|
|
62
|
+
* plugins: [authPlugin, logger()],
|
|
63
|
+
* });
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
interface CreateExecutorOptions {
|
|
67
|
+
/** Plugins applied in declaration order (first plugin is outermost). */
|
|
68
|
+
plugins?: ExecutorPlugin[];
|
|
69
|
+
}
|
|
40
70
|
/**
|
|
41
71
|
* Any object with a `parse` method — compatible with Zod, Valibot, Yup, etc.
|
|
42
72
|
*
|
|
@@ -116,7 +146,7 @@ interface RouterDef<TEndpoints extends RouterEndpoints = RouterEndpoints> {
|
|
|
116
146
|
* ```
|
|
117
147
|
*/
|
|
118
148
|
type ApiTypes<TApi> = {
|
|
119
|
-
[K in keyof TApi]: TApi[K] extends (...args: any[]) => Promise<infer R> ? {
|
|
149
|
+
[K in keyof TApi as K extends "$router" ? never : K]: TApi[K] extends (...args: any[]) => Promise<infer R> ? {
|
|
120
150
|
request: Parameters<TApi[K]>[0];
|
|
121
151
|
response: R;
|
|
122
152
|
} : TApi[K] extends object ? ApiTypes<TApi[K]> : never;
|
|
@@ -158,6 +188,17 @@ type EndpointFn<TSpec extends EndpointSpec<any, any, any>> = TSpec["request"] ex
|
|
|
158
188
|
type ApiClient<TEndpoints extends RouterEndpoints> = {
|
|
159
189
|
[K in keyof TEndpoints]: TEndpoints[K] extends RouterDef<infer TNestedEndpoints> ? ApiClient<TNestedEndpoints> : TEndpoints[K] extends EndpointSpec<any, any, any> ? EndpointFn<TEndpoints[K]> : never;
|
|
160
190
|
};
|
|
191
|
+
/**
|
|
192
|
+
* An {@link ApiClient} that also carries its source {@link RouterDef} on the
|
|
193
|
+
* `$router` property. This is the actual return type of {@link createApi};
|
|
194
|
+
* downstream tools (e.g. `@routar/react-query`) recover the router (prefix +
|
|
195
|
+
* endpoint methods) from it without it being re-passed. `$router` is
|
|
196
|
+
* non-enumerable and excluded from {@link ApiTypes}; the `$` prefix keeps it
|
|
197
|
+
* from colliding with endpoint names.
|
|
198
|
+
*/
|
|
199
|
+
type ApiClientWithRouter<TEndpoints extends RouterEndpoints> = ApiClient<TEndpoints> & {
|
|
200
|
+
readonly $router: RouterDef<TEndpoints>;
|
|
201
|
+
};
|
|
161
202
|
/**
|
|
162
203
|
* Builds a fully-typed API client from an {@link Executor} and a router
|
|
163
204
|
* (or bare endpoint map).
|
|
@@ -213,71 +254,59 @@ type ApiClient<TEndpoints extends RouterEndpoints> = {
|
|
|
213
254
|
* });
|
|
214
255
|
* ```
|
|
215
256
|
*/
|
|
216
|
-
declare function createApi<TEndpoints extends RouterEndpoints>(executor: Executor, router: RouterDef<TEndpoints>, options?: CreateApiOptions):
|
|
257
|
+
declare function createApi<TEndpoints extends RouterEndpoints>(executor: Executor, router: RouterDef<TEndpoints>, options?: CreateApiOptions): ApiClientWithRouter<TEndpoints>;
|
|
217
258
|
/**
|
|
218
259
|
* @param executor - Transport to use for every HTTP call.
|
|
219
260
|
* @param prefix - URL prefix prepended to every endpoint path.
|
|
220
261
|
* @param endpoints - Record of named endpoint specs.
|
|
221
262
|
* @param options - Optional settings.
|
|
222
263
|
*/
|
|
223
|
-
declare function createApi<TEndpoints extends RouterEndpoints>(executor: Executor, prefix: string, endpoints: TEndpoints, options?: CreateApiOptions):
|
|
264
|
+
declare function createApi<TEndpoints extends RouterEndpoints>(executor: Executor, prefix: string, endpoints: TEndpoints, options?: CreateApiOptions): ApiClientWithRouter<TEndpoints>;
|
|
224
265
|
/**
|
|
225
266
|
* @param executor - Transport to use for every HTTP call.
|
|
226
267
|
* @param endpoints - Record of named endpoint specs (no URL prefix).
|
|
227
268
|
* @param options - Optional settings.
|
|
228
269
|
*/
|
|
229
|
-
declare function createApi<TEndpoints extends RouterEndpoints>(executor: Executor, endpoints: TEndpoints, options?: CreateApiOptions):
|
|
270
|
+
declare function createApi<TEndpoints extends RouterEndpoints>(executor: Executor, endpoints: TEndpoints, options?: CreateApiOptions): ApiClientWithRouter<TEndpoints>;
|
|
230
271
|
|
|
231
272
|
/**
|
|
232
|
-
* Creates an {@link Executor} by wrapping a transport function with
|
|
233
|
-
* optional middleware chain.
|
|
273
|
+
* Creates an {@link Executor} by wrapping a transport function with plugins.
|
|
234
274
|
*
|
|
235
|
-
*
|
|
236
|
-
* outermost wrapper and runs first on each request.
|
|
275
|
+
* Plugins run in declaration order (first plugin is outermost).
|
|
237
276
|
*
|
|
238
|
-
*
|
|
239
|
-
*
|
|
277
|
+
* For `retry` and `timeout`, use the options on {@link createFetchExecutor}
|
|
278
|
+
* or configure them via the underlying HTTP client (axios, ky).
|
|
240
279
|
*
|
|
241
280
|
* @example
|
|
242
281
|
* ```ts
|
|
243
|
-
* const executor = createExecutor(
|
|
244
|
-
*
|
|
245
|
-
*
|
|
246
|
-
* return res.json();
|
|
247
|
-
* },
|
|
248
|
-
* [withTimeout(5000), withRetry(3), withLogger()],
|
|
249
|
-
* );
|
|
282
|
+
* const executor = createExecutor(transport, {
|
|
283
|
+
* plugins: [authPlugin, logger()],
|
|
284
|
+
* });
|
|
250
285
|
* ```
|
|
251
286
|
*/
|
|
252
|
-
declare function createExecutor(execute: (options: ExecuteOptions) => Promise<unknown>,
|
|
287
|
+
declare function createExecutor(execute: (options: ExecuteOptions) => Promise<unknown>, options?: CreateExecutorOptions): Executor;
|
|
253
288
|
/**
|
|
254
289
|
* Creates an {@link Executor} that selects the underlying transport at
|
|
255
290
|
* request time based on the result of `resolver`.
|
|
256
291
|
*
|
|
257
|
-
* Use this to unify SSR and CSR behind a single API client — the resolver
|
|
258
|
-
* picks the right executor per request, so `createApi` is called once and
|
|
259
|
-
* works in both environments without duplicate `*ServerApi` instances.
|
|
260
|
-
*
|
|
261
|
-
* The resolver receives the full {@link ExecuteOptions} so it can branch on
|
|
262
|
-
* environment, URL prefix, auth context, or any runtime condition.
|
|
263
|
-
*
|
|
264
|
-
* @param resolver - Called on every request; returns the executor to delegate to.
|
|
265
|
-
*
|
|
266
292
|
* @example
|
|
267
293
|
* ```ts
|
|
268
|
-
* // SSR vs CSR — pick transport based on environment
|
|
269
294
|
* const apiExecutor = dispatchExecutor(() =>
|
|
270
295
|
* typeof window === 'undefined' ? serverExecutor : clientExecutor,
|
|
271
296
|
* );
|
|
272
|
-
*
|
|
273
|
-
* // Route by URL prefix — internal routes use a different transport
|
|
274
|
-
* const apiExecutor = dispatchExecutor((opts) =>
|
|
275
|
-
* opts.url.startsWith('/internal') ? internalExecutor : publicExecutor,
|
|
276
|
-
* );
|
|
277
297
|
* ```
|
|
278
298
|
*/
|
|
279
299
|
declare function dispatchExecutor(resolver: (opts: ExecuteOptions) => Executor): Executor;
|
|
280
300
|
|
|
301
|
+
type FetchRetryOption = number | {
|
|
302
|
+
count: number;
|
|
303
|
+
shouldRetry?: (error: unknown, attempt: number) => boolean;
|
|
304
|
+
};
|
|
305
|
+
interface FetchExecutorOptions extends CreateExecutorOptions {
|
|
306
|
+
defaultHeaders?: () => Record<string, string> | Promise<Record<string, string>>;
|
|
307
|
+
retry?: FetchRetryOption;
|
|
308
|
+
timeout?: number;
|
|
309
|
+
}
|
|
281
310
|
/**
|
|
282
311
|
* Creates an {@link Executor} backed by the browser / Node.js `fetch` API.
|
|
283
312
|
*
|
|
@@ -293,7 +322,13 @@ declare function dispatchExecutor(resolver: (opts: ExecuteOptions) => Executor):
|
|
|
293
322
|
* @param baseURL - Absolute base URL prepended to every endpoint path.
|
|
294
323
|
* @param options.defaultHeaders - Async factory called on every request to
|
|
295
324
|
* produce headers (e.g. reading cookies in a Next.js server component).
|
|
296
|
-
* @param options.
|
|
325
|
+
* @param options.plugins - Plugins applied around the fetch call. Each retry
|
|
326
|
+
* attempt re-runs `onRequest` hooks (so headers are refreshed per attempt)
|
|
327
|
+
* and `onError` hooks. Token-refresh-on-401 patterns work by updating an
|
|
328
|
+
* external token store in `onError` and letting `onRequest` pick it up on
|
|
329
|
+
* the next attempt.
|
|
330
|
+
* @param options.retry - Number of retries, or `{ count, shouldRetry? }`.
|
|
331
|
+
* @param options.timeout - Per-attempt timeout in milliseconds.
|
|
297
332
|
*
|
|
298
333
|
* @example Minimal — no options needed
|
|
299
334
|
* ```ts
|
|
@@ -310,22 +345,15 @@ declare function dispatchExecutor(resolver: (opts: ExecuteOptions) => Executor):
|
|
|
310
345
|
* });
|
|
311
346
|
* ```
|
|
312
347
|
*
|
|
313
|
-
* @example
|
|
348
|
+
* @example With retry and timeout
|
|
314
349
|
* ```ts
|
|
315
350
|
* const executor = createFetchExecutor('https://api.example.com', {
|
|
316
|
-
*
|
|
317
|
-
*
|
|
318
|
-
* const token = (await cookies()).get('access_token')?.value;
|
|
319
|
-
* return token ? { Authorization: `Bearer ${token}` } : {};
|
|
320
|
-
* },
|
|
321
|
-
* middlewares: [withTimeout(8_000), withRetry(2)],
|
|
351
|
+
* retry: 2,
|
|
352
|
+
* timeout: 8_000,
|
|
322
353
|
* });
|
|
323
354
|
* ```
|
|
324
355
|
*/
|
|
325
|
-
declare function createFetchExecutor(baseURL: string, options?:
|
|
326
|
-
defaultHeaders?: () => Record<string, string> | Promise<Record<string, string>>;
|
|
327
|
-
middlewares?: ExecutorMiddleware[];
|
|
328
|
-
}): Executor;
|
|
356
|
+
declare function createFetchExecutor(baseURL: string, options?: FetchExecutorOptions): Executor;
|
|
329
357
|
/**
|
|
330
358
|
* Thrown by {@link createFetchExecutor} when the server returns a non-2xx
|
|
331
359
|
* status code.
|
|
@@ -342,19 +370,10 @@ declare function createFetchExecutor(baseURL: string, options?: {
|
|
|
342
370
|
* ```
|
|
343
371
|
*/
|
|
344
372
|
declare class HttpError extends Error {
|
|
345
|
-
/** HTTP status code (e.g. 404, 500). */
|
|
346
373
|
readonly status: number;
|
|
347
|
-
/** HTTP status text (e.g. "Not Found"). */
|
|
348
374
|
readonly statusText: string;
|
|
349
|
-
/** Parsed response body, or `null` if the body was empty or not JSON. */
|
|
350
375
|
readonly body: unknown;
|
|
351
|
-
constructor(
|
|
352
|
-
/** HTTP status code (e.g. 404, 500). */
|
|
353
|
-
status: number,
|
|
354
|
-
/** HTTP status text (e.g. "Not Found"). */
|
|
355
|
-
statusText: string,
|
|
356
|
-
/** Parsed response body, or `null` if the body was empty or not JSON. */
|
|
357
|
-
body?: unknown);
|
|
376
|
+
constructor(status: number, statusText: string, body?: unknown);
|
|
358
377
|
}
|
|
359
378
|
|
|
360
379
|
/**
|
|
@@ -387,6 +406,10 @@ type PathConstraint<TPath extends string> = [PathParams<TPath>] extends [never]
|
|
|
387
406
|
* that `request` includes a matching `path` field with those param names.
|
|
388
407
|
* A mismatch or missing key is a compile-time error.
|
|
389
408
|
*
|
|
409
|
+
* The literal HTTP method (`'GET'`, `'POST'`, …) is preserved on the return
|
|
410
|
+
* type — `endpoint({ method: 'GET', ... }).method` is typed `'GET'`, not the
|
|
411
|
+
* `HttpMethod` union.
|
|
412
|
+
*
|
|
390
413
|
* @example Basic GET with no params
|
|
391
414
|
* ```ts
|
|
392
415
|
* const getList = endpoint({ method: 'GET', path: '/', response: z.array(TodoSchema) });
|
|
@@ -442,47 +465,47 @@ type PathConstraint<TPath extends string> = [PathParams<TPath>] extends [never]
|
|
|
442
465
|
* });
|
|
443
466
|
* ```
|
|
444
467
|
*/
|
|
445
|
-
declare function endpoint<TPath extends string, TRequest extends RequestShape & PathConstraint<TPath>, TResponse extends Validator<unknown>, TOut>(spec: {
|
|
446
|
-
method:
|
|
468
|
+
declare function endpoint<TMethod extends HttpMethod, TPath extends string, TRequest extends RequestShape & PathConstraint<TPath>, TResponse extends Validator<unknown>, TOut>(spec: {
|
|
469
|
+
method: TMethod;
|
|
447
470
|
path: TPath;
|
|
448
471
|
request: Validator<TRequest>;
|
|
449
472
|
response: TResponse;
|
|
450
473
|
adapter: (raw: ValidatorOutput<TResponse>) => TOut;
|
|
451
474
|
}): {
|
|
452
|
-
method:
|
|
475
|
+
method: TMethod;
|
|
453
476
|
path: string;
|
|
454
477
|
request: Validator<TRequest>;
|
|
455
478
|
response: TResponse;
|
|
456
479
|
adapter: (raw: ValidatorOutput<TResponse>) => TOut;
|
|
457
480
|
};
|
|
458
|
-
declare function endpoint<TPath extends string, TRequest extends RequestShape & PathConstraint<TPath>, TResponse extends Validator<unknown>>(spec: {
|
|
459
|
-
method:
|
|
481
|
+
declare function endpoint<TMethod extends HttpMethod, TPath extends string, TRequest extends RequestShape & PathConstraint<TPath>, TResponse extends Validator<unknown>>(spec: {
|
|
482
|
+
method: TMethod;
|
|
460
483
|
path: TPath;
|
|
461
484
|
request: Validator<TRequest>;
|
|
462
485
|
response: TResponse;
|
|
463
486
|
}): {
|
|
464
|
-
method:
|
|
487
|
+
method: TMethod;
|
|
465
488
|
path: string;
|
|
466
489
|
request: Validator<TRequest>;
|
|
467
490
|
response: TResponse;
|
|
468
491
|
};
|
|
469
|
-
declare function endpoint<TResponse extends Validator<unknown>, TOut>(spec: {
|
|
470
|
-
method:
|
|
492
|
+
declare function endpoint<TMethod extends HttpMethod, TResponse extends Validator<unknown>, TOut>(spec: {
|
|
493
|
+
method: TMethod;
|
|
471
494
|
path: string;
|
|
472
495
|
response: TResponse;
|
|
473
496
|
adapter: (raw: ValidatorOutput<TResponse>) => TOut;
|
|
474
497
|
}): {
|
|
475
|
-
method:
|
|
498
|
+
method: TMethod;
|
|
476
499
|
path: string;
|
|
477
500
|
response: TResponse;
|
|
478
501
|
adapter: (raw: ValidatorOutput<TResponse>) => TOut;
|
|
479
502
|
};
|
|
480
|
-
declare function endpoint<TResponse extends Validator<unknown>>(spec: {
|
|
481
|
-
method:
|
|
503
|
+
declare function endpoint<TMethod extends HttpMethod, TResponse extends Validator<unknown>>(spec: {
|
|
504
|
+
method: TMethod;
|
|
482
505
|
path: string;
|
|
483
506
|
response: TResponse;
|
|
484
507
|
}): {
|
|
485
|
-
method:
|
|
508
|
+
method: TMethod;
|
|
486
509
|
path: string;
|
|
487
510
|
response: TResponse;
|
|
488
511
|
};
|
|
@@ -522,71 +545,29 @@ declare function isRouterDef(entry: object): entry is RouterDef<RouterEndpoints>
|
|
|
522
545
|
declare function defineRouter<TEndpoints extends RouterEndpoints>(prefix: string, endpoints: TEndpoints): RouterDef<TEndpoints>;
|
|
523
546
|
|
|
524
547
|
/**
|
|
525
|
-
* Thrown by
|
|
526
|
-
* Distinguishable from a user-initiated
|
|
548
|
+
* Thrown by the built-in `timeout` option when a request exceeds the
|
|
549
|
+
* configured duration. Distinguishable from a user-initiated
|
|
550
|
+
* {@link AbortSignal} cancellation.
|
|
527
551
|
*/
|
|
528
552
|
declare class TimeoutError extends Error {
|
|
529
553
|
readonly ms: number;
|
|
530
554
|
constructor(ms: number);
|
|
531
555
|
}
|
|
532
556
|
/**
|
|
533
|
-
* Identity helper that returns the
|
|
534
|
-
*
|
|
535
|
-
* Wrap your middleware function with this to get full type inference on `opts`
|
|
536
|
-
* and `next` without having to annotate the type manually.
|
|
537
|
-
*
|
|
538
|
-
* @example
|
|
539
|
-
* ```ts
|
|
540
|
-
* const withCorrelationId = defineMiddleware((opts, next) =>
|
|
541
|
-
* next({ ...opts, headers: { ...opts.headers, 'X-Request-Id': crypto.randomUUID() } })
|
|
542
|
-
* );
|
|
543
|
-
* ```
|
|
544
|
-
*/
|
|
545
|
-
declare function defineMiddleware(fn: ExecutorMiddleware): ExecutorMiddleware;
|
|
546
|
-
/**
|
|
547
|
-
* Retries a failed request up to `count` additional times.
|
|
548
|
-
*
|
|
549
|
-
* By default all errors trigger a retry. Pass `shouldRetry` to skip retries
|
|
550
|
-
* for non-transient errors (e.g. 4xx responses).
|
|
551
|
-
*
|
|
552
|
-
* @param count - Number of retries (not counting the initial attempt).
|
|
553
|
-
* @param options.shouldRetry - Return `false` to stop retrying early.
|
|
554
|
-
* Receives the error and a zero-based `attempt` index (0 = first failure,
|
|
555
|
-
* 1 = second failure, …) so you can limit retries by count or error type.
|
|
556
|
-
*
|
|
557
|
-
* @example
|
|
558
|
-
* ```ts
|
|
559
|
-
* withRetry(3, {
|
|
560
|
-
* shouldRetry: (err) => err instanceof HttpError && err.status >= 500,
|
|
561
|
-
* })
|
|
562
|
-
* ```
|
|
563
|
-
*/
|
|
564
|
-
declare function withRetry(count: number, options?: {
|
|
565
|
-
shouldRetry?: (error: unknown, attempt: number) => boolean;
|
|
566
|
-
}): ExecutorMiddleware;
|
|
567
|
-
/**
|
|
568
|
-
* Aborts a request if it does not complete within `ms` milliseconds.
|
|
569
|
-
*
|
|
570
|
-
* Merges the timeout signal with any existing `AbortSignal` on the request,
|
|
571
|
-
* so whichever fires first wins.
|
|
572
|
-
*
|
|
573
|
-
* @param ms - Timeout in milliseconds.
|
|
557
|
+
* Identity helper that returns the plugin as-is, providing full type inference.
|
|
574
558
|
*
|
|
575
559
|
* @example
|
|
576
560
|
* ```ts
|
|
577
|
-
* const
|
|
578
|
-
*
|
|
561
|
+
* const authPlugin = definePlugin({
|
|
562
|
+
* name: 'auth',
|
|
563
|
+
* onRequest: async (opts) => ({
|
|
564
|
+
* ...opts,
|
|
565
|
+
* headers: { ...opts.headers, Authorization: `Bearer ${await getToken()}` },
|
|
566
|
+
* }),
|
|
579
567
|
* });
|
|
580
|
-
*
|
|
581
|
-
* // Combine with retry — timeout applies per attempt
|
|
582
|
-
* const executor = createExecutor(transport, [
|
|
583
|
-
* withTimeout(5_000),
|
|
584
|
-
* withRetry(3, { shouldRetry: (err) => !(err instanceof HttpError && err.status < 500) }),
|
|
585
|
-
* withLogger(),
|
|
586
|
-
* ]);
|
|
587
568
|
* ```
|
|
588
569
|
*/
|
|
589
|
-
declare function
|
|
570
|
+
declare function definePlugin(plugin: ExecutorPlugin): ExecutorPlugin;
|
|
590
571
|
/**
|
|
591
572
|
* Logs each request and its outcome (success duration or error).
|
|
592
573
|
*
|
|
@@ -594,12 +575,14 @@ declare function withTimeout(ms: number): ExecutorMiddleware;
|
|
|
594
575
|
*
|
|
595
576
|
* @example
|
|
596
577
|
* ```ts
|
|
597
|
-
*
|
|
578
|
+
* createExecutor(transport, {
|
|
579
|
+
* plugins: [logger({ log: (msg, data) => myLogger.debug(msg, data) })],
|
|
580
|
+
* })
|
|
598
581
|
* ```
|
|
599
582
|
*/
|
|
600
|
-
declare function
|
|
583
|
+
declare function logger(options?: {
|
|
601
584
|
log?: (message: string, data?: unknown) => void;
|
|
602
|
-
}):
|
|
585
|
+
}): ExecutorPlugin;
|
|
603
586
|
|
|
604
587
|
declare function serializeParams(params: Record<string, unknown>): URLSearchParams;
|
|
605
588
|
|
|
@@ -618,4 +601,4 @@ declare class ValidationError extends Error {
|
|
|
618
601
|
constructor(message: string, cause?: unknown);
|
|
619
602
|
}
|
|
620
603
|
|
|
621
|
-
export { type ApiTypes, type CreateApiOptions, type EndpointSpec, type ExecuteOptions, type Executor, type
|
|
604
|
+
export { type ApiClient, type ApiClientWithRouter, type ApiTypes, type CreateApiOptions, type CreateExecutorOptions, type EndpointSpec, type ExecuteOptions, type Executor, type ExecutorPlugin, type FetchExecutorOptions, type FetchRetryOption, HttpError, type HttpMethod, type InferResponse, type PathParams, type RequestShape, type RouterDef, type RouterEndpoints, type RouterEntry, TimeoutError, ValidationError, type Validator, type ValidatorOutput, createApi, createExecutor, createFetchExecutor, definePlugin, defineRouter, dispatchExecutor, endpoint, isRouterDef, joinPaths, logger, resolvePath, serializeParams };
|