@spoosh/angular 0.4.0 → 0.5.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 +26 -5
- package/dist/index.d.mts +28 -4
- package/dist/index.d.ts +28 -4
- package/dist/index.js +137 -13
- package/dist/index.mjs +141 -13
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @spoosh/angular
|
|
2
2
|
|
|
3
|
-
Angular signals integration for Spoosh - `injectRead`, `injectWrite`, and `injectInfiniteRead`.
|
|
3
|
+
Angular signals integration for Spoosh - `injectRead`, `injectLazyRead`, `injectWrite`, and `injectInfiniteRead`.
|
|
4
4
|
|
|
5
5
|
**[Documentation](https://spoosh.dev/docs/integrations/angular)** · **Requirements:** TypeScript >= 5.0, Angular >= 16.0
|
|
6
6
|
|
|
@@ -23,13 +23,13 @@ const spoosh = new Spoosh<ApiSchema, Error>("/api").use([
|
|
|
23
23
|
cachePlugin({ staleTime: 5000 }),
|
|
24
24
|
]);
|
|
25
25
|
|
|
26
|
-
export const { injectRead, injectWrite, injectInfiniteRead } =
|
|
26
|
+
export const { injectRead, injectLazyRead, injectWrite, injectInfiniteRead } =
|
|
27
27
|
createAngularSpoosh(spoosh);
|
|
28
28
|
```
|
|
29
29
|
|
|
30
30
|
### injectRead
|
|
31
31
|
|
|
32
|
-
Fetch data with automatic caching and
|
|
32
|
+
Fetch data with automatic caching and triggering using Angular signals.
|
|
33
33
|
|
|
34
34
|
```typescript
|
|
35
35
|
@Component({
|
|
@@ -74,6 +74,28 @@ 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
|
+
|
|
77
99
|
### injectWrite
|
|
78
100
|
|
|
79
101
|
Trigger mutations with loading and error states.
|
|
@@ -187,7 +209,7 @@ export class PostListComponent {
|
|
|
187
209
|
| `loading` | `Signal<boolean>` | True during initial load |
|
|
188
210
|
| `fetching` | `Signal<boolean>` | True during any fetch |
|
|
189
211
|
| `meta` | `Signal<PluginResults>` | Plugin metadata (e.g., `transformedData`) |
|
|
190
|
-
| `
|
|
212
|
+
| `trigger` | `() => Promise` | Manually trigger fetch |
|
|
191
213
|
| `abort` | `() => void` | Abort current request |
|
|
192
214
|
|
|
193
215
|
### injectWrite(writeFn)
|
|
@@ -202,7 +224,6 @@ export class PostListComponent {
|
|
|
202
224
|
| `loading` | `Signal<boolean>` | True while mutation is in progress |
|
|
203
225
|
| `meta` | `Signal<PluginResults>` | Plugin metadata |
|
|
204
226
|
| `input` | `TriggerOptions \| undefined` | Last trigger input |
|
|
205
|
-
| `reset` | `() => void` | Reset state |
|
|
206
227
|
| `abort` | `() => void` | Abort current request |
|
|
207
228
|
|
|
208
229
|
### injectInfiniteRead(readFn, options)
|
package/dist/index.d.mts
CHANGED
|
@@ -24,7 +24,7 @@ interface BaseReadResult<TData, TError, TPluginResult = Record<string, unknown>>
|
|
|
24
24
|
fetching: Signal<boolean>;
|
|
25
25
|
meta: Signal<TPluginResult>;
|
|
26
26
|
abort: () => void;
|
|
27
|
-
|
|
27
|
+
trigger: () => Promise<SpooshResponse<TData, TError>>;
|
|
28
28
|
}
|
|
29
29
|
interface BaseWriteResult<TData, TError, TOptions, TPluginResult = Record<string, unknown>> {
|
|
30
30
|
trigger: (options?: TOptions) => Promise<SpooshResponse<TData, TError>>;
|
|
@@ -32,7 +32,13 @@ interface BaseWriteResult<TData, TError, TOptions, TPluginResult = Record<string
|
|
|
32
32
|
error: Signal<TError | undefined>;
|
|
33
33
|
loading: Signal<boolean>;
|
|
34
34
|
meta: Signal<TPluginResult>;
|
|
35
|
-
|
|
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>;
|
|
36
42
|
abort: () => void;
|
|
37
43
|
}
|
|
38
44
|
type PageContext<TData, TRequest> = {
|
|
@@ -61,7 +67,7 @@ interface BaseInfiniteReadResult<TData, TError, TItem, TPluginResult = Record<st
|
|
|
61
67
|
meta: Signal<TPluginResult>;
|
|
62
68
|
fetchNext: () => Promise<void>;
|
|
63
69
|
fetchPrev: () => Promise<void>;
|
|
64
|
-
|
|
70
|
+
trigger: () => Promise<void>;
|
|
65
71
|
abort: () => void;
|
|
66
72
|
}
|
|
67
73
|
type QueryRequestOptions = CoreRequestOptionsBase;
|
|
@@ -148,6 +154,23 @@ type ExtractMethodBody<T> = ExtractMethodOptions<T> extends {
|
|
|
148
154
|
body: infer B;
|
|
149
155
|
} ? B : never;
|
|
150
156
|
|
|
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
|
+
|
|
151
174
|
type AnyInfiniteRequestOptions = InfiniteRequestOptions;
|
|
152
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>, {
|
|
153
176
|
data: unknown;
|
|
@@ -319,8 +342,9 @@ type SpooshAngularFunctions<TDefaultError, TSchema, TPlugins extends PluginArray
|
|
|
319
342
|
injectRead: ReturnType<typeof createInjectRead<TSchema, TDefaultError, TPlugins>>;
|
|
320
343
|
injectWrite: ReturnType<typeof createInjectWrite<TSchema, TDefaultError, TPlugins>>;
|
|
321
344
|
injectInfiniteRead: ReturnType<typeof createInjectInfiniteRead<TSchema, TDefaultError, TPlugins>>;
|
|
345
|
+
injectLazyRead: ReturnType<typeof createInjectLazyRead<TSchema, TDefaultError, TPlugins>>;
|
|
322
346
|
} & MergePluginInstanceApi<TPlugins, TSchema>;
|
|
323
347
|
|
|
324
348
|
declare function createAngularSpoosh<TSchema, TDefaultError, TPlugins extends PluginArray, TApi>(instance: SpooshInstanceShape<TApi, TSchema, TDefaultError, TPlugins>): SpooshAngularFunctions<TDefaultError, TSchema, TPlugins>;
|
|
325
349
|
|
|
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 };
|
|
350
|
+
export { type AngularOptionsMap, type BaseInfiniteReadOptions, type BaseInfiniteReadResult, type BaseLazyReadResult, 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
|
@@ -24,7 +24,7 @@ interface BaseReadResult<TData, TError, TPluginResult = Record<string, unknown>>
|
|
|
24
24
|
fetching: Signal<boolean>;
|
|
25
25
|
meta: Signal<TPluginResult>;
|
|
26
26
|
abort: () => void;
|
|
27
|
-
|
|
27
|
+
trigger: () => Promise<SpooshResponse<TData, TError>>;
|
|
28
28
|
}
|
|
29
29
|
interface BaseWriteResult<TData, TError, TOptions, TPluginResult = Record<string, unknown>> {
|
|
30
30
|
trigger: (options?: TOptions) => Promise<SpooshResponse<TData, TError>>;
|
|
@@ -32,7 +32,13 @@ interface BaseWriteResult<TData, TError, TOptions, TPluginResult = Record<string
|
|
|
32
32
|
error: Signal<TError | undefined>;
|
|
33
33
|
loading: Signal<boolean>;
|
|
34
34
|
meta: Signal<TPluginResult>;
|
|
35
|
-
|
|
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>;
|
|
36
42
|
abort: () => void;
|
|
37
43
|
}
|
|
38
44
|
type PageContext<TData, TRequest> = {
|
|
@@ -61,7 +67,7 @@ interface BaseInfiniteReadResult<TData, TError, TItem, TPluginResult = Record<st
|
|
|
61
67
|
meta: Signal<TPluginResult>;
|
|
62
68
|
fetchNext: () => Promise<void>;
|
|
63
69
|
fetchPrev: () => Promise<void>;
|
|
64
|
-
|
|
70
|
+
trigger: () => Promise<void>;
|
|
65
71
|
abort: () => void;
|
|
66
72
|
}
|
|
67
73
|
type QueryRequestOptions = CoreRequestOptionsBase;
|
|
@@ -148,6 +154,23 @@ type ExtractMethodBody<T> = ExtractMethodOptions<T> extends {
|
|
|
148
154
|
body: infer B;
|
|
149
155
|
} ? B : never;
|
|
150
156
|
|
|
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
|
+
|
|
151
174
|
type AnyInfiniteRequestOptions = InfiniteRequestOptions;
|
|
152
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>, {
|
|
153
176
|
data: unknown;
|
|
@@ -319,8 +342,9 @@ type SpooshAngularFunctions<TDefaultError, TSchema, TPlugins extends PluginArray
|
|
|
319
342
|
injectRead: ReturnType<typeof createInjectRead<TSchema, TDefaultError, TPlugins>>;
|
|
320
343
|
injectWrite: ReturnType<typeof createInjectWrite<TSchema, TDefaultError, TPlugins>>;
|
|
321
344
|
injectInfiniteRead: ReturnType<typeof createInjectInfiniteRead<TSchema, TDefaultError, TPlugins>>;
|
|
345
|
+
injectLazyRead: ReturnType<typeof createInjectLazyRead<TSchema, TDefaultError, TPlugins>>;
|
|
322
346
|
} & MergePluginInstanceApi<TPlugins, TSchema>;
|
|
323
347
|
|
|
324
348
|
declare function createAngularSpoosh<TSchema, TDefaultError, TPlugins extends PluginArray, TApi>(instance: SpooshInstanceShape<TApi, TSchema, TDefaultError, TPlugins>): SpooshAngularFunctions<TDefaultError, TSchema, TPlugins>;
|
|
325
349
|
|
|
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 };
|
|
350
|
+
export { type AngularOptionsMap, type BaseInfiniteReadOptions, type BaseInfiniteReadResult, type BaseLazyReadResult, 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
|
@@ -267,7 +267,7 @@ function createInjectRead(options) {
|
|
|
267
267
|
const abort = () => {
|
|
268
268
|
currentController?.abort();
|
|
269
269
|
};
|
|
270
|
-
const
|
|
270
|
+
const trigger = () => {
|
|
271
271
|
if (currentController) {
|
|
272
272
|
if (!isMounted) {
|
|
273
273
|
currentController.mount();
|
|
@@ -287,7 +287,7 @@ function createInjectRead(options) {
|
|
|
287
287
|
loading: loadingSignal,
|
|
288
288
|
fetching: fetchingSignal,
|
|
289
289
|
abort,
|
|
290
|
-
|
|
290
|
+
trigger
|
|
291
291
|
};
|
|
292
292
|
return result;
|
|
293
293
|
};
|
|
@@ -333,14 +333,6 @@ function createInjectWrite(options) {
|
|
|
333
333
|
currentSubscription();
|
|
334
334
|
}
|
|
335
335
|
});
|
|
336
|
-
const reset = () => {
|
|
337
|
-
if (currentQueryKey) {
|
|
338
|
-
stateManager.deleteCache(currentQueryKey);
|
|
339
|
-
}
|
|
340
|
-
dataSignal.set(void 0);
|
|
341
|
-
errorSignal.set(void 0);
|
|
342
|
-
loadingSignal.set(false);
|
|
343
|
-
};
|
|
344
336
|
const abort = () => {
|
|
345
337
|
currentController?.abort();
|
|
346
338
|
};
|
|
@@ -431,7 +423,6 @@ function createInjectWrite(options) {
|
|
|
431
423
|
data: dataSignal,
|
|
432
424
|
error: errorSignal,
|
|
433
425
|
loading: loadingSignal,
|
|
434
|
-
reset,
|
|
435
426
|
abort
|
|
436
427
|
};
|
|
437
428
|
return result;
|
|
@@ -730,7 +721,7 @@ function createInjectInfiniteRead(options) {
|
|
|
730
721
|
fetchingPrevSignal.set(false);
|
|
731
722
|
}
|
|
732
723
|
};
|
|
733
|
-
const
|
|
724
|
+
const trigger = async () => {
|
|
734
725
|
if (!currentController) return;
|
|
735
726
|
if (!isMounted) {
|
|
736
727
|
currentController.mount();
|
|
@@ -763,7 +754,131 @@ function createInjectInfiniteRead(options) {
|
|
|
763
754
|
canFetchPrev: canFetchPrevSignal,
|
|
764
755
|
fetchNext,
|
|
765
756
|
fetchPrev,
|
|
766
|
-
|
|
757
|
+
trigger,
|
|
758
|
+
abort
|
|
759
|
+
};
|
|
760
|
+
return result;
|
|
761
|
+
};
|
|
762
|
+
}
|
|
763
|
+
|
|
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,
|
|
767
882
|
abort
|
|
768
883
|
};
|
|
769
884
|
return result;
|
|
@@ -791,6 +906,14 @@ function createAngularSpoosh(instance) {
|
|
|
791
906
|
eventEmitter,
|
|
792
907
|
pluginExecutor
|
|
793
908
|
});
|
|
909
|
+
const injectLazyRead = createInjectLazyRead(
|
|
910
|
+
{
|
|
911
|
+
api,
|
|
912
|
+
stateManager,
|
|
913
|
+
eventEmitter,
|
|
914
|
+
pluginExecutor
|
|
915
|
+
}
|
|
916
|
+
);
|
|
794
917
|
const instanceApiContext = {
|
|
795
918
|
api,
|
|
796
919
|
stateManager,
|
|
@@ -811,6 +934,7 @@ function createAngularSpoosh(instance) {
|
|
|
811
934
|
injectRead,
|
|
812
935
|
injectWrite,
|
|
813
936
|
injectInfiniteRead,
|
|
937
|
+
injectLazyRead,
|
|
814
938
|
...instanceApis
|
|
815
939
|
};
|
|
816
940
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -252,7 +252,7 @@ function createInjectRead(options) {
|
|
|
252
252
|
const abort = () => {
|
|
253
253
|
currentController?.abort();
|
|
254
254
|
};
|
|
255
|
-
const
|
|
255
|
+
const trigger = () => {
|
|
256
256
|
if (currentController) {
|
|
257
257
|
if (!isMounted) {
|
|
258
258
|
currentController.mount();
|
|
@@ -272,7 +272,7 @@ function createInjectRead(options) {
|
|
|
272
272
|
loading: loadingSignal,
|
|
273
273
|
fetching: fetchingSignal,
|
|
274
274
|
abort,
|
|
275
|
-
|
|
275
|
+
trigger
|
|
276
276
|
};
|
|
277
277
|
return result;
|
|
278
278
|
};
|
|
@@ -323,14 +323,6 @@ function createInjectWrite(options) {
|
|
|
323
323
|
currentSubscription();
|
|
324
324
|
}
|
|
325
325
|
});
|
|
326
|
-
const reset = () => {
|
|
327
|
-
if (currentQueryKey) {
|
|
328
|
-
stateManager.deleteCache(currentQueryKey);
|
|
329
|
-
}
|
|
330
|
-
dataSignal.set(void 0);
|
|
331
|
-
errorSignal.set(void 0);
|
|
332
|
-
loadingSignal.set(false);
|
|
333
|
-
};
|
|
334
326
|
const abort = () => {
|
|
335
327
|
currentController?.abort();
|
|
336
328
|
};
|
|
@@ -421,7 +413,6 @@ function createInjectWrite(options) {
|
|
|
421
413
|
data: dataSignal,
|
|
422
414
|
error: errorSignal,
|
|
423
415
|
loading: loadingSignal,
|
|
424
|
-
reset,
|
|
425
416
|
abort
|
|
426
417
|
};
|
|
427
418
|
return result;
|
|
@@ -732,7 +723,7 @@ function createInjectInfiniteRead(options) {
|
|
|
732
723
|
fetchingPrevSignal.set(false);
|
|
733
724
|
}
|
|
734
725
|
};
|
|
735
|
-
const
|
|
726
|
+
const trigger = async () => {
|
|
736
727
|
if (!currentController) return;
|
|
737
728
|
if (!isMounted) {
|
|
738
729
|
currentController.mount();
|
|
@@ -765,7 +756,135 @@ function createInjectInfiniteRead(options) {
|
|
|
765
756
|
canFetchPrev: canFetchPrevSignal,
|
|
766
757
|
fetchNext,
|
|
767
758
|
fetchPrev,
|
|
768
|
-
|
|
759
|
+
trigger,
|
|
760
|
+
abort
|
|
761
|
+
};
|
|
762
|
+
return result;
|
|
763
|
+
};
|
|
764
|
+
}
|
|
765
|
+
|
|
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,
|
|
769
888
|
abort
|
|
770
889
|
};
|
|
771
890
|
return result;
|
|
@@ -793,6 +912,14 @@ function createAngularSpoosh(instance) {
|
|
|
793
912
|
eventEmitter,
|
|
794
913
|
pluginExecutor
|
|
795
914
|
});
|
|
915
|
+
const injectLazyRead = createInjectLazyRead(
|
|
916
|
+
{
|
|
917
|
+
api,
|
|
918
|
+
stateManager,
|
|
919
|
+
eventEmitter,
|
|
920
|
+
pluginExecutor
|
|
921
|
+
}
|
|
922
|
+
);
|
|
796
923
|
const instanceApiContext = {
|
|
797
924
|
api,
|
|
798
925
|
stateManager,
|
|
@@ -813,6 +940,7 @@ function createAngularSpoosh(instance) {
|
|
|
813
940
|
injectRead,
|
|
814
941
|
injectWrite,
|
|
815
942
|
injectInfiniteRead,
|
|
943
|
+
injectLazyRead,
|
|
816
944
|
...instanceApis
|
|
817
945
|
};
|
|
818
946
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@spoosh/angular",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Angular signals integration for Spoosh API client",
|
|
6
6
|
"keywords": [
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"@angular/core": ">=16.0.0"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
|
-
"@spoosh/core": "0.
|
|
41
|
+
"@spoosh/core": "0.9.0"
|
|
42
42
|
},
|
|
43
43
|
"scripts": {
|
|
44
44
|
"dev": "tsup --watch",
|