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