@spoosh/angular 0.5.0 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -24
- package/dist/index.d.mts +134 -120
- package/dist/index.d.ts +134 -120
- package/dist/index.js +75 -146
- package/dist/index.mjs +75 -150
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @spoosh/angular
|
|
2
2
|
|
|
3
|
-
Angular signals integration for Spoosh - `injectRead`, `
|
|
3
|
+
Angular signals integration for Spoosh - `injectRead`, `injectWrite`, and `injectInfiniteRead`.
|
|
4
4
|
|
|
5
5
|
**[Documentation](https://spoosh.dev/docs/integrations/angular)** · **Requirements:** TypeScript >= 5.0, Angular >= 16.0
|
|
6
6
|
|
|
@@ -23,7 +23,7 @@ const spoosh = new Spoosh<ApiSchema, Error>("/api").use([
|
|
|
23
23
|
cachePlugin({ staleTime: 5000 }),
|
|
24
24
|
]);
|
|
25
25
|
|
|
26
|
-
export const { injectRead,
|
|
26
|
+
export const { injectRead, injectWrite, injectInfiniteRead } =
|
|
27
27
|
createAngularSpoosh(spoosh);
|
|
28
28
|
```
|
|
29
29
|
|
|
@@ -74,28 +74,6 @@ export class UserListComponent {
|
|
|
74
74
|
}
|
|
75
75
|
```
|
|
76
76
|
|
|
77
|
-
### injectLazyRead
|
|
78
|
-
|
|
79
|
-
Lazy data fetching for print/download/export scenarios. Does not auto-fetch on mount.
|
|
80
|
-
|
|
81
|
-
```typescript
|
|
82
|
-
@Component({
|
|
83
|
-
template: `
|
|
84
|
-
<button (click)="handlePrint('123')" [disabled]="order.loading()">
|
|
85
|
-
{{ order.loading() ? "Loading..." : "Print" }}
|
|
86
|
-
</button>
|
|
87
|
-
`,
|
|
88
|
-
})
|
|
89
|
-
export class PrintOrderComponent {
|
|
90
|
-
order = injectLazyRead((api) => api("orders/:id").GET);
|
|
91
|
-
|
|
92
|
-
async handlePrint(orderId: string) {
|
|
93
|
-
const { data } = await this.order.trigger({ params: { id: orderId } });
|
|
94
|
-
if (data) this.printService.printReceipt(data);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
```
|
|
98
|
-
|
|
99
77
|
### injectWrite
|
|
100
78
|
|
|
101
79
|
Trigger mutations with loading and error states.
|
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,
|
|
2
|
+
import { PluginArray, StateManager, EventEmitter, PluginExecutor, MethodOptionsMap, CoreRequestOptionsBase, ReadClient, TagOptions, SpooshPlugin, PluginTypeConfig, SpooshResponse, InfiniteRequestOptions, ResolveTypes, ResolverContext, WriteClient, 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,33 +14,10 @@ interface SpooshInstanceShape<TApi, TSchema, TDefaultError, TPlugins extends Plu
|
|
|
14
14
|
};
|
|
15
15
|
}
|
|
16
16
|
type EnabledOption = boolean | (() => boolean);
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
data: Signal<TData | undefined>;
|
|
22
|
-
error: Signal<TError | undefined>;
|
|
23
|
-
loading: Signal<boolean>;
|
|
24
|
-
fetching: Signal<boolean>;
|
|
25
|
-
meta: Signal<TPluginResult>;
|
|
26
|
-
abort: () => void;
|
|
27
|
-
trigger: () => Promise<SpooshResponse<TData, TError>>;
|
|
28
|
-
}
|
|
29
|
-
interface BaseWriteResult<TData, TError, TOptions, TPluginResult = Record<string, unknown>> {
|
|
30
|
-
trigger: (options?: TOptions) => Promise<SpooshResponse<TData, TError>>;
|
|
31
|
-
data: Signal<TData | undefined>;
|
|
32
|
-
error: Signal<TError | undefined>;
|
|
33
|
-
loading: Signal<boolean>;
|
|
34
|
-
meta: Signal<TPluginResult>;
|
|
35
|
-
abort: () => void;
|
|
36
|
-
}
|
|
37
|
-
interface BaseLazyReadResult<TData, TError, TOptions> {
|
|
38
|
-
trigger: (options?: TOptions) => Promise<SpooshResponse<TData, TError>>;
|
|
39
|
-
data: Signal<TData | undefined>;
|
|
40
|
-
error: Signal<TError | undefined>;
|
|
41
|
-
loading: Signal<boolean>;
|
|
42
|
-
abort: () => void;
|
|
43
|
-
}
|
|
17
|
+
type QueryRequestOptions = CoreRequestOptionsBase;
|
|
18
|
+
type MutationRequestOptions = CoreRequestOptionsBase;
|
|
19
|
+
type AngularOptionsMap = MethodOptionsMap<QueryRequestOptions, MutationRequestOptions>;
|
|
20
|
+
|
|
44
21
|
type PageContext<TData, TRequest> = {
|
|
45
22
|
response: TData | undefined;
|
|
46
23
|
allResponses: TData[];
|
|
@@ -70,32 +47,54 @@ interface BaseInfiniteReadResult<TData, TError, TItem, TPluginResult = Record<st
|
|
|
70
47
|
trigger: () => Promise<void>;
|
|
71
48
|
abort: () => void;
|
|
72
49
|
}
|
|
73
|
-
type
|
|
74
|
-
|
|
75
|
-
type
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
} : {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
}
|
|
50
|
+
type InfiniteReadApiClient<TSchema, TDefaultError> = ReadClient<TSchema, TDefaultError>;
|
|
51
|
+
|
|
52
|
+
type AnyInfiniteRequestOptions = InfiniteRequestOptions;
|
|
53
|
+
declare function createInjectInfiniteRead<TSchema, TDefaultError, TPlugins extends readonly SpooshPlugin<PluginTypeConfig>[]>(options: Omit<SpooshInstanceShape<unknown, TSchema, TDefaultError, TPlugins>, "_types">): <TReadFn extends (api: InfiniteReadApiClient<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>, {
|
|
54
|
+
data: unknown;
|
|
55
|
+
error?: undefined;
|
|
56
|
+
}> extends {
|
|
57
|
+
data: infer D;
|
|
58
|
+
} ? D : unknown : unknown, TItem, TRequest> & ResolveTypes<((TPlugins[number] extends infer T_3 ? T_3 extends TPlugins[number] ? T_3 extends SpooshPlugin<infer Types_1 extends PluginTypeConfig> ? Types_1 extends {
|
|
59
|
+
readOptions: infer R_3;
|
|
60
|
+
} ? R_3 : 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 {
|
|
61
|
+
readOptions: infer R_3;
|
|
62
|
+
} ? R_3 : object : object : never : never) ? T_4 extends unknown ? (x: T_4) => void : never : never : never) extends (x: infer I) => void ? I : never, ResolverContext<TSchema, TReadFn extends (...args: never[]) => infer R ? Extract<Awaited<R>, {
|
|
63
|
+
data: unknown;
|
|
64
|
+
error?: undefined;
|
|
65
|
+
}> extends {
|
|
66
|
+
data: infer D;
|
|
67
|
+
} ? D : unknown : unknown, [TReadFn extends (...args: never[]) => infer R_1 ? Extract<Awaited<R_1>, {
|
|
68
|
+
error: unknown;
|
|
69
|
+
data?: undefined;
|
|
70
|
+
}> extends {
|
|
71
|
+
error: infer E;
|
|
72
|
+
} ? E : unknown : unknown] extends [unknown] ? TDefaultError : TReadFn extends (...args: never[]) => infer R_1 ? Extract<Awaited<R_1>, {
|
|
73
|
+
error: unknown;
|
|
74
|
+
data?: undefined;
|
|
75
|
+
}> extends {
|
|
76
|
+
error: infer E;
|
|
77
|
+
} ? E : unknown : unknown>>) => BaseInfiniteReadResult<TReadFn extends (...args: never[]) => infer R ? Extract<Awaited<R>, {
|
|
78
|
+
data: unknown;
|
|
79
|
+
error?: undefined;
|
|
80
|
+
}> extends {
|
|
81
|
+
data: infer D;
|
|
82
|
+
} ? D : unknown : unknown, [TReadFn extends (...args: never[]) => infer R_1 ? Extract<Awaited<R_1>, {
|
|
83
|
+
error: unknown;
|
|
84
|
+
data?: undefined;
|
|
85
|
+
}> extends {
|
|
86
|
+
error: infer E;
|
|
87
|
+
} ? E : unknown : unknown] extends [unknown] ? TDefaultError : TReadFn extends (...args: never[]) => infer R_1 ? Extract<Awaited<R_1>, {
|
|
88
|
+
error: unknown;
|
|
89
|
+
data?: undefined;
|
|
90
|
+
}> extends {
|
|
91
|
+
error: infer E;
|
|
92
|
+
} ? E : unknown : unknown, TItem, ((TPlugins[number] extends infer T ? T extends TPlugins[number] ? T extends SpooshPlugin<infer Types extends PluginTypeConfig> ? Types extends {
|
|
93
|
+
readResult: infer R_2;
|
|
94
|
+
} ? 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 {
|
|
95
|
+
readResult: infer R_2;
|
|
96
|
+
} ? R_2 : object : object : never : never) ? T_1 extends unknown ? (x: T_1) => void : never : never : never) extends (x: infer I) => void ? I : never>;
|
|
97
|
+
|
|
99
98
|
type OptionalQueryField<TQuery> = [TQuery] extends [never] ? object : undefined extends TQuery ? {
|
|
100
99
|
query?: Exclude<TQuery, undefined>;
|
|
101
100
|
} : {
|
|
@@ -115,6 +114,16 @@ type InputFields<TQuery, TBody, TParamNames extends string> = OptionalQueryField
|
|
|
115
114
|
type WriteResponseInputFields<TQuery, TBody, TParamNames extends string> = [TQuery, TBody, TParamNames] extends [never, never, never] ? object : {
|
|
116
115
|
input: Signal<InputFields<TQuery, TBody, TParamNames> | undefined>;
|
|
117
116
|
};
|
|
117
|
+
interface BaseWriteResult<TData, TError, TOptions, TPluginResult = Record<string, unknown>> {
|
|
118
|
+
trigger: (options?: TOptions) => Promise<SpooshResponse<TData, TError>>;
|
|
119
|
+
data: Signal<TData | undefined>;
|
|
120
|
+
error: Signal<TError | undefined>;
|
|
121
|
+
loading: Signal<boolean>;
|
|
122
|
+
meta: Signal<TPluginResult>;
|
|
123
|
+
abort: () => void;
|
|
124
|
+
}
|
|
125
|
+
type WriteApiClient<TSchema, TDefaultError> = WriteClient<TSchema, TDefaultError>;
|
|
126
|
+
|
|
118
127
|
type SuccessResponse<T> = Extract<T, {
|
|
119
128
|
data: unknown;
|
|
120
129
|
error?: undefined;
|
|
@@ -154,69 +163,6 @@ type ExtractMethodBody<T> = ExtractMethodOptions<T> extends {
|
|
|
154
163
|
body: infer B;
|
|
155
164
|
} ? B : never;
|
|
156
165
|
|
|
157
|
-
declare function createInjectLazyRead<TSchema, TDefaultError, TPlugins extends readonly SpooshPlugin<PluginTypeConfig>[]>(options: Omit<SpooshInstanceShape<unknown, TSchema, TDefaultError, TPlugins>, "_types">): <TMethod extends (...args: never[]) => Promise<SpooshResponse<unknown, unknown>>>(readFn: (api: ReadApiClient<TSchema, TDefaultError>) => TMethod) => BaseLazyReadResult<TMethod extends (...args: never[]) => infer R ? Extract<Awaited<R>, {
|
|
158
|
-
data: unknown;
|
|
159
|
-
error?: undefined;
|
|
160
|
-
}> extends {
|
|
161
|
-
data: infer D;
|
|
162
|
-
} ? D : unknown : unknown, [TMethod extends (...args: never[]) => infer R_1 ? Extract<Awaited<R_1>, {
|
|
163
|
-
error: unknown;
|
|
164
|
-
data?: undefined;
|
|
165
|
-
}> extends {
|
|
166
|
-
error: infer E;
|
|
167
|
-
} ? E : unknown : unknown] extends [unknown] ? TDefaultError : TMethod extends (...args: never[]) => infer R_1 ? Extract<Awaited<R_1>, {
|
|
168
|
-
error: unknown;
|
|
169
|
-
data?: undefined;
|
|
170
|
-
}> extends {
|
|
171
|
-
error: infer E;
|
|
172
|
-
} ? E : unknown : unknown, TMethod extends (...args: infer A) => unknown ? A[0] extends object ? Pick<A[0], Extract<keyof A[0], "query" | "body" | "params">> : object : object> & WriteResponseInputFields<ExtractResponseQuery<TMethod>, ExtractResponseBody<TMethod>, ExtractResponseParamNames<TMethod>>;
|
|
173
|
-
|
|
174
|
-
type AnyInfiniteRequestOptions = InfiniteRequestOptions;
|
|
175
|
-
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>, {
|
|
176
|
-
data: unknown;
|
|
177
|
-
error?: undefined;
|
|
178
|
-
}> extends {
|
|
179
|
-
data: infer D;
|
|
180
|
-
} ? D : unknown : unknown, TItem, TRequest> & ResolveTypes<((TPlugins[number] extends infer T_3 ? T_3 extends TPlugins[number] ? T_3 extends SpooshPlugin<infer Types_1 extends PluginTypeConfig> ? Types_1 extends {
|
|
181
|
-
readOptions: infer R_3;
|
|
182
|
-
} ? R_3 : 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 {
|
|
183
|
-
readOptions: infer R_3;
|
|
184
|
-
} ? R_3 : object : object : never : never) ? T_4 extends unknown ? (x: T_4) => void : never : never : never) extends (x: infer I) => void ? I : never, ResolverContext<TSchema, TReadFn extends (...args: never[]) => infer R ? Extract<Awaited<R>, {
|
|
185
|
-
data: unknown;
|
|
186
|
-
error?: undefined;
|
|
187
|
-
}> extends {
|
|
188
|
-
data: infer D;
|
|
189
|
-
} ? D : unknown : unknown, [TReadFn extends (...args: never[]) => infer R_1 ? Extract<Awaited<R_1>, {
|
|
190
|
-
error: unknown;
|
|
191
|
-
data?: undefined;
|
|
192
|
-
}> extends {
|
|
193
|
-
error: infer E;
|
|
194
|
-
} ? E : unknown : unknown] extends [unknown] ? TDefaultError : TReadFn extends (...args: never[]) => infer R_1 ? Extract<Awaited<R_1>, {
|
|
195
|
-
error: unknown;
|
|
196
|
-
data?: undefined;
|
|
197
|
-
}> extends {
|
|
198
|
-
error: infer E;
|
|
199
|
-
} ? E : unknown : unknown>>) => BaseInfiniteReadResult<TReadFn extends (...args: never[]) => infer R ? Extract<Awaited<R>, {
|
|
200
|
-
data: unknown;
|
|
201
|
-
error?: undefined;
|
|
202
|
-
}> extends {
|
|
203
|
-
data: infer D;
|
|
204
|
-
} ? D : unknown : unknown, [TReadFn extends (...args: never[]) => infer R_1 ? Extract<Awaited<R_1>, {
|
|
205
|
-
error: unknown;
|
|
206
|
-
data?: undefined;
|
|
207
|
-
}> extends {
|
|
208
|
-
error: infer E;
|
|
209
|
-
} ? E : unknown : unknown] extends [unknown] ? TDefaultError : TReadFn extends (...args: never[]) => infer R_1 ? Extract<Awaited<R_1>, {
|
|
210
|
-
error: unknown;
|
|
211
|
-
data?: undefined;
|
|
212
|
-
}> extends {
|
|
213
|
-
error: infer E;
|
|
214
|
-
} ? E : unknown : unknown, TItem, ((TPlugins[number] extends infer T ? T extends TPlugins[number] ? T extends SpooshPlugin<infer Types extends PluginTypeConfig> ? Types extends {
|
|
215
|
-
readResult: infer R_2;
|
|
216
|
-
} ? 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 {
|
|
217
|
-
readResult: infer R_2;
|
|
218
|
-
} ? R_2 : object : object : never : never) ? T_1 extends unknown ? (x: T_1) => void : never : never : never) extends (x: infer I) => void ? I : never>;
|
|
219
|
-
|
|
220
166
|
declare function createInjectWrite<TSchema, TDefaultError, TPlugins extends readonly SpooshPlugin<PluginTypeConfig>[]>(options: Omit<SpooshInstanceShape<unknown, TSchema, TDefaultError, TPlugins>, "_types">): <TMethod extends (...args: never[]) => Promise<SpooshResponse<unknown, unknown>>, TWriteOpts extends (TMethod extends (...args: infer A) => unknown ? A[0] : never) & _spoosh_core.ResolveTypes<((TPlugins[number] extends infer T_3 ? T_3 extends TPlugins[number] ? T_3 extends SpooshPlugin<infer Types_1 extends PluginTypeConfig> ? Types_1 extends {
|
|
221
167
|
writeOptions: infer W_1;
|
|
222
168
|
} ? 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 {
|
|
@@ -276,6 +222,75 @@ declare function createInjectWrite<TSchema, TDefaultError, TPlugins extends read
|
|
|
276
222
|
writeResult: infer W;
|
|
277
223
|
} ? 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>>;
|
|
278
224
|
|
|
225
|
+
interface BaseReadOptions extends TagOptions {
|
|
226
|
+
enabled?: EnabledOption;
|
|
227
|
+
}
|
|
228
|
+
type QueryField<TQuery> = [TQuery] extends [never] ? object : undefined extends TQuery ? {
|
|
229
|
+
query?: Exclude<TQuery, undefined>;
|
|
230
|
+
} : {
|
|
231
|
+
query: TQuery;
|
|
232
|
+
};
|
|
233
|
+
type BodyField<TBody> = [TBody] extends [never] ? object : undefined extends TBody ? {
|
|
234
|
+
body?: Exclude<TBody, undefined>;
|
|
235
|
+
} : {
|
|
236
|
+
body: TBody;
|
|
237
|
+
};
|
|
238
|
+
type ParamsField<TParamNames extends string> = [TParamNames] extends [never] ? object : {
|
|
239
|
+
params: Record<TParamNames, string | number>;
|
|
240
|
+
};
|
|
241
|
+
type ReadInputFields<TQuery, TBody, TParamNames extends string> = QueryField<TQuery> & BodyField<TBody> & ParamsField<TParamNames>;
|
|
242
|
+
type ResponseInputFields<TQuery, TBody, TParamNames extends string> = [
|
|
243
|
+
TQuery,
|
|
244
|
+
TBody,
|
|
245
|
+
TParamNames
|
|
246
|
+
] extends [never, never, never] ? object : {
|
|
247
|
+
input: ReadInputFields<TQuery, TBody, TParamNames>;
|
|
248
|
+
};
|
|
249
|
+
type AwaitedReturnTypeTrigger<T> = T extends (...args: never[]) => infer R ? Awaited<R> : never;
|
|
250
|
+
type ExtractInputFromResponse<T> = T extends {
|
|
251
|
+
input: infer I;
|
|
252
|
+
} ? I : never;
|
|
253
|
+
type ExtractTriggerQuery<I> = I extends {
|
|
254
|
+
query: infer Q;
|
|
255
|
+
} ? {
|
|
256
|
+
query?: Q;
|
|
257
|
+
} : unknown;
|
|
258
|
+
type ExtractTriggerBody<I> = I extends {
|
|
259
|
+
body: infer B;
|
|
260
|
+
} ? {
|
|
261
|
+
body?: B;
|
|
262
|
+
} : unknown;
|
|
263
|
+
type ExtractTriggerParams<I> = I extends {
|
|
264
|
+
params: infer P;
|
|
265
|
+
} ? {
|
|
266
|
+
params?: P;
|
|
267
|
+
} : unknown;
|
|
268
|
+
type TriggerOptions<T> = ExtractInputFromResponse<AwaitedReturnTypeTrigger<T>> extends infer I ? [I] extends [never] ? {
|
|
269
|
+
force?: boolean;
|
|
270
|
+
} : ExtractTriggerQuery<I> & ExtractTriggerBody<I> & ExtractTriggerParams<I> & {
|
|
271
|
+
/** Force refetch even if data is cached */
|
|
272
|
+
force?: boolean;
|
|
273
|
+
} : {
|
|
274
|
+
force?: boolean;
|
|
275
|
+
};
|
|
276
|
+
interface BaseReadResult<TData, TError, TPluginResult = Record<string, unknown>, TTriggerOptions = {
|
|
277
|
+
force?: boolean;
|
|
278
|
+
}> {
|
|
279
|
+
data: Signal<TData | undefined>;
|
|
280
|
+
error: Signal<TError | undefined>;
|
|
281
|
+
loading: Signal<boolean>;
|
|
282
|
+
fetching: Signal<boolean>;
|
|
283
|
+
meta: Signal<TPluginResult>;
|
|
284
|
+
abort: () => void;
|
|
285
|
+
/**
|
|
286
|
+
* Manually trigger a fetch.
|
|
287
|
+
*
|
|
288
|
+
* @param options - Optional override options (query, body, params) to use for this specific request
|
|
289
|
+
*/
|
|
290
|
+
trigger: (options?: TTriggerOptions) => Promise<SpooshResponse<TData, TError>>;
|
|
291
|
+
}
|
|
292
|
+
type ReadApiClient<TSchema, TDefaultError> = ReadClient<TSchema, TDefaultError>;
|
|
293
|
+
|
|
279
294
|
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<{
|
|
280
295
|
data?: unknown;
|
|
281
296
|
error?: unknown;
|
|
@@ -336,15 +351,14 @@ declare function createInjectRead<TSchema, TDefaultError, TPlugins extends reado
|
|
|
336
351
|
readResult: infer R_2;
|
|
337
352
|
} ? 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 {
|
|
338
353
|
readResult: infer R_2;
|
|
339
|
-
} ? 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>>;
|
|
354
|
+
} ? 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>, TriggerOptions<TReadFn>> & ResponseInputFields<ExtractResponseQuery<TReadFn>, ExtractResponseBody<TReadFn>, ExtractResponseParamNames<TReadFn>>;
|
|
340
355
|
|
|
341
356
|
type SpooshAngularFunctions<TDefaultError, TSchema, TPlugins extends PluginArray> = {
|
|
342
357
|
injectRead: ReturnType<typeof createInjectRead<TSchema, TDefaultError, TPlugins>>;
|
|
343
358
|
injectWrite: ReturnType<typeof createInjectWrite<TSchema, TDefaultError, TPlugins>>;
|
|
344
359
|
injectInfiniteRead: ReturnType<typeof createInjectInfiniteRead<TSchema, TDefaultError, TPlugins>>;
|
|
345
|
-
injectLazyRead: ReturnType<typeof createInjectLazyRead<TSchema, TDefaultError, TPlugins>>;
|
|
346
360
|
} & MergePluginInstanceApi<TPlugins, TSchema>;
|
|
347
361
|
|
|
348
362
|
declare function createAngularSpoosh<TSchema, TDefaultError, TPlugins extends PluginArray, TApi>(instance: SpooshInstanceShape<TApi, TSchema, TDefaultError, TPlugins>): SpooshAngularFunctions<TDefaultError, TSchema, TPlugins>;
|
|
349
363
|
|
|
350
|
-
export { type AngularOptionsMap, type BaseInfiniteReadOptions, type BaseInfiniteReadResult, type
|
|
364
|
+
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 InfiniteReadApiClient, type PageContext, type ReadApiClient, type ResponseInputFields, type SpooshInstanceShape, type TriggerOptions, 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,
|
|
2
|
+
import { PluginArray, StateManager, EventEmitter, PluginExecutor, MethodOptionsMap, CoreRequestOptionsBase, ReadClient, TagOptions, SpooshPlugin, PluginTypeConfig, SpooshResponse, InfiniteRequestOptions, ResolveTypes, ResolverContext, WriteClient, 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,33 +14,10 @@ interface SpooshInstanceShape<TApi, TSchema, TDefaultError, TPlugins extends Plu
|
|
|
14
14
|
};
|
|
15
15
|
}
|
|
16
16
|
type EnabledOption = boolean | (() => boolean);
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
data: Signal<TData | undefined>;
|
|
22
|
-
error: Signal<TError | undefined>;
|
|
23
|
-
loading: Signal<boolean>;
|
|
24
|
-
fetching: Signal<boolean>;
|
|
25
|
-
meta: Signal<TPluginResult>;
|
|
26
|
-
abort: () => void;
|
|
27
|
-
trigger: () => Promise<SpooshResponse<TData, TError>>;
|
|
28
|
-
}
|
|
29
|
-
interface BaseWriteResult<TData, TError, TOptions, TPluginResult = Record<string, unknown>> {
|
|
30
|
-
trigger: (options?: TOptions) => Promise<SpooshResponse<TData, TError>>;
|
|
31
|
-
data: Signal<TData | undefined>;
|
|
32
|
-
error: Signal<TError | undefined>;
|
|
33
|
-
loading: Signal<boolean>;
|
|
34
|
-
meta: Signal<TPluginResult>;
|
|
35
|
-
abort: () => void;
|
|
36
|
-
}
|
|
37
|
-
interface BaseLazyReadResult<TData, TError, TOptions> {
|
|
38
|
-
trigger: (options?: TOptions) => Promise<SpooshResponse<TData, TError>>;
|
|
39
|
-
data: Signal<TData | undefined>;
|
|
40
|
-
error: Signal<TError | undefined>;
|
|
41
|
-
loading: Signal<boolean>;
|
|
42
|
-
abort: () => void;
|
|
43
|
-
}
|
|
17
|
+
type QueryRequestOptions = CoreRequestOptionsBase;
|
|
18
|
+
type MutationRequestOptions = CoreRequestOptionsBase;
|
|
19
|
+
type AngularOptionsMap = MethodOptionsMap<QueryRequestOptions, MutationRequestOptions>;
|
|
20
|
+
|
|
44
21
|
type PageContext<TData, TRequest> = {
|
|
45
22
|
response: TData | undefined;
|
|
46
23
|
allResponses: TData[];
|
|
@@ -70,32 +47,54 @@ interface BaseInfiniteReadResult<TData, TError, TItem, TPluginResult = Record<st
|
|
|
70
47
|
trigger: () => Promise<void>;
|
|
71
48
|
abort: () => void;
|
|
72
49
|
}
|
|
73
|
-
type
|
|
74
|
-
|
|
75
|
-
type
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
} : {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
}
|
|
50
|
+
type InfiniteReadApiClient<TSchema, TDefaultError> = ReadClient<TSchema, TDefaultError>;
|
|
51
|
+
|
|
52
|
+
type AnyInfiniteRequestOptions = InfiniteRequestOptions;
|
|
53
|
+
declare function createInjectInfiniteRead<TSchema, TDefaultError, TPlugins extends readonly SpooshPlugin<PluginTypeConfig>[]>(options: Omit<SpooshInstanceShape<unknown, TSchema, TDefaultError, TPlugins>, "_types">): <TReadFn extends (api: InfiniteReadApiClient<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>, {
|
|
54
|
+
data: unknown;
|
|
55
|
+
error?: undefined;
|
|
56
|
+
}> extends {
|
|
57
|
+
data: infer D;
|
|
58
|
+
} ? D : unknown : unknown, TItem, TRequest> & ResolveTypes<((TPlugins[number] extends infer T_3 ? T_3 extends TPlugins[number] ? T_3 extends SpooshPlugin<infer Types_1 extends PluginTypeConfig> ? Types_1 extends {
|
|
59
|
+
readOptions: infer R_3;
|
|
60
|
+
} ? R_3 : 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 {
|
|
61
|
+
readOptions: infer R_3;
|
|
62
|
+
} ? R_3 : object : object : never : never) ? T_4 extends unknown ? (x: T_4) => void : never : never : never) extends (x: infer I) => void ? I : never, ResolverContext<TSchema, TReadFn extends (...args: never[]) => infer R ? Extract<Awaited<R>, {
|
|
63
|
+
data: unknown;
|
|
64
|
+
error?: undefined;
|
|
65
|
+
}> extends {
|
|
66
|
+
data: infer D;
|
|
67
|
+
} ? D : unknown : unknown, [TReadFn extends (...args: never[]) => infer R_1 ? Extract<Awaited<R_1>, {
|
|
68
|
+
error: unknown;
|
|
69
|
+
data?: undefined;
|
|
70
|
+
}> extends {
|
|
71
|
+
error: infer E;
|
|
72
|
+
} ? E : unknown : unknown] extends [unknown] ? TDefaultError : TReadFn extends (...args: never[]) => infer R_1 ? Extract<Awaited<R_1>, {
|
|
73
|
+
error: unknown;
|
|
74
|
+
data?: undefined;
|
|
75
|
+
}> extends {
|
|
76
|
+
error: infer E;
|
|
77
|
+
} ? E : unknown : unknown>>) => BaseInfiniteReadResult<TReadFn extends (...args: never[]) => infer R ? Extract<Awaited<R>, {
|
|
78
|
+
data: unknown;
|
|
79
|
+
error?: undefined;
|
|
80
|
+
}> extends {
|
|
81
|
+
data: infer D;
|
|
82
|
+
} ? D : unknown : unknown, [TReadFn extends (...args: never[]) => infer R_1 ? Extract<Awaited<R_1>, {
|
|
83
|
+
error: unknown;
|
|
84
|
+
data?: undefined;
|
|
85
|
+
}> extends {
|
|
86
|
+
error: infer E;
|
|
87
|
+
} ? E : unknown : unknown] extends [unknown] ? TDefaultError : TReadFn extends (...args: never[]) => infer R_1 ? Extract<Awaited<R_1>, {
|
|
88
|
+
error: unknown;
|
|
89
|
+
data?: undefined;
|
|
90
|
+
}> extends {
|
|
91
|
+
error: infer E;
|
|
92
|
+
} ? E : unknown : unknown, TItem, ((TPlugins[number] extends infer T ? T extends TPlugins[number] ? T extends SpooshPlugin<infer Types extends PluginTypeConfig> ? Types extends {
|
|
93
|
+
readResult: infer R_2;
|
|
94
|
+
} ? 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 {
|
|
95
|
+
readResult: infer R_2;
|
|
96
|
+
} ? R_2 : object : object : never : never) ? T_1 extends unknown ? (x: T_1) => void : never : never : never) extends (x: infer I) => void ? I : never>;
|
|
97
|
+
|
|
99
98
|
type OptionalQueryField<TQuery> = [TQuery] extends [never] ? object : undefined extends TQuery ? {
|
|
100
99
|
query?: Exclude<TQuery, undefined>;
|
|
101
100
|
} : {
|
|
@@ -115,6 +114,16 @@ type InputFields<TQuery, TBody, TParamNames extends string> = OptionalQueryField
|
|
|
115
114
|
type WriteResponseInputFields<TQuery, TBody, TParamNames extends string> = [TQuery, TBody, TParamNames] extends [never, never, never] ? object : {
|
|
116
115
|
input: Signal<InputFields<TQuery, TBody, TParamNames> | undefined>;
|
|
117
116
|
};
|
|
117
|
+
interface BaseWriteResult<TData, TError, TOptions, TPluginResult = Record<string, unknown>> {
|
|
118
|
+
trigger: (options?: TOptions) => Promise<SpooshResponse<TData, TError>>;
|
|
119
|
+
data: Signal<TData | undefined>;
|
|
120
|
+
error: Signal<TError | undefined>;
|
|
121
|
+
loading: Signal<boolean>;
|
|
122
|
+
meta: Signal<TPluginResult>;
|
|
123
|
+
abort: () => void;
|
|
124
|
+
}
|
|
125
|
+
type WriteApiClient<TSchema, TDefaultError> = WriteClient<TSchema, TDefaultError>;
|
|
126
|
+
|
|
118
127
|
type SuccessResponse<T> = Extract<T, {
|
|
119
128
|
data: unknown;
|
|
120
129
|
error?: undefined;
|
|
@@ -154,69 +163,6 @@ type ExtractMethodBody<T> = ExtractMethodOptions<T> extends {
|
|
|
154
163
|
body: infer B;
|
|
155
164
|
} ? B : never;
|
|
156
165
|
|
|
157
|
-
declare function createInjectLazyRead<TSchema, TDefaultError, TPlugins extends readonly SpooshPlugin<PluginTypeConfig>[]>(options: Omit<SpooshInstanceShape<unknown, TSchema, TDefaultError, TPlugins>, "_types">): <TMethod extends (...args: never[]) => Promise<SpooshResponse<unknown, unknown>>>(readFn: (api: ReadApiClient<TSchema, TDefaultError>) => TMethod) => BaseLazyReadResult<TMethod extends (...args: never[]) => infer R ? Extract<Awaited<R>, {
|
|
158
|
-
data: unknown;
|
|
159
|
-
error?: undefined;
|
|
160
|
-
}> extends {
|
|
161
|
-
data: infer D;
|
|
162
|
-
} ? D : unknown : unknown, [TMethod extends (...args: never[]) => infer R_1 ? Extract<Awaited<R_1>, {
|
|
163
|
-
error: unknown;
|
|
164
|
-
data?: undefined;
|
|
165
|
-
}> extends {
|
|
166
|
-
error: infer E;
|
|
167
|
-
} ? E : unknown : unknown] extends [unknown] ? TDefaultError : TMethod extends (...args: never[]) => infer R_1 ? Extract<Awaited<R_1>, {
|
|
168
|
-
error: unknown;
|
|
169
|
-
data?: undefined;
|
|
170
|
-
}> extends {
|
|
171
|
-
error: infer E;
|
|
172
|
-
} ? E : unknown : unknown, TMethod extends (...args: infer A) => unknown ? A[0] extends object ? Pick<A[0], Extract<keyof A[0], "query" | "body" | "params">> : object : object> & WriteResponseInputFields<ExtractResponseQuery<TMethod>, ExtractResponseBody<TMethod>, ExtractResponseParamNames<TMethod>>;
|
|
173
|
-
|
|
174
|
-
type AnyInfiniteRequestOptions = InfiniteRequestOptions;
|
|
175
|
-
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>, {
|
|
176
|
-
data: unknown;
|
|
177
|
-
error?: undefined;
|
|
178
|
-
}> extends {
|
|
179
|
-
data: infer D;
|
|
180
|
-
} ? D : unknown : unknown, TItem, TRequest> & ResolveTypes<((TPlugins[number] extends infer T_3 ? T_3 extends TPlugins[number] ? T_3 extends SpooshPlugin<infer Types_1 extends PluginTypeConfig> ? Types_1 extends {
|
|
181
|
-
readOptions: infer R_3;
|
|
182
|
-
} ? R_3 : 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 {
|
|
183
|
-
readOptions: infer R_3;
|
|
184
|
-
} ? R_3 : object : object : never : never) ? T_4 extends unknown ? (x: T_4) => void : never : never : never) extends (x: infer I) => void ? I : never, ResolverContext<TSchema, TReadFn extends (...args: never[]) => infer R ? Extract<Awaited<R>, {
|
|
185
|
-
data: unknown;
|
|
186
|
-
error?: undefined;
|
|
187
|
-
}> extends {
|
|
188
|
-
data: infer D;
|
|
189
|
-
} ? D : unknown : unknown, [TReadFn extends (...args: never[]) => infer R_1 ? Extract<Awaited<R_1>, {
|
|
190
|
-
error: unknown;
|
|
191
|
-
data?: undefined;
|
|
192
|
-
}> extends {
|
|
193
|
-
error: infer E;
|
|
194
|
-
} ? E : unknown : unknown] extends [unknown] ? TDefaultError : TReadFn extends (...args: never[]) => infer R_1 ? Extract<Awaited<R_1>, {
|
|
195
|
-
error: unknown;
|
|
196
|
-
data?: undefined;
|
|
197
|
-
}> extends {
|
|
198
|
-
error: infer E;
|
|
199
|
-
} ? E : unknown : unknown>>) => BaseInfiniteReadResult<TReadFn extends (...args: never[]) => infer R ? Extract<Awaited<R>, {
|
|
200
|
-
data: unknown;
|
|
201
|
-
error?: undefined;
|
|
202
|
-
}> extends {
|
|
203
|
-
data: infer D;
|
|
204
|
-
} ? D : unknown : unknown, [TReadFn extends (...args: never[]) => infer R_1 ? Extract<Awaited<R_1>, {
|
|
205
|
-
error: unknown;
|
|
206
|
-
data?: undefined;
|
|
207
|
-
}> extends {
|
|
208
|
-
error: infer E;
|
|
209
|
-
} ? E : unknown : unknown] extends [unknown] ? TDefaultError : TReadFn extends (...args: never[]) => infer R_1 ? Extract<Awaited<R_1>, {
|
|
210
|
-
error: unknown;
|
|
211
|
-
data?: undefined;
|
|
212
|
-
}> extends {
|
|
213
|
-
error: infer E;
|
|
214
|
-
} ? E : unknown : unknown, TItem, ((TPlugins[number] extends infer T ? T extends TPlugins[number] ? T extends SpooshPlugin<infer Types extends PluginTypeConfig> ? Types extends {
|
|
215
|
-
readResult: infer R_2;
|
|
216
|
-
} ? 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 {
|
|
217
|
-
readResult: infer R_2;
|
|
218
|
-
} ? R_2 : object : object : never : never) ? T_1 extends unknown ? (x: T_1) => void : never : never : never) extends (x: infer I) => void ? I : never>;
|
|
219
|
-
|
|
220
166
|
declare function createInjectWrite<TSchema, TDefaultError, TPlugins extends readonly SpooshPlugin<PluginTypeConfig>[]>(options: Omit<SpooshInstanceShape<unknown, TSchema, TDefaultError, TPlugins>, "_types">): <TMethod extends (...args: never[]) => Promise<SpooshResponse<unknown, unknown>>, TWriteOpts extends (TMethod extends (...args: infer A) => unknown ? A[0] : never) & _spoosh_core.ResolveTypes<((TPlugins[number] extends infer T_3 ? T_3 extends TPlugins[number] ? T_3 extends SpooshPlugin<infer Types_1 extends PluginTypeConfig> ? Types_1 extends {
|
|
221
167
|
writeOptions: infer W_1;
|
|
222
168
|
} ? 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 {
|
|
@@ -276,6 +222,75 @@ declare function createInjectWrite<TSchema, TDefaultError, TPlugins extends read
|
|
|
276
222
|
writeResult: infer W;
|
|
277
223
|
} ? 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>>;
|
|
278
224
|
|
|
225
|
+
interface BaseReadOptions extends TagOptions {
|
|
226
|
+
enabled?: EnabledOption;
|
|
227
|
+
}
|
|
228
|
+
type QueryField<TQuery> = [TQuery] extends [never] ? object : undefined extends TQuery ? {
|
|
229
|
+
query?: Exclude<TQuery, undefined>;
|
|
230
|
+
} : {
|
|
231
|
+
query: TQuery;
|
|
232
|
+
};
|
|
233
|
+
type BodyField<TBody> = [TBody] extends [never] ? object : undefined extends TBody ? {
|
|
234
|
+
body?: Exclude<TBody, undefined>;
|
|
235
|
+
} : {
|
|
236
|
+
body: TBody;
|
|
237
|
+
};
|
|
238
|
+
type ParamsField<TParamNames extends string> = [TParamNames] extends [never] ? object : {
|
|
239
|
+
params: Record<TParamNames, string | number>;
|
|
240
|
+
};
|
|
241
|
+
type ReadInputFields<TQuery, TBody, TParamNames extends string> = QueryField<TQuery> & BodyField<TBody> & ParamsField<TParamNames>;
|
|
242
|
+
type ResponseInputFields<TQuery, TBody, TParamNames extends string> = [
|
|
243
|
+
TQuery,
|
|
244
|
+
TBody,
|
|
245
|
+
TParamNames
|
|
246
|
+
] extends [never, never, never] ? object : {
|
|
247
|
+
input: ReadInputFields<TQuery, TBody, TParamNames>;
|
|
248
|
+
};
|
|
249
|
+
type AwaitedReturnTypeTrigger<T> = T extends (...args: never[]) => infer R ? Awaited<R> : never;
|
|
250
|
+
type ExtractInputFromResponse<T> = T extends {
|
|
251
|
+
input: infer I;
|
|
252
|
+
} ? I : never;
|
|
253
|
+
type ExtractTriggerQuery<I> = I extends {
|
|
254
|
+
query: infer Q;
|
|
255
|
+
} ? {
|
|
256
|
+
query?: Q;
|
|
257
|
+
} : unknown;
|
|
258
|
+
type ExtractTriggerBody<I> = I extends {
|
|
259
|
+
body: infer B;
|
|
260
|
+
} ? {
|
|
261
|
+
body?: B;
|
|
262
|
+
} : unknown;
|
|
263
|
+
type ExtractTriggerParams<I> = I extends {
|
|
264
|
+
params: infer P;
|
|
265
|
+
} ? {
|
|
266
|
+
params?: P;
|
|
267
|
+
} : unknown;
|
|
268
|
+
type TriggerOptions<T> = ExtractInputFromResponse<AwaitedReturnTypeTrigger<T>> extends infer I ? [I] extends [never] ? {
|
|
269
|
+
force?: boolean;
|
|
270
|
+
} : ExtractTriggerQuery<I> & ExtractTriggerBody<I> & ExtractTriggerParams<I> & {
|
|
271
|
+
/** Force refetch even if data is cached */
|
|
272
|
+
force?: boolean;
|
|
273
|
+
} : {
|
|
274
|
+
force?: boolean;
|
|
275
|
+
};
|
|
276
|
+
interface BaseReadResult<TData, TError, TPluginResult = Record<string, unknown>, TTriggerOptions = {
|
|
277
|
+
force?: boolean;
|
|
278
|
+
}> {
|
|
279
|
+
data: Signal<TData | undefined>;
|
|
280
|
+
error: Signal<TError | undefined>;
|
|
281
|
+
loading: Signal<boolean>;
|
|
282
|
+
fetching: Signal<boolean>;
|
|
283
|
+
meta: Signal<TPluginResult>;
|
|
284
|
+
abort: () => void;
|
|
285
|
+
/**
|
|
286
|
+
* Manually trigger a fetch.
|
|
287
|
+
*
|
|
288
|
+
* @param options - Optional override options (query, body, params) to use for this specific request
|
|
289
|
+
*/
|
|
290
|
+
trigger: (options?: TTriggerOptions) => Promise<SpooshResponse<TData, TError>>;
|
|
291
|
+
}
|
|
292
|
+
type ReadApiClient<TSchema, TDefaultError> = ReadClient<TSchema, TDefaultError>;
|
|
293
|
+
|
|
279
294
|
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<{
|
|
280
295
|
data?: unknown;
|
|
281
296
|
error?: unknown;
|
|
@@ -336,15 +351,14 @@ declare function createInjectRead<TSchema, TDefaultError, TPlugins extends reado
|
|
|
336
351
|
readResult: infer R_2;
|
|
337
352
|
} ? 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 {
|
|
338
353
|
readResult: infer R_2;
|
|
339
|
-
} ? 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>>;
|
|
354
|
+
} ? 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>, TriggerOptions<TReadFn>> & ResponseInputFields<ExtractResponseQuery<TReadFn>, ExtractResponseBody<TReadFn>, ExtractResponseParamNames<TReadFn>>;
|
|
340
355
|
|
|
341
356
|
type SpooshAngularFunctions<TDefaultError, TSchema, TPlugins extends PluginArray> = {
|
|
342
357
|
injectRead: ReturnType<typeof createInjectRead<TSchema, TDefaultError, TPlugins>>;
|
|
343
358
|
injectWrite: ReturnType<typeof createInjectWrite<TSchema, TDefaultError, TPlugins>>;
|
|
344
359
|
injectInfiniteRead: ReturnType<typeof createInjectInfiniteRead<TSchema, TDefaultError, TPlugins>>;
|
|
345
|
-
injectLazyRead: ReturnType<typeof createInjectLazyRead<TSchema, TDefaultError, TPlugins>>;
|
|
346
360
|
} & MergePluginInstanceApi<TPlugins, TSchema>;
|
|
347
361
|
|
|
348
362
|
declare function createAngularSpoosh<TSchema, TDefaultError, TPlugins extends PluginArray, TApi>(instance: SpooshInstanceShape<TApi, TSchema, TDefaultError, TPlugins>): SpooshAngularFunctions<TDefaultError, TSchema, TPlugins>;
|
|
349
363
|
|
|
350
|
-
export { type AngularOptionsMap, type BaseInfiniteReadOptions, type BaseInfiniteReadResult, type
|
|
364
|
+
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 InfiniteReadApiClient, type PageContext, type ReadApiClient, type ResponseInputFields, type SpooshInstanceShape, type TriggerOptions, type WriteApiClient, type WriteResponseInputFields, createAngularSpoosh };
|
package/dist/index.js
CHANGED
|
@@ -45,6 +45,7 @@ function createInjectRead(options) {
|
|
|
45
45
|
const metaSignal = (0, import_core.signal)({});
|
|
46
46
|
let currentController = null;
|
|
47
47
|
let currentQueryKey = null;
|
|
48
|
+
let baseQueryKey = null;
|
|
48
49
|
let currentSubscription = null;
|
|
49
50
|
let currentResolvedTags = [];
|
|
50
51
|
let prevContext = null;
|
|
@@ -99,12 +100,16 @@ function createInjectRead(options) {
|
|
|
99
100
|
currentResolvedTags = resolvedTags;
|
|
100
101
|
return controller;
|
|
101
102
|
};
|
|
102
|
-
const executeWithTracking = async (controller, force = false) => {
|
|
103
|
+
const executeWithTracking = async (controller, force = false, overrideOptions) => {
|
|
103
104
|
const hasData = dataSignal() !== void 0;
|
|
104
105
|
loadingSignal.set(!hasData);
|
|
105
106
|
fetchingSignal.set(true);
|
|
106
107
|
try {
|
|
107
|
-
const
|
|
108
|
+
const execOptions = overrideOptions ? {
|
|
109
|
+
...currentController?.getContext().requestOptions,
|
|
110
|
+
...overrideOptions
|
|
111
|
+
} : void 0;
|
|
112
|
+
const response = await controller.execute(execOptions, { force });
|
|
108
113
|
if (response.error) {
|
|
109
114
|
errorSignal.set(response.error);
|
|
110
115
|
} else {
|
|
@@ -116,7 +121,7 @@ function createInjectRead(options) {
|
|
|
116
121
|
return response;
|
|
117
122
|
} catch (err) {
|
|
118
123
|
errorSignal.set(err);
|
|
119
|
-
|
|
124
|
+
return { error: err };
|
|
120
125
|
} finally {
|
|
121
126
|
loadingSignal.set(false);
|
|
122
127
|
fetchingSignal.set(false);
|
|
@@ -145,6 +150,7 @@ function createInjectRead(options) {
|
|
|
145
150
|
options: initialCapturedCall.options
|
|
146
151
|
});
|
|
147
152
|
createController(initialCapturedCall, initialResolvedTags, initialQueryKey);
|
|
153
|
+
baseQueryKey = initialQueryKey;
|
|
148
154
|
loadingSignal.set(false);
|
|
149
155
|
let wasEnabled = false;
|
|
150
156
|
(0, import_core.effect)(
|
|
@@ -181,10 +187,11 @@ function createInjectRead(options) {
|
|
|
181
187
|
inputInner.params = opts.params;
|
|
182
188
|
}
|
|
183
189
|
inputSignal.set(inputInner);
|
|
184
|
-
const
|
|
190
|
+
const baseQueryKeyChanged = queryKey !== baseQueryKey;
|
|
185
191
|
const enabledChanged = isEnabled !== wasEnabled;
|
|
186
192
|
wasEnabled = isEnabled;
|
|
187
|
-
if (
|
|
193
|
+
if (baseQueryKeyChanged) {
|
|
194
|
+
baseQueryKey = queryKey;
|
|
188
195
|
if (currentController) {
|
|
189
196
|
prevContext = currentController.getContext();
|
|
190
197
|
if (isMounted) {
|
|
@@ -249,9 +256,17 @@ function createInjectRead(options) {
|
|
|
249
256
|
}
|
|
250
257
|
}
|
|
251
258
|
);
|
|
259
|
+
const unsubRefetchAll = eventEmitter.on("refetchAll", () => {
|
|
260
|
+
if (currentController) {
|
|
261
|
+
(0, import_core.untracked)(() => {
|
|
262
|
+
executeWithTracking(currentController, true);
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
});
|
|
252
266
|
return () => {
|
|
253
267
|
unsubRefetch();
|
|
254
268
|
unsubInvalidate();
|
|
269
|
+
unsubRefetchAll();
|
|
255
270
|
};
|
|
256
271
|
},
|
|
257
272
|
{ allowSignalWrites: true }
|
|
@@ -267,15 +282,47 @@ function createInjectRead(options) {
|
|
|
267
282
|
const abort = () => {
|
|
268
283
|
currentController?.abort();
|
|
269
284
|
};
|
|
270
|
-
const trigger = () => {
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
285
|
+
const trigger = async (triggerOptions) => {
|
|
286
|
+
const { force = false, ...overrideOptions } = triggerOptions ?? {};
|
|
287
|
+
const hasOverrides = Object.keys(overrideOptions).length > 0;
|
|
288
|
+
if (!hasOverrides) {
|
|
289
|
+
if (!currentController) {
|
|
290
|
+
return Promise.resolve({ data: void 0, error: void 0 });
|
|
275
291
|
}
|
|
276
|
-
return executeWithTracking(currentController,
|
|
292
|
+
return executeWithTracking(currentController, force, void 0);
|
|
277
293
|
}
|
|
278
|
-
|
|
294
|
+
const selectorResult = captureSelector();
|
|
295
|
+
const capturedCall = selectorResult.call;
|
|
296
|
+
if (!capturedCall) {
|
|
297
|
+
return Promise.resolve({ data: void 0, error: void 0 });
|
|
298
|
+
}
|
|
299
|
+
const mergedOptions = {
|
|
300
|
+
...capturedCall.options ?? {},
|
|
301
|
+
...overrideOptions
|
|
302
|
+
};
|
|
303
|
+
const pathSegments = capturedCall.path.split("/").filter(Boolean);
|
|
304
|
+
const newQueryKey = stateManager.createQueryKey({
|
|
305
|
+
path: pathSegments,
|
|
306
|
+
method: capturedCall.method,
|
|
307
|
+
options: mergedOptions
|
|
308
|
+
});
|
|
309
|
+
if (newQueryKey === currentQueryKey && currentController) {
|
|
310
|
+
return executeWithTracking(currentController, force, overrideOptions);
|
|
311
|
+
}
|
|
312
|
+
const params = mergedOptions?.params;
|
|
313
|
+
const newResolvedPath = (0, import_core2.resolvePath)(pathSegments, params);
|
|
314
|
+
const newResolvedTags = (0, import_core2.resolveTags)(
|
|
315
|
+
tags !== void 0 ? { tags } : void 0,
|
|
316
|
+
newResolvedPath
|
|
317
|
+
);
|
|
318
|
+
const newController = createController(
|
|
319
|
+
{ ...capturedCall, options: mergedOptions },
|
|
320
|
+
newResolvedTags,
|
|
321
|
+
newQueryKey
|
|
322
|
+
);
|
|
323
|
+
newController.mount();
|
|
324
|
+
isMounted = true;
|
|
325
|
+
return executeWithTracking(newController, force, void 0);
|
|
279
326
|
};
|
|
280
327
|
const result = {
|
|
281
328
|
meta: metaSignal,
|
|
@@ -393,7 +440,7 @@ function createInjectWrite(options) {
|
|
|
393
440
|
return response;
|
|
394
441
|
} catch (err) {
|
|
395
442
|
errorSignal.set(err);
|
|
396
|
-
|
|
443
|
+
return { error: err };
|
|
397
444
|
} finally {
|
|
398
445
|
loadingSignal.set(false);
|
|
399
446
|
}
|
|
@@ -490,6 +537,7 @@ function createInjectInfiniteRead(options) {
|
|
|
490
537
|
let prevContext = null;
|
|
491
538
|
let isMounted = false;
|
|
492
539
|
let unsubInvalidate = null;
|
|
540
|
+
let unsubRefetchAll = null;
|
|
493
541
|
const updateSignalsFromState = () => {
|
|
494
542
|
if (!currentController) return;
|
|
495
543
|
const state = currentController.getState();
|
|
@@ -524,6 +572,9 @@ function createInjectInfiniteRead(options) {
|
|
|
524
572
|
if (unsubInvalidate) {
|
|
525
573
|
unsubInvalidate();
|
|
526
574
|
}
|
|
575
|
+
if (unsubRefetchAll) {
|
|
576
|
+
unsubRefetchAll();
|
|
577
|
+
}
|
|
527
578
|
const requestOptions = capturedCall.options;
|
|
528
579
|
const pathSegments = capturedCall.path.split("/").filter(Boolean);
|
|
529
580
|
const baseOptionsForKey = {
|
|
@@ -596,6 +647,14 @@ function createInjectInfiniteRead(options) {
|
|
|
596
647
|
}
|
|
597
648
|
}
|
|
598
649
|
);
|
|
650
|
+
unsubRefetchAll = eventEmitter.on("refetchAll", () => {
|
|
651
|
+
if (!getEnabled() || !currentController) return;
|
|
652
|
+
loadingSignal.set(true);
|
|
653
|
+
currentController.refetch().finally(() => {
|
|
654
|
+
updateSignalsFromState();
|
|
655
|
+
loadingSignal.set(false);
|
|
656
|
+
});
|
|
657
|
+
});
|
|
599
658
|
return controller;
|
|
600
659
|
};
|
|
601
660
|
const initialCapturedCall = captureSelector();
|
|
@@ -686,6 +745,9 @@ function createInjectInfiniteRead(options) {
|
|
|
686
745
|
if (unsubInvalidate) {
|
|
687
746
|
unsubInvalidate();
|
|
688
747
|
}
|
|
748
|
+
if (unsubRefetchAll) {
|
|
749
|
+
unsubRefetchAll();
|
|
750
|
+
}
|
|
689
751
|
if (currentSubscription) {
|
|
690
752
|
currentSubscription();
|
|
691
753
|
}
|
|
@@ -761,130 +823,6 @@ function createInjectInfiniteRead(options) {
|
|
|
761
823
|
};
|
|
762
824
|
}
|
|
763
825
|
|
|
764
|
-
// src/injectLazyRead/index.ts
|
|
765
|
-
var import_core7 = require("@angular/core");
|
|
766
|
-
var import_core8 = require("@spoosh/core");
|
|
767
|
-
function createInjectLazyRead(options) {
|
|
768
|
-
const { api, stateManager, pluginExecutor, eventEmitter } = options;
|
|
769
|
-
return function injectLazyRead(readFn) {
|
|
770
|
-
const destroyRef = (0, import_core7.inject)(import_core7.DestroyRef);
|
|
771
|
-
const captureSelector = () => {
|
|
772
|
-
const selectorResult = {
|
|
773
|
-
call: null,
|
|
774
|
-
selector: null
|
|
775
|
-
};
|
|
776
|
-
const selectorProxy = (0, import_core8.createSelectorProxy)(
|
|
777
|
-
(result2) => {
|
|
778
|
-
selectorResult.call = result2.call;
|
|
779
|
-
selectorResult.selector = result2.selector;
|
|
780
|
-
}
|
|
781
|
-
);
|
|
782
|
-
readFn(selectorProxy);
|
|
783
|
-
if (!selectorResult.selector) {
|
|
784
|
-
throw new Error(
|
|
785
|
-
'injectLazyRead requires selecting an HTTP method (GET). Example: injectLazyRead((api) => api("posts").GET)'
|
|
786
|
-
);
|
|
787
|
-
}
|
|
788
|
-
return selectorResult.selector;
|
|
789
|
-
};
|
|
790
|
-
const hookId = `angular-${Math.random().toString(36).slice(2)}`;
|
|
791
|
-
let currentQueryKey = null;
|
|
792
|
-
let currentController = null;
|
|
793
|
-
let currentSubscription = null;
|
|
794
|
-
const dataSignal = (0, import_core7.signal)(void 0);
|
|
795
|
-
const errorSignal = (0, import_core7.signal)(void 0);
|
|
796
|
-
const loadingSignal = (0, import_core7.signal)(false);
|
|
797
|
-
const lastTriggerOptionsSignal = (0, import_core7.signal)(void 0);
|
|
798
|
-
const inputSignal = (0, import_core7.signal)({});
|
|
799
|
-
destroyRef.onDestroy(() => {
|
|
800
|
-
if (currentSubscription) {
|
|
801
|
-
currentSubscription();
|
|
802
|
-
}
|
|
803
|
-
});
|
|
804
|
-
const abort = () => {
|
|
805
|
-
currentController?.abort();
|
|
806
|
-
};
|
|
807
|
-
const trigger = async (triggerOptions) => {
|
|
808
|
-
const selectedEndpoint = captureSelector();
|
|
809
|
-
const params = triggerOptions?.params;
|
|
810
|
-
const pathSegments = selectedEndpoint.path.split("/").filter(Boolean);
|
|
811
|
-
(0, import_core8.resolvePath)(pathSegments, params);
|
|
812
|
-
const queryKey = stateManager.createQueryKey({
|
|
813
|
-
path: pathSegments,
|
|
814
|
-
method: selectedEndpoint.method,
|
|
815
|
-
options: triggerOptions
|
|
816
|
-
});
|
|
817
|
-
const needsNewController = !currentController || currentQueryKey !== queryKey;
|
|
818
|
-
if (needsNewController) {
|
|
819
|
-
if (currentSubscription) {
|
|
820
|
-
currentSubscription();
|
|
821
|
-
}
|
|
822
|
-
const controller = (0, import_core8.createOperationController)({
|
|
823
|
-
operationType: "read",
|
|
824
|
-
path: pathSegments,
|
|
825
|
-
method: selectedEndpoint.method,
|
|
826
|
-
tags: [],
|
|
827
|
-
stateManager,
|
|
828
|
-
eventEmitter,
|
|
829
|
-
pluginExecutor,
|
|
830
|
-
hookId,
|
|
831
|
-
requestOptions: triggerOptions,
|
|
832
|
-
fetchFn: async (fetchOpts) => {
|
|
833
|
-
const pathMethods = api(selectedEndpoint.path);
|
|
834
|
-
const method = pathMethods[selectedEndpoint.method];
|
|
835
|
-
return method(fetchOpts);
|
|
836
|
-
}
|
|
837
|
-
});
|
|
838
|
-
currentSubscription = controller.subscribe(() => {
|
|
839
|
-
const state = controller.getState();
|
|
840
|
-
dataSignal.set(state.data);
|
|
841
|
-
errorSignal.set(state.error);
|
|
842
|
-
});
|
|
843
|
-
currentController = controller;
|
|
844
|
-
currentQueryKey = queryKey;
|
|
845
|
-
}
|
|
846
|
-
lastTriggerOptionsSignal.set(triggerOptions);
|
|
847
|
-
const opts = triggerOptions;
|
|
848
|
-
const inputInner = {};
|
|
849
|
-
if (opts?.query !== void 0) {
|
|
850
|
-
inputInner.query = opts.query;
|
|
851
|
-
}
|
|
852
|
-
if (opts?.body !== void 0) {
|
|
853
|
-
inputInner.body = opts.body;
|
|
854
|
-
}
|
|
855
|
-
if (opts?.params !== void 0) {
|
|
856
|
-
inputInner.params = opts.params;
|
|
857
|
-
}
|
|
858
|
-
inputSignal.set(inputInner);
|
|
859
|
-
loadingSignal.set(true);
|
|
860
|
-
currentController.setPluginOptions(triggerOptions);
|
|
861
|
-
try {
|
|
862
|
-
const response = await currentController.execute(triggerOptions);
|
|
863
|
-
if (response.error) {
|
|
864
|
-
errorSignal.set(response.error);
|
|
865
|
-
} else {
|
|
866
|
-
errorSignal.set(void 0);
|
|
867
|
-
}
|
|
868
|
-
return response;
|
|
869
|
-
} catch (err) {
|
|
870
|
-
errorSignal.set(err);
|
|
871
|
-
throw err;
|
|
872
|
-
} finally {
|
|
873
|
-
loadingSignal.set(false);
|
|
874
|
-
}
|
|
875
|
-
};
|
|
876
|
-
const result = {
|
|
877
|
-
trigger,
|
|
878
|
-
input: inputSignal,
|
|
879
|
-
data: dataSignal,
|
|
880
|
-
error: errorSignal,
|
|
881
|
-
loading: loadingSignal,
|
|
882
|
-
abort
|
|
883
|
-
};
|
|
884
|
-
return result;
|
|
885
|
-
};
|
|
886
|
-
}
|
|
887
|
-
|
|
888
826
|
// src/createAngularSpoosh/index.ts
|
|
889
827
|
function createAngularSpoosh(instance) {
|
|
890
828
|
const { api, stateManager, eventEmitter, pluginExecutor } = instance;
|
|
@@ -906,14 +844,6 @@ function createAngularSpoosh(instance) {
|
|
|
906
844
|
eventEmitter,
|
|
907
845
|
pluginExecutor
|
|
908
846
|
});
|
|
909
|
-
const injectLazyRead = createInjectLazyRead(
|
|
910
|
-
{
|
|
911
|
-
api,
|
|
912
|
-
stateManager,
|
|
913
|
-
eventEmitter,
|
|
914
|
-
pluginExecutor
|
|
915
|
-
}
|
|
916
|
-
);
|
|
917
847
|
const instanceApiContext = {
|
|
918
848
|
api,
|
|
919
849
|
stateManager,
|
|
@@ -934,7 +864,6 @@ function createAngularSpoosh(instance) {
|
|
|
934
864
|
injectRead,
|
|
935
865
|
injectWrite,
|
|
936
866
|
injectInfiniteRead,
|
|
937
|
-
injectLazyRead,
|
|
938
867
|
...instanceApis
|
|
939
868
|
};
|
|
940
869
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -30,6 +30,7 @@ function createInjectRead(options) {
|
|
|
30
30
|
const metaSignal = signal({});
|
|
31
31
|
let currentController = null;
|
|
32
32
|
let currentQueryKey = null;
|
|
33
|
+
let baseQueryKey = null;
|
|
33
34
|
let currentSubscription = null;
|
|
34
35
|
let currentResolvedTags = [];
|
|
35
36
|
let prevContext = null;
|
|
@@ -84,12 +85,16 @@ function createInjectRead(options) {
|
|
|
84
85
|
currentResolvedTags = resolvedTags;
|
|
85
86
|
return controller;
|
|
86
87
|
};
|
|
87
|
-
const executeWithTracking = async (controller, force = false) => {
|
|
88
|
+
const executeWithTracking = async (controller, force = false, overrideOptions) => {
|
|
88
89
|
const hasData = dataSignal() !== void 0;
|
|
89
90
|
loadingSignal.set(!hasData);
|
|
90
91
|
fetchingSignal.set(true);
|
|
91
92
|
try {
|
|
92
|
-
const
|
|
93
|
+
const execOptions = overrideOptions ? {
|
|
94
|
+
...currentController?.getContext().requestOptions,
|
|
95
|
+
...overrideOptions
|
|
96
|
+
} : void 0;
|
|
97
|
+
const response = await controller.execute(execOptions, { force });
|
|
93
98
|
if (response.error) {
|
|
94
99
|
errorSignal.set(response.error);
|
|
95
100
|
} else {
|
|
@@ -101,7 +106,7 @@ function createInjectRead(options) {
|
|
|
101
106
|
return response;
|
|
102
107
|
} catch (err) {
|
|
103
108
|
errorSignal.set(err);
|
|
104
|
-
|
|
109
|
+
return { error: err };
|
|
105
110
|
} finally {
|
|
106
111
|
loadingSignal.set(false);
|
|
107
112
|
fetchingSignal.set(false);
|
|
@@ -130,6 +135,7 @@ function createInjectRead(options) {
|
|
|
130
135
|
options: initialCapturedCall.options
|
|
131
136
|
});
|
|
132
137
|
createController(initialCapturedCall, initialResolvedTags, initialQueryKey);
|
|
138
|
+
baseQueryKey = initialQueryKey;
|
|
133
139
|
loadingSignal.set(false);
|
|
134
140
|
let wasEnabled = false;
|
|
135
141
|
effect(
|
|
@@ -166,10 +172,11 @@ function createInjectRead(options) {
|
|
|
166
172
|
inputInner.params = opts.params;
|
|
167
173
|
}
|
|
168
174
|
inputSignal.set(inputInner);
|
|
169
|
-
const
|
|
175
|
+
const baseQueryKeyChanged = queryKey !== baseQueryKey;
|
|
170
176
|
const enabledChanged = isEnabled !== wasEnabled;
|
|
171
177
|
wasEnabled = isEnabled;
|
|
172
|
-
if (
|
|
178
|
+
if (baseQueryKeyChanged) {
|
|
179
|
+
baseQueryKey = queryKey;
|
|
173
180
|
if (currentController) {
|
|
174
181
|
prevContext = currentController.getContext();
|
|
175
182
|
if (isMounted) {
|
|
@@ -234,9 +241,17 @@ function createInjectRead(options) {
|
|
|
234
241
|
}
|
|
235
242
|
}
|
|
236
243
|
);
|
|
244
|
+
const unsubRefetchAll = eventEmitter.on("refetchAll", () => {
|
|
245
|
+
if (currentController) {
|
|
246
|
+
untracked(() => {
|
|
247
|
+
executeWithTracking(currentController, true);
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
});
|
|
237
251
|
return () => {
|
|
238
252
|
unsubRefetch();
|
|
239
253
|
unsubInvalidate();
|
|
254
|
+
unsubRefetchAll();
|
|
240
255
|
};
|
|
241
256
|
},
|
|
242
257
|
{ allowSignalWrites: true }
|
|
@@ -252,15 +267,47 @@ function createInjectRead(options) {
|
|
|
252
267
|
const abort = () => {
|
|
253
268
|
currentController?.abort();
|
|
254
269
|
};
|
|
255
|
-
const trigger = () => {
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
270
|
+
const trigger = async (triggerOptions) => {
|
|
271
|
+
const { force = false, ...overrideOptions } = triggerOptions ?? {};
|
|
272
|
+
const hasOverrides = Object.keys(overrideOptions).length > 0;
|
|
273
|
+
if (!hasOverrides) {
|
|
274
|
+
if (!currentController) {
|
|
275
|
+
return Promise.resolve({ data: void 0, error: void 0 });
|
|
260
276
|
}
|
|
261
|
-
return executeWithTracking(currentController,
|
|
277
|
+
return executeWithTracking(currentController, force, void 0);
|
|
262
278
|
}
|
|
263
|
-
|
|
279
|
+
const selectorResult = captureSelector();
|
|
280
|
+
const capturedCall = selectorResult.call;
|
|
281
|
+
if (!capturedCall) {
|
|
282
|
+
return Promise.resolve({ data: void 0, error: void 0 });
|
|
283
|
+
}
|
|
284
|
+
const mergedOptions = {
|
|
285
|
+
...capturedCall.options ?? {},
|
|
286
|
+
...overrideOptions
|
|
287
|
+
};
|
|
288
|
+
const pathSegments = capturedCall.path.split("/").filter(Boolean);
|
|
289
|
+
const newQueryKey = stateManager.createQueryKey({
|
|
290
|
+
path: pathSegments,
|
|
291
|
+
method: capturedCall.method,
|
|
292
|
+
options: mergedOptions
|
|
293
|
+
});
|
|
294
|
+
if (newQueryKey === currentQueryKey && currentController) {
|
|
295
|
+
return executeWithTracking(currentController, force, overrideOptions);
|
|
296
|
+
}
|
|
297
|
+
const params = mergedOptions?.params;
|
|
298
|
+
const newResolvedPath = resolvePath(pathSegments, params);
|
|
299
|
+
const newResolvedTags = resolveTags(
|
|
300
|
+
tags !== void 0 ? { tags } : void 0,
|
|
301
|
+
newResolvedPath
|
|
302
|
+
);
|
|
303
|
+
const newController = createController(
|
|
304
|
+
{ ...capturedCall, options: mergedOptions },
|
|
305
|
+
newResolvedTags,
|
|
306
|
+
newQueryKey
|
|
307
|
+
);
|
|
308
|
+
newController.mount();
|
|
309
|
+
isMounted = true;
|
|
310
|
+
return executeWithTracking(newController, force, void 0);
|
|
264
311
|
};
|
|
265
312
|
const result = {
|
|
266
313
|
meta: metaSignal,
|
|
@@ -383,7 +430,7 @@ function createInjectWrite(options) {
|
|
|
383
430
|
return response;
|
|
384
431
|
} catch (err) {
|
|
385
432
|
errorSignal.set(err);
|
|
386
|
-
|
|
433
|
+
return { error: err };
|
|
387
434
|
} finally {
|
|
388
435
|
loadingSignal.set(false);
|
|
389
436
|
}
|
|
@@ -492,6 +539,7 @@ function createInjectInfiniteRead(options) {
|
|
|
492
539
|
let prevContext = null;
|
|
493
540
|
let isMounted = false;
|
|
494
541
|
let unsubInvalidate = null;
|
|
542
|
+
let unsubRefetchAll = null;
|
|
495
543
|
const updateSignalsFromState = () => {
|
|
496
544
|
if (!currentController) return;
|
|
497
545
|
const state = currentController.getState();
|
|
@@ -526,6 +574,9 @@ function createInjectInfiniteRead(options) {
|
|
|
526
574
|
if (unsubInvalidate) {
|
|
527
575
|
unsubInvalidate();
|
|
528
576
|
}
|
|
577
|
+
if (unsubRefetchAll) {
|
|
578
|
+
unsubRefetchAll();
|
|
579
|
+
}
|
|
529
580
|
const requestOptions = capturedCall.options;
|
|
530
581
|
const pathSegments = capturedCall.path.split("/").filter(Boolean);
|
|
531
582
|
const baseOptionsForKey = {
|
|
@@ -598,6 +649,14 @@ function createInjectInfiniteRead(options) {
|
|
|
598
649
|
}
|
|
599
650
|
}
|
|
600
651
|
);
|
|
652
|
+
unsubRefetchAll = eventEmitter.on("refetchAll", () => {
|
|
653
|
+
if (!getEnabled() || !currentController) return;
|
|
654
|
+
loadingSignal.set(true);
|
|
655
|
+
currentController.refetch().finally(() => {
|
|
656
|
+
updateSignalsFromState();
|
|
657
|
+
loadingSignal.set(false);
|
|
658
|
+
});
|
|
659
|
+
});
|
|
601
660
|
return controller;
|
|
602
661
|
};
|
|
603
662
|
const initialCapturedCall = captureSelector();
|
|
@@ -688,6 +747,9 @@ function createInjectInfiniteRead(options) {
|
|
|
688
747
|
if (unsubInvalidate) {
|
|
689
748
|
unsubInvalidate();
|
|
690
749
|
}
|
|
750
|
+
if (unsubRefetchAll) {
|
|
751
|
+
unsubRefetchAll();
|
|
752
|
+
}
|
|
691
753
|
if (currentSubscription) {
|
|
692
754
|
currentSubscription();
|
|
693
755
|
}
|
|
@@ -763,134 +825,6 @@ function createInjectInfiniteRead(options) {
|
|
|
763
825
|
};
|
|
764
826
|
}
|
|
765
827
|
|
|
766
|
-
// src/injectLazyRead/index.ts
|
|
767
|
-
import { signal as signal4, DestroyRef as DestroyRef4, inject as inject4 } from "@angular/core";
|
|
768
|
-
import {
|
|
769
|
-
createOperationController as createOperationController3,
|
|
770
|
-
createSelectorProxy as createSelectorProxy4,
|
|
771
|
-
resolvePath as resolvePath4
|
|
772
|
-
} from "@spoosh/core";
|
|
773
|
-
function createInjectLazyRead(options) {
|
|
774
|
-
const { api, stateManager, pluginExecutor, eventEmitter } = options;
|
|
775
|
-
return function injectLazyRead(readFn) {
|
|
776
|
-
const destroyRef = inject4(DestroyRef4);
|
|
777
|
-
const captureSelector = () => {
|
|
778
|
-
const selectorResult = {
|
|
779
|
-
call: null,
|
|
780
|
-
selector: null
|
|
781
|
-
};
|
|
782
|
-
const selectorProxy = createSelectorProxy4(
|
|
783
|
-
(result2) => {
|
|
784
|
-
selectorResult.call = result2.call;
|
|
785
|
-
selectorResult.selector = result2.selector;
|
|
786
|
-
}
|
|
787
|
-
);
|
|
788
|
-
readFn(selectorProxy);
|
|
789
|
-
if (!selectorResult.selector) {
|
|
790
|
-
throw new Error(
|
|
791
|
-
'injectLazyRead requires selecting an HTTP method (GET). Example: injectLazyRead((api) => api("posts").GET)'
|
|
792
|
-
);
|
|
793
|
-
}
|
|
794
|
-
return selectorResult.selector;
|
|
795
|
-
};
|
|
796
|
-
const hookId = `angular-${Math.random().toString(36).slice(2)}`;
|
|
797
|
-
let currentQueryKey = null;
|
|
798
|
-
let currentController = null;
|
|
799
|
-
let currentSubscription = null;
|
|
800
|
-
const dataSignal = signal4(void 0);
|
|
801
|
-
const errorSignal = signal4(void 0);
|
|
802
|
-
const loadingSignal = signal4(false);
|
|
803
|
-
const lastTriggerOptionsSignal = signal4(void 0);
|
|
804
|
-
const inputSignal = signal4({});
|
|
805
|
-
destroyRef.onDestroy(() => {
|
|
806
|
-
if (currentSubscription) {
|
|
807
|
-
currentSubscription();
|
|
808
|
-
}
|
|
809
|
-
});
|
|
810
|
-
const abort = () => {
|
|
811
|
-
currentController?.abort();
|
|
812
|
-
};
|
|
813
|
-
const trigger = async (triggerOptions) => {
|
|
814
|
-
const selectedEndpoint = captureSelector();
|
|
815
|
-
const params = triggerOptions?.params;
|
|
816
|
-
const pathSegments = selectedEndpoint.path.split("/").filter(Boolean);
|
|
817
|
-
resolvePath4(pathSegments, params);
|
|
818
|
-
const queryKey = stateManager.createQueryKey({
|
|
819
|
-
path: pathSegments,
|
|
820
|
-
method: selectedEndpoint.method,
|
|
821
|
-
options: triggerOptions
|
|
822
|
-
});
|
|
823
|
-
const needsNewController = !currentController || currentQueryKey !== queryKey;
|
|
824
|
-
if (needsNewController) {
|
|
825
|
-
if (currentSubscription) {
|
|
826
|
-
currentSubscription();
|
|
827
|
-
}
|
|
828
|
-
const controller = createOperationController3({
|
|
829
|
-
operationType: "read",
|
|
830
|
-
path: pathSegments,
|
|
831
|
-
method: selectedEndpoint.method,
|
|
832
|
-
tags: [],
|
|
833
|
-
stateManager,
|
|
834
|
-
eventEmitter,
|
|
835
|
-
pluginExecutor,
|
|
836
|
-
hookId,
|
|
837
|
-
requestOptions: triggerOptions,
|
|
838
|
-
fetchFn: async (fetchOpts) => {
|
|
839
|
-
const pathMethods = api(selectedEndpoint.path);
|
|
840
|
-
const method = pathMethods[selectedEndpoint.method];
|
|
841
|
-
return method(fetchOpts);
|
|
842
|
-
}
|
|
843
|
-
});
|
|
844
|
-
currentSubscription = controller.subscribe(() => {
|
|
845
|
-
const state = controller.getState();
|
|
846
|
-
dataSignal.set(state.data);
|
|
847
|
-
errorSignal.set(state.error);
|
|
848
|
-
});
|
|
849
|
-
currentController = controller;
|
|
850
|
-
currentQueryKey = queryKey;
|
|
851
|
-
}
|
|
852
|
-
lastTriggerOptionsSignal.set(triggerOptions);
|
|
853
|
-
const opts = triggerOptions;
|
|
854
|
-
const inputInner = {};
|
|
855
|
-
if (opts?.query !== void 0) {
|
|
856
|
-
inputInner.query = opts.query;
|
|
857
|
-
}
|
|
858
|
-
if (opts?.body !== void 0) {
|
|
859
|
-
inputInner.body = opts.body;
|
|
860
|
-
}
|
|
861
|
-
if (opts?.params !== void 0) {
|
|
862
|
-
inputInner.params = opts.params;
|
|
863
|
-
}
|
|
864
|
-
inputSignal.set(inputInner);
|
|
865
|
-
loadingSignal.set(true);
|
|
866
|
-
currentController.setPluginOptions(triggerOptions);
|
|
867
|
-
try {
|
|
868
|
-
const response = await currentController.execute(triggerOptions);
|
|
869
|
-
if (response.error) {
|
|
870
|
-
errorSignal.set(response.error);
|
|
871
|
-
} else {
|
|
872
|
-
errorSignal.set(void 0);
|
|
873
|
-
}
|
|
874
|
-
return response;
|
|
875
|
-
} catch (err) {
|
|
876
|
-
errorSignal.set(err);
|
|
877
|
-
throw err;
|
|
878
|
-
} finally {
|
|
879
|
-
loadingSignal.set(false);
|
|
880
|
-
}
|
|
881
|
-
};
|
|
882
|
-
const result = {
|
|
883
|
-
trigger,
|
|
884
|
-
input: inputSignal,
|
|
885
|
-
data: dataSignal,
|
|
886
|
-
error: errorSignal,
|
|
887
|
-
loading: loadingSignal,
|
|
888
|
-
abort
|
|
889
|
-
};
|
|
890
|
-
return result;
|
|
891
|
-
};
|
|
892
|
-
}
|
|
893
|
-
|
|
894
828
|
// src/createAngularSpoosh/index.ts
|
|
895
829
|
function createAngularSpoosh(instance) {
|
|
896
830
|
const { api, stateManager, eventEmitter, pluginExecutor } = instance;
|
|
@@ -912,14 +846,6 @@ function createAngularSpoosh(instance) {
|
|
|
912
846
|
eventEmitter,
|
|
913
847
|
pluginExecutor
|
|
914
848
|
});
|
|
915
|
-
const injectLazyRead = createInjectLazyRead(
|
|
916
|
-
{
|
|
917
|
-
api,
|
|
918
|
-
stateManager,
|
|
919
|
-
eventEmitter,
|
|
920
|
-
pluginExecutor
|
|
921
|
-
}
|
|
922
|
-
);
|
|
923
849
|
const instanceApiContext = {
|
|
924
850
|
api,
|
|
925
851
|
stateManager,
|
|
@@ -940,7 +866,6 @@ function createAngularSpoosh(instance) {
|
|
|
940
866
|
injectRead,
|
|
941
867
|
injectWrite,
|
|
942
868
|
injectInfiniteRead,
|
|
943
|
-
injectLazyRead,
|
|
944
869
|
...instanceApis
|
|
945
870
|
};
|
|
946
871
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@spoosh/angular",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Angular signals integration for Spoosh API client",
|
|
6
6
|
"keywords": [
|
|
@@ -38,7 +38,9 @@
|
|
|
38
38
|
"@angular/core": ">=16.0.0"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
|
-
"@
|
|
41
|
+
"@angular/core": "^19.0.0",
|
|
42
|
+
"@spoosh/core": "0.9.3",
|
|
43
|
+
"@spoosh/test-utils": "0.1.5"
|
|
42
44
|
},
|
|
43
45
|
"scripts": {
|
|
44
46
|
"dev": "tsup --watch",
|