fastfetch-api-fetch-enhancer 2.0.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/.idea/FastFetch-Smart-API-Fetcher.iml +12 -0
- package/.idea/modules.xml +8 -0
- package/.idea/vcs.xml +6 -0
- package/LICENSE +21 -0
- package/README.md +101 -0
- package/__tests__/demo.test.ts +216 -0
- package/__tests__/test_database.json +5002 -0
- package/coverage/clover.xml +463 -0
- package/coverage/coverage-final.json +11 -0
- package/coverage/lcov-report/base.css +224 -0
- package/coverage/lcov-report/block-navigation.js +87 -0
- package/coverage/lcov-report/circuit-breaker.ts.html +547 -0
- package/coverage/lcov-report/client.ts.html +1858 -0
- package/coverage/lcov-report/errors.ts.html +415 -0
- package/coverage/lcov-report/fastFetch.ts.html +1045 -0
- package/coverage/lcov-report/favicon.png +0 -0
- package/coverage/lcov-report/index.html +251 -0
- package/coverage/lcov-report/index.ts.html +241 -0
- package/coverage/lcov-report/metrics.ts.html +685 -0
- package/coverage/lcov-report/middleware.ts.html +403 -0
- package/coverage/lcov-report/offline-queue.ts.html +535 -0
- package/coverage/lcov-report/prettify.css +1 -0
- package/coverage/lcov-report/prettify.js +2 -0
- package/coverage/lcov-report/queue.ts.html +421 -0
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +196 -0
- package/coverage/lcov-report/streaming.ts.html +466 -0
- package/coverage/lcov.info +908 -0
- package/dist/circuit-breaker.d.ts +61 -0
- package/dist/circuit-breaker.d.ts.map +1 -0
- package/dist/circuit-breaker.js +106 -0
- package/dist/client.d.ts +215 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +391 -0
- package/dist/errors.d.ts +56 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +91 -0
- package/dist/fastFetch.d.ts +65 -0
- package/dist/fastFetch.d.ts.map +1 -0
- package/dist/fastFetch.js +209 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/metrics.d.ts +71 -0
- package/dist/metrics.d.ts.map +1 -0
- package/dist/metrics.js +131 -0
- package/dist/middleware.d.ts +66 -0
- package/dist/middleware.d.ts.map +1 -0
- package/dist/middleware.js +45 -0
- package/dist/offline-queue.d.ts +65 -0
- package/dist/offline-queue.d.ts.map +1 -0
- package/dist/offline-queue.js +120 -0
- package/dist/queue.d.ts +33 -0
- package/dist/queue.d.ts.map +1 -0
- package/dist/queue.js +76 -0
- package/dist/streaming.d.ts +40 -0
- package/dist/streaming.d.ts.map +1 -0
- package/dist/streaming.js +98 -0
- package/index.d.ts +167 -0
- package/jest.config.js +16 -0
- package/package.json +55 -0
- package/src/circuit-breaker.ts +154 -0
- package/src/client.ts +591 -0
- package/src/errors.ts +110 -0
- package/src/fastFetch.ts +320 -0
- package/src/index.ts +52 -0
- package/src/metrics.ts +200 -0
- package/src/middleware.ts +106 -0
- package/src/offline-queue.ts +150 -0
- package/src/queue.ts +112 -0
- package/src/streaming.ts +127 -0
- package/tsconfig.json +18 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FastFetch Circuit Breaker — Finite State Machine implementation.
|
|
3
|
+
*
|
|
4
|
+
* Prevents cascading failures by "opening" the circuit after a configurable
|
|
5
|
+
* number of consecutive failures, then probing with a single request after
|
|
6
|
+
* the reset timeout before fully re-closing.
|
|
7
|
+
*
|
|
8
|
+
* States:
|
|
9
|
+
* CLOSED — normal operation; every request goes through
|
|
10
|
+
* OPEN — requests are immediately rejected (CircuitOpenError)
|
|
11
|
+
* HALF_OPEN — one probe request is allowed; success → CLOSED, failure → OPEN
|
|
12
|
+
*/
|
|
13
|
+
export type CircuitState = "CLOSED" | "OPEN" | "HALF_OPEN";
|
|
14
|
+
export interface CircuitBreakerOptions {
|
|
15
|
+
/**
|
|
16
|
+
* Number of consecutive failures before the circuit opens (default: 5).
|
|
17
|
+
*/
|
|
18
|
+
threshold?: number;
|
|
19
|
+
/**
|
|
20
|
+
* Milliseconds to wait in the OPEN state before transitioning to HALF_OPEN
|
|
21
|
+
* and allowing a single probe request (default: 30 000 ms = 30 s).
|
|
22
|
+
*/
|
|
23
|
+
timeout?: number;
|
|
24
|
+
/** Called when the circuit transitions CLOSED → OPEN. */
|
|
25
|
+
onOpen?: () => void;
|
|
26
|
+
/** Called when the circuit transitions HALF_OPEN → CLOSED (recovered). */
|
|
27
|
+
onClose?: () => void;
|
|
28
|
+
/** Called when the circuit transitions OPEN → HALF_OPEN (probing). */
|
|
29
|
+
onHalfOpen?: () => void;
|
|
30
|
+
}
|
|
31
|
+
export declare class CircuitBreaker {
|
|
32
|
+
private _state;
|
|
33
|
+
private consecutiveFailures;
|
|
34
|
+
private openedAt;
|
|
35
|
+
private probeInFlight;
|
|
36
|
+
private readonly threshold;
|
|
37
|
+
private readonly timeoutMs;
|
|
38
|
+
private readonly onOpen?;
|
|
39
|
+
private readonly onClose?;
|
|
40
|
+
private readonly onHalfOpen?;
|
|
41
|
+
constructor(options?: CircuitBreakerOptions);
|
|
42
|
+
/**
|
|
43
|
+
* Current circuit state. Reading this property can trigger an automatic
|
|
44
|
+
* OPEN → HALF_OPEN transition when the reset timeout has elapsed.
|
|
45
|
+
*/
|
|
46
|
+
get state(): CircuitState;
|
|
47
|
+
/**
|
|
48
|
+
* Execute `fn` through the circuit breaker.
|
|
49
|
+
* - CLOSED → run `fn`, track success/failure
|
|
50
|
+
* - OPEN → throw `CircuitOpenError` immediately (no network call)
|
|
51
|
+
* - HALF_OPEN → allow one probe; success closes, failure re-opens
|
|
52
|
+
*/
|
|
53
|
+
execute<T>(fn: () => Promise<T>): Promise<T>;
|
|
54
|
+
private recordSuccess;
|
|
55
|
+
private recordFailure;
|
|
56
|
+
/** Manually reset the circuit to CLOSED. Useful for testing. */
|
|
57
|
+
reset(): void;
|
|
58
|
+
/** Number of consecutive failures recorded since last success. */
|
|
59
|
+
get failures(): number;
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=circuit-breaker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"circuit-breaker.d.ts","sourceRoot":"","sources":["../src/circuit-breaker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,MAAM,GAAG,WAAW,CAAC;AAE3D,MAAM,WAAW,qBAAqB;IACpC;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,yDAAyD;IACzD,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,0EAA0E;IAC1E,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,sEAAsE;IACtE,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;CACzB;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAA0B;IACxC,OAAO,CAAC,mBAAmB,CAAK;IAChC,OAAO,CAAC,QAAQ,CAAK;IACrB,OAAO,CAAC,aAAa,CAAS;IAE9B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAa;IACrC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAa;IACtC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAa;gBAE7B,OAAO,GAAE,qBAA0B;IAU/C;;;OAGG;IACH,IAAI,KAAK,IAAI,YAAY,CAUxB;IAID;;;;;OAKG;IACG,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IA2BlD,OAAO,CAAC,aAAa;IAUrB,OAAO,CAAC,aAAa;IAuBrB,gEAAgE;IAChE,KAAK,IAAI,IAAI;IAOb,kEAAkE;IAClE,IAAI,QAAQ,IAAI,MAAM,CAErB;CACF"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FastFetch Circuit Breaker — Finite State Machine implementation.
|
|
3
|
+
*
|
|
4
|
+
* Prevents cascading failures by "opening" the circuit after a configurable
|
|
5
|
+
* number of consecutive failures, then probing with a single request after
|
|
6
|
+
* the reset timeout before fully re-closing.
|
|
7
|
+
*
|
|
8
|
+
* States:
|
|
9
|
+
* CLOSED — normal operation; every request goes through
|
|
10
|
+
* OPEN — requests are immediately rejected (CircuitOpenError)
|
|
11
|
+
* HALF_OPEN — one probe request is allowed; success → CLOSED, failure → OPEN
|
|
12
|
+
*/
|
|
13
|
+
import { CircuitOpenError } from "./errors.js";
|
|
14
|
+
export class CircuitBreaker {
|
|
15
|
+
constructor(options = {}) {
|
|
16
|
+
this._state = "CLOSED";
|
|
17
|
+
this.consecutiveFailures = 0;
|
|
18
|
+
this.openedAt = 0;
|
|
19
|
+
this.probeInFlight = false;
|
|
20
|
+
this.threshold = options.threshold ?? 5;
|
|
21
|
+
this.timeoutMs = options.timeout ?? 30000;
|
|
22
|
+
this.onOpen = options.onOpen;
|
|
23
|
+
this.onClose = options.onClose;
|
|
24
|
+
this.onHalfOpen = options.onHalfOpen;
|
|
25
|
+
}
|
|
26
|
+
// ── State accessor ───────────────────────────────────────────────────────
|
|
27
|
+
/**
|
|
28
|
+
* Current circuit state. Reading this property can trigger an automatic
|
|
29
|
+
* OPEN → HALF_OPEN transition when the reset timeout has elapsed.
|
|
30
|
+
*/
|
|
31
|
+
get state() {
|
|
32
|
+
if (this._state === "OPEN" &&
|
|
33
|
+
Date.now() - this.openedAt >= this.timeoutMs) {
|
|
34
|
+
this._state = "HALF_OPEN";
|
|
35
|
+
this.probeInFlight = false;
|
|
36
|
+
this.onHalfOpen?.();
|
|
37
|
+
}
|
|
38
|
+
return this._state;
|
|
39
|
+
}
|
|
40
|
+
// ── Core execute ─────────────────────────────────────────────────────────
|
|
41
|
+
/**
|
|
42
|
+
* Execute `fn` through the circuit breaker.
|
|
43
|
+
* - CLOSED → run `fn`, track success/failure
|
|
44
|
+
* - OPEN → throw `CircuitOpenError` immediately (no network call)
|
|
45
|
+
* - HALF_OPEN → allow one probe; success closes, failure re-opens
|
|
46
|
+
*/
|
|
47
|
+
async execute(fn) {
|
|
48
|
+
const currentState = this.state; // may trigger OPEN→HALF_OPEN
|
|
49
|
+
if (currentState === "OPEN") {
|
|
50
|
+
throw new CircuitOpenError();
|
|
51
|
+
}
|
|
52
|
+
if (currentState === "HALF_OPEN") {
|
|
53
|
+
// Reject parallel probes — only one probe allowed at a time
|
|
54
|
+
if (this.probeInFlight) {
|
|
55
|
+
throw new CircuitOpenError();
|
|
56
|
+
}
|
|
57
|
+
this.probeInFlight = true;
|
|
58
|
+
}
|
|
59
|
+
try {
|
|
60
|
+
const result = await fn();
|
|
61
|
+
this.recordSuccess();
|
|
62
|
+
return result;
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
this.recordFailure();
|
|
66
|
+
throw err;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
// ── Private FSM transitions ──────────────────────────────────────────────
|
|
70
|
+
recordSuccess() {
|
|
71
|
+
this.consecutiveFailures = 0;
|
|
72
|
+
this.probeInFlight = false;
|
|
73
|
+
if (this._state === "HALF_OPEN") {
|
|
74
|
+
this._state = "CLOSED";
|
|
75
|
+
this.onClose?.();
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
recordFailure() {
|
|
79
|
+
this.consecutiveFailures++;
|
|
80
|
+
this.probeInFlight = false;
|
|
81
|
+
if (this._state === "HALF_OPEN") {
|
|
82
|
+
// Probe failed — re-open the circuit
|
|
83
|
+
this._state = "OPEN";
|
|
84
|
+
this.openedAt = Date.now();
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
if (this._state === "CLOSED" &&
|
|
88
|
+
this.consecutiveFailures >= this.threshold) {
|
|
89
|
+
this._state = "OPEN";
|
|
90
|
+
this.openedAt = Date.now();
|
|
91
|
+
this.onOpen?.();
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
// ── Manual controls ──────────────────────────────────────────────────────
|
|
95
|
+
/** Manually reset the circuit to CLOSED. Useful for testing. */
|
|
96
|
+
reset() {
|
|
97
|
+
this._state = "CLOSED";
|
|
98
|
+
this.consecutiveFailures = 0;
|
|
99
|
+
this.openedAt = 0;
|
|
100
|
+
this.probeInFlight = false;
|
|
101
|
+
}
|
|
102
|
+
/** Number of consecutive failures recorded since last success. */
|
|
103
|
+
get failures() {
|
|
104
|
+
return this.consecutiveFailures;
|
|
105
|
+
}
|
|
106
|
+
}
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FastFetch client factory — `createClient()`.
|
|
3
|
+
*
|
|
4
|
+
* Creates a pre-configured `FastFetchClient` instance with:
|
|
5
|
+
* - Base URL + default headers
|
|
6
|
+
* - Request / Response / Error interceptors (v1.x, preserved)
|
|
7
|
+
* - Koa-style middleware pipeline (`api.use()`)
|
|
8
|
+
* - Circuit breaker
|
|
9
|
+
* - Concurrency-limited request queue
|
|
10
|
+
* - Built-in metrics
|
|
11
|
+
* - SSE streaming (`api.stream()`)
|
|
12
|
+
* - Offline request queue
|
|
13
|
+
* - Typed HTTP method helpers (get / post / put / patch / delete / json)
|
|
14
|
+
* - Auto-serialisation of request body (plain objects → JSON)
|
|
15
|
+
*/
|
|
16
|
+
import { FastFetchOptions } from "./fastFetch.js";
|
|
17
|
+
import { MetricsCollector } from "./metrics.js";
|
|
18
|
+
import { CircuitBreaker, CircuitBreakerOptions } from "./circuit-breaker.js";
|
|
19
|
+
import { RequestQueue } from "./queue.js";
|
|
20
|
+
import { MiddlewareFn } from "./middleware.js";
|
|
21
|
+
import { SSEHandler } from "./streaming.js";
|
|
22
|
+
export type RequestInterceptor = (url: string, init: RequestInit & FastFetchOptions) => (RequestInit & FastFetchOptions) | Promise<RequestInit & FastFetchOptions>;
|
|
23
|
+
export type ResponseInterceptor = (response: Response) => Response | Promise<Response>;
|
|
24
|
+
export type ErrorInterceptor = (error: unknown) => unknown | Promise<unknown>;
|
|
25
|
+
export interface ClientOptions extends FastFetchOptions {
|
|
26
|
+
/**
|
|
27
|
+
* Base URL prepended to all relative paths.
|
|
28
|
+
* @example `'https://api.example.com/v1'`
|
|
29
|
+
*/
|
|
30
|
+
baseURL?: string;
|
|
31
|
+
/**
|
|
32
|
+
* Default headers merged into every request.
|
|
33
|
+
* Per-request headers take precedence.
|
|
34
|
+
*/
|
|
35
|
+
headers?: Record<string, string>;
|
|
36
|
+
/**
|
|
37
|
+
* Throw an `HttpError` for non-2xx responses (default: `true`).
|
|
38
|
+
* Set to `false` to receive the raw Response regardless of status.
|
|
39
|
+
*/
|
|
40
|
+
throwOnError?: boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Circuit breaker configuration.
|
|
43
|
+
* When provided, the circuit breaker wraps every request.
|
|
44
|
+
*/
|
|
45
|
+
circuitBreaker?: CircuitBreakerOptions;
|
|
46
|
+
/**
|
|
47
|
+
* Maximum number of concurrent in-flight requests for this client.
|
|
48
|
+
* Additional requests are queued until a slot becomes free.
|
|
49
|
+
*/
|
|
50
|
+
maxConcurrent?: number;
|
|
51
|
+
/**
|
|
52
|
+
* Rolling window size for the built-in metrics collector (default: 1 000).
|
|
53
|
+
*/
|
|
54
|
+
metricsWindowSize?: number;
|
|
55
|
+
/**
|
|
56
|
+
* When `true`, mutating requests (POST/PUT/PATCH/DELETE) made while
|
|
57
|
+
* `navigator.onLine === false` are queued and replayed on reconnect.
|
|
58
|
+
* No-op in non-browser environments.
|
|
59
|
+
*/
|
|
60
|
+
offlineQueue?: boolean;
|
|
61
|
+
/** v1.x interceptors — still supported. Prefer `use()` for new code. */
|
|
62
|
+
interceptors?: {
|
|
63
|
+
request?: RequestInterceptor[];
|
|
64
|
+
response?: ResponseInterceptor[];
|
|
65
|
+
error?: ErrorInterceptor[];
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
export declare class FastFetchClient {
|
|
69
|
+
private readonly baseURL;
|
|
70
|
+
private readonly defaultHeaders;
|
|
71
|
+
private readonly defaultOptions;
|
|
72
|
+
private readonly clientThrowOnError;
|
|
73
|
+
private readonly requestInterceptors;
|
|
74
|
+
private readonly responseInterceptors;
|
|
75
|
+
private readonly errorInterceptors;
|
|
76
|
+
private readonly middlewares;
|
|
77
|
+
private readonly _circuitBreaker?;
|
|
78
|
+
private readonly _queue?;
|
|
79
|
+
private readonly _offlineQueue?;
|
|
80
|
+
private readonly _metrics;
|
|
81
|
+
constructor(options?: ClientOptions);
|
|
82
|
+
/**
|
|
83
|
+
* Register a middleware function.
|
|
84
|
+
*
|
|
85
|
+
* Middleware runs in registration order (Koa onion model):
|
|
86
|
+
* - Code *before* `await next()` executes on the way *down* (pre-request).
|
|
87
|
+
* - Code *after* `await next()` executes on the way *up* (post-response).
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* ```ts
|
|
91
|
+
* api.use(async (ctx, next) => {
|
|
92
|
+
* ctx.init.headers['X-Request-Id'] = crypto.randomUUID();
|
|
93
|
+
* const start = Date.now();
|
|
94
|
+
* await next();
|
|
95
|
+
* console.log(`${ctx.method} ${ctx.url} — ${Date.now() - start}ms ${ctx.response?.status}`);
|
|
96
|
+
* });
|
|
97
|
+
* ```
|
|
98
|
+
*/
|
|
99
|
+
use(middleware: MiddlewareFn): this;
|
|
100
|
+
/**
|
|
101
|
+
* Built-in metrics collector.
|
|
102
|
+
* Call `.metrics.snapshot()` to get request counts, error rates, and latency percentiles.
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* ```ts
|
|
106
|
+
* console.table(api.metrics.snapshot().byEndpoint);
|
|
107
|
+
* ```
|
|
108
|
+
*/
|
|
109
|
+
get metrics(): MetricsCollector;
|
|
110
|
+
/**
|
|
111
|
+
* Direct access to the circuit breaker (if configured).
|
|
112
|
+
* Useful for inspecting state or manually resetting in tests.
|
|
113
|
+
*/
|
|
114
|
+
get circuitBreaker(): CircuitBreaker | undefined;
|
|
115
|
+
/**
|
|
116
|
+
* Direct access to the concurrency queue (if configured).
|
|
117
|
+
* Useful for observing `pending` / `active` counts.
|
|
118
|
+
*/
|
|
119
|
+
get queue(): RequestQueue | undefined;
|
|
120
|
+
private resolveURL;
|
|
121
|
+
private mergeInit;
|
|
122
|
+
/**
|
|
123
|
+
* Auto-serialise the request body.
|
|
124
|
+
* - Plain objects / arrays → JSON string + `Content-Type: application/json`
|
|
125
|
+
* - FormData / URLSearchParams / Blob / ArrayBuffer / string → passed through
|
|
126
|
+
*/
|
|
127
|
+
private autoSerializeBody;
|
|
128
|
+
/**
|
|
129
|
+
* Make an HTTP request. Runs the full pipeline:
|
|
130
|
+
* request interceptors → middleware → circuit breaker → queue → fastFetch → response interceptors.
|
|
131
|
+
*
|
|
132
|
+
* Throws `HttpError` on non-2xx by default (disable with `throwOnError: false`).
|
|
133
|
+
*/
|
|
134
|
+
fetch(path: string, init?: RequestInit & FastFetchOptions & {
|
|
135
|
+
throwOnError?: boolean;
|
|
136
|
+
}): Promise<Response>;
|
|
137
|
+
/**
|
|
138
|
+
* Fetch and automatically parse the response body as JSON.
|
|
139
|
+
* Returns a typed `Promise<T>`.
|
|
140
|
+
*
|
|
141
|
+
* @example
|
|
142
|
+
* ```ts
|
|
143
|
+
* const user = await api.json<User>('/users/1');
|
|
144
|
+
* const posts = await api.json<Post[]>('/posts?limit=10');
|
|
145
|
+
* ```
|
|
146
|
+
*/
|
|
147
|
+
json<T = unknown>(path: string, init?: RequestInit & FastFetchOptions): Promise<T>;
|
|
148
|
+
/**
|
|
149
|
+
* Open a Server-Sent Events stream and call `handler` for each event.
|
|
150
|
+
*
|
|
151
|
+
* The method resolves when the stream ends or the provided `AbortSignal` fires.
|
|
152
|
+
* Automatically sets `Accept: text/event-stream` and `Cache-Control: no-cache`.
|
|
153
|
+
*
|
|
154
|
+
* @example
|
|
155
|
+
* ```ts
|
|
156
|
+
* const ctrl = new AbortController();
|
|
157
|
+
* await api.stream('/api/ai/generate', (event) => {
|
|
158
|
+
* process.stdout.write(event.data);
|
|
159
|
+
* }, { signal: ctrl.signal });
|
|
160
|
+
* ```
|
|
161
|
+
*/
|
|
162
|
+
stream(path: string, handler: SSEHandler, init?: RequestInit & FastFetchOptions): Promise<void>;
|
|
163
|
+
/** GET request — returns raw `Response`. Use `.json<T>()` for parsed data. */
|
|
164
|
+
get(path: string, init?: RequestInit & FastFetchOptions): Promise<Response>;
|
|
165
|
+
/**
|
|
166
|
+
* POST request. Body is automatically serialised:
|
|
167
|
+
* - Plain objects / arrays → JSON (+ `Content-Type: application/json`)
|
|
168
|
+
* - FormData / URLSearchParams / string → passed through as-is
|
|
169
|
+
*/
|
|
170
|
+
post<B = unknown>(path: string, body?: B, init?: RequestInit & FastFetchOptions): Promise<Response>;
|
|
171
|
+
/**
|
|
172
|
+
* PUT request with auto body serialisation.
|
|
173
|
+
*/
|
|
174
|
+
put<B = unknown>(path: string, body?: B, init?: RequestInit & FastFetchOptions): Promise<Response>;
|
|
175
|
+
/**
|
|
176
|
+
* PATCH request with auto body serialisation.
|
|
177
|
+
*/
|
|
178
|
+
patch<B = unknown>(path: string, body?: B, init?: RequestInit & FastFetchOptions): Promise<Response>;
|
|
179
|
+
/** DELETE request. */
|
|
180
|
+
delete(path: string, init?: RequestInit & FastFetchOptions): Promise<Response>;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Create a pre-configured `FastFetchClient` instance.
|
|
184
|
+
*
|
|
185
|
+
* @example
|
|
186
|
+
* ```ts
|
|
187
|
+
* import { createClient } from 'fastfetch-api-fetch-enhancer';
|
|
188
|
+
*
|
|
189
|
+
* const api = createClient({
|
|
190
|
+
* baseURL: 'https://api.example.com/v1',
|
|
191
|
+
* headers: { Authorization: `Bearer ${token}` },
|
|
192
|
+
* retries: 3,
|
|
193
|
+
* timeout: 8_000,
|
|
194
|
+
* circuitBreaker: { threshold: 5, timeout: 30_000 },
|
|
195
|
+
* maxConcurrent: 10,
|
|
196
|
+
* offlineQueue: true,
|
|
197
|
+
* });
|
|
198
|
+
*
|
|
199
|
+
* // Register middleware
|
|
200
|
+
* api.use(async (ctx, next) => {
|
|
201
|
+
* ctx.init.headers['X-Request-Id'] = crypto.randomUUID();
|
|
202
|
+
* await next();
|
|
203
|
+
* console.log(`${ctx.method} ${ctx.url} → ${ctx.response?.status} in ${ctx.duration}ms`);
|
|
204
|
+
* });
|
|
205
|
+
*
|
|
206
|
+
* const user = await api.json<User>('/users/1');
|
|
207
|
+
* const posts = await api.json<Post[]>('/posts');
|
|
208
|
+
* await api.post('/users', { name: 'Alice', role: 'admin' }); // auto-JSON
|
|
209
|
+
* await api.stream('/events', (e) => console.log(e.data));
|
|
210
|
+
*
|
|
211
|
+
* console.table(api.metrics.snapshot().byEndpoint);
|
|
212
|
+
* ```
|
|
213
|
+
*/
|
|
214
|
+
export declare function createClient(options?: ClientOptions): FastFetchClient;
|
|
215
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|