tanstack-fetch 1.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.
@@ -0,0 +1,257 @@
1
+ type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS';
2
+ type ClientSource = 'browser' | 'ssr' | 'edge';
3
+ type IncomingHeaders = {
4
+ cookie?: string;
5
+ authorization?: string;
6
+ requestId?: string;
7
+ };
8
+ type PathParams = Record<string, string | number>;
9
+ type QueryParams = Record<string, string | number | boolean | undefined | null>;
10
+ type PluginName = 'trace' | 'ssr-forward' | 'retry-idempotent' | 'sse-resume';
11
+ type MaybePromise<T> = T | Promise<T>;
12
+
13
+ type OkResult<T> = {
14
+ ok: true;
15
+ status: number;
16
+ data: T;
17
+ headers: Headers;
18
+ };
19
+ type ErrResult<E> = {
20
+ ok: false;
21
+ status: number;
22
+ error: E;
23
+ headers: Headers;
24
+ };
25
+ type FetchResult<T, E = FetchErrorInfo> = OkResult<T> | ErrResult<E>;
26
+ type FetchErrorInfo = {
27
+ status: number;
28
+ code: string;
29
+ message: string;
30
+ body: unknown;
31
+ };
32
+ /** @deprecated Use FetchResult */
33
+ type HttpResult<T, E = FetchErrorInfo> = FetchResult<T, E>;
34
+ /** @deprecated Use FetchErrorInfo */
35
+ type HttpError = FetchErrorInfo;
36
+
37
+ type RequestContext = {
38
+ request: {
39
+ method: HttpMethod;
40
+ url: URL;
41
+ headers: Headers;
42
+ body?: unknown;
43
+ signal?: AbortSignal;
44
+ };
45
+ response?: Response;
46
+ data?: unknown;
47
+ error?: FetchErrorInfo;
48
+ incoming?: IncomingHeaders;
49
+ meta: {
50
+ attempt: number;
51
+ maxRetries: number;
52
+ source: ClientSource;
53
+ operation?: string;
54
+ requestId?: string;
55
+ lastEventId?: string;
56
+ };
57
+ };
58
+ type SseEventContext<T = unknown> = RequestContext & {
59
+ event: {
60
+ event?: string;
61
+ data: T;
62
+ id?: string;
63
+ retry?: number;
64
+ };
65
+ };
66
+ type InterceptorDecision<T> = {
67
+ action: 'continue';
68
+ context?: T;
69
+ } | {
70
+ action: 'skip';
71
+ } | {
72
+ action: 'drop';
73
+ } | {
74
+ action: 'retry';
75
+ delayMs?: number;
76
+ } | {
77
+ action: 'short-circuit';
78
+ result: FetchResult<unknown, unknown>;
79
+ };
80
+ type InterceptorHandler<T> = (context: T) => MaybePromise<InterceptorDecision<T> | void>;
81
+ type HttpInterceptor = {
82
+ name: string;
83
+ order?: number;
84
+ match?: {
85
+ operation?: string;
86
+ method?: HttpMethod;
87
+ pathPrefix?: string;
88
+ status?: number;
89
+ };
90
+ onRequest?: InterceptorHandler<RequestContext>;
91
+ onRequestError?: InterceptorHandler<RequestContext>;
92
+ onResponse?: InterceptorHandler<RequestContext>;
93
+ onResponseError?: InterceptorHandler<RequestContext>;
94
+ onSseOpen?: InterceptorHandler<RequestContext>;
95
+ onSseEvent?: InterceptorHandler<SseEventContext>;
96
+ onSseError?: InterceptorHandler<RequestContext>;
97
+ onSseReconnect?: InterceptorHandler<RequestContext>;
98
+ };
99
+
100
+ type StatusHandlerInput = {
101
+ status: number;
102
+ error: FetchErrorInfo;
103
+ context: RequestContext;
104
+ };
105
+ type StatusHandlerResult = void | {
106
+ action: 'continue';
107
+ } | {
108
+ action: 'retry';
109
+ delayMs?: number;
110
+ };
111
+ type StatusHandler = (input: StatusHandlerInput) => MaybePromise<StatusHandlerResult>;
112
+ type StatusHandlers = {
113
+ 401?: StatusHandler;
114
+ 403?: StatusHandler;
115
+ 404?: StatusHandler;
116
+ 500?: StatusHandler;
117
+ '4xx'?: StatusHandler;
118
+ '5xx'?: StatusHandler;
119
+ default?: StatusHandler;
120
+ } & {
121
+ [status: number]: StatusHandler | undefined;
122
+ };
123
+ type AuthConfig = {
124
+ /** Return access token (or null/undefined to skip). */
125
+ getToken: () => MaybePromise<string | null | undefined>;
126
+ /** Header name. Default: `authorization`. */
127
+ header?: string;
128
+ /** Prefix before token. Default: `Bearer`. Use `''` for raw token. */
129
+ scheme?: string;
130
+ };
131
+
132
+ type SseEvent<T = unknown> = {
133
+ event?: string;
134
+ data: T;
135
+ id?: string;
136
+ retry?: number;
137
+ };
138
+ type SseSubscription = {
139
+ /** Stop the stream. */
140
+ close: () => void;
141
+ };
142
+ type SseHandlers<T = unknown> = {
143
+ /** Simple path — only the payload. */
144
+ onMessage?: (data: T, event: SseEvent<T>) => void;
145
+ /** Full SSE event (`event`, `data`, `id`). */
146
+ onEvent?: (event: SseEvent<T>) => void;
147
+ onOpen?: () => void;
148
+ onError?: (error: unknown) => void;
149
+ onClose?: () => void;
150
+ };
151
+
152
+ type RequestInterceptorConfig = {
153
+ use?: HttpInterceptor[];
154
+ eject?: string[];
155
+ };
156
+ type RequestOptions = {
157
+ params?: PathParams;
158
+ query?: QueryParams;
159
+ body?: unknown;
160
+ headers?: HeadersInit;
161
+ signal?: AbortSignal;
162
+ timeoutMs?: number;
163
+ /** Default `true` — matches TanStack Query `queryFn` (throw on HTTP error). */
164
+ throwOnError?: boolean;
165
+ parseAs?: 'json' | 'text' | 'blob';
166
+ operation?: string;
167
+ interceptors?: RequestInterceptorConfig;
168
+ };
169
+ type CreateFetchOptions = {
170
+ baseUrl?: string;
171
+ headers?: HeadersInit | (() => MaybePromise<HeadersInit>);
172
+ source?: ClientSource;
173
+ incoming?: IncomingHeaders | (() => MaybePromise<IncomingHeaders>);
174
+ timeoutMs?: number;
175
+ /** Default `true` for TanStack Query. Set `false` to get `FetchResult`. */
176
+ throwOnError?: boolean;
177
+ interceptors?: HttpInterceptor[];
178
+ plugins?: PluginName[];
179
+ fetch?: typeof fetch;
180
+ credentials?: RequestCredentials;
181
+ maxRetries?: number;
182
+ /** Simple auth: attach Bearer token on every request. */
183
+ getToken?: () => MaybePromise<string | null | undefined>;
184
+ /** Advanced auth config (overrides `getToken` when both set via `auth`). */
185
+ auth?: AuthConfig;
186
+ /** Called on HTTP 401 before the error is thrown / returned. */
187
+ onUnauthorized?: StatusHandler;
188
+ /** Called on HTTP 403. */
189
+ onForbidden?: StatusHandler;
190
+ /** Called on HTTP 404. */
191
+ onNotFound?: StatusHandler;
192
+ /** Called on HTTP 5xx (500–599). */
193
+ onServerError?: StatusHandler;
194
+ /** Advanced per-status map (`401`, `403`, `4xx`, `5xx`, `default`, …). */
195
+ onStatus?: StatusHandlers;
196
+ };
197
+ type ThrowingOptions = Omit<RequestOptions, 'throwOnError'> & {
198
+ throwOnError?: true;
199
+ };
200
+ type ResultOptions = Omit<RequestOptions, 'throwOnError'> & {
201
+ throwOnError: false;
202
+ };
203
+ type FetchMethod = {
204
+ <T>(path: string, options?: ThrowingOptions): Promise<T>;
205
+ <T, E = FetchErrorInfo>(path: string, options: ResultOptions): Promise<FetchResult<T, E>>;
206
+ };
207
+ type FetchRequest = {
208
+ <T>(method: HttpMethod, path: string, options?: ThrowingOptions): Promise<T>;
209
+ <T, E = FetchErrorInfo>(method: HttpMethod, path: string, options: ResultOptions): Promise<FetchResult<T, E>>;
210
+ };
211
+ type SseCallOptions<T = unknown> = RequestOptions & SseHandlers<T> & {
212
+ lastEventId?: string;
213
+ };
214
+ type FetchClient = {
215
+ use: (name: string, interceptor: Omit<HttpInterceptor, 'name'> & {
216
+ name?: string;
217
+ }, config?: {
218
+ order?: number;
219
+ }) => void;
220
+ eject: (name: string) => void;
221
+ request: FetchRequest;
222
+ get: FetchMethod;
223
+ post: FetchMethod;
224
+ put: FetchMethod;
225
+ patch: FetchMethod;
226
+ delete: FetchMethod;
227
+ /**
228
+ * Simple: pass `onMessage` / `onEvent` → returns `{ close }`.
229
+ * Advanced: no handlers → `AsyncIterable` for `for await`.
230
+ */
231
+ sse: {
232
+ <T>(path: string, options: SseCallOptions<T> & ({
233
+ onMessage: SseHandlers<T>['onMessage'];
234
+ } | {
235
+ onEvent: SseHandlers<T>['onEvent'];
236
+ })): SseSubscription;
237
+ <T>(path: string, options?: SseCallOptions<T>): AsyncIterable<SseEvent<T>>;
238
+ };
239
+ };
240
+ /** @deprecated Use CreateFetchOptions */
241
+ type CreateClientOptions = CreateFetchOptions;
242
+ /** @deprecated Use FetchClient */
243
+ type HttpClient = FetchClient;
244
+
245
+ type FetchError = Error & {
246
+ readonly name: 'FetchError';
247
+ readonly status: number;
248
+ readonly code: string;
249
+ readonly body: unknown;
250
+ readonly headers: Headers;
251
+ readonly result: FetchResult<never, FetchErrorInfo>;
252
+ };
253
+ declare const createFetchError: (result: FetchResult<never, FetchErrorInfo>) => FetchError;
254
+ declare const isFetchError: (error: unknown) => error is FetchError;
255
+ declare const isAbortError: (error: unknown) => boolean;
256
+
257
+ export { type AuthConfig as A, type CreateFetchOptions as C, type FetchClient as F, type HttpInterceptor as H, type IncomingHeaders as I, type PluginName as P, type RequestContext as R, type StatusHandlers as S, type FetchResult as a, type FetchErrorInfo as b, type CreateClientOptions as c, type FetchError as d, type HttpClient as e, type HttpError as f, type HttpMethod as g, type HttpResult as h, type RequestOptions as i, type SseCallOptions as j, type SseEvent as k, type SseHandlers as l, type SseSubscription as m, type StatusHandler as n, type StatusHandlerInput as o, type StatusHandlerResult as p, createFetchError as q, isAbortError as r, isFetchError as s };
@@ -0,0 +1,257 @@
1
+ type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS';
2
+ type ClientSource = 'browser' | 'ssr' | 'edge';
3
+ type IncomingHeaders = {
4
+ cookie?: string;
5
+ authorization?: string;
6
+ requestId?: string;
7
+ };
8
+ type PathParams = Record<string, string | number>;
9
+ type QueryParams = Record<string, string | number | boolean | undefined | null>;
10
+ type PluginName = 'trace' | 'ssr-forward' | 'retry-idempotent' | 'sse-resume';
11
+ type MaybePromise<T> = T | Promise<T>;
12
+
13
+ type OkResult<T> = {
14
+ ok: true;
15
+ status: number;
16
+ data: T;
17
+ headers: Headers;
18
+ };
19
+ type ErrResult<E> = {
20
+ ok: false;
21
+ status: number;
22
+ error: E;
23
+ headers: Headers;
24
+ };
25
+ type FetchResult<T, E = FetchErrorInfo> = OkResult<T> | ErrResult<E>;
26
+ type FetchErrorInfo = {
27
+ status: number;
28
+ code: string;
29
+ message: string;
30
+ body: unknown;
31
+ };
32
+ /** @deprecated Use FetchResult */
33
+ type HttpResult<T, E = FetchErrorInfo> = FetchResult<T, E>;
34
+ /** @deprecated Use FetchErrorInfo */
35
+ type HttpError = FetchErrorInfo;
36
+
37
+ type RequestContext = {
38
+ request: {
39
+ method: HttpMethod;
40
+ url: URL;
41
+ headers: Headers;
42
+ body?: unknown;
43
+ signal?: AbortSignal;
44
+ };
45
+ response?: Response;
46
+ data?: unknown;
47
+ error?: FetchErrorInfo;
48
+ incoming?: IncomingHeaders;
49
+ meta: {
50
+ attempt: number;
51
+ maxRetries: number;
52
+ source: ClientSource;
53
+ operation?: string;
54
+ requestId?: string;
55
+ lastEventId?: string;
56
+ };
57
+ };
58
+ type SseEventContext<T = unknown> = RequestContext & {
59
+ event: {
60
+ event?: string;
61
+ data: T;
62
+ id?: string;
63
+ retry?: number;
64
+ };
65
+ };
66
+ type InterceptorDecision<T> = {
67
+ action: 'continue';
68
+ context?: T;
69
+ } | {
70
+ action: 'skip';
71
+ } | {
72
+ action: 'drop';
73
+ } | {
74
+ action: 'retry';
75
+ delayMs?: number;
76
+ } | {
77
+ action: 'short-circuit';
78
+ result: FetchResult<unknown, unknown>;
79
+ };
80
+ type InterceptorHandler<T> = (context: T) => MaybePromise<InterceptorDecision<T> | void>;
81
+ type HttpInterceptor = {
82
+ name: string;
83
+ order?: number;
84
+ match?: {
85
+ operation?: string;
86
+ method?: HttpMethod;
87
+ pathPrefix?: string;
88
+ status?: number;
89
+ };
90
+ onRequest?: InterceptorHandler<RequestContext>;
91
+ onRequestError?: InterceptorHandler<RequestContext>;
92
+ onResponse?: InterceptorHandler<RequestContext>;
93
+ onResponseError?: InterceptorHandler<RequestContext>;
94
+ onSseOpen?: InterceptorHandler<RequestContext>;
95
+ onSseEvent?: InterceptorHandler<SseEventContext>;
96
+ onSseError?: InterceptorHandler<RequestContext>;
97
+ onSseReconnect?: InterceptorHandler<RequestContext>;
98
+ };
99
+
100
+ type StatusHandlerInput = {
101
+ status: number;
102
+ error: FetchErrorInfo;
103
+ context: RequestContext;
104
+ };
105
+ type StatusHandlerResult = void | {
106
+ action: 'continue';
107
+ } | {
108
+ action: 'retry';
109
+ delayMs?: number;
110
+ };
111
+ type StatusHandler = (input: StatusHandlerInput) => MaybePromise<StatusHandlerResult>;
112
+ type StatusHandlers = {
113
+ 401?: StatusHandler;
114
+ 403?: StatusHandler;
115
+ 404?: StatusHandler;
116
+ 500?: StatusHandler;
117
+ '4xx'?: StatusHandler;
118
+ '5xx'?: StatusHandler;
119
+ default?: StatusHandler;
120
+ } & {
121
+ [status: number]: StatusHandler | undefined;
122
+ };
123
+ type AuthConfig = {
124
+ /** Return access token (or null/undefined to skip). */
125
+ getToken: () => MaybePromise<string | null | undefined>;
126
+ /** Header name. Default: `authorization`. */
127
+ header?: string;
128
+ /** Prefix before token. Default: `Bearer`. Use `''` for raw token. */
129
+ scheme?: string;
130
+ };
131
+
132
+ type SseEvent<T = unknown> = {
133
+ event?: string;
134
+ data: T;
135
+ id?: string;
136
+ retry?: number;
137
+ };
138
+ type SseSubscription = {
139
+ /** Stop the stream. */
140
+ close: () => void;
141
+ };
142
+ type SseHandlers<T = unknown> = {
143
+ /** Simple path — only the payload. */
144
+ onMessage?: (data: T, event: SseEvent<T>) => void;
145
+ /** Full SSE event (`event`, `data`, `id`). */
146
+ onEvent?: (event: SseEvent<T>) => void;
147
+ onOpen?: () => void;
148
+ onError?: (error: unknown) => void;
149
+ onClose?: () => void;
150
+ };
151
+
152
+ type RequestInterceptorConfig = {
153
+ use?: HttpInterceptor[];
154
+ eject?: string[];
155
+ };
156
+ type RequestOptions = {
157
+ params?: PathParams;
158
+ query?: QueryParams;
159
+ body?: unknown;
160
+ headers?: HeadersInit;
161
+ signal?: AbortSignal;
162
+ timeoutMs?: number;
163
+ /** Default `true` — matches TanStack Query `queryFn` (throw on HTTP error). */
164
+ throwOnError?: boolean;
165
+ parseAs?: 'json' | 'text' | 'blob';
166
+ operation?: string;
167
+ interceptors?: RequestInterceptorConfig;
168
+ };
169
+ type CreateFetchOptions = {
170
+ baseUrl?: string;
171
+ headers?: HeadersInit | (() => MaybePromise<HeadersInit>);
172
+ source?: ClientSource;
173
+ incoming?: IncomingHeaders | (() => MaybePromise<IncomingHeaders>);
174
+ timeoutMs?: number;
175
+ /** Default `true` for TanStack Query. Set `false` to get `FetchResult`. */
176
+ throwOnError?: boolean;
177
+ interceptors?: HttpInterceptor[];
178
+ plugins?: PluginName[];
179
+ fetch?: typeof fetch;
180
+ credentials?: RequestCredentials;
181
+ maxRetries?: number;
182
+ /** Simple auth: attach Bearer token on every request. */
183
+ getToken?: () => MaybePromise<string | null | undefined>;
184
+ /** Advanced auth config (overrides `getToken` when both set via `auth`). */
185
+ auth?: AuthConfig;
186
+ /** Called on HTTP 401 before the error is thrown / returned. */
187
+ onUnauthorized?: StatusHandler;
188
+ /** Called on HTTP 403. */
189
+ onForbidden?: StatusHandler;
190
+ /** Called on HTTP 404. */
191
+ onNotFound?: StatusHandler;
192
+ /** Called on HTTP 5xx (500–599). */
193
+ onServerError?: StatusHandler;
194
+ /** Advanced per-status map (`401`, `403`, `4xx`, `5xx`, `default`, …). */
195
+ onStatus?: StatusHandlers;
196
+ };
197
+ type ThrowingOptions = Omit<RequestOptions, 'throwOnError'> & {
198
+ throwOnError?: true;
199
+ };
200
+ type ResultOptions = Omit<RequestOptions, 'throwOnError'> & {
201
+ throwOnError: false;
202
+ };
203
+ type FetchMethod = {
204
+ <T>(path: string, options?: ThrowingOptions): Promise<T>;
205
+ <T, E = FetchErrorInfo>(path: string, options: ResultOptions): Promise<FetchResult<T, E>>;
206
+ };
207
+ type FetchRequest = {
208
+ <T>(method: HttpMethod, path: string, options?: ThrowingOptions): Promise<T>;
209
+ <T, E = FetchErrorInfo>(method: HttpMethod, path: string, options: ResultOptions): Promise<FetchResult<T, E>>;
210
+ };
211
+ type SseCallOptions<T = unknown> = RequestOptions & SseHandlers<T> & {
212
+ lastEventId?: string;
213
+ };
214
+ type FetchClient = {
215
+ use: (name: string, interceptor: Omit<HttpInterceptor, 'name'> & {
216
+ name?: string;
217
+ }, config?: {
218
+ order?: number;
219
+ }) => void;
220
+ eject: (name: string) => void;
221
+ request: FetchRequest;
222
+ get: FetchMethod;
223
+ post: FetchMethod;
224
+ put: FetchMethod;
225
+ patch: FetchMethod;
226
+ delete: FetchMethod;
227
+ /**
228
+ * Simple: pass `onMessage` / `onEvent` → returns `{ close }`.
229
+ * Advanced: no handlers → `AsyncIterable` for `for await`.
230
+ */
231
+ sse: {
232
+ <T>(path: string, options: SseCallOptions<T> & ({
233
+ onMessage: SseHandlers<T>['onMessage'];
234
+ } | {
235
+ onEvent: SseHandlers<T>['onEvent'];
236
+ })): SseSubscription;
237
+ <T>(path: string, options?: SseCallOptions<T>): AsyncIterable<SseEvent<T>>;
238
+ };
239
+ };
240
+ /** @deprecated Use CreateFetchOptions */
241
+ type CreateClientOptions = CreateFetchOptions;
242
+ /** @deprecated Use FetchClient */
243
+ type HttpClient = FetchClient;
244
+
245
+ type FetchError = Error & {
246
+ readonly name: 'FetchError';
247
+ readonly status: number;
248
+ readonly code: string;
249
+ readonly body: unknown;
250
+ readonly headers: Headers;
251
+ readonly result: FetchResult<never, FetchErrorInfo>;
252
+ };
253
+ declare const createFetchError: (result: FetchResult<never, FetchErrorInfo>) => FetchError;
254
+ declare const isFetchError: (error: unknown) => error is FetchError;
255
+ declare const isAbortError: (error: unknown) => boolean;
256
+
257
+ export { type AuthConfig as A, type CreateFetchOptions as C, type FetchClient as F, type HttpInterceptor as H, type IncomingHeaders as I, type PluginName as P, type RequestContext as R, type StatusHandlers as S, type FetchResult as a, type FetchErrorInfo as b, type CreateClientOptions as c, type FetchError as d, type HttpClient as e, type HttpError as f, type HttpMethod as g, type HttpResult as h, type RequestOptions as i, type SseCallOptions as j, type SseEvent as k, type SseHandlers as l, type SseSubscription as m, type StatusHandler as n, type StatusHandlerInput as o, type StatusHandlerResult as p, createFetchError as q, isAbortError as r, isFetchError as s };