@chill-sharp/react-client 1.1.12 → 1.1.15

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/src/hooks.ts CHANGED
@@ -1,515 +1,515 @@
1
- /*
2
- * ChillSharp is a lightweight .NET library that sits on top of Entity Framework Core
3
- * and turns an existing data model into a fully working REST API with almost no setup.
4
- * Copyright (C) 2025 Andrea Piovesan
5
- *
6
- * This program is free software: you can redistribute it and/or modify
7
- * it under the terms of the GNU Affero General Public License as published by
8
- * the Free Software Foundation, either version 3 of the License, or
9
- * (at your option) any later version.
10
- *
11
- * This program is distributed in the hope that it will be useful,
12
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
- * GNU Affero General Public License for more details.
15
- *
16
- * You should have received a copy of the GNU Affero General Public License
17
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
18
- */
19
-
20
- import { useEffect, useRef, useState } from "react";
21
- import { CHILL_SHARP_REACT_CLIENT_VERSION } from "./version.js";
22
- import { useChillSharpClient } from "./context.js";
23
- import type {
24
- ChillDtoSchema,
25
- ChillDtoSchemaListItem,
26
- ChillUserPreferences,
27
- ChillEntityChangeCallback,
28
- ChillEntityChangeSubscription,
29
- ChillValidationError,
30
- GetTextRequest,
31
- GetTextResponse,
32
- JsonObject
33
- } from "@chill-sharp/ts-client";
34
-
35
- export interface UseChillAsyncState<TData> {
36
- data: TData | null;
37
- error: unknown;
38
- isLoading: boolean;
39
- reload: () => Promise<TData | null>;
40
- }
41
-
42
- export interface UseChillMutationState<TData> {
43
- data: TData | null;
44
- error: unknown;
45
- isLoading: boolean;
46
- execute: (...args: unknown[]) => Promise<TData>;
47
- reset: () => void;
48
- }
49
-
50
- export interface UseChillSubscriptionState {
51
- error: unknown;
52
- isSubscribed: boolean;
53
- }
54
-
55
- export function useSchema(
56
- chillType: string,
57
- chillViewCode = "default",
58
- cultureName?: string,
59
- update = false
60
- ): UseChillAsyncState<ChillDtoSchema> {
61
- const client = useChillSharpClient();
62
- const [data, setData] = useState<ChillDtoSchema | null>(null);
63
- const [error, setError] = useState<unknown>(null);
64
- const [isLoading, setIsLoading] = useState<boolean>(true);
65
-
66
- const load = async () => {
67
- setIsLoading(true);
68
- setError(null);
69
-
70
- try {
71
- const response = await client.getSchema(chillType, chillViewCode, cultureName, update);
72
- setData(response);
73
- return response;
74
- } catch (err) {
75
- setError(err);
76
- throw err;
77
- } finally {
78
- setIsLoading(false);
79
- }
80
- };
81
-
82
- useEffect(() => {
83
- void load();
84
- }, [client, chillType, chillViewCode, cultureName, update]);
85
-
86
- return {
87
- data,
88
- error,
89
- isLoading,
90
- reload: load
91
- };
92
- }
93
-
94
- export function useSchemaList(cultureName?: string): UseChillAsyncState<ChillDtoSchemaListItem[]> {
95
- const client = useChillSharpClient();
96
- const [data, setData] = useState<ChillDtoSchemaListItem[] | null>(null);
97
- const [error, setError] = useState<unknown>(null);
98
- const [isLoading, setIsLoading] = useState<boolean>(true);
99
-
100
- const load = async () => {
101
- setIsLoading(true);
102
- setError(null);
103
-
104
- try {
105
- const response = await client.getSchemaList(cultureName);
106
- setData(response);
107
- return response;
108
- } catch (err) {
109
- setError(err);
110
- throw err;
111
- } finally {
112
- setIsLoading(false);
113
- }
114
- };
115
-
116
- useEffect(() => {
117
- void load();
118
- }, [client, cultureName]);
119
-
120
- return {
121
- data,
122
- error,
123
- isLoading,
124
- reload: load
125
- };
126
- }
127
-
128
- export function useText(request: GetTextRequest): UseChillAsyncState<GetTextResponse> {
129
- const client = useChillSharpClient();
130
- const [data, setData] = useState<GetTextResponse | null>(null);
131
- const [error, setError] = useState<unknown>(null);
132
- const [isLoading, setIsLoading] = useState<boolean>(true);
133
-
134
- const load = async () => {
135
- setIsLoading(true);
136
- setError(null);
137
-
138
- try {
139
- const response = await client.getText(request);
140
- setData(response);
141
- return response;
142
- } catch (err) {
143
- setError(err);
144
- throw err;
145
- } finally {
146
- setIsLoading(false);
147
- }
148
- };
149
-
150
- useEffect(() => {
151
- void load();
152
- }, [client, request]);
153
-
154
- return {
155
- data,
156
- error,
157
- isLoading,
158
- reload: load
159
- };
160
- }
161
-
162
- export function useTexts(requests: GetTextRequest[]): UseChillAsyncState<Array<GetTextResponse | null>> {
163
- const client = useChillSharpClient();
164
- const [data, setData] = useState<Array<GetTextResponse | null> | null>(null);
165
- const [error, setError] = useState<unknown>(null);
166
- const [isLoading, setIsLoading] = useState<boolean>(true);
167
-
168
- const load = async () => {
169
- setIsLoading(true);
170
- setError(null);
171
-
172
- try {
173
- const response = await client.getTexts(requests);
174
- setData(response);
175
- return response;
176
- } catch (err) {
177
- setError(err);
178
- throw err;
179
- } finally {
180
- setIsLoading(false);
181
- }
182
- };
183
-
184
- useEffect(() => {
185
- void load();
186
- }, [client, requests]);
187
-
188
- return {
189
- data,
190
- error,
191
- isLoading,
192
- reload: load
193
- };
194
- }
195
-
196
- export function useVersion(): string {
197
- return CHILL_SHARP_REACT_CLIENT_VERSION;
198
- }
199
-
200
- export function useTest(): UseChillAsyncState<string> {
201
- const client = useChillSharpClient();
202
- const [data, setData] = useState<string | null>(null);
203
- const [error, setError] = useState<unknown>(null);
204
- const [isLoading, setIsLoading] = useState<boolean>(true);
205
-
206
- const load = async () => {
207
- setIsLoading(true);
208
- setError(null);
209
-
210
- try {
211
- const response = await client.test();
212
- setData(response);
213
- return response;
214
- } catch (err) {
215
- setError(err);
216
- throw err;
217
- } finally {
218
- setIsLoading(false);
219
- }
220
- };
221
-
222
- useEffect(() => {
223
- void load();
224
- }, [client]);
225
-
226
- return {
227
- data,
228
- error,
229
- isLoading,
230
- reload: load
231
- };
232
- }
233
-
234
- export function useCurrentUserPreferences(): UseChillAsyncState<ChillUserPreferences> {
235
- const client = useChillSharpClient();
236
- const [data, setData] = useState<ChillUserPreferences | null>(null);
237
- const [error, setError] = useState<unknown>(null);
238
- const [isLoading, setIsLoading] = useState<boolean>(true);
239
-
240
- const load = async () => {
241
- setIsLoading(true);
242
- setError(null);
243
- try {
244
- const response = await client.getCurrentUserPreferences();
245
- setData(response);
246
- return response;
247
- } catch (err) {
248
- setError(err);
249
- throw err;
250
- } finally {
251
- setIsLoading(false);
252
- }
253
- };
254
-
255
- useEffect(() => { void load(); }, [client]);
256
- return { data, error, isLoading, reload: load };
257
- }
258
-
259
- export function useQueryMutation(): UseChillMutationState<JsonObject> {
260
- const client = useChillSharpClient();
261
- const [data, setData] = useState<JsonObject | null>(null);
262
- const [error, setError] = useState<unknown>(null);
263
- const [isLoading, setIsLoading] = useState<boolean>(false);
264
-
265
- const execute = async (...args: unknown[]) => {
266
- const payload = args[0] as JsonObject;
267
- setIsLoading(true);
268
- setError(null);
269
-
270
- try {
271
- const response = await client.query(payload);
272
- setData(response);
273
- return response;
274
- } catch (err) {
275
- setError(err);
276
- throw err;
277
- } finally {
278
- setIsLoading(false);
279
- }
280
- };
281
-
282
- return {
283
- data,
284
- error,
285
- isLoading,
286
- execute,
287
- reset: () => {
288
- setData(null);
289
- setError(null);
290
- setIsLoading(false);
291
- }
292
- };
293
- }
294
-
295
- export function useLookupMutation(): UseChillMutationState<JsonObject> {
296
- const client = useChillSharpClient();
297
- const [data, setData] = useState<JsonObject | null>(null);
298
- const [error, setError] = useState<unknown>(null);
299
- const [isLoading, setIsLoading] = useState<boolean>(false);
300
-
301
- const execute = async (...args: unknown[]) => {
302
- const payload = args[0] as JsonObject;
303
- setIsLoading(true);
304
- setError(null);
305
-
306
- try {
307
- const response = await client.lookup(payload);
308
- setData(response);
309
- return response;
310
- } catch (err) {
311
- setError(err);
312
- throw err;
313
- } finally {
314
- setIsLoading(false);
315
- }
316
- };
317
-
318
- return {
319
- data,
320
- error,
321
- isLoading,
322
- execute,
323
- reset: () => {
324
- setData(null);
325
- setError(null);
326
- setIsLoading(false);
327
- }
328
- };
329
- }
330
-
331
- export function useAutocompleteMutation(): UseChillMutationState<JsonObject> {
332
- const client = useChillSharpClient();
333
- const [data, setData] = useState<JsonObject | null>(null);
334
- const [error, setError] = useState<unknown>(null);
335
- const [isLoading, setIsLoading] = useState<boolean>(false);
336
-
337
- const execute = async (...args: unknown[]) => {
338
- const payload = args[0] as JsonObject;
339
- setIsLoading(true);
340
- setError(null);
341
-
342
- try {
343
- const response = await client.autocomplete(payload);
344
- setData(response);
345
- return response;
346
- } catch (err) {
347
- setError(err);
348
- throw err;
349
- } finally {
350
- setIsLoading(false);
351
- }
352
- };
353
-
354
- return {
355
- data,
356
- error,
357
- isLoading,
358
- execute,
359
- reset: () => {
360
- setData(null);
361
- setError(null);
362
- setIsLoading(false);
363
- }
364
- };
365
- }
366
-
367
- export function useValidateMutation(): UseChillMutationState<ChillValidationError[]> {
368
- const client = useChillSharpClient();
369
- const [data, setData] = useState<ChillValidationError[] | null>(null);
370
- const [error, setError] = useState<unknown>(null);
371
- const [isLoading, setIsLoading] = useState<boolean>(false);
372
-
373
- const execute = async (...args: unknown[]) => {
374
- const payload = args[0] as JsonObject;
375
- setIsLoading(true);
376
- setError(null);
377
-
378
- try {
379
- const response = await client.validate(payload);
380
- setData(response);
381
- return response;
382
- } catch (err) {
383
- setError(err);
384
- throw err;
385
- } finally {
386
- setIsLoading(false);
387
- }
388
- };
389
-
390
- return {
391
- data,
392
- error,
393
- isLoading,
394
- execute,
395
- reset: () => {
396
- setData(null);
397
- setError(null);
398
- setIsLoading(false);
399
- }
400
- };
401
- }
402
-
403
- export function useEntityMutation(action: "find" | "create" | "update" | "delete"): UseChillMutationState<JsonObject | null> {
404
- const client = useChillSharpClient();
405
- const [data, setData] = useState<JsonObject | null>(null);
406
- const [error, setError] = useState<unknown>(null);
407
- const [isLoading, setIsLoading] = useState<boolean>(false);
408
-
409
- const execute = async (...args: unknown[]) => {
410
- const payload = args[0] as JsonObject;
411
- setIsLoading(true);
412
- setError(null);
413
-
414
- try {
415
- let response: JsonObject | null;
416
- switch (action) {
417
- case "find":
418
- response = await client.find(payload);
419
- break;
420
- case "create":
421
- response = await client.create(payload);
422
- break;
423
- case "update":
424
- response = await client.update(payload);
425
- break;
426
- default:
427
- await client.delete(payload);
428
- response = null;
429
- break;
430
- }
431
-
432
- setData(response);
433
- return response;
434
- } catch (err) {
435
- setError(err);
436
- throw err;
437
- } finally {
438
- setIsLoading(false);
439
- }
440
- };
441
-
442
- return {
443
- data,
444
- error,
445
- isLoading,
446
- execute,
447
- reset: () => {
448
- setData(null);
449
- setError(null);
450
- setIsLoading(false);
451
- }
452
- };
453
- }
454
-
455
- export function useEntityChanges(
456
- chillType: string,
457
- onChanges: ChillEntityChangeCallback,
458
- guid?: string | null
459
- ): UseChillSubscriptionState {
460
- const client = useChillSharpClient();
461
- const onChangesRef = useRef<ChillEntityChangeCallback>(onChanges);
462
- const unsubscribeRef = useRef<null | (() => Promise<void>)>(null);
463
- const [error, setError] = useState<unknown>(null);
464
- const [isSubscribed, setIsSubscribed] = useState<boolean>(false);
465
-
466
- useEffect(() => {
467
- onChangesRef.current = onChanges;
468
- }, [onChanges]);
469
-
470
- useEffect(() => {
471
- let isDisposed = false;
472
-
473
- setError(null);
474
- setIsSubscribed(false);
475
- unsubscribeRef.current = null;
476
-
477
- void client
478
- .subscribeToEntityChanges(
479
- chillType,
480
- async (changes) => {
481
- await onChangesRef.current(changes);
482
- },
483
- guid
484
- )
485
- .then((subscription: ChillEntityChangeSubscription) => {
486
- if (isDisposed) {
487
- void subscription.unsubscribe();
488
- return;
489
- }
490
-
491
- unsubscribeRef.current = () => subscription.unsubscribe();
492
- setIsSubscribed(true);
493
- })
494
- .catch((err) => {
495
- if (!isDisposed) {
496
- setError(err);
497
- setIsSubscribed(false);
498
- }
499
- });
500
-
501
- return () => {
502
- isDisposed = true;
503
- setIsSubscribed(false);
504
- if (unsubscribeRef.current) {
505
- void unsubscribeRef.current();
506
- unsubscribeRef.current = null;
507
- }
508
- };
509
- }, [client, chillType, guid]);
510
-
511
- return {
512
- error,
513
- isSubscribed
514
- };
515
- }
1
+ /*
2
+ * ChillSharp is a lightweight .NET library that sits on top of Entity Framework Core
3
+ * and turns an existing data model into a fully working REST API with almost no setup.
4
+ * Copyright (C) 2025 Andrea Piovesan
5
+ *
6
+ * This program is free software: you can redistribute it and/or modify
7
+ * it under the terms of the GNU Affero General Public License as published by
8
+ * the Free Software Foundation, either version 3 of the License, or
9
+ * (at your option) any later version.
10
+ *
11
+ * This program is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ * GNU Affero General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU Affero General Public License
17
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
18
+ */
19
+
20
+ import { useEffect, useRef, useState } from "react";
21
+ import { CHILL_SHARP_REACT_CLIENT_VERSION } from "./version.js";
22
+ import { useChillSharpClient } from "./context.js";
23
+ import type {
24
+ ChillDtoSchema,
25
+ ChillDtoSchemaListItem,
26
+ ChillUserPreferences,
27
+ ChillEntityChangeCallback,
28
+ ChillEntityChangeSubscription,
29
+ ChillValidationError,
30
+ GetTextRequest,
31
+ GetTextResponse,
32
+ JsonObject
33
+ } from "@chill-sharp/ts-client";
34
+
35
+ export interface UseChillAsyncState<TData> {
36
+ data: TData | null;
37
+ error: unknown;
38
+ isLoading: boolean;
39
+ reload: () => Promise<TData | null>;
40
+ }
41
+
42
+ export interface UseChillMutationState<TData> {
43
+ data: TData | null;
44
+ error: unknown;
45
+ isLoading: boolean;
46
+ execute: (...args: unknown[]) => Promise<TData>;
47
+ reset: () => void;
48
+ }
49
+
50
+ export interface UseChillSubscriptionState {
51
+ error: unknown;
52
+ isSubscribed: boolean;
53
+ }
54
+
55
+ export function useSchema(
56
+ chillType: string,
57
+ chillViewCode = "default",
58
+ cultureName?: string,
59
+ update = false
60
+ ): UseChillAsyncState<ChillDtoSchema> {
61
+ const client = useChillSharpClient();
62
+ const [data, setData] = useState<ChillDtoSchema | null>(null);
63
+ const [error, setError] = useState<unknown>(null);
64
+ const [isLoading, setIsLoading] = useState<boolean>(true);
65
+
66
+ const load = async () => {
67
+ setIsLoading(true);
68
+ setError(null);
69
+
70
+ try {
71
+ const response = await client.getSchema(chillType, chillViewCode, cultureName, update);
72
+ setData(response);
73
+ return response;
74
+ } catch (err) {
75
+ setError(err);
76
+ throw err;
77
+ } finally {
78
+ setIsLoading(false);
79
+ }
80
+ };
81
+
82
+ useEffect(() => {
83
+ void load();
84
+ }, [client, chillType, chillViewCode, cultureName, update]);
85
+
86
+ return {
87
+ data,
88
+ error,
89
+ isLoading,
90
+ reload: load
91
+ };
92
+ }
93
+
94
+ export function useSchemaList(cultureName?: string): UseChillAsyncState<ChillDtoSchemaListItem[]> {
95
+ const client = useChillSharpClient();
96
+ const [data, setData] = useState<ChillDtoSchemaListItem[] | null>(null);
97
+ const [error, setError] = useState<unknown>(null);
98
+ const [isLoading, setIsLoading] = useState<boolean>(true);
99
+
100
+ const load = async () => {
101
+ setIsLoading(true);
102
+ setError(null);
103
+
104
+ try {
105
+ const response = await client.getSchemaList(cultureName);
106
+ setData(response);
107
+ return response;
108
+ } catch (err) {
109
+ setError(err);
110
+ throw err;
111
+ } finally {
112
+ setIsLoading(false);
113
+ }
114
+ };
115
+
116
+ useEffect(() => {
117
+ void load();
118
+ }, [client, cultureName]);
119
+
120
+ return {
121
+ data,
122
+ error,
123
+ isLoading,
124
+ reload: load
125
+ };
126
+ }
127
+
128
+ export function useText(request: GetTextRequest): UseChillAsyncState<GetTextResponse> {
129
+ const client = useChillSharpClient();
130
+ const [data, setData] = useState<GetTextResponse | null>(null);
131
+ const [error, setError] = useState<unknown>(null);
132
+ const [isLoading, setIsLoading] = useState<boolean>(true);
133
+
134
+ const load = async () => {
135
+ setIsLoading(true);
136
+ setError(null);
137
+
138
+ try {
139
+ const response = await client.getText(request);
140
+ setData(response);
141
+ return response;
142
+ } catch (err) {
143
+ setError(err);
144
+ throw err;
145
+ } finally {
146
+ setIsLoading(false);
147
+ }
148
+ };
149
+
150
+ useEffect(() => {
151
+ void load();
152
+ }, [client, request]);
153
+
154
+ return {
155
+ data,
156
+ error,
157
+ isLoading,
158
+ reload: load
159
+ };
160
+ }
161
+
162
+ export function useTexts(requests: GetTextRequest[]): UseChillAsyncState<Array<GetTextResponse | null>> {
163
+ const client = useChillSharpClient();
164
+ const [data, setData] = useState<Array<GetTextResponse | null> | null>(null);
165
+ const [error, setError] = useState<unknown>(null);
166
+ const [isLoading, setIsLoading] = useState<boolean>(true);
167
+
168
+ const load = async () => {
169
+ setIsLoading(true);
170
+ setError(null);
171
+
172
+ try {
173
+ const response = await client.getTexts(requests);
174
+ setData(response);
175
+ return response;
176
+ } catch (err) {
177
+ setError(err);
178
+ throw err;
179
+ } finally {
180
+ setIsLoading(false);
181
+ }
182
+ };
183
+
184
+ useEffect(() => {
185
+ void load();
186
+ }, [client, requests]);
187
+
188
+ return {
189
+ data,
190
+ error,
191
+ isLoading,
192
+ reload: load
193
+ };
194
+ }
195
+
196
+ export function useVersion(): string {
197
+ return CHILL_SHARP_REACT_CLIENT_VERSION;
198
+ }
199
+
200
+ export function useTest(): UseChillAsyncState<string> {
201
+ const client = useChillSharpClient();
202
+ const [data, setData] = useState<string | null>(null);
203
+ const [error, setError] = useState<unknown>(null);
204
+ const [isLoading, setIsLoading] = useState<boolean>(true);
205
+
206
+ const load = async () => {
207
+ setIsLoading(true);
208
+ setError(null);
209
+
210
+ try {
211
+ const response = await client.test();
212
+ setData(response);
213
+ return response;
214
+ } catch (err) {
215
+ setError(err);
216
+ throw err;
217
+ } finally {
218
+ setIsLoading(false);
219
+ }
220
+ };
221
+
222
+ useEffect(() => {
223
+ void load();
224
+ }, [client]);
225
+
226
+ return {
227
+ data,
228
+ error,
229
+ isLoading,
230
+ reload: load
231
+ };
232
+ }
233
+
234
+ export function useCurrentUserPreferences(): UseChillAsyncState<ChillUserPreferences> {
235
+ const client = useChillSharpClient();
236
+ const [data, setData] = useState<ChillUserPreferences | null>(null);
237
+ const [error, setError] = useState<unknown>(null);
238
+ const [isLoading, setIsLoading] = useState<boolean>(true);
239
+
240
+ const load = async () => {
241
+ setIsLoading(true);
242
+ setError(null);
243
+ try {
244
+ const response = await client.getCurrentUserPreferences();
245
+ setData(response);
246
+ return response;
247
+ } catch (err) {
248
+ setError(err);
249
+ throw err;
250
+ } finally {
251
+ setIsLoading(false);
252
+ }
253
+ };
254
+
255
+ useEffect(() => { void load(); }, [client]);
256
+ return { data, error, isLoading, reload: load };
257
+ }
258
+
259
+ export function useQueryMutation(): UseChillMutationState<JsonObject> {
260
+ const client = useChillSharpClient();
261
+ const [data, setData] = useState<JsonObject | null>(null);
262
+ const [error, setError] = useState<unknown>(null);
263
+ const [isLoading, setIsLoading] = useState<boolean>(false);
264
+
265
+ const execute = async (...args: unknown[]) => {
266
+ const payload = args[0] as JsonObject;
267
+ setIsLoading(true);
268
+ setError(null);
269
+
270
+ try {
271
+ const response = await client.query(payload);
272
+ setData(response);
273
+ return response;
274
+ } catch (err) {
275
+ setError(err);
276
+ throw err;
277
+ } finally {
278
+ setIsLoading(false);
279
+ }
280
+ };
281
+
282
+ return {
283
+ data,
284
+ error,
285
+ isLoading,
286
+ execute,
287
+ reset: () => {
288
+ setData(null);
289
+ setError(null);
290
+ setIsLoading(false);
291
+ }
292
+ };
293
+ }
294
+
295
+ export function useLookupMutation(): UseChillMutationState<JsonObject> {
296
+ const client = useChillSharpClient();
297
+ const [data, setData] = useState<JsonObject | null>(null);
298
+ const [error, setError] = useState<unknown>(null);
299
+ const [isLoading, setIsLoading] = useState<boolean>(false);
300
+
301
+ const execute = async (...args: unknown[]) => {
302
+ const payload = args[0] as JsonObject;
303
+ setIsLoading(true);
304
+ setError(null);
305
+
306
+ try {
307
+ const response = await client.lookup(payload);
308
+ setData(response);
309
+ return response;
310
+ } catch (err) {
311
+ setError(err);
312
+ throw err;
313
+ } finally {
314
+ setIsLoading(false);
315
+ }
316
+ };
317
+
318
+ return {
319
+ data,
320
+ error,
321
+ isLoading,
322
+ execute,
323
+ reset: () => {
324
+ setData(null);
325
+ setError(null);
326
+ setIsLoading(false);
327
+ }
328
+ };
329
+ }
330
+
331
+ export function useAutocompleteMutation(): UseChillMutationState<JsonObject> {
332
+ const client = useChillSharpClient();
333
+ const [data, setData] = useState<JsonObject | null>(null);
334
+ const [error, setError] = useState<unknown>(null);
335
+ const [isLoading, setIsLoading] = useState<boolean>(false);
336
+
337
+ const execute = async (...args: unknown[]) => {
338
+ const payload = args[0] as JsonObject;
339
+ setIsLoading(true);
340
+ setError(null);
341
+
342
+ try {
343
+ const response = await client.autocomplete(payload);
344
+ setData(response);
345
+ return response;
346
+ } catch (err) {
347
+ setError(err);
348
+ throw err;
349
+ } finally {
350
+ setIsLoading(false);
351
+ }
352
+ };
353
+
354
+ return {
355
+ data,
356
+ error,
357
+ isLoading,
358
+ execute,
359
+ reset: () => {
360
+ setData(null);
361
+ setError(null);
362
+ setIsLoading(false);
363
+ }
364
+ };
365
+ }
366
+
367
+ export function useValidateMutation(): UseChillMutationState<ChillValidationError[]> {
368
+ const client = useChillSharpClient();
369
+ const [data, setData] = useState<ChillValidationError[] | null>(null);
370
+ const [error, setError] = useState<unknown>(null);
371
+ const [isLoading, setIsLoading] = useState<boolean>(false);
372
+
373
+ const execute = async (...args: unknown[]) => {
374
+ const payload = args[0] as JsonObject;
375
+ setIsLoading(true);
376
+ setError(null);
377
+
378
+ try {
379
+ const response = await client.validate(payload);
380
+ setData(response);
381
+ return response;
382
+ } catch (err) {
383
+ setError(err);
384
+ throw err;
385
+ } finally {
386
+ setIsLoading(false);
387
+ }
388
+ };
389
+
390
+ return {
391
+ data,
392
+ error,
393
+ isLoading,
394
+ execute,
395
+ reset: () => {
396
+ setData(null);
397
+ setError(null);
398
+ setIsLoading(false);
399
+ }
400
+ };
401
+ }
402
+
403
+ export function useEntityMutation(action: "find" | "create" | "update" | "delete"): UseChillMutationState<JsonObject | null> {
404
+ const client = useChillSharpClient();
405
+ const [data, setData] = useState<JsonObject | null>(null);
406
+ const [error, setError] = useState<unknown>(null);
407
+ const [isLoading, setIsLoading] = useState<boolean>(false);
408
+
409
+ const execute = async (...args: unknown[]) => {
410
+ const payload = args[0] as JsonObject;
411
+ setIsLoading(true);
412
+ setError(null);
413
+
414
+ try {
415
+ let response: JsonObject | null;
416
+ switch (action) {
417
+ case "find":
418
+ response = await client.find(payload);
419
+ break;
420
+ case "create":
421
+ response = await client.create(payload);
422
+ break;
423
+ case "update":
424
+ response = await client.update(payload);
425
+ break;
426
+ default:
427
+ await client.delete(payload);
428
+ response = null;
429
+ break;
430
+ }
431
+
432
+ setData(response);
433
+ return response;
434
+ } catch (err) {
435
+ setError(err);
436
+ throw err;
437
+ } finally {
438
+ setIsLoading(false);
439
+ }
440
+ };
441
+
442
+ return {
443
+ data,
444
+ error,
445
+ isLoading,
446
+ execute,
447
+ reset: () => {
448
+ setData(null);
449
+ setError(null);
450
+ setIsLoading(false);
451
+ }
452
+ };
453
+ }
454
+
455
+ export function useEntityChanges(
456
+ chillType: string,
457
+ onChanges: ChillEntityChangeCallback,
458
+ guid?: string | null
459
+ ): UseChillSubscriptionState {
460
+ const client = useChillSharpClient();
461
+ const onChangesRef = useRef<ChillEntityChangeCallback>(onChanges);
462
+ const unsubscribeRef = useRef<null | (() => Promise<void>)>(null);
463
+ const [error, setError] = useState<unknown>(null);
464
+ const [isSubscribed, setIsSubscribed] = useState<boolean>(false);
465
+
466
+ useEffect(() => {
467
+ onChangesRef.current = onChanges;
468
+ }, [onChanges]);
469
+
470
+ useEffect(() => {
471
+ let isDisposed = false;
472
+
473
+ setError(null);
474
+ setIsSubscribed(false);
475
+ unsubscribeRef.current = null;
476
+
477
+ void client
478
+ .subscribeToEntityChanges(
479
+ chillType,
480
+ async (changes) => {
481
+ await onChangesRef.current(changes);
482
+ },
483
+ guid
484
+ )
485
+ .then((subscription: ChillEntityChangeSubscription) => {
486
+ if (isDisposed) {
487
+ void subscription.unsubscribe();
488
+ return;
489
+ }
490
+
491
+ unsubscribeRef.current = () => subscription.unsubscribe();
492
+ setIsSubscribed(true);
493
+ })
494
+ .catch((err) => {
495
+ if (!isDisposed) {
496
+ setError(err);
497
+ setIsSubscribed(false);
498
+ }
499
+ });
500
+
501
+ return () => {
502
+ isDisposed = true;
503
+ setIsSubscribed(false);
504
+ if (unsubscribeRef.current) {
505
+ void unsubscribeRef.current();
506
+ unsubscribeRef.current = null;
507
+ }
508
+ };
509
+ }, [client, chillType, guid]);
510
+
511
+ return {
512
+ error,
513
+ isSubscribed
514
+ };
515
+ }