tanstack-fetch 1.0.0 → 1.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.
package/README.md CHANGED
@@ -1,8 +1,13 @@
1
1
  # tanstack-fetch
2
2
 
3
- Typed `fetch` client shaped for **TanStack Query**.
3
+ Typed `fetch` client shaped for **TanStack Query** — tiny HTTP core, optional SSE / React.
4
4
 
5
- `queryFn` / `mutationFn` ready by default: returns **data**, throws **`FetchError`**, passes **`signal`**. Works in browser, SSR, and Edge — with SSE, named interceptors, and OpenAPI codegen.
5
+ | Import | What you get | Typical gzip |
6
+ | --- | --- | --- |
7
+ | `tanstack-fetch` | HTTP only (`get/post/…`) | **~3.5KB** |
8
+ | `tanstack-fetch/sse` | + `api.sse()` | **~4.7KB** |
9
+ | `tanstack-fetch/plugins` | plugin factories | **~0.9KB** |
10
+ | `tanstack-fetch/react` | `FetchProvider` / hooks (peer: core) | **~1KB** |
6
11
 
7
12
  ```bash
8
13
  npm install tanstack-fetch
@@ -14,6 +19,24 @@ Node 18+ (native `fetch`).
14
19
 
15
20
  ---
16
21
 
22
+ ## Bundle size
23
+
24
+ Tree-shake by importing only what you need:
25
+
26
+ ```ts
27
+ // smallest — HTTP for TanStack Query
28
+ import { createFetch } from 'tanstack-fetch'
29
+
30
+ // only when you need streams
31
+ import { createFetch } from 'tanstack-fetch/sse'
32
+ ```
33
+
34
+ `yaml` is an **optional** peer (CLI YAML specs only). React is optional too.
35
+
36
+ Run `npm run size` after build to print local gzip numbers.
37
+
38
+ ---
39
+
17
40
  ## Two ways to configure
18
41
 
19
42
  ### 1) Simple path — `baseUrl`, token, status handlers
@@ -555,6 +578,8 @@ await api.post('/orders', { body: { sku: 'A' } }) // not retried
555
578
  ### `sse-resume`
556
579
 
557
580
  ```ts
