@spoosh/react 0.1.0-beta.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 +21 -0
- package/README.md +222 -0
- package/dist/index.d.mts +411 -0
- package/dist/index.d.ts +411 -0
- package/dist/index.js +549 -0
- package/dist/index.mjs +555 -0
- package/package.json +49 -0
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,222 @@
|
|
|
1
|
+
# @spoosh/react
|
|
2
|
+
|
|
3
|
+
React hooks for Spoosh - `useRead`, `useWrite`, and `useInfiniteRead`.
|
|
4
|
+
|
|
5
|
+
**[Documentation](https://spoosh.dev/docs/integrations/react)** · **Requirements:** TypeScript >= 5.0, React >= 18.0
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @spoosh/core @spoosh/react
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
### Setup
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
import { createSpoosh } from "@spoosh/core";
|
|
19
|
+
import { createReactSpoosh } from "@spoosh/react";
|
|
20
|
+
import { cachePlugin } from "@spoosh/plugin-cache";
|
|
21
|
+
|
|
22
|
+
const plugins = [cachePlugin({ staleTime: 5000 })];
|
|
23
|
+
|
|
24
|
+
const client = createSpoosh<ApiSchema, Error, typeof plugins>({
|
|
25
|
+
baseUrl: "/api",
|
|
26
|
+
plugins,
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
export const { useRead, useWrite, useInfiniteRead } = createReactSpoosh(client);
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### useRead
|
|
33
|
+
|
|
34
|
+
Fetch data with automatic caching and refetching.
|
|
35
|
+
|
|
36
|
+
```typescript
|
|
37
|
+
function UserList() {
|
|
38
|
+
const { data, loading, error, refetch } = useRead(
|
|
39
|
+
(api) => api.users.$get()
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
if (loading) return <div>Loading...</div>;
|
|
43
|
+
if (error) return <div>Error: {error.message}</div>;
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
<ul>
|
|
47
|
+
{data?.map((user) => <li key={user.id}>{user.name}</li>)}
|
|
48
|
+
</ul>
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// With options
|
|
53
|
+
const { data } = useRead(
|
|
54
|
+
(api) => api.users.$get({ query: { page: 1 } }),
|
|
55
|
+
{
|
|
56
|
+
staleTime: 10000,
|
|
57
|
+
enabled: isReady,
|
|
58
|
+
}
|
|
59
|
+
);
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### useWrite
|
|
63
|
+
|
|
64
|
+
Trigger mutations with loading and error states.
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
function CreateUser() {
|
|
68
|
+
const { trigger, loading, error } = useWrite(
|
|
69
|
+
(api) => api.users.$post
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
const handleSubmit = async (data: CreateUserBody) => {
|
|
73
|
+
const result = await trigger({ body: data });
|
|
74
|
+
if (result.data) {
|
|
75
|
+
// Success
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
return (
|
|
80
|
+
<form onSubmit={handleSubmit}>
|
|
81
|
+
{/* form fields */}
|
|
82
|
+
<button disabled={loading}>
|
|
83
|
+
{loading ? "Creating..." : "Create User"}
|
|
84
|
+
</button>
|
|
85
|
+
</form>
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### useInfiniteRead
|
|
91
|
+
|
|
92
|
+
Bidirectional paginated data fetching with infinite scroll support.
|
|
93
|
+
|
|
94
|
+
```typescript
|
|
95
|
+
function PostList() {
|
|
96
|
+
const {
|
|
97
|
+
data,
|
|
98
|
+
allResponses,
|
|
99
|
+
loading,
|
|
100
|
+
canFetchNext,
|
|
101
|
+
canFetchPrev,
|
|
102
|
+
fetchNext,
|
|
103
|
+
fetchPrev,
|
|
104
|
+
fetchingNext,
|
|
105
|
+
fetchingPrev,
|
|
106
|
+
} = useInfiniteRead(
|
|
107
|
+
(api) => api.posts.$get({ query: { page: 1 } }),
|
|
108
|
+
{
|
|
109
|
+
// Required: Check if next page exists
|
|
110
|
+
canFetchNext: ({ response }) => response?.meta.hasMore ?? false,
|
|
111
|
+
|
|
112
|
+
// Required: Build request for next page
|
|
113
|
+
nextPageRequest: ({ response, request }) => ({
|
|
114
|
+
query: { ...request.query, page: (response?.meta.page ?? 0) + 1 },
|
|
115
|
+
}),
|
|
116
|
+
|
|
117
|
+
// Required: Merge all responses into items
|
|
118
|
+
merger: (allResponses) => allResponses.flatMap((r) => r.items),
|
|
119
|
+
|
|
120
|
+
// Optional: Check if previous page exists
|
|
121
|
+
canFetchPrev: ({ response }) => (response?.meta.page ?? 1) > 1,
|
|
122
|
+
|
|
123
|
+
// Optional: Build request for previous page
|
|
124
|
+
prevPageRequest: ({ response, request }) => ({
|
|
125
|
+
query: { ...request.query, page: (response?.meta.page ?? 2) - 1 },
|
|
126
|
+
}),
|
|
127
|
+
}
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
return (
|
|
131
|
+
<div>
|
|
132
|
+
{canFetchPrev && (
|
|
133
|
+
<button onClick={fetchPrev} disabled={fetchingPrev}>
|
|
134
|
+
{fetchingPrev ? "Loading..." : "Load Previous"}
|
|
135
|
+
</button>
|
|
136
|
+
)}
|
|
137
|
+
|
|
138
|
+
{data?.map((post) => <PostCard key={post.id} post={post} />)}
|
|
139
|
+
|
|
140
|
+
{canFetchNext && (
|
|
141
|
+
<button onClick={fetchNext} disabled={fetchingNext}>
|
|
142
|
+
{fetchingNext ? "Loading..." : "Load More"}
|
|
143
|
+
</button>
|
|
144
|
+
)}
|
|
145
|
+
</div>
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## API Reference
|
|
151
|
+
|
|
152
|
+
### useRead(readFn, options?)
|
|
153
|
+
|
|
154
|
+
| Option | Type | Default | Description |
|
|
155
|
+
| ---------------- | --------- | ------- | ------------------------------------ |
|
|
156
|
+
| `enabled` | `boolean` | `true` | Whether to fetch automatically |
|
|
157
|
+
| `staleTime` | `number` | - | Cache stale time (from plugin-cache) |
|
|
158
|
+
| `retries` | `number` | - | Retry attempts (from plugin-retry) |
|
|
159
|
+
| + plugin options | - | - | Options from installed plugins |
|
|
160
|
+
|
|
161
|
+
**Returns:**
|
|
162
|
+
|
|
163
|
+
| Property | Type | Description |
|
|
164
|
+
| ---------- | --------------------- | ------------------------ |
|
|
165
|
+
| `data` | `TData \| undefined` | Response data |
|
|
166
|
+
| `error` | `TError \| undefined` | Error if request failed |
|
|
167
|
+
| `loading` | `boolean` | True during initial load |
|
|
168
|
+
| `fetching` | `boolean` | True during any fetch |
|
|
169
|
+
| `refetch` | `() => Promise` | Manually trigger refetch |
|
|
170
|
+
| `abort` | `() => void` | Abort current request |
|
|
171
|
+
|
|
172
|
+
### useWrite(writeFn)
|
|
173
|
+
|
|
174
|
+
**Returns:**
|
|
175
|
+
|
|
176
|
+
| Property | Type | Description |
|
|
177
|
+
| --------- | ---------------------- | ---------------------------------- |
|
|
178
|
+
| `trigger` | `(options) => Promise` | Execute the mutation |
|
|
179
|
+
| `data` | `TData \| undefined` | Response data |
|
|
180
|
+
| `error` | `TError \| undefined` | Error if request failed |
|
|
181
|
+
| `loading` | `boolean` | True while mutation is in progress |
|
|
182
|
+
| `reset` | `() => void` | Reset state |
|
|
183
|
+
| `abort` | `() => void` | Abort current request |
|
|
184
|
+
|
|
185
|
+
### useInfiniteRead(readFn, options)
|
|
186
|
+
|
|
187
|
+
| Option | Type | Required | Description |
|
|
188
|
+
| ----------------- | ---------------------------- | -------- | ------------------------------- |
|
|
189
|
+
| `canFetchNext` | `(ctx) => boolean` | Yes | Check if next page exists |
|
|
190
|
+
| `nextPageRequest` | `(ctx) => Partial<TRequest>` | Yes | Build request for next page |
|
|
191
|
+
| `merger` | `(allResponses) => TItem[]` | Yes | Merge all responses into items |
|
|
192
|
+
| `canFetchPrev` | `(ctx) => boolean` | No | Check if previous page exists |
|
|
193
|
+
| `prevPageRequest` | `(ctx) => Partial<TRequest>` | No | Build request for previous page |
|
|
194
|
+
| `enabled` | `boolean` | No | Whether to fetch automatically |
|
|
195
|
+
|
|
196
|
+
**Context object passed to callbacks:**
|
|
197
|
+
|
|
198
|
+
```typescript
|
|
199
|
+
type Context<TData, TRequest> = {
|
|
200
|
+
response: TData | undefined; // Latest response
|
|
201
|
+
allResponses: TData[]; // All fetched responses
|
|
202
|
+
request: TRequest; // Current request options
|
|
203
|
+
};
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
**Returns:**
|
|
207
|
+
|
|
208
|
+
| Property | Type | Description |
|
|
209
|
+
| -------------- | ---------------------- | ------------------------------- |
|
|
210
|
+
| `data` | `TItem[] \| undefined` | Merged items from all responses |
|
|
211
|
+
| `allResponses` | `TData[] \| undefined` | Array of all raw responses |
|
|
212
|
+
| `loading` | `boolean` | True during initial load |
|
|
213
|
+
| `fetching` | `boolean` | True during any fetch |
|
|
214
|
+
| `fetchingNext` | `boolean` | True while fetching next page |
|
|
215
|
+
| `fetchingPrev` | `boolean` | True while fetching previous |
|
|
216
|
+
| `canFetchNext` | `boolean` | Whether next page exists |
|
|
217
|
+
| `canFetchPrev` | `boolean` | Whether previous page exists |
|
|
218
|
+
| `fetchNext` | `() => Promise<void>` | Fetch the next page |
|
|
219
|
+
| `fetchPrev` | `() => Promise<void>` | Fetch the previous page |
|
|
220
|
+
| `refetch` | `() => Promise<void>` | Refetch all pages |
|
|
221
|
+
| `abort` | `() => void` | Abort current request |
|
|
222
|
+
| `error` | `TError \| undefined` | Error if request failed |
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
import * as _spoosh_core from '@spoosh/core';
|
|
2
|
+
import { QueryOnlyClient, MethodOptionsMap, CoreRequestOptionsBase, TagOptions, SpooshResponse, MutationOnlyClient, SpooshPlugin, PluginTypeConfig, SpooshOptions, MergePluginResults, StateManager, EventEmitter, PluginExecutor, PluginArray, MergePluginOptions, ResolverContext, ResolveResultTypes, MergePluginInstanceApi } from '@spoosh/core';
|
|
3
|
+
|
|
4
|
+
type QueryRequestOptions = CoreRequestOptionsBase;
|
|
5
|
+
type MutationRequestOptions = CoreRequestOptionsBase;
|
|
6
|
+
type ReactOptionsMap = MethodOptionsMap<QueryRequestOptions, MutationRequestOptions>;
|
|
7
|
+
type PluginHooksConfig<TPlugins extends readonly SpooshPlugin<PluginTypeConfig>[]> = {
|
|
8
|
+
baseUrl: string;
|
|
9
|
+
defaultOptions?: SpooshOptions;
|
|
10
|
+
plugins: TPlugins;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Base options for `useRead` hook.
|
|
14
|
+
*/
|
|
15
|
+
type BaseReadOptions = TagOptions & {
|
|
16
|
+
/** Whether to fetch automatically on mount. Default: true */
|
|
17
|
+
enabled?: boolean;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Result returned by `useRead` hook.
|
|
22
|
+
*
|
|
23
|
+
* @template TData - The response data type
|
|
24
|
+
* @template TError - The error type
|
|
25
|
+
*/
|
|
26
|
+
type BaseReadResult<TData, TError> = {
|
|
27
|
+
/** True during the initial load (no data yet) */
|
|
28
|
+
loading: boolean;
|
|
29
|
+
/** True during any fetch operation */
|
|
30
|
+
fetching: boolean;
|
|
31
|
+
/** Response data from the API */
|
|
32
|
+
data: TData | undefined;
|
|
33
|
+
/** Error from the last failed request */
|
|
34
|
+
error: TError | undefined;
|
|
35
|
+
/** Abort the current fetch operation */
|
|
36
|
+
abort: () => void;
|
|
37
|
+
/** Manually trigger a refetch */
|
|
38
|
+
refetch: () => Promise<SpooshResponse<TData, TError>>;
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Result returned by `useWrite` hook.
|
|
42
|
+
*
|
|
43
|
+
* @template TData - The response data type
|
|
44
|
+
* @template TError - The error type
|
|
45
|
+
* @template TOptions - The trigger options type
|
|
46
|
+
*/
|
|
47
|
+
type BaseWriteResult<TData, TError, TOptions> = {
|
|
48
|
+
/** Execute the mutation with optional options */
|
|
49
|
+
trigger: (options?: TOptions) => Promise<SpooshResponse<TData, TError>>;
|
|
50
|
+
/** True while the mutation is in progress */
|
|
51
|
+
loading: boolean;
|
|
52
|
+
/** Response data from the API */
|
|
53
|
+
data: TData | undefined;
|
|
54
|
+
/** Error from the last failed request */
|
|
55
|
+
error: TError | undefined;
|
|
56
|
+
/** Reset the state to initial values */
|
|
57
|
+
reset: () => void;
|
|
58
|
+
/** Abort the current mutation */
|
|
59
|
+
abort: () => void;
|
|
60
|
+
};
|
|
61
|
+
type OptionalQueryField<TQuery> = [TQuery] extends [never] ? object : {
|
|
62
|
+
query: TQuery;
|
|
63
|
+
};
|
|
64
|
+
type OptionalBodyField<TBody> = [TBody] extends [never] ? object : {
|
|
65
|
+
body: TBody;
|
|
66
|
+
};
|
|
67
|
+
type OptionalFormDataField<TFormData> = [TFormData] extends [never] ? object : {
|
|
68
|
+
formData: TFormData;
|
|
69
|
+
};
|
|
70
|
+
type OptionalParamsField<TParamNames extends string> = [TParamNames] extends [
|
|
71
|
+
never
|
|
72
|
+
] ? object : {
|
|
73
|
+
params: Record<TParamNames, string | number>;
|
|
74
|
+
};
|
|
75
|
+
type InputFields<TQuery, TBody, TFormData, TParamNames extends string> = OptionalQueryField<TQuery> & OptionalBodyField<TBody> & OptionalFormDataField<TFormData> & OptionalParamsField<TParamNames>;
|
|
76
|
+
type WriteResponseInputFields<TQuery, TBody, TFormData, TParamNames extends string> = [TQuery, TBody, TFormData, TParamNames] extends [never, never, never, never] ? object : {
|
|
77
|
+
input: InputFields<TQuery, TBody, TFormData, TParamNames> | undefined;
|
|
78
|
+
};
|
|
79
|
+
type UseReadResult<TData, TError, TPlugins extends readonly SpooshPlugin<PluginTypeConfig>[]> = BaseReadResult<TData, TError> & MergePluginResults<TPlugins>["read"];
|
|
80
|
+
type UseWriteResult<TData, TError, TOptions, TPlugins extends readonly SpooshPlugin<PluginTypeConfig>[]> = BaseWriteResult<TData, TError, TOptions> & MergePluginResults<TPlugins>["write"];
|
|
81
|
+
type ReadApiClient<TSchema, TDefaultError> = QueryOnlyClient<TSchema, TDefaultError, ReactOptionsMap>;
|
|
82
|
+
type WriteApiClient<TSchema, TDefaultError> = MutationOnlyClient<TSchema, TDefaultError, ReactOptionsMap>;
|
|
83
|
+
type SuccessResponse<T> = Extract<T, {
|
|
84
|
+
data: unknown;
|
|
85
|
+
error?: undefined;
|
|
86
|
+
}>;
|
|
87
|
+
type ErrorResponse<T> = Extract<T, {
|
|
88
|
+
error: unknown;
|
|
89
|
+
data?: undefined;
|
|
90
|
+
}>;
|
|
91
|
+
type ExtractMethodData<T> = T extends (...args: never[]) => infer R ? SuccessResponse<Awaited<R>> extends {
|
|
92
|
+
data: infer D;
|
|
93
|
+
} ? D : unknown : unknown;
|
|
94
|
+
type ExtractMethodError<T> = T extends (...args: never[]) => infer R ? ErrorResponse<Awaited<R>> extends {
|
|
95
|
+
error: infer E;
|
|
96
|
+
} ? E : unknown : unknown;
|
|
97
|
+
type ExtractMethodOptions<T> = T extends (...args: infer A) => unknown ? A[0] : never;
|
|
98
|
+
type ExtractMethodQuery<T> = ExtractMethodOptions<T> extends {
|
|
99
|
+
query: infer Q;
|
|
100
|
+
} ? Q : never;
|
|
101
|
+
type ExtractMethodBody<T> = ExtractMethodOptions<T> extends {
|
|
102
|
+
body: infer B;
|
|
103
|
+
} ? B : never;
|
|
104
|
+
type ExtractMethodFormData<T> = ExtractMethodOptions<T> extends {
|
|
105
|
+
formData: infer F;
|
|
106
|
+
} ? F : never;
|
|
107
|
+
type ExtractMethodUrlEncoded<T> = ExtractMethodOptions<T> extends {
|
|
108
|
+
urlEncoded: infer U;
|
|
109
|
+
} ? U : never;
|
|
110
|
+
type AwaitedReturnType<T> = T extends (...args: never[]) => infer R ? Awaited<R> : never;
|
|
111
|
+
type SuccessReturnType<T> = SuccessResponse<AwaitedReturnType<T>>;
|
|
112
|
+
type ExtractResponseQuery<T> = SuccessReturnType<T> extends {
|
|
113
|
+
input: {
|
|
114
|
+
query: infer Q;
|
|
115
|
+
};
|
|
116
|
+
} ? Q : never;
|
|
117
|
+
type ExtractResponseBody<T> = SuccessReturnType<T> extends {
|
|
118
|
+
input: {
|
|
119
|
+
body: infer B;
|
|
120
|
+
};
|
|
121
|
+
} ? B : never;
|
|
122
|
+
type ExtractResponseFormData<T> = SuccessReturnType<T> extends {
|
|
123
|
+
input: {
|
|
124
|
+
formData: infer F;
|
|
125
|
+
};
|
|
126
|
+
} ? F : never;
|
|
127
|
+
type ExtractResponseParamNames<T> = SuccessReturnType<T> extends {
|
|
128
|
+
input: {
|
|
129
|
+
params: Record<infer K, unknown>;
|
|
130
|
+
};
|
|
131
|
+
} ? K extends string ? K : never : never;
|
|
132
|
+
type QueryField<TQuery> = [TQuery] extends [never] ? object : {
|
|
133
|
+
query: TQuery;
|
|
134
|
+
};
|
|
135
|
+
type BodyField<TBody> = [TBody] extends [never] ? object : {
|
|
136
|
+
body: TBody;
|
|
137
|
+
};
|
|
138
|
+
type FormDataField<TFormData> = [TFormData] extends [never] ? object : {
|
|
139
|
+
formData: TFormData;
|
|
140
|
+
};
|
|
141
|
+
type ParamsField<TParamNames extends string> = [TParamNames] extends [never] ? object : {
|
|
142
|
+
params: Record<TParamNames, string | number>;
|
|
143
|
+
};
|
|
144
|
+
type ReadInputFields<TQuery, TBody, TFormData, TParamNames extends string> = QueryField<TQuery> & BodyField<TBody> & FormDataField<TFormData> & ParamsField<TParamNames>;
|
|
145
|
+
type ResponseInputFields<TQuery, TBody, TFormData, TParamNames extends string> = [TQuery, TBody, TFormData, TParamNames] extends [never, never, never, never] ? object : {
|
|
146
|
+
input: ReadInputFields<TQuery, TBody, TFormData, TParamNames>;
|
|
147
|
+
};
|
|
148
|
+
type AnyInfiniteRequestOptions = {
|
|
149
|
+
query?: Record<string, unknown>;
|
|
150
|
+
params?: Record<string, string | number>;
|
|
151
|
+
body?: unknown;
|
|
152
|
+
};
|
|
153
|
+
/**
|
|
154
|
+
* Context passed to `canFetchNext` and `nextPageRequest` callbacks.
|
|
155
|
+
*/
|
|
156
|
+
type InfiniteNextContext<TData, TRequest> = {
|
|
157
|
+
/** The latest fetched response data */
|
|
158
|
+
response: TData | undefined;
|
|
159
|
+
/** All responses fetched so far */
|
|
160
|
+
allResponses: TData[];
|
|
161
|
+
/** The current request options (query, params, body) */
|
|
162
|
+
request: TRequest;
|
|
163
|
+
};
|
|
164
|
+
/**
|
|
165
|
+
* Context passed to `canFetchPrev` and `prevPageRequest` callbacks.
|
|
166
|
+
*/
|
|
167
|
+
type InfinitePrevContext<TData, TRequest> = {
|
|
168
|
+
/** The latest fetched response data */
|
|
169
|
+
response: TData | undefined;
|
|
170
|
+
/** All responses fetched so far */
|
|
171
|
+
allResponses: TData[];
|
|
172
|
+
/** The current request options (query, params, body) */
|
|
173
|
+
request: TRequest;
|
|
174
|
+
};
|
|
175
|
+
/**
|
|
176
|
+
* Options for `useInfiniteRead` hook.
|
|
177
|
+
*
|
|
178
|
+
* @template TData - The response data type for each page
|
|
179
|
+
* @template TItem - The item type after merging all responses
|
|
180
|
+
* @template TRequest - The request options type (query, params, body)
|
|
181
|
+
*/
|
|
182
|
+
type BaseInfiniteReadOptions<TData, TItem, TRequest = AnyInfiniteRequestOptions> = TagOptions & {
|
|
183
|
+
/** Whether to fetch automatically on mount. Default: true */
|
|
184
|
+
enabled?: boolean;
|
|
185
|
+
/** Callback to determine if there's a next page to fetch */
|
|
186
|
+
canFetchNext: (ctx: InfiniteNextContext<TData, TRequest>) => boolean;
|
|
187
|
+
/** Callback to build the request options for the next page */
|
|
188
|
+
nextPageRequest: (ctx: InfiniteNextContext<TData, TRequest>) => Partial<TRequest>;
|
|
189
|
+
/** Callback to merge all responses into a single array of items */
|
|
190
|
+
merger: (allResponses: TData[]) => TItem[];
|
|
191
|
+
/** Callback to determine if there's a previous page to fetch */
|
|
192
|
+
canFetchPrev?: (ctx: InfinitePrevContext<TData, TRequest>) => boolean;
|
|
193
|
+
/** Callback to build the request options for the previous page */
|
|
194
|
+
prevPageRequest?: (ctx: InfinitePrevContext<TData, TRequest>) => Partial<TRequest>;
|
|
195
|
+
};
|
|
196
|
+
/**
|
|
197
|
+
* Result returned by `useInfiniteRead` hook.
|
|
198
|
+
*
|
|
199
|
+
* @template TData - The response data type for each page
|
|
200
|
+
* @template TError - The error type
|
|
201
|
+
* @template TItem - The item type after merging all responses
|
|
202
|
+
*/
|
|
203
|
+
type BaseInfiniteReadResult<TData, TError, TItem> = {
|
|
204
|
+
/** Merged items from all fetched responses */
|
|
205
|
+
data: TItem[] | undefined;
|
|
206
|
+
/** Array of all raw response data */
|
|
207
|
+
allResponses: TData[] | undefined;
|
|
208
|
+
/** True during the initial load (no data yet) */
|
|
209
|
+
loading: boolean;
|
|
210
|
+
/** True during any fetch operation */
|
|
211
|
+
fetching: boolean;
|
|
212
|
+
/** True while fetching the next page */
|
|
213
|
+
fetchingNext: boolean;
|
|
214
|
+
/** True while fetching the previous page */
|
|
215
|
+
fetchingPrev: boolean;
|
|
216
|
+
/** Whether there's a next page available to fetch */
|
|
217
|
+
canFetchNext: boolean;
|
|
218
|
+
/** Whether there's a previous page available to fetch */
|
|
219
|
+
canFetchPrev: boolean;
|
|
220
|
+
/** Fetch the next page */
|
|
221
|
+
fetchNext: () => Promise<void>;
|
|
222
|
+
/** Fetch the previous page */
|
|
223
|
+
fetchPrev: () => Promise<void>;
|
|
224
|
+
/** Refetch all pages from the beginning */
|
|
225
|
+
refetch: () => Promise<void>;
|
|
226
|
+
/** Abort the current fetch operation */
|
|
227
|
+
abort: () => void;
|
|
228
|
+
/** Error from the last failed request */
|
|
229
|
+
error: TError | undefined;
|
|
230
|
+
};
|
|
231
|
+
type UseInfiniteReadResult<TData, TError, TItem, TPlugins extends readonly SpooshPlugin<PluginTypeConfig>[]> = BaseInfiniteReadResult<TData, TError, TItem> & MergePluginResults<TPlugins>["read"];
|
|
232
|
+
type InfiniteReadApiClient<TSchema, TDefaultError> = QueryOnlyClient<TSchema, TDefaultError, ReactOptionsMap>;
|
|
233
|
+
|
|
234
|
+
type InferError<T, TDefaultError> = [T] extends [unknown] ? TDefaultError : T;
|
|
235
|
+
type ExtractParamsRecord<T> = ExtractResponseParamNames<T> extends never ? never : Record<ExtractResponseParamNames<T>, string | number>;
|
|
236
|
+
type ReadResolverContext<TSchema, TReadFn, TDefaultError> = ResolverContext<TSchema, ExtractMethodData<TReadFn>, InferError<ExtractMethodError<TReadFn>, TDefaultError>, ExtractResponseQuery<TReadFn>, ExtractResponseBody<TReadFn>, ExtractParamsRecord<TReadFn>, ExtractResponseFormData<TReadFn>>;
|
|
237
|
+
type ResolvedReadOptions<TSchema, TPlugins extends PluginArray, TReadFn, TDefaultError> = _spoosh_core.ResolveTypes<MergePluginOptions<TPlugins>["read"], ReadResolverContext<TSchema, TReadFn, TDefaultError>>;
|
|
238
|
+
type WriteResolverContext<TSchema, TMethod, TDefaultError> = ResolverContext<TSchema, ExtractMethodData<TMethod>, InferError<ExtractMethodError<TMethod>, TDefaultError>, ExtractMethodQuery<TMethod>, ExtractMethodBody<TMethod>, ExtractResponseParamNames<TMethod> extends never ? never : Record<ExtractResponseParamNames<TMethod>, string | number>, ExtractMethodFormData<TMethod>, ExtractMethodUrlEncoded<TMethod>>;
|
|
239
|
+
type ResolvedWriteOptions<TSchema, TPlugins extends PluginArray, TMethod, TDefaultError> = _spoosh_core.ResolveTypes<MergePluginOptions<TPlugins>["write"], WriteResolverContext<TSchema, TMethod, TDefaultError>>;
|
|
240
|
+
type UseReadFn<TDefaultError, TSchema, TPlugins extends PluginArray> = <TReadFn extends (api: ReadApiClient<TSchema, TDefaultError>) => Promise<{
|
|
241
|
+
data?: unknown;
|
|
242
|
+
error?: unknown;
|
|
243
|
+
}>, TReadOpts extends BaseReadOptions & ResolvedReadOptions<TSchema, TPlugins, TReadFn, TDefaultError> = BaseReadOptions & ResolvedReadOptions<TSchema, TPlugins, TReadFn, TDefaultError>>(readFn: TReadFn, readOptions?: TReadOpts) => BaseReadResult<ExtractMethodData<TReadFn>, InferError<ExtractMethodError<TReadFn>, TDefaultError>> & ResponseInputFields<ExtractResponseQuery<TReadFn>, ExtractResponseBody<TReadFn>, ExtractResponseFormData<TReadFn>, ExtractResponseParamNames<TReadFn>> & ResolveResultTypes<MergePluginResults<TPlugins>["read"], TReadOpts>;
|
|
244
|
+
type UseWriteFn<TDefaultError, TSchema, TPlugins extends PluginArray> = <TMethod extends (...args: never[]) => Promise<SpooshResponse<unknown, unknown>>, TWriteOpts extends (TMethod extends (options: infer O) => unknown ? O : object) & ResolvedWriteOptions<TSchema, TPlugins, TMethod, TDefaultError> = (TMethod extends (options: infer O) => unknown ? O : object) & ResolvedWriteOptions<TSchema, TPlugins, TMethod, TDefaultError>>(writeFn: (api: WriteApiClient<TSchema, TDefaultError>) => TMethod) => BaseWriteResult<ExtractMethodData<TMethod>, InferError<ExtractMethodError<TMethod>, TDefaultError>, TWriteOpts> & WriteResponseInputFields<ExtractResponseQuery<TMethod>, ExtractResponseBody<TMethod>, ExtractResponseFormData<TMethod>, ExtractResponseParamNames<TMethod>> & ResolveResultTypes<MergePluginResults<TPlugins>["write"], TWriteOpts>;
|
|
245
|
+
type InfiniteReadResolverContext<TSchema, TData, TError, TRequest> = ResolverContext<TSchema, TData, TError, TRequest extends {
|
|
246
|
+
query: infer Q;
|
|
247
|
+
} ? Q : never, TRequest extends {
|
|
248
|
+
body: infer B;
|
|
249
|
+
} ? B : never, TRequest extends {
|
|
250
|
+
params: infer P;
|
|
251
|
+
} ? P : never, never>;
|
|
252
|
+
type ResolvedInfiniteReadOptions<TSchema, TPlugins extends PluginArray, TData, TError, TRequest> = _spoosh_core.ResolveTypes<MergePluginOptions<TPlugins>["infiniteRead"], InfiniteReadResolverContext<TSchema, TData, TError, TRequest>>;
|
|
253
|
+
type UseInfiniteReadFn<TDefaultError, TSchema, TPlugins extends PluginArray> = <TData, TItem, TError = TDefaultError, TRequest extends AnyInfiniteRequestOptions = AnyInfiniteRequestOptions>(readFn: (api: InfiniteReadApiClient<TSchema, TDefaultError>) => Promise<SpooshResponse<TData, TError>>, readOptions: BaseInfiniteReadOptions<TData, TItem, TRequest> & ResolvedInfiniteReadOptions<TSchema, TPlugins, TData, TError, TRequest>) => BaseInfiniteReadResult<TData, TError, TItem> & MergePluginResults<TPlugins>["read"];
|
|
254
|
+
/**
|
|
255
|
+
* Spoosh React hooks interface containing useRead, useWrite, and useInfiniteRead.
|
|
256
|
+
*
|
|
257
|
+
* @template TDefaultError - The default error type
|
|
258
|
+
* @template TSchema - The API schema type
|
|
259
|
+
* @template TPlugins - The plugins array type
|
|
260
|
+
*/
|
|
261
|
+
type SpooshReactHooks<TDefaultError, TSchema, TPlugins extends PluginArray> = {
|
|
262
|
+
/**
|
|
263
|
+
* React hook for fetching data from an API endpoint with automatic caching and revalidation.
|
|
264
|
+
*
|
|
265
|
+
* @param readFn - Function that selects the API endpoint to call (e.g., `(api) => api.posts.$get()`)
|
|
266
|
+
* @param readOptions - Optional configuration including `enabled`, `tags`, and plugin-specific options
|
|
267
|
+
* @returns Object containing `data`, `error`, `loading`, `fetching`, `refetch`, and `abort`
|
|
268
|
+
*
|
|
269
|
+
* @example
|
|
270
|
+
* ```tsx
|
|
271
|
+
* const { data, loading, error } = useRead((api) => api.posts.$get());
|
|
272
|
+
*
|
|
273
|
+
* const { data: post } = useRead(
|
|
274
|
+
* (api) => api.posts[postId].$get(),
|
|
275
|
+
* { enabled: !!postId }
|
|
276
|
+
* );
|
|
277
|
+
* ```
|
|
278
|
+
*/
|
|
279
|
+
useRead: UseReadFn<TDefaultError, TSchema, TPlugins>;
|
|
280
|
+
/**
|
|
281
|
+
* React hook for mutations (POST, PUT, PATCH, DELETE) with manual triggering.
|
|
282
|
+
*
|
|
283
|
+
* @param writeFn - Function that selects the API endpoint (e.g., `(api) => api.posts.$post`)
|
|
284
|
+
* @returns Object containing `trigger`, `data`, `error`, `loading`, `reset`, and `abort`
|
|
285
|
+
*
|
|
286
|
+
* @example
|
|
287
|
+
* ```tsx
|
|
288
|
+
* const { trigger, loading, data } = useWrite((api) => api.posts.$post);
|
|
289
|
+
*
|
|
290
|
+
* const handleSubmit = async (formData) => {
|
|
291
|
+
* const { data, error } = await trigger({ body: formData });
|
|
292
|
+
* if (data) console.log('Created:', data);
|
|
293
|
+
* };
|
|
294
|
+
* ```
|
|
295
|
+
*/
|
|
296
|
+
useWrite: UseWriteFn<TDefaultError, TSchema, TPlugins>;
|
|
297
|
+
/**
|
|
298
|
+
* React hook for infinite/paginated data fetching with automatic pagination control.
|
|
299
|
+
*
|
|
300
|
+
* @param readFn - Function that selects the API endpoint to call
|
|
301
|
+
* @param readOptions - Configuration including `canFetchNext`, `nextPageRequest`, `merger`, and optional `canFetchPrev`/`prevPageRequest`
|
|
302
|
+
* @returns Object containing `data`, `allResponses`, `fetchNext`, `fetchPrev`, `canFetchNext`, `canFetchPrev`, `loading`, `fetching`, and pagination states
|
|
303
|
+
*
|
|
304
|
+
* @example
|
|
305
|
+
* ```tsx
|
|
306
|
+
* const { data, fetchNext, canFetchNext, loading } = useInfiniteRead(
|
|
307
|
+
* (api) => api.posts.$get(),
|
|
308
|
+
* {
|
|
309
|
+
* canFetchNext: ({ response }) => !!response?.nextCursor,
|
|
310
|
+
* nextPageRequest: ({ response }) => ({ query: { cursor: response?.nextCursor } }),
|
|
311
|
+
* merger: (responses) => responses.flatMap(r => r.items)
|
|
312
|
+
* }
|
|
313
|
+
* );
|
|
314
|
+
* ```
|
|
315
|
+
*/
|
|
316
|
+
useInfiniteRead: UseInfiniteReadFn<TDefaultError, TSchema, TPlugins>;
|
|
317
|
+
} & MergePluginInstanceApi<TPlugins, TSchema>;
|
|
318
|
+
/**
|
|
319
|
+
* Shape of a Spoosh instance required for creating React hooks.
|
|
320
|
+
*/
|
|
321
|
+
type SpooshInstanceShape<TApi, TSchema, TDefaultError, TPlugins> = {
|
|
322
|
+
/** The API client instance */
|
|
323
|
+
api: TApi;
|
|
324
|
+
/** State manager for caching and state */
|
|
325
|
+
stateManager: StateManager;
|
|
326
|
+
/** Event emitter for refetch and invalidation events */
|
|
327
|
+
eventEmitter: EventEmitter;
|
|
328
|
+
/** Plugin executor for running plugins */
|
|
329
|
+
pluginExecutor: PluginExecutor;
|
|
330
|
+
/** Type information (not used at runtime) */
|
|
331
|
+
_types: {
|
|
332
|
+
schema: TSchema;
|
|
333
|
+
defaultError: TDefaultError;
|
|
334
|
+
plugins: TPlugins;
|
|
335
|
+
};
|
|
336
|
+
};
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* Creates React hooks (useRead, useWrite, useInfiniteRead) from a Spoosh instance.
|
|
340
|
+
*
|
|
341
|
+
* @template TSchema - The API schema type
|
|
342
|
+
* @template TDefaultError - The default error type
|
|
343
|
+
* @template TPlugins - The plugins array type
|
|
344
|
+
* @template TApi - The API client type
|
|
345
|
+
* @param instance - The Spoosh instance containing api, stateManager, eventEmitter, and pluginExecutor
|
|
346
|
+
* @returns An object containing useRead, useWrite, useInfiniteRead hooks and plugin instance APIs
|
|
347
|
+
*
|
|
348
|
+
* @example
|
|
349
|
+
* ```ts
|
|
350
|
+
* const { useRead, useWrite, useInfiniteRead } = createReactSpoosh(spooshInstance);
|
|
351
|
+
*
|
|
352
|
+
* function MyComponent() {
|
|
353
|
+
* const { data, loading } = useRead((api) => api.posts.$get());
|
|
354
|
+
* return <div>{loading ? 'Loading...' : data?.title}</div>;
|
|
355
|
+
* }
|
|
356
|
+
* ```
|
|
357
|
+
*/
|
|
358
|
+
declare function createReactSpoosh<TSchema, TDefaultError, TPlugins extends PluginArray, TApi>(instance: SpooshInstanceShape<TApi, TSchema, TDefaultError, TPlugins>): SpooshReactHooks<TDefaultError, TSchema, TPlugins>;
|
|
359
|
+
|
|
360
|
+
declare function createUseRead<TSchema, TDefaultError, TPlugins extends readonly SpooshPlugin<PluginTypeConfig>[]>(options: Omit<SpooshInstanceShape<unknown, TSchema, TDefaultError, TPlugins>, "_types">): <TReadFn extends (api: ReadApiClient<TSchema, TDefaultError>) => Promise<{
|
|
361
|
+
data?: unknown;
|
|
362
|
+
error?: unknown;
|
|
363
|
+
}>, TReadOpts extends BaseReadOptions & (((TPlugins[number] extends infer T_3 ? T_3 extends TPlugins[number] ? T_3 extends SpooshPlugin<infer Types_1 extends PluginTypeConfig> ? Types_1 extends {
|
|
364
|
+
readOptions: infer R_1;
|
|
365
|
+
} ? R_1 : object : object : never : never) extends infer T_4 ? T_4 extends (TPlugins[number] extends infer T_5 ? T_5 extends TPlugins[number] ? T_5 extends SpooshPlugin<infer Types_1 extends PluginTypeConfig> ? Types_1 extends {
|
|
366
|
+
readOptions: infer R_1;
|
|
367
|
+
} ? R_1 : object : object : never : never) ? T_4 extends unknown ? (x: T_4) => void : never : never : never) extends (x: infer I) => void ? I : never) = BaseReadOptions & (((TPlugins[number] extends infer T_6 ? T_6 extends TPlugins[number] ? T_6 extends SpooshPlugin<infer Types_1 extends PluginTypeConfig> ? Types_1 extends {
|
|
368
|
+
readOptions: infer R_1;
|
|
369
|
+
} ? R_1 : object : object : never : never) extends infer T_7 ? T_7 extends (TPlugins[number] extends infer T_8 ? T_8 extends TPlugins[number] ? T_8 extends SpooshPlugin<infer Types_1 extends PluginTypeConfig> ? Types_1 extends {
|
|
370
|
+
readOptions: infer R_1;
|
|
371
|
+
} ? R_1 : object : object : never : never) ? T_7 extends unknown ? (x: T_7) => void : never : never : never) extends (x: infer I) => void ? I : never)>(readFn: TReadFn, readOptions?: TReadOpts) => BaseReadResult<TReadFn extends (...args: unknown[]) => Promise<{
|
|
372
|
+
data: infer D;
|
|
373
|
+
}> ? D : unknown, [TReadFn extends (...args: unknown[]) => Promise<{
|
|
374
|
+
error: infer E;
|
|
375
|
+
}> ? E : unknown] extends [unknown] ? TDefaultError : TReadFn extends (...args: unknown[]) => Promise<{
|
|
376
|
+
error: infer E;
|
|
377
|
+
}> ? E : unknown> & ResponseInputFields<ExtractResponseQuery<TReadFn>, ExtractResponseBody<TReadFn>, ExtractResponseFormData<TReadFn>, ExtractResponseParamNames<TReadFn>> & ResolveResultTypes<((TPlugins[number] extends infer T ? T extends TPlugins[number] ? T extends SpooshPlugin<infer Types extends PluginTypeConfig> ? Types extends {
|
|
378
|
+
readResult: infer R;
|
|
379
|
+
} ? R : object : object : never : never) extends infer T_1 ? T_1 extends (TPlugins[number] extends infer T_2 ? T_2 extends TPlugins[number] ? T_2 extends SpooshPlugin<infer Types extends PluginTypeConfig> ? Types extends {
|
|
380
|
+
readResult: infer R;
|
|
381
|
+
} ? R : object : object : never : never) ? T_1 extends unknown ? (x: T_1) => void : never : never : never) extends (x: infer I) => void ? I : never, TReadOpts>;
|
|
382
|
+
|
|
383
|
+
declare function createUseWrite<TSchema, TDefaultError, TPlugins extends readonly SpooshPlugin<PluginTypeConfig>[]>(options: Omit<SpooshInstanceShape<unknown, TSchema, TDefaultError, TPlugins>, "_types">): <TMethod extends (...args: never[]) => Promise<SpooshResponse<unknown, unknown>>>(writeFn: (api: WriteApiClient<TSchema, TDefaultError>) => TMethod) => BaseWriteResult<ExtractMethodData<TMethod>, [ExtractMethodError<TMethod>] extends [unknown] ? TDefaultError : ExtractMethodError<TMethod>, ExtractMethodOptions<TMethod> & _spoosh_core.ResolveTypes<((TPlugins[number] extends infer T ? T extends TPlugins[number] ? T extends SpooshPlugin<infer Types extends PluginTypeConfig> ? Types extends {
|
|
384
|
+
writeOptions: infer W;
|
|
385
|
+
} ? 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 {
|
|
386
|
+
writeOptions: infer W;
|
|
387
|
+
} ? W : object : object : never : never) ? T_1 extends unknown ? (x: T_1) => void : never : never : never) extends (x: infer I) => void ? I : never, ResolverContext<TSchema, ExtractMethodData<TMethod>, [ExtractMethodError<TMethod>] extends [unknown] ? TDefaultError : ExtractMethodError<TMethod>, ExtractMethodQuery<TMethod>, ExtractMethodBody<TMethod>, ExtractResponseParamNames<TMethod> extends never ? never : Record<ExtractResponseParamNames<TMethod>, string | number>, ExtractMethodFormData<TMethod>, ExtractMethodUrlEncoded<TMethod>>>> & WriteResponseInputFields<ExtractResponseQuery<TMethod>, ExtractResponseBody<TMethod>, ExtractResponseFormData<TMethod>, ExtractResponseParamNames<TMethod>> & ResolveResultTypes<((TPlugins[number] extends infer T_3 ? T_3 extends TPlugins[number] ? T_3 extends SpooshPlugin<infer Types_1 extends PluginTypeConfig> ? Types_1 extends {
|
|
388
|
+
writeResult: infer W_1;
|
|
389
|
+
} ? 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 {
|
|
390
|
+
writeResult: infer W_1;
|
|
391
|
+
} ? W_1 : object : object : never : never) ? T_4 extends unknown ? (x: T_4) => void : never : never : never) extends (x: infer I) => void ? I : never, ExtractMethodOptions<TMethod> & _spoosh_core.ResolveTypes<((TPlugins[number] extends infer T_6 ? T_6 extends TPlugins[number] ? T_6 extends SpooshPlugin<infer Types extends PluginTypeConfig> ? Types extends {
|
|
392
|
+
writeOptions: infer W;
|
|
393
|
+
} ? W : object : object : never : never) extends infer T_7 ? T_7 extends (TPlugins[number] extends infer T_8 ? T_8 extends TPlugins[number] ? T_8 extends SpooshPlugin<infer Types extends PluginTypeConfig> ? Types extends {
|
|
394
|
+
writeOptions: infer W;
|
|
395
|
+
} ? W : object : object : never : never) ? T_7 extends unknown ? (x: T_7) => void : never : never : never) extends (x: infer I) => void ? I : never, ResolverContext<TSchema, ExtractMethodData<TMethod>, [ExtractMethodError<TMethod>] extends [unknown] ? TDefaultError : ExtractMethodError<TMethod>, ExtractMethodQuery<TMethod>, ExtractMethodBody<TMethod>, ExtractResponseParamNames<TMethod> extends never ? never : Record<ExtractResponseParamNames<TMethod>, string | number>, ExtractMethodFormData<TMethod>, ExtractMethodUrlEncoded<TMethod>>>>;
|
|
396
|
+
|
|
397
|
+
declare function createUseInfiniteRead<TSchema, TDefaultError, TPlugins extends readonly SpooshPlugin<PluginTypeConfig>[]>(options: Omit<SpooshInstanceShape<unknown, TSchema, TDefaultError, TPlugins>, "_types">): <TData, TItem, TError = TDefaultError, TRequest extends AnyInfiniteRequestOptions = AnyInfiniteRequestOptions, TReadOpts extends BaseInfiniteReadOptions<TData, TItem, TRequest> & (((TPlugins[number] extends infer T_3 ? T_3 extends TPlugins[number] ? T_3 extends SpooshPlugin<infer Types_1 extends PluginTypeConfig> ? Types_1 extends {
|
|
398
|
+
infiniteReadOptions: infer I_1;
|
|
399
|
+
} ? I_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 {
|
|
400
|
+
infiniteReadOptions: infer I_1;
|
|
401
|
+
} ? I_1 : object : object : never : never) ? T_4 extends unknown ? (x: T_4) => void : never : never : never) extends (x: infer I) => void ? I : never) = BaseInfiniteReadOptions<TData, TItem, TRequest> & (((TPlugins[number] extends infer T_6 ? T_6 extends TPlugins[number] ? T_6 extends SpooshPlugin<infer Types_1 extends PluginTypeConfig> ? Types_1 extends {
|
|
402
|
+
infiniteReadOptions: infer I_1;
|
|
403
|
+
} ? I_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 {
|
|
404
|
+
infiniteReadOptions: infer I_1;
|
|
405
|
+
} ? I_1 : object : object : never : never) ? T_7 extends unknown ? (x: T_7) => void : never : never : never) extends (x: infer I) => void ? I : never)>(readFn: (api: InfiniteReadApiClient<TSchema, TDefaultError>) => Promise<SpooshResponse<TData, TError>>, readOptions: TReadOpts) => BaseInfiniteReadResult<TData, TError, TItem> & ResolveResultTypes<((TPlugins[number] extends infer T ? T extends TPlugins[number] ? T extends SpooshPlugin<infer Types extends PluginTypeConfig> ? Types extends {
|
|
406
|
+
readResult: infer R;
|
|
407
|
+
} ? R : object : object : never : never) extends infer T_1 ? T_1 extends (TPlugins[number] extends infer T_2 ? T_2 extends TPlugins[number] ? T_2 extends SpooshPlugin<infer Types extends PluginTypeConfig> ? Types extends {
|
|
408
|
+
readResult: infer R;
|
|
409
|
+
} ? R : object : object : never : never) ? T_1 extends unknown ? (x: T_1) => void : never : never : never) extends (x: infer I) => void ? I : never, TReadOpts>;
|
|
410
|
+
|
|
411
|
+
export { type BaseInfiniteReadOptions, type BaseInfiniteReadResult, type BaseReadOptions, type BaseReadResult, type BaseWriteResult, type PluginHooksConfig, type SpooshReactHooks, type UseInfiniteReadResult, type UseReadResult, type UseWriteResult, createReactSpoosh, createUseInfiniteRead, createUseRead, createUseWrite };
|