@spoosh/angular 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -48,7 +48,7 @@ Fetch data with automatic caching and refetching using Angular signals.
48
48
  `,
49
49
  })
50
50
  export class UserListComponent {
51
- users = injectRead((api) => api.users.$get());
51
+ users = injectRead((api) => api("users").GET());
52
52
  }
53
53
 
54
54
  // With options
@@ -58,15 +58,19 @@ export class UserListComponent {
58
58
 
59
59
  // Recommended: Pass signal directly (shorter syntax)
60
60
  users = injectRead(
61
- (api) => api.users.$get({ query: { page: 1 } }),
61
+ (api) => api("users").GET({ query: { page: 1 } }),
62
62
  {
63
63
  staleTime: 10000,
64
64
  enabled: this.isReady,
65
65
  }
66
66
  );
67
67
 
68
- // Also works: Arrow function wrapper
69
- // enabled: () => this.isReady(),
68
+ // With path parameters
69
+ userId = signal(123);
70
+ user = injectRead(
71
+ (api) => api("users/:id").GET({ params: { id: this.userId() } }),
72
+ { enabled: () => this.userId() !== null }
73
+ );
70
74
  }
71
75
  ```
72
76
 
@@ -88,7 +92,7 @@ Trigger mutations with loading and error states.
88
92
  export class CreateUserComponent {
89
93
  title = signal("");
90
94
 
91
- createUser = injectWrite((api) => api.users.$post);
95
+ createUser = injectWrite((api) => api("users").POST);
92
96
 
93
97
  async handleSubmit() {
94
98
  const result = await this.createUser.trigger({
@@ -100,6 +104,16 @@ export class CreateUserComponent {
100
104
  }
101
105
  }
102
106
  }
107
+
108
+ // With path parameters
109
+ updateUser = injectWrite((api) => api("users/:id").PUT);
110
+
111
+ async updateUserName(userId: number, name: string) {
112
+ await this.updateUser.trigger({
113
+ params: { id: userId },
114
+ body: { name },
115
+ });
116
+ }
103
117
  ```
104
118
 
105
119
  ### injectInfiniteRead
@@ -127,26 +141,29 @@ Bidirectional paginated data fetching with infinite scroll support.
127
141
  `,
128
142
  })
129
143
  export class PostListComponent {
130
- posts = injectInfiniteRead((api) => api.posts.$get({ query: { page: 1 } }), {
131
- // Required: Check if next page exists
132
- canFetchNext: ({ response }) => response?.meta.hasMore ?? false,
144
+ posts = injectInfiniteRead(
145
+ (api) => api("posts").GET({ query: { page: 1 } }),
146
+ {
147
+ // Required: Check if next page exists
148
+ canFetchNext: ({ response }) => response?.meta.hasMore ?? false,
133
149
 
134
- // Required: Build request for next page
135
- nextPageRequest: ({ response, request }) => ({
136
- query: { ...request.query, page: (response?.meta.page ?? 0) + 1 },
137
- }),
150
+ // Required: Build request for next page
151
+ nextPageRequest: ({ response, request }) => ({
152
+ query: { ...request.query, page: (response?.meta.page ?? 0) + 1 },
153
+ }),
138
154
 
139
- // Required: Merge all responses into items
140
- merger: (allResponses) => allResponses.flatMap((r) => r.items),
155
+ // Required: Merge all responses into items
156
+ merger: (allResponses) => allResponses.flatMap((r) => r.items),
141
157
 
142
- // Optional: Check if previous page exists
143
- canFetchPrev: ({ response }) => (response?.meta.page ?? 1) > 1,
158
+ // Optional: Check if previous page exists
159
+ canFetchPrev: ({ response }) => (response?.meta.page ?? 1) > 1,
144
160
 
145
- // Optional: Build request for previous page
146
- prevPageRequest: ({ response, request }) => ({
147
- query: { ...request.query, page: (response?.meta.page ?? 2) - 1 },
148
- }),
149
- });
161
+ // Optional: Build request for previous page
162
+ prevPageRequest: ({ response, request }) => ({
163
+ query: { ...request.query, page: (response?.meta.page ?? 2) - 1 },
164
+ }),
165
+ }
166
+ );
150
167
  }
