@web-ts-toolkit/access-router-react 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +70 -0
- package/index.d.mts +176 -0
- package/index.d.ts +176 -0
- package/index.js +610 -0
- package/index.mjs +583 -0
- package/package.json +43 -0
package/index.mjs
ADDED
|
@@ -0,0 +1,583 @@
|
|
|
1
|
+
// src/create-model-hook.ts
|
|
2
|
+
import { useState, useEffect as useEffect2, useRef as useRef2, useCallback as useCallback2 } from "react";
|
|
3
|
+
|
|
4
|
+
// src/fetch.ts
|
|
5
|
+
import { useEffect, useRef, useCallback } from "react";
|
|
6
|
+
function isAbortError(err) {
|
|
7
|
+
return err instanceof DOMException && err.name === "AbortError";
|
|
8
|
+
}
|
|
9
|
+
function useAbortManager() {
|
|
10
|
+
const ref = useRef(null);
|
|
11
|
+
const replace = useCallback((next) => {
|
|
12
|
+
ref.current?.abort();
|
|
13
|
+
ref.current = next;
|
|
14
|
+
}, []);
|
|
15
|
+
useEffect(() => {
|
|
16
|
+
return () => {
|
|
17
|
+
ref.current?.abort();
|
|
18
|
+
ref.current = null;
|
|
19
|
+
};
|
|
20
|
+
}, []);
|
|
21
|
+
return { replace };
|
|
22
|
+
}
|
|
23
|
+
function stableStringify(value) {
|
|
24
|
+
if (value == null) return "";
|
|
25
|
+
if (typeof value !== "object") return JSON.stringify(value);
|
|
26
|
+
if (Array.isArray(value)) return `[${value.map(stableStringify).join(",")}]`;
|
|
27
|
+
const keys = Object.keys(value).sort();
|
|
28
|
+
return `{${keys.map((k) => `${JSON.stringify(k)}:${stableStringify(value[k])}`).join(",")}}`;
|
|
29
|
+
}
|
|
30
|
+
function useMountRef() {
|
|
31
|
+
const ref = useRef(true);
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
ref.current = true;
|
|
34
|
+
return () => {
|
|
35
|
+
ref.current = false;
|
|
36
|
+
};
|
|
37
|
+
}, []);
|
|
38
|
+
return ref;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// src/create-model-hook.ts
|
|
42
|
+
function useAutoQuery({
|
|
43
|
+
doFetch,
|
|
44
|
+
applyResult,
|
|
45
|
+
shouldFetch,
|
|
46
|
+
deps,
|
|
47
|
+
onSuccess,
|
|
48
|
+
onError,
|
|
49
|
+
onSettled
|
|
50
|
+
}) {
|
|
51
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
52
|
+
const [isFetching, setIsFetching] = useState(false);
|
|
53
|
+
const [error, setError] = useState(null);
|
|
54
|
+
const manager = useAbortManager();
|
|
55
|
+
const mountRef = useMountRef();
|
|
56
|
+
const fetchAndSet = useCallback2(
|
|
57
|
+
async (signal) => {
|
|
58
|
+
setIsFetching(true);
|
|
59
|
+
setError(null);
|
|
60
|
+
try {
|
|
61
|
+
return await doFetch(signal);
|
|
62
|
+
} catch (err) {
|
|
63
|
+
if (!isAbortError(err)) setError(err);
|
|
64
|
+
throw err;
|
|
65
|
+
} finally {
|
|
66
|
+
if (!signal?.aborted) setIsFetching(false);
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
[doFetch]
|
|
70
|
+
);
|
|
71
|
+
const doFetchWithCallbacks = useCallback2(
|
|
72
|
+
async (signal) => {
|
|
73
|
+
const res = await fetchAndSet(signal);
|
|
74
|
+
if (!signal?.aborted) {
|
|
75
|
+
applyResult(res);
|
|
76
|
+
onSuccess?.(res);
|
|
77
|
+
onSettled?.(res, null);
|
|
78
|
+
}
|
|
79
|
+
return res;
|
|
80
|
+
},
|
|
81
|
+
[fetchAndSet, applyResult, onSuccess, onSettled]
|
|
82
|
+
);
|
|
83
|
+
useEffect2(() => {
|
|
84
|
+
if (!shouldFetch) return;
|
|
85
|
+
mountRef.current = true;
|
|
86
|
+
setIsLoading(true);
|
|
87
|
+
const controller = new AbortController();
|
|
88
|
+
manager.replace(controller);
|
|
89
|
+
doFetchWithCallbacks(controller.signal).catch((err) => {
|
|
90
|
+
if (!mountRef.current || controller.signal.aborted) return;
|
|
91
|
+
onError?.(err);
|
|
92
|
+
onSettled?.(null, err);
|
|
93
|
+
}).finally(() => {
|
|
94
|
+
if (mountRef.current && !controller.signal.aborted) setIsLoading(false);
|
|
95
|
+
});
|
|
96
|
+
return () => {
|
|
97
|
+
mountRef.current = false;
|
|
98
|
+
controller.abort();
|
|
99
|
+
};
|
|
100
|
+
}, deps);
|
|
101
|
+
const refetch = useCallback2(() => {
|
|
102
|
+
setIsLoading(true);
|
|
103
|
+
const controller = new AbortController();
|
|
104
|
+
manager.replace(controller);
|
|
105
|
+
doFetchWithCallbacks(controller.signal).catch(() => {
|
|
106
|
+
}).finally(() => {
|
|
107
|
+
if (!controller.signal.aborted) setIsLoading(false);
|
|
108
|
+
});
|
|
109
|
+
}, [doFetchWithCallbacks, manager]);
|
|
110
|
+
return { isLoading, isFetching, error, setError, refetch, manager, mountRef };
|
|
111
|
+
}
|
|
112
|
+
function useMutation(execute, options) {
|
|
113
|
+
const [isPending, setIsPending] = useState(false);
|
|
114
|
+
const [error, setError] = useState(null);
|
|
115
|
+
const mountRef = useMountRef();
|
|
116
|
+
const { onSuccess, onSettled } = options ?? {};
|
|
117
|
+
const executeMutate = useCallback2(
|
|
118
|
+
async (...args) => {
|
|
119
|
+
setIsPending(true);
|
|
120
|
+
setError(null);
|
|
121
|
+
try {
|
|
122
|
+
const result = await execute(...args);
|
|
123
|
+
if (mountRef.current) {
|
|
124
|
+
onSuccess?.(result);
|
|
125
|
+
onSettled?.(result, null);
|
|
126
|
+
}
|
|
127
|
+
return result;
|
|
128
|
+
} catch (err) {
|
|
129
|
+
const svcErr = err;
|
|
130
|
+
if (mountRef.current) {
|
|
131
|
+
setError(svcErr);
|
|
132
|
+
onSettled?.(null, svcErr);
|
|
133
|
+
}
|
|
134
|
+
throw svcErr;
|
|
135
|
+
} finally {
|
|
136
|
+
if (mountRef.current) setIsPending(false);
|
|
137
|
+
}
|
|
138
|
+
},
|
|
139
|
+
[execute, mountRef, onSuccess, onSettled]
|
|
140
|
+
);
|
|
141
|
+
const reset = useCallback2(() => setError(null), []);
|
|
142
|
+
return { isPending, error, executeMutate, reset };
|
|
143
|
+
}
|
|
144
|
+
function createModelHooks(config) {
|
|
145
|
+
const { modelService } = config;
|
|
146
|
+
function useRead(options = {}) {
|
|
147
|
+
const {
|
|
148
|
+
id,
|
|
149
|
+
advanced,
|
|
150
|
+
select,
|
|
151
|
+
populate,
|
|
152
|
+
sort,
|
|
153
|
+
include,
|
|
154
|
+
tasks,
|
|
155
|
+
basicOptions,
|
|
156
|
+
advancedOptions,
|
|
157
|
+
enabled = true,
|
|
158
|
+
initialData = null,
|
|
159
|
+
requestConfig,
|
|
160
|
+
onSuccess,
|
|
161
|
+
onError,
|
|
162
|
+
onSettled
|
|
163
|
+
} = options;
|
|
164
|
+
const [data, setData] = useState(initialData);
|
|
165
|
+
const applyResult = useCallback2((res) => {
|
|
166
|
+
setData(res.data);
|
|
167
|
+
}, []);
|
|
168
|
+
const doFetchById = useCallback2(
|
|
169
|
+
async (targetId, signal) => {
|
|
170
|
+
if (advanced) {
|
|
171
|
+
return await modelService.readAdvanced(
|
|
172
|
+
targetId,
|
|
173
|
+
{ select, populate, sort, include, tasks },
|
|
174
|
+
advancedOptions,
|
|
175
|
+
{ ...requestConfig, signal }
|
|
176
|
+
).exec();
|
|
177
|
+
}
|
|
178
|
+
return await modelService.read(targetId, basicOptions, { ...requestConfig, signal }).exec();
|
|
179
|
+
},
|
|
180
|
+
[modelService, advanced, select, populate, sort, include, tasks, basicOptions, advancedOptions, requestConfig]
|
|
181
|
+
);
|
|
182
|
+
const doFetch = useCallback2(
|
|
183
|
+
(signal) => {
|
|
184
|
+
if (!id) throw new Error("useRead: id is required");
|
|
185
|
+
return doFetchById(id, signal);
|
|
186
|
+
},
|
|
187
|
+
[doFetchById, id]
|
|
188
|
+
);
|
|
189
|
+
const shouldFetch = Boolean(id && enabled);
|
|
190
|
+
const { isLoading, isFetching, error, refetch } = useAutoQuery({
|
|
191
|
+
doFetch,
|
|
192
|
+
applyResult,
|
|
193
|
+
shouldFetch,
|
|
194
|
+
deps: [id, enabled, advanced, select, populate, sort, include, tasks, basicOptions, advancedOptions],
|
|
195
|
+
onSuccess,
|
|
196
|
+
onError,
|
|
197
|
+
onSettled
|
|
198
|
+
});
|
|
199
|
+
const query = useCallback2(
|
|
200
|
+
async (readId) => {
|
|
201
|
+
const res = await doFetchById(readId);
|
|
202
|
+
applyResult(res);
|
|
203
|
+
onSuccess?.(res);
|
|
204
|
+
onSettled?.(res, null);
|
|
205
|
+
return res;
|
|
206
|
+
},
|
|
207
|
+
[doFetchById, applyResult, onSuccess, onSettled]
|
|
208
|
+
);
|
|
209
|
+
const reset = useCallback2(() => {
|
|
210
|
+
setData(initialData);
|
|
211
|
+
}, [initialData]);
|
|
212
|
+
return { data, isLoading, isFetching, error, query, refetch, reset };
|
|
213
|
+
}
|
|
214
|
+
function useList(options = {}) {
|
|
215
|
+
const {
|
|
216
|
+
listParams,
|
|
217
|
+
filter,
|
|
218
|
+
advanced,
|
|
219
|
+
sort,
|
|
220
|
+
select,
|
|
221
|
+
populate,
|
|
222
|
+
include,
|
|
223
|
+
tasks,
|
|
224
|
+
basicOptions,
|
|
225
|
+
advancedOptions,
|
|
226
|
+
enabled = true,
|
|
227
|
+
keepPreviousData = false,
|
|
228
|
+
initialData,
|
|
229
|
+
requestConfig,
|
|
230
|
+
onSuccess,
|
|
231
|
+
onError,
|
|
232
|
+
onSettled
|
|
233
|
+
} = options;
|
|
234
|
+
const [data, setData] = useState(initialData ?? []);
|
|
235
|
+
const [previousData, setPreviousData] = useState(void 0);
|
|
236
|
+
const [totalCount, setTotalCount] = useState(0);
|
|
237
|
+
const latestDataRef = useRef2(data);
|
|
238
|
+
latestDataRef.current = data;
|
|
239
|
+
const applyResult = useCallback2((res) => {
|
|
240
|
+
setData(res.data);
|
|
241
|
+
setTotalCount(res.totalCount);
|
|
242
|
+
setPreviousData(void 0);
|
|
243
|
+
}, []);
|
|
244
|
+
const baseFetch = useCallback2(
|
|
245
|
+
async (args, signal) => {
|
|
246
|
+
if (keepPreviousData) {
|
|
247
|
+
setPreviousData(latestDataRef.current);
|
|
248
|
+
}
|
|
249
|
+
if (advanced) {
|
|
250
|
+
return await modelService.listAdvanced(
|
|
251
|
+
filter ?? {},
|
|
252
|
+
{ sort, select, populate, include, tasks, ...args },
|
|
253
|
+
advancedOptions,
|
|
254
|
+
{ ...requestConfig, signal }
|
|
255
|
+
).exec();
|
|
256
|
+
}
|
|
257
|
+
return await modelService.list(args ?? listParams, basicOptions, { ...requestConfig, signal }).exec();
|
|
258
|
+
},
|
|
259
|
+
[
|
|
260
|
+
modelService,
|
|
261
|
+
advanced,
|
|
262
|
+
filter,
|
|
263
|
+
sort,
|
|
264
|
+
select,
|
|
265
|
+
populate,
|
|
266
|
+
include,
|
|
267
|
+
tasks,
|
|
268
|
+
listParams,
|
|
269
|
+
basicOptions,
|
|
270
|
+
advancedOptions,
|
|
271
|
+
requestConfig,
|
|
272
|
+
keepPreviousData,
|
|
273
|
+
latestDataRef
|
|
274
|
+
]
|
|
275
|
+
);
|
|
276
|
+
const doFetch = useCallback2((signal) => baseFetch(listParams, signal), [baseFetch, listParams]);
|
|
277
|
+
const listParamsKey = stableStringify(listParams);
|
|
278
|
+
const filterKey = stableStringify(filter);
|
|
279
|
+
const sortKey = stableStringify(sort);
|
|
280
|
+
const shouldFetch = Boolean((listParams || advanced) && enabled);
|
|
281
|
+
const { isLoading, isFetching, error, refetch } = useAutoQuery({
|
|
282
|
+
doFetch,
|
|
283
|
+
applyResult,
|
|
284
|
+
shouldFetch,
|
|
285
|
+
deps: [
|
|
286
|
+
listParamsKey,
|
|
287
|
+
filterKey,
|
|
288
|
+
advanced,
|
|
289
|
+
enabled,
|
|
290
|
+
select,
|
|
291
|
+
populate,
|
|
292
|
+
sortKey,
|
|
293
|
+
include,
|
|
294
|
+
tasks,
|
|
295
|
+
basicOptions,
|
|
296
|
+
advancedOptions
|
|
297
|
+
],
|
|
298
|
+
onSuccess,
|
|
299
|
+
onError,
|
|
300
|
+
onSettled
|
|
301
|
+
});
|
|
302
|
+
const query = useCallback2(
|
|
303
|
+
async (args) => {
|
|
304
|
+
const res = await baseFetch(args);
|
|
305
|
+
applyResult(res);
|
|
306
|
+
onSuccess?.(res);
|
|
307
|
+
onSettled?.(res, null);
|
|
308
|
+
return res;
|
|
309
|
+
},
|
|
310
|
+
[baseFetch, applyResult, onSuccess, onSettled]
|
|
311
|
+
);
|
|
312
|
+
const reset = useCallback2(() => {
|
|
313
|
+
setData(initialData ?? []);
|
|
314
|
+
setPreviousData(void 0);
|
|
315
|
+
setTotalCount(0);
|
|
316
|
+
}, [initialData]);
|
|
317
|
+
return { data, previousData, totalCount, isLoading, isFetching, error, query, refetch, reset };
|
|
318
|
+
}
|
|
319
|
+
function useCreate(options = {}) {
|
|
320
|
+
const {
|
|
321
|
+
advanced,
|
|
322
|
+
select,
|
|
323
|
+
populate,
|
|
324
|
+
tasks,
|
|
325
|
+
basicOptions,
|
|
326
|
+
advancedOptions,
|
|
327
|
+
requestConfig,
|
|
328
|
+
onSuccess,
|
|
329
|
+
onError,
|
|
330
|
+
onSettled
|
|
331
|
+
} = options;
|
|
332
|
+
const [data, setData] = useState(null);
|
|
333
|
+
const mountRef = useMountRef();
|
|
334
|
+
const execute = useCallback2(
|
|
335
|
+
async (createData) => {
|
|
336
|
+
let res;
|
|
337
|
+
if (advanced) {
|
|
338
|
+
res = await modelService.createAdvanced(
|
|
339
|
+
createData,
|
|
340
|
+
{ select, populate, tasks },
|
|
341
|
+
advancedOptions,
|
|
342
|
+
requestConfig
|
|
343
|
+
).exec();
|
|
344
|
+
} else {
|
|
345
|
+
res = await modelService.create(createData, basicOptions, requestConfig).exec();
|
|
346
|
+
}
|
|
347
|
+
if (mountRef.current) setData(res.data);
|
|
348
|
+
return res;
|
|
349
|
+
},
|
|
350
|
+
[modelService, advanced, select, populate, tasks, basicOptions, advancedOptions, requestConfig, mountRef]
|
|
351
|
+
);
|
|
352
|
+
const { isPending, error, executeMutate, reset: resetError } = useMutation(execute, { onSuccess, onSettled });
|
|
353
|
+
const mutate = useCallback2(
|
|
354
|
+
async (createData) => {
|
|
355
|
+
try {
|
|
356
|
+
return await executeMutate(createData);
|
|
357
|
+
} catch (err) {
|
|
358
|
+
onError?.(err);
|
|
359
|
+
throw err;
|
|
360
|
+
}
|
|
361
|
+
},
|
|
362
|
+
[executeMutate, onError]
|
|
363
|
+
);
|
|
364
|
+
const reset = useCallback2(() => {
|
|
365
|
+
setData(null);
|
|
366
|
+
resetError();
|
|
367
|
+
}, [resetError]);
|
|
368
|
+
return { data, isPending, error, mutate, reset };
|
|
369
|
+
}
|
|
370
|
+
function useUpdate(options = {}) {
|
|
371
|
+
const {
|
|
372
|
+
advanced,
|
|
373
|
+
select,
|
|
374
|
+
populate,
|
|
375
|
+
tasks,
|
|
376
|
+
basicOptions,
|
|
377
|
+
advancedOptions,
|
|
378
|
+
requestConfig,
|
|
379
|
+
onSuccess,
|
|
380
|
+
onError,
|
|
381
|
+
onSettled
|
|
382
|
+
} = options;
|
|
383
|
+
const [data, setData] = useState(null);
|
|
384
|
+
const mountRef = useMountRef();
|
|
385
|
+
const execute = useCallback2(
|
|
386
|
+
async (updateId, updateData) => {
|
|
387
|
+
let res;
|
|
388
|
+
if (advanced) {
|
|
389
|
+
res = await modelService.updateAdvanced(
|
|
390
|
+
updateId,
|
|
391
|
+
updateData,
|
|
392
|
+
{ select, populate, tasks },
|
|
393
|
+
advancedOptions,
|
|
394
|
+
requestConfig
|
|
395
|
+
).exec();
|
|
396
|
+
} else {
|
|
397
|
+
res = await modelService.update(updateId, updateData, basicOptions, requestConfig).exec();
|
|
398
|
+
}
|
|
399
|
+
if (mountRef.current) setData(res.data);
|
|
400
|
+
return res;
|
|
401
|
+
},
|
|
402
|
+
[modelService, advanced, select, populate, tasks, basicOptions, advancedOptions, requestConfig, mountRef]
|
|
403
|
+
);
|
|
404
|
+
const { isPending, error, executeMutate, reset: resetError } = useMutation(execute, { onSuccess, onSettled });
|
|
405
|
+
const mutate = useCallback2(
|
|
406
|
+
async (updateId, updateData) => {
|
|
407
|
+
try {
|
|
408
|
+
return await executeMutate(updateId, updateData);
|
|
409
|
+
} catch (err) {
|
|
410
|
+
onError?.(err);
|
|
411
|
+
throw err;
|
|
412
|
+
}
|
|
413
|
+
},
|
|
414
|
+
[executeMutate, onError]
|
|
415
|
+
);
|
|
416
|
+
const reset = useCallback2(() => {
|
|
417
|
+
setData(null);
|
|
418
|
+
resetError();
|
|
419
|
+
}, [resetError]);
|
|
420
|
+
return { data, isPending, error, mutate, reset };
|
|
421
|
+
}
|
|
422
|
+
function useUpsert(options = {}) {
|
|
423
|
+
const {
|
|
424
|
+
advanced,
|
|
425
|
+
select,
|
|
426
|
+
populate,
|
|
427
|
+
tasks,
|
|
428
|
+
basicOptions,
|
|
429
|
+
advancedOptions,
|
|
430
|
+
requestConfig,
|
|
431
|
+
onSuccess,
|
|
432
|
+
onError,
|
|
433
|
+
onSettled
|
|
434
|
+
} = options;
|
|
435
|
+
const [data, setData] = useState(null);
|
|
436
|
+
const mountRef = useMountRef();
|
|
437
|
+
const execute = useCallback2(
|
|
438
|
+
async (upsertData) => {
|
|
439
|
+
let res;
|
|
440
|
+
if (advanced) {
|
|
441
|
+
res = await modelService.upsertAdvanced(
|
|
442
|
+
upsertData,
|
|
443
|
+
{ select, populate, tasks },
|
|
444
|
+
advancedOptions,
|
|
445
|
+
requestConfig
|
|
446
|
+
).exec();
|
|
447
|
+
} else {
|
|
448
|
+
res = await modelService.upsert(upsertData, basicOptions, requestConfig).exec();
|
|
449
|
+
}
|
|
450
|
+
if (mountRef.current) setData(res.data);
|
|
451
|
+
return res;
|
|
452
|
+
},
|
|
453
|
+
[modelService, advanced, select, populate, tasks, basicOptions, advancedOptions, requestConfig, mountRef]
|
|
454
|
+
);
|
|
455
|
+
const { isPending, error, executeMutate, reset: resetError } = useMutation(execute, { onSuccess, onSettled });
|
|
456
|
+
const mutate = useCallback2(
|
|
457
|
+
async (upsertData) => {
|
|
458
|
+
try {
|
|
459
|
+
return await executeMutate(upsertData);
|
|
460
|
+
} catch (err) {
|
|
461
|
+
onError?.(err);
|
|
462
|
+
throw err;
|
|
463
|
+
}
|
|
464
|
+
},
|
|
465
|
+
[executeMutate, onError]
|
|
466
|
+
);
|
|
467
|
+
const reset = useCallback2(() => {
|
|
468
|
+
setData(null);
|
|
469
|
+
resetError();
|
|
470
|
+
}, [resetError]);
|
|
471
|
+
return { data, isPending, error, mutate, reset };
|
|
472
|
+
}
|
|
473
|
+
function useDelete(options = {}) {
|
|
474
|
+
const { requestConfig, onSuccess, onError, onSettled } = options;
|
|
475
|
+
const execute = useCallback2(
|
|
476
|
+
async (deleteId) => {
|
|
477
|
+
const res = await modelService.delete(deleteId, requestConfig).exec();
|
|
478
|
+
return res;
|
|
479
|
+
},
|
|
480
|
+
[modelService, requestConfig]
|
|
481
|
+
);
|
|
482
|
+
const { isPending, error, executeMutate, reset } = useMutation(execute, { onSuccess, onSettled });
|
|
483
|
+
const mutate = useCallback2(
|
|
484
|
+
async (deleteId) => {
|
|
485
|
+
try {
|
|
486
|
+
return await executeMutate(deleteId);
|
|
487
|
+
} catch (err) {
|
|
488
|
+
onError?.(err);
|
|
489
|
+
throw err;
|
|
490
|
+
}
|
|
491
|
+
},
|
|
492
|
+
[executeMutate, onError]
|
|
493
|
+
);
|
|
494
|
+
return { isPending, error, mutate, reset };
|
|
495
|
+
}
|
|
496
|
+
function useCount(options = {}) {
|
|
497
|
+
const { advanced, filter, enabled = true, requestConfig, onSuccess, onError, onSettled } = options;
|
|
498
|
+
const [data, setData] = useState(null);
|
|
499
|
+
const applyResult = useCallback2((res) => {
|
|
500
|
+
setData(res.data);
|
|
501
|
+
}, []);
|
|
502
|
+
const doFetch = useCallback2(
|
|
503
|
+
async (signal) => {
|
|
504
|
+
if (advanced) {
|
|
505
|
+
return await modelService.countAdvanced(filter ?? {}, void 0, { ...requestConfig, signal }).exec();
|
|
506
|
+
}
|
|
507
|
+
return await modelService.count({ ...requestConfig, signal }).exec();
|
|
508
|
+
},
|
|
509
|
+
[modelService, advanced, filter, requestConfig]
|
|
510
|
+
);
|
|
511
|
+
const filterKey = stableStringify(filter);
|
|
512
|
+
const { isLoading, error, refetch } = useAutoQuery({
|
|
513
|
+
doFetch,
|
|
514
|
+
applyResult,
|
|
515
|
+
shouldFetch: enabled,
|
|
516
|
+
deps: [enabled, advanced, filterKey],
|
|
517
|
+
onSuccess,
|
|
518
|
+
onError,
|
|
519
|
+
onSettled
|
|
520
|
+
});
|
|
521
|
+
const query = useCallback2(async () => {
|
|
522
|
+
const res = await doFetch();
|
|
523
|
+
applyResult(res);
|
|
524
|
+
onSuccess?.(res);
|
|
525
|
+
onSettled?.(res, null);
|
|
526
|
+
return res;
|
|
527
|
+
}, [doFetch, applyResult, onSuccess, onSettled]);
|
|
528
|
+
const reset = useCallback2(() => {
|
|
529
|
+
setData(null);
|
|
530
|
+
}, []);
|
|
531
|
+
return { data, isLoading, error, query, refetch, reset };
|
|
532
|
+
}
|
|
533
|
+
function useDistinct(options) {
|
|
534
|
+
const { field, conditions, enabled = true, requestConfig, onSuccess, onError, onSettled } = options;
|
|
535
|
+
const [data, setData] = useState(null);
|
|
536
|
+
const applyResult = useCallback2((res) => {
|
|
537
|
+
setData(res.data);
|
|
538
|
+
}, []);
|
|
539
|
+
const doFetch = useCallback2(
|
|
540
|
+
async (signal) => {
|
|
541
|
+
if (conditions && Object.keys(conditions).length > 0) {
|
|
542
|
+
return await modelService.distinctAdvanced(field, conditions, { ...requestConfig, signal }).exec();
|
|
543
|
+
}
|
|
544
|
+
return await modelService.distinct(field, { ...requestConfig, signal }).exec();
|
|
545
|
+
},
|
|
546
|
+
[modelService, field, conditions, requestConfig]
|
|
547
|
+
);
|
|
548
|
+
const conditionsKey = stableStringify(conditions);
|
|
549
|
+
const { isLoading, error, refetch } = useAutoQuery({
|
|
550
|
+
doFetch,
|
|
551
|
+
applyResult,
|
|
552
|
+
shouldFetch: enabled,
|
|
553
|
+
deps: [enabled, field, conditionsKey],
|
|
554
|
+
onSuccess,
|
|
555
|
+
onError,
|
|
556
|
+
onSettled
|
|
557
|
+
});
|
|
558
|
+
const query = useCallback2(async () => {
|
|
559
|
+
const res = await doFetch();
|
|
560
|
+
applyResult(res);
|
|
561
|
+
onSuccess?.(res);
|
|
562
|
+
onSettled?.(res, null);
|
|
563
|
+
return res;
|
|
564
|
+
}, [doFetch, applyResult, onSuccess, onSettled]);
|
|
565
|
+
const reset = useCallback2(() => {
|
|
566
|
+
setData(null);
|
|
567
|
+
}, []);
|
|
568
|
+
return { data, isLoading, error, query, refetch, reset };
|
|
569
|
+
}
|
|
570
|
+
return {
|
|
571
|
+
useRead,
|
|
572
|
+
useList,
|
|
573
|
+
useCreate,
|
|
574
|
+
useUpdate,
|
|
575
|
+
useUpsert,
|
|
576
|
+
useDelete,
|
|
577
|
+
useCount,
|
|
578
|
+
useDistinct
|
|
579
|
+
};
|
|
580
|
+
}
|
|
581
|
+
export {
|
|
582
|
+
createModelHooks
|
|
583
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@web-ts-toolkit/access-router-react",
|
|
3
|
+
"description": "React hooks for @web-ts-toolkit/access-router-client model services",
|
|
4
|
+
"homepage": "https://web-ts-toolkit.pages.dev/docs/packages/access-router-react",
|
|
5
|
+
"version": "0.5.0",
|
|
6
|
+
"sideEffects": false,
|
|
7
|
+
"keywords": [
|
|
8
|
+
"react",
|
|
9
|
+
"hooks",
|
|
10
|
+
"typescript",
|
|
11
|
+
"crud",
|
|
12
|
+
"access-router",
|
|
13
|
+
"model"
|
|
14
|
+
],
|
|
15
|
+
"main": "./index.js",
|
|
16
|
+
"module": "./index.mjs",
|
|
17
|
+
"types": "./index.d.ts",
|
|
18
|
+
"exports": {
|
|
19
|
+
".": {
|
|
20
|
+
"types": "./index.d.ts",
|
|
21
|
+
"import": "./index.mjs",
|
|
22
|
+
"require": "./index.js",
|
|
23
|
+
"default": "./index.js"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"engines": {
|
|
27
|
+
"node": ">=20"
|
|
28
|
+
},
|
|
29
|
+
"peerDependencies": {
|
|
30
|
+
"react": "^18.0.0 || ^19.0.0",
|
|
31
|
+
"@web-ts-toolkit/access-router-client": "0.5.0"
|
|
32
|
+
},
|
|
33
|
+
"author": "Junmin Ahn",
|
|
34
|
+
"bugs": {
|
|
35
|
+
"url": "https://github.com/egose/web-ts-toolkit/issues"
|
|
36
|
+
},
|
|
37
|
+
"license": "Apache-2.0",
|
|
38
|
+
"repository": {
|
|
39
|
+
"type": "git",
|
|
40
|
+
"url": "git+https://github.com/egose/web-ts-toolkit.git",
|
|
41
|
+
"directory": "packages/access-router-react"
|
|
42
|
+
}
|
|
43
|
+
}
|