@spoosh/react 0.4.1 → 0.5.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/dist/index.d.mts CHANGED
@@ -1,27 +1,34 @@
1
- import * as _spoosh_core from '@spoosh/core';
2
- import { ReadClient, TagOptions, SpooshResponse, WriteClient, SpooshPlugin, PluginTypeConfig, SpooshOptions, MergePluginResults, StateManager, EventEmitter, PluginExecutor, PluginArray, MergePluginOptions, ResolverContext, ResolveResultTypes, MergePluginInstanceApi } from '@spoosh/core';
1
+ import { ReadClient, TagMode, SpooshResponse, WriteClient, SpooshPlugin, PluginTypeConfig, SpooshOptions, MergePluginResults, StateManager, EventEmitter, PluginExecutor, PluginArray, ResolveTypes, MergePluginOptions, ResolverContext, ResolveResultTypes, MergePluginInstanceApi } from '@spoosh/core';
3
2
 
4
3
  type PluginHooksConfig<TPlugins extends readonly SpooshPlugin<PluginTypeConfig>[]> = {
5
4
  baseUrl: string;
6
5
  defaultOptions?: SpooshOptions;
7
6
  plugins: TPlugins;
8
7
  };
8
+ type TagModeInArray = "all" | "self";
9
9
  /**
10
10
  * Base options for `useRead` hook.
11
11
  */