151
168
  ```
152
169
 
package/dist/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as _spoosh_core from '@spoosh/core';
2
- import { PluginArray, StateManager, EventEmitter, PluginExecutor, QueryOnlyClient, MethodOptionsMap, CoreRequestOptionsBase, SpooshResponse, MutationOnlyClient, SpooshPlugin, PluginTypeConfig, InfiniteRequestOptions, ResolveTypes, ResolverContext, ResolveResultTypes, MergePluginInstanceApi } from '@spoosh/core';
2
+ import { PluginArray, StateManager, EventEmitter, PluginExecutor, ReadClient, TagOptions, SpooshResponse, WriteClient, MethodOptionsMap, CoreRequestOptionsBase, SpooshPlugin, PluginTypeConfig, InfiniteRequestOptions, ResolveTypes, ResolverContext, ResolveResultTypes, MergePluginInstanceApi } from '@spoosh/core';
3
3
  import { Signal } from '@angular/core';
4
4
 
5
5
  interface SpooshInstanceShape<TApi, TSchema, TDefaultError, TPlugins extends PluginArray> {
@@ -14,10 +14,8 @@ interface SpooshInstanceShape<TApi, TSchema, TDefaultError, TPlugins extends Plu
14
14
  };
15
15
  }
16
16
  type EnabledOption = boolean | (() => boolean);
17
- interface BaseReadOptions {
17
+ interface BaseReadOptions extends TagOptions {
18
18
  enabled?: EnabledOption;
19
- tags?: string[];
20
- additionalTags?: string[];
21
19
  }
22
20
  interface BaseReadResult<TData, TError, TPluginResult = Record<string, unknown>> {
23
21
  data: Signal<TData | undefined>;
@@ -42,7 +40,8 @@ type PageContext<TData, TRequest> = {
42
40
  allResponses: TData[];
43
41
  request: TRequest;
44
42
  };
45
- interface BaseInfiniteReadOptions<TData, TItem, TRequest> extends BaseReadOptions {
43
+ interface BaseInfiniteReadOptions<TData, TItem, TRequest> extends TagOptions {
44
+ enabled?: EnabledOption;
46
45
  canFetchNext: (ctx: PageContext<TData, TRequest>) => boolean;
47
46
  canFetchPrev?: (ctx: PageContext<TData, TRequest>) => boolean;
48
47
  nextPageRequest: (ctx: PageContext<TData, TRequest>) => Partial<TRequest>;
@@ -68,8 +67,8 @@ interface BaseInfiniteReadResult<TData, TError, TItem, TPluginResult = Record<st
68
67
  type QueryRequestOptions = CoreRequestOptionsBase;
69
68
  type MutationRequestOptions = CoreRequestOptionsBase;
70
69
  type AngularOptionsMap = MethodOptionsMap<QueryRequestOptions, MutationRequestOptions>;
71
- type ReadApiClient<TSchema, TDefaultError> = QueryOnlyClient<TSchema, TDefaultError, AngularOptionsMap>;
72
- type WriteApiClient<TSchema, TDefaultError> = MutationOnlyClient<TSchema, TDefaultError, AngularOptionsMap>;
70
+ type ReadApiClient<TSchema, TDefaultError> = ReadClient<TSchema, TDefaultError>;
71
+ type WriteApiClient<TSchema, TDefaultError> = WriteClient<TSchema, TDefaultError>;
73
72
  type QueryField<TQuery> = [TQuery] extends [never] ? object : undefined extends TQuery ? {
74
73
  query?: Exclude<TQuery, undefined>;
75
74
  } : {
@@ -80,17 +79,16 @@ type BodyField<TBody> = [TBody] extends [never] ? object : undefined extends TBo
80
79
  } : {
81
80
  body: TBody;
82
81
  };
83
- type FormDataField<TFormData> = [TFormData] extends [never] ? object : undefined extends TFormData ? {
84
- formData?: Exclude<TFormData, undefined>;
85
- } : {
86
- formData: TFormData;
87
- };
88
82
  type ParamsField<TParamNames extends string> = [TParamNames] extends [never] ? object : {
89
83
  params: Record<TParamNames, string | number>;
90
84
  };
91
- type ReadInputFields<TQuery, TBody, TFormData, TParamNames extends string> = QueryField<TQuery> & BodyField<TBody> & FormDataField<TFormData> & ParamsField<TParamNames>;
92
- type ResponseInputFields<TQuery, TBody, TFormData, TParamNames extends string> = [TQuery, TBody, TFormData, TParamNames] extends [never, never, never, never] ? object : {
93
- input: ReadInputFields<TQuery, TBody, TFormData, TParamNames>;
85
+ type ReadInputFields<TQuery, TBody, TParamNames extends string> = QueryField<TQuery> & BodyField<TBody> & ParamsField<TParamNames>;
86
+ type ResponseInputFields<TQuery, TBody, TParamNames extends string> = [
87
+ TQuery,
88
+ TBody,
89
+ TParamNames
90
+ ] extends [never, never, never] ? object : {
91
+ input: ReadInputFields<TQuery, TBody, TParamNames>;
94
92
  };
95
93
  type OptionalQueryField<TQuery> = [TQuery] extends [never] ? object : undefined extends TQuery ? {
96
94
  query?: Exclude<TQuery, undefined>;
@@ -102,19 +100,14 @@ type OptionalBodyField<TBody> = [TBody] extends [never] ? object : undefined ext
102
100
  } : {
103
101
  body: TBody;
104
102
  };
105
- type OptionalFormDataField<TFormData> = [TFormData] extends [never] ? object : undefined extends TFormData ? {
106
- formData?: Exclude<TFormData, undefined>;
107
- } : {
108
- formData: TFormData;
109
- };
110
103
  type OptionalParamsField<TParamNames extends string> = [TParamNames] extends [
111
104
  never
112
105
  ] ? object : {
113
106
  params: Record<TParamNames, string | number>;
114
107
  };
115
- type InputFields<TQuery, TBody, TFormData, TParamNames extends string> = OptionalQueryField<TQuery> & OptionalBodyField<TBody> & OptionalFormDataField<TFormData> & OptionalParamsField<TParamNames>;
116
- type WriteResponseInputFields<TQuery, TBody, TFormData, TParamNames extends string> = [TQuery, TBody, TFormData, TParamNames] extends [never, never, never, never] ? object : {
117
- input: Signal<InputFields<TQuery, TBody, TFormData, TParamNames> | undefined>;
108
+ type InputFields<TQuery, TBody, TParamNames extends string> = OptionalQueryField<TQuery> & OptionalBodyField<TBody> & OptionalParamsField<TParamNames>;
109
+ type WriteResponseInputFields<TQuery, TBody, TParamNames extends string> = [TQuery, TBody, TParamNames] extends [never, never, never] ? object : {
110
+ input: Signal<InputFields<TQuery, TBody, TParamNames> | undefined>;
118
111
  };
119
112
  type SuccessResponse<T> = Extract<T, {
120
113
  data: unknown;
@@ -143,11 +136,6 @@ type ExtractResponseBody<T> = SuccessReturnType<T> extends {
143
136
  body: infer B;
144
137
  };
145
138
  } ? B : never;
146
- type ExtractResponseFormData<T> = SuccessReturnType<T> extends {
147
- input: {
148
- formData: infer F;
149
- };
150
- } ? F : never;
151
139
  type ExtractResponseParamNames<T> = SuccessReturnType<T> extends {
152
140
  input: {
153
141
  params: Record<infer K, unknown>;
@@ -159,12 +147,6 @@ type ExtractMethodQuery<T> = ExtractMethodOptions<T> extends {
159
147
  type ExtractMethodBody<T> = ExtractMethodOptions<T> extends {
160
148
  body: infer B;
161
149
  } ? B : never;
162
- type ExtractMethodFormData<T> = ExtractMethodOptions<T> extends {
163
- formData: infer F;
164
- } ? F : never;
165
- type ExtractMethodUrlEncoded<T> = ExtractMethodOptions<T> extends {
166
- urlEncoded: infer U;
167
- } ? U : never;
168
150
 
169
151
  type AnyInfiniteRequestOptions = InfiniteRequestOptions;
170
152
  declare function createInjectInfiniteRead<TSchema, TDefaultError, TPlugins extends readonly SpooshPlugin<PluginTypeConfig>[]>(options: Omit<SpooshInstanceShape<unknown, TSchema, TDefaultError, TPlugins>, "_types">): <TReadFn extends (api: ReadApiClient<TSchema, TDefaultError>) => Promise<SpooshResponse<unknown, unknown>>, TRequest extends AnyInfiniteRequestOptions = AnyInfiniteRequestOptions, TItem = unknown>(readFn: TReadFn, readOptions: BaseInfiniteReadOptions<TReadFn extends (...args: never[]) => infer R ? Extract<Awaited<R>, {
@@ -231,7 +213,7 @@ declare function createInjectWrite<TSchema, TDefaultError, TPlugins extends read
231
213
  data?: undefined;
232
214
  }> extends {
233
215
  error: infer E;
234
- } ? E : unknown : unknown, ExtractMethodQuery<TMethod>, ExtractMethodBody<TMethod>, ExtractResponseParamNames<TMethod> extends never ? never : Record<ExtractResponseParamNames<TMethod>, string | number>, ExtractMethodFormData<TMethod>, never>> = (TMethod extends (...args: infer A) => unknown ? A[0] : never) & _spoosh_core.ResolveTypes<((TPlugins[number] extends infer T_6 ? T_6 extends TPlugins[number] ? T_6 extends SpooshPlugin<infer Types_1 extends PluginTypeConfig> ? Types_1 extends {
216
+ } ? E : unknown : unknown, ExtractMethodQuery<TMethod>, ExtractMethodBody<TMethod>, ExtractResponseParamNames<TMethod> extends never ? never : Record<ExtractResponseParamNames<TMethod>, string | number>>> = (TMethod extends (...args: infer A) => unknown ? A[0] : never) & _spoosh_core.ResolveTypes<((TPlugins[number] extends infer T_6 ? T_6 extends TPlugins[number] ? T_6 extends SpooshPlugin<infer Types_1 extends PluginTypeConfig> ? Types_1 extends {
235
217
  writeOptions: infer W_1;
236
218
  } ? W_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 {
237
219
  writeOptions: infer W_1;
@@ -250,7 +232,7 @@ declare function createInjectWrite<TSchema, TDefaultError, TPlugins extends read
250
232
  data?: undefined;
251
233
  }> extends {
252
234
  error: infer E;
253
- } ? E : unknown : unknown, ExtractMethodQuery<TMethod>, ExtractMethodBody<TMethod>, ExtractResponseParamNames<TMethod> extends never ? never : Record<ExtractResponseParamNames<TMethod>, string | number>, ExtractMethodFormData<TMethod>, never>>>(writeFn: (api: WriteApiClient<TSchema, TDefaultError>) => TMethod) => BaseWriteResult<TMethod extends (...args: never[]) => infer R ? Extract<Awaited<R>, {
235
+ } ? E : unknown : unknown, ExtractMethodQuery<TMethod>, ExtractMethodBody<TMethod>, ExtractResponseParamNames<TMethod> extends never ? never : Record<ExtractResponseParamNames<TMethod>, string | number>>>>(writeFn: (api: WriteApiClient<TSchema, TDefaultError>) => TMethod) => BaseWriteResult<TMethod extends (...args: never[]) => infer R ? Extract<Awaited<R>, {
254
236
  data: unknown;
255
237
  error?: undefined;
256
238
  }> extends {
@@ -269,7 +251,7 @@ declare function createInjectWrite<TSchema, TDefaultError, TPlugins extends read
269
251
  writeResult: infer W;
270
252
  } ? 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 {
271
253
  writeResult: infer W;
272
- } ? W : object : object : never : never) ? T_1 extends unknown ? (x: T_1) => void : never : never : never) extends (x: infer I) => void ? I : never, TWriteOpts>> & WriteResponseInputFields<ExtractResponseQuery<TMethod>, ExtractResponseBody<TMethod>, ExtractResponseFormData<TMethod>, ExtractResponseParamNames<TMethod>>;
254
+ } ? W : object : object : never : never) ? T_1 extends unknown ? (x: T_1) => void : never : never : never) extends (x: infer I) => void ? I : never, TWriteOpts>> & WriteResponseInputFields<ExtractResponseQuery<TMethod>, ExtractResponseBody<TMethod>, ExtractResponseParamNames<TMethod>>;
273
255
 
274
256
  declare function createInjectRead<TSchema, TDefaultError, TPlugins extends readonly SpooshPlugin<PluginTypeConfig>[]>(options: Omit<SpooshInstanceShape<unknown, TSchema, TDefaultError, TPlugins>, "_types">): <TReadFn extends (api: ReadApiClient<TSchema, TDefaultError>) => Promise<{
275
257
  data?: unknown;
@@ -331,7 +313,7 @@ declare function createInjectRead<TSchema, TDefaultError, TPlugins extends reado
331
313
  readResult: infer R_2;
332
314
  } ? R_2 : 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 {
333
315
  readResult: infer R_2;
334
- } ? R_2 : 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>, ExtractResponseFormData<TReadFn>, ExtractResponseParamNames<TReadFn>>;
316
+ } ? R_2 : 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>>;
335
317
 
336
318
  type SpooshAngularFunctions<TDefaultError, TSchema, TPlugins extends PluginArray> = {
337
319
  injectRead: ReturnType<typeof createInjectRead<TSchema, TDefaultError, TPlugins>>;
@@ -341,4 +323,4 @@ type SpooshAngularFunctions<TDefaultError, TSchema, TPlugins extends PluginArray
341
323
 
342
324
  declare function createAngularSpoosh<TSchema, TDefaultError, TPlugins extends PluginArray, TApi>(instance: SpooshInstanceShape<TApi, TSchema, TDefaultError, TPlugins>): SpooshAngularFunctions<TDefaultError, TSchema, TPlugins>;
343
325
 
344
- export { type AngularOptionsMap, type BaseInfiniteReadOptions, type BaseInfiniteReadResult, type BaseReadOptions, type BaseReadResult, type BaseWriteResult, type EnabledOption, type ExtractMethodBody, type ExtractMethodData, type ExtractMethodError, type ExtractMethodFormData, type ExtractMethodOptions, type ExtractMethodQuery, type ExtractMethodUrlEncoded, type ExtractResponseBody, type ExtractResponseFormData, type ExtractResponseParamNames, type ExtractResponseQuery, type PageContext, type ReadApiClient, type ResponseInputFields, type SpooshInstanceShape, type WriteApiClient, type WriteResponseInputFields, createAngularSpoosh };
326
+ export { type AngularOptionsMap, type BaseInfiniteReadOptions, type BaseInfiniteReadResult, type BaseReadOptions, type BaseReadResult, type BaseWriteResult, type EnabledOption, type ExtractMethodBody, type ExtractMethodData, type ExtractMethodError, type ExtractMethodOptions, type ExtractMethodQuery, type ExtractResponseBody, type ExtractResponseParamNames, type ExtractResponseQuery, type PageContext, type ReadApiClient, type ResponseInputFields, type SpooshInstanceShape, type WriteApiClient, type WriteResponseInputFields, createAngularSpoosh };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as _spoosh_core from '@spoosh/core';
2
- import { PluginArray, StateManager, EventEmitter, PluginExecutor, QueryOnlyClient, MethodOptionsMap, CoreRequestOptionsBase, SpooshResponse, MutationOnlyClient, SpooshPlugin, PluginTypeConfig, InfiniteRequestOptions, ResolveTypes, ResolverContext, ResolveResultTypes, MergePluginInstanceApi } from '@spoosh/core';
2
+ import { PluginArray, StateManager, EventEmitter, PluginExecutor, ReadClient, TagOptions, SpooshResponse, WriteClient, MethodOptionsMap, CoreRequestOptionsBase, SpooshPlugin, PluginTypeConfig, InfiniteRequestOptions, ResolveTypes, ResolverContext, ResolveResultTypes, MergePluginInstanceApi } from '@spoosh/core';
3
3
  import { Signal } from '@angular/core';
4
4
 
5
5
  interface SpooshInstanceShape<TApi, TSchema, TDefaultError, TPlugins extends PluginArray> {
@@ -14,10 +14,8 @@ interface SpooshInstanceShape<TApi, TSchema, TDefaultError, TPlugins extends Plu
14
14
  };
15
15
  }
16
16
  type EnabledOption = boolean | (() => boolean);
17
- interface BaseReadOptions {
17
+ interface BaseReadOptions extends TagOptions {
18
18
  enabled?: EnabledOption;
19
- tags?: string[];
20
- additionalTags?: string[];
21
19
  }
22
20
  interface BaseReadResult<TData, TError, TPluginResult = Record<string, unknown>> {
23
21
  data: Signal<TData | undefined>;
@@ -42,7 +40,8 @@ type PageContext<TData, TRequest> = {
42
40
  allResponses: TData[];
43
41
  request: TRequest;
44
42
  };
45
- interface BaseInfiniteReadOptions<TData, TItem, TRequest> extends BaseReadOptions {
43
+ interface BaseInfiniteReadOptions<TData, TItem, TRequest> extends TagOptions {
44
+ enabled?: EnabledOption;
46
45
  canFetchNext: (ctx: PageContext<TData, TRequest>) => boolean;
47
46
  canFetchPrev?: (ctx: PageContext<TData, TRequest>) => boolean;
48
47
  nextPageRequest: (ctx: PageContext<TData, TRequest>) => Partial<TRequest>;
@@ -68,8 +67,8 @@ interface BaseInfiniteReadResult<TData, TError, TItem, TPluginResult = Record<st
68
67
  type QueryRequestOptions = CoreRequestOptionsBase;
69
68
  type MutationRequestOptions = CoreRequestOptionsBase;
70
69
  type AngularOptionsMap = MethodOptionsMap<QueryRequestOptions, MutationRequestOptions>;
71
- type ReadApiClient<TSchema, TDefaultError> = QueryOnlyClient<TSchema, TDefaultError, AngularOptionsMap>;
72
- type WriteApiClient<TSchema, TDefaultError> = MutationOnlyClient<TSchema, TDefaultError, AngularOptionsMap>;
70
+ type ReadApiClient<TSchema, TDefaultError> = ReadClient<TSchema, TDefaultError>;
71
+ type WriteApiClient<TSchema, TDefaultError> = WriteClient<TSchema, TDefaultError>;
73
72
  type QueryField<TQuery> = [TQuery] extends [never] ? object : undefined extends TQuery ? {
74
73
  query?: Exclude<TQuery, undefined>;
75
74
  } : {
@@ -80,17 +79,16 @@ type BodyField<TBody> = [TBody] extends [never] ? object : undefined extends TBo
80
79
  } : {
81
80
  body: TBody;
82
81
  };
83
- type FormDataField<TFormData> = [TFormData] extends [never] ? object : undefined extends TFormData ? {
84
- formData?: Exclude<TFormData, undefined>;
85
- } : {
86
- formData: TFormData;
87
- };
88
82
  type ParamsField<TParamNames extends string> = [TParamNames] extends [never] ? object : {
89
83
  params: Record<TParamNames, string | number>;
90
84
  };
91
- type ReadInputFields<TQuery, TBody, TFormData, TParamNames extends string> = QueryField<TQuery> & BodyField<TBody> & FormDataField<TFormData> & ParamsField<TParamNames>;
92
- type ResponseInputFields<TQuery, TBody, TFormData, TParamNames extends string> = [TQuery, TBody, TFormData, TParamNames] extends [never, never, never, never] ? object : {
93
- input: ReadInputFields<TQuery, TBody, TFormData, TParamNames>;
85
+ type ReadInputFields<TQuery, TBody, TParamNames extends string> = QueryField<TQuery> & BodyField<TBody> & ParamsField<TParamNames>;
86
+ type ResponseInputFields<TQuery, TBody, TParamNames extends string> = [
87
+ TQuery,
88
+ TBody,
89
+ TParamNames
90
+ ] extends [never, never, never] ? object : {
91
+ input: ReadInputFields<TQuery, TBody, TParamNames>;
94
92
  };
95
93
  type OptionalQueryField<TQuery> = [TQuery] extends [never] ? object : undefined extends TQuery ? {
96
94
  query?: Exclude<TQuery, undefined>;
@@ -102,19 +100,14 @@ type OptionalBodyField<TBody> = [TBody] extends [never] ? object : undefined ext
102
100
  } : {
103
101
  body: TBody;
104
102
  };
105
- type OptionalFormDataField<TFormData> = [TFormData] extends [never] ? object : undefined extends TFormData ? {
106
- formData?: Exclude<TFormData, undefined>;
107
- } : {
108
- formData: TFormData;
109
- };
110
103
  type OptionalParamsField<TParamNames extends string> = [TParamNames] extends [
111
104
  never
112
105
  ] ? object : {
113
106
  params: Record<TParamNames, string | number>;
114
107
  };
115
- type InputFields<TQuery, TBody, TFormData, TParamNames extends string> = OptionalQueryField<TQuery> & OptionalBodyField<TBody> & OptionalFormDataField<TFormData> & OptionalParamsField<TParamNames>;
116
- type WriteResponseInputFields<TQuery, TBody, TFormData, TParamNames extends string> = [TQuery, TBody, TFormData, TParamNames] extends [never, never, never, never] ? object : {
117
- input: Signal<InputFields<TQuery, TBody, TFormData, TParamNames> | undefined>;
108
+ type InputFields<TQuery, TBody, TParamNames extends string> = OptionalQueryField<TQuery> & OptionalBodyField<TBody> & OptionalParamsField<TParamNames>;
109
+ type WriteResponseInputFields<TQuery, TBody, TParamNames extends string> = [TQuery, TBody, TParamNames] extends [never, never, never] ? object : {
110
+ input: Signal<InputFields<TQuery, TBody, TParamNames> | undefined>;
118
111
  };
119
112
  type SuccessResponse<T> = Extract<T, {
120
113
  data: unknown;
@@ -143,11 +136,6 @@ type ExtractResponseBody<T> = SuccessReturnType<T> extends {
143
136
  body: infer B;
144
137
  };
145
138
  } ? B : never;
146
- type ExtractResponseFormData<T> = SuccessReturnType<T> extends {
147
- input: {
148
- formData: infer F;
149
- };
150
- } ? F : never;
151
139
  type ExtractResponseParamNames<T> = SuccessReturnType<T> extends {
152
140
  input: {
153
141
  params: Record<infer K, unknown>;
@@ -159,12 +147,6 @@ type ExtractMethodQuery<T> = ExtractMethodOptions<T> extends {
159
147
  type ExtractMethodBody<T> = ExtractMethodOptions<T> extends {
160
148
  body: infer B;
161
149
  } ? B : never;
162
- type ExtractMethodFormData<T> = ExtractMethodOptions<T> extends {
163
- formData: infer F;
164
- } ? F : never;
165
- type ExtractMethodUrlEncoded<T> = ExtractMethodOptions<T> extends {
166
- urlEncoded: infer U;
167
- } ? U : never;
168
150
 
169
151
  type AnyInfiniteRequestOptions = InfiniteRequestOptions;
170
152
  declare function createInjectInfiniteRead<TSchema, TDefaultError, TPlugins extends readonly SpooshPlugin<PluginTypeConfig>[]>(options: Omit<SpooshInstanceShape<unknown, TSchema, TDefaultError, TPlugins>, "_types">): <TReadFn extends (api: ReadApiClient<TSchema, TDefaultError>) => Promise<SpooshResponse<unknown, unknown>>, TRequest extends AnyInfiniteRequestOptions = AnyInfiniteRequestOptions, TItem = unknown>(readFn: TReadFn, readOptions: BaseInfiniteReadOptions<TReadFn extends (...args: never[]) => infer R ? Extract<Awaited<R>, {
@@ -231,7 +213,7 @@ declare function createInjectWrite<TSchema, TDefaultError, TPlugins extends read
231
213
  data?: undefined;
232
214
  }> extends {
233
215
  error: infer E;
234
- } ? E : unknown : unknown, ExtractMethodQuery<TMethod>, ExtractMethodBody<TMethod>, ExtractResponseParamNames<TMethod> extends never ? never : Record<ExtractResponseParamNames<TMethod>, string | number>, ExtractMethodFormData<TMethod>, never>> = (TMethod extends (...args: infer A) => unknown ? A[0] : never) & _spoosh_core.ResolveTypes<((TPlugins[number] extends infer T_6 ? T_6 extends TPlugins[number] ? T_6 extends SpooshPlugin<infer Types_1 extends PluginTypeConfig> ? Types_1 extends {
216
+ } ? E : unknown : unknown, ExtractMethodQuery<TMethod>, ExtractMethodBody<TMethod>, ExtractResponseParamNames<TMethod> extends never ? never : Record<ExtractResponseParamNames<TMethod>, string | number>>> = (TMethod extends (...args: infer A) => unknown ? A[0] : never) & _spoosh_core.ResolveTypes<((TPlugins[number] extends infer T_6 ? T_6 extends TPlugins[number] ? T_6 extends SpooshPlugin<infer Types_1 extends PluginTypeConfig> ? Types_1 extends {
235
217
  writeOptions: infer W_1;
236
218
  } ? W_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 {
237
219
  writeOptions: infer W_1;
@@ -250,7 +232,7 @@ declare function createInjectWrite<TSchema, TDefaultError, TPlugins extends read
250
232
  data?: undefined;
251
233
  }> extends {
252
234
  error: infer E;
253
- } ? E : unknown : unknown, ExtractMethodQuery<TMethod>, ExtractMethodBody<TMethod>, ExtractResponseParamNames<TMethod> extends never ? never : Record<ExtractResponseParamNames<TMethod>, string | number>, ExtractMethodFormData<TMethod>, never>>>(writeFn: (api: WriteApiClient<TSchema, TDefaultError>) => TMethod) => BaseWriteResult<TMethod extends (...args: never[]) => infer R ? Extract<Awaited<R>, {
235
+ } ? E : unknown : unknown, ExtractMethodQuery<TMethod>, ExtractMethodBody<TMethod>, ExtractResponseParamNames<TMethod> extends never ? never : Record<ExtractResponseParamNames<TMethod>, string | number>>>>(writeFn: (api: WriteApiClient<TSchema, TDefaultError>) => TMethod) => BaseWriteResult<TMethod extends (...args: never[]) => infer R ? Extract<Awaited<R>, {
254
236
  data: unknown;
255
237
  error?: undefined;
256
238
  }> extends {
@@ -269,7 +251,7 @@ declare function createInjectWrite<TSchema, TDefaultError, TPlugins extends read
269
251
  writeResult: infer W;
270
252
  } ? 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 {
271
253
  writeResult: infer W;
272
- } ? W : object : object : never : never) ? T_1 extends unknown ? (x: T_1) => void : never : never : never) extends (x: infer I) => void ? I : never, TWriteOpts>> & WriteResponseInputFields<ExtractResponseQuery<TMethod>, ExtractResponseBody<TMethod>, ExtractResponseFormData<TMethod>, ExtractResponseParamNames<TMethod>>;
254
+ } ? W : object : object : never : never) ? T_1 extends unknown ? (x: T_1) => void : never : never : never) extends (x: infer I) => void ? I : never, TWriteOpts>> & WriteResponseInputFields<ExtractResponseQuery<TMethod>, ExtractResponseBody<TMethod>, ExtractResponseParamNames<TMethod>>;
273
255
 
274
256
  declare function createInjectRead<TSchema, TDefaultError, TPlugins extends readonly SpooshPlugin<PluginTypeConfig>[]>(options: Omit<SpooshInstanceShape<unknown, TSchema, TDefaultError, TPlugins>, "_types">): <TReadFn extends (api: ReadApiClient<TSchema, TDefaultError>) => Promise<{
275
257
  data?: unknown;
@@ -331,7 +313,7 @@ declare function createInjectRead<TSchema, TDefaultError, TPlugins extends reado
331
313
  readResult: infer R_2;
332
314
  } ? R_2 : 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 {
333
315
  readResult: infer R_2;
334
- } ? R_2 : 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>, ExtractResponseFormData<TReadFn>, ExtractResponseParamNames<TReadFn>>;
316
+ } ? R_2 : 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>>;
335
317
 
336
318
  type SpooshAngularFunctions<TDefaultError, TSchema, TPlugins extends PluginArray> = {
337
319
  injectRead: ReturnType<typeof createInjectRead<TSchema, TDefaultError, TPlugins>>;
@@ -341,4 +323,4 @@ type SpooshAngularFunctions<TDefaultError, TSchema, TPlugins extends PluginArray
341
323
 
342
324
  declare function createAngularSpoosh<TSchema, TDefaultError, TPlugins extends PluginArray, TApi>(instance: SpooshInstanceShape<TApi, TSchema, TDefaultError, TPlugins>): SpooshAngularFunctions<TDefaultError, TSchema, TPlugins>;
343
325
 
344
- export { type AngularOptionsMap, type BaseInfiniteReadOptions, type BaseInfiniteReadResult, type BaseReadOptions, type BaseReadResult, type BaseWriteResult, type EnabledOption, type ExtractMethodBody, type ExtractMethodData, type ExtractMethodError, type ExtractMethodFormData, type ExtractMethodOptions, type ExtractMethodQuery, type ExtractMethodUrlEncoded, type ExtractResponseBody, type ExtractResponseFormData, type ExtractResponseParamNames, type ExtractResponseQuery, type PageContext, type ReadApiClient, type ResponseInputFields, type SpooshInstanceShape, type WriteApiClient, type WriteResponseInputFields, createAngularSpoosh };
326
+ export { type AngularOptionsMap, type BaseInfiniteReadOptions, type BaseInfiniteReadResult, type BaseReadOptions, type BaseReadResult, type BaseWriteResult, type EnabledOption, type ExtractMethodBody, type ExtractMethodData, type ExtractMethodError, type ExtractMethodOptions, type ExtractMethodQuery, type ExtractResponseBody, type ExtractResponseParamNames, type ExtractResponseQuery, type PageContext, type ReadApiClient, type ResponseInputFields, type SpooshInstanceShape, type WriteApiClient, type WriteResponseInputFields, createAngularSpoosh };
package/dist/index.js CHANGED
@@ -33,8 +33,7 @@ function createInjectRead(options) {
33
33
  const destroyRef = (0, import_core.inject)(import_core.DestroyRef);
34
34
  const {
35
35
  enabled: enabledOption = true,
36
- tags = void 0,
37
- additionalTags = void 0,
36
+ tags,
38
37
  ...pluginOpts
39
38
  } = readOptions ?? {};
40
39
  const getEnabled = () => typeof enabledOption === "function" ? enabledOption() : enabledOption;
@@ -65,13 +64,14 @@ function createInjectRead(options) {
65
64
  readFn(selectorProxy);
66
65
  return selectorResult;
67
66
  };
68
- const createController = (capturedCall, resolvedPath, resolvedTags, queryKey) => {
67
+ const createController = (capturedCall, resolvedTags, queryKey) => {
69
68
  if (currentSubscription) {
70
69
  currentSubscription();
71
70
  }
71
+ const pathSegments = capturedCall.path.split("/").filter(Boolean);
72
72
  const controller = (0, import_core2.createOperationController)({
73
73
  operationType: "read",
74
- path: capturedCall.path,
74
+ path: pathSegments,
75
75
  method: capturedCall.method,
76
76
  tags: resolvedTags,
77
77
  requestOptions: capturedCall.options,
@@ -80,11 +80,8 @@ function createInjectRead(options) {
80
80
  pluginExecutor,
81
81
  hookId,
82
82
  fetchFn: async (fetchOpts) => {
83
- let current = api;
84
- for (const segment of resolvedPath) {
85
- current = current[segment];
86
- }
87
- const method = current[capturedCall.method];
83
+ const pathMethods = api(capturedCall.path);
84
+ const method = pathMethods[capturedCall.method];
88
85
  return method(fetchOpts);
89
86
  }
90
87
  });
@@ -129,29 +126,25 @@ function createInjectRead(options) {
129
126
  const initialCapturedCall = initialSelectorResult.call;
130
127
  if (!initialCapturedCall) {
131
128
  throw new Error(
132
- "injectRead requires calling an HTTP method ($get). Example: injectRead((api) => api.posts.$get())"
129
+ 'injectRead requires calling an HTTP method (GET). Example: injectRead((api) => api("posts").GET())'
133
130
  );
134
131
  }
135
132
  const initialRequestOptions = initialCapturedCall.options;
133
+ const initialPathSegments = initialCapturedCall.path.split("/").filter(Boolean);
136
134
  const initialResolvedPath = (0, import_core2.resolvePath)(
137
- initialCapturedCall.path,
135
+ initialPathSegments,
138
136
  initialRequestOptions?.params
139
137
  );
140
138
  const initialResolvedTags = (0, import_core2.resolveTags)(
141
- { tags, additionalTags },
139
+ tags !== void 0 ? { tags } : void 0,
142
140
  initialResolvedPath
143
141
  );
144
142
  const initialQueryKey = stateManager.createQueryKey({
145
- path: initialCapturedCall.path,
143
+ path: initialPathSegments,
146
144
  method: initialCapturedCall.method,
147
145
  options: initialCapturedCall.options
148
146
  });
149
- createController(
150
- initialCapturedCall,
151
- initialResolvedPath,
152
- initialResolvedTags,
153
- initialQueryKey
154
- );
147
+ createController(initialCapturedCall, initialResolvedTags, initialQueryKey);
155
148
  loadingSignal.set(false);
156
149
  let wasEnabled = false;
157
150
  (0, import_core.effect)(
@@ -161,20 +154,18 @@ function createInjectRead(options) {
161
154
  const capturedCall = selectorResult.call;
162
155
  if (!capturedCall) {
163
156
  throw new Error(
164
- "injectRead requires calling an HTTP method ($get). Example: injectRead((api) => api.posts.$get())"
157
+ 'injectRead requires calling an HTTP method (GET). Example: injectRead((api) => api("posts").GET())'
165
158
  );
166
159
  }
167
160
  const requestOptions = capturedCall.options;
168
- const resolvedPath = (0, import_core2.resolvePath)(
169
- capturedCall.path,
170
- requestOptions?.params
171
- );
161
+ const pathSegments = capturedCall.path.split("/").filter(Boolean);
162
+ const resolvedPath = (0, import_core2.resolvePath)(pathSegments, requestOptions?.params);
172
163
  const resolvedTags = (0, import_core2.resolveTags)(
173
- { tags, additionalTags },
164
+ tags !== void 0 ? { tags } : void 0,
174
165
  resolvedPath
175
166
  );
176
167
  const queryKey = stateManager.createQueryKey({
177
- path: capturedCall.path,
168
+ path: pathSegments,
178
169
  method: capturedCall.method,
179
170
  options: capturedCall.options
180
171
  });
@@ -186,9 +177,6 @@ function createInjectRead(options) {
186
177
  if (opts?.body !== void 0) {
187
178
  inputInner.body = opts.body;
188
179
  }
189
- if (opts?.formData !== void 0) {
190
- inputInner.formData = opts.formData;
191
- }
192
180
  if (opts?.params !== void 0) {
193
181
  inputInner.params = opts.params;
194
182
  }
@@ -206,7 +194,6 @@ function createInjectRead(options) {
206
194
  }
207
195
  const controller = createController(
208
196
  capturedCall,
209
- resolvedPath,
210
197
  resolvedTags,
211
198
  queryKey
212
199
  );
@@ -327,7 +314,7 @@ function createInjectWrite(options) {
327
314
  writeFn(selectorProxy);
328
315
  if (!selectorResult.selector) {
329
316
  throw new Error(
330
- "injectWrite requires selecting an HTTP method ($post, $put, $patch, $delete). Example: injectWrite((api) => api.posts.$post)"
317
+ 'injectWrite requires selecting an HTTP method (POST, PUT, PATCH, DELETE). Example: injectWrite((api) => api("posts").POST)'
331
318
  );
332
319
  }
333
320
  return selectorResult.selector;
@@ -360,10 +347,11 @@ function createInjectWrite(options) {
360
347
  const trigger = async (triggerOptions) => {
361
348
  const selectedEndpoint = captureSelector();
362
349
  const params = triggerOptions?.params;
363
- const resolvedPath = (0, import_core4.resolvePath)(selectedEndpoint.path, params);
350
+ const pathSegments = selectedEndpoint.path.split("/").filter(Boolean);
351
+ const resolvedPath = (0, import_core4.resolvePath)(pathSegments, params);
364
352
  const tags = (0, import_core4.resolveTags)(triggerOptions, resolvedPath);
365
353
  const queryKey = stateManager.createQueryKey({
366
- path: selectedEndpoint.path,
354
+ path: pathSegments,
367
355
  method: selectedEndpoint.method,
368
356
  options: triggerOptions
369
357
  });
@@ -374,7 +362,7 @@ function createInjectWrite(options) {
374
362
  }
375
363
  const controller = (0, import_core4.createOperationController)({
376
364
  operationType: "write",
377
- path: selectedEndpoint.path,
365
+ path: pathSegments,
378
366
  method: selectedEndpoint.method,
379
367
  tags,
380
368
  stateManager,
@@ -382,16 +370,8 @@ function createInjectWrite(options) {
382
370
  pluginExecutor,
383
371
  hookId,
384
372
  fetchFn: async (fetchOpts) => {
385
- const fetchParams = fetchOpts?.params;
386
- const fetchResolvedPath = (0, import_core4.resolvePath)(
387
- selectedEndpoint.path,
388
- fetchParams
389
- );
390
- let current = api;
391
- for (const segment of fetchResolvedPath) {
392
- current = current[segment];
393
- }
394
- const method = current[selectedEndpoint.method];
373
+ const pathMethods = api(selectedEndpoint.path);
374
+ const method = pathMethods[selectedEndpoint.method];
395
375
  return method(fetchOpts);
396
376
  }
397
377
  });
@@ -437,9 +417,6 @@ function createInjectWrite(options) {
437
417
  if (opts?.body !== void 0) {
438
418
  inputInner.body = opts.body;
439
419
  }
440
- if (opts?.formData !== void 0) {
441
- inputInner.formData = opts.formData;
442
- }
443
420
  if (opts?.params !== void 0) {
444
421
  inputInner.params = opts.params;
445
422
  }
@@ -471,7 +448,6 @@ function createInjectInfiniteRead(options) {
471
448
  const {
472
449
  enabled: enabledOption = true,
473
450
  tags,
474
- additionalTags,
475
451
  canFetchNext,
476
452
  nextPageRequest,
477
453
  merger,
@@ -501,7 +477,7 @@ function createInjectInfiniteRead(options) {
501
477
  readFn(selectorProxy);
502
478
  if (!selectorResult.call) {
503
479
  throw new Error(
504
- "injectInfiniteRead requires calling an HTTP method ($get). Example: injectInfiniteRead((api) => api.posts.$get())"
480
+ 'injectInfiniteRead requires calling an HTTP method (GET). Example: injectInfiniteRead((api) => api("posts").GET())'
505
481
  );
506
482
  }
507
483
  return selectorResult.call;
@@ -558,6 +534,7 @@ function createInjectInfiniteRead(options) {
558
534
  unsubInvalidate();
559
535
  }
560
536
  const requestOptions = capturedCall.options;
537
+ const pathSegments = capturedCall.path.split("/").filter(Boolean);
561
538
  const baseOptionsForKey = {
562
539
  ...capturedCall.options,
563
540
  query: void 0,
@@ -570,7 +547,7 @@ function createInjectInfiniteRead(options) {
570
547
  body: requestOptions?.body
571
548
  };
572
549
  const controller = (0, import_core6.createInfiniteReadController)({
573
- path: capturedCall.path,
550
+ path: pathSegments,
574
551
  method: capturedCall.method,
575
552
  tags: resolvedTags,
576
553
  initialRequest,
@@ -585,12 +562,8 @@ function createInjectInfiniteRead(options) {
585
562
  pluginExecutor,
586
563
  hookId,
587
564
  fetchFn: async (opts, abortSignal) => {
588
- const fetchPath = (0, import_core6.resolvePath)(capturedCall.path, opts.params);
589
- let current = api;
590
- for (const segment of fetchPath) {
591
- current = current[segment];
592
- }
593
- const method = current[capturedCall.method];
565
+ const pathMethods = api(capturedCall.path);
566
+ const method = pathMethods[capturedCall.method];
594
567
  const fetchOptions = {
595
568
  ...capturedCall.options,
596
569
  query: opts.query,
@@ -636,12 +609,13 @@ function createInjectInfiniteRead(options) {
636
609
  };
637
610
  const initialCapturedCall = captureSelector();
638
611
  const initialRequestOptions = initialCapturedCall.options;
612
+ const initialPathSegments = initialCapturedCall.path.split("/").filter(Boolean);
639
613
  const initialResolvedPath = (0, import_core6.resolvePath)(
640
- initialCapturedCall.path,
614
+ initialPathSegments,
641
615
  initialRequestOptions?.params
642
616
  );
643
617
  const initialResolvedTags = (0, import_core6.resolveTags)(
644
- { tags, additionalTags },
618
+ tags !== void 0 ? { tags } : void 0,
645
619
  initialResolvedPath
646
620
  );
647
621
  const initialBaseOptionsForKey = {
@@ -651,7 +625,7 @@ function createInjectInfiniteRead(options) {
651
625
  body: void 0
652
626
  };
653
627
  const initialQueryKey = stateManager.createQueryKey({
654
- path: initialCapturedCall.path,
628
+ path: initialPathSegments,
655
629
  method: initialCapturedCall.method,
656
630
  options: initialBaseOptionsForKey
657
631
  });
@@ -661,12 +635,10 @@ function createInjectInfiniteRead(options) {
661
635
  const isEnabled = getEnabled();
662
636
  const capturedCall = captureSelector();
663
637
  const requestOptions = capturedCall.options;
664
- const resolvedPath = (0, import_core6.resolvePath)(
665
- capturedCall.path,
666
- requestOptions?.params
667
- );
638
+ const pathSegments = capturedCall.path.split("/").filter(Boolean);
639
+ const resolvedPath = (0, import_core6.resolvePath)(pathSegments, requestOptions?.params);
668
640
  const resolvedTags = (0, import_core6.resolveTags)(
669
- { tags, additionalTags },
641
+ tags !== void 0 ? { tags } : void 0,
670
642
  resolvedPath
671
643
  );
672
644
  const baseOptionsForKey = {
@@ -676,7 +648,7 @@ function createInjectInfiniteRead(options) {
676
648
  body: void 0
677
649
  };
678
650
  const queryKey = stateManager.createQueryKey({
679
- path: capturedCall.path,
651
+ path: pathSegments,
680
652
  method: capturedCall.method,
681
653
  options: baseOptionsForKey
682
654
  });
package/dist/index.mjs CHANGED
@@ -18,8 +18,7 @@ function createInjectRead(options) {
18
18
  const destroyRef = inject(DestroyRef);
19
19
  const {
20
20
  enabled: enabledOption = true,
21
- tags = void 0,
22
- additionalTags = void 0,
21
+ tags,
23
22
  ...pluginOpts
24
23
  } = readOptions ?? {};
25
24
  const getEnabled = () => typeof enabledOption === "function" ? enabledOption() : enabledOption;
@@ -50,13 +49,14 @@ function createInjectRead(options) {
50
49
  readFn(selectorProxy);
51
50
  return selectorResult;
52
51
  };
53
- const createController = (capturedCall, resolvedPath, resolvedTags, queryKey) => {
52
+ const createController = (capturedCall, resolvedTags, queryKey) => {
54
53
  if (currentSubscription) {
55
54
  currentSubscription();
56
55
  }
56
+ const pathSegments = capturedCall.path.split("/").filter(Boolean);
57
57
  const controller = createOperationController({
58
58
  operationType: "read",
59
- path: capturedCall.path,
59
+ path: pathSegments,
60
60
  method: capturedCall.method,
61
61
  tags: resolvedTags,
62
62
  requestOptions: capturedCall.options,
@@ -65,11 +65,8 @@ function createInjectRead(options) {
65
65
  pluginExecutor,
66
66
  hookId,
67
67
  fetchFn: async (fetchOpts) => {
68
- let current = api;
69
- for (const segment of resolvedPath) {
70
- current = current[segment];
71
- }
72
- const method = current[capturedCall.method];
68
+ const pathMethods = api(capturedCall.path);
69
+ const method = pathMethods[capturedCall.method];
73
70
  return method(fetchOpts);
74
71
  }
75
72
  });
@@ -114,29 +111,25 @@ function createInjectRead(options) {
114
111
  const initialCapturedCall = initialSelectorResult.call;
115
112
  if (!initialCapturedCall) {
116
113
  throw new Error(
117
- "injectRead requires calling an HTTP method ($get). Example: injectRead((api) => api.posts.$get())"
114
+ 'injectRead requires calling an HTTP method (GET). Example: injectRead((api) => api("posts").GET())'
118
115
  );
119
116
  }
120
117
  const initialRequestOptions = initialCapturedCall.options;
118
+ const initialPathSegments = initialCapturedCall.path.split("/").filter(Boolean);
121
119
  const initialResolvedPath = resolvePath(
122
- initialCapturedCall.path,
120
+ initialPathSegments,
123
121
  initialRequestOptions?.params
124
122
  );
125
123
  const initialResolvedTags = resolveTags(
126
- { tags, additionalTags },
124
+ tags !== void 0 ? { tags } : void 0,
127
125
  initialResolvedPath
128
126
  );
129
127
  const initialQueryKey = stateManager.createQueryKey({
130
- path: initialCapturedCall.path,
128
+ path: initialPathSegments,
131
129
  method: initialCapturedCall.method,
132
130
  options: initialCapturedCall.options
133
131
  });
134
- createController(
135
- initialCapturedCall,
136
- initialResolvedPath,
137
- initialResolvedTags,
138
- initialQueryKey
139
- );
132
+ createController(initialCapturedCall, initialResolvedTags, initialQueryKey);
140
133
  loadingSignal.set(false);
141
134
  let wasEnabled = false;
142
135
  effect(
@@ -146,20 +139,18 @@ function createInjectRead(options) {
146
139
  const capturedCall = selectorResult.call;
147
140
  if (!capturedCall) {
148
141
  throw new Error(
149
- "injectRead requires calling an HTTP method ($get). Example: injectRead((api) => api.posts.$get())"
142
+ 'injectRead requires calling an HTTP method (GET). Example: injectRead((api) => api("posts").GET())'
150
143
  );
151
144
  }
152
145
  const requestOptions = capturedCall.options;
153
- const resolvedPath = resolvePath(
154
- capturedCall.path,
155
- requestOptions?.params
156
- );
146
+ const pathSegments = capturedCall.path.split("/").filter(Boolean);
147
+ const resolvedPath = resolvePath(pathSegments, requestOptions?.params);
157
148
  const resolvedTags = resolveTags(
158
- { tags, additionalTags },
149
+ tags !== void 0 ? { tags } : void 0,
159
150
  resolvedPath
160
151
  );
161
152
  const queryKey = stateManager.createQueryKey({
162
- path: capturedCall.path,
153
+ path: pathSegments,
163
154
  method: capturedCall.method,
164
155
  options: capturedCall.options
165
156
  });
@@ -171,9 +162,6 @@ function createInjectRead(options) {
171
162
  if (opts?.body !== void 0) {
172
163
  inputInner.body = opts.body;
173
164
  }
174
- if (opts?.formData !== void 0) {
175
- inputInner.formData = opts.formData;
176
- }
177
165
  if (opts?.params !== void 0) {
178
166
  inputInner.params = opts.params;
179
167
  }
@@ -191,7 +179,6 @@ function createInjectRead(options) {
191
179
  }
192
180
  const controller = createController(
193
181
  capturedCall,
194
- resolvedPath,
195
182
  resolvedTags,
196
183
  queryKey
197
184
  );
@@ -317,7 +304,7 @@ function createInjectWrite(options) {
317
304
  writeFn(selectorProxy);
318
305
  if (!selectorResult.selector) {
319
306
  throw new Error(
320
- "injectWrite requires selecting an HTTP method ($post, $put, $patch, $delete). Example: injectWrite((api) => api.posts.$post)"
307
+ 'injectWrite requires selecting an HTTP method (POST, PUT, PATCH, DELETE). Example: injectWrite((api) => api("posts").POST)'
321
308
  );
322
309
  }
323
310
  return selectorResult.selector;
@@ -350,10 +337,11 @@ function createInjectWrite(options) {
350
337
  const trigger = async (triggerOptions) => {
351
338
  const selectedEndpoint = captureSelector();
352
339
  const params = triggerOptions?.params;
353
- const resolvedPath = resolvePath2(selectedEndpoint.path, params);
340
+ const pathSegments = selectedEndpoint.path.split("/").filter(Boolean);
341
+ const resolvedPath = resolvePath2(pathSegments, params);
354
342
  const tags = resolveTags2(triggerOptions, resolvedPath);
355
343
  const queryKey = stateManager.createQueryKey({
356
- path: selectedEndpoint.path,
344
+ path: pathSegments,
357
345
  method: selectedEndpoint.method,
358
346
  options: triggerOptions
359
347
  });
@@ -364,7 +352,7 @@ function createInjectWrite(options) {
364
352
  }
365
353
  const controller = createOperationController2({
366
354
  operationType: "write",
367
- path: selectedEndpoint.path,
355
+ path: pathSegments,
368
356
  method: selectedEndpoint.method,
369
357
  tags,
370
358
  stateManager,
@@ -372,16 +360,8 @@ function createInjectWrite(options) {
372
360
  pluginExecutor,
373
361
  hookId,
374
362
  fetchFn: async (fetchOpts) => {
375
- const fetchParams = fetchOpts?.params;
376
- const fetchResolvedPath = resolvePath2(
377
- selectedEndpoint.path,
378
- fetchParams
379
- );
380
- let current = api;
381
- for (const segment of fetchResolvedPath) {
382
- current = current[segment];
383
- }
384
- const method = current[selectedEndpoint.method];
363
+ const pathMethods = api(selectedEndpoint.path);
364
+ const method = pathMethods[selectedEndpoint.method];
385
365
  return method(fetchOpts);
386
366
  }
387
367
  });
@@ -427,9 +407,6 @@ function createInjectWrite(options) {
427
407
  if (opts?.body !== void 0) {
428
408
  inputInner.body = opts.body;
429
409
  }
430
- if (opts?.formData !== void 0) {
431
- inputInner.formData = opts.formData;
432
- }
433
410
  if (opts?.params !== void 0) {
434
411
  inputInner.params = opts.params;
435
412
  }
@@ -473,7 +450,6 @@ function createInjectInfiniteRead(options) {
473
450
  const {
474
451
  enabled: enabledOption = true,
475
452
  tags,
476
- additionalTags,
477
453
  canFetchNext,
478
454
  nextPageRequest,
479
455
  merger,
@@ -503,7 +479,7 @@ function createInjectInfiniteRead(options) {
503
479
  readFn(selectorProxy);
504
480
  if (!selectorResult.call) {
505
481
  throw new Error(
506
- "injectInfiniteRead requires calling an HTTP method ($get). Example: injectInfiniteRead((api) => api.posts.$get())"
482
+ 'injectInfiniteRead requires calling an HTTP method (GET). Example: injectInfiniteRead((api) => api("posts").GET())'
507
483
  );
508
484
  }
509
485
  return selectorResult.call;
@@ -560,6 +536,7 @@ function createInjectInfiniteRead(options) {
560
536
  unsubInvalidate();
561
537
  }
562
538
  const requestOptions = capturedCall.options;
539
+ const pathSegments = capturedCall.path.split("/").filter(Boolean);
563
540
  const baseOptionsForKey = {
564
541
  ...capturedCall.options,
565
542
  query: void 0,
@@ -572,7 +549,7 @@ function createInjectInfiniteRead(options) {
572
549
  body: requestOptions?.body
573
550
  };
574
551
  const controller = createInfiniteReadController({
575
- path: capturedCall.path,
552
+ path: pathSegments,
576
553
  method: capturedCall.method,
577
554
  tags: resolvedTags,
578
555
  initialRequest,
@@ -587,12 +564,8 @@ function createInjectInfiniteRead(options) {
587
564
  pluginExecutor,
588
565
  hookId,
589
566
  fetchFn: async (opts, abortSignal) => {
590
- const fetchPath = resolvePath3(capturedCall.path, opts.params);
591
- let current = api;
592
- for (const segment of fetchPath) {
593
- current = current[segment];
594
- }
595
- const method = current[capturedCall.method];
567
+ const pathMethods = api(capturedCall.path);
568
+ const method = pathMethods[capturedCall.method];
596
569
  const fetchOptions = {
597
570
  ...capturedCall.options,
598
571
  query: opts.query,
@@ -638,12 +611,13 @@ function createInjectInfiniteRead(options) {
638
611
  };
639
612
  const initialCapturedCall = captureSelector();
640
613
  const initialRequestOptions = initialCapturedCall.options;
614
+ const initialPathSegments = initialCapturedCall.path.split("/").filter(Boolean);
641
615
  const initialResolvedPath = resolvePath3(
642
- initialCapturedCall.path,
616
+ initialPathSegments,
643
617
  initialRequestOptions?.params
644
618
  );
645
619
  const initialResolvedTags = resolveTags3(
646
- { tags, additionalTags },
620
+ tags !== void 0 ? { tags } : void 0,
647
621
  initialResolvedPath
648
622
  );
649
623
  const initialBaseOptionsForKey = {
@@ -653,7 +627,7 @@ function createInjectInfiniteRead(options) {
653
627
  body: void 0
654
628
  };
655
629
  const initialQueryKey = stateManager.createQueryKey({
656
- path: initialCapturedCall.path,
630
+ path: initialPathSegments,
657
631
  method: initialCapturedCall.method,
658
632
  options: initialBaseOptionsForKey
659
633
  });
@@ -663,12 +637,10 @@ function createInjectInfiniteRead(options) {
663
637
  const isEnabled = getEnabled();
664
638
  const capturedCall = captureSelector();
665
639
  const requestOptions = capturedCall.options;
666
- const resolvedPath = resolvePath3(
667
- capturedCall.path,
668
- requestOptions?.params
669
- );
640
+ const pathSegments = capturedCall.path.split("/").filter(Boolean);
641
+ const resolvedPath = resolvePath3(pathSegments, requestOptions?.params);
670
642
  const resolvedTags = resolveTags3(
671
- { tags, additionalTags },
643
+ tags !== void 0 ? { tags } : void 0,
672
644
  resolvedPath
673
645
  );
674
646
  const baseOptionsForKey = {
@@ -678,7 +650,7 @@ function createInjectInfiniteRead(options) {
678
650
  body: void 0
679
651
  };
680
652
  const queryKey = stateManager.createQueryKey({
681
- path: capturedCall.path,
653
+ path: pathSegments,
682
654
  method: capturedCall.method,
683
655
  options: baseOptionsForKey
684
656
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spoosh/angular",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "license": "MIT",
5
5
  "description": "Angular signals integration for Spoosh API client",
6
6
  "keywords": [
@@ -34,11 +34,11 @@
34
34
  }
35
35
  },
36
36
  "peerDependencies": {
37
- "@spoosh/core": ">=0.4.0",
37
+ "@spoosh/core": ">=0.7.0",
38
38
  "@angular/core": ">=16.0.0"
39
39
  },
40
40
  "devDependencies": {
41
- "@spoosh/core": "0.5.0"
41
+ "@spoosh/core": "0.7.0"
42
42
  },
43
43
  "scripts": {
44
44
  "dev": "tsup --watch",