zustic 1.0.5 → 1.0.7
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 +15 -0
- package/README.md +1 -1
- package/dist/index.d.mts +70 -0
- package/dist/index.d.ts +70 -0
- package/dist/query/index.d.mts +612 -15
- package/dist/query/index.d.ts +612 -15
- package/dist/query/index.js +1 -1
- package/dist/query/index.mjs +1 -1
- package/package.json +1 -1
package/dist/query/index.d.mts
CHANGED
|
@@ -1,68 +1,442 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Query function object structure for HTTP requests.
|
|
3
|
+
* Defines the HTTP method, URL, body, and headers for an API call.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```typescript
|
|
7
|
+
* const queryFnObj: QueryFnObj = {
|
|
8
|
+
* url: '/api/users/1',
|
|
9
|
+
* method: 'GET',
|
|
10
|
+
* headers: {'Authorization': 'Bearer token'}
|
|
11
|
+
* };
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
1
14
|
type QueryFnObj = {
|
|
15
|
+
/** The API endpoint URL */
|
|
2
16
|
url: string;
|
|
17
|
+
/** HTTP method (GET, POST, PUT, DELETE, PATCH) */
|
|
3
18
|
method: "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
|
|
19
|
+
/** Optional request body */
|
|
4
20
|
body?: any;
|
|
21
|
+
/** Optional HTTP headers */
|
|
5
22
|
headers?: Record<string, any>;
|
|
6
23
|
};
|
|
24
|
+
/**
|
|
25
|
+
* Return type for query functions.
|
|
26
|
+
* Can be either a simple string URL or a full QueryFnObj with method and headers.
|
|
27
|
+
*/
|
|
7
28
|
type QueryFnReturn = string | QueryFnObj;
|
|
29
|
+
/**
|
|
30
|
+
* Query function type that transforms arguments into HTTP request parameters.
|
|
31
|
+
*
|
|
32
|
+
* @template Arg - Type of arguments passed to the query
|
|
33
|
+
* @param arg - Query arguments
|
|
34
|
+
* @returns Either a URL string or QueryFnObj with full HTTP configuration
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```typescript
|
|
38
|
+
* const queryFn: QueryFn<{id: number}> = (arg) => ({
|
|
39
|
+
* url: `/users/${arg.id}`,
|
|
40
|
+
* method: 'GET'
|
|
41
|
+
* });
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
8
44
|
type QueryFn<Arg = any> = (arg: Arg) => QueryFnReturn;
|
|
45
|
+
/**
|
|
46
|
+
* Main query return type indicating success (data) or failure (error).
|
|
47
|
+
* Discriminated union for type-safe handling of both cases.
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```typescript
|
|
51
|
+
* const result: MainQueryReturnTypes = await query();
|
|
52
|
+
* if ('data' in result) {
|
|
53
|
+
* // Handle success
|
|
54
|
+
* console.log(result.data);
|
|
55
|
+
* } else {
|
|
56
|
+
* // Handle error
|
|
57
|
+
* console.error(result.error);
|
|
58
|
+
* }
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
9
61
|
type MainQueryReturnTypes = Promise<{
|
|
62
|
+
/** Successful response data */
|
|
10
63
|
data: any;
|
|
11
64
|
error?: undefined;
|
|
12
65
|
} | {
|
|
66
|
+
/** Error from failed request */
|
|
13
67
|
error: any;
|
|
14
68
|
data?: undefined;
|
|
15
69
|
}>;
|
|
16
|
-
type
|
|
70
|
+
type ApiOptionBase<Arg, R> = {
|
|
71
|
+
/**
|
|
72
|
+
* Transform the response data before storing in cache.
|
|
73
|
+
* Useful for normalizing, filtering, or restructuring API responses.
|
|
74
|
+
*/
|
|
17
75
|
transformResponse?: (currData: any, preData: any) => Promise<R> | R;
|
|
76
|
+
/**
|
|
77
|
+
* Transform error responses for consistent error handling.
|
|
78
|
+
* Useful for extracting error messages or codes.
|
|
79
|
+
*/
|
|
18
80
|
transformError?: (currError: any, preError: any) => Promise<any> | any;
|
|
81
|
+
/**
|
|
82
|
+
* Transform request body before sending to API.
|
|
83
|
+
* Useful for adding timestamps, user info, or formatting data.
|
|
84
|
+
*/
|
|
19
85
|
transformBody?: (body: Arg) => Promise<any> | any;
|
|
86
|
+
/**
|
|
87
|
+
* Transform request headers before sending to API.
|
|
88
|
+
* Useful for adding authentication tokens or custom headers.
|
|
89
|
+
*/
|
|
20
90
|
transformHeader?: (header: Record<string, any>) => Promise<Record<string, any>> | Record<string, any>;
|
|
91
|
+
/**
|
|
92
|
+
* Called when the endpoint encounters an error.
|
|
93
|
+
* Useful for error logging, showing toast messages, or retries.
|
|
94
|
+
*/
|
|
21
95
|
onError?: (err: any) => Promise<void> | void;
|
|
96
|
+
/**
|
|
97
|
+
* Called when the endpoint succeeds.
|
|
98
|
+
* Useful for success logging, showing notifications, or side effects.
|
|
99
|
+
*/
|
|
22
100
|
onSuccess?: (data: R) => Promise<void> | void;
|
|
101
|
+
/**
|
|
102
|
+
* Custom query function that bypasses the base query.
|
|
103
|
+
* Useful for complex request logic or special handling.
|
|
104
|
+
*/
|
|
23
105
|
queryFnc?: (arg: Arg, baseQuery: CreateApiParams<any>['baseQuery']) => MainQueryReturnTypes;
|
|
106
|
+
/**
|
|
107
|
+
* Endpoint-level middleware functions.
|
|
108
|
+
* Execute in addition to global middleware.
|
|
109
|
+
*/
|
|
24
110
|
middlewares?: ApiMiddleware[];
|
|
111
|
+
/**
|
|
112
|
+
* Endpoint-level plugins with lifecycle hooks.
|
|
113
|
+
* Execute in addition to global plugins.
|
|
114
|
+
*/
|
|
25
115
|
plugins?: ApiPlugin[];
|
|
26
116
|
};
|
|
27
|
-
|
|
117
|
+
/**
|
|
118
|
+
* Configuration options for both queries and mutations.
|
|
119
|
+
* Provides hooks, transformations, and cache invalidation controls.
|
|
120
|
+
*
|
|
121
|
+
* @template Arg - Type of arguments passed to the endpoint
|
|
122
|
+
* @template R - Type of response data
|
|
123
|
+
* @template TagTypes - Union type of cache tag strings
|
|
124
|
+
*/
|
|
125
|
+
type ApiOptionQuery<Arg, R, TagTypes extends readonly string[] = readonly []> = {
|
|
126
|
+
/**
|
|
127
|
+
* Cache tags provided by this endpoint.
|
|
128
|
+
* Used for cache invalidation and management.
|
|
129
|
+
* Can be static array or computed from response data.
|
|
130
|
+
*
|
|
131
|
+
* @example
|
|
132
|
+
* ```typescript
|
|
133
|
+
* // Static tags
|
|
134
|
+
* providesTags: ['users']
|
|
135
|
+
*
|
|
136
|
+
* // Dynamic tags from response
|
|
137
|
+
* providesTags: (result) => result
|
|
138
|
+
* ? [{type: 'users', id: result.id}]
|
|
139
|
+
* : []
|
|
140
|
+
* ```
|
|
141
|
+
*/
|
|
142
|
+
providesTags?: TagTypes extends readonly [] ? (any[] | ((result: R) => any[])) : ((TagTypes[number] | {
|
|
143
|
+
type: TagTypes[number];
|
|
144
|
+
id?: string | number;
|
|
145
|
+
})[] | ((result: R) => (TagTypes[number] | {
|
|
146
|
+
type: TagTypes[number];
|
|
147
|
+
id?: string | number;
|
|
148
|
+
})[]));
|
|
149
|
+
} & ApiOptionBase<Arg, R>;
|
|
150
|
+
/**
|
|
151
|
+
* Configuration options for both queries and mutations.
|
|
152
|
+
* Provides hooks, transformations, and cache invalidation controls.
|
|
153
|
+
*
|
|
154
|
+
* @template Arg - Type of arguments passed to the endpoint
|
|
155
|
+
* @template R - Type of response data
|
|
156
|
+
* @template TagTypes - Union type of cache tag strings
|
|
157
|
+
*/
|
|
158
|
+
type ApiOptionMutation<Arg, R> = {} & ApiOptionBase<Arg, R>;
|
|
159
|
+
/**
|
|
160
|
+
* Query endpoint definition for read-only data fetching.
|
|
161
|
+
*
|
|
162
|
+
* Queries are cached and automatically refetched when invalidated.
|
|
163
|
+
* Perfect for GET requests and data fetching operations.
|
|
164
|
+
*
|
|
165
|
+
* @template Arg - Type of query arguments
|
|
166
|
+
* @template Result - Type of response data
|
|
167
|
+
* @template TagTypes - Union type of cache tag strings
|
|
168
|
+
*/
|
|
169
|
+
type QueryDef<Arg, Result, TagTypes extends readonly string[] = readonly []> = {
|
|
170
|
+
/** Marks this endpoint as a query (read-only) */
|
|
28
171
|
type: 'query';
|
|
172
|
+
/** Function that builds the query request */
|
|
29
173
|
queryFn?: QueryFn<Arg>;
|
|
30
|
-
} &
|
|
31
|
-
|
|
174
|
+
} & ApiOptionQuery<Arg, Result, TagTypes>;
|
|
175
|
+
/**
|
|
176
|
+
* Mutation endpoint definition for write operations (create, update, delete).
|
|
177
|
+
*
|
|
178
|
+
* Mutations are not cached and must be explicitly invoked.
|
|
179
|
+
* Perfect for POST, PUT, DELETE requests.
|
|
180
|
+
*
|
|
181
|
+
* @template Arg - Type of mutation arguments/input
|
|
182
|
+
* @template Result - Type of response data
|
|
183
|
+
* @template TagTypes - Union type of cache tag strings
|
|
184
|
+
*/
|
|
185
|
+
type MutationDef<Arg, Result, TagTypes extends readonly string[] = readonly []> = {
|
|
186
|
+
/** Marks this endpoint as a mutation (write operation) */
|
|
32
187
|
type: 'mutation';
|
|
188
|
+
/** Function that builds the mutation request */
|
|
33
189
|
queryFn?: QueryFn<Arg>;
|
|
34
|
-
} &
|
|
35
|
-
|
|
190
|
+
} & ApiOptionMutation<Arg, Result>;
|
|
191
|
+
/**
|
|
192
|
+
* Union type for endpoint definitions.
|
|
193
|
+
* Can be either a query or mutation endpoint.
|
|
194
|
+
*
|
|
195
|
+
* @template TagTypes - Union type of cache tag strings
|
|
196
|
+
*/
|
|
197
|
+
type EndpointDef<TagTypes extends readonly string[] = readonly []> = QueryDef<any, any, TagTypes> | MutationDef<any, any, TagTypes>;
|
|
198
|
+
/**
|
|
199
|
+
* Return type for query hooks.
|
|
200
|
+
* Provides data, loading states, error information, and refetch capability.
|
|
201
|
+
*
|
|
202
|
+
* @template Result - Type of response data
|
|
203
|
+
*
|
|
204
|
+
* @example
|
|
205
|
+
* ```typescript
|
|
206
|
+
* const {data, isLoading, isError, error, reFetch} = useGetUserQuery({id: 1});
|
|
207
|
+
* if (isLoading) return <Spinner />;
|
|
208
|
+
* if (isError) return <Error message={error.message} />;
|
|
209
|
+
* return <User data={data} onRefresh={reFetch} />;
|
|
210
|
+
* ```
|
|
211
|
+
*/
|
|
36
212
|
type MainQueryHookResult<Result> = {
|
|
213
|
+
/** The fetched data from the endpoint */
|
|
37
214
|
data?: Result;
|
|
215
|
+
/** True while the query is first loading */
|
|
38
216
|
isLoading: boolean;
|
|
217
|
+
/** True if the query encountered an error */
|
|
39
218
|
isError: boolean;
|
|
219
|
+
/** True while refetching data in the background */
|
|
40
220
|
isFetching: boolean;
|
|
221
|
+
/** True if the query completed successfully */
|
|
41
222
|
isSuccess: boolean;
|
|
223
|
+
/** The error object if the query failed */
|
|
42
224
|
error: any;
|
|
225
|
+
/** Function to manually refetch the data */
|
|
43
226
|
reFetch: () => MainQueryReturnTypes;
|
|
44
227
|
};
|
|
228
|
+
/**
|
|
229
|
+
* State type for mutation hooks.
|
|
230
|
+
* Provides result, loading states, and error information.
|
|
231
|
+
*
|
|
232
|
+
* @template Result - Type of mutation response data
|
|
233
|
+
*
|
|
234
|
+
* @example
|
|
235
|
+
* ```typescript
|
|
236
|
+
* const [createUser, {data, isLoading, isError}] = useCreateUserMutation();
|
|
237
|
+
*
|
|
238
|
+
* const handleSubmit = async (input) => {
|
|
239
|
+
* await createUser(input);
|
|
240
|
+
* };
|
|
241
|
+
* ```
|
|
242
|
+
*/
|
|
45
243
|
type MainMutationState<Result> = {
|
|
244
|
+
/** The response data from the mutation */
|
|
46
245
|
data?: Result;
|
|
246
|
+
/** True while the mutation is executing */
|
|
47
247
|
isLoading: boolean;
|
|
248
|
+
/** True if the mutation encountered an error */
|
|
48
249
|
isError: boolean;
|
|
250
|
+
/** True if the mutation completed successfully */
|
|
49
251
|
isSuccess: boolean;
|
|
252
|
+
/** The error object if the mutation failed */
|
|
50
253
|
error: any;
|
|
51
254
|
};
|
|
52
|
-
|
|
53
|
-
|
|
255
|
+
/**
|
|
256
|
+
* Map of endpoint definitions for an API.
|
|
257
|
+
* Keys are endpoint names, values are query/mutation definitions.
|
|
258
|
+
*
|
|
259
|
+
* @template TagTypes - Tuple of cache tag types (e.g., ['users', 'posts'])
|
|
260
|
+
*
|
|
261
|
+
* @example
|
|
262
|
+
* ```typescript
|
|
263
|
+
* type UserAPI = EndpointsMap<['users', 'posts']>;
|
|
264
|
+
* // Equivalent to:
|
|
265
|
+
* {
|
|
266
|
+
* getUser: QueryDef<{id: number}, User, ['users', 'posts']>;
|
|
267
|
+
* createUser: MutationDef<CreateUserInput, User, ['users', 'posts']>;
|
|
268
|
+
* }
|
|
269
|
+
* ```
|
|
270
|
+
*/
|
|
271
|
+
type EndpointsMap<TagTypes extends readonly string[] = readonly []> = Record<string, EndpointDef<TagTypes>>;
|
|
272
|
+
/** @internal Infers argument type from a query definition */
|
|
273
|
+
type InferQueryArg<T> = T extends QueryDef<infer Arg, any, any> ? Arg : never;
|
|
274
|
+
/**
|
|
275
|
+
* Keys of all query endpoints in an endpoints map.
|
|
276
|
+
* Filters out mutations to get only query names.
|
|
277
|
+
* @internal Internal type utility
|
|
278
|
+
*/
|
|
279
|
+
type QueryKeys<T> = {
|
|
280
|
+
[K in keyof T]: T[K] extends QueryDef<any, any, any> ? K : never;
|
|
281
|
+
}[keyof T];
|
|
282
|
+
/** @internal Infers result type from a query definition */
|
|
283
|
+
type InferQueryResult<T> = T extends QueryDef<any, infer Result, any> ? Result : never;
|
|
284
|
+
/**
|
|
285
|
+
* Generated hooks and utilities from an endpoints map.
|
|
286
|
+
* Dynamically creates hooks for each query and mutation endpoint.
|
|
287
|
+
* Hook names are generated as useNameQuery or useNameMutation based on endpoint type.
|
|
288
|
+
*
|
|
289
|
+
* @template T - The endpoints map
|
|
290
|
+
* @template TagTypes - The cache tag types
|
|
291
|
+
*
|
|
292
|
+
* @example
|
|
293
|
+
* ```typescript
|
|
294
|
+
* // Given this API definition:
|
|
295
|
+
* const api = createApi({
|
|
296
|
+
* tagTypes: ['users'] as const,
|
|
297
|
+
* endpoints: (builder) => ({
|
|
298
|
+
* getUser: builder.query({
|
|
299
|
+
* query: ({id}) => `/users/${id}`,
|
|
300
|
+
* providesTags: ['users']
|
|
301
|
+
* }),
|
|
302
|
+
* createUser: builder.mutation({
|
|
303
|
+
* query: (input) => ({
|
|
304
|
+
* url: '/users',
|
|
305
|
+
* method: 'POST',
|
|
306
|
+
* body: input
|
|
307
|
+
* }),
|
|
308
|
+
* invalidateTags: ['users']
|
|
309
|
+
* })
|
|
310
|
+
* })
|
|
311
|
+
* });
|
|
312
|
+
*
|
|
313
|
+
* // You get these hooks:
|
|
314
|
+
* api.useGetUserQuery({id: 1}); // Returns {data, isLoading, error, reFetch}
|
|
315
|
+
* api.useCreateUserMutation(); // Returns [mutate, {data, isLoading, error}]
|
|
316
|
+
* api.utils.invalidateTags(['users']); // Invalidate users cache
|
|
317
|
+
* api.utils.updateQueryData('getUser', {id: 1}, (draft) => {...});
|
|
318
|
+
* ```
|
|
319
|
+
*/
|
|
320
|
+
type HooksFromEndpoints<T extends EndpointsMap<TagTypes>, TagTypes extends readonly string[] = readonly []> = {
|
|
54
321
|
[K in keyof T as T[K] extends {
|
|
55
322
|
type: 'query';
|
|
56
|
-
} ? `use${Capitalize<string & K>}Query` : `use${Capitalize<string & K>}Mutation`]: T[K] extends QueryDef<infer Arg, infer Result> ? (arg: Arg, option?: QueryHookOption) => MainQueryHookResult<Result> : T[K] extends MutationDef<infer Arg, infer Result> ? () => readonly [
|
|
323
|
+
} ? `use${Capitalize<string & K>}Query` : `use${Capitalize<string & K>}Mutation`]: T[K] extends QueryDef<infer Arg, infer Result, any> ? (arg: Arg, option?: QueryHookOption) => MainQueryHookResult<Result> : T[K] extends MutationDef<infer Arg, infer Result, any> ? () => readonly [
|
|
324
|
+
(arg: Arg) => Promise<Result>,
|
|
325
|
+
MainMutationState<Result>
|
|
326
|
+
] : never;
|
|
327
|
+
} & {
|
|
328
|
+
/** Utilities for cache management and manual updates */
|
|
329
|
+
utils: {
|
|
330
|
+
/**
|
|
331
|
+
* Manually update query cache data with optimistic updates.
|
|
332
|
+
*
|
|
333
|
+
* @example
|
|
334
|
+
* ```typescript
|
|
335
|
+
* api.utils.updateQueryData('getUser', {id: 1}, (draft) => {
|
|
336
|
+
* draft.name = 'Updated Name';
|
|
337
|
+
* });
|
|
338
|
+
* ```
|
|
339
|
+
*/
|
|
340
|
+
updateQueryData: <K extends QueryKeys<T>>(key: K, arg: InferQueryArg<T[K]>, updater: (data: InferQueryResult<T[K]>) => InferQueryResult<T[K]>) => void;
|
|
341
|
+
/**
|
|
342
|
+
* Invalidate cache tags to trigger refetches of affected queries.
|
|
343
|
+
* Supports both string tags and object tags with IDs.
|
|
344
|
+
*
|
|
345
|
+
* @example
|
|
346
|
+
* ```typescript
|
|
347
|
+
* // Invalidate all users queries
|
|
348
|
+
* api.utils.invalidateTags(['users']);
|
|
349
|
+
*
|
|
350
|
+
* // Invalidate specific user with ID
|
|
351
|
+
* api.utils.invalidateTags([{type: 'users', id: '123'}]);
|
|
352
|
+
*
|
|
353
|
+
* // Mix both formats
|
|
354
|
+
* api.utils.invalidateTags(['users', {type: 'posts', id: 'abc'}]);
|
|
355
|
+
* ```
|
|
356
|
+
*/
|
|
357
|
+
invalidateTags: TagTypes extends readonly [] ? (tags?: any[]) => void : (tags?: TagTypes[number][]) => void;
|
|
358
|
+
/**
|
|
359
|
+
* Reset the entire API state, clearing all cached data and refetching active queries.
|
|
360
|
+
* Useful for scenarios like user logout, where you want to clear all user-specific data.
|
|
361
|
+
* This will set all cache expiration times to 0 and trigger refetches for any active queries.
|
|
362
|
+
* @example
|
|
363
|
+
* ```typescript
|
|
364
|
+
* // Reset API state on user logout
|
|
365
|
+
* const handleLogout = () => {
|
|
366
|
+
* api.utils.resetApiState();
|
|
367
|
+
* // Additional logout logic...
|
|
368
|
+
* };
|
|
369
|
+
* ```
|
|
370
|
+
*/
|
|
371
|
+
resetApiState(): void;
|
|
372
|
+
/**
|
|
373
|
+
* Clears cache and refetches a specific query by endpoint key and arguments.
|
|
374
|
+
*
|
|
375
|
+
* Useful when you want to refresh a single query without affecting others.
|
|
376
|
+
*
|
|
377
|
+
* @template K - The endpoint key
|
|
378
|
+
* @param key - The endpoint name (e.g., 'getUser', 'getUsers')
|
|
379
|
+
* @param arg - The arguments used when calling the endpoint
|
|
380
|
+
*
|
|
381
|
+
* @example
|
|
382
|
+
* ```typescript
|
|
383
|
+
* // Refresh a specific user query
|
|
384
|
+
* api.utils.refetchQuery('getUser', {id: 1});
|
|
385
|
+
* ```
|
|
386
|
+
*/
|
|
387
|
+
refetchQuery<K extends QueryKeys<T>>(key: K, arg: InferQueryArg<T[K]>): void;
|
|
388
|
+
};
|
|
57
389
|
};
|
|
58
|
-
|
|
390
|
+
/**
|
|
391
|
+
* Builder helper for creating query and mutation endpoints.
|
|
392
|
+
* Passed as parameter to the endpoints factory function in createApi.
|
|
393
|
+
*
|
|
394
|
+
* @template TagTypes - Union type of cache tag strings
|
|
395
|
+
*
|
|
396
|
+
* @example
|
|
397
|
+
* ```typescript
|
|
398
|
+
* const api = createApi({
|
|
399
|
+
* baseQuery,
|
|
400
|
+
* tagTypes: ['users', 'posts'] as const,
|
|
401
|
+
* endpoints: (builder) => ({
|
|
402
|
+
* getUser: builder.query({
|
|
403
|
+
* query: ({id}) => `/users/${id}`,
|
|
404
|
+
* providesTags: ['users'],
|
|
405
|
+
* onSuccess: (data) => console.log('User fetched:', data)
|
|
406
|
+
* }),
|
|
407
|
+
* createPost: builder.mutation({
|
|
408
|
+
* query: (post) => ({
|
|
409
|
+
* url: '/posts',
|
|
410
|
+
* method: 'POST',
|
|
411
|
+
* body: post
|
|
412
|
+
* }),
|
|
413
|
+
* invalidateTags: ['posts']
|
|
414
|
+
* })
|
|
415
|
+
* })
|
|
416
|
+
* });
|
|
417
|
+
* ```
|
|
418
|
+
*/
|
|
419
|
+
type BuilderType<TagTypes extends readonly string[] = readonly []> = {
|
|
420
|
+
/**
|
|
421
|
+
* Create a read-only query endpoint for data fetching.
|
|
422
|
+
*
|
|
423
|
+
* @param config - Configuration including query function and options
|
|
424
|
+
* @returns Query endpoint definition
|
|
425
|
+
*/
|
|
59
426
|
query<Result, Arg = void>(config: {
|
|
60
427
|
query?: (arg: Arg) => QueryFnReturn;
|
|
61
|
-
} &
|
|
428
|
+
} & ApiOptionQuery<Arg, Result, TagTypes>): QueryDef<Arg, Result, TagTypes>;
|
|
429
|
+
/**
|
|
430
|
+
* Create a write operation mutation endpoint.
|
|
431
|
+
*
|
|
432
|
+
* @param config - Configuration including query function and options
|
|
433
|
+
* @returns Mutation endpoint definition
|
|
434
|
+
*/
|
|
62
435
|
mutation<Result, Arg = void>(config: {
|
|
63
436
|
query?: (arg: Arg) => QueryFnObj;
|
|
64
|
-
} &
|
|
437
|
+
} & ApiOptionMutation<Arg, Result>): MutationDef<Arg, Result, TagTypes>;
|
|
65
438
|
};
|
|
439
|
+
/** @internal Base query return type with discriminated union for success/error */
|
|
66
440
|
type BaseQueryReturn<Data = any, Error = any> = {
|
|
67
441
|
data: Data;
|
|
68
442
|
error?: undefined;
|
|
@@ -70,22 +444,145 @@ type BaseQueryReturn<Data = any, Error = any> = {
|
|
|
70
444
|
data?: undefined;
|
|
71
445
|
error: Error;
|
|
72
446
|
};
|
|
73
|
-
|
|
447
|
+
/**
|
|
448
|
+
* Parameters for createApi function.
|
|
449
|
+
* Configures the API with base query, endpoints, caching, middleware, and plugins.
|
|
450
|
+
*
|
|
451
|
+
* @template T - Endpoints map type
|
|
452
|
+
* @template TagTypes - Cache tag type tuple
|
|
453
|
+
*
|
|
454
|
+
* @example
|
|
455
|
+
* ```typescript
|
|
456
|
+
* const api = createApi<typeof api, ['users', 'posts']>({
|
|
457
|
+
* baseQuery: async (queryArg) => {
|
|
458
|
+
* try {
|
|
459
|
+
* const result = await fetch(queryArg).then(r => r.json());
|
|
460
|
+
* return { data: result };
|
|
461
|
+
* } catch (error) {
|
|
462
|
+
* return { error: error.message };
|
|
463
|
+
* }
|
|
464
|
+
* },
|
|
465
|
+
* tagTypes: ['users', 'posts'] as const,
|
|
466
|
+
* cacheTimeout: 5 * 60 * 1000, // 5 minutes
|
|
467
|
+
* endpoints: (builder) => ({
|
|
468
|
+
* getUser: builder.query({
|
|
469
|
+
* query: ({id}) => `/users/${id}`,
|
|
470
|
+
* providesTags: ['users']
|
|
471
|
+
* })
|
|
472
|
+
* }),
|
|
473
|
+
* middlewares: [loggerMiddleware],
|
|
474
|
+
* plugins: [persistencePlugin]
|
|
475
|
+
* });
|
|
476
|
+
* ```
|
|
477
|
+
*/
|
|
478
|
+
interface CreateApiParams<T extends EndpointsMap<TagTypes>, TagTypes extends readonly string[] = readonly []> {
|
|
479
|
+
/**
|
|
480
|
+
* HTTP client function that executes requests.
|
|
481
|
+
* Receives QueryFnReturn and returns success/error response.
|
|
482
|
+
*/
|
|
74
483
|
baseQuery: (option: QueryFnReturn) => Promise<BaseQueryReturn>;
|
|
75
|
-
|
|
484
|
+
/**
|
|
485
|
+
* Factory function that creates all endpoint definitions.
|
|
486
|
+
* Receives builder with query and mutation helpers.
|
|
487
|
+
*/
|
|
488
|
+
endpoints: (builder: BuilderType<TagTypes>) => T;
|
|
489
|
+
/**
|
|
490
|
+
* How long to cache query results in milliseconds.
|
|
491
|
+
* Default: 5 minutes (300000ms).
|
|
492
|
+
* @default 300000
|
|
493
|
+
*/
|
|
76
494
|
cacheTimeout?: number;
|
|
495
|
+
/**
|
|
496
|
+
* Global middleware applied to all endpoints.
|
|
497
|
+
* Executed before individual endpoint middleware.
|
|
498
|
+
*/
|
|
77
499
|
middlewares?: ApiMiddleware[];
|
|
500
|
+
/**
|
|
501
|
+
* Global plugins with lifecycle hooks.
|
|
502
|
+
* Executed for all query and mutation operations.
|
|
503
|
+
*/
|
|
78
504
|
plugins?: ApiPlugin[];
|
|
505
|
+
/**
|
|
506
|
+
* Cache tag types used for cache invalidation.
|
|
507
|
+
* Must match tags in providesTags and invalidateTags.
|
|
508
|
+
* @example
|
|
509
|
+
* ```typescript
|
|
510
|
+
* tagTypes: ['users', 'posts', 'comments'] as const
|
|
511
|
+
* ```
|
|
512
|
+
*/
|
|
513
|
+
tagTypes?: TagTypes;
|
|
79
514
|
}
|
|
515
|
+
/**
|
|
516
|
+
* Options passed to query hooks for behavior control.
|
|
517
|
+
*
|
|
518
|
+
* @example
|
|
519
|
+
* ```typescript
|
|
520
|
+
* // Skip loading the query initially
|
|
521
|
+
* const {data} = useGetUserQuery({id: 1}, {skip: true});
|
|
522
|
+
*
|
|
523
|
+
* // Later trigger the query
|
|
524
|
+
* const {data, reFetch} = useGetUserQuery({id: 1}, {skip: false});
|
|
525
|
+
* if (data) {
|
|
526
|
+
* await reFetch();
|
|
527
|
+
* }
|
|
528
|
+
* ```
|
|
529
|
+
*/
|
|
80
530
|
interface QueryHookOption {
|
|
531
|
+
/** If true, skips executing the query */
|
|
81
532
|
skip: boolean;
|
|
82
533
|
}
|
|
534
|
+
/**
|
|
535
|
+
* Context object passed to middleware functions.
|
|
536
|
+
* Contains query arguments, endpoint definition, and store access.
|
|
537
|
+
*
|
|
538
|
+
* @example
|
|
539
|
+
* ```typescript
|
|
540
|
+
* const loggingMiddleware: ApiMiddleware = async (ctx, next) => {
|
|
541
|
+
* console.log('Query starting:', ctx.arg);
|
|
542
|
+
* const result = await next();
|
|
543
|
+
* console.log('Query finished:', result);
|
|
544
|
+
* return result;
|
|
545
|
+
* };
|
|
546
|
+
* ```
|
|
547
|
+
*/
|
|
83
548
|
type MiddlewareContext = {
|
|
549
|
+
/** Arguments passed to the query or mutation */
|
|
84
550
|
arg: any;
|
|
551
|
+
/** The endpoint definition */
|
|
85
552
|
def: any;
|
|
553
|
+
/** Store getter function */
|
|
86
554
|
get: any;
|
|
555
|
+
/** Store setter function */
|
|
87
556
|
set: any;
|
|
88
557
|
};
|
|
558
|
+
/**
|
|
559
|
+
* Middleware function type for intercepting and modifying requests/responses.
|
|
560
|
+
* Similar to Express middleware with async/await support.
|
|
561
|
+
*
|
|
562
|
+
* Middlewares execute in pipeline order and can:
|
|
563
|
+
* - Transform requests before execution
|
|
564
|
+
* - Intercept responses
|
|
565
|
+
* - Handle errors
|
|
566
|
+
* - Add logging or monitoring
|
|
567
|
+
*
|
|
568
|
+
* @example
|
|
569
|
+
* ```typescript
|
|
570
|
+
* const authMiddleware: ApiMiddleware = async (ctx, next) => {
|
|
571
|
+
* // Add auth token before request
|
|
572
|
+
* const authToken = localStorage.getItem('token');
|
|
573
|
+
*
|
|
574
|
+
* const result = await next();
|
|
575
|
+
*
|
|
576
|
+
* // Check for auth errors
|
|
577
|
+
* if (result.error?.status === 401) {
|
|
578
|
+
* // Handle unauthorized
|
|
579
|
+
* localStorage.removeItem('token');
|
|
580
|
+
* }
|
|
581
|
+
*
|
|
582
|
+
* return result;
|
|
583
|
+
* };
|
|
584
|
+
* ```
|
|
585
|
+
*/
|
|
89
586
|
type ApiMiddleware = (ctx: MiddlewareContext, next: () => Promise<{
|
|
90
587
|
data?: any;
|
|
91
588
|
error?: any;
|
|
@@ -93,24 +590,124 @@ type ApiMiddleware = (ctx: MiddlewareContext, next: () => Promise<{
|
|
|
93
590
|
data?: any;
|
|
94
591
|
error?: any;
|
|
95
592
|
}>;
|
|
593
|
+
/**
|
|
594
|
+
* Plugin object with lifecycle hooks for cross-cutting concerns.
|
|
595
|
+
* Plugins execute at specific points in the query/mutation lifecycle.
|
|
596
|
+
*
|
|
597
|
+
* @example
|
|
598
|
+
* ```typescript
|
|
599
|
+
* const analyticsPlugin: ApiPlugin = {
|
|
600
|
+
* name: 'analytics',
|
|
601
|
+
* beforeQuery: (ctx) => {
|
|
602
|
+
* gtag.event('api_call', {endpoint: ctx.def.name});
|
|
603
|
+
* },
|
|
604
|
+
* afterQuery: (result, ctx) => {
|
|
605
|
+
* gtag.event('api_response', {
|
|
606
|
+
* endpoint: ctx.def.name,
|
|
607
|
+
* success: !result.error
|
|
608
|
+
* });
|
|
609
|
+
* },
|
|
610
|
+
* onError: (error, ctx) => {
|
|
611
|
+
* gtag.event('api_error', {
|
|
612
|
+
* endpoint: ctx.def.name,
|
|
613
|
+
* error: error.message
|
|
614
|
+
* });
|
|
615
|
+
* }
|
|
616
|
+
* };
|
|
617
|
+
* ```
|
|
618
|
+
*/
|
|
96
619
|
type ApiPlugin = {
|
|
620
|
+
/** Unique identifier for the plugin */
|
|
97
621
|
name: string;
|
|
622
|
+
/**
|
|
623
|
+
* Called once when the API is created.
|
|
624
|
+
* Use for initialization and setup.
|
|
625
|
+
*/
|
|
98
626
|
onInit?: (api: {
|
|
99
627
|
baseQuery: any;
|
|
100
628
|
endpoints: any;
|
|
101
629
|
}) => void;
|
|
630
|
+
/**
|
|
631
|
+
* Called before executing a query or mutation.
|
|
632
|
+
* Can perform setup tasks like loading UI state.
|
|
633
|
+
*/
|
|
102
634
|
beforeQuery?: (ctx: PluginContext) => void | Promise<void>;
|
|
635
|
+
/**
|
|
636
|
+
* Middleware handler for intercepting requests/responses.
|
|
637
|
+
* Executed in the middleware pipeline.
|
|
638
|
+
*/
|
|
103
639
|
middleware?: ApiMiddleware;
|
|
640
|
+
/**
|
|
641
|
+
* Called after successful query or mutation execution.
|
|
642
|
+
* Perfect for success notifications and logging.
|
|
643
|
+
*/
|
|
104
644
|
afterQuery?: (result: any, ctx: PluginContext) => void | Promise<void>;
|
|
645
|
+
/**
|
|
646
|
+
* Called when query or mutation encounters an error.
|
|
647
|
+
* Use for error logging, notifications, or recovery.
|
|
648
|
+
*/
|
|
105
649
|
onError?: (error: any, ctx: PluginContext) => void | Promise<void>;
|
|
106
650
|
};
|
|
651
|
+
/**
|
|
652
|
+
* Context object passed to plugin lifecycle hooks.
|
|
653
|
+
* Contains execution context including arguments and store access.
|
|
654
|
+
*
|
|
655
|
+
* @internal Used internally by plugin system
|
|
656
|
+
*/
|
|
107
657
|
type PluginContext = {
|
|
658
|
+
/** Arguments passed to the query or mutation */
|
|
108
659
|
arg: any;
|
|
660
|
+
/** The endpoint definition */
|
|
109
661
|
def: any;
|
|
662
|
+
/** Store getter function */
|
|
110
663
|
get: any;
|
|
664
|
+
/** Store setter function */
|
|
111
665
|
set: any;
|
|
112
666
|
};
|
|
113
667
|
|
|
114
|
-
|
|
668
|
+
/**
|
|
669
|
+
* Creates an API instance with typed queries, mutations, and utilities.
|
|
670
|
+
*
|
|
671
|
+
* The createApi function is the main entry point for setting up your API.
|
|
672
|
+
* It generates typed hooks for each endpoint defined and provides utility functions
|
|
673
|
+
* for cache management.
|
|
674
|
+
*
|
|
675
|
+
* @template TagTypes - Union type of tag names for cache invalidation
|
|
676
|
+
* @template T - EndpointsMap type with all endpoints
|
|
677
|
+
*
|
|
678
|
+
* @param params - Configuration object containing:
|
|
679
|
+
* - baseQuery: Function to make HTTP requests
|
|
680
|
+
* - endpoints: Function that defines all API endpoints
|
|
681
|
+
* - cacheTimeout: (Optional) Cache duration in milliseconds (default: 30s)
|
|
682
|
+
* - middlewares: (Optional) Global middleware functions
|
|
683
|
+
* - plugins: (Optional) Plugin objects with lifecycle hooks
|
|
684
|
+
* - tagTypes: (Optional) Array of tag type strings for cache invalidation
|
|
685
|
+
*
|
|
686
|
+
* @returns Object containing:
|
|
687
|
+
* - Generated hooks (useXxxQuery, useXxxMutation) for each endpoint
|
|
688
|
+
* - utils object with updateQueryData and invalidateTags functions
|
|
689
|
+
*
|
|
690
|
+
* @example
|
|
691
|
+
* ```typescript
|
|
692
|
+
* const api = createApi({
|
|
693
|
+
* baseQuery: async (params) => {
|
|
694
|
+
* const response = await fetch(params.url, {method: params.method});
|
|
695
|
+
* return {data: await response.json()};
|
|
696
|
+
* },
|
|
697
|
+
* tagTypes: ['users', 'posts'] as const,
|
|
698
|
+
* endpoints: (builder) => ({
|
|
699
|
+
* getUsers: builder.query<User[]>({
|
|
700
|
+
* query: () => ({url: '/users', method: 'GET'}),
|
|
701
|
+
* providesTags: ['users'],
|
|
702
|
+
* }),
|
|
703
|
+
* createUser: builder.mutation<User, CreateUserInput>({
|
|
704
|
+
* query: (body) => ({url: '/users', method: 'POST', body}),
|
|
705
|
+
* invalidateTags: ['users'],
|
|
706
|
+
* }),
|
|
707
|
+
* }),
|
|
708
|
+
* });
|
|
709
|
+
* ```
|
|
710
|
+
*/
|
|
711
|
+
declare function createApi<const TagTypes extends readonly string[] = readonly [], T extends EndpointsMap<TagTypes> = EndpointsMap<TagTypes>>(params: CreateApiParams<T, TagTypes>): HooksFromEndpoints<T, TagTypes>;
|
|
115
712
|
|
|
116
713
|
export { type ApiMiddleware, type ApiPlugin, createApi };
|