12
- type BaseReadOptions = TagOptions & {
12
+ type BaseReadOptions = {
13
13
  /** Whether to fetch automatically on mount. Default: true */
14
14
  enabled?: boolean;
15
+ /**
16
+ * Unified tag option
17
+ * - String: mode only ('all' | 'self' | 'none')
18
+ * - Array: custom tags only OR [mode keyword mixed with custom tags]
19
+ * - 'all' or 'self' can be used in arrays
20
+ * - 'none' should only be used as string (use `tags: 'none'` not in array)
21
+ */
22
+ tags?: TagMode | (TagModeInArray | (string & {}))[];
15
23
  };
16
-
17
24
  /**
18
25
  * Result returned by `useRead` hook.
19
26
  *
20
27
  * @template TData - The response data type
21
28
  * @template TError - The error type
22
- * @template TPluginResult - Plugin-provided result fields
29
+ * @template TMeta - Plugin-provided metadata fields
23
30
  */
24
- type BaseReadResult<TData, TError, TPluginResult = Record<string, unknown>> = {
31
+ type BaseReadResult<TData, TError, TMeta = Record<string, unknown>> = {
25
32
  /** True during the initial load (no data yet) */
26
33
  loading: boolean;
27
34
  /** True during any fetch operation */
@@ -31,7 +38,7 @@ type BaseReadResult<TData, TError, TPluginResult = Record<string, unknown>> = {
31
38
  /** Error from the last failed request */
32
39
  error: TError | undefined;
33
40
  /** Plugin-provided metadata */
34
- meta: TPluginResult;
41
+ meta: TMeta;
35
42
  /** Abort the current fetch operation */
36
43
  abort: () => void;
37
44
  /** Manually trigger a refetch */
@@ -43,9 +50,9 @@ type BaseReadResult<TData, TError, TPluginResult = Record<string, unknown>> = {
43
50
  * @template TData - The response data type
44
51
  * @template TError - The error type
45
52
  * @template TOptions - The trigger options type
46
- * @template TPluginResult - Plugin-provided result fields
53
+ * @template TMeta - Plugin-provided metadata fields
47
54
  */
48
- type BaseWriteResult<TData, TError, TOptions, TPluginResult = Record<string, unknown>> = {
55
+ type BaseWriteResult<TData, TError, TOptions, TMeta = Record<string, unknown>> = {
49
56
  /** Execute the mutation with optional options */
50
57
  trigger: (options?: TOptions) => Promise<SpooshResponse<TData, TError>>;
51
58
  /** True while the mutation is in progress */
@@ -55,7 +62,7 @@ type BaseWriteResult<TData, TError, TOptions, TPluginResult = Record<string, unk
55
62
  /** Error from the last failed request */
56
63
  error: TError | undefined;
57
64
  /** Plugin-provided metadata */
58
- meta: TPluginResult;
65
+ meta: TMeta;
59
66
  /** Reset the state to initial values */
60
67
  reset: () => void;
61
68
  /** Abort the current mutation */
@@ -80,8 +87,8 @@ type InputFields<TQuery, TBody, TParamNames extends string> = OptionalQueryField
80
87
  type WriteResponseInputFields<TQuery, TBody, TParamNames extends string> = [TQuery, TBody, TParamNames] extends [never, never, never] ? object : {
81
88
  input: InputFields<TQuery, TBody, TParamNames> | undefined;
82
89
  };
83
- type UseReadResult<TData, TError, TPlugins extends readonly SpooshPlugin<PluginTypeConfig>[]> = BaseReadResult<TData, TError> & MergePluginResults<TPlugins>["read"];
84
- type UseWriteResult<TData, TError, TOptions, TPlugins extends readonly SpooshPlugin<PluginTypeConfig>[]> = BaseWriteResult<TData, TError, TOptions> & MergePluginResults<TPlugins>["write"];
90
+ type UseReadResult<TData, TError, TMeta, TPlugins extends readonly SpooshPlugin<PluginTypeConfig>[]> = BaseReadResult<TData, TError, TMeta> & MergePluginResults<TPlugins>["read"];
91
+ type UseWriteResult<TData, TError, TOptions, TMeta, TPlugins extends readonly SpooshPlugin<PluginTypeConfig>[]> = BaseWriteResult<TData, TError, TOptions, TMeta> & MergePluginResults<TPlugins>["write"];
85
92
  type ReadApiClient<TSchema, TDefaultError> = ReadClient<TSchema, TDefaultError>;
86
93
  type WriteApiClient<TSchema, TDefaultError> = WriteClient<TSchema, TDefaultError>;
87
94
  type SuccessResponse<T> = Extract<T, {
@@ -177,9 +184,17 @@ type InfinitePrevContext<TData, TRequest> = {
177
184
  * @template TItem - The item type after merging all responses
178
185
  * @template TRequest - The request options type (query, params, body)
179
186
  */
180
- type BaseInfiniteReadOptions<TData, TItem, TRequest = AnyInfiniteRequestOptions> = TagOptions & {
187
+ type BaseInfiniteReadOptions<TData, TItem, TRequest = AnyInfiniteRequestOptions> = {
181
188
  /** Whether to fetch automatically on mount. Default: true */
182
189
  enabled?: boolean;
190
+ /**
191
+ * Unified tag option
192
+ * - String: mode only ('all' | 'self' | 'none')
193
+ * - Array: custom tags only OR [mode keyword mixed with custom tags]
194
+ * - 'all' or 'self' can be used in arrays
195
+ * - 'none' should only be used as string (use `tags: 'none'` not in array)
196
+ */
197
+ tags?: TagMode | (TagModeInArray | (string & {}))[];
183
198
  /** Callback to determine if there's a next page to fetch */
184
199
  canFetchNext: (ctx: InfiniteNextContext<TData, TRequest>) => boolean;
185
200
  /** Callback to build the request options for the next page */
@@ -233,16 +248,21 @@ type UseInfiniteReadResult<TData, TError, TItem, TPlugins extends readonly Spoos
233
248
  type InfiniteReadApiClient<TSchema, TDefaultError> = ReadClient<TSchema, TDefaultError>;
234
249
 
235
250
  type InferError<T, TDefaultError> = [T] extends [unknown] ? TDefaultError : T;
236
- type ExtractParamsRecord<T> = ExtractResponseParamNames<T> extends never ? never : Record<ExtractResponseParamNames<T>, string | number>;
237
- type ReadResolverContext<TSchema, TReadFn, TDefaultError> = ResolverContext<TSchema, ExtractMethodData<TReadFn>, InferError<ExtractMethodError<TReadFn>, TDefaultError>, ExtractResponseQuery<TReadFn>, ExtractResponseBody<TReadFn>, ExtractParamsRecord<TReadFn>>;
238
- type ResolvedReadOptions<TSchema, TPlugins extends PluginArray, TReadFn, TDefaultError> = _spoosh_core.ResolveTypes<MergePluginOptions<TPlugins>["read"], ReadResolverContext<TSchema, TReadFn, TDefaultError>>;
239
251
  type WriteResolverContext<TSchema, TMethod, TDefaultError> = ResolverContext<TSchema, ExtractMethodData<TMethod>, InferError<ExtractMethodError<TMethod>, TDefaultError>, ExtractMethodQuery<TMethod>, ExtractMethodBody<TMethod>, ExtractResponseParamNames<TMethod> extends never ? never : Record<ExtractResponseParamNames<TMethod>, string | number>>;
240
- type ResolvedWriteOptions<TSchema, TPlugins extends PluginArray, TMethod, TDefaultError> = _spoosh_core.ResolveTypes<MergePluginOptions<TPlugins>["write"], WriteResolverContext<TSchema, TMethod, TDefaultError>>;
241
- type UseReadFn<TDefaultError, TSchema, TPlugins extends PluginArray> = <TReadFn extends (api: ReadApiClient<TSchema, TDefaultError>) => Promise<{
242
- data?: unknown;
243
- error?: unknown;
244
- }>>(readFn: TReadFn, readOptions?: BaseReadOptions & ResolvedReadOptions<TSchema, TPlugins, TReadFn, TDefaultError>) => BaseReadResult<ExtractMethodData<TReadFn>, InferError<ExtractMethodError<TReadFn>, TDefaultError>, ResolveResultTypes<MergePluginResults<TPlugins>["read"], BaseReadOptions & ResolvedReadOptions<TSchema, TPlugins, TReadFn, TDefaultError>>> & ResponseInputFields<ExtractResponseQuery<TReadFn>, ExtractResponseBody<TReadFn>, ExtractResponseParamNames<TReadFn>>;
245
- type UseWriteFn<TDefaultError, TSchema, TPlugins extends PluginArray> = <TMethod extends (...args: never) => Promise<SpooshResponse<unknown, unknown>>>(writeFn: (api: WriteApiClient<TSchema, TDefaultError>) => TMethod) => BaseWriteResult<ExtractMethodData<TMethod>, InferError<ExtractMethodError<TMethod>, TDefaultError>, Parameters<TMethod>[0] & ResolvedWriteOptions<TSchema, TPlugins, TMethod, TDefaultError>, ResolveResultTypes<MergePluginResults<TPlugins>["write"], Parameters<TMethod>[0] & ResolvedWriteOptions<TSchema, TPlugins, TMethod, TDefaultError>>> & WriteResponseInputFields<ExtractMethodQuery<TMethod>, ExtractMethodBody<TMethod>, ExtractResponseParamNames<TMethod>>;
252
+ type ResolvedWriteOptions<TSchema, TPlugins extends PluginArray, TMethod, TDefaultError> = ResolveTypes<MergePluginOptions<TPlugins>["write"], WriteResolverContext<TSchema, TMethod, TDefaultError>>;
253
+ type UseReadFn<TDefaultError, TSchema, TPlugins extends PluginArray> = {
254
+ <TReadFn extends (api: ReadApiClient<TSchema, TDefaultError>) => Promise<{
255
+ data?: unknown;
256
+ error?: unknown;
257
+ }>, TReadOpts>(readFn: TReadFn, readOptions: TReadOpts & BaseReadOptions & ResolveTypes<MergePluginOptions<TPlugins>["read"], ResolverContext<TSchema, ExtractMethodData<TReadFn>, InferError<ExtractMethodError<TReadFn>, TDefaultError>, ExtractResponseQuery<TReadFn>, ExtractResponseBody<TReadFn>, ExtractResponseParamNames<TReadFn> extends never ? never : Record<ExtractResponseParamNames<TReadFn>, string | number>>>): BaseReadResult<ExtractMethodData<TReadFn>, InferError<ExtractMethodError<TReadFn>, TDefaultError>, ResolveResultTypes<MergePluginResults<TPlugins>["read"], TReadOpts>> & ResponseInputFields<ExtractResponseQuery<TReadFn>, ExtractResponseBody<TReadFn>, ExtractResponseParamNames<TReadFn>>;
258
+ <TReadFn extends (api: ReadApiClient<TSchema, TDefaultError>) => Promise<{
259
+ data?: unknown;
260
+ error?: unknown;
261
+ }>>(readFn: TReadFn): BaseReadResult<ExtractMethodData<TReadFn>, InferError<ExtractMethodError<TReadFn>, TDefaultError>, MergePluginResults<TPlugins>["read"]> & ResponseInputFields<ExtractResponseQuery<TReadFn>, ExtractResponseBody<TReadFn>, ExtractResponseParamNames<TReadFn>>;
262
+ };
263
+ type UseWriteFn<TDefaultError, TSchema, TPlugins extends PluginArray> = {
264
+ <TMethod extends (...args: never) => Promise<SpooshResponse<unknown, unknown>>>(writeFn: (api: WriteApiClient<TSchema, TDefaultError>) => TMethod): BaseWriteResult<ExtractMethodData<TMethod>, InferError<ExtractMethodError<TMethod>, TDefaultError>, Parameters<TMethod>[0] & ResolvedWriteOptions<TSchema, TPlugins, TMethod, TDefaultError>, MergePluginResults<TPlugins>["write"]> & WriteResponseInputFields<ExtractMethodQuery<TMethod>, ExtractMethodBody<TMethod>, ExtractResponseParamNames<TMethod>>;
265
+ };
246
266
  type InfiniteReadResolverContext<TSchema, TData, TError, TRequest> = ResolverContext<TSchema, TData, TError, TRequest extends {
247
267
  query: infer Q;
248
268
  } ? Q : never, TRequest extends {
@@ -250,7 +270,7 @@ type InfiniteReadResolverContext<TSchema, TData, TError, TRequest> = ResolverCon
250
270
  } ? B : never, TRequest extends {
251
271
  params: infer P;
252
272
  } ? P : never>;
253
- type ResolvedInfiniteReadOptions<TSchema, TPlugins extends PluginArray, TData, TError, TRequest> = _spoosh_core.ResolveTypes<MergePluginOptions<TPlugins>["infiniteRead"], InfiniteReadResolverContext<TSchema, TData, TError, TRequest>>;
273
+ type ResolvedInfiniteReadOptions<TSchema, TPlugins extends PluginArray, TData, TError, TRequest> = ResolveTypes<MergePluginOptions<TPlugins>["infiniteRead"], InfiniteReadResolverContext<TSchema, TData, TError, TRequest>>;
254
274
  type UseInfiniteReadFn<TDefaultError, TSchema, TPlugins extends PluginArray> = <TData, TItem, TError = TDefaultError, TRequest extends AnyInfiniteRequestOptions = AnyInfiniteRequestOptions>(readFn: (api: InfiniteReadApiClient<TSchema, TDefaultError>) => Promise<SpooshResponse<TData, TError>>, readOptions: BaseInfiniteReadOptions<TData, TItem, TRequest> & ResolvedInfiniteReadOptions<TSchema, TPlugins, TData, TError, TRequest>) => BaseInfiniteReadResult<TData, TError, TItem, MergePluginResults<TPlugins>["read"]>;
255
275
  /**
256
276
  * Spoosh React hooks interface containing useRead, useWrite, and useInfiniteRead.
@@ -358,42 +378,44 @@ type SpooshInstanceShape<TApi, TSchema, TDefaultError, TPlugins> = {
358
378
  */
359
379
  declare function createReactSpoosh<TSchema, TDefaultError, TPlugins extends PluginArray, TApi>(instance: SpooshInstanceShape<TApi, TSchema, TDefaultError, TPlugins>): SpooshReactHooks<TDefaultError, TSchema, TPlugins>;
360
380
 
361
- declare function createUseRead<TSchema, TDefaultError, TPlugins extends readonly SpooshPlugin<PluginTypeConfig>[]>(options: Omit<SpooshInstanceShape<unknown, TSchema, TDefaultError, TPlugins>, "_types">): <TReadFn extends (api: ReadApiClient<TSchema, TDefaultError>) => Promise<{
362
- data?: unknown;
363
- error?: unknown;
364
- }>, TReadOpts extends BaseReadOptions & (((TPlugins[number] extends infer T_3 ? T_3 extends TPlugins[number] ? T_3 extends SpooshPlugin<infer Types_1 extends PluginTypeConfig> ? Types_1 extends {
365
- readOptions: infer R_1;
366
- } ? R_1 : object : object : never : never) extends infer T_4 ? T_4 extends (TPlugins[number] extends infer T_5 ? T_5 extends TPlugins[number] ? T_5 extends SpooshPlugin<infer Types_1 extends PluginTypeConfig> ? Types_1 extends {
367
- readOptions: infer R_1;
368
- } ? R_1 : object : object : never : never) ? T_4 extends unknown ? (x: T_4) => void : never : never : never) extends (x: infer I) => void ? I : never) = BaseReadOptions & (((TPlugins[number] extends infer T_6 ? T_6 extends TPlugins[number] ? T_6 extends SpooshPlugin<infer Types_1 extends PluginTypeConfig> ? Types_1 extends {
369
- readOptions: infer R_1;
370
- } ? R_1 : object : object : never : never) extends infer T_7 ? T_7 extends (TPlugins[number] extends infer T_8 ? T_8 extends TPlugins[number] ? T_8 extends SpooshPlugin<infer Types_1 extends PluginTypeConfig> ? Types_1 extends {
371
- readOptions: infer R_1;
372
- } ? R_1 : object : object : never : never) ? T_7 extends unknown ? (x: T_7) => void : never : never : never) extends (x: infer I) => void ? I : never)>(readFn: TReadFn, readOptions?: TReadOpts) => BaseReadResult<TReadFn extends (...args: unknown[]) => Promise<{
373
- data: infer D;
374
- }> ? D : unknown, [TReadFn extends (...args: unknown[]) => Promise<{
375
- error: infer E;
376
- }> ? E : unknown] extends [unknown] ? TDefaultError : TReadFn extends (...args: unknown[]) => Promise<{
377
- error: infer E;
378
- }> ? E : unknown, ResolveResultTypes<((TPlugins[number] extends infer T ? T extends TPlugins[number] ? T extends SpooshPlugin<infer Types extends PluginTypeConfig> ? Types extends {
379
- readResult: infer R;
380
- } ? R : object : object : never : never) extends infer T_1 ? T_1 extends (TPlugins[number] extends infer T_2 ? T_2 extends TPlugins[number] ? T_2 extends SpooshPlugin<infer Types extends PluginTypeConfig> ? Types extends {
381
- readResult: infer R;
382
- } ? R : object : object : never : never) ? T_1 extends unknown ? (x: T_1) => void : never : never : never) extends (x: infer I) => void ? I : never, TReadOpts>> & ResponseInputFields<ExtractResponseQuery<TReadFn>, ExtractResponseBody<TReadFn>, ExtractResponseParamNames<TReadFn>>;
381
+ declare function createUseRead<TSchema, TDefaultError, TPlugins extends readonly SpooshPlugin<PluginTypeConfig>[]>(options: Omit<SpooshInstanceShape<unknown, TSchema, TDefaultError, TPlugins>, "_types">): {
382
+ <TReadFn extends (api: ReadApiClient<TSchema, TDefaultError>) => Promise<{
383
+ data?: unknown;
384
+ error?: unknown;
385
+ }>, TReadOpts>(readFn: TReadFn, readOptions: TReadOpts & BaseReadOptions & ResolveTypes<((TPlugins[number] extends infer T ? T extends TPlugins[number] ? T extends SpooshPlugin<infer Types extends PluginTypeConfig> ? Types extends {
386
+ readOptions: infer R;
387
+ } ? R : object : object : never : never) extends infer T_1 ? T_1 extends (TPlugins[number] extends infer T_2 ? T_2 extends TPlugins[number] ? T_2 extends SpooshPlugin<infer Types extends PluginTypeConfig> ? Types extends {
388
+ readOptions: infer R;
389
+ } ? R : object : object : never : never) ? T_1 extends unknown ? (x: T_1) => void : never : never : never) extends (x: infer I) => void ? I : never, ResolverContext<TSchema, TReadFn extends (...args: unknown[]) => Promise<{
390
+ data: infer D;
391
+ }> ? D : unknown, [TReadFn extends (...args: unknown[]) => Promise<{
392
+ error: infer E;
393
+ }> ? E : unknown] extends [unknown] ? TDefaultError : TReadFn extends (...args: unknown[]) => Promise<{
394
+ error: infer E;
395
+ }> ? E : unknown, ExtractResponseQuery<TReadFn>, ExtractResponseBody<TReadFn>, ExtractResponseParamNames<TReadFn> extends never ? never : Record<ExtractResponseParamNames<TReadFn>, string | number>>>): BaseReadResult<TReadFn extends (...args: unknown[]) => Promise<{
396
+ data: infer D;
397
+ }> ? D : unknown, [TReadFn extends (...args: unknown[]) => Promise<{
398
+ error: infer E;
399
+ }> ? E : unknown] extends [unknown] ? TDefaultError : TReadFn extends (...args: unknown[]) => Promise<{
400
+ error: infer E;
401
+ }> ? E : unknown, ResolveResultTypes<MergePluginResults<TPlugins>["read"], TReadOpts>> & ResponseInputFields<ExtractResponseQuery<TReadFn>, ExtractResponseBody<TReadFn>, ExtractResponseParamNames<TReadFn>>;
402
+ <TReadFn extends (api: ReadApiClient<TSchema, TDefaultError>) => Promise<{
403
+ data?: unknown;
404
+ error?: unknown;
405
+ }>>(readFn: TReadFn): BaseReadResult<TReadFn extends (...args: unknown[]) => Promise<{
406
+ data: infer D;
407
+ }> ? D : unknown, [TReadFn extends (...args: unknown[]) => Promise<{
408
+ error: infer E;
409
+ }> ? E : unknown] extends [unknown] ? TDefaultError : TReadFn extends (...args: unknown[]) => Promise<{
410
+ error: infer E;
411
+ }> ? E : unknown, MergePluginResults<TPlugins>["read"]> & ResponseInputFields<ExtractResponseQuery<TReadFn>, ExtractResponseBody<TReadFn>, ExtractResponseParamNames<TReadFn>>;
412
+ };
383
413
 
384
- declare function createUseWrite<TSchema, TDefaultError, TPlugins extends readonly SpooshPlugin<PluginTypeConfig>[]>(options: Omit<SpooshInstanceShape<unknown, TSchema, TDefaultError, TPlugins>, "_types">): <TMethod extends (...args: never[]) => Promise<SpooshResponse<unknown, unknown>>>(writeFn: (api: WriteApiClient<TSchema, TDefaultError>) => TMethod) => BaseWriteResult<ExtractMethodData<TMethod>, [ExtractMethodError<TMethod>] extends [unknown] ? TDefaultError : ExtractMethodError<TMethod>, ExtractMethodOptions<TMethod> & _spoosh_core.ResolveTypes<((TPlugins[number] extends infer T ? T extends TPlugins[number] ? T extends SpooshPlugin<infer Types extends PluginTypeConfig> ? Types extends {
414
+ declare function createUseWrite<TSchema, TDefaultError, TPlugins extends readonly SpooshPlugin<PluginTypeConfig>[]>(options: Omit<SpooshInstanceShape<unknown, TSchema, TDefaultError, TPlugins>, "_types">): <TMethod extends (...args: never[]) => Promise<SpooshResponse<unknown, unknown>>>(writeFn: (api: WriteApiClient<TSchema, TDefaultError>) => TMethod) => BaseWriteResult<ExtractMethodData<TMethod>, [ExtractMethodError<TMethod>] extends [unknown] ? TDefaultError : ExtractMethodError<TMethod>, ExtractMethodOptions<TMethod> & ResolveTypes<((TPlugins[number] extends infer T ? T extends TPlugins[number] ? T extends SpooshPlugin<infer Types extends PluginTypeConfig> ? Types extends {
385
415
  writeOptions: infer W;
386
416
  } ? W : object : object : never : never) extends infer T_1 ? T_1 extends (TPlugins[number] extends infer T_2 ? T_2 extends TPlugins[number] ? T_2 extends SpooshPlugin<infer Types extends PluginTypeConfig> ? Types extends {
387
417
  writeOptions: infer W;
388
- } ? W : object : object : never : never) ? T_1 extends unknown ? (x: T_1) => void : never : never : never) extends (x: infer I) => void ? I : never, ResolverContext<TSchema, ExtractMethodData<TMethod>, [ExtractMethodError<TMethod>] extends [unknown] ? TDefaultError : ExtractMethodError<TMethod>, ExtractMethodQuery<TMethod>, ExtractMethodBody<TMethod>, ExtractResponseParamNames<TMethod> extends never ? never : Record<ExtractResponseParamNames<TMethod>, string | number>>>, ResolveResultTypes<((TPlugins[number] extends infer T_3 ? T_3 extends TPlugins[number] ? T_3 extends SpooshPlugin<infer Types_1 extends PluginTypeConfig> ? Types_1 extends {
389
- writeResult: infer W_1;
390
- } ? W_1 : object : object : never : never) extends infer T_4 ? T_4 extends (TPlugins[number] extends infer T_5 ? T_5 extends TPlugins[number] ? T_5 extends SpooshPlugin<infer Types_1 extends PluginTypeConfig> ? Types_1 extends {
391
- writeResult: infer W_1;
392
- } ? W_1 : object : object : never : never) ? T_4 extends unknown ? (x: T_4) => void : never : never : never) extends (x: infer I) => void ? I : never, ExtractMethodOptions<TMethod> & _spoosh_core.ResolveTypes<((TPlugins[number] extends infer T_6 ? T_6 extends TPlugins[number] ? T_6 extends SpooshPlugin<infer Types extends PluginTypeConfig> ? Types extends {
393
- writeOptions: infer W;
394
- } ? W : object : object : never : never) extends infer T_7 ? T_7 extends (TPlugins[number] extends infer T_8 ? T_8 extends TPlugins[number] ? T_8 extends SpooshPlugin<infer Types extends PluginTypeConfig> ? Types extends {
395
- writeOptions: infer W;
396
- } ? W : object : object : never : never) ? T_7 extends unknown ? (x: T_7) => void : never : never : never) extends (x: infer I) => void ? I : never, ResolverContext<TSchema, ExtractMethodData<TMethod>, [ExtractMethodError<TMethod>] extends [unknown] ? TDefaultError : ExtractMethodError<TMethod>, ExtractMethodQuery<TMethod>, ExtractMethodBody<TMethod>, ExtractResponseParamNames<TMethod> extends never ? never : Record<ExtractResponseParamNames<TMethod>, string | number>>>>> & WriteResponseInputFields<ExtractResponseQuery<TMethod>, ExtractResponseBody<TMethod>, ExtractResponseParamNames<TMethod>>;
418
+ } ? W : object : object : never : never) ? T_1 extends unknown ? (x: T_1) => void : never : never : never) extends (x: infer I) => void ? I : never, ResolverContext<TSchema, ExtractMethodData<TMethod>, [ExtractMethodError<TMethod>] extends [unknown] ? TDefaultError : ExtractMethodError<TMethod>, ExtractMethodQuery<TMethod>, ExtractMethodBody<TMethod>, ExtractResponseParamNames<TMethod> extends never ? never : Record<ExtractResponseParamNames<TMethod>, string | number>>>, MergePluginResults<TPlugins>["write"]> & WriteResponseInputFields<ExtractResponseQuery<TMethod>, ExtractResponseBody<TMethod>, ExtractResponseParamNames<TMethod>>;
397
419
 
398
420
  declare function createUseInfiniteRead<TSchema, TDefaultError, TPlugins extends readonly SpooshPlugin<PluginTypeConfig>[]>(options: Omit<SpooshInstanceShape<unknown, TSchema, TDefaultError, TPlugins>, "_types">): <TData, TItem, TError = TDefaultError, TRequest extends AnyInfiniteRequestOptions = AnyInfiniteRequestOptions>(readFn: (api: InfiniteReadApiClient<TSchema, TDefaultError>) => Promise<SpooshResponse<TData, TError>>, readOptions: BaseInfiniteReadOptions<TData, TItem, TRequest> & (((TPlugins[number] extends infer T_3 ? T_3 extends TPlugins[number] ? T_3 extends SpooshPlugin<infer Types_1 extends PluginTypeConfig> ? Types_1 extends {
399
421
  infiniteReadOptions: infer I_1;
package/dist/index.d.ts CHANGED
@@ -1,27 +1,34 @@
1
- import * as _spoosh_core from '@spoosh/core';
2
- import { ReadClient, TagOptions, SpooshResponse, WriteClient, SpooshPlugin, PluginTypeConfig, SpooshOptions, MergePluginResults, StateManager, EventEmitter, PluginExecutor, PluginArray, MergePluginOptions, ResolverContext, ResolveResultTypes, MergePluginInstanceApi } from '@spoosh/core';
1
+ import { ReadClient, TagMode, SpooshResponse, WriteClient, SpooshPlugin, PluginTypeConfig, SpooshOptions, MergePluginResults, StateManager, EventEmitter, PluginExecutor, PluginArray, ResolveTypes, MergePluginOptions, ResolverContext, ResolveResultTypes, MergePluginInstanceApi } from '@spoosh/core';
3
2
 
4
3
  type PluginHooksConfig<TPlugins extends readonly SpooshPlugin<PluginTypeConfig>[]> = {
5
4
  baseUrl: string;
6
5
  defaultOptions?: SpooshOptions;
7
6
  plugins: TPlugins;
8
7
  };
8
+ type TagModeInArray = "all" | "self";
9
9
  /**
10
10
  * Base options for `useRead` hook.
11
11
  */
12
- type BaseReadOptions = TagOptions & {
12
+ type BaseReadOptions = {
13
13
  /** Whether to fetch automatically on mount. Default: true */
14
14
  enabled?: boolean;
15
+ /**
16
+ * Unified tag option
17
+ * - String: mode only ('all' | 'self' | 'none')
18
+ * - Array: custom tags only OR [mode keyword mixed with custom tags]
19
+ * - 'all' or 'self' can be used in arrays
20
+ * - 'none' should only be used as string (use `tags: 'none'` not in array)
21
+ */
22
+ tags?: TagMode | (TagModeInArray | (string & {}))[];
15
23
  };
16
-
17
24
  /**
18
25
  * Result returned by `useRead` hook.
19
26
  *
20
27
  * @template TData - The response data type
21
28
  * @template TError - The error type
22
- * @template TPluginResult - Plugin-provided result fields
29
+ * @template TMeta - Plugin-provided metadata fields
23
30
  */
24
- type BaseReadResult<TData, TError, TPluginResult = Record<string, unknown>> = {
31
+ type BaseReadResult<TData, TError, TMeta = Record<string, unknown>> = {
25
32
  /** True during the initial load (no data yet) */
26
33
  loading: boolean;
27
34
  /** True during any fetch operation */
@@ -31,7 +38,7 @@ type BaseReadResult<TData, TError, TPluginResult = Record<string, unknown>> = {
31
38
  /** Error from the last failed request */
32
39
  error: TError | undefined;
33
40
  /** Plugin-provided metadata */
34
- meta: TPluginResult;
41
+ meta: TMeta;
35
42
  /** Abort the current fetch operation */
36
43
  abort: () => void;
37
44
  /** Manually trigger a refetch */
@@ -43,9 +50,9 @@ type BaseReadResult<TData, TError, TPluginResult = Record<string, unknown>> = {
43
50
  * @template TData - The response data type
44
51
  * @template TError - The error type
45
52
  * @template TOptions - The trigger options type
46
- * @template TPluginResult - Plugin-provided result fields
53
+ * @template TMeta - Plugin-provided metadata fields
47
54
  */
48
- type BaseWriteResult<TData, TError, TOptions, TPluginResult = Record<string, unknown>> = {
55
+ type BaseWriteResult<TData, TError, TOptions, TMeta = Record<string, unknown>> = {
49
56
  /** Execute the mutation with optional options */
50
57
  trigger: (options?: TOptions) => Promise<SpooshResponse<TData, TError>>;
51
58
  /** True while the mutation is in progress */
@@ -55,7 +62,7 @@ type BaseWriteResult<TData, TError, TOptions, TPluginResult = Record<string, unk
55
62
  /** Error from the last failed request */
56
63
  error: TError | undefined;
57
64
  /** Plugin-provided metadata */
58
- meta: TPluginResult;
65
+ meta: TMeta;
59
66
  /** Reset the state to initial values */
60
67
  reset: () => void;
61
68
  /** Abort the current mutation */
@@ -80,8 +87,8 @@ type InputFields<TQuery, TBody, TParamNames extends string> = OptionalQueryField
80
87
  type WriteResponseInputFields<TQuery, TBody, TParamNames extends string> = [TQuery, TBody, TParamNames] extends [never, never, never] ? object : {
81
88
  input: InputFields<TQuery, TBody, TParamNames> | undefined;
82
89
  };
83
- type UseReadResult<TData, TError, TPlugins extends readonly SpooshPlugin<PluginTypeConfig>[]> = BaseReadResult<TData, TError> & MergePluginResults<TPlugins>["read"];
84
- type UseWriteResult<TData, TError, TOptions, TPlugins extends readonly SpooshPlugin<PluginTypeConfig>[]> = BaseWriteResult<TData, TError, TOptions> & MergePluginResults<TPlugins>["write"];
90
+ type UseReadResult<TData, TError, TMeta, TPlugins extends readonly SpooshPlugin<PluginTypeConfig>[]> = BaseReadResult<TData, TError, TMeta> & MergePluginResults<TPlugins>["read"];
91
+ type UseWriteResult<TData, TError, TOptions, TMeta, TPlugins extends readonly SpooshPlugin<PluginTypeConfig>[]> = BaseWriteResult<TData, TError, TOptions, TMeta> & MergePluginResults<TPlugins>["write"];
85
92
  type ReadApiClient<TSchema, TDefaultError> = ReadClient<TSchema, TDefaultError>;
86
93
  type WriteApiClient<TSchema, TDefaultError> = WriteClient<TSchema, TDefaultError>;
87
94
  type SuccessResponse<T> = Extract<T, {
@@ -177,9 +184,17 @@ type InfinitePrevContext<TData, TRequest> = {
177
184
  * @template TItem - The item type after merging all responses
178
185
  * @template TRequest - The request options type (query, params, body)
179
186
  */
180
- type BaseInfiniteReadOptions<TData, TItem, TRequest = AnyInfiniteRequestOptions> = TagOptions & {
187
+ type BaseInfiniteReadOptions<TData, TItem, TRequest = AnyInfiniteRequestOptions> = {
181
188
  /** Whether to fetch automatically on mount. Default: true */
182
189
  enabled?: boolean;
190
+ /**
191
+ * Unified tag option
192
+ * - String: mode only ('all' | 'self' | 'none')
193
+ * - Array: custom tags only OR [mode keyword mixed with custom tags]
194
+ * - 'all' or 'self' can be used in arrays
195
+ * - 'none' should only be used as string (use `tags: 'none'` not in array)
196
+ */
197
+ tags?: TagMode | (TagModeInArray | (string & {}))[];
183
198
  /** Callback to determine if there's a next page to fetch */
184
199
  canFetchNext: (ctx: InfiniteNextContext<TData, TRequest>) => boolean;
185
200
  /** Callback to build the request options for the next page */
@@ -233,16 +248,21 @@ type UseInfiniteReadResult<TData, TError, TItem, TPlugins extends readonly Spoos
233
248
  type InfiniteReadApiClient<TSchema, TDefaultError> = ReadClient<TSchema, TDefaultError>;
234
249
 
235
250
  type InferError<T, TDefaultError> = [T] extends [unknown] ? TDefaultError : T;
236
- type ExtractParamsRecord<T> = ExtractResponseParamNames<T> extends never ? never : Record<ExtractResponseParamNames<T>, string | number>;
237
- type ReadResolverContext<TSchema, TReadFn, TDefaultError> = ResolverContext<TSchema, ExtractMethodData<TReadFn>, InferError<ExtractMethodError<TReadFn>, TDefaultError>, ExtractResponseQuery<TReadFn>, ExtractResponseBody<TReadFn>, ExtractParamsRecord<TReadFn>>;
238
- type ResolvedReadOptions<TSchema, TPlugins extends PluginArray, TReadFn, TDefaultError> = _spoosh_core.ResolveTypes<MergePluginOptions<TPlugins>["read"], ReadResolverContext<TSchema, TReadFn, TDefaultError>>;
239
251
  type WriteResolverContext<TSchema, TMethod, TDefaultError> = ResolverContext<TSchema, ExtractMethodData<TMethod>, InferError<ExtractMethodError<TMethod>, TDefaultError>, ExtractMethodQuery<TMethod>, ExtractMethodBody<TMethod>, ExtractResponseParamNames<TMethod> extends never ? never : Record<ExtractResponseParamNames<TMethod>, string | number>>;
240
- type ResolvedWriteOptions<TSchema, TPlugins extends PluginArray, TMethod, TDefaultError> = _spoosh_core.ResolveTypes<MergePluginOptions<TPlugins>["write"], WriteResolverContext<TSchema, TMethod, TDefaultError>>;
241
- type UseReadFn<TDefaultError, TSchema, TPlugins extends PluginArray> = <TReadFn extends (api: ReadApiClient<TSchema, TDefaultError>) => Promise<{
242
- data?: unknown;
243
- error?: unknown;
244
- }>>(readFn: TReadFn, readOptions?: BaseReadOptions & ResolvedReadOptions<TSchema, TPlugins, TReadFn, TDefaultError>) => BaseReadResult<ExtractMethodData<TReadFn>, InferError<ExtractMethodError<TReadFn>, TDefaultError>, ResolveResultTypes<MergePluginResults<TPlugins>["read"], BaseReadOptions & ResolvedReadOptions<TSchema, TPlugins, TReadFn, TDefaultError>>> & ResponseInputFields<ExtractResponseQuery<TReadFn>, ExtractResponseBody<TReadFn>, ExtractResponseParamNames<TReadFn>>;
245
- type UseWriteFn<TDefaultError, TSchema, TPlugins extends PluginArray> = <TMethod extends (...args: never) => Promise<SpooshResponse<unknown, unknown>>>(writeFn: (api: WriteApiClient<TSchema, TDefaultError>) => TMethod) => BaseWriteResult<ExtractMethodData<TMethod>, InferError<ExtractMethodError<TMethod>, TDefaultError>, Parameters<TMethod>[0] & ResolvedWriteOptions<TSchema, TPlugins, TMethod, TDefaultError>, ResolveResultTypes<MergePluginResults<TPlugins>["write"], Parameters<TMethod>[0] & ResolvedWriteOptions<TSchema, TPlugins, TMethod, TDefaultError>>> & WriteResponseInputFields<ExtractMethodQuery<TMethod>, ExtractMethodBody<TMethod>, ExtractResponseParamNames<TMethod>>;
252
+ type ResolvedWriteOptions<TSchema, TPlugins extends PluginArray, TMethod, TDefaultError> = ResolveTypes<MergePluginOptions<TPlugins>["write"], WriteResolverContext<TSchema, TMethod, TDefaultError>>;
253
+ type UseReadFn<TDefaultError, TSchema, TPlugins extends PluginArray> = {
254
+ <TReadFn extends (api: ReadApiClient<TSchema, TDefaultError>) => Promise<{
255
+ data?: unknown;
256
+ error?: unknown;
257
+ }>, TReadOpts>(readFn: TReadFn, readOptions: TReadOpts & BaseReadOptions & ResolveTypes<MergePluginOptions<TPlugins>["read"], ResolverContext<TSchema, ExtractMethodData<TReadFn>, InferError<ExtractMethodError<TReadFn>, TDefaultError>, ExtractResponseQuery<TReadFn>, ExtractResponseBody<TReadFn>, ExtractResponseParamNames<TReadFn> extends never ? never : Record<ExtractResponseParamNames<TReadFn>, string | number>>>): BaseReadResult<ExtractMethodData<TReadFn>, InferError<ExtractMethodError<TReadFn>, TDefaultError>, ResolveResultTypes<MergePluginResults<TPlugins>["read"], TReadOpts>> & ResponseInputFields<ExtractResponseQuery<TReadFn>, ExtractResponseBody<TReadFn>, ExtractResponseParamNames<TReadFn>>;
258
+ <TReadFn extends (api: ReadApiClient<TSchema, TDefaultError>) => Promise<{
259
+ data?: unknown;
260
+ error?: unknown;
261
+ }>>(readFn: TReadFn): BaseReadResult<ExtractMethodData<TReadFn>, InferError<ExtractMethodError<TReadFn>, TDefaultError>, MergePluginResults<TPlugins>["read"]> & ResponseInputFields<ExtractResponseQuery<TReadFn>, ExtractResponseBody<TReadFn>, ExtractResponseParamNames<TReadFn>>;
262
+ };
263
+ type UseWriteFn<TDefaultError, TSchema, TPlugins extends PluginArray> = {
264
+ <TMethod extends (...args: never) => Promise<SpooshResponse<unknown, unknown>>>(writeFn: (api: WriteApiClient<TSchema, TDefaultError>) => TMethod): BaseWriteResult<ExtractMethodData<TMethod>, InferError<ExtractMethodError<TMethod>, TDefaultError>, Parameters<TMethod>[0] & ResolvedWriteOptions<TSchema, TPlugins, TMethod, TDefaultError>, MergePluginResults<TPlugins>["write"]> & WriteResponseInputFields<ExtractMethodQuery<TMethod>, ExtractMethodBody<TMethod>, ExtractResponseParamNames<TMethod>>;
265
+ };
246
266
  type InfiniteReadResolverContext<TSchema, TData, TError, TRequest> = ResolverContext<TSchema, TData, TError, TRequest extends {
247
267
  query: infer Q;
248
268
  } ? Q : never, TRequest extends {
@@ -250,7 +270,7 @@ type InfiniteReadResolverContext<TSchema, TData, TError, TRequest> = ResolverCon
250
270
  } ? B : never, TRequest extends {
251
271
  params: infer P;
252
272
  } ? P : never>;
253
- type ResolvedInfiniteReadOptions<TSchema, TPlugins extends PluginArray, TData, TError, TRequest> = _spoosh_core.ResolveTypes<MergePluginOptions<TPlugins>["infiniteRead"], InfiniteReadResolverContext<TSchema, TData, TError, TRequest>>;
273
+ type ResolvedInfiniteReadOptions<TSchema, TPlugins extends PluginArray, TData, TError, TRequest> = ResolveTypes<MergePluginOptions<TPlugins>["infiniteRead"], InfiniteReadResolverContext<TSchema, TData, TError, TRequest>>;
254
274
  type UseInfiniteReadFn<TDefaultError, TSchema, TPlugins extends PluginArray> = <TData, TItem, TError = TDefaultError, TRequest extends AnyInfiniteRequestOptions = AnyInfiniteRequestOptions>(readFn: (api: InfiniteReadApiClient<TSchema, TDefaultError>) => Promise<SpooshResponse<TData, TError>>, readOptions: BaseInfiniteReadOptions<TData, TItem, TRequest> & ResolvedInfiniteReadOptions<TSchema, TPlugins, TData, TError, TRequest>) => BaseInfiniteReadResult<TData, TError, TItem, MergePluginResults<TPlugins>["read"]>;
255
275
  /**
256
276
  * Spoosh React hooks interface containing useRead, useWrite, and useInfiniteRead.
@@ -358,42 +378,44 @@ type SpooshInstanceShape<TApi, TSchema, TDefaultError, TPlugins> = {
358
378
  */
359
379
  declare function createReactSpoosh<TSchema, TDefaultError, TPlugins extends PluginArray, TApi>(instance: SpooshInstanceShape<TApi, TSchema, TDefaultError, TPlugins>): SpooshReactHooks<TDefaultError, TSchema, TPlugins>;
360
380
 
361
- declare function createUseRead<TSchema, TDefaultError, TPlugins extends readonly SpooshPlugin<PluginTypeConfig>[]>(options: Omit<SpooshInstanceShape<unknown, TSchema, TDefaultError, TPlugins>, "_types">): <TReadFn extends (api: ReadApiClient<TSchema, TDefaultError>) => Promise<{
362
- data?: unknown;
363
- error?: unknown;
364
- }>, TReadOpts extends BaseReadOptions & (((TPlugins[number] extends infer T_3 ? T_3 extends TPlugins[number] ? T_3 extends SpooshPlugin<infer Types_1 extends PluginTypeConfig> ? Types_1 extends {
365
- readOptions: infer R_1;
366
- } ? R_1 : object : object : never : never) extends infer T_4 ? T_4 extends (TPlugins[number] extends infer T_5 ? T_5 extends TPlugins[number] ? T_5 extends SpooshPlugin<infer Types_1 extends PluginTypeConfig> ? Types_1 extends {
367
- readOptions: infer R_1;
368
- } ? R_1 : object : object : never : never) ? T_4 extends unknown ? (x: T_4) => void : never : never : never) extends (x: infer I) => void ? I : never) = BaseReadOptions & (((TPlugins[number] extends infer T_6 ? T_6 extends TPlugins[number] ? T_6 extends SpooshPlugin<infer Types_1 extends PluginTypeConfig> ? Types_1 extends {
369
- readOptions: infer R_1;
370
- } ? R_1 : object : object : never : never) extends infer T_7 ? T_7 extends (TPlugins[number] extends infer T_8 ? T_8 extends TPlugins[number] ? T_8 extends SpooshPlugin<infer Types_1 extends PluginTypeConfig> ? Types_1 extends {
371
- readOptions: infer R_1;
372
- } ? R_1 : object : object : never : never) ? T_7 extends unknown ? (x: T_7) => void : never : never : never) extends (x: infer I) => void ? I : never)>(readFn: TReadFn, readOptions?: TReadOpts) => BaseReadResult<TReadFn extends (...args: unknown[]) => Promise<{
373
- data: infer D;
374
- }> ? D : unknown, [TReadFn extends (...args: unknown[]) => Promise<{
375
- error: infer E;
376
- }> ? E : unknown] extends [unknown] ? TDefaultError : TReadFn extends (...args: unknown[]) => Promise<{
377
- error: infer E;
378
- }> ? E : unknown, ResolveResultTypes<((TPlugins[number] extends infer T ? T extends TPlugins[number] ? T extends SpooshPlugin<infer Types extends PluginTypeConfig> ? Types extends {
379
- readResult: infer R;
380
- } ? R : object : object : never : never) extends infer T_1 ? T_1 extends (TPlugins[number] extends infer T_2 ? T_2 extends TPlugins[number] ? T_2 extends SpooshPlugin<infer Types extends PluginTypeConfig> ? Types extends {
381
- readResult: infer R;
382
- } ? R : object : object : never : never) ? T_1 extends unknown ? (x: T_1) => void : never : never : never) extends (x: infer I) => void ? I : never, TReadOpts>> & ResponseInputFields<ExtractResponseQuery<TReadFn>, ExtractResponseBody<TReadFn>, ExtractResponseParamNames<TReadFn>>;
381
+ declare function createUseRead<TSchema, TDefaultError, TPlugins extends readonly SpooshPlugin<PluginTypeConfig>[]>(options: Omit<SpooshInstanceShape<unknown, TSchema, TDefaultError, TPlugins>, "_types">): {
382
+ <TReadFn extends (api: ReadApiClient<TSchema, TDefaultError>) => Promise<{
383
+ data?: unknown;
384
+ error?: unknown;
385
+ }>, TReadOpts>(readFn: TReadFn, readOptions: TReadOpts & BaseReadOptions & ResolveTypes<((TPlugins[number] extends infer T ? T extends TPlugins[number] ? T extends SpooshPlugin<infer Types extends PluginTypeConfig> ? Types extends {
386
+ readOptions: infer R;
387
+ } ? R : object : object : never : never) extends infer T_1 ? T_1 extends (TPlugins[number] extends infer T_2 ? T_2 extends TPlugins[number] ? T_2 extends SpooshPlugin<infer Types extends PluginTypeConfig> ? Types extends {
388
+ readOptions: infer R;
389
+ } ? R : object : object : never : never) ? T_1 extends unknown ? (x: T_1) => void : never : never : never) extends (x: infer I) => void ? I : never, ResolverContext<TSchema, TReadFn extends (...args: unknown[]) => Promise<{
390
+ data: infer D;
391
+ }> ? D : unknown, [TReadFn extends (...args: unknown[]) => Promise<{
392
+ error: infer E;
393
+ }> ? E : unknown] extends [unknown] ? TDefaultError : TReadFn extends (...args: unknown[]) => Promise<{
394
+ error: infer E;
395
+ }> ? E : unknown, ExtractResponseQuery<TReadFn>, ExtractResponseBody<TReadFn>, ExtractResponseParamNames<TReadFn> extends never ? never : Record<ExtractResponseParamNames<TReadFn>, string | number>>>): BaseReadResult<TReadFn extends (...args: unknown[]) => Promise<{
396
+ data: infer D;
397
+ }> ? D : unknown, [TReadFn extends (...args: unknown[]) => Promise<{
398
+ error: infer E;
399
+ }> ? E : unknown] extends [unknown] ? TDefaultError : TReadFn extends (...args: unknown[]) => Promise<{
400
+ error: infer E;
401
+ }> ? E : unknown, ResolveResultTypes<MergePluginResults<TPlugins>["read"], TReadOpts>> & ResponseInputFields<ExtractResponseQuery<TReadFn>, ExtractResponseBody<TReadFn>, ExtractResponseParamNames<TReadFn>>;
402
+ <TReadFn extends (api: ReadApiClient<TSchema, TDefaultError>) => Promise<{
403
+ data?: unknown;
404
+ error?: unknown;
405
+ }>>(readFn: TReadFn): BaseReadResult<TReadFn extends (...args: unknown[]) => Promise<{
406
+ data: infer D;
407
+ }> ? D : unknown, [TReadFn extends (...args: unknown[]) => Promise<{
408
+ error: infer E;
409
+ }> ? E : unknown] extends [unknown] ? TDefaultError : TReadFn extends (...args: unknown[]) => Promise<{
410
+ error: infer E;
411
+ }> ? E : unknown, MergePluginResults<TPlugins>["read"]> & ResponseInputFields<ExtractResponseQuery<TReadFn>, ExtractResponseBody<TReadFn>, ExtractResponseParamNames<TReadFn>>;
412
+ };
383
413
 
384
- declare function createUseWrite<TSchema, TDefaultError, TPlugins extends readonly SpooshPlugin<PluginTypeConfig>[]>(options: Omit<SpooshInstanceShape<unknown, TSchema, TDefaultError, TPlugins>, "_types">): <TMethod extends (...args: never[]) => Promise<SpooshResponse<unknown, unknown>>>(writeFn: (api: WriteApiClient<TSchema, TDefaultError>) => TMethod) => BaseWriteResult<ExtractMethodData<TMethod>, [ExtractMethodError<TMethod>] extends [unknown] ? TDefaultError : ExtractMethodError<TMethod>, ExtractMethodOptions<TMethod> & _spoosh_core.ResolveTypes<((TPlugins[number] extends infer T ? T extends TPlugins[number] ? T extends SpooshPlugin<infer Types extends PluginTypeConfig> ? Types extends {
414
+ declare function createUseWrite<TSchema, TDefaultError, TPlugins extends readonly SpooshPlugin<PluginTypeConfig>[]>(options: Omit<SpooshInstanceShape<unknown, TSchema, TDefaultError, TPlugins>, "_types">): <TMethod extends (...args: never[]) => Promise<SpooshResponse<unknown, unknown>>>(writeFn: (api: WriteApiClient<TSchema, TDefaultError>) => TMethod) => BaseWriteResult<ExtractMethodData<TMethod>, [ExtractMethodError<TMethod>] extends [unknown] ? TDefaultError : ExtractMethodError<TMethod>, ExtractMethodOptions<TMethod> & ResolveTypes<((TPlugins[number] extends infer T ? T extends TPlugins[number] ? T extends SpooshPlugin<infer Types extends PluginTypeConfig> ? Types extends {
385
415
  writeOptions: infer W;
386
416
  } ? W : object : object : never : never) extends infer T_1 ? T_1 extends (TPlugins[number] extends infer T_2 ? T_2 extends TPlugins[number] ? T_2 extends SpooshPlugin<infer Types extends PluginTypeConfig> ? Types extends {
387
417
  writeOptions: infer W;
388
- } ? W : object : object : never : never) ? T_1 extends unknown ? (x: T_1) => void : never : never : never) extends (x: infer I) => void ? I : never, ResolverContext<TSchema, ExtractMethodData<TMethod>, [ExtractMethodError<TMethod>] extends [unknown] ? TDefaultError : ExtractMethodError<TMethod>, ExtractMethodQuery<TMethod>, ExtractMethodBody<TMethod>, ExtractResponseParamNames<TMethod> extends never ? never : Record<ExtractResponseParamNames<TMethod>, string | number>>>, ResolveResultTypes<((TPlugins[number] extends infer T_3 ? T_3 extends TPlugins[number] ? T_3 extends SpooshPlugin<infer Types_1 extends PluginTypeConfig> ? Types_1 extends {
389
- writeResult: infer W_1;
390
- } ? W_1 : object : object : never : never) extends infer T_4 ? T_4 extends (TPlugins[number] extends infer T_5 ? T_5 extends TPlugins[number] ? T_5 extends SpooshPlugin<infer Types_1 extends PluginTypeConfig> ? Types_1 extends {
391
- writeResult: infer W_1;
392
- } ? W_1 : object : object : never : never) ? T_4 extends unknown ? (x: T_4) => void : never : never : never) extends (x: infer I) => void ? I : never, ExtractMethodOptions<TMethod> & _spoosh_core.ResolveTypes<((TPlugins[number] extends infer T_6 ? T_6 extends TPlugins[number] ? T_6 extends SpooshPlugin<infer Types extends PluginTypeConfig> ? Types extends {
393
- writeOptions: infer W;
394
- } ? W : object : object : never : never) extends infer T_7 ? T_7 extends (TPlugins[number] extends infer T_8 ? T_8 extends TPlugins[number] ? T_8 extends SpooshPlugin<infer Types extends PluginTypeConfig> ? Types extends {
395
- writeOptions: infer W;
396
- } ? W : object : object : never : never) ? T_7 extends unknown ? (x: T_7) => void : never : never : never) extends (x: infer I) => void ? I : never, ResolverContext<TSchema, ExtractMethodData<TMethod>, [ExtractMethodError<TMethod>] extends [unknown] ? TDefaultError : ExtractMethodError<TMethod>, ExtractMethodQuery<TMethod>, ExtractMethodBody<TMethod>, ExtractResponseParamNames<TMethod> extends never ? never : Record<ExtractResponseParamNames<TMethod>, string | number>>>>> & WriteResponseInputFields<ExtractResponseQuery<TMethod>, ExtractResponseBody<TMethod>, ExtractResponseParamNames<TMethod>>;
418
+ } ? W : object : object : never : never) ? T_1 extends unknown ? (x: T_1) => void : never : never : never) extends (x: infer I) => void ? I : never, ResolverContext<TSchema, ExtractMethodData<TMethod>, [ExtractMethodError<TMethod>] extends [unknown] ? TDefaultError : ExtractMethodError<TMethod>, ExtractMethodQuery<TMethod>, ExtractMethodBody<TMethod>, ExtractResponseParamNames<TMethod> extends never ? never : Record<ExtractResponseParamNames<TMethod>, string | number>>>, MergePluginResults<TPlugins>["write"]> & WriteResponseInputFields<ExtractResponseQuery<TMethod>, ExtractResponseBody<TMethod>, ExtractResponseParamNames<TMethod>>;
397
419
 
398
420
  declare function createUseInfiniteRead<TSchema, TDefaultError, TPlugins extends readonly SpooshPlugin<PluginTypeConfig>[]>(options: Omit<SpooshInstanceShape<unknown, TSchema, TDefaultError, TPlugins>, "_types">): <TData, TItem, TError = TDefaultError, TRequest extends AnyInfiniteRequestOptions = AnyInfiniteRequestOptions>(readFn: (api: InfiniteReadApiClient<TSchema, TDefaultError>) => Promise<SpooshResponse<TData, TError>>, readOptions: BaseInfiniteReadOptions<TData, TItem, TRequest> & (((TPlugins[number] extends infer T_3 ? T_3 extends TPlugins[number] ? T_3 extends SpooshPlugin<infer Types_1 extends PluginTypeConfig> ? Types_1 extends {
399
421
  infiniteReadOptions: infer I_1;
package/dist/index.js CHANGED
@@ -34,11 +34,10 @@ var import_react = require("react");
34
34
  var import_core = require("@spoosh/core");
35
35
  function createUseRead(options) {
36
36
  const { api, stateManager, eventEmitter, pluginExecutor } = options;
37
- return function useRead(readFn, readOptions) {
37
+ function useRead(readFn, readOptions) {
38
38
  const {
39
39
  enabled = true,
40
40
  tags,
41
- additionalTags,
42
41
  ...pluginOpts
43
42
  } = readOptions ?? {};
44
43
  const hookId = (0, import_react.useId)();
@@ -46,8 +45,8 @@ function createUseRead(options) {
46
45
  call: null,
47
46
  selector: null
48
47
  });
49
- const selectorProxy = (0, import_core.createSelectorProxy)((result2) => {
50
- selectorResultRef.current = result2;
48
+ const selectorProxy = (0, import_core.createSelectorProxy)((result) => {
49
+ selectorResultRef.current = result;
51
50
  });
52
51
  readFn(selectorProxy);
53
52
  const capturedCall = selectorResultRef.current.call;
@@ -59,7 +58,7 @@ function createUseRead(options) {
59
58
  const requestOptions = capturedCall.options;
60
59
  const pathSegments = capturedCall.path.split("/").filter(Boolean);
61
60
  const resolvedPath = (0, import_core.resolvePath)(pathSegments, requestOptions?.params);
62
- const resolvedTags = (0, import_core.resolveTags)({ tags, additionalTags }, resolvedPath);
61
+ const resolvedTags = (0, import_core.resolveTags)({ tags }, resolvedPath);
63
62
  const queryKey = stateManager.createQueryKey({
64
63
  path: pathSegments,
65
64
  method: capturedCall.method,
@@ -107,6 +106,7 @@ function createUseRead(options) {
107
106
  const abortRef = (0, import_react.useRef)(controller.abort);
108
107
  abortRef.current = controller.abort;
109
108
  const pluginOptsKey = JSON.stringify(pluginOpts);
109
+ const tagsKey = JSON.stringify(tags);
110
110
  const executeWithTracking = (0, import_react.useCallback)(
111
111
  async (force = false) => {
112
112
  setRequestState((prev) => ({ ...prev, isPending: true }));
@@ -162,7 +162,7 @@ function createUseRead(options) {
162
162
  unsubRefetch();
163
163
  unsubInvalidate();
164
164
  };
165
- }, [queryKey, enabled]);
165
+ }, [queryKey, enabled, tagsKey]);
166
166
  (0, import_react.useEffect)(() => {
167
167
  if (!enabled || !lifecycleRef.current.initialized) return;
168
168
  const prevContext = controller.getContext();
@@ -191,7 +191,8 @@ function createUseRead(options) {
191
191
  const hasData = state.data !== void 0;
192
192
  const loading = requestState.isPending && !hasData;
193
193
  const fetching = requestState.isPending;
194
- const result = {
194
+ return {
195
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
195
196
  meta: pluginResultData,
196
197
  ...inputField,
197
198
  data: state.data,
@@ -201,8 +202,8 @@ function createUseRead(options) {
201
202
  abort,
202
203
  refetch
203
204
  };
204
- return result;
205
- };
205
+ }
206
+ return useRead;
206
207
  }
207
208
 
208
209
  // src/useWrite/index.ts
@@ -210,14 +211,14 @@ var import_react2 = require("react");
210
211
  var import_core2 = require("@spoosh/core");
211
212
  function createUseWrite(options) {
212
213
  const { api, stateManager, pluginExecutor, eventEmitter } = options;
213
- return function useWrite(writeFn) {
214
+ function useWrite(writeFn) {
214
215
  const hookId = (0, import_react2.useId)();
215
216
  const selectorResultRef = (0, import_react2.useRef)({
216
217
  call: null,
217
218
  selector: null
218
219
  });
219
- const selectorProxy = (0, import_core2.createSelectorProxy)((result2) => {
220
- selectorResultRef.current = result2;
220
+ const selectorProxy = (0, import_core2.createSelectorProxy)((result) => {
221
+ selectorResultRef.current = result;
221
222
  });
222
223
  writeFn(selectorProxy);
223
224
  const selectedEndpoint = selectorResultRef.current.selector;
@@ -308,8 +309,9 @@ function createUseWrite(options) {
308
309
  }
309
310
  const inputField = Object.keys(inputInner).length > 0 ? { input: inputInner } : {};
310
311
  const loading = requestState.isPending;
311
- const result = {
312
+ return {
312
313
  trigger,
314
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
313
315
  meta: pluginResultData,
314
316
  ...inputField,
315
317
  data: state.data,
@@ -317,9 +319,10 @@ function createUseWrite(options) {
317
319
  loading,
318
320
  reset,
319
321
  abort
322
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
320
323
  };
321
- return result;
322
- };
324
+ }
325
+ return useWrite;
323
326
  }
324
327
 
325
328
  // src/useInfiniteRead/index.ts
@@ -331,7 +334,6 @@ function createUseInfiniteRead(options) {
331
334
  const {
332
335
  enabled = true,
333
336
  tags,
334
- additionalTags,
335
337
  canFetchNext,
336
338
  nextPageRequest,
337
339
  merger,
@@ -368,7 +370,7 @@ function createUseInfiniteRead(options) {
368
370
  body: void 0
369
371
  };
370
372
  const resolvedPath = (0, import_core3.resolvePath)(pathSegments, requestOptions?.params);
371
- const resolvedTags = (0, import_core3.resolveTags)({ tags, additionalTags }, resolvedPath);
373
+ const resolvedTags = (0, import_core3.resolveTags)({ tags }, resolvedPath);
372
374
  const canFetchNextRef = (0, import_react3.useRef)(canFetchNext);
373
375
  const canFetchPrevRef = (0, import_react3.useRef)(canFetchPrev);
374
376
  const nextPageRequestRef = (0, import_react3.useRef)(nextPageRequest);
@@ -438,6 +440,7 @@ function createUseInfiniteRead(options) {
438
440
  initialized: false,
439
441
  prevContext: null
440
442
  });
443
+ const tagsKey = JSON.stringify(tags);
441
444
  (0, import_react3.useEffect)(() => {
442
445
  return () => {
443
446
  controllerRef.current?.controller.unmount();
@@ -462,7 +465,7 @@ function createUseInfiniteRead(options) {
462
465
  return () => {
463
466
  unsubInvalidate();
464
467
  };
465
- }, []);
468
+ }, [tagsKey]);
466
469
  (0, import_react3.useEffect)(() => {
467
470
  if (!lifecycleRef.current.initialized) return;
468
471
  if (enabled) {
package/dist/index.mjs CHANGED
@@ -18,11 +18,10 @@ import {
18
18
  } from "@spoosh/core";
19
19
  function createUseRead(options) {
20
20
  const { api, stateManager, eventEmitter, pluginExecutor } = options;
21
- return function useRead(readFn, readOptions) {
21
+ function useRead(readFn, readOptions) {
22
22
  const {
23
23
  enabled = true,
24
24
  tags,
25
- additionalTags,
26
25
  ...pluginOpts
27
26
  } = readOptions ?? {};
28
27
  const hookId = useId();
@@ -30,8 +29,8 @@ function createUseRead(options) {
30
29
  call: null,
31
30
  selector: null
32
31
  });
33
- const selectorProxy = createSelectorProxy((result2) => {
34
- selectorResultRef.current = result2;
32
+ const selectorProxy = createSelectorProxy((result) => {
33
+ selectorResultRef.current = result;
35
34
  });
36
35
  readFn(selectorProxy);
37
36
  const capturedCall = selectorResultRef.current.call;
@@ -43,7 +42,7 @@ function createUseRead(options) {
43
42
  const requestOptions = capturedCall.options;
44
43
  const pathSegments = capturedCall.path.split("/").filter(Boolean);
45
44
  const resolvedPath = resolvePath(pathSegments, requestOptions?.params);
46
- const resolvedTags = resolveTags({ tags, additionalTags }, resolvedPath);
45
+ const resolvedTags = resolveTags({ tags }, resolvedPath);
47
46
  const queryKey = stateManager.createQueryKey({
48
47
  path: pathSegments,
49
48
  method: capturedCall.method,
@@ -91,6 +90,7 @@ function createUseRead(options) {
91
90
  const abortRef = useRef(controller.abort);
92
91
  abortRef.current = controller.abort;
93
92
  const pluginOptsKey = JSON.stringify(pluginOpts);
93
+ const tagsKey = JSON.stringify(tags);
94
94
  const executeWithTracking = useCallback(
95
95
  async (force = false) => {
96
96
  setRequestState((prev) => ({ ...prev, isPending: true }));
@@ -146,7 +146,7 @@ function createUseRead(options) {
146
146
  unsubRefetch();
147
147
  unsubInvalidate();
148
148
  };
149
- }, [queryKey, enabled]);
149
+ }, [queryKey, enabled, tagsKey]);
150
150
  useEffect(() => {
151
151
  if (!enabled || !lifecycleRef.current.initialized) return;
152
152
  const prevContext = controller.getContext();
@@ -175,7 +175,8 @@ function createUseRead(options) {
175
175
  const hasData = state.data !== void 0;
176
176
  const loading = requestState.isPending && !hasData;
177
177
  const fetching = requestState.isPending;
178
- const result = {
178
+ return {
179
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
179
180
  meta: pluginResultData,
180
181
  ...inputField,
181
182
  data: state.data,
@@ -185,8 +186,8 @@ function createUseRead(options) {
185
186
  abort,
186
187
  refetch
187
188
  };
188
- return result;
189
- };
189
+ }
190
+ return useRead;
190
191
  }
191
192
 
192
193
  // src/useWrite/index.ts
@@ -205,14 +206,14 @@ import {
205
206
  } from "@spoosh/core";
206
207
  function createUseWrite(options) {
207
208
  const { api, stateManager, pluginExecutor, eventEmitter } = options;
208
- return function useWrite(writeFn) {
209
+ function useWrite(writeFn) {
209
210
  const hookId = useId2();
210
211
  const selectorResultRef = useRef2({
211
212
  call: null,
212
213
  selector: null
213
214
  });
214
- const selectorProxy = createSelectorProxy2((result2) => {
215
- selectorResultRef.current = result2;
215
+ const selectorProxy = createSelectorProxy2((result) => {
216
+ selectorResultRef.current = result;
216
217
  });
217
218
  writeFn(selectorProxy);
218
219
  const selectedEndpoint = selectorResultRef.current.selector;
@@ -303,8 +304,9 @@ function createUseWrite(options) {
303
304
  }
304
305
  const inputField = Object.keys(inputInner).length > 0 ? { input: inputInner } : {};
305
306
  const loading = requestState.isPending;
306
- const result = {
307
+ return {
307
308
  trigger,
309
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
308
310
  meta: pluginResultData,
309
311
  ...inputField,
310
312
  data: state.data,
@@ -312,9 +314,10 @@ function createUseWrite(options) {
312
314
  loading,
313
315
  reset,
314
316
  abort
317
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
315
318
  };
316
- return result;
317
- };
319
+ }
320
+ return useWrite;
318
321
  }
319
322
 
320
323
  // src/useInfiniteRead/index.ts
@@ -337,7 +340,6 @@ function createUseInfiniteRead(options) {
337
340
  const {
338
341
  enabled = true,
339
342
  tags,
340
- additionalTags,
341
343
  canFetchNext,
342
344
  nextPageRequest,
343
345
  merger,
@@ -374,7 +376,7 @@ function createUseInfiniteRead(options) {
374
376
  body: void 0
375
377
  };
376
378
  const resolvedPath = resolvePath3(pathSegments, requestOptions?.params);
377
- const resolvedTags = resolveTags3({ tags, additionalTags }, resolvedPath);
379
+ const resolvedTags = resolveTags3({ tags }, resolvedPath);
378
380
  const canFetchNextRef = useRef3(canFetchNext);
379
381
  const canFetchPrevRef = useRef3(canFetchPrev);
380
382
  const nextPageRequestRef = useRef3(nextPageRequest);
@@ -444,6 +446,7 @@ function createUseInfiniteRead(options) {
444
446
  initialized: false,
445
447
  prevContext: null
446
448
  });
449
+ const tagsKey = JSON.stringify(tags);
447
450
  useEffect2(() => {
448
451
  return () => {
449
452
  controllerRef.current?.controller.unmount();
@@ -468,7 +471,7 @@ function createUseInfiniteRead(options) {
468
471
  return () => {
469
472
  unsubInvalidate();
470
473
  };
471
- }, []);
474
+ }, [tagsKey]);
472
475
  useEffect2(() => {
473
476
  if (!lifecycleRef.current.initialized) return;
474
477
  if (enabled) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spoosh/react",
3
- "version": "0.4.1",
3
+ "version": "0.5.1",
4
4
  "license": "MIT",
5
5
  "description": "React hooks for Spoosh API client",
6
6
  "keywords": [
@@ -34,11 +34,11 @@
34
34
  }
35
35
  },
36
36
  "peerDependencies": {
37
- "@spoosh/core": ">=0.6.0",
37
+ "@spoosh/core": ">=0.7.0",
38
38
  "react": "^18 || ^19"
39
39
  },
40
40
  "devDependencies": {
41
- "@spoosh/core": "0.6.0"
41
+ "@spoosh/core": "0.7.0"
42
42
  },
43
43
  "scripts": {
44
44
  "dev": "tsup --watch",