@spoosh/angular 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Spoosh
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,229 @@
1
+ # @spoosh/angular
2
+
3
+ Angular signals integration for Spoosh - `injectRead`, `injectWrite`, and `injectInfiniteRead`.
4
+
5
+ **[Documentation](https://spoosh.dev/docs/integrations/angular)** · **Requirements:** TypeScript >= 5.0, Angular >= 16.0
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install @spoosh/core @spoosh/angular
11
+ ```
12
+
13
+ ## Usage
14
+
15
+ ### Setup
16
+
17
+ ```typescript
18
+ import { Spoosh } from "@spoosh/core";
19
+ import { createAngularSpoosh } from "@spoosh/angular";
20
+ import { cachePlugin } from "@spoosh/plugin-cache";
21
+
22
+ const spoosh = new Spoosh<ApiSchema, Error>("/api").use([
23
+ cachePlugin({ staleTime: 5000 }),
24
+ ]);
25
+
26
+ export const { injectRead, injectWrite, injectInfiniteRead } =
27
+ createAngularSpoosh(spoosh);
28
+ ```
29
+
30
+ ### injectRead
31
+
32
+ Fetch data with automatic caching and refetching using Angular signals.
33
+
34
+ ```typescript
35
+ @Component({
36
+ template: `
37
+ @if (users.loading()) {
38
+ <div>Loading...</div>
39
+ } @else if (users.error()) {
40
+ <div>Error: {{ users.error()?.message }}</div>
41
+ } @else {
42
+ <ul>
43
+ @for (user of users.data(); track user.id) {
44
+ <li>{{ user.name }}</li>
45
+ }
46
+ </ul>
47
+ }
48
+ `,
49
+ })
50
+ export class UserListComponent {
51
+ users = injectRead((api) => api.users.$get());
52
+ }
53
+
54
+ // With options
55
+ @Component({ ... })
56
+ export class UserListComponent {
57
+ isReady = signal(false);
58
+
59
+ // Recommended: Pass signal directly (shorter syntax)
60
+ users = injectRead(
61
+ (api) => api.users.$get({ query: { page: 1 } }),
62
+ {
63
+ staleTime: 10000,
64
+ enabled: this.isReady,
65
+ }
66
+ );
67
+
68
+ // Also works: Arrow function wrapper
69
+ // enabled: () => this.isReady(),
70
+ }
71
+ ```
72
+
73
+ ### injectWrite
74
+
75
+ Trigger mutations with loading and error states.
76
+
77
+ ```typescript
78
+ @Component({
79
+ template: `
80
+ <form (ngSubmit)="handleSubmit()">
81
+ <input [(ngModel)]="title" />
82
+ <button [disabled]="createUser.loading()">
83
+ {{ createUser.loading() ? "Creating..." : "Create User" }}
84
+ </button>
85
+ </form>
86
+ `,
87
+ })
88
+ export class CreateUserComponent {
89
+ title = signal("");
90
+
91
+ createUser = injectWrite((api) => api.users.$post);
92
+
93
+ async handleSubmit() {
94
+ const result = await this.createUser.trigger({
95
+ body: { name: this.title() },
96
+ });
97
+
98
+ if (result.data) {
99
+ // Success
100
+ }
101
+ }
102
+ }
103
+ ```
104
+
105
+ ### injectInfiniteRead
106
+
107
+ Bidirectional paginated data fetching with infinite scroll support.
108
+
109
+ ```typescript
110
+ @Component({
111
+ template: `
112
+ @if (posts.canFetchPrev()) {
113
+ <button (click)="posts.fetchPrev()" [disabled]="posts.fetchingPrev()">
114
+ {{ posts.fetchingPrev() ? "Loading..." : "Load Previous" }}
115
+ </button>
116
+ }
117
+
118
+ @for (post of posts.data(); track post.id) {
119
+ <app-post-card [post]="post" />
120
+ }
121
+
122
+ @if (posts.canFetchNext()) {
123
+ <button (click)="posts.fetchNext()" [disabled]="posts.fetchingNext()">
124
+ {{ posts.fetchingNext() ? "Loading..." : "Load More" }}
125
+ </button>
126
+ }
127
+ `,
128
+ })
129
+ export class PostListComponent {
130
+ posts = injectInfiniteRead((api) => api.posts.$get({ query: { page: 1 } }), {
131
+ // Required: Check if next page exists
132
+ canFetchNext: ({ response }) => response?.meta.hasMore ?? false,
133
+
134
+ // Required: Build request for next page
135
+ nextPageRequest: ({ response, request }) => ({
136
+ query: { ...request.query, page: (response?.meta.page ?? 0) + 1 },
137
+ }),
138
+
139
+ // Required: Merge all responses into items
140
+ merger: (allResponses) => allResponses.flatMap((r) => r.items),
141
+
142
+ // Optional: Check if previous page exists
143
+ canFetchPrev: ({ response }) => (response?.meta.page ?? 1) > 1,
144
+
145
+ // Optional: Build request for previous page
146
+ prevPageRequest: ({ response, request }) => ({
147
+ query: { ...request.query, page: (response?.meta.page ?? 2) - 1 },
148
+ }),
149
+ });
150
+ }
151
+ ```
152
+
153
+ ## API Reference
154
+
155
+ ### injectRead(readFn, options?)
156
+
157
+ | Option | Type | Default | Description |
158
+ | ---------------- | --------------------------------------------- | ------- | ------------------------------------ |
159
+ | `enabled` | `boolean \| Signal<boolean> \| () => boolean` | `true` | Whether to fetch automatically |
160
+ | `staleTime` | `number` | - | Cache stale time (from plugin-cache) |
161
+ | `retries` | `number` | - | Retry attempts (from plugin-retry) |
162
+ | + plugin options | - | - | Options from installed plugins |
163
+
164
+ **Returns:**
165
+
166
+ | Property | Type | Description |
167
+ | ---------- | ----------------------------- | ----------------------------------------- |
168
+ | `data` | `Signal<TData \| undefined>` | Response data |
169
+ | `error` | `Signal<TError \| undefined>` | Error if request failed |
170
+ | `loading` | `Signal<boolean>` | True during initial load |
171
+ | `fetching` | `Signal<boolean>` | True during any fetch |
172
+ | `meta` | `Signal<PluginResults>` | Plugin metadata (e.g., `transformedData`) |
173
+ | `refetch` | `() => Promise` | Manually trigger refetch |
174
+ | `abort` | `() => void` | Abort current request |
175
+
176
+ ### injectWrite(writeFn)
177
+
178
+ **Returns:**
179
+
180
+ | Property | Type | Description |
181
+ | --------- | ----------------------------- | ---------------------------------- |
182
+ | `trigger` | `(options) => Promise` | Execute the mutation |
183
+ | `data` | `Signal<TData \| undefined>` | Response data |
184
+ | `error` | `Signal<TError \| undefined>` | Error if request failed |
185
+ | `loading` | `Signal<boolean>` | True while mutation is in progress |
186
+ | `meta` | `Signal<PluginResults>` | Plugin metadata |
187
+ | `input` | `TriggerOptions \| undefined` | Last trigger input |
188
+ | `reset` | `() => void` | Reset state |
189
+ | `abort` | `() => void` | Abort current request |
190
+
191
+ ### injectInfiniteRead(readFn, options)
192
+
193
+ | Option | Type | Required | Description |
194
+ | ----------------- | --------------------------------------------- | -------- | ------------------------------- |
195
+ | `canFetchNext` | `(ctx) => boolean` | Yes | Check if next page exists |
196
+ | `nextPageRequest` | `(ctx) => Partial<TRequest>` | Yes | Build request for next page |
197
+ | `merger` | `(allResponses) => TItem[]` | Yes | Merge all responses into items |
198
+ | `canFetchPrev` | `(ctx) => boolean` | No | Check if previous page exists |
199
+ | `prevPageRequest` | `(ctx) => Partial<TRequest>` | No | Build request for previous page |
200
+ | `enabled` | `boolean \| Signal<boolean> \| () => boolean` | No | Whether to fetch automatically |
201
+
202
+ **Context object passed to callbacks:**
203
+
204
+ ```typescript
205
+ type Context<TData, TRequest> = {
206
+ response: TData | undefined; // Latest response
207
+ allResponses: TData[]; // All fetched responses
208
+ request: TRequest; // Current request options
209
+ };
210
+ ```
211
+
212
+ **Returns:**
213
+
214
+ | Property | Type | Description |
215
+ | -------------- | ------------------------------ | ------------------------------- |
216
+ | `data` | `Signal<TItem[] \| undefined>` | Merged items from all responses |
217
+ | `allResponses` | `Signal<TData[] \| undefined>` | Array of all raw responses |
218
+ | `loading` | `Signal<boolean>` | True during initial load |
219
+ | `fetching` | `Signal<boolean>` | True during any fetch |
220
+ | `fetchingNext` | `Signal<boolean>` | True while fetching next page |
221
+ | `fetchingPrev` | `Signal<boolean>` | True while fetching previous |
222
+ | `canFetchNext` | `Signal<boolean>` | Whether next page exists |
223
+ | `canFetchPrev` | `Signal<boolean>` | Whether previous page exists |
224
+ | `meta` | `Signal<PluginResults>` | Plugin metadata |
225
+ | `fetchNext` | `() => Promise<void>` | Fetch the next page |
226
+ | `fetchPrev` | `() => Promise<void>` | Fetch the previous page |
227
+ | `refetch` | `() => Promise<void>` | Refetch all pages |
228
+ | `abort` | `() => void` | Abort current request |
229
+ | `error` | `Signal<TError \| undefined>` | Error if request failed |
@@ -0,0 +1,358 @@
1
+ import * as _spoosh_core from '@spoosh/core';
2
+ import { PluginArray, StateManager, EventEmitter, PluginExecutor, QueryOnlyClient, MethodOptionsMap, CoreRequestOptionsBase, SpooshResponse, MutationOnlyClient, SpooshPlugin, PluginTypeConfig, InfiniteRequestOptions, ResolveTypes, ResolverContext, ResolveResultTypes, MergePluginInstanceApi } from '@spoosh/core';
3
+ import { Signal } from '@angular/core';
4
+
5
+ interface SpooshInstanceShape<TApi, TSchema, TDefaultError, TPlugins extends PluginArray> {
6
+ api: TApi;
7
+ stateManager: StateManager;
8
+ eventEmitter: EventEmitter;
9
+ pluginExecutor: PluginExecutor;
10
+ _types: {
11
+ schema: TSchema;
12
+ defaultError: TDefaultError;
13
+ plugins: TPlugins;
14
+ };
15
+ }
16
+ type EnabledOption = boolean | (() => boolean);
17
+ interface BaseReadOptions {
18
+ enabled?: EnabledOption;
19
+ tags?: string[];
20
+ additionalTags?: string[];
21
+ }
22
+ interface BaseReadResult<TData, TError, TPluginResult = Record<string, unknown>> {
23
+ data: Signal<TData | undefined>;
24
+ error: Signal<TError | undefined>;
25
+ loading: Signal<boolean>;
26
+ fetching: Signal<boolean>;
27
+ meta: Signal<TPluginResult>;
28
+ abort: () => void;
29
+ refetch: () => Promise<SpooshResponse<TData, TError>>;
30
+ }
31
+ interface BaseWriteResult<TData, TError, TOptions, TPluginResult = Record<string, unknown>> {
32
+ trigger: (options?: TOptions) => Promise<SpooshResponse<TData, TError>>;
33
+ data: Signal<TData | undefined>;
34
+ error: Signal<TError | undefined>;
35
+ loading: Signal<boolean>;
36
+ meta: Signal<TPluginResult>;
37
+ reset: () => void;
38
+ abort: () => void;
39
+ }
40
+ type PageContext<TData, TRequest> = {
41
+ response: TData | undefined;
42
+ allResponses: TData[];
43
+ request: TRequest;
44
+ };
45
+ interface BaseInfiniteReadOptions<TData, TItem, TRequest> extends BaseReadOptions {
46
+ canFetchNext: (ctx: PageContext<TData, TRequest>) => boolean;
47
+ canFetchPrev?: (ctx: PageContext<TData, TRequest>) => boolean;
48
+ nextPageRequest: (ctx: PageContext<TData, TRequest>) => Partial<TRequest>;
49
+ prevPageRequest?: (ctx: PageContext<TData, TRequest>) => Partial<TRequest>;
50
+ merger: (responses: TData[]) => TItem[];
51
+ }
52
+ interface BaseInfiniteReadResult<TData, TError, TItem, TPluginResult = Record<string, unknown>> {
53
+ data: Signal<TItem[] | undefined>;
54
+ allResponses: Signal<TData[] | undefined>;
55
+ error: Signal<TError | undefined>;
56
+ loading: Signal<boolean>;
57
+ fetching: Signal<boolean>;
58
+ fetchingNext: Signal<boolean>;
59
+ fetchingPrev: Signal<boolean>;
60
+ canFetchNext: Signal<boolean>;
61
+ canFetchPrev: Signal<boolean>;
62
+ meta: Signal<TPluginResult>;
63
+ fetchNext: () => Promise<void>;
64
+ fetchPrev: () => Promise<void>;
65
+ refetch: () => Promise<void>;
66
+ abort: () => void;
67
+ }
68
+ type QueryRequestOptions = CoreRequestOptionsBase;
69
+ type MutationRequestOptions = CoreRequestOptionsBase;
70
+ type AngularOptionsMap = MethodOptionsMap<QueryRequestOptions, MutationRequestOptions>;
71
+ type ReadApiClient<TSchema, TDefaultError> = QueryOnlyClient<TSchema, TDefaultError, AngularOptionsMap>;
72
+ type WriteApiClient<TSchema, TDefaultError> = MutationOnlyClient<TSchema, TDefaultError, AngularOptionsMap>;
73
+ type QueryField<TQuery> = [TQuery] extends [never] ? object : {
74
+ query: TQuery;
75
+ };
76
+ type BodyField<TBody> = [TBody] extends [never] ? object : {
77
+ body: TBody;
78
+ };
79
+ type FormDataField<TFormData> = [TFormData] extends [never] ? object : {
80
+ formData: TFormData;
81
+ };
82
+ type ParamsField<TParamNames extends string> = [TParamNames] extends [never] ? object : {
83
+ params: Record<TParamNames, string | number>;
84
+ };
85
+ type ReadInputFields<TQuery, TBody, TFormData, TParamNames extends string> = QueryField<TQuery> & BodyField<TBody> & FormDataField<TFormData> & ParamsField<TParamNames>;
86
+ type ResponseInputFields<TQuery, TBody, TFormData, TParamNames extends string> = [TQuery, TBody, TFormData, TParamNames] extends [never, never, never, never] ? object : {
87
+ input: ReadInputFields<TQuery, TBody, TFormData, TParamNames>;
88
+ };
89
+ type OptionalQueryField<TQuery> = [TQuery] extends [never] ? object : {
90
+ query: TQuery;
91
+ };
92
+ type OptionalBodyField<TBody> = [TBody] extends [never] ? object : {
93
+ body: TBody;
94
+ };
95
+ type OptionalFormDataField<TFormData> = [TFormData] extends [never] ? object : {
96
+ formData: TFormData;
97
+ };
98
+ type OptionalParamsField<TParamNames extends string> = [TParamNames] extends [
99
+ never
100
+ ] ? object : {
101
+ params: Record<TParamNames, string | number>;
102
+ };
103
+ type InputFields<TQuery, TBody, TFormData, TParamNames extends string> = OptionalQueryField<TQuery> & OptionalBodyField<TBody> & OptionalFormDataField<TFormData> & OptionalParamsField<TParamNames>;
104
+ type WriteResponseInputFields<TQuery, TBody, TFormData, TParamNames extends string> = [TQuery, TBody, TFormData, TParamNames] extends [never, never, never, never] ? object : {
105
+ input: Signal<InputFields<TQuery, TBody, TFormData, TParamNames> | undefined>;
106
+ };
107
+ type SuccessResponse<T> = Extract<T, {
108
+ data: unknown;
109
+ error?: undefined;
110
+ }>;
111
+ type ErrorResponse<T> = Extract<T, {
112
+ error: unknown;
113
+ data?: undefined;
114
+ }>;
115
+ type ExtractMethodData<T> = T extends (...args: never[]) => infer R ? SuccessResponse<Awaited<R>> extends {
116
+ data: infer D;
117
+ } ? D : unknown : unknown;
118
+ type ExtractMethodError<T> = T extends (...args: never[]) => infer R ? ErrorResponse<Awaited<R>> extends {
119
+ error: infer E;
120
+ } ? E : unknown : unknown;
121
+ type ExtractMethodOptions<T> = T extends (options?: infer O) => Promise<unknown> ? O : never;
122
+ type AwaitedReturnType<T> = T extends (...args: never[]) => infer R ? Awaited<R> : never;
123
+ type SuccessReturnType<T> = SuccessResponse<AwaitedReturnType<T>>;
124
+ type ExtractResponseQuery<T> = SuccessReturnType<T> extends {
125
+ input: {
126
+ query: infer Q;
127
+ };
128
+ } ? Q : never;
129
+ type ExtractResponseBody<T> = SuccessReturnType<T> extends {
130
+ input: {
131
+ body: infer B;
132
+ };
133
+ } ? B : never;
134
+ type ExtractResponseFormData<T> = SuccessReturnType<T> extends {
135
+ input: {
136
+ formData: infer F;
137
+ };
138
+ } ? F : never;
139
+ type ExtractResponseParamNames<T> = SuccessReturnType<T> extends {
140
+ input: {
141
+ params: Record<infer K, unknown>;
142
+ };
143
+ } ? K extends string ? K : never : never;
144
+ type ExtractMethodQuery<T> = ExtractMethodOptions<T> extends {
145
+ query: infer Q;
146
+ } ? Q : never;
147
+ type ExtractMethodBody<T> = ExtractMethodOptions<T> extends {
148
+ body: infer B;
149
+ } ? B : never;
150
+ type ExtractMethodFormData<T> = ExtractMethodOptions<T> extends {
151
+ formData: infer F;
152
+ } ? F : never;
153
+ type ExtractMethodUrlEncoded<T> = ExtractMethodOptions<T> extends {
154
+ urlEncoded: infer U;
155
+ } ? U : never;
156
+
157
+ type AnyInfiniteRequestOptions = InfiniteRequestOptions;
158
+ 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, TReadOpts extends BaseInfiniteReadOptions<TReadFn extends (...args: never[]) => infer R ? Extract<Awaited<R>, {
159
+ data: unknown;
160
+ error?: undefined;
161
+ }> extends {
162
+ data: infer D;
163
+ } ? D : unknown : unknown, unknown, 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 {
164
+ readOptions: infer R_3;
165
+ } ? 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 {
166
+ readOptions: infer R_3;
167
+ } ? R_3 : object : object : never : never) ? T_4 extends unknown ? (x: T_4) => void : never : never : never) extends (x: infer I_1) => void ? I_1 : never, ResolverContext<TSchema, TReadFn extends (...args: never[]) => infer R ? Extract<Awaited<R>, {
168
+ data: unknown;
169
+ error?: undefined;
170
+ }> extends {
171
+ data: infer D;
172
+ } ? D : unknown : unknown, [TReadFn extends (...args: never[]) => infer R_1 ? Extract<Awaited<R_1>, {
173
+ error: unknown;
174
+ data?: undefined;
175
+ }> extends {
176
+ error: infer E;
177
+ } ? E : unknown : unknown] extends [unknown] ? TDefaultError : TReadFn extends (...args: never[]) => infer R_1 ? Extract<Awaited<R_1>, {
178
+ error: unknown;
179
+ data?: undefined;
180
+ }> extends {
181
+ error: infer E;
182
+ } ? E : unknown : unknown>> = BaseInfiniteReadOptions<TReadFn extends (...args: never[]) => infer R ? Extract<Awaited<R>, {
183
+ data: unknown;
184
+ error?: undefined;
185
+ }> extends {
186
+ data: infer D;
187
+ } ? D : unknown : unknown, unknown, TRequest> & ResolveTypes<((TPlugins[number] extends infer T_6 ? T_6 extends TPlugins[number] ? T_6 extends SpooshPlugin<infer Types_1 extends PluginTypeConfig> ? Types_1 extends {
188
+ readOptions: infer R_3;
189
+ } ? R_3 : object : object : never : never) extends infer T_7 ? T_7 extends (TPlugins[number] extends infer T_8 ? T_8 extends TPlugins[number] ? T_8 extends SpooshPlugin<infer Types_1 extends PluginTypeConfig> ? Types_1 extends {
190
+ readOptions: infer R_3;
191
+ } ? R_3 : object : object : never : never) ? T_7 extends unknown ? (x: T_7) => void : never : never : never) extends (x: infer I_1) => void ? I_1 : never, ResolverContext<TSchema, TReadFn extends (...args: never[]) => infer R ? Extract<Awaited<R>, {
192
+ data: unknown;
193
+ error?: undefined;
194
+ }> extends {
195
+ data: infer D;
196
+ } ? D : unknown : unknown, [TReadFn extends (...args: never[]) => infer R_1 ? Extract<Awaited<R_1>, {
197
+ error: unknown;
198
+ data?: undefined;
199
+ }> extends {
200
+ error: infer E;
201
+ } ? E : unknown : unknown] extends [unknown] ? TDefaultError : TReadFn extends (...args: never[]) => infer R_1 ? Extract<Awaited<R_1>, {
202
+ error: unknown;
203
+ data?: undefined;
204
+ }> extends {
205
+ error: infer E;
206
+ } ? E : unknown : unknown>>>(readFn: TReadFn, readOptions: TReadOpts) => BaseInfiniteReadResult<TReadFn extends (...args: never[]) => infer R ? Extract<Awaited<R>, {
207
+ data: unknown;
208
+ error?: undefined;
209
+ }> extends {
210
+ data: infer D;
211
+ } ? D : unknown : unknown, [TReadFn extends (...args: never[]) => infer R_1 ? Extract<Awaited<R_1>, {
212
+ error: unknown;
213
+ data?: undefined;
214
+ }> extends {
215
+ error: infer E;
216
+ } ? E : unknown : unknown] extends [unknown] ? TDefaultError : TReadFn extends (...args: never[]) => infer R_1 ? Extract<Awaited<R_1>, {
217
+ error: unknown;
218
+ data?: undefined;
219
+ }> extends {
220
+ error: infer E;
221
+ } ? E : unknown : unknown, TReadOpts extends {
222
+ merger: (...args: never[]) => (infer I)[];
223
+ } ? I : unknown, ResolveResultTypes<((TPlugins[number] extends infer T ? T extends TPlugins[number] ? T extends SpooshPlugin<infer Types extends PluginTypeConfig> ? Types extends {
224
+ readResult: infer R_2;
225
+ } ? 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 {
226
+ readResult: infer R_2;
227
+ } ? R_2 : object : object : never : never) ? T_1 extends unknown ? (x: T_1) => void : never : never : never) extends (x: infer I_1) => void ? I_1 : never, TReadOpts>>;
228
+
229
+ 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 {
230
+ writeOptions: infer W_1;
231
+ } ? 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 {
232
+ writeOptions: infer W_1;
233
+ } ? W_1 : object : object : never : never) ? T_4 extends unknown ? (x: T_4) => void : never : never : never) extends (x: infer I) => void ? I : never, ResolverContext<TSchema, TMethod extends (...args: never[]) => infer R ? Extract<Awaited<R>, {
234
+ data: unknown;
235
+ error?: undefined;
236
+ }> extends {
237
+ data: infer D;
238
+ } ? D : unknown : unknown, [TMethod extends (...args: never[]) => infer R_1 ? Extract<Awaited<R_1>, {
239
+ error: unknown;
240
+ data?: undefined;
241
+ }> extends {
242
+ error: infer E;
243
+ } ? E : unknown : unknown] extends [unknown] ? TDefaultError : TMethod extends (...args: never[]) => infer R_1 ? Extract<Awaited<R_1>, {
244
+ error: unknown;
245
+ data?: undefined;
246
+ }> extends {
247
+ error: infer E;
248
+ } ? E : unknown : unknown, ExtractMethodQuery<TMethod>, ExtractMethodBody<TMethod>, ExtractResponseParamNames<TMethod> extends never ? never : Record<ExtractResponseParamNames<TMethod>, string | number>, ExtractMethodFormData<TMethod>, never>> = (TMethod extends (...args: infer A) => unknown ? A[0] : never) & _spoosh_core.ResolveTypes<((TPlugins[number] extends infer T_6 ? T_6 extends TPlugins[number] ? T_6 extends SpooshPlugin<infer Types_1 extends PluginTypeConfig> ? Types_1 extends {
249
+ writeOptions: infer W_1;
250
+ } ? W_1 : object : object : never : never) extends infer T_7 ? T_7 extends (TPlugins[number] extends infer T_8 ? T_8 extends TPlugins[number] ? T_8 extends SpooshPlugin<infer Types_1 extends PluginTypeConfig> ? Types_1 extends {
251
+ writeOptions: infer W_1;
252
+ } ? W_1 : object : object : never : never) ? T_7 extends unknown ? (x: T_7) => void : never : never : never) extends (x: infer I) => void ? I : never, ResolverContext<TSchema, TMethod extends (...args: never[]) => infer R ? Extract<Awaited<R>, {
253
+ data: unknown;
254
+ error?: undefined;
255
+ }> extends {
256
+ data: infer D;
257
+ } ? D : unknown : unknown, [TMethod extends (...args: never[]) => infer R_1 ? Extract<Awaited<R_1>, {
258
+ error: unknown;
259
+ data?: undefined;
260
+ }> extends {
261
+ error: infer E;
262
+ } ? E : unknown : unknown] extends [unknown] ? TDefaultError : TMethod extends (...args: never[]) => infer R_1 ? Extract<Awaited<R_1>, {
263
+ error: unknown;
264
+ data?: undefined;
265
+ }> extends {
266
+ error: infer E;
267
+ } ? E : unknown : unknown, ExtractMethodQuery<TMethod>, ExtractMethodBody<TMethod>, ExtractResponseParamNames<TMethod> extends never ? never : Record<ExtractResponseParamNames<TMethod>, string | number>, ExtractMethodFormData<TMethod>, never>>>(writeFn: (api: WriteApiClient<TSchema, TDefaultError>) => TMethod) => BaseWriteResult<TMethod extends (...args: never[]) => infer R ? Extract<Awaited<R>, {
268
+ data: unknown;
269
+ error?: undefined;
270
+ }> extends {
271
+ data: infer D;
272
+ } ? D : unknown : unknown, [TMethod extends (...args: never[]) => infer R_1 ? Extract<Awaited<R_1>, {
273
+ error: unknown;
274
+ data?: undefined;
275
+ }> extends {
276
+ error: infer E;
277
+ } ? E : unknown : unknown] extends [unknown] ? TDefaultError : TMethod extends (...args: never[]) => infer R_1 ? Extract<Awaited<R_1>, {
278
+ error: unknown;
279
+ data?: undefined;
280
+ }> extends {
281
+ error: infer E;
282
+ } ? E : unknown : unknown, TWriteOpts, ResolveResultTypes<((TPlugins[number] extends infer T ? T extends TPlugins[number] ? T extends SpooshPlugin<infer Types extends PluginTypeConfig> ? Types extends {
283
+ writeResult: infer W;
284
+ } ? W : object : object : never : never) extends infer T_1 ? T_1 extends (TPlugins[number] extends infer T_2 ? T_2 extends TPlugins[number] ? T_2 extends SpooshPlugin<infer Types extends PluginTypeConfig> ? Types extends {
285
+ writeResult: infer W;
286
+ } ? W : object : object : never : never) ? T_1 extends unknown ? (x: T_1) => void : never : never : never) extends (x: infer I) => void ? I : never, TWriteOpts>> & WriteResponseInputFields<ExtractResponseQuery<TMethod>, ExtractResponseBody<TMethod>, ExtractResponseFormData<TMethod>, ExtractResponseParamNames<TMethod>>;
287
+
288
+ 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<{
289
+ data?: unknown;
290
+ error?: unknown;
291
+ }>, TReadOpts extends BaseReadOptions & ResolveTypes<((TPlugins[number] extends infer T_3 ? T_3 extends TPlugins[number] ? T_3 extends SpooshPlugin<infer Types_1 extends PluginTypeConfig> ? Types_1 extends {
292
+ readOptions: infer R_3;
293
+ } ? 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 {
294
+ readOptions: infer R_3;
295
+ } ? 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>, {
296
+ data: unknown;
297
+ error?: undefined;
298
+ }> extends {
299
+ data: infer D;
300
+ } ? D : unknown : unknown, [TReadFn extends (...args: never[]) => infer R_1 ? Extract<Awaited<R_1>, {
301
+ error: unknown;
302
+ data?: undefined;
303
+ }> extends {
304
+ error: infer E;
305
+ } ? E : unknown : unknown] extends [unknown] ? TDefaultError : TReadFn extends (...args: never[]) => infer R_1 ? Extract<Awaited<R_1>, {
306
+ error: unknown;
307
+ data?: undefined;
308
+ }> extends {
309
+ error: infer E;
310
+ } ? E : unknown : unknown>> = BaseReadOptions & ResolveTypes<((TPlugins[number] extends infer T_6 ? T_6 extends TPlugins[number] ? T_6 extends SpooshPlugin<infer Types_1 extends PluginTypeConfig> ? Types_1 extends {
311
+ readOptions: infer R_3;
312
+ } ? R_3 : object : object : never : never) extends infer T_7 ? T_7 extends (TPlugins[number] extends infer T_8 ? T_8 extends TPlugins[number] ? T_8 extends SpooshPlugin<infer Types_1 extends PluginTypeConfig> ? Types_1 extends {
313
+ readOptions: infer R_3;
314
+ } ? R_3 : object : object : never : never) ? T_7 extends unknown ? (x: T_7) => void : never : never : never) extends (x: infer I) => void ? I : never, ResolverContext<TSchema, TReadFn extends (...args: never[]) => infer R ? Extract<Awaited<R>, {
315
+ data: unknown;
316
+ error?: undefined;
317
+ }> extends {
318
+ data: infer D;
319
+ } ? D : unknown : unknown, [TReadFn extends (...args: never[]) => infer R_1 ? Extract<Awaited<R_1>, {
320
+ error: unknown;
321
+ data?: undefined;
322
+ }> extends {
323
+ error: infer E;
324
+ } ? E : unknown : unknown] extends [unknown] ? TDefaultError : TReadFn extends (...args: never[]) => infer R_1 ? Extract<Awaited<R_1>, {
325
+ error: unknown;
326
+ data?: undefined;
327
+ }> extends {
328
+ error: infer E;
329
+ } ? E : unknown : unknown>>>(readFn: TReadFn, readOptions?: TReadOpts) => BaseReadResult<TReadFn extends (...args: never[]) => infer R ? Extract<Awaited<R>, {
330
+ data: unknown;
331
+ error?: undefined;
332
+ }> extends {
333
+ data: infer D;
334
+ } ? D : unknown : unknown, [TReadFn extends (...args: never[]) => infer R_1 ? Extract<Awaited<R_1>, {
335
+ error: unknown;
336
+ data?: undefined;
337
+ }> extends {
338
+ error: infer E;
339
+ } ? E : unknown : unknown] extends [unknown] ? TDefaultError : TReadFn extends (...args: never[]) => infer R_1 ? Extract<Awaited<R_1>, {
340
+ error: unknown;
341
+ data?: undefined;
342
+ }> extends {
343
+ error: infer E;
344
+ } ? E : unknown : unknown, ResolveResultTypes<((TPlugins[number] extends infer T ? T extends TPlugins[number] ? T extends SpooshPlugin<infer Types extends PluginTypeConfig> ? Types extends {
345
+ readResult: infer R_2;
346
+ } ? 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 {
347
+ readResult: infer R_2;
348
+ } ? R_2 : object : object : never : never) ? T_1 extends unknown ? (x: T_1) => void : never : never : never) extends (x: infer I) => void ? I : never, TReadOpts>> & ResponseInputFields<ExtractResponseQuery<TReadFn>, ExtractResponseBody<TReadFn>, ExtractResponseFormData<TReadFn>, ExtractResponseParamNames<TReadFn>>;
349
+
350
+ type SpooshAngularFunctions<TDefaultError, TSchema, TPlugins extends PluginArray> = {
351
+ injectRead: ReturnType<typeof createInjectRead<TSchema, TDefaultError, TPlugins>>;
352
+ injectWrite: ReturnType<typeof createInjectWrite<TSchema, TDefaultError, TPlugins>>;
353
+ injectInfiniteRead: ReturnType<typeof createInjectInfiniteRead<TSchema, TDefaultError, TPlugins>>;
354
+ } & MergePluginInstanceApi<TPlugins, TSchema>;
355
+
356
+ declare function createAngularSpoosh<TSchema, TDefaultError, TPlugins extends PluginArray, TApi>(instance: SpooshInstanceShape<TApi, TSchema, TDefaultError, TPlugins>): SpooshAngularFunctions<TDefaultError, TSchema, TPlugins>;
357
+
358
+ export { type AngularOptionsMap, type BaseInfiniteReadOptions, type BaseInfiniteReadResult, type BaseReadOptions, type BaseReadResult, type BaseWriteResult, type EnabledOption, type ExtractMethodBody, type ExtractMethodData, type ExtractMethodError, type ExtractMethodFormData, type ExtractMethodOptions, type ExtractMethodQuery, type ExtractMethodUrlEncoded, type ExtractResponseBody, type ExtractResponseFormData, type ExtractResponseParamNames, type ExtractResponseQuery, type PageContext, type ReadApiClient, type ResponseInputFields, type SpooshInstanceShape, type WriteApiClient, type WriteResponseInputFields, createAngularSpoosh };