@spoosh/core 0.10.1 → 0.11.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 +13 -54
- package/dist/index.d.mts +60 -80
- package/dist/index.d.ts +60 -80
- package/dist/index.js +37 -90
- package/dist/index.mjs +37 -90
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -47,8 +47,11 @@ type ApiSchema = {
|
|
|
47
47
|
```typescript
|
|
48
48
|
import { createClient } from "@spoosh/core";
|
|
49
49
|
|
|
50
|
-
const api = createClient<ApiSchema>(
|
|
51
|
-
|
|
50
|
+
const api = createClient<ApiSchema>("/api");
|
|
51
|
+
|
|
52
|
+
// With custom options
|
|
53
|
+
const apiWithAuth = createClient<ApiSchema>("/api", {
|
|
54
|
+
headers: { Authorization: "Bearer token" },
|
|
52
55
|
});
|
|
53
56
|
|
|
54
57
|
// Import body wrappers for explicit serialization
|
|
@@ -115,7 +118,7 @@ When using `createClient`, Next.js cache tags are automatically generated from t
|
|
|
115
118
|
// Server component
|
|
116
119
|
import { createClient } from "@spoosh/core";
|
|
117
120
|
|
|
118
|
-
const api = createClient<ApiSchema>(
|
|
121
|
+
const api = createClient<ApiSchema>(process.env.API_URL!);
|
|
119
122
|
|
|
120
123
|
// Auto-generates next: { tags: ['posts'] }
|
|
121
124
|
const { data: posts } = await api("posts").GET();
|
|
@@ -128,51 +131,6 @@ const { data: userPosts } = await api("users/:id/posts").GET({
|
|
|
128
131
|
|
|
129
132
|
This enables automatic cache invalidation with `revalidateTag()` in Next.js.
|
|
130
133
|
|
|
131
|
-
### With Middlewares
|
|
132
|
-
|
|
133
|
-
```typescript
|
|
134
|
-
import { createClient, createMiddleware } from "@spoosh/core";
|
|
135
|
-
|
|
136
|
-
const authMiddleware = createMiddleware("auth", "before", async (ctx) => {
|
|
137
|
-
ctx.requestOptions = {
|
|
138
|
-
...ctx.requestOptions,
|
|
139
|
-
headers: { Authorization: `Bearer ${token}` },
|
|
140
|
-
};
|
|
141
|
-
return ctx;
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
const api = createClient<ApiSchema>({
|
|
145
|
-
baseUrl: "/api",
|
|
146
|
-
middlewares: [authMiddleware],
|
|
147
|
-
});
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
### Middleware Utilities
|
|
151
|
-
|
|
152
|
-
```typescript
|
|
153
|
-
import {
|
|
154
|
-
createMiddleware,
|
|
155
|
-
applyMiddlewares,
|
|
156
|
-
composeMiddlewares,
|
|
157
|
-
} from "@spoosh/core";
|
|
158
|
-
|
|
159
|
-
// createMiddleware(name, phase, handler) - Create a named middleware
|
|
160
|
-
const logMiddleware = createMiddleware("logger", "after", async (ctx) => {
|
|
161
|
-
console.log(ctx.response?.status);
|
|
162
|
-
return ctx;
|
|
163
|
-
});
|
|
164
|
-
|
|
165
|
-
// composeMiddlewares(...lists) - Combine multiple middleware arrays
|
|
166
|
-
const allMiddlewares = composeMiddlewares(
|
|
167
|
-
[authMiddleware],
|
|
168
|
-
[logMiddleware],
|
|
169
|
-
conditionalMiddlewares
|
|
170
|
-
);
|
|
171
|
-
|
|
172
|
-
// applyMiddlewares(context, middlewares, phase) - Run middlewares for a phase
|
|
173
|
-
const updatedContext = await applyMiddlewares(context, middlewares, "before");
|
|
174
|
-
```
|
|
175
|
-
|
|
176
134
|
## Schema Types
|
|
177
135
|
|
|
178
136
|
| Field | Description | Example |
|
|
@@ -186,15 +144,16 @@ Path parameters are defined using `:param` syntax in the path key (e.g., `"users
|
|
|
186
144
|
|
|
187
145
|
## API Reference
|
|
188
146
|
|
|
189
|
-
### createClient(
|
|
147
|
+
### createClient(baseUrl, defaultOptions?)
|
|
190
148
|
|
|
191
149
|
Creates a lightweight type-safe API instance.
|
|
192
150
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
|
196
|
-
|
|
|
197
|
-
| `
|
|
151
|
+
**Parameters:**
|
|
152
|
+
|
|
153
|
+
| Parameter | Type | Description |
|
|
154
|
+
| ---------------- | ------------- | ------------------------------------------------------------- |
|
|
155
|
+
| `baseUrl` | `string` | Base URL for all API requests |
|
|
156
|
+
| `defaultOptions` | `RequestInit` | (Optional) Default fetch options (headers, credentials, etc.) |
|
|
198
157
|
|
|
199
158
|
### Spoosh (class)
|
|
200
159
|
|
package/dist/index.d.mts
CHANGED
|
@@ -4,24 +4,6 @@ type Simplify<T> = {
|
|
|
4
4
|
[K in keyof T]: T[K];
|
|
5
5
|
} & {};
|
|
6
6
|
|
|
7
|
-
type MiddlewarePhase = "before" | "after";
|
|
8
|
-
type MiddlewareContext<TData = unknown, TError = unknown> = {
|
|
9
|
-
baseUrl: string;
|
|
10
|
-
path: string[];
|
|
11
|
-
method: HttpMethod;
|
|
12
|
-
defaultOptions: SpooshOptions & SpooshOptionsExtra;
|
|
13
|
-
requestOptions?: AnyRequestOptions;
|
|
14
|
-
fetchInit?: RequestInit;
|
|
15
|
-
response?: SpooshResponse<TData, TError>;
|
|
16
|
-
metadata: Record<string, unknown>;
|
|
17
|
-
};
|
|
18
|
-
type MiddlewareHandler<TData = unknown, TError = unknown> = (context: MiddlewareContext<TData, TError>) => MiddlewareContext<TData, TError> | Promise<MiddlewareContext<TData, TError>>;
|
|
19
|
-
type SpooshMiddleware<TData = unknown, TError = unknown> = {
|
|
20
|
-
name: string;
|
|
21
|
-
phase: MiddlewarePhase;
|
|
22
|
-
handler: MiddlewareHandler<TData, TError>;
|
|
23
|
-
};
|
|
24
|
-
|
|
25
7
|
type QueryField<TQuery> = [TQuery] extends [never] ? object : {
|
|
26
8
|
query: TQuery;
|
|
27
9
|
};
|
|
@@ -54,15 +36,25 @@ type SpooshResponse<TData, TError, TRequestOptions = unknown, TQuery = never, TB
|
|
|
54
36
|
aborted?: boolean;
|
|
55
37
|
readonly __requestOptions?: TRequestOptions;
|
|
56
38
|
} & InputFieldWrapper<TQuery, TBody, TParamNames>);
|
|
57
|
-
type SpooshOptionsExtra<TData = unknown, TError = unknown> = {
|
|
58
|
-
middlewares?: SpooshMiddleware<TData, TError>[];
|
|
59
|
-
};
|
|
60
39
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
40
|
+
/**
|
|
41
|
+
* Opaque type representing a transformed body. Create using `form()`, `json()`, or `urlencoded()` helpers.
|
|
42
|
+
* Do not create this type manually - use the helper functions instead.
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```ts
|
|
46
|
+
* import { form, json, urlencoded } from "@spoosh/core";
|
|
47
|
+
*
|
|
48
|
+
* // Use helpers to create SpooshBody
|
|
49
|
+
* trigger({ body: form({ file: myFile }) });
|
|
50
|
+
* trigger({ body: json({ data: "value" }) });
|
|
51
|
+
* trigger({ body: urlencoded({ key: "value" }) });
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
declare class SpooshBodyClass<T> {
|
|
55
|
+
private __brand;
|
|
56
|
+
}
|
|
57
|
+
type SpooshBody<T = unknown> = SpooshBodyClass<T>;
|
|
66
58
|
declare function isSpooshBody(value: unknown): value is SpooshBody;
|
|
67
59
|
declare function form<T>(value: T): SpooshBody<T>;
|
|
68
60
|
declare function json<T>(value: T): SpooshBody<T>;
|
|
@@ -231,7 +223,7 @@ type CacheEntryWithKey<TData = unknown, TError = unknown> = {
|
|
|
231
223
|
declare function createInitialState<TData, TError>(): OperationState<TData, TError>;
|
|
232
224
|
type StateManager = {
|
|
233
225
|
createQueryKey: (params: {
|
|
234
|
-
path: string
|
|
226
|
+
path: string;
|
|
235
227
|
method: string;
|
|
236
228
|
options?: unknown;
|
|
237
229
|
}) => string;
|
|
@@ -249,6 +241,8 @@ type StateManager = {
|
|
|
249
241
|
getAllCacheEntries: <TData, TError>() => CacheEntryWithKey<TData, TError>[];
|
|
250
242
|
/** Get the number of cache entries */
|
|
251
243
|
getSize: () => number;
|
|
244
|
+
/** Get the number of active subscribers for a cache key */
|
|
245
|
+
getSubscribersCount: (key: string) => number;
|
|
252
246
|
/** Set a pending promise for a query key (for deduplication) */
|
|
253
247
|
setPendingPromise: (key: string, promise: Promise<unknown> | undefined) => void;
|
|
254
248
|
/** Get a pending promise for a query key */
|
|
@@ -275,9 +269,13 @@ type CacheEntry<TData = unknown, TError = unknown> = {
|
|
|
275
269
|
/** Cache was invalidated while no subscriber was listening. Triggers refetch on next mount. */
|
|
276
270
|
stale?: boolean;
|
|
277
271
|
};
|
|
278
|
-
|
|
272
|
+
/** RequestOptions in plugin context have headers already resolved to Record */
|
|
273
|
+
type PluginRequestOptions = Omit<AnyRequestOptions, "headers"> & {
|
|
274
|
+
headers: Record<string, string>;
|
|
275
|
+
};
|
|
276
|
+
type PluginContext = {
|
|
279
277
|
readonly operationType: OperationType;
|
|
280
|
-
readonly path: string
|
|
278
|
+
readonly path: string;
|
|
281
279
|
readonly method: HttpMethod;
|
|
282
280
|
readonly queryKey: string;
|
|
283
281
|
readonly tags: string[];
|
|
@@ -285,17 +283,10 @@ type PluginContext<TData = unknown, TError = unknown> = {
|
|
|
285
283
|
readonly requestTimestamp: number;
|
|
286
284
|
/** Unique identifier for the hook instance. Persists across queryKey changes within the same hook. */
|
|
287
285
|
readonly hookId?: string;
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
response?: SpooshResponse<TData, TError>;
|
|
291
|
-
metadata: Map<string, unknown>;
|
|
292
|
-
abort: () => void;
|
|
286
|
+
request: PluginRequestOptions;
|
|
287
|
+
temp: Map<string, unknown>;
|
|
293
288
|
stateManager: StateManager;
|
|
294
289
|
eventEmitter: EventEmitter;
|
|
295
|
-
/** Resolved headers as a plain object. Modify via setHeaders(). */
|
|
296
|
-
headers: Record<string, string>;
|
|
297
|
-
/** Add/update headers. Merges with existing headers. */
|
|
298
|
-
setHeaders: (headers: Record<string, string>) => void;
|
|
299
290
|
/** Access other plugins' exported APIs */
|
|
300
291
|
plugins: PluginAccessor;
|
|
301
292
|
/** Plugin-specific options passed from hooks (useRead/useWrite/useInfiniteRead) */
|
|
@@ -304,7 +295,7 @@ type PluginContext<TData = unknown, TError = unknown> = {
|
|
|
304
295
|
forceRefetch?: boolean;
|
|
305
296
|
};
|
|
306
297
|
/** Input type for creating PluginContext (without injected properties) */
|
|
307
|
-
type PluginContextInput
|
|
298
|
+
type PluginContextInput = Omit<PluginContext, "plugins">;
|
|
308
299
|
/**
|
|
309
300
|
* Middleware function that wraps the fetch flow.
|
|
310
301
|
* Plugins use this for full control over request/response handling.
|
|
@@ -334,22 +325,22 @@ type PluginContextInput<TData = unknown, TError = unknown> = Omit<PluginContext<
|
|
|
334
325
|
* }
|
|
335
326
|
* ```
|
|
336
327
|
*/
|
|
337
|
-
type PluginMiddleware
|
|
338
|
-
type PluginHandler
|
|
339
|
-
type PluginUpdateHandler
|
|
328
|
+
type PluginMiddleware = (context: PluginContext, next: () => Promise<SpooshResponse<any, any>>) => Promise<SpooshResponse<any, any>>;
|
|
329
|
+
type PluginHandler = (context: PluginContext) => void | Promise<void>;
|
|
330
|
+
type PluginUpdateHandler = (context: PluginContext, previousContext: PluginContext) => void | Promise<void>;
|
|
340
331
|
/**
|
|
341
332
|
* Handler called after every response, regardless of early returns from middleware.
|
|
342
333
|
* Can return a new response to transform it, or void for side effects only.
|
|
343
334
|
* Returned responses are chained through plugins in order.
|
|
344
335
|
*/
|
|
345
|
-
type PluginResponseHandler
|
|
346
|
-
type PluginLifecycle
|
|
336
|
+
type PluginResponseHandler = (context: PluginContext, response: SpooshResponse<any, any>) => SpooshResponse<any, any> | void | Promise<SpooshResponse<any, any> | void>;
|
|
337
|
+
type PluginLifecycle = {
|
|
347
338
|
/** Called on component mount */
|
|
348
|
-
onMount?: PluginHandler
|
|
339
|
+
onMount?: PluginHandler;
|
|
349
340
|
/** Called when options/query changes. Receives both new and previous context. */
|
|
350
|
-
onUpdate?: PluginUpdateHandler
|
|
341
|
+
onUpdate?: PluginUpdateHandler;
|
|
351
342
|
/** Called on component unmount */
|
|
352
|
-
onUnmount?: PluginHandler
|
|
343
|
+
onUnmount?: PluginHandler;
|
|
353
344
|
};
|
|
354
345
|
/**
|
|
355
346
|
* Configuration object for plugin type definitions.
|
|
@@ -606,8 +597,8 @@ type RefetchEvent = {
|
|
|
606
597
|
* Avoids circular dependency with executor.ts.
|
|
607
598
|
*/
|
|
608
599
|
type InstancePluginExecutor = {
|
|
609
|
-
executeMiddleware: <TData, TError>(operationType: OperationType, context: PluginContext
|
|
610
|
-
createContext:
|
|
600
|
+
executeMiddleware: <TData, TError>(operationType: OperationType, context: PluginContext, coreFetch: () => Promise<SpooshResponse<any, any>>) => Promise<SpooshResponse<TData, TError>>;
|
|
601
|
+
createContext: (input: PluginContextInput) => PluginContext;
|
|
611
602
|
};
|
|
612
603
|
/**
|
|
613
604
|
* Context provided to plugin's instanceApi function.
|
|
@@ -622,14 +613,13 @@ type InstanceApiContext<TApi = unknown> = {
|
|
|
622
613
|
|
|
623
614
|
type PluginExecutor = {
|
|
624
615
|
/** Execute lifecycle hooks for onMount or onUnmount */
|
|
625
|
-
executeLifecycle:
|
|
616
|
+
executeLifecycle: (phase: "onMount" | "onUnmount", operationType: OperationType, context: PluginContext) => Promise<void>;
|
|
626
617
|
/** Execute onUpdate lifecycle with previous context */
|
|
627
|
-
executeUpdateLifecycle:
|
|
628
|
-
|
|
629
|
-
executeMiddleware: <TData, TError>(operationType: OperationType, context: PluginContext<TData, TError>, coreFetch: () => Promise<SpooshResponse<TData, TError>>) => Promise<SpooshResponse<TData, TError>>;
|
|
618
|
+
executeUpdateLifecycle: (operationType: OperationType, context: PluginContext, previousContext: PluginContext) => Promise<void>;
|
|
619
|
+
executeMiddleware: (operationType: OperationType, context: PluginContext, coreFetch: () => Promise<SpooshResponse<any, any>>) => Promise<SpooshResponse<any, any>>;
|
|
630
620
|
getPlugins: () => readonly SpooshPlugin[];
|
|
631
621
|
/** Creates a full PluginContext with plugins accessor injected */
|
|
632
|
-
createContext:
|
|
622
|
+
createContext: (input: PluginContextInput) => PluginContext;
|
|
633
623
|
};
|
|
634
624
|
declare function createPluginExecutor(initialPlugins?: SpooshPlugin[]): PluginExecutor;
|
|
635
625
|
|
|
@@ -1346,18 +1336,14 @@ declare class Spoosh<TSchema = unknown, TError = unknown, TPlugins extends Plugi
|
|
|
1346
1336
|
};
|
|
1347
1337
|
}
|
|
1348
1338
|
|
|
1349
|
-
type SpooshClientConfig = {
|
|
1350
|
-
baseUrl: string;
|
|
1351
|
-
defaultOptions?: SpooshOptionsInput;
|
|
1352
|
-
middlewares?: SpooshMiddleware[];
|
|
1353
|
-
};
|
|
1354
1339
|
/**
|
|
1355
1340
|
* Creates a lightweight type-safe API instance for vanilla JavaScript/TypeScript usage.
|
|
1356
1341
|
*
|
|
1357
1342
|
* This is a simpler alternative to `Spoosh` for users who don't need
|
|
1358
1343
|
* the full plugin system, state management, or React integration.
|
|
1359
1344
|
*
|
|
1360
|
-
* @param
|
|
1345
|
+
* @param baseUrl - Base URL for all API requests
|
|
1346
|
+
* @param defaultOptions - Default fetch options (headers, credentials, etc.)
|
|
1361
1347
|
* @returns Type-safe API instance
|
|
1362
1348
|
*
|
|
1363
1349
|
* @example
|
|
@@ -1378,23 +1364,21 @@ type SpooshClientConfig = {
|
|
|
1378
1364
|
* message: string;
|
|
1379
1365
|
* }
|
|
1380
1366
|
*
|
|
1381
|
-
* const api = createClient<ApiSchema, ApiError>(
|
|
1382
|
-
* baseUrl: "/api",
|
|
1383
|
-
* });
|
|
1367
|
+
* const api = createClient<ApiSchema, ApiError>("/api");
|
|
1384
1368
|
*
|
|
1385
1369
|
* // Type-safe API calls with path strings
|
|
1386
1370
|
* const { data } = await api("posts").GET();
|
|
1387
1371
|
* const { data: post } = await api("posts/123").GET();
|
|
1388
1372
|
* await api("posts/:id").GET({ params: { id: 123 } });
|
|
1389
1373
|
*
|
|
1390
|
-
* // With
|
|
1391
|
-
* const api = createClient<ApiSchema, ApiError>({
|
|
1392
|
-
*
|
|
1393
|
-
*
|
|
1374
|
+
* // With custom options
|
|
1375
|
+
* const api = createClient<ApiSchema, ApiError>("/api", {
|
|
1376
|
+
* headers: { Authorization: "Bearer token" },
|
|
1377
|
+
* transport: "xhr",
|
|
1394
1378
|
* });
|
|
1395
1379
|
* ```
|
|
1396
1380
|
*/
|
|
1397
|
-
declare function createClient<TSchema, TDefaultError = unknown>(
|
|
1381
|
+
declare function createClient<TSchema, TDefaultError = unknown>(baseUrl: string, defaultOptions?: SpooshOptionsInput): SpooshClient<TSchema, TDefaultError>;
|
|
1398
1382
|
|
|
1399
1383
|
declare function buildUrl(baseUrl: string, path: string[], query?: Record<string, string | number | boolean | undefined>): string;
|
|
1400
1384
|
|
|
@@ -1593,11 +1577,7 @@ declare module "./types" {
|
|
|
1593
1577
|
}
|
|
1594
1578
|
declare const xhrTransport: Transport<XhrTransportOptions>;
|
|
1595
1579
|
|
|
1596
|
-
declare function executeFetch<TData, TError>(baseUrl: string, path: string[], method: HttpMethod, defaultOptions: SpooshOptions
|
|
1597
|
-
|
|
1598
|
-
declare function createMiddleware<TData = unknown, TError = unknown>(name: string, phase: MiddlewarePhase, handler: SpooshMiddleware<TData, TError>["handler"]): SpooshMiddleware<TData, TError>;
|
|
1599
|
-
declare function applyMiddlewares<TData = unknown, TError = unknown>(context: MiddlewareContext<TData, TError>, middlewares: SpooshMiddleware<TData, TError>[], phase: MiddlewarePhase): Promise<MiddlewareContext<TData, TError>>;
|
|
1600
|
-
declare function composeMiddlewares<TData = unknown, TError = unknown>(...middlewareLists: (SpooshMiddleware<TData, TError>[] | undefined)[]): SpooshMiddleware<TData, TError>[];
|
|
1580
|
+
declare function executeFetch<TData, TError>(baseUrl: string, path: string[], method: HttpMethod, defaultOptions: SpooshOptions, requestOptions?: AnyRequestOptions, nextTags?: boolean): Promise<SpooshResponse<TData, TError>>;
|
|
1601
1581
|
|
|
1602
1582
|
type ExecuteOptions = {
|
|
1603
1583
|
force?: boolean;
|
|
@@ -1613,15 +1593,15 @@ type OperationController<TData = unknown, TError = unknown> = {
|
|
|
1613
1593
|
/** Called once when hook finally unmounts */
|
|
1614
1594
|
unmount: () => void;
|
|
1615
1595
|
/** Called when options/query changes. Pass previous context for cleanup. */
|
|
1616
|
-
update: (previousContext: PluginContext
|
|
1596
|
+
update: (previousContext: PluginContext) => void;
|
|
1617
1597
|
/** Get current context (for passing to update as previousContext) */
|
|
1618
|
-
getContext: () => PluginContext
|
|
1598
|
+
getContext: () => PluginContext;
|
|
1619
1599
|
setPluginOptions: (options: unknown) => void;
|
|
1620
1600
|
setMetadata: (key: string, value: unknown) => void;
|
|
1621
1601
|
};
|
|
1622
1602
|
type CreateOperationOptions<TData, TError> = {
|
|
1623
1603
|
operationType: OperationType;
|
|
1624
|
-
path: string
|
|
1604
|
+
path: string;
|
|
1625
1605
|
method: HttpMethod;
|
|
1626
1606
|
tags: string[];
|
|
1627
1607
|
requestOptions?: AnyRequestOptions;
|
|
@@ -1663,12 +1643,12 @@ type InfiniteReadController<TData, TItem, TError> = {
|
|
|
1663
1643
|
abort: () => void;
|
|
1664
1644
|
mount: () => void;
|
|
1665
1645
|
unmount: () => void;
|
|
1666
|
-
update: (previousContext: PluginContext
|
|
1667
|
-
getContext: () => PluginContext
|
|
1646
|
+
update: (previousContext: PluginContext) => void;
|
|
1647
|
+
getContext: () => PluginContext;
|
|
1668
1648
|
setPluginOptions: (options: unknown) => void;
|
|
1669
1649
|
};
|
|
1670
1650
|
type CreateInfiniteReadOptions<TData, TItem, TError, TRequest> = {
|
|
1671
|
-
path: string
|
|
1651
|
+
path: string;
|
|
1672
1652
|
method: HttpMethod;
|
|
1673
1653
|
tags: string[];
|
|
1674
1654
|
initialRequest: InfiniteRequestOptions;
|
|
@@ -1687,4 +1667,4 @@ type CreateInfiniteReadOptions<TData, TItem, TError, TRequest> = {
|
|
|
1687
1667
|
};
|
|
1688
1668
|
declare function createInfiniteReadController<TData, TItem, TError, TRequest extends InfiniteRequestOptions = InfiniteRequestOptions>(options: CreateInfiniteReadOptions<TData, TItem, TError, TRequest>): InfiniteReadController<TData, TItem, TError>;
|
|
1689
1669
|
|
|
1690
|
-
export { type AnyRequestOptions, type ApiSchema, type BuiltInEvents, type CacheEntry, type CacheEntryWithKey, type CapturedCall, type
|
|
1670
|
+
export { type AnyRequestOptions, type ApiSchema, type BuiltInEvents, type CacheEntry, type CacheEntryWithKey, type CapturedCall, type ComputeRequestOptions, type CoreRequestOptionsBase, type CreateInfiniteReadOptions, type CreateOperationOptions, type DataAwareCallback, type DataAwareTransform, type EventEmitter, type ExtractBody$1 as ExtractBody, type ExtractData, type ExtractError, type ExtractMethodOptions, type ExtractParamNames, type ExtractQuery$1 as ExtractQuery, type FetchDirection, type FetchExecutor, type FindMatchingKey, HTTP_METHODS, type HasParams, type HasReadMethod, type HasWriteMethod, type HeadersInitOrGetter, type HttpMethod, type HttpMethodKey, type InfiniteReadController, type InfiniteReadState, type InfiniteRequestOptions, type InstanceApiContext, type InstanceApiResolvers, type InstancePluginExecutor, type LifecyclePhase, type MergePluginInstanceApi, type MergePluginOptions, type MergePluginResults, type MethodOptionsMap, type OperationController, type OperationState, type OperationType, type PageContext, type PluginAccessor, type PluginArray, type PluginContext, type PluginContextInput, type PluginExecutor, type PluginExportsRegistry, type PluginFactory, type PluginHandler, type PluginLifecycle, type PluginMiddleware, type PluginRegistry, type PluginRequestOptions, type PluginResolvers, type PluginResponseHandler, type PluginResultResolvers, type PluginTypeConfig, type PluginUpdateHandler, type ReadClient, type ReadPaths, type ReadSchemaHelper, type RefetchEvent, type RequestOptions$1 as RequestOptions, type ResolveInstanceApi, type ResolveResultTypes, type ResolveSchemaTypes, type ResolveTypes, type ResolverContext, type RetryConfig, type SchemaPaths, type SelectedEndpoint, type SelectorFunction, type SelectorResult, type Simplify, Spoosh, type SpooshBody, type SpooshClient, type SpooshConfig, type SpooshInstance, type SpooshOptions, type SpooshOptionsInput, type SpooshPlugin, type SpooshResponse, type SpooshSchema, type StateManager, type StripPrefix, type TagMode, type TagOptions, type Transport, type TransportOption, type TransportOptionsMap, type TransportResponse, type WriteClient, type WriteMethod, type WritePaths, type WriteSchemaHelper, __DEV__, buildUrl, containsFile, createClient, createEventEmitter, createInfiniteReadController, createInitialState, createOperationController, createPluginExecutor, createPluginRegistry, createProxyHandler, createSelectorProxy, createStateManager, executeFetch, extractMethodFromSelector, extractPathFromSelector, fetchTransport, form, generateTags, getContentType, isJsonBody, isSpooshBody, json, mergeHeaders, objectToFormData, objectToUrlEncoded, resolveHeadersToRecord, resolvePath, resolveRequestBody, resolveTags, setHeaders, sortObjectKeys, urlencoded, xhrTransport };
|
package/dist/index.d.ts
CHANGED
|
@@ -4,24 +4,6 @@ type Simplify<T> = {
|
|
|
4
4
|
[K in keyof T]: T[K];
|
|
5
5
|
} & {};
|
|
6
6
|
|
|
7
|
-
type MiddlewarePhase = "before" | "after";
|
|
8
|
-
type MiddlewareContext<TData = unknown, TError = unknown> = {
|
|
9
|
-
baseUrl: string;
|
|
10
|
-
path: string[];
|
|
11
|
-
method: HttpMethod;
|
|
12
|
-
defaultOptions: SpooshOptions & SpooshOptionsExtra;
|
|
13
|
-
requestOptions?: AnyRequestOptions;
|
|
14
|
-
fetchInit?: RequestInit;
|
|
15
|
-
response?: SpooshResponse<TData, TError>;
|
|
16
|
-
metadata: Record<string, unknown>;
|
|
17
|
-
};
|
|
18
|
-
type MiddlewareHandler<TData = unknown, TError = unknown> = (context: MiddlewareContext<TData, TError>) => MiddlewareContext<TData, TError> | Promise<MiddlewareContext<TData, TError>>;
|
|
19
|
-
type SpooshMiddleware<TData = unknown, TError = unknown> = {
|
|
20
|
-
name: string;
|
|
21
|
-
phase: MiddlewarePhase;
|
|
22
|
-
handler: MiddlewareHandler<TData, TError>;
|
|
23
|
-
};
|
|
24
|
-
|
|
25
7
|
type QueryField<TQuery> = [TQuery] extends [never] ? object : {
|
|
26
8
|
query: TQuery;
|
|
27
9
|
};
|
|
@@ -54,15 +36,25 @@ type SpooshResponse<TData, TError, TRequestOptions = unknown, TQuery = never, TB
|
|
|
54
36
|
aborted?: boolean;
|
|
55
37
|
readonly __requestOptions?: TRequestOptions;
|
|
56
38
|
} & InputFieldWrapper<TQuery, TBody, TParamNames>);
|
|
57
|
-
type SpooshOptionsExtra<TData = unknown, TError = unknown> = {
|
|
58
|
-
middlewares?: SpooshMiddleware<TData, TError>[];
|
|
59
|
-
};
|
|
60
39
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
40
|
+
/**
|
|
41
|
+
* Opaque type representing a transformed body. Create using `form()`, `json()`, or `urlencoded()` helpers.
|
|
42
|
+
* Do not create this type manually - use the helper functions instead.
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```ts
|
|
46
|
+
* import { form, json, urlencoded } from "@spoosh/core";
|
|
47
|
+
*
|
|
48
|
+
* // Use helpers to create SpooshBody
|
|
49
|
+
* trigger({ body: form({ file: myFile }) });
|
|
50
|
+
* trigger({ body: json({ data: "value" }) });
|
|
51
|
+
* trigger({ body: urlencoded({ key: "value" }) });
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
declare class SpooshBodyClass<T> {
|
|
55
|
+
private __brand;
|
|
56
|
+
}
|
|
57
|
+
type SpooshBody<T = unknown> = SpooshBodyClass<T>;
|
|
66
58
|
declare function isSpooshBody(value: unknown): value is SpooshBody;
|
|
67
59
|
declare function form<T>(value: T): SpooshBody<T>;
|
|
68
60
|
declare function json<T>(value: T): SpooshBody<T>;
|
|
@@ -231,7 +223,7 @@ type CacheEntryWithKey<TData = unknown, TError = unknown> = {
|
|
|
231
223
|
declare function createInitialState<TData, TError>(): OperationState<TData, TError>;
|
|
232
224
|
type StateManager = {
|
|
233
225
|
createQueryKey: (params: {
|
|
234
|
-
path: string
|
|
226
|
+
path: string;
|
|
235
227
|
method: string;
|
|
236
228
|
options?: unknown;
|
|
237
229
|
}) => string;
|
|
@@ -249,6 +241,8 @@ type StateManager = {
|
|
|
249
241
|
getAllCacheEntries: <TData, TError>() => CacheEntryWithKey<TData, TError>[];
|
|
250
242
|
/** Get the number of cache entries */
|
|
251
243
|
getSize: () => number;
|
|
244
|
+
/** Get the number of active subscribers for a cache key */
|
|
245
|
+
getSubscribersCount: (key: string) => number;
|
|
252
246
|
/** Set a pending promise for a query key (for deduplication) */
|
|
253
247
|
setPendingPromise: (key: string, promise: Promise<unknown> | undefined) => void;
|
|
254
248
|
/** Get a pending promise for a query key */
|
|
@@ -275,9 +269,13 @@ type CacheEntry<TData = unknown, TError = unknown> = {
|
|
|
275
269
|
/** Cache was invalidated while no subscriber was listening. Triggers refetch on next mount. */
|
|
276
270
|
stale?: boolean;
|
|
277
271
|
};
|
|
278
|
-
|
|
272
|
+
/** RequestOptions in plugin context have headers already resolved to Record */
|
|
273
|
+
type PluginRequestOptions = Omit<AnyRequestOptions, "headers"> & {
|
|
274
|
+
headers: Record<string, string>;
|
|
275
|
+
};
|
|
276
|
+
type PluginContext = {
|
|
279
277
|
readonly operationType: OperationType;
|
|
280
|
-
readonly path: string
|
|
278
|
+
readonly path: string;
|
|
281
279
|
readonly method: HttpMethod;
|
|
282
280
|
readonly queryKey: string;
|
|
283
281
|
readonly tags: string[];
|
|
@@ -285,17 +283,10 @@ type PluginContext<TData = unknown, TError = unknown> = {
|
|
|
285
283
|
readonly requestTimestamp: number;
|
|
286
284
|
/** Unique identifier for the hook instance. Persists across queryKey changes within the same hook. */
|
|
287
285
|
readonly hookId?: string;
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
response?: SpooshResponse<TData, TError>;
|
|
291
|
-
metadata: Map<string, unknown>;
|
|
292
|
-
abort: () => void;
|
|
286
|
+
request: PluginRequestOptions;
|
|
287
|
+
temp: Map<string, unknown>;
|
|
293
288
|
stateManager: StateManager;
|
|
294
289
|
eventEmitter: EventEmitter;
|
|
295
|
-
/** Resolved headers as a plain object. Modify via setHeaders(). */
|
|
296
|
-
headers: Record<string, string>;
|
|
297
|
-
/** Add/update headers. Merges with existing headers. */
|
|
298
|
-
setHeaders: (headers: Record<string, string>) => void;
|
|
299
290
|
/** Access other plugins' exported APIs */
|
|
300
291
|
plugins: PluginAccessor;
|
|
301
292
|
/** Plugin-specific options passed from hooks (useRead/useWrite/useInfiniteRead) */
|
|
@@ -304,7 +295,7 @@ type PluginContext<TData = unknown, TError = unknown> = {
|
|
|
304
295
|
forceRefetch?: boolean;
|
|
305
296
|
};
|
|
306
297
|
/** Input type for creating PluginContext (without injected properties) */
|
|
307
|
-
type PluginContextInput
|
|
298
|
+
type PluginContextInput = Omit<PluginContext, "plugins">;
|
|
308
299
|
/**
|
|
309
300
|
* Middleware function that wraps the fetch flow.
|
|
310
301
|
* Plugins use this for full control over request/response handling.
|
|
@@ -334,22 +325,22 @@ type PluginContextInput<TData = unknown, TError = unknown> = Omit<PluginContext<
|
|
|
334
325
|
* }
|
|
335
326
|
* ```
|
|
336
327
|
*/
|
|
337
|
-
type PluginMiddleware
|
|
338
|
-
type PluginHandler
|
|
339
|
-
type PluginUpdateHandler
|
|
328
|
+
type PluginMiddleware = (context: PluginContext, next: () => Promise<SpooshResponse<any, any>>) => Promise<SpooshResponse<any, any>>;
|
|
329
|
+
type PluginHandler = (context: PluginContext) => void | Promise<void>;
|
|
330
|
+
type PluginUpdateHandler = (context: PluginContext, previousContext: PluginContext) => void | Promise<void>;
|
|
340
331
|
/**
|
|
341
332
|
* Handler called after every response, regardless of early returns from middleware.
|
|
342
333
|
* Can return a new response to transform it, or void for side effects only.
|
|
343
334
|
* Returned responses are chained through plugins in order.
|
|
344
335
|
*/
|
|
345
|
-
type PluginResponseHandler
|
|
346
|
-
type PluginLifecycle
|
|
336
|
+
type PluginResponseHandler = (context: PluginContext, response: SpooshResponse<any, any>) => SpooshResponse<any, any> | void | Promise<SpooshResponse<any, any> | void>;
|
|
337
|
+
type PluginLifecycle = {
|
|
347
338
|
/** Called on component mount */
|
|
348
|
-
onMount?: PluginHandler
|
|
339
|
+
onMount?: PluginHandler;
|
|
349
340
|
/** Called when options/query changes. Receives both new and previous context. */
|
|
350
|
-
onUpdate?: PluginUpdateHandler
|
|
341
|
+
onUpdate?: PluginUpdateHandler;
|
|
351
342
|
/** Called on component unmount */
|
|
352
|
-
onUnmount?: PluginHandler
|
|
343
|
+
onUnmount?: PluginHandler;
|
|
353
344
|
};
|
|
354
345
|
/**
|
|
355
346
|
* Configuration object for plugin type definitions.
|
|
@@ -606,8 +597,8 @@ type RefetchEvent = {
|
|
|
606
597
|
* Avoids circular dependency with executor.ts.
|
|
607
598
|
*/
|
|
608
599
|
type InstancePluginExecutor = {
|
|
609
|
-
executeMiddleware: <TData, TError>(operationType: OperationType, context: PluginContext
|
|
610
|
-
createContext:
|
|
600
|
+
executeMiddleware: <TData, TError>(operationType: OperationType, context: PluginContext, coreFetch: () => Promise<SpooshResponse<any, any>>) => Promise<SpooshResponse<TData, TError>>;
|
|
601
|
+
createContext: (input: PluginContextInput) => PluginContext;
|
|
611
602
|
};
|
|
612
603
|
/**
|
|
613
604
|
* Context provided to plugin's instanceApi function.
|
|
@@ -622,14 +613,13 @@ type InstanceApiContext<TApi = unknown> = {
|
|
|
622
613
|
|
|
623
614
|
type PluginExecutor = {
|
|
624
615
|
/** Execute lifecycle hooks for onMount or onUnmount */
|
|
625
|
-
executeLifecycle:
|
|
616
|
+
executeLifecycle: (phase: "onMount" | "onUnmount", operationType: OperationType, context: PluginContext) => Promise<void>;
|
|
626
617
|
/** Execute onUpdate lifecycle with previous context */
|
|
627
|
-
executeUpdateLifecycle:
|
|
628
|
-
|
|
629
|
-
executeMiddleware: <TData, TError>(operationType: OperationType, context: PluginContext<TData, TError>, coreFetch: () => Promise<SpooshResponse<TData, TError>>) => Promise<SpooshResponse<TData, TError>>;
|
|
618
|
+
executeUpdateLifecycle: (operationType: OperationType, context: PluginContext, previousContext: PluginContext) => Promise<void>;
|
|
619
|
+
executeMiddleware: (operationType: OperationType, context: PluginContext, coreFetch: () => Promise<SpooshResponse<any, any>>) => Promise<SpooshResponse<any, any>>;
|
|
630
620
|
getPlugins: () => readonly SpooshPlugin[];
|
|
631
621
|
/** Creates a full PluginContext with plugins accessor injected */
|
|
632
|
-
createContext:
|
|
622
|
+
createContext: (input: PluginContextInput) => PluginContext;
|
|
633
623
|
};
|
|
634
624
|
declare function createPluginExecutor(initialPlugins?: SpooshPlugin[]): PluginExecutor;
|
|
635
625
|
|
|
@@ -1346,18 +1336,14 @@ declare class Spoosh<TSchema = unknown, TError = unknown, TPlugins extends Plugi
|
|
|
1346
1336
|
};
|
|
1347
1337
|
}
|
|
1348
1338
|
|
|
1349
|
-
type SpooshClientConfig = {
|
|
1350
|
-
baseUrl: string;
|
|
1351
|
-
defaultOptions?: SpooshOptionsInput;
|
|
1352
|
-
middlewares?: SpooshMiddleware[];
|
|
1353
|
-
};
|
|
1354
1339
|
/**
|
|
1355
1340
|
* Creates a lightweight type-safe API instance for vanilla JavaScript/TypeScript usage.
|
|
1356
1341
|
*
|
|
1357
1342
|
* This is a simpler alternative to `Spoosh` for users who don't need
|
|
1358
1343
|
* the full plugin system, state management, or React integration.
|
|
1359
1344
|
*
|
|
1360
|
-
* @param
|
|
1345
|
+
* @param baseUrl - Base URL for all API requests
|
|
1346
|
+
* @param defaultOptions - Default fetch options (headers, credentials, etc.)
|
|
1361
1347
|
* @returns Type-safe API instance
|
|
1362
1348
|
*
|
|
1363
1349
|
* @example
|
|
@@ -1378,23 +1364,21 @@ type SpooshClientConfig = {
|
|
|
1378
1364
|
* message: string;
|
|
1379
1365
|
* }
|
|
1380
1366
|
*
|
|
1381
|
-
* const api = createClient<ApiSchema, ApiError>(
|
|
1382
|
-
* baseUrl: "/api",
|
|
1383
|
-
* });
|
|
1367
|
+
* const api = createClient<ApiSchema, ApiError>("/api");
|
|
1384
1368
|
*
|
|
1385
1369
|
* // Type-safe API calls with path strings
|
|
1386
1370
|
* const { data } = await api("posts").GET();
|
|
1387
1371
|
* const { data: post } = await api("posts/123").GET();
|
|
1388
1372
|
* await api("posts/:id").GET({ params: { id: 123 } });
|
|
1389
1373
|
*
|
|
1390
|
-
* // With
|
|
1391
|
-
* const api = createClient<ApiSchema, ApiError>({
|
|
1392
|
-
*
|
|
1393
|
-
*
|
|
1374
|
+
* // With custom options
|
|
1375
|
+
* const api = createClient<ApiSchema, ApiError>("/api", {
|
|
1376
|
+
* headers: { Authorization: "Bearer token" },
|
|
1377
|
+
* transport: "xhr",
|
|
1394
1378
|
* });
|
|
1395
1379
|
* ```
|
|
1396
1380
|
*/
|
|
1397
|
-
declare function createClient<TSchema, TDefaultError = unknown>(
|
|
1381
|
+
declare function createClient<TSchema, TDefaultError = unknown>(baseUrl: string, defaultOptions?: SpooshOptionsInput): SpooshClient<TSchema, TDefaultError>;
|
|
1398
1382
|
|
|
1399
1383
|
declare function buildUrl(baseUrl: string, path: string[], query?: Record<string, string | number | boolean | undefined>): string;
|
|
1400
1384
|
|
|
@@ -1593,11 +1577,7 @@ declare module "./types" {
|
|
|
1593
1577
|
}
|
|
1594
1578
|
declare const xhrTransport: Transport<XhrTransportOptions>;
|
|
1595
1579
|
|
|
1596
|
-
declare function executeFetch<TData, TError>(baseUrl: string, path: string[], method: HttpMethod, defaultOptions: SpooshOptions
|
|
1597
|
-
|
|
1598
|
-
declare function createMiddleware<TData = unknown, TError = unknown>(name: string, phase: MiddlewarePhase, handler: SpooshMiddleware<TData, TError>["handler"]): SpooshMiddleware<TData, TError>;
|
|
1599
|
-
declare function applyMiddlewares<TData = unknown, TError = unknown>(context: MiddlewareContext<TData, TError>, middlewares: SpooshMiddleware<TData, TError>[], phase: MiddlewarePhase): Promise<MiddlewareContext<TData, TError>>;
|
|
1600
|
-
declare function composeMiddlewares<TData = unknown, TError = unknown>(...middlewareLists: (SpooshMiddleware<TData, TError>[] | undefined)[]): SpooshMiddleware<TData, TError>[];
|
|
1580
|
+
declare function executeFetch<TData, TError>(baseUrl: string, path: string[], method: HttpMethod, defaultOptions: SpooshOptions, requestOptions?: AnyRequestOptions, nextTags?: boolean): Promise<SpooshResponse<TData, TError>>;
|
|
1601
1581
|
|
|
1602
1582
|
type ExecuteOptions = {
|
|
1603
1583
|
force?: boolean;
|
|
@@ -1613,15 +1593,15 @@ type OperationController<TData = unknown, TError = unknown> = {
|
|
|
1613
1593
|
/** Called once when hook finally unmounts */
|
|
1614
1594
|
unmount: () => void;
|
|
1615
1595
|
/** Called when options/query changes. Pass previous context for cleanup. */
|
|
1616
|
-
update: (previousContext: PluginContext
|
|
1596
|
+
update: (previousContext: PluginContext) => void;
|
|
1617
1597
|
/** Get current context (for passing to update as previousContext) */
|
|
1618
|
-
getContext: () => PluginContext
|
|
1598
|
+
getContext: () => PluginContext;
|
|
1619
1599
|
setPluginOptions: (options: unknown) => void;
|
|
1620
1600
|
setMetadata: (key: string, value: unknown) => void;
|
|
1621
1601
|
};
|
|
1622
1602
|
type CreateOperationOptions<TData, TError> = {
|
|
1623
1603
|
operationType: OperationType;
|
|
1624
|
-
path: string
|
|
1604
|
+
path: string;
|
|
1625
1605
|
method: HttpMethod;
|
|
1626
1606
|
tags: string[];
|
|
1627
1607
|
requestOptions?: AnyRequestOptions;
|
|
@@ -1663,12 +1643,12 @@ type InfiniteReadController<TData, TItem, TError> = {
|
|
|
1663
1643
|
abort: () => void;
|
|
1664
1644
|
mount: () => void;
|
|
1665
1645
|
unmount: () => void;
|
|
1666
|
-
update: (previousContext: PluginContext
|
|
1667
|
-
getContext: () => PluginContext
|
|
1646
|
+
update: (previousContext: PluginContext) => void;
|
|
1647
|
+
getContext: () => PluginContext;
|
|
1668
1648
|
setPluginOptions: (options: unknown) => void;
|
|
1669
1649
|
};
|
|
1670
1650
|
type CreateInfiniteReadOptions<TData, TItem, TError, TRequest> = {
|
|
1671
|
-
path: string
|
|
1651
|
+
path: string;
|
|
1672
1652
|
method: HttpMethod;
|
|
1673
1653
|
tags: string[];
|
|
1674
1654
|
initialRequest: InfiniteRequestOptions;
|
|
@@ -1687,4 +1667,4 @@ type CreateInfiniteReadOptions<TData, TItem, TError, TRequest> = {
|
|
|
1687
1667
|
};
|
|
1688
1668
|
declare function createInfiniteReadController<TData, TItem, TError, TRequest extends InfiniteRequestOptions = InfiniteRequestOptions>(options: CreateInfiniteReadOptions<TData, TItem, TError, TRequest>): InfiniteReadController<TData, TItem, TError>;
|
|
1689
1669
|
|
|
1690
|
-
export { type AnyRequestOptions, type ApiSchema, type BuiltInEvents, type CacheEntry, type CacheEntryWithKey, type CapturedCall, type
|
|
1670
|
+
export { type AnyRequestOptions, type ApiSchema, type BuiltInEvents, type CacheEntry, type CacheEntryWithKey, type CapturedCall, type ComputeRequestOptions, type CoreRequestOptionsBase, type CreateInfiniteReadOptions, type CreateOperationOptions, type DataAwareCallback, type DataAwareTransform, type EventEmitter, type ExtractBody$1 as ExtractBody, type ExtractData, type ExtractError, type ExtractMethodOptions, type ExtractParamNames, type ExtractQuery$1 as ExtractQuery, type FetchDirection, type FetchExecutor, type FindMatchingKey, HTTP_METHODS, type HasParams, type HasReadMethod, type HasWriteMethod, type HeadersInitOrGetter, type HttpMethod, type HttpMethodKey, type InfiniteReadController, type InfiniteReadState, type InfiniteRequestOptions, type InstanceApiContext, type InstanceApiResolvers, type InstancePluginExecutor, type LifecyclePhase, type MergePluginInstanceApi, type MergePluginOptions, type MergePluginResults, type MethodOptionsMap, type OperationController, type OperationState, type OperationType, type PageContext, type PluginAccessor, type PluginArray, type PluginContext, type PluginContextInput, type PluginExecutor, type PluginExportsRegistry, type PluginFactory, type PluginHandler, type PluginLifecycle, type PluginMiddleware, type PluginRegistry, type PluginRequestOptions, type PluginResolvers, type PluginResponseHandler, type PluginResultResolvers, type PluginTypeConfig, type PluginUpdateHandler, type ReadClient, type ReadPaths, type ReadSchemaHelper, type RefetchEvent, type RequestOptions$1 as RequestOptions, type ResolveInstanceApi, type ResolveResultTypes, type ResolveSchemaTypes, type ResolveTypes, type ResolverContext, type RetryConfig, type SchemaPaths, type SelectedEndpoint, type SelectorFunction, type SelectorResult, type Simplify, Spoosh, type SpooshBody, type SpooshClient, type SpooshConfig, type SpooshInstance, type SpooshOptions, type SpooshOptionsInput, type SpooshPlugin, type SpooshResponse, type SpooshSchema, type StateManager, type StripPrefix, type TagMode, type TagOptions, type Transport, type TransportOption, type TransportOptionsMap, type TransportResponse, type WriteClient, type WriteMethod, type WritePaths, type WriteSchemaHelper, __DEV__, buildUrl, containsFile, createClient, createEventEmitter, createInfiniteReadController, createInitialState, createOperationController, createPluginExecutor, createPluginRegistry, createProxyHandler, createSelectorProxy, createStateManager, executeFetch, extractMethodFromSelector, extractPathFromSelector, fetchTransport, form, generateTags, getContentType, isJsonBody, isSpooshBody, json, mergeHeaders, objectToFormData, objectToUrlEncoded, resolveHeadersToRecord, resolvePath, resolveRequestBody, resolveTags, setHeaders, sortObjectKeys, urlencoded, xhrTransport };
|
package/dist/index.js
CHANGED
|
@@ -23,15 +23,12 @@ __export(src_exports, {
|
|
|
23
23
|
HTTP_METHODS: () => HTTP_METHODS,
|
|
24
24
|
Spoosh: () => Spoosh,
|
|
25
25
|
__DEV__: () => __DEV__,
|
|
26
|
-
applyMiddlewares: () => applyMiddlewares,
|
|
27
26
|
buildUrl: () => buildUrl,
|
|
28
|
-
composeMiddlewares: () => composeMiddlewares,
|
|
29
27
|
containsFile: () => containsFile,
|
|
30
28
|
createClient: () => createClient,
|
|
31
29
|
createEventEmitter: () => createEventEmitter,
|
|
32
30
|
createInfiniteReadController: () => createInfiniteReadController,
|
|
33
31
|
createInitialState: () => createInitialState,
|
|
34
|
-
createMiddleware: () => createMiddleware,
|
|
35
32
|
createOperationController: () => createOperationController,
|
|
36
33
|
createPluginExecutor: () => createPluginExecutor,
|
|
37
34
|
createPluginRegistry: () => createPluginRegistry,
|
|
@@ -62,22 +59,6 @@ __export(src_exports, {
|
|
|
62
59
|
});
|
|
63
60
|
module.exports = __toCommonJS(src_exports);
|
|
64
61
|
|
|
65
|
-
// src/middleware.ts
|
|
66
|
-
function createMiddleware(name, phase, handler) {
|
|
67
|
-
return { name, phase, handler };
|
|
68
|
-
}
|
|
69
|
-
async function applyMiddlewares(context, middlewares, phase) {
|
|
70
|
-
const phaseMiddlewares = middlewares.filter((m) => m.phase === phase);
|
|
71
|
-
let ctx = context;
|
|
72
|
-
for (const middleware of phaseMiddlewares) {
|
|
73
|
-
ctx = await middleware.handler(ctx);
|
|
74
|
-
}
|
|
75
|
-
return ctx;
|
|
76
|
-
}
|
|
77
|
-
function composeMiddlewares(...middlewareLists) {
|
|
78
|
-
return middlewareLists.flat().filter(Boolean);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
62
|
// src/utils/buildUrl.ts
|
|
82
63
|
function stringifyQuery(query) {
|
|
83
64
|
const parts = [];
|
|
@@ -288,19 +269,20 @@ function resolveRequestBody(rawBody) {
|
|
|
288
269
|
return void 0;
|
|
289
270
|
}
|
|
290
271
|
if (isSpooshBody(rawBody)) {
|
|
291
|
-
|
|
272
|
+
const body = rawBody;
|
|
273
|
+
switch (body.kind) {
|
|
292
274
|
case "form":
|
|
293
275
|
return {
|
|
294
|
-
body: objectToFormData(
|
|
276
|
+
body: objectToFormData(body.value)
|
|
295
277
|
};
|
|
296
278
|
case "json":
|
|
297
279
|
return {
|
|
298
|
-
body: JSON.stringify(
|
|
280
|
+
body: JSON.stringify(body.value),
|
|
299
281
|
headers: { "Content-Type": "application/json" }
|
|
300
282
|
};
|
|
301
283
|
case "urlencoded":
|
|
302
284
|
return {
|
|
303
|
-
body: objectToUrlEncoded(
|
|
285
|
+
body: objectToUrlEncoded(body.value),
|
|
304
286
|
headers: { "Content-Type": "application/x-www-form-urlencoded" }
|
|
305
287
|
};
|
|
306
288
|
}
|
|
@@ -456,32 +438,15 @@ var delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
|
456
438
|
var isNetworkError = (err) => err instanceof TypeError;
|
|
457
439
|
var isAbortError = (err) => err instanceof DOMException && err.name === "AbortError";
|
|
458
440
|
async function executeFetch(baseUrl, path, method, defaultOptions, requestOptions, nextTags) {
|
|
459
|
-
|
|
460
|
-
let context = {
|
|
441
|
+
return executeCoreFetch({
|
|
461
442
|
baseUrl,
|
|
462
443
|
path,
|
|
463
444
|
method,
|
|
464
445
|
defaultOptions,
|
|
465
446
|
requestOptions,
|
|
466
|
-
|
|
467
|
-
};
|
|
468
|
-
if (middlewares.length > 0) {
|
|
469
|
-
context = await applyMiddlewares(context, middlewares, "before");
|
|
470
|
-
}
|
|
471
|
-
const response = await executeCoreFetch({
|
|
472
|
-
baseUrl: context.baseUrl,
|
|
473
|
-
path: context.path,
|
|
474
|
-
method: context.method,
|
|
475
|
-
defaultOptions: context.defaultOptions,
|
|
476
|
-
requestOptions: context.requestOptions,
|
|
477
|
-
middlewareFetchInit: context.fetchInit,
|
|
447
|
+
middlewareFetchInit: void 0,
|
|
478
448
|
nextTags
|
|
479
449
|
});
|
|
480
|
-
context.response = response;
|
|
481
|
-
if (middlewares.length > 0) {
|
|
482
|
-
context = await applyMiddlewares(context, middlewares, "after");
|
|
483
|
-
}
|
|
484
|
-
return context.response;
|
|
485
450
|
}
|
|
486
451
|
function buildInputFields(requestOptions) {
|
|
487
452
|
const fields = {};
|
|
@@ -516,12 +481,10 @@ async function executeCoreFetch(config) {
|
|
|
516
481
|
nextTags
|
|
517
482
|
} = config;
|
|
518
483
|
const {
|
|
519
|
-
middlewares: _,
|
|
520
484
|
headers: defaultHeaders,
|
|
521
485
|
transport: defaultTransport,
|
|
522
486
|
...fetchDefaults
|
|
523
487
|
} = defaultOptions;
|
|
524
|
-
void _;
|
|
525
488
|
const inputFields = buildInputFields(requestOptions);
|
|
526
489
|
const maxRetries = requestOptions?.retries ?? 3;
|
|
527
490
|
const baseDelay = requestOptions?.retryDelay ?? 1e3;
|
|
@@ -712,7 +675,7 @@ function createInitialState() {
|
|
|
712
675
|
function generateSelfTagFromKey(key) {
|
|
713
676
|
try {
|
|
714
677
|
const parsed = JSON.parse(key);
|
|
715
|
-
return parsed.path
|
|
678
|
+
return parsed.path;
|
|
716
679
|
} catch {
|
|
717
680
|
return void 0;
|
|
718
681
|
}
|
|
@@ -854,6 +817,9 @@ function createStateManager() {
|
|
|
854
817
|
getSize() {
|
|
855
818
|
return cache.size;
|
|
856
819
|
},
|
|
820
|
+
getSubscribersCount(key) {
|
|
821
|
+
return subscribers.get(key)?.size ?? 0;
|
|
822
|
+
},
|
|
857
823
|
setPendingPromise(key, promise) {
|
|
858
824
|
if (promise === void 0) {
|
|
859
825
|
pendingPromises.delete(key);
|
|
@@ -967,10 +933,7 @@ function createPluginExecutor(initialPlugins = []) {
|
|
|
967
933
|
if (!handler) {
|
|
968
934
|
continue;
|
|
969
935
|
}
|
|
970
|
-
await handler(
|
|
971
|
-
context,
|
|
972
|
-
previousContext
|
|
973
|
-
);
|
|
936
|
+
await handler(context, previousContext);
|
|
974
937
|
}
|
|
975
938
|
};
|
|
976
939
|
return {
|
|
@@ -990,6 +953,7 @@ function createPluginExecutor(initialPlugins = []) {
|
|
|
990
953
|
return () => middleware(
|
|
991
954
|
context,
|
|
992
955
|
next
|
|
956
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
993
957
|
);
|
|
994
958
|
},
|
|
995
959
|
coreFetch
|
|
@@ -1015,11 +979,6 @@ function createPluginExecutor(initialPlugins = []) {
|
|
|
1015
979
|
createContext(input) {
|
|
1016
980
|
const ctx = input;
|
|
1017
981
|
ctx.plugins = createPluginAccessor(ctx);
|
|
1018
|
-
ctx.headers = {};
|
|
1019
|
-
ctx.setHeaders = (newHeaders) => {
|
|
1020
|
-
ctx.headers = { ...ctx.headers, ...newHeaders };
|
|
1021
|
-
ctx.requestOptions.headers = ctx.headers;
|
|
1022
|
-
};
|
|
1023
982
|
return ctx;
|
|
1024
983
|
}
|
|
1025
984
|
};
|
|
@@ -1253,15 +1212,10 @@ var Spoosh = class _Spoosh {
|
|
|
1253
1212
|
};
|
|
1254
1213
|
|
|
1255
1214
|
// src/createClient.ts
|
|
1256
|
-
function createClient(
|
|
1257
|
-
const { baseUrl, defaultOptions = {}, middlewares = [] } = config;
|
|
1258
|
-
const optionsWithMiddlewares = {
|
|
1259
|
-
...defaultOptions,
|
|
1260
|
-
middlewares
|
|
1261
|
-
};
|
|
1215
|
+
function createClient(baseUrl, defaultOptions) {
|
|
1262
1216
|
return createProxyHandler({
|
|
1263
1217
|
baseUrl,
|
|
1264
|
-
defaultOptions:
|
|
1218
|
+
defaultOptions: defaultOptions || {},
|
|
1265
1219
|
nextTags: true
|
|
1266
1220
|
});
|
|
1267
1221
|
}
|
|
@@ -1286,15 +1240,13 @@ function createOperationController(options) {
|
|
|
1286
1240
|
options: initialRequestOptions
|
|
1287
1241
|
});
|
|
1288
1242
|
let abortController = null;
|
|
1289
|
-
const
|
|
1243
|
+
const temp = /* @__PURE__ */ new Map();
|
|
1290
1244
|
let pluginOptions = void 0;
|
|
1291
1245
|
const initialState = createInitialState();
|
|
1292
1246
|
let cachedState = initialState;
|
|
1293
1247
|
let currentRequestTimestamp = Date.now();
|
|
1294
1248
|
let isFirstExecute = true;
|
|
1295
|
-
const createContext = (requestOptions = {}, requestTimestamp = Date.now()) => {
|
|
1296
|
-
const cached = stateManager.getCache(queryKey);
|
|
1297
|
-
const state = cached?.state ?? createInitialState();
|
|
1249
|
+
const createContext = (requestOptions = {}, requestTimestamp = Date.now(), resolvedHeaders) => {
|
|
1298
1250
|
const resolvedTags = pluginOptions?.tags ?? tags;
|
|
1299
1251
|
return pluginExecutor.createContext({
|
|
1300
1252
|
operationType,
|
|
@@ -1304,11 +1256,13 @@ function createOperationController(options) {
|
|
|
1304
1256
|
tags: resolvedTags,
|
|
1305
1257
|
requestTimestamp,
|
|
1306
1258
|
hookId,
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1259
|
+
request: {
|
|
1260
|
+
...initialRequestOptions,
|
|
1261
|
+
...requestOptions,
|
|
1262
|
+
headers: resolvedHeaders ?? {}
|
|
1263
|
+
},
|
|
1264
|
+
temp,
|
|
1310
1265
|
pluginOptions,
|
|
1311
|
-
abort: () => abortController?.abort(),
|
|
1312
1266
|
stateManager,
|
|
1313
1267
|
eventEmitter
|
|
1314
1268
|
});
|
|
@@ -1336,21 +1290,24 @@ function createOperationController(options) {
|
|
|
1336
1290
|
currentRequestTimestamp = Date.now();
|
|
1337
1291
|
}
|
|
1338
1292
|
isFirstExecute = false;
|
|
1339
|
-
const
|
|
1293
|
+
const mergedOptions = { ...initialRequestOptions, ...opts };
|
|
1294
|
+
const resolvedHeaders = await resolveHeadersToRecord(
|
|
1295
|
+
mergedOptions.headers
|
|
1296
|
+
);
|
|
1297
|
+
const context = createContext(
|
|
1298
|
+
opts,
|
|
1299
|
+
currentRequestTimestamp,
|
|
1300
|
+
resolvedHeaders
|
|
1301
|
+
);
|
|
1340
1302
|
if (force) {
|
|
1341
1303
|
context.forceRefetch = true;
|
|
1342
1304
|
}
|
|
1343
|
-
context.headers = await resolveHeadersToRecord(
|
|
1344
|
-
context.requestOptions.headers
|
|
1345
|
-
);
|
|
1346
|
-
context.requestOptions.headers = context.headers;
|
|
1347
1305
|
const coreFetch = async () => {
|
|
1348
1306
|
abortController = new AbortController();
|
|
1349
|
-
context.
|
|
1307
|
+
context.request.signal = abortController.signal;
|
|
1350
1308
|
const fetchPromise = (async () => {
|
|
1351
1309
|
try {
|
|
1352
|
-
const response = await fetchFn(context.
|
|
1353
|
-
context.response = response;
|
|
1310
|
+
const response = await fetchFn(context.request);
|
|
1354
1311
|
return response;
|
|
1355
1312
|
} catch (err) {
|
|
1356
1313
|
const errorResponse = {
|
|
@@ -1358,7 +1315,6 @@ function createOperationController(options) {
|
|
|
1358
1315
|
error: err,
|
|
1359
1316
|
data: void 0
|
|
1360
1317
|
};
|
|
1361
|
-
context.response = errorResponse;
|
|
1362
1318
|
return errorResponse;
|
|
1363
1319
|
}
|
|
1364
1320
|
})();
|
|
@@ -1426,7 +1382,7 @@ function createOperationController(options) {
|
|
|
1426
1382
|
pluginOptions = options2;
|
|
1427
1383
|
},
|
|
1428
1384
|
setMetadata(key, value) {
|
|
1429
|
-
|
|
1385
|
+
temp.set(key, value);
|
|
1430
1386
|
}
|
|
1431
1387
|
};
|
|
1432
1388
|
return controller;
|
|
@@ -1587,11 +1543,6 @@ function createInfiniteReadController(options) {
|
|
|
1587
1543
|
);
|
|
1588
1544
|
};
|
|
1589
1545
|
const createContext = (pageKey) => {
|
|
1590
|
-
const initialState = {
|
|
1591
|
-
data: void 0,
|
|
1592
|
-
error: void 0,
|
|
1593
|
-
timestamp: 0
|
|
1594
|
-
};
|
|
1595
1546
|
return pluginExecutor.createContext({
|
|
1596
1547
|
operationType: "infiniteRead",
|
|
1597
1548
|
path,
|
|
@@ -1600,11 +1551,9 @@ function createInfiniteReadController(options) {
|
|
|
1600
1551
|
tags,
|
|
1601
1552
|
requestTimestamp: Date.now(),
|
|
1602
1553
|
hookId,
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
metadata: /* @__PURE__ */ new Map(),
|
|
1554
|
+
request: { headers: {} },
|
|
1555
|
+
temp: /* @__PURE__ */ new Map(),
|
|
1606
1556
|
pluginOptions,
|
|
1607
|
-
abort: () => abortController?.abort(),
|
|
1608
1557
|
stateManager,
|
|
1609
1558
|
eventEmitter
|
|
1610
1559
|
});
|
|
@@ -1631,7 +1580,6 @@ function createInfiniteReadController(options) {
|
|
|
1631
1580
|
const fetchPromise = (async () => {
|
|
1632
1581
|
try {
|
|
1633
1582
|
const response = await fetchFn(mergedRequest, signal);
|
|
1634
|
-
context.response = response;
|
|
1635
1583
|
if (signal.aborted) {
|
|
1636
1584
|
return {
|
|
1637
1585
|
status: 0,
|
|
@@ -1653,7 +1601,6 @@ function createInfiniteReadController(options) {
|
|
|
1653
1601
|
error: err,
|
|
1654
1602
|
data: void 0
|
|
1655
1603
|
};
|
|
1656
|
-
context.response = errorResponse;
|
|
1657
1604
|
latestError = err;
|
|
1658
1605
|
return errorResponse;
|
|
1659
1606
|
} finally {
|
package/dist/index.mjs
CHANGED
|
@@ -1,19 +1,3 @@
|
|
|
1
|
-
// src/middleware.ts
|
|
2
|
-
function createMiddleware(name, phase, handler) {
|
|
3
|
-
return { name, phase, handler };
|
|
4
|
-
}
|
|
5
|
-
async function applyMiddlewares(context, middlewares, phase) {
|
|
6
|
-
const phaseMiddlewares = middlewares.filter((m) => m.phase === phase);
|
|
7
|
-
let ctx = context;
|
|
8
|
-
for (const middleware of phaseMiddlewares) {
|
|
9
|
-
ctx = await middleware.handler(ctx);
|
|
10
|
-
}
|
|
11
|
-
return ctx;
|
|
12
|
-
}
|
|
13
|
-
function composeMiddlewares(...middlewareLists) {
|
|
14
|
-
return middlewareLists.flat().filter(Boolean);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
1
|
// src/utils/buildUrl.ts
|
|
18
2
|
function stringifyQuery(query) {
|
|
19
3
|
const parts = [];
|
|
@@ -224,19 +208,20 @@ function resolveRequestBody(rawBody) {
|
|
|
224
208
|
return void 0;
|
|
225
209
|
}
|
|
226
210
|
if (isSpooshBody(rawBody)) {
|
|
227
|
-
|
|
211
|
+
const body = rawBody;
|
|
212
|
+
switch (body.kind) {
|
|
228
213
|
case "form":
|
|
229
214
|
return {
|
|
230
|
-
body: objectToFormData(
|
|
215
|
+
body: objectToFormData(body.value)
|
|
231
216
|
};
|
|
232
217
|
case "json":
|
|
233
218
|
return {
|
|
234
|
-
body: JSON.stringify(
|
|
219
|
+
body: JSON.stringify(body.value),
|
|
235
220
|
headers: { "Content-Type": "application/json" }
|
|
236
221
|
};
|
|
237
222
|
case "urlencoded":
|
|
238
223
|
return {
|
|
239
|
-
body: objectToUrlEncoded(
|
|
224
|
+
body: objectToUrlEncoded(body.value),
|
|
240
225
|
headers: { "Content-Type": "application/x-www-form-urlencoded" }
|
|
241
226
|
};
|
|
242
227
|
}
|
|
@@ -392,32 +377,15 @@ var delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
|
392
377
|
var isNetworkError = (err) => err instanceof TypeError;
|
|
393
378
|
var isAbortError = (err) => err instanceof DOMException && err.name === "AbortError";
|
|
394
379
|
async function executeFetch(baseUrl, path, method, defaultOptions, requestOptions, nextTags) {
|
|
395
|
-
|
|
396
|
-
let context = {
|
|
380
|
+
return executeCoreFetch({
|
|
397
381
|
baseUrl,
|
|
398
382
|
path,
|
|
399
383
|
method,
|
|
400
384
|
defaultOptions,
|
|
401
385
|
requestOptions,
|
|
402
|
-
|
|
403
|
-
};
|
|
404
|
-
if (middlewares.length > 0) {
|
|
405
|
-
context = await applyMiddlewares(context, middlewares, "before");
|
|
406
|
-
}
|
|
407
|
-
const response = await executeCoreFetch({
|
|
408
|
-
baseUrl: context.baseUrl,
|
|
409
|
-
path: context.path,
|
|
410
|
-
method: context.method,
|
|
411
|
-
defaultOptions: context.defaultOptions,
|
|
412
|
-
requestOptions: context.requestOptions,
|
|
413
|
-
middlewareFetchInit: context.fetchInit,
|
|
386
|
+
middlewareFetchInit: void 0,
|
|
414
387
|
nextTags
|
|
415
388
|
});
|
|
416
|
-
context.response = response;
|
|
417
|
-
if (middlewares.length > 0) {
|
|
418
|
-
context = await applyMiddlewares(context, middlewares, "after");
|
|
419
|
-
}
|
|
420
|
-
return context.response;
|
|
421
389
|
}
|
|
422
390
|
function buildInputFields(requestOptions) {
|
|
423
391
|
const fields = {};
|
|
@@ -452,12 +420,10 @@ async function executeCoreFetch(config) {
|
|
|
452
420
|
nextTags
|
|
453
421
|
} = config;
|
|
454
422
|
const {
|
|
455
|
-
middlewares: _,
|
|
456
423
|
headers: defaultHeaders,
|
|
457
424
|
transport: defaultTransport,
|
|
458
425
|
...fetchDefaults
|
|
459
426
|
} = defaultOptions;
|
|
460
|
-
void _;
|
|
461
427
|
const inputFields = buildInputFields(requestOptions);
|
|
462
428
|
const maxRetries = requestOptions?.retries ?? 3;
|
|
463
429
|
const baseDelay = requestOptions?.retryDelay ?? 1e3;
|
|
@@ -648,7 +614,7 @@ function createInitialState() {
|
|
|
648
614
|
function generateSelfTagFromKey(key) {
|
|
649
615
|
try {
|
|
650
616
|
const parsed = JSON.parse(key);
|
|
651
|
-
return parsed.path
|
|
617
|
+
return parsed.path;
|
|
652
618
|
} catch {
|
|
653
619
|
return void 0;
|
|
654
620
|
}
|
|
@@ -790,6 +756,9 @@ function createStateManager() {
|
|
|
790
756
|
getSize() {
|
|
791
757
|
return cache.size;
|
|
792
758
|
},
|
|
759
|
+
getSubscribersCount(key) {
|
|
760
|
+
return subscribers.get(key)?.size ?? 0;
|
|
761
|
+
},
|
|
793
762
|
setPendingPromise(key, promise) {
|
|
794
763
|
if (promise === void 0) {
|
|
795
764
|
pendingPromises.delete(key);
|
|
@@ -903,10 +872,7 @@ function createPluginExecutor(initialPlugins = []) {
|
|
|
903
872
|
if (!handler) {
|
|
904
873
|
continue;
|
|
905
874
|
}
|
|
906
|
-
await handler(
|
|
907
|
-
context,
|
|
908
|
-
previousContext
|
|
909
|
-
);
|
|
875
|
+
await handler(context, previousContext);
|
|
910
876
|
}
|
|
911
877
|
};
|
|
912
878
|
return {
|
|
@@ -926,6 +892,7 @@ function createPluginExecutor(initialPlugins = []) {
|
|
|
926
892
|
return () => middleware(
|
|
927
893
|
context,
|
|
928
894
|
next
|
|
895
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
929
896
|
);
|
|
930
897
|
},
|
|
931
898
|
coreFetch
|
|
@@ -951,11 +918,6 @@ function createPluginExecutor(initialPlugins = []) {
|
|
|
951
918
|
createContext(input) {
|
|
952
919
|
const ctx = input;
|
|
953
920
|
ctx.plugins = createPluginAccessor(ctx);
|
|
954
|
-
ctx.headers = {};
|
|
955
|
-
ctx.setHeaders = (newHeaders) => {
|
|
956
|
-
ctx.headers = { ...ctx.headers, ...newHeaders };
|
|
957
|
-
ctx.requestOptions.headers = ctx.headers;
|
|
958
|
-
};
|
|
959
921
|
return ctx;
|
|
960
922
|
}
|
|
961
923
|
};
|
|
@@ -1189,15 +1151,10 @@ var Spoosh = class _Spoosh {
|
|
|
1189
1151
|
};
|
|
1190
1152
|
|
|
1191
1153
|
// src/createClient.ts
|
|
1192
|
-
function createClient(
|
|
1193
|
-
const { baseUrl, defaultOptions = {}, middlewares = [] } = config;
|
|
1194
|
-
const optionsWithMiddlewares = {
|
|
1195
|
-
...defaultOptions,
|
|
1196
|
-
middlewares
|
|
1197
|
-
};
|
|
1154
|
+
function createClient(baseUrl, defaultOptions) {
|
|
1198
1155
|
return createProxyHandler({
|
|
1199
1156
|
baseUrl,
|
|
1200
|
-
defaultOptions:
|
|
1157
|
+
defaultOptions: defaultOptions || {},
|
|
1201
1158
|
nextTags: true
|
|
1202
1159
|
});
|
|
1203
1160
|
}
|
|
@@ -1222,15 +1179,13 @@ function createOperationController(options) {
|
|
|
1222
1179
|
options: initialRequestOptions
|
|
1223
1180
|
});
|
|
1224
1181
|
let abortController = null;
|
|
1225
|
-
const
|
|
1182
|
+
const temp = /* @__PURE__ */ new Map();
|
|
1226
1183
|
let pluginOptions = void 0;
|
|
1227
1184
|
const initialState = createInitialState();
|
|
1228
1185
|
let cachedState = initialState;
|
|
1229
1186
|
let currentRequestTimestamp = Date.now();
|
|
1230
1187
|
let isFirstExecute = true;
|
|
1231
|
-
const createContext = (requestOptions = {}, requestTimestamp = Date.now()) => {
|
|
1232
|
-
const cached = stateManager.getCache(queryKey);
|
|
1233
|
-
const state = cached?.state ?? createInitialState();
|
|
1188
|
+
const createContext = (requestOptions = {}, requestTimestamp = Date.now(), resolvedHeaders) => {
|
|
1234
1189
|
const resolvedTags = pluginOptions?.tags ?? tags;
|
|
1235
1190
|
return pluginExecutor.createContext({
|
|
1236
1191
|
operationType,
|
|
@@ -1240,11 +1195,13 @@ function createOperationController(options) {
|
|
|
1240
1195
|
tags: resolvedTags,
|
|
1241
1196
|
requestTimestamp,
|
|
1242
1197
|
hookId,
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1198
|
+
request: {
|
|
1199
|
+
...initialRequestOptions,
|
|
1200
|
+
...requestOptions,
|
|
1201
|
+
headers: resolvedHeaders ?? {}
|
|
1202
|
+
},
|
|
1203
|
+
temp,
|
|
1246
1204
|
pluginOptions,
|
|
1247
|
-
abort: () => abortController?.abort(),
|
|
1248
1205
|
stateManager,
|
|
1249
1206
|
eventEmitter
|
|
1250
1207
|
});
|
|
@@ -1272,21 +1229,24 @@ function createOperationController(options) {
|
|
|
1272
1229
|
currentRequestTimestamp = Date.now();
|
|
1273
1230
|
}
|
|
1274
1231
|
isFirstExecute = false;
|
|
1275
|
-
const
|
|
1232
|
+
const mergedOptions = { ...initialRequestOptions, ...opts };
|
|
1233
|
+
const resolvedHeaders = await resolveHeadersToRecord(
|
|
1234
|
+
mergedOptions.headers
|
|
1235
|
+
);
|
|
1236
|
+
const context = createContext(
|
|
1237
|
+
opts,
|
|
1238
|
+
currentRequestTimestamp,
|
|
1239
|
+
resolvedHeaders
|
|
1240
|
+
);
|
|
1276
1241
|
if (force) {
|
|
1277
1242
|
context.forceRefetch = true;
|
|
1278
1243
|
}
|
|
1279
|
-
context.headers = await resolveHeadersToRecord(
|
|
1280
|
-
context.requestOptions.headers
|
|
1281
|
-
);
|
|
1282
|
-
context.requestOptions.headers = context.headers;
|
|
1283
1244
|
const coreFetch = async () => {
|
|
1284
1245
|
abortController = new AbortController();
|
|
1285
|
-
context.
|
|
1246
|
+
context.request.signal = abortController.signal;
|
|
1286
1247
|
const fetchPromise = (async () => {
|
|
1287
1248
|
try {
|
|
1288
|
-
const response = await fetchFn(context.
|
|
1289
|
-
context.response = response;
|
|
1249
|
+
const response = await fetchFn(context.request);
|
|
1290
1250
|
return response;
|
|
1291
1251
|
} catch (err) {
|
|
1292
1252
|
const errorResponse = {
|
|
@@ -1294,7 +1254,6 @@ function createOperationController(options) {
|
|
|
1294
1254
|
error: err,
|
|
1295
1255
|
data: void 0
|
|
1296
1256
|
};
|
|
1297
|
-
context.response = errorResponse;
|
|
1298
1257
|
return errorResponse;
|
|
1299
1258
|
}
|
|
1300
1259
|
})();
|
|
@@ -1362,7 +1321,7 @@ function createOperationController(options) {
|
|
|
1362
1321
|
pluginOptions = options2;
|
|
1363
1322
|
},
|
|
1364
1323
|
setMetadata(key, value) {
|
|
1365
|
-
|
|
1324
|
+
temp.set(key, value);
|
|
1366
1325
|
}
|
|
1367
1326
|
};
|
|
1368
1327
|
return controller;
|
|
@@ -1523,11 +1482,6 @@ function createInfiniteReadController(options) {
|
|
|
1523
1482
|
);
|
|
1524
1483
|
};
|
|
1525
1484
|
const createContext = (pageKey) => {
|
|
1526
|
-
const initialState = {
|
|
1527
|
-
data: void 0,
|
|
1528
|
-
error: void 0,
|
|
1529
|
-
timestamp: 0
|
|
1530
|
-
};
|
|
1531
1485
|
return pluginExecutor.createContext({
|
|
1532
1486
|
operationType: "infiniteRead",
|
|
1533
1487
|
path,
|
|
@@ -1536,11 +1490,9 @@ function createInfiniteReadController(options) {
|
|
|
1536
1490
|
tags,
|
|
1537
1491
|
requestTimestamp: Date.now(),
|
|
1538
1492
|
hookId,
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
metadata: /* @__PURE__ */ new Map(),
|
|
1493
|
+
request: { headers: {} },
|
|
1494
|
+
temp: /* @__PURE__ */ new Map(),
|
|
1542
1495
|
pluginOptions,
|
|
1543
|
-
abort: () => abortController?.abort(),
|
|
1544
1496
|
stateManager,
|
|
1545
1497
|
eventEmitter
|
|
1546
1498
|
});
|
|
@@ -1567,7 +1519,6 @@ function createInfiniteReadController(options) {
|
|
|
1567
1519
|
const fetchPromise = (async () => {
|
|
1568
1520
|
try {
|
|
1569
1521
|
const response = await fetchFn(mergedRequest, signal);
|
|
1570
|
-
context.response = response;
|
|
1571
1522
|
if (signal.aborted) {
|
|
1572
1523
|
return {
|
|
1573
1524
|
status: 0,
|
|
@@ -1589,7 +1540,6 @@ function createInfiniteReadController(options) {
|
|
|
1589
1540
|
error: err,
|
|
1590
1541
|
data: void 0
|
|
1591
1542
|
};
|
|
1592
|
-
context.response = errorResponse;
|
|
1593
1543
|
latestError = err;
|
|
1594
1544
|
return errorResponse;
|
|
1595
1545
|
} finally {
|
|
@@ -1764,15 +1714,12 @@ export {
|
|
|
1764
1714
|
HTTP_METHODS,
|
|
1765
1715
|
Spoosh,
|
|
1766
1716
|
__DEV__,
|
|
1767
|
-
applyMiddlewares,
|
|
1768
1717
|
buildUrl,
|
|
1769
|
-
composeMiddlewares,
|
|
1770
1718
|
containsFile,
|
|
1771
1719
|
createClient,
|
|
1772
1720
|
createEventEmitter,
|
|
1773
1721
|
createInfiniteReadController,
|
|
1774
1722
|
createInitialState,
|
|
1775
|
-
createMiddleware,
|
|
1776
1723
|
createOperationController,
|
|
1777
1724
|
createPluginExecutor,
|
|
1778
1725
|
createPluginRegistry,
|