581
+ import { createFetch } from 'tanstack-fetch/sse'
582
+
558
583
  const api = createFetch({
559
584
  baseUrl: 'https://api.example.com',
560
585
  plugins: ['sse-resume'],
@@ -703,6 +728,13 @@ Uses `fetch` streams (not `EventSource`) — Authorization, cookies, and SSR wor
703
728
  ### Simple — `onMessage`
704
729
 
705
730
  ```ts
731
+ import { createFetch } from 'tanstack-fetch/sse'
732
+
733
+ const api = createFetch({
734
+ baseUrl: 'https://api.example.com',
735
+ plugins: ['sse-resume'],
736
+ })
737
+
706
738
  const stream = api.sse<OrderEvent>('/orders/stream', {
707
739
  onMessage: (data) => {
708
740
  console.log(data) // just the payload
@@ -716,8 +748,22 @@ stream.close()
716
748
 
717
749
  ### React — `useSse`
718
750
 
751
+ Pass a client created from `tanstack-fetch/sse`:
752
+
719
753
  ```tsx
720
- import { useSse } from 'tanstack-fetch/react'
754
+ import { createFetch } from 'tanstack-fetch/sse'
755
+ import { FetchProvider, useSse } from 'tanstack-fetch/react'
756
+
757
+ const api = createFetch({
758
+ baseUrl: import.meta.env.VITE_API_URL,
759
+ plugins: ['sse-resume'],
760
+ })
761
+
762
+ const App = () => (
763
+ <FetchProvider client={api}>
764
+ <OrdersLive />
765
+ </FetchProvider>
766
+ )
721
767
 
722
768
  const OrdersLive = () => {
723
769
  const { data, isConnected, error } = useSse<OrderEvent>('/orders/stream')
@@ -734,6 +780,10 @@ const OrdersLive = () => {
734
780
  ### Advanced — `for await`
735
781
 
736
782
  ```ts
783
+ import { createFetch } from 'tanstack-fetch/sse'
784
+
785
+ const api = createFetch({ baseUrl: 'https://api.example.com' })
786
+
737
787
  for await (const event of api.sse<OrderEvent>('/orders/stream', { signal })) {
738
788
  event.event
739
789
  event.data
package/dist/cli.js CHANGED
@@ -1,234 +1,35 @@
1
1
  #!/usr/bin/env node
2
-
3
- // src/cli/generate.ts
4
- import { mkdir, writeFile } from "fs/promises";
5
- import { join } from "path";
6
-
7
- // src/cli/schema-to-ts.ts
8
- var toPascal = (value) => value.replace(/[^A-Za-z0-9]+/g, " ").trim().split(" ").filter(Boolean).map((part) => part[0].toUpperCase() + part.slice(1)).join("") || "Schema";
9
- var toCamel = (value) => {
10
- const pascal = toPascal(value);
11
- return pascal[0].toLowerCase() + pascal.slice(1);
12
- };
13
- var refName = (ref) => {
14
- const parts = ref.split("/");
15
- return toPascal(parts[parts.length - 1] ?? "Schema");
16
- };
17
- var schemaToTs = (schema) => {
18
- if (!schema) {
19
- return "unknown";
20
- }
21
- if (schema.$ref) {
22
- return refName(schema.$ref);
23
- }
24
- if (schema.enum && schema.enum.length > 0) {
25
- return schema.enum.map((value) => JSON.stringify(value)).join(" | ");
26
- }
27
- const typeValue = Array.isArray(schema.type) ? schema.type[0] : schema.type;
28
- if (typeValue === "string") {
29
- return "string";
30
- }
31
- if (typeValue === "integer" || typeValue === "number") {
32
- return "number";
33
- }
34
- if (typeValue === "boolean") {
35
- return "boolean";
36
- }
37
- if (typeValue === "array") {
38
- return `Array<${schemaToTs(schema.items)}>`;
39
- }
40
- if (typeValue === "object" || schema.properties) {
41
- return objectToTs(schema);
42
- }
43
- return "unknown";
44
- };
45
- var objectToTs = (schema) => {
46
- const required = new Set(schema.required ?? []);
47
- const fields = Object.entries(schema.properties ?? {}).map(([key, value]) => {
48
- const optional = required.has(key) ? "" : "?";
49
- return ` ${key}${optional}: ${schemaToTs(value)}`;
50
- });
51
- if (fields.length === 0) {
52
- return "Record<string, unknown>";
53
- }
54
- return `{
55
- ${fields.join("\n")}
56
- }`;
57
- };
58
-
59
- // src/cli/collect-operations.ts
60
- var HTTP_METHODS = ["get", "post", "put", "patch", "delete"];
61
- var isSseOperation = (operation) => {
62
- const contents = Object.values(operation.responses ?? {}).flatMap(
63
- (response) => Object.keys(response.content ?? {})
64
- );
65
- return contents.some((type) => type.includes("event-stream"));
66
- };
67
- var collectOperations = (spec) => {
68
- const operations = [];
69
- Object.entries(spec.paths ?? {}).forEach(([path, methods]) => {
70
- HTTP_METHODS.forEach((method) => {
71
- const operation = methods?.[method];
72
- if (!operation) {
73
- return;
74
- }
75
- const tag = operation.tags?.[0] ?? "api";
76
- const fallbackId = `${method}_${path}`;
77
- operations.push({
78
- method: method.toUpperCase(),
79
- path,
80
- operationId: toCamel(operation.operationId ?? fallbackId),
81
- tag: toCamel(tag),
82
- isSse: isSseOperation(operation),
83
- parameters: operation.parameters ?? [],
84
- bodySchema: operation.requestBody?.content?.["application/json"]?.schema,
85
- successSchema: pickSuccessSchema(operation)
86
- });
87
- });
88
- });
89
- return operations;
90
- };
91
- var pickSuccessSchema = (operation) => {
92
- const success = operation.responses?.["200"] ?? operation.responses?.["201"];
93
- const content = success?.content ?? {};
94
- return content["application/json"]?.schema ?? content["text/event-stream"]?.schema;
95
- };
96
-
97
- // src/cli/generate.ts
98
- var generateTypesFile = (spec) => {
99
- const schemas = Object.entries(spec.components?.schemas ?? {});
100
- const types = schemas.map(([name, schema]) => `type ${toPascal(name)} = ${schemaToTs(schema)}`);
101
- const exports = schemas.map(([name]) => toPascal(name));
102
- if (exports.length === 0) {
103
- return "export {}\n";
104
- }
105
- const body = `${types.join("\n\n")}
106
-
107
- export type { ${exports.join(", ")} }
108
- `;
109
- return body.trimStart();
110
- };
111
- var paramsType = (operation, kind) => {
112
- const params = operation.parameters.filter((item) => item.in === kind);
113
- if (params.length === 0) {
114
- return void 0;
115
- }
116
- const fields = params.map((item) => {
117
- const optional = item.required ? "" : "?";
118
- return `${item.name}${optional}: ${schemaToTs(item.schema)}`;
119
- });
120
- return `{ ${fields.join("; ")} }`;
121
- };
122
- var optionsType = (operation) => {
123
- const fields = [];
124
- const pathType = paramsType(operation, "path");
125
- const queryType = paramsType(operation, "query");
126
- if (pathType) {
127
- fields.push(`params: ${pathType}`);
128
- }
129
- if (queryType) {
130
- fields.push(`query?: ${queryType}`);
131
- }
132
- if (operation.bodySchema) {
133
- fields.push(`body: ${schemaToTs(operation.bodySchema)}`);
134
- }
135
- if (fields.length === 0) {
136
- return "RequestOptions | undefined";
137
- }
138
- return `Omit<RequestOptions, 'params' | 'query' | 'body'> & { ${fields.join("; ")} }`;
139
- };
140
- var clientPath = (path) => path.replace(/\{([A-Za-z0-9_]+)\}/g, ":$1");
141
- var methodLine = (operation) => {
142
- const response = schemaToTs(operation.successSchema);
143
- const options = optionsType(operation);
144
- const optional = options.endsWith("| undefined") ? "?" : "";
145
- if (operation.isSse) {
146
- return ` ${operation.operationId}: (options${optional}: ${options}) => api.sse<${response}>('${clientPath(operation.path)}', options),`;
147
- }
148
- const method = operation.method.toLowerCase();
149
- const call = method === "delete" ? "delete" : method;
150
- return ` ${operation.operationId}: (options${optional}: ${options}) => api.${call}<${response}>('${clientPath(operation.path)}', options),`;
151
- };
152
- var generateClientFile = (spec, operations) => {
153
- const tags = [...new Set(operations.map((item) => item.tag))];
154
- const groups = tags.map((tag) => {
155
- const lines = operations.filter((item) => item.tag === tag).map(methodLine);
156
- return ` ${tag}: {
157
- ${lines.join("\n")}
158
- },`;
159
- });
160
- const schemaNames = Object.keys(spec.components?.schemas ?? {}).map((name) => toPascal(name));
161
- const typesImport = schemaNames.length > 0 ? `import type { ${schemaNames.join(", ")} } from './types'
162
- ` : "";
163
- return `import { createFetch } from 'tanstack-fetch'
164
- import type { CreateFetchOptions, RequestOptions } from 'tanstack-fetch'
165
- ${typesImport}
2
+ import{mkdir as T,writeFile as f}from"fs/promises";import{join as h}from"path";var i=e=>e.replace(/[^A-Za-z0-9]+/g," ").trim().split(" ").filter(Boolean).map(t=>t[0].toUpperCase()+t.slice(1)).join("")||"Schema",u=e=>{let t=i(e);return t[0].toLowerCase()+t.slice(1)},k=e=>{let t=e.split("/");return i(t[t.length-1]??"Schema")},p=e=>{if(!e)return"unknown";if(e.$ref)return k(e.$ref);if(e.enum&&e.enum.length>0)return e.enum.map(n=>JSON.stringify(n)).join(" | ");let t=Array.isArray(e.type)?e.type[0]:e.type;return t==="string"?"string":t==="integer"||t==="number"?"number":t==="boolean"?"boolean":t==="array"?`Array<${p(e.items)}>`:t==="object"||e.properties?C(e):"unknown"},C=e=>{let t=new Set(e.required??[]),n=Object.entries(e.properties??{}).map(([r,s])=>{let o=t.has(r)?"":"?";return` ${r}${o}: ${p(s)}`});return n.length===0?"Record<string, unknown>":`{
3
+ ${n.join(`
4
+ `)}
5
+ }`};var j=["get","post","put","patch","delete"],b=e=>Object.values(e.responses??{}).flatMap(n=>Object.keys(n.content??{})).some(n=>n.includes("event-stream")),d=e=>{let t=[];return Object.entries(e.paths??{}).forEach(([n,r])=>{j.forEach(s=>{let o=r?.[s];if(!o)return;let a=o.tags?.[0]??"api",m=`${s}_${n}`;t.push({method:s.toUpperCase(),path:n,operationId:u(o.operationId??m),tag:u(a),isSse:b(o),parameters:o.parameters??[],bodySchema:o.requestBody?.content?.["application/json"]?.schema,successSchema:x(o)})})}),t},x=e=>{let n=(e.responses?.["200"]??e.responses?.["201"])?.content??{};return n["application/json"]?.schema??n["text/event-stream"]?.schema};var q=e=>{let t=Object.entries(e.components?.schemas??{}),n=t.map(([o,a])=>`type ${i(o)} = ${p(a)}`),r=t.map(([o])=>i(o));return r.length===0?`export {}
6
+ `:`${n.join(`
7
+
8
+ `)}
9
+
10
+ export type { ${r.join(", ")} }
11
+ `.trimStart()},g=(e,t)=>{let n=e.parameters.filter(s=>s.in===t);return n.length===0?void 0:`{ ${n.map(s=>{let o=s.required?"":"?";return`${s.name}${o}: ${p(s.schema)}`}).join("; ")} }`},F=e=>{let t=[],n=g(e,"path"),r=g(e,"query");return n&&t.push(`params: ${n}`),r&&t.push(`query?: ${r}`),e.bodySchema&&t.push(`body: ${p(e.bodySchema)}`),t.length===0?"RequestOptions | undefined":`Omit<RequestOptions, 'params' | 'query' | 'body'> & { ${t.join("; ")} }`},y=e=>e.replace(/\{([A-Za-z0-9_]+)\}/g,":$1"),I=e=>{let t=p(e.successSchema),n=F(e),r=n.endsWith("| undefined")?"?":"";if(e.isSse)return` ${e.operationId}: (options${r}: ${n}) => api.sse<${t}>('${y(e.path)}', options),`;let s=e.method.toLowerCase(),o=s==="delete"?"delete":s;return` ${e.operationId}: (options${r}: ${n}) => api.${o}<${t}>('${y(e.path)}', options),`},E=(e,t)=>{let r=[...new Set(t.map(c=>c.tag))].map(c=>{let l=t.filter(A=>A.tag===c).map(I);return` ${c}: {
12
+ ${l.join(`
13
+ `)}
14
+ },`}),s=Object.keys(e.components?.schemas??{}).map(c=>i(c)),o=s.length>0?`import type { ${s.join(", ")} } from './types'
15
+ `:"";return`${t.some(c=>c.isSse)?`import { createFetch } from 'tanstack-fetch/sse'
16
+ import type { CreateFetchOptions, RequestOptions } from 'tanstack-fetch'`:`import { createFetch } from 'tanstack-fetch'
17
+ import type { CreateFetchOptions, RequestOptions } from 'tanstack-fetch'`}
18
+ ${o}
166
19
  const createApi = (options: CreateFetchOptions = {}) => {
167
20
  const api = createFetch(options)
168
21
  return {
169
- ${groups.join("\n")}
22
+ ${r.join(`
23
+ `)}
170
24
  }
171
25
  }
172
26
 
173
27
  export { createApi }
174
- `;
175
- };
176
- var generateIndexFile = () => `import { createApi } from './client'
28
+ `},J=()=>`import { createApi } from './client'
177
29
 
178
30
  export { createApi }
179
31
  export type * from './types'
180
- `;
181
- var generateClient = async (spec, outDir) => {
182
- const operations = collectOperations(spec);
183
- await mkdir(outDir, { recursive: true });
184
- await writeFile(join(outDir, "types.ts"), generateTypesFile(spec), "utf8");
185
- await writeFile(join(outDir, "client.ts"), generateClientFile(spec, operations), "utf8");
186
- await writeFile(join(outDir, "index.ts"), generateIndexFile(), "utf8");
187
- };
188
-
189
- // src/cli/load-spec.ts
190
- import { readFile } from "fs/promises";
191
- import { parse as parseYaml } from "yaml";
192
- var loadSpec = async (specPath) => {
193
- const raw = await readFile(specPath, "utf8");
194
- const parsed = specPath.endsWith(".yaml") || specPath.endsWith(".yml") ? parseYaml(raw) : JSON.parse(raw);
195
- if (!parsed || typeof parsed !== "object") {
196
- throw new Error("tanstack-fetch: OpenAPI spec must be an object");
197
- }
198
- return parsed;
199
- };
200
-
201
- // src/cli/parse-args.ts
202
- var parseArgs = (argv) => {
203
- const [command, ...rest] = argv;
204
- if (!command || command === "--help" || command === "help" || command === "-h") {
205
- return { command: "help" };
206
- }
207
- if (command !== "generate") {
208
- throw new Error(`tanstack-fetch: unknown command "${command}"`);
209
- }
210
- const flags = /* @__PURE__ */ new Map();
211
- for (let index = 0; index < rest.length; index += 1) {
212
- const token = rest[index];
213
- if (!token.startsWith("--")) {
214
- continue;
215
- }
216
- const key = token.slice(2);
217
- const value = rest[index + 1];
218
- if (!value || value.startsWith("--")) {
219
- throw new Error(`tanstack-fetch: missing value for --${key}`);
220
- }
221
- flags.set(key, value);
222
- index += 1;
223
- }
224
- const spec = flags.get("spec");
225
- const out = flags.get("out");
226
- if (!spec || !out) {
227
- throw new Error("tanstack-fetch: generate requires --spec and --out");
228
- }
229
- return { command: "generate", spec, out };
230
- };
231
- var helpText = `tanstack-fetch
32
+ `,O=async(e,t)=>{let n=d(e);await T(t,{recursive:!0}),await f(h(t,"types.ts"),q(e),"utf8"),await f(h(t,"client.ts"),E(e,n),"utf8"),await f(h(t,"index.ts"),J(),"utf8")};import{readFile as v}from"fs/promises";var L=async e=>{try{return(await import("yaml")).parse(e)}catch{throw new Error('tanstack-fetch: install optional peer "yaml" to load YAML specs (npm i yaml)')}},$=async e=>{let t=await v(e,"utf8"),n=e.endsWith(".yaml")||e.endsWith(".yml")?await L(t):JSON.parse(t);if(!n||typeof n!="object")throw new Error("tanstack-fetch: OpenAPI spec must be an object");return n};var S=e=>{let[t,...n]=e;if(!t||t==="--help"||t==="help"||t==="-h")return{command:"help"};if(t!=="generate")throw new Error(`tanstack-fetch: unknown command "${t}"`);let r=new Map;for(let a=0;a<n.length;a+=1){let m=n[a];if(!m.startsWith("--"))continue;let c=m.slice(2),l=n[a+1];if(!l||l.startsWith("--"))throw new Error(`tanstack-fetch: missing value for --${c}`);r.set(c,l),a+=1}let s=r.get("spec"),o=r.get("out");if(!s||!o)throw new Error("tanstack-fetch: generate requires --spec and --out");return{command:"generate",spec:s,out:o}},w=`tanstack-fetch
232
33
 
233
34
  Usage:
234
35
  tanstack-fetch generate --spec ./openapi.json --out ./src/api
@@ -236,22 +37,4 @@ Usage:
236
37
  Flags:
237
38
  --spec OpenAPI/Swagger JSON or YAML file
238
39
  --out Directory for generated client files
239
- `;
240
-
241
- // src/cli/index.ts
242
- var runCli = async (argv = process.argv.slice(2)) => {
243
- const args = parseArgs(argv);
244
- if (args.command === "help") {
245
- console.log(helpText);
246
- return;
247
- }
248
- const spec = await loadSpec(args.spec);
249
- await generateClient(spec, args.out);
250
- console.log(`tanstack-fetch: generated client in ${args.out}`);
251
- };
252
- runCli().catch((error) => {
253
- const message = error instanceof Error ? error.message : "Unknown CLI error";
254
- console.error(message);
255
- process.exitCode = 1;
256
- });
257
- //# sourceMappingURL=cli.js.map
40
+ `;var P=async(e=process.argv.slice(2))=>{let t=S(e);if(t.command==="help"){console.log(w);return}let n=await $(t.spec);await O(n,t.out),console.log(`tanstack-fetch: generated client in ${t.out}`)};P().catch(e=>{let t=e instanceof Error?e.message:"Unknown CLI error";console.error(t),process.exitCode=1});
@@ -0,0 +1,116 @@
1
+ import { M as MaybePromise, C as ClientSource, I as IncomingHeaders, b as HttpInterceptor, P as PluginName, A as AuthConfig, S as StatusHandler, g as StatusHandlers, c as HttpMethod, h as PathParams, Q as QueryParams, a as FetchErrorInfo, F as FetchResult } from './config.type-eG_cuxpu.cjs';
2
+
3
+ type SseEvent<T = unknown> = {
4
+ event?: string;
5
+ data: T;
6
+ id?: string;
7
+ retry?: number;
8
+ };
9
+ type SseSubscription = {
10
+ /** Stop the stream. */
11
+ close: () => void;
12
+ };
13
+ type SseHandlers<T = unknown> = {
14
+ /** Simple path — only the payload. */
15
+ onMessage?: (data: T, event: SseEvent<T>) => void;
16
+ /** Full SSE event (`event`, `data`, `id`). */
17
+ onEvent?: (event: SseEvent<T>) => void;
18
+ onOpen?: () => void;
19
+ onError?: (error: unknown) => void;
20
+ onClose?: () => void;
21
+ };
22
+
23
+ type RequestInterceptorConfig = {
24
+ use?: HttpInterceptor[];
25
+ eject?: string[];
26
+ };
27
+ type RequestOptions = {
28
+ params?: PathParams;
29
+ query?: QueryParams;
30
+ body?: unknown;
31
+ headers?: HeadersInit;
32
+ signal?: AbortSignal;
33
+ timeoutMs?: number;
34
+ /** Default `true` — matches TanStack Query `queryFn` (throw on HTTP error). */
35
+ throwOnError?: boolean;
36
+ parseAs?: 'json' | 'text' | 'blob';
37
+ operation?: string;
38
+ interceptors?: RequestInterceptorConfig;
39
+ };
40
+ type CreateFetchOptions = {
41
+ baseUrl?: string;
42
+ headers?: HeadersInit | (() => MaybePromise<HeadersInit>);
43
+ source?: ClientSource;
44
+ incoming?: IncomingHeaders | (() => MaybePromise<IncomingHeaders>);
45
+ timeoutMs?: number;
46
+ /** Default `true` for TanStack Query. Set `false` to get `FetchResult`. */
47
+ throwOnError?: boolean;
48
+ interceptors?: HttpInterceptor[];
49
+ plugins?: PluginName[];
50
+ fetch?: typeof fetch;
51
+ credentials?: RequestCredentials;
52
+ maxRetries?: number;
53
+ /** Simple auth: attach Bearer token on every request. */
54
+ getToken?: () => MaybePromise<string | null | undefined>;
55
+ /** Advanced auth config (overrides `getToken` when both set via `auth`). */
56
+ auth?: AuthConfig;
57
+ /** Called on HTTP 401 before the error is thrown / returned. */
58
+ onUnauthorized?: StatusHandler;
59
+ /** Called on HTTP 403. */
60
+ onForbidden?: StatusHandler;
61
+ /** Called on HTTP 404. */
62
+ onNotFound?: StatusHandler;
63
+ /** Called on HTTP 5xx (500–599). */
64
+ onServerError?: StatusHandler;
65
+ /** Advanced per-status map (`401`, `403`, `4xx`, `5xx`, `default`, …). */
66
+ onStatus?: StatusHandlers;
67
+ };
68
+ type ThrowingOptions = Omit<RequestOptions, 'throwOnError'> & {
69
+ throwOnError?: true;
70
+ };
71
+ type ResultOptions = Omit<RequestOptions, 'throwOnError'> & {
72
+ throwOnError: false;
73
+ };
74
+ type FetchMethod = {
75
+ <T>(path: string, options?: ThrowingOptions): Promise<T>;
76
+ <T, E = FetchErrorInfo>(path: string, options: ResultOptions): Promise<FetchResult<T, E>>;
77
+ };
78
+ type FetchRequest = {
79
+ <T>(method: HttpMethod, path: string, options?: ThrowingOptions): Promise<T>;
80
+ <T, E = FetchErrorInfo>(method: HttpMethod, path: string, options: ResultOptions): Promise<FetchResult<T, E>>;
81
+ };
82
+ type SseCallOptions<T = unknown> = RequestOptions & SseHandlers<T> & {
83
+ lastEventId?: string;
84
+ };
85
+ type FetchClient = {
86
+ use: (name: string, interceptor: Omit<HttpInterceptor, 'name'> & {
87
+ name?: string;
88
+ }, config?: {
89
+ order?: number;
90
+ }) => void;
91
+ eject: (name: string) => void;
92
+ request: FetchRequest;
93
+ get: FetchMethod;
94
+ post: FetchMethod;
95
+ put: FetchMethod;
96
+ patch: FetchMethod;
97
+ delete: FetchMethod;
98
+ /**
99
+ * Simple: pass `onMessage` / `onEvent` → returns `{ close }`.
100
+ * Advanced: no handlers → `AsyncIterable` for `for await`.
101
+ */
102
+ sse: {
103
+ <T>(path: string, options: SseCallOptions<T> & ({
104
+ onMessage: SseHandlers<T>['onMessage'];
105
+ } | {
106
+ onEvent: SseHandlers<T>['onEvent'];
107
+ })): SseSubscription;
108
+ <T>(path: string, options?: SseCallOptions<T>): AsyncIterable<SseEvent<T>>;
109
+ };
110
+ };
111
+ /** @deprecated Use CreateFetchOptions */
112
+ type CreateClientOptions = CreateFetchOptions;
113
+ /** @deprecated Use FetchClient */
114
+ type HttpClient = FetchClient;
115
+
116
+ export type { CreateFetchOptions as C, FetchClient as F, HttpClient as H, RequestOptions as R, SseCallOptions as S, CreateClientOptions as a, SseEvent as b, SseHandlers as c, SseSubscription as d };
@@ -0,0 +1,116 @@
1
+ import { M as MaybePromise, C as ClientSource, I as IncomingHeaders, b as HttpInterceptor, P as PluginName, A as AuthConfig, S as StatusHandler, g as StatusHandlers, c as HttpMethod, h as PathParams, Q as QueryParams, a as FetchErrorInfo, F as FetchResult } from './config.type-eG_cuxpu.js';
2
+
3
+ type SseEvent<T = unknown> = {
4
+ event?: string;
5
+ data: T;
6
+ id?: string;
7
+ retry?: number;
8
+ };
9
+ type SseSubscription = {
10
+ /** Stop the stream. */
11
+ close: () => void;
12
+ };
13
+ type SseHandlers<T = unknown> = {
14
+ /** Simple path — only the payload. */
15
+ onMessage?: (data: T, event: SseEvent<T>) => void;
16
+ /** Full SSE event (`event`, `data`, `id`). */
17
+ onEvent?: (event: SseEvent<T>) => void;
18
+ onOpen?: () => void;
19
+ onError?: (error: unknown) => void;
20
+ onClose?: () => void;
21
+ };
22
+
23
+ type RequestInterceptorConfig = {
24
+ use?: HttpInterceptor[];
25
+ eject?: string[];
26
+ };
27
+ type RequestOptions = {
28
+ params?: PathParams;
29
+ query?: QueryParams;
30
+ body?: unknown;
31
+ headers?: HeadersInit;
32
+ signal?: AbortSignal;
33
+ timeoutMs?: number;
34
+ /** Default `true` — matches TanStack Query `queryFn` (throw on HTTP error). */
35
+ throwOnError?: boolean;
36
+ parseAs?: 'json' | 'text' | 'blob';
37
+ operation?: string;
38
+ interceptors?: RequestInterceptorConfig;
39
+ };
40
+ type CreateFetchOptions = {
41
+ baseUrl?: string;
42
+ headers?: HeadersInit | (() => MaybePromise<HeadersInit>);
43
+ source?: ClientSource;
44
+ incoming?: IncomingHeaders | (() => MaybePromise<IncomingHeaders>);
45
+ timeoutMs?: number;
46
+ /** Default `true` for TanStack Query. Set `false` to get `FetchResult`. */
47
+ throwOnError?: boolean;
48
+ interceptors?: HttpInterceptor[];
49
+ plugins?: PluginName[];
50
+ fetch?: typeof fetch;
51
+ credentials?: RequestCredentials;
52
+ maxRetries?: number;
53
+ /** Simple auth: attach Bearer token on every request. */
54
+ getToken?: () => MaybePromise<string | null | undefined>;
55
+ /** Advanced auth config (overrides `getToken` when both set via `auth`). */
56
+ auth?: AuthConfig;
57
+ /** Called on HTTP 401 before the error is thrown / returned. */
58
+ onUnauthorized?: StatusHandler;
59
+ /** Called on HTTP 403. */
60
+ onForbidden?: StatusHandler;
61
+ /** Called on HTTP 404. */
62
+ onNotFound?: StatusHandler;
63
+ /** Called on HTTP 5xx (500–599). */
64
+ onServerError?: StatusHandler;
65
+ /** Advanced per-status map (`401`, `403`, `4xx`, `5xx`, `default`, …). */
66
+ onStatus?: StatusHandlers;
67
+ };
68
+ type ThrowingOptions = Omit<RequestOptions, 'throwOnError'> & {
69
+ throwOnError?: true;
70
+ };
71
+ type ResultOptions = Omit<RequestOptions, 'throwOnError'> & {
72
+ throwOnError: false;
73
+ };
74
+ type FetchMethod = {
75
+ <T>(path: string, options?: ThrowingOptions): Promise<T>;
76
+ <T, E = FetchErrorInfo>(path: string, options: ResultOptions): Promise<FetchResult<T, E>>;
77
+ };
78
+ type FetchRequest = {
79
+ <T>(method: HttpMethod, path: string, options?: ThrowingOptions): Promise<T>;
80
+ <T, E = FetchErrorInfo>(method: HttpMethod, path: string, options: ResultOptions): Promise<FetchResult<T, E>>;
81
+ };
82
+ type SseCallOptions<T = unknown> = RequestOptions & SseHandlers<T> & {
83
+ lastEventId?: string;
84
+ };
85
+ type FetchClient = {
86
+ use: (name: string, interceptor: Omit<HttpInterceptor, 'name'> & {
87
+ name?: string;
88
+ }, config?: {
89
+ order?: number;
90
+ }) => void;
91
+ eject: (name: string) => void;
92
+ request: FetchRequest;
93
+ get: FetchMethod;
94
+ post: FetchMethod;
95
+ put: FetchMethod;
96
+ patch: FetchMethod;
97
+ delete: FetchMethod;
98
+ /**
99
+ * Simple: pass `onMessage` / `onEvent` → returns `{ close }`.
100
+ * Advanced: no handlers → `AsyncIterable` for `for await`.
101
+ */
102
+ sse: {
103
+ <T>(path: string, options: SseCallOptions<T> & ({
104
+ onMessage: SseHandlers<T>['onMessage'];
105
+ } | {
106
+ onEvent: SseHandlers<T>['onEvent'];
107
+ })): SseSubscription;
108
+ <T>(path: string, options?: SseCallOptions<T>): AsyncIterable<SseEvent<T>>;
109
+ };
110
+ };
111
+ /** @deprecated Use CreateFetchOptions */
112
+ type CreateClientOptions = CreateFetchOptions;
113
+ /** @deprecated Use FetchClient */
114
+ type HttpClient = FetchClient;
115
+
116
+ export type { CreateFetchOptions as C, FetchClient as F, HttpClient as H, RequestOptions as R, SseCallOptions as S, CreateClientOptions as a, SseEvent as b, SseHandlers as c, SseSubscription as d };