@spoosh/core 0.12.0 → 0.12.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
@@ -164,7 +164,7 @@ import { Spoosh } from "@spoosh/core";
164
164
  import { cachePlugin } from "@spoosh/plugin-cache";
165
165
  import { retryPlugin } from "@spoosh/plugin-retry";
166
166
 
167
- const client = new Spoosh<ApiSchema, Error>("/api", {
167
+ const spoosh = new Spoosh<ApiSchema, Error>("/api", {
168
168
  headers: { Authorization: "Bearer token" },
169
169
  }).use([cachePlugin({ staleTime: 5000 }), retryPlugin({ retries: 3 })]);
170
170
 
package/dist/index.d.mts CHANGED
@@ -82,10 +82,6 @@ interface TransportOptionsMap {
82
82
  fetch: never;
83
83
  }
84
84
 
85
- type RetryConfig = {
86
- retries?: number | false;
87
- retryDelay?: number;
88
- };
89
85
  type HeadersInitOrGetter = HeadersInit | (() => HeadersInit | Promise<HeadersInit>);
90
86
  type SpooshOptions = Omit<RequestInit, "method" | "body" | "headers"> & {
91
87
  headers?: HeadersInitOrGetter;
@@ -134,7 +130,7 @@ type AnyRequestOptions = BaseRequestOptions$1 & {
134
130
  transport?: TransportOption;
135
131
  /** Transport-specific options passed through to the transport function. */
136
132
  transportOptions?: unknown;
137
- } & Partial<RetryConfig>;
133
+ };
138
134
  type DynamicParamsOption = {
139
135
  params?: Record<string, string | number>;
140
136
  };
@@ -270,7 +266,7 @@ type CacheEntry<TData = unknown, TError = unknown> = {
270
266
  stale?: boolean;
271
267
  };
272
268
  /** RequestOptions in plugin context have headers already resolved to Record */
273
- type PluginRequestOptions = Omit<AnyRequestOptions, "headers"> & {
269
+ type PluginRequestOptions = Omit<AnyRequestOptions, "headers" | "cache"> & {
274
270
  headers: Record<string, string>;
275
271
  };
276
272
  type PluginContext = {
@@ -318,12 +314,9 @@ type PluginContextInput = Omit<PluginContext, "plugins">;
318
314
  * return next();
319
315
  * }
320
316
  *
321
- * // Retry middleware - wrap and retry on error
317
+ * // Auth middleware - add authentication headers
322
318
  * middleware: async (context, next) => {
323
- * for (let i = 0; i < 3; i++) {
324
- * const result = await next();
325
- * if (!result.error) return result;
326
- * }
319
+ * context.request.headers['Authorization'] = `Bearer ${getToken()}`;
327
320
  * return next();
328
321
  * }
329
322
  * ```
@@ -379,7 +372,7 @@ type PluginTypeConfig = {
379
372
  * Base interface for Spoosh plugins.
380
373
  *
381
374
  * Plugins can implement:
382
- * - `middleware`: Wraps the fetch flow for full control (intercept, retry, transform)
375
+ * - `middleware`: Wraps the fetch flow for full control (intercept, transform, modify)
383
376
  * - `afterResponse`: Called after every response, regardless of early returns
384
377
  * - `lifecycle`: Component lifecycle hooks (onMount, onUpdate, onUnmount)
385
378
  * - `exports`: Functions/variables accessible to other plugins
@@ -427,7 +420,7 @@ interface SpooshPlugin<T extends PluginTypeConfig = PluginTypeConfig> {
427
420
  /** Expose functions/variables for other plugins to access via `context.plugins.get(name)` */
428
421
  exports?: (context: PluginContext) => object;
429
422
  /**
430
- * Expose functions/properties on the framework adapter return value (e.g., createReactSpoosh).
423
+ * Expose functions/properties on the framework adapter return value (e.g., create).
431
424
  * Unlike `exports`, these are accessible directly from the instance, not just within plugin context.
432
425
  *
433
426
  * @example
@@ -441,7 +434,37 @@ interface SpooshPlugin<T extends PluginTypeConfig = PluginTypeConfig> {
441
434
  instanceApi?: (context: InstanceApiContext) => T extends {
442
435
  instanceApi: infer A;
443
436
  } ? A : object;
444
- /** Declare plugin dependencies. These plugins must be registered before this one. */
437
+ /**
438
+ * Plugin execution priority. Lower numbers run first, higher numbers run last.
439
+ * Default: 0
440
+ *
441
+ * @example
442
+ * ```ts
443
+ * // Cache plugin runs early (checks cache before other plugins)
444
+ * { name: "cache", priority: -10, ... }
445
+ *
446
+ * // Throttle plugin runs last (blocks all requests including force fetches)
447
+ * { name: "throttle", priority: 100, ... }
448
+ *
449
+ * // Most plugins use default priority
450
+ * { name: "retry", priority: 0, ... } // or omit priority
451
+ * ```
452
+ */
453
+ priority?: number;
454
+ /**
455
+ * List of plugin names that this plugin depends on.
456
+ * Used to validate that required plugins are registered.
457
+ * Does not affect execution order - use `priority` for that.
458
+ *
459
+ * @example
460
+ * ```ts
461
+ * {
462
+ * name: "spoosh:optimistic",
463
+ * dependencies: ["spoosh:invalidation"],
464
+ * // ...
465
+ * }
466
+ * ```
467
+ */
445
468
  dependencies?: string[];
446
469
  /** @internal Type carrier for inference - do not use directly */
447
470
  readonly _types?: T;
@@ -1132,8 +1155,8 @@ type SpooshInstance<TSchema = unknown, TDefaultError = unknown, TPlugins extends
1132
1155
  *
1133
1156
  * @example Basic usage
1134
1157
  * ```ts
1135
- * const client = new Spoosh<ApiSchema, Error>('/api')
1136
- * .use([cachePlugin(), retryPlugin()]);
1158
+ * const spoosh = new Spoosh<ApiSchema, Error>('/api')
1159
+ * .use([cachePlugin(), debugPlugin()]);
1137
1160
  *
1138
1161
  * const { api } = client;
1139
1162
  * const response = await api("posts").GET();
@@ -1141,19 +1164,19 @@ type SpooshInstance<TSchema = unknown, TDefaultError = unknown, TPlugins extends
1141
1164
  *
1142
1165
  * @example With default options
1143
1166
  * ```ts
1144
- * const client = new Spoosh<ApiSchema, Error>('/api', {
1167
+ * const spoosh = new Spoosh<ApiSchema, Error>('/api', {
1145
1168
  * headers: { 'Authorization': 'Bearer token' }
1146
1169
  * }).use([cachePlugin()]);
1147
1170
  * ```
1148
1171
  *
1149
1172
  * @example With React hooks
1150
1173
  * ```ts
1151
- * import { createReactSpoosh } from '@spoosh/react';
1174
+ * import { create } from '@spoosh/react';
1152
1175
  *
1153
- * const client = new Spoosh<ApiSchema, Error>('/api')
1154
- * .use([cachePlugin(), retryPlugin()]);
1176
+ * const spoosh = new Spoosh<ApiSchema, Error>('/api')
1177
+ * .use([cachePlugin(), prefetchPlugin()]);
1155
1178
  *
1156
- * const { useRead, useWrite } = createReactSpoosh(client);
1179
+ * const { useRead, useWrite } = create(client);
1157
1180
  *
1158
1181
  * // In component
1159
1182
  * const { data } = useRead((api) => api("posts").GET());
@@ -1176,15 +1199,15 @@ declare class Spoosh<TSchema = unknown, TError = unknown, TPlugins extends Plugi
1176
1199
  * @example
1177
1200
  * ```ts
1178
1201
  * // Simple usage
1179
- * const client = new Spoosh<ApiSchema, Error>('/api');
1202
+ * const spoosh = new Spoosh<ApiSchema, Error>('/api');
1180
1203
  *
1181
1204
  * // With default headers
1182
- * const client = new Spoosh<ApiSchema, Error>('/api', {
1205
+ * const spoosh = new Spoosh<ApiSchema, Error>('/api', {
1183
1206
  * headers: { 'X-API-Key': 'secret' }
1184
1207
  * });
1185
1208
  *
1186
1209
  * // With XHR transport (narrows available options to XHR-compatible fields)
1187
- * const client = new Spoosh<ApiSchema, Error>('/api', {
1210
+ * const spoosh = new Spoosh<ApiSchema, Error>('/api', {
1188
1211
  * transport: 'xhr',
1189
1212
  * credentials: 'include',
1190
1213
  * });
@@ -1201,26 +1224,10 @@ declare class Spoosh<TSchema = unknown, TError = unknown, TPlugins extends Plugi
1201
1224
  * @param plugins - Array of plugin instances to use
1202
1225
  * @returns A new Spoosh instance with the specified plugins
1203
1226
  *
1204
- * @example Single use() call
1205
- * ```ts
1206
- * const client = new Spoosh<Schema, Error>('/api')
1207
- * .use([cachePlugin(), retryPlugin(), debouncePlugin()]);
1208
- * ```
1209
- *
1210
- * @example Chaining use() calls (replaces plugins)
1211
- * ```ts
1212
- * const client1 = new Spoosh<Schema, Error>('/api')
1213
- * .use([cachePlugin()]);
1214
- *
1215
- * // This replaces cachePlugin with retryPlugin
1216
- * const client2 = client1.use([retryPlugin()]);
1217
- * ```
1218
- *
1219
- * @example With plugin configuration
1220
1227
  * ```ts
1221
- * const client = new Spoosh<Schema, Error>('/api').use([
1228
+ * const spoosh = new Spoosh<Schema, Error>('/api').use([
1222
1229
  * cachePlugin({ staleTime: 5000 }),
1223
- * retryPlugin({ retries: 3, retryDelay: 1000 }),
1230
+ * invalidationPlugin(),
1224
1231
  * prefetchPlugin(),
1225
1232
  * ]);
1226
1233
  * ```
@@ -1245,7 +1252,7 @@ declare class Spoosh<TSchema = unknown, TError = unknown, TPlugins extends Plugi
1245
1252
  *
1246
1253
  * @example
1247
1254
  * ```ts
1248
- * const client = new Spoosh<ApiSchema, Error>('/api').use([...]);
1255
+ * const spoosh = new Spoosh<ApiSchema, Error>('/api').use([...]);
1249
1256
  * const { api } = client;
1250
1257
  *
1251
1258
  * // GET request
@@ -1436,6 +1443,9 @@ type TagOptions = {
1436
1443
  declare function resolveTags(options: TagOptions | undefined, resolvedPath: string[]): string[];
1437
1444
  declare function resolvePath(path: string[], params: Record<string, string | number> | undefined): string[];
1438
1445
 
1446
+ declare const isNetworkError: (err: unknown) => boolean;
1447
+ declare const isAbortError: (err: unknown) => boolean;
1448
+
1439
1449
  type ProxyHandlerConfig<TOptions = SpooshOptions> = {
1440
1450
  baseUrl: string;
1441
1451
  defaultOptions: TOptions;
@@ -1670,4 +1680,4 @@ type CreateInfiniteReadOptions<TData, TItem, TError, TRequest> = {
1670
1680
  };
1671
1681
  declare function createInfiniteReadController<TData, TItem, TError, TRequest extends InfiniteRequestOptions = InfiniteRequestOptions>(options: CreateInfiniteReadOptions<TData, TItem, TError, TRequest>): InfiniteReadController<TData, TItem, TError>;
1672
1682
 
1673
- 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 };
1683
+ 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 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, isAbortError, isJsonBody, isNetworkError, isSpooshBody, json, mergeHeaders, objectToFormData, objectToUrlEncoded, resolveHeadersToRecord, resolvePath, resolveRequestBody, resolveTags, setHeaders, sortObjectKeys, urlencoded, xhrTransport };
package/dist/index.d.ts CHANGED
@@ -82,10 +82,6 @@ interface TransportOptionsMap {
82
82
  fetch: never;
83
83
  }
84
84
 
85
- type RetryConfig = {
86
- retries?: number | false;
87
- retryDelay?: number;
88
- };
89
85
  type HeadersInitOrGetter = HeadersInit | (() => HeadersInit | Promise<HeadersInit>);
90
86
  type SpooshOptions = Omit<RequestInit, "method" | "body" | "headers"> & {
91
87
  headers?: HeadersInitOrGetter;
@@ -134,7 +130,7 @@ type AnyRequestOptions = BaseRequestOptions$1 & {
134
130
  transport?: TransportOption;
135
131
  /** Transport-specific options passed through to the transport function. */
136
132
  transportOptions?: unknown;
137
- } & Partial<RetryConfig>;
133
+ };
138
134
  type DynamicParamsOption = {
139
135
  params?: Record<string, string | number>;
140
136
  };
@@ -270,7 +266,7 @@ type CacheEntry<TData = unknown, TError = unknown> = {
270
266
  stale?: boolean;
271
267
  };
272
268
  /** RequestOptions in plugin context have headers already resolved to Record */
273
- type PluginRequestOptions = Omit<AnyRequestOptions, "headers"> & {
269
+ type PluginRequestOptions = Omit<AnyRequestOptions, "headers" | "cache"> & {
274
270
  headers: Record<string, string>;
275
271
  };
276
272
  type PluginContext = {
@@ -318,12 +314,9 @@ type PluginContextInput = Omit<PluginContext, "plugins">;
318
314
  * return next();
319
315
  * }
320
316
  *
321
- * // Retry middleware - wrap and retry on error
317
+ * // Auth middleware - add authentication headers
322
318
  * middleware: async (context, next) => {
323
- * for (let i = 0; i < 3; i++) {
324
- * const result = await next();
325
- * if (!result.error) return result;
326
- * }
319
+ * context.request.headers['Authorization'] = `Bearer ${getToken()}`;
327
320
  * return next();
328
321
  * }
329
322
  * ```
@@ -379,7 +372,7 @@ type PluginTypeConfig = {
379
372
  * Base interface for Spoosh plugins.
380
373
  *
381
374
  * Plugins can implement:
382
- * - `middleware`: Wraps the fetch flow for full control (intercept, retry, transform)
375
+ * - `middleware`: Wraps the fetch flow for full control (intercept, transform, modify)
383
376
  * - `afterResponse`: Called after every response, regardless of early returns
384
377
  * - `lifecycle`: Component lifecycle hooks (onMount, onUpdate, onUnmount)
385
378
  * - `exports`: Functions/variables accessible to other plugins
@@ -427,7 +420,7 @@ interface SpooshPlugin<T extends PluginTypeConfig = PluginTypeConfig> {
427
420
  /** Expose functions/variables for other plugins to access via `context.plugins.get(name)` */
428
421
  exports?: (context: PluginContext) => object;
429
422
  /**
430
- * Expose functions/properties on the framework adapter return value (e.g., createReactSpoosh).
423
+ * Expose functions/properties on the framework adapter return value (e.g., create).
431
424
  * Unlike `exports`, these are accessible directly from the instance, not just within plugin context.
432
425
  *
433
426
  * @example
@@ -441,7 +434,37 @@ interface SpooshPlugin<T extends PluginTypeConfig = PluginTypeConfig> {
441
434
  instanceApi?: (context: InstanceApiContext) => T extends {
442
435
  instanceApi: infer A;
443
436
  } ? A : object;
444
- /** Declare plugin dependencies. These plugins must be registered before this one. */
437
+ /**
438
+ * Plugin execution priority. Lower numbers run first, higher numbers run last.
439
+ * Default: 0
440
+ *
441
+ * @example
442
+ * ```ts
443
+ * // Cache plugin runs early (checks cache before other plugins)
444
+ * { name: "cache", priority: -10, ... }
445
+ *
446
+ * // Throttle plugin runs last (blocks all requests including force fetches)
447
+ * { name: "throttle", priority: 100, ... }
448
+ *
449
+ * // Most plugins use default priority
450
+ * { name: "retry", priority: 0, ... } // or omit priority
451
+ * ```
452
+ */
453
+ priority?: number;
454
+ /**
455
+ * List of plugin names that this plugin depends on.
456
+ * Used to validate that required plugins are registered.
457
+ * Does not affect execution order - use `priority` for that.
458
+ *
459
+ * @example
460
+ * ```ts
461
+ * {
462
+ * name: "spoosh:optimistic",
463
+ * dependencies: ["spoosh:invalidation"],
464
+ * // ...
465
+ * }
466
+ * ```
467
+ */
445
468
  dependencies?: string[];
446
469
  /** @internal Type carrier for inference - do not use directly */
447
470
  readonly _types?: T;
@@ -1132,8 +1155,8 @@ type SpooshInstance<TSchema = unknown, TDefaultError = unknown, TPlugins extends
1132
1155
  *
1133
1156
  * @example Basic usage
1134
1157
  * ```ts
1135
- * const client = new Spoosh<ApiSchema, Error>('/api')
1136
- * .use([cachePlugin(), retryPlugin()]);
1158
+ * const spoosh = new Spoosh<ApiSchema, Error>('/api')
1159
+ * .use([cachePlugin(), debugPlugin()]);
1137
1160
  *
1138
1161
  * const { api } = client;
1139
1162
  * const response = await api("posts").GET();
@@ -1141,19 +1164,19 @@ type SpooshInstance<TSchema = unknown, TDefaultError = unknown, TPlugins extends
1141
1164
  *
1142
1165
  * @example With default options
1143
1166
  * ```ts
1144
- * const client = new Spoosh<ApiSchema, Error>('/api', {
1167
+ * const spoosh = new Spoosh<ApiSchema, Error>('/api', {
1145
1168
  * headers: { 'Authorization': 'Bearer token' }
1146
1169
  * }).use([cachePlugin()]);
1147
1170
  * ```
1148
1171
  *
1149
1172
  * @example With React hooks
1150
1173
  * ```ts
1151
- * import { createReactSpoosh } from '@spoosh/react';
1174
+ * import { create } from '@spoosh/react';
1152
1175
  *
1153
- * const client = new Spoosh<ApiSchema, Error>('/api')
1154
- * .use([cachePlugin(), retryPlugin()]);
1176
+ * const spoosh = new Spoosh<ApiSchema, Error>('/api')
1177
+ * .use([cachePlugin(), prefetchPlugin()]);
1155
1178
  *
1156
- * const { useRead, useWrite } = createReactSpoosh(client);
1179
+ * const { useRead, useWrite } = create(client);
1157
1180
  *
1158
1181
  * // In component
1159
1182
  * const { data } = useRead((api) => api("posts").GET());
@@ -1176,15 +1199,15 @@ declare class Spoosh<TSchema = unknown, TError = unknown, TPlugins extends Plugi
1176
1199
  * @example
1177
1200
  * ```ts
1178
1201
  * // Simple usage
1179
- * const client = new Spoosh<ApiSchema, Error>('/api');
1202
+ * const spoosh = new Spoosh<ApiSchema, Error>('/api');
1180
1203
  *
1181
1204
  * // With default headers
1182
- * const client = new Spoosh<ApiSchema, Error>('/api', {
1205
+ * const spoosh = new Spoosh<ApiSchema, Error>('/api', {
1183
1206
  * headers: { 'X-API-Key': 'secret' }
1184
1207
  * });
1185
1208
  *
1186
1209
  * // With XHR transport (narrows available options to XHR-compatible fields)
1187
- * const client = new Spoosh<ApiSchema, Error>('/api', {
1210
+ * const spoosh = new Spoosh<ApiSchema, Error>('/api', {
1188
1211
  * transport: 'xhr',
1189
1212
  * credentials: 'include',
1190
1213
  * });
@@ -1201,26 +1224,10 @@ declare class Spoosh<TSchema = unknown, TError = unknown, TPlugins extends Plugi
1201
1224
  * @param plugins - Array of plugin instances to use
1202
1225
  * @returns A new Spoosh instance with the specified plugins
1203
1226
  *
1204
- * @example Single use() call
1205
- * ```ts
1206
- * const client = new Spoosh<Schema, Error>('/api')
1207
- * .use([cachePlugin(), retryPlugin(), debouncePlugin()]);
1208
- * ```
1209
- *
1210
- * @example Chaining use() calls (replaces plugins)
1211
- * ```ts
1212
- * const client1 = new Spoosh<Schema, Error>('/api')
1213
- * .use([cachePlugin()]);
1214
- *
1215
- * // This replaces cachePlugin with retryPlugin
1216
- * const client2 = client1.use([retryPlugin()]);
1217
- * ```
1218
- *
1219
- * @example With plugin configuration
1220
1227
  * ```ts
1221
- * const client = new Spoosh<Schema, Error>('/api').use([
1228
+ * const spoosh = new Spoosh<Schema, Error>('/api').use([
1222
1229
  * cachePlugin({ staleTime: 5000 }),
1223
- * retryPlugin({ retries: 3, retryDelay: 1000 }),
1230
+ * invalidationPlugin(),
1224
1231
  * prefetchPlugin(),
1225
1232
  * ]);
1226
1233
  * ```
@@ -1245,7 +1252,7 @@ declare class Spoosh<TSchema = unknown, TError = unknown, TPlugins extends Plugi
1245
1252
  *
1246
1253
  * @example
1247
1254
  * ```ts
1248
- * const client = new Spoosh<ApiSchema, Error>('/api').use([...]);
1255
+ * const spoosh = new Spoosh<ApiSchema, Error>('/api').use([...]);
1249
1256
  * const { api } = client;
1250
1257
  *
1251
1258
  * // GET request
@@ -1436,6 +1443,9 @@ type TagOptions = {
1436
1443
  declare function resolveTags(options: TagOptions | undefined, resolvedPath: string[]): string[];
1437
1444
  declare function resolvePath(path: string[], params: Record<string, string | number> | undefined): string[];
1438
1445
 
1446
+ declare const isNetworkError: (err: unknown) => boolean;
1447
+ declare const isAbortError: (err: unknown) => boolean;
1448
+
1439
1449
  type ProxyHandlerConfig<TOptions = SpooshOptions> = {
1440
1450
  baseUrl: string;
1441
1451
  defaultOptions: TOptions;
@@ -1670,4 +1680,4 @@ type CreateInfiniteReadOptions<TData, TItem, TError, TRequest> = {
1670
1680
  };
1671
1681
  declare function createInfiniteReadController<TData, TItem, TError, TRequest extends InfiniteRequestOptions = InfiniteRequestOptions>(options: CreateInfiniteReadOptions<TData, TItem, TError, TRequest>): InfiniteReadController<TData, TItem, TError>;
1672
1682
 
1673
- 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 };
1683
+ 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 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, isAbortError, isJsonBody, isNetworkError, isSpooshBody, json, mergeHeaders, objectToFormData, objectToUrlEncoded, resolveHeadersToRecord, resolvePath, resolveRequestBody, resolveTags, setHeaders, sortObjectKeys, urlencoded, xhrTransport };
package/dist/index.js CHANGED
@@ -42,7 +42,9 @@ __export(src_exports, {
42
42
  form: () => form,
43
43
  generateTags: () => generateTags,
44
44
  getContentType: () => getContentType,
45
+ isAbortError: () => isAbortError,
45
46
  isJsonBody: () => isJsonBody,
47
+ isNetworkError: () => isNetworkError,
46
48
  isSpooshBody: () => isSpooshBody,
47
49
  json: () => json,
48
50
  mergeHeaders: () => mergeHeaders,
@@ -352,6 +354,10 @@ function resolvePath(path, params) {
352
354
  });
353
355
  }
354
356
 
357
+ // src/utils/errors.ts
358
+ var isNetworkError = (err) => err instanceof TypeError;
359
+ var isAbortError = (err) => err instanceof DOMException && err.name === "AbortError";
360
+
355
361
  // src/transport/fetch.ts
356
362
  var fetchTransport = async (url, init) => {
357
363
  const res = await fetch(url, init);
@@ -434,9 +440,6 @@ var xhrTransport = (url, init, options) => {
434
440
  };
435
441
 
436
442
  // src/fetch.ts
437
- var delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
438
- var isNetworkError = (err) => err instanceof TypeError;
439
- var isAbortError = (err) => err instanceof DOMException && err.name === "AbortError";
440
443
  async function executeFetch(baseUrl, path, method, defaultOptions, requestOptions, nextTags) {
441
444
  return executeCoreFetch({
442
445
  baseUrl,
@@ -486,9 +489,6 @@ async function executeCoreFetch(config) {
486
489
  ...fetchDefaults
487
490
  } = defaultOptions;
488
491
  const inputFields = buildInputFields(requestOptions);
489
- const maxRetries = requestOptions?.retries ?? 3;
490
- const baseDelay = requestOptions?.retryDelay ?? 1e3;
491
- const retryCount = maxRetries === false ? 0 : maxRetries;
492
492
  const finalPath = path;
493
493
  const url = buildUrl(baseUrl, finalPath, requestOptions?.query);
494
494
  let headers = await mergeHeaders(defaultHeaders, requestOptions?.headers);
@@ -529,50 +529,40 @@ async function executeCoreFetch(config) {
529
529
  const resolvedTransport = resolveTransport(
530
530
  requestOptions?.transport ?? defaultTransport
531
531
  );
532
- let lastError;
533
- for (let attempt = 0; attempt <= retryCount; attempt++) {
534
- try {
535
- const result = await resolvedTransport(
536
- url,
537
- fetchInit,
538
- requestOptions?.transportOptions
539
- );
540
- if (result.ok) {
541
- return {
542
- status: result.status,
543
- data: result.data,
544
- headers: result.headers,
545
- error: void 0,
546
- ...inputFields
547
- };
548
- }
532
+ try {
533
+ const result = await resolvedTransport(
534
+ url,
535
+ fetchInit,
536
+ requestOptions?.transportOptions
537
+ );
538
+ if (result.ok) {
549
539
  return {
550
540
  status: result.status,
551
- error: result.data,
541
+ data: result.data,
552
542
  headers: result.headers,
543
+ error: void 0,
544
+ ...inputFields
545
+ };
546
+ }
547
+ return {
548
+ status: result.status,
549
+ error: result.data,
550
+ headers: result.headers,
551
+ data: void 0,
552
+ ...inputFields
553
+ };
554
+ } catch (err) {
555
+ if (isAbortError(err)) {
556
+ return {
557
+ status: 0,
558
+ error: err,
553
559
  data: void 0,
560
+ aborted: true,
554
561
  ...inputFields
555
562
  };
556
- } catch (err) {
557
- if (isAbortError(err)) {
558
- return {
559
- status: 0,
560
- error: err,
561
- data: void 0,
562
- aborted: true,
563
- ...inputFields
564
- };
565
- }
566
- lastError = err;
567
- if (isNetworkError(err) && attempt < retryCount) {
568
- const delayMs = baseDelay * Math.pow(2, attempt);
569
- await delay(delayMs);
570
- continue;
571
- }
572
- return { status: 0, error: lastError, data: void 0, ...inputFields };
573
563
  }
564
+ return { status: 0, error: err, data: void 0, ...inputFields };
574
565
  }
575
- return { status: 0, error: lastError, data: void 0, ...inputFields };
576
566
  }
577
567
 
578
568
  // src/proxy/handler.ts
@@ -865,46 +855,29 @@ function createEventEmitter() {
865
855
 
866
856
  // src/plugins/executor.ts
867
857
  function validateDependencies(plugins) {
868
- const names = new Set(plugins.map((p) => p.name));
858
+ const pluginNames = new Set(plugins.map((p) => p.name));
869
859
  for (const plugin of plugins) {
870
- for (const dep of plugin.dependencies ?? []) {
871
- if (!names.has(dep)) {
872
- throw new Error(
873
- `Plugin "${plugin.name}" depends on "${dep}" which is not registered`
874
- );
860
+ if (plugin.dependencies) {
861
+ for (const dep of plugin.dependencies) {
862
+ if (!pluginNames.has(dep)) {
863
+ throw new Error(
864
+ `Plugin "${plugin.name}" depends on "${dep}", but "${dep}" is not registered.`
865
+ );
866
+ }
875
867
  }
876
868
  }
877
869
  }
878
870
  }
879
- function sortByDependencies(plugins) {
880
- const sorted = [];
881
- const visited = /* @__PURE__ */ new Set();
882
- const visiting = /* @__PURE__ */ new Set();
883
- const pluginMap = new Map(plugins.map((p) => [p.name, p]));
884
- function visit(plugin) {
885
- if (visited.has(plugin.name)) return;
886
- if (visiting.has(plugin.name)) {
887
- throw new Error(
888
- `Circular dependency detected involving "${plugin.name}"`
889
- );
890
- }
891
- visiting.add(plugin.name);
892
- for (const dep of plugin.dependencies ?? []) {
893
- const depPlugin = pluginMap.get(dep);
894
- if (depPlugin) visit(depPlugin);
895
- }
896
- visiting.delete(plugin.name);
897
- visited.add(plugin.name);
898
- sorted.push(plugin);
899
- }
900
- for (const plugin of plugins) {
901
- visit(plugin);
902
- }
903
- return sorted;
871
+ function sortByPriority(plugins) {
872
+ return [...plugins].sort((a, b) => {
873
+ const priorityA = a.priority ?? 0;
874
+ const priorityB = b.priority ?? 0;
875
+ return priorityA - priorityB;
876
+ });
904
877
  }
905
878
  function createPluginExecutor(initialPlugins = []) {
906
879
  validateDependencies(initialPlugins);
907
- const plugins = sortByDependencies(initialPlugins);
880
+ const plugins = sortByPriority(initialPlugins);
908
881
  const frozenPlugins = Object.freeze([...plugins]);
909
882
  const createPluginAccessor = (context) => ({
910
883
  get(name) {
@@ -1007,15 +980,15 @@ var Spoosh = class _Spoosh {
1007
980
  * @example
1008
981
  * ```ts
1009
982
  * // Simple usage
1010
- * const client = new Spoosh<ApiSchema, Error>('/api');
983
+ * const spoosh = new Spoosh<ApiSchema, Error>('/api');
1011
984
  *
1012
985
  * // With default headers
1013
- * const client = new Spoosh<ApiSchema, Error>('/api', {
986
+ * const spoosh = new Spoosh<ApiSchema, Error>('/api', {
1014
987
  * headers: { 'X-API-Key': 'secret' }
1015
988
  * });
1016
989
  *
1017
990
  * // With XHR transport (narrows available options to XHR-compatible fields)
1018
- * const client = new Spoosh<ApiSchema, Error>('/api', {
991
+ * const spoosh = new Spoosh<ApiSchema, Error>('/api', {
1019
992
  * transport: 'xhr',
1020
993
  * credentials: 'include',
1021
994
  * });
@@ -1036,26 +1009,10 @@ var Spoosh = class _Spoosh {
1036
1009
  * @param plugins - Array of plugin instances to use
1037
1010
  * @returns A new Spoosh instance with the specified plugins
1038
1011
  *
1039
- * @example Single use() call
1040
- * ```ts
1041
- * const client = new Spoosh<Schema, Error>('/api')
1042
- * .use([cachePlugin(), retryPlugin(), debouncePlugin()]);
1043
- * ```
1044
- *
1045
- * @example Chaining use() calls (replaces plugins)
1046
- * ```ts
1047
- * const client1 = new Spoosh<Schema, Error>('/api')
1048
- * .use([cachePlugin()]);
1049
- *
1050
- * // This replaces cachePlugin with retryPlugin
1051
- * const client2 = client1.use([retryPlugin()]);
1052
- * ```
1053
- *
1054
- * @example With plugin configuration
1055
1012
  * ```ts
1056
- * const client = new Spoosh<Schema, Error>('/api').use([
1013
+ * const spoosh = new Spoosh<Schema, Error>('/api').use([
1057
1014
  * cachePlugin({ staleTime: 5000 }),
1058
- * retryPlugin({ retries: 3, retryDelay: 1000 }),
1015
+ * invalidationPlugin(),
1059
1016
  * prefetchPlugin(),
1060
1017
  * ]);
1061
1018
  * ```
@@ -1112,7 +1069,7 @@ var Spoosh = class _Spoosh {
1112
1069
  *
1113
1070
  * @example
1114
1071
  * ```ts
1115
- * const client = new Spoosh<ApiSchema, Error>('/api').use([...]);
1072
+ * const spoosh = new Spoosh<ApiSchema, Error>('/api').use([...]);
1116
1073
  * const { api } = client;
1117
1074
  *
1118
1075
  * // GET request
package/dist/index.mjs CHANGED
@@ -291,6 +291,10 @@ function resolvePath(path, params) {
291
291
  });
292
292
  }
293
293
 
294
+ // src/utils/errors.ts
295
+ var isNetworkError = (err) => err instanceof TypeError;
296
+ var isAbortError = (err) => err instanceof DOMException && err.name === "AbortError";
297
+
294
298
  // src/transport/fetch.ts
295
299
  var fetchTransport = async (url, init) => {
296
300
  const res = await fetch(url, init);
@@ -373,9 +377,6 @@ var xhrTransport = (url, init, options) => {
373
377
  };
374
378
 
375
379
  // src/fetch.ts
376
- var delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
377
- var isNetworkError = (err) => err instanceof TypeError;
378
- var isAbortError = (err) => err instanceof DOMException && err.name === "AbortError";
379
380
  async function executeFetch(baseUrl, path, method, defaultOptions, requestOptions, nextTags) {
380
381
  return executeCoreFetch({
381
382
  baseUrl,
@@ -425,9 +426,6 @@ async function executeCoreFetch(config) {
425
426
  ...fetchDefaults
426
427
  } = defaultOptions;
427
428
  const inputFields = buildInputFields(requestOptions);
428
- const maxRetries = requestOptions?.retries ?? 3;
429
- const baseDelay = requestOptions?.retryDelay ?? 1e3;
430
- const retryCount = maxRetries === false ? 0 : maxRetries;
431
429
  const finalPath = path;
432
430
  const url = buildUrl(baseUrl, finalPath, requestOptions?.query);
433
431
  let headers = await mergeHeaders(defaultHeaders, requestOptions?.headers);
@@ -468,50 +466,40 @@ async function executeCoreFetch(config) {
468
466
  const resolvedTransport = resolveTransport(
469
467
  requestOptions?.transport ?? defaultTransport
470
468
  );
471
- let lastError;
472
- for (let attempt = 0; attempt <= retryCount; attempt++) {
473
- try {
474
- const result = await resolvedTransport(
475
- url,
476
- fetchInit,
477
- requestOptions?.transportOptions
478
- );
479
- if (result.ok) {
480
- return {
481
- status: result.status,
482
- data: result.data,
483
- headers: result.headers,
484
- error: void 0,
485
- ...inputFields
486
- };
487
- }
469
+ try {
470
+ const result = await resolvedTransport(
471
+ url,
472
+ fetchInit,
473
+ requestOptions?.transportOptions
474
+ );
475
+ if (result.ok) {
488
476
  return {
489
477
  status: result.status,
490
- error: result.data,
478
+ data: result.data,
491
479
  headers: result.headers,
480
+ error: void 0,
481
+ ...inputFields
482
+ };
483
+ }
484
+ return {
485
+ status: result.status,
486
+ error: result.data,
487
+ headers: result.headers,
488
+ data: void 0,
489
+ ...inputFields
490
+ };
491
+ } catch (err) {
492
+ if (isAbortError(err)) {
493
+ return {
494
+ status: 0,
495
+ error: err,
492
496
  data: void 0,
497
+ aborted: true,
493
498
  ...inputFields
494
499
  };
495
- } catch (err) {
496
- if (isAbortError(err)) {
497
- return {
498
- status: 0,
499
- error: err,
500
- data: void 0,
501
- aborted: true,
502
- ...inputFields
503
- };
504
- }
505
- lastError = err;
506
- if (isNetworkError(err) && attempt < retryCount) {
507
- const delayMs = baseDelay * Math.pow(2, attempt);
508
- await delay(delayMs);
509
- continue;
510
- }
511
- return { status: 0, error: lastError, data: void 0, ...inputFields };
512
500
  }
501
+ return { status: 0, error: err, data: void 0, ...inputFields };
513
502
  }
514
- return { status: 0, error: lastError, data: void 0, ...inputFields };
515
503
  }
516
504
 
517
505
  // src/proxy/handler.ts
@@ -804,46 +792,29 @@ function createEventEmitter() {
804
792
 
805
793
  // src/plugins/executor.ts
806
794
  function validateDependencies(plugins) {
807
- const names = new Set(plugins.map((p) => p.name));
795
+ const pluginNames = new Set(plugins.map((p) => p.name));
808
796
  for (const plugin of plugins) {
809
- for (const dep of plugin.dependencies ?? []) {
810
- if (!names.has(dep)) {
811
- throw new Error(
812
- `Plugin "${plugin.name}" depends on "${dep}" which is not registered`
813
- );
797
+ if (plugin.dependencies) {
798
+ for (const dep of plugin.dependencies) {
799
+ if (!pluginNames.has(dep)) {
800
+ throw new Error(
801
+ `Plugin "${plugin.name}" depends on "${dep}", but "${dep}" is not registered.`
802
+ );
803
+ }
814
804
  }
815
805
  }
816
806
  }
817
807
  }
818
- function sortByDependencies(plugins) {
819
- const sorted = [];
820
- const visited = /* @__PURE__ */ new Set();
821
- const visiting = /* @__PURE__ */ new Set();
822
- const pluginMap = new Map(plugins.map((p) => [p.name, p]));
823
- function visit(plugin) {
824
- if (visited.has(plugin.name)) return;
825
- if (visiting.has(plugin.name)) {
826
- throw new Error(
827
- `Circular dependency detected involving "${plugin.name}"`
828
- );
829
- }
830
- visiting.add(plugin.name);
831
- for (const dep of plugin.dependencies ?? []) {
832
- const depPlugin = pluginMap.get(dep);
833
- if (depPlugin) visit(depPlugin);
834
- }
835
- visiting.delete(plugin.name);
836
- visited.add(plugin.name);
837
- sorted.push(plugin);
838
- }
839
- for (const plugin of plugins) {
840
- visit(plugin);
841
- }
842
- return sorted;
808
+ function sortByPriority(plugins) {
809
+ return [...plugins].sort((a, b) => {
810
+ const priorityA = a.priority ?? 0;
811
+ const priorityB = b.priority ?? 0;
812
+ return priorityA - priorityB;
813
+ });
843
814
  }
844
815
  function createPluginExecutor(initialPlugins = []) {
845
816
  validateDependencies(initialPlugins);
846
- const plugins = sortByDependencies(initialPlugins);
817
+ const plugins = sortByPriority(initialPlugins);
847
818
  const frozenPlugins = Object.freeze([...plugins]);
848
819
  const createPluginAccessor = (context) => ({
849
820
  get(name) {
@@ -946,15 +917,15 @@ var Spoosh = class _Spoosh {
946
917
  * @example
947
918
  * ```ts
948
919
  * // Simple usage
949
- * const client = new Spoosh<ApiSchema, Error>('/api');
920
+ * const spoosh = new Spoosh<ApiSchema, Error>('/api');
950
921
  *
951
922
  * // With default headers
952
- * const client = new Spoosh<ApiSchema, Error>('/api', {
923
+ * const spoosh = new Spoosh<ApiSchema, Error>('/api', {
953
924
  * headers: { 'X-API-Key': 'secret' }
954
925
  * });
955
926
  *
956
927
  * // With XHR transport (narrows available options to XHR-compatible fields)
957
- * const client = new Spoosh<ApiSchema, Error>('/api', {
928
+ * const spoosh = new Spoosh<ApiSchema, Error>('/api', {
958
929
  * transport: 'xhr',
959
930
  * credentials: 'include',
960
931
  * });
@@ -975,26 +946,10 @@ var Spoosh = class _Spoosh {
975
946
  * @param plugins - Array of plugin instances to use
976
947
  * @returns A new Spoosh instance with the specified plugins
977
948
  *
978
- * @example Single use() call
979
- * ```ts
980
- * const client = new Spoosh<Schema, Error>('/api')
981
- * .use([cachePlugin(), retryPlugin(), debouncePlugin()]);
982
- * ```
983
- *
984
- * @example Chaining use() calls (replaces plugins)
985
- * ```ts
986
- * const client1 = new Spoosh<Schema, Error>('/api')
987
- * .use([cachePlugin()]);
988
- *
989
- * // This replaces cachePlugin with retryPlugin
990
- * const client2 = client1.use([retryPlugin()]);
991
- * ```
992
- *
993
- * @example With plugin configuration
994
949
  * ```ts
995
- * const client = new Spoosh<Schema, Error>('/api').use([
950
+ * const spoosh = new Spoosh<Schema, Error>('/api').use([
996
951
  * cachePlugin({ staleTime: 5000 }),
997
- * retryPlugin({ retries: 3, retryDelay: 1000 }),
952
+ * invalidationPlugin(),
998
953
  * prefetchPlugin(),
999
954
  * ]);
1000
955
  * ```
@@ -1051,7 +1006,7 @@ var Spoosh = class _Spoosh {
1051
1006
  *
1052
1007
  * @example
1053
1008
  * ```ts
1054
- * const client = new Spoosh<ApiSchema, Error>('/api').use([...]);
1009
+ * const spoosh = new Spoosh<ApiSchema, Error>('/api').use([...]);
1055
1010
  * const { api } = client;
1056
1011
  *
1057
1012
  * // GET request
@@ -1733,7 +1688,9 @@ export {
1733
1688
  form,
1734
1689
  generateTags,
1735
1690
  getContentType,
1691
+ isAbortError,
1736
1692
  isJsonBody,
1693
+ isNetworkError,
1737
1694
  isSpooshBody,
1738
1695
  json,
1739
1696
  mergeHeaders,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spoosh/core",
3
- "version": "0.12.0",
3
+ "version": "0.12.1",
4
4
  "license": "MIT",
5
5
  "description": "Type-safe API toolkit with plugin middleware system",
6
6
  "keywords": [