@azure-net/kit 2.2.2 → 2.2.6
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/dist/core/delivery/schema/rules/Rules.d.ts +6 -0
- package/dist/core/delivery/schema/rules/Rules.js +87 -4
- package/dist/core/svelte/ActiveForm/ActiveForm.svelte.d.ts +10 -1
- package/dist/core/svelte/ActiveForm/ActiveForm.svelte.js +48 -2
- package/dist/core/svelte/AsyncSignal/AsyncSignal.svelte.d.ts +1 -0
- package/dist/core/svelte/AsyncSignal/AsyncSignal.svelte.js +24 -4
- package/dist/core/svelte/Query/Query.svelte.d.ts +20 -0
- package/dist/core/svelte/Query/Query.svelte.js +71 -0
- package/dist/core/svelte/Query/index.d.ts +1 -0
- package/dist/core/svelte/Query/index.js +1 -0
- package/dist/core/svelte/index.d.ts +1 -0
- package/dist/core/svelte/index.js +1 -0
- package/package.json +1 -1
|
@@ -19,6 +19,12 @@ type ArrayItemRules<Context> = ValidationRuleResult<Context>[] | Record<string,
|
|
|
19
19
|
type ArrayParams<Context> = LengthParams & {
|
|
20
20
|
schema?: ArrayItemRules<Context>;
|
|
21
21
|
};
|
|
22
|
+
/**
|
|
23
|
+
*
|
|
24
|
+
* @param validationMessages - BaseValidationMessages
|
|
25
|
+
* @returns ValidationRuleResult<T, D>
|
|
26
|
+
* @description Creates the rules for the schema.
|
|
27
|
+
*/
|
|
22
28
|
export declare const createRules: <M extends BaseValidationMessages>(validationMessages: M) => {
|
|
23
29
|
string: <T = unknown, D = unknown>(params?: ValidationRuleParams<"string", LengthParams>) => ValidationRuleResult<T, D>;
|
|
24
30
|
number: <T = unknown, D_1 = unknown>(params?: ValidationRuleParams<"number", RangeParams>) => ValidationRuleResult<T, D_1>;
|
|
@@ -1,8 +1,20 @@
|
|
|
1
1
|
import { masks } from '../../../constants/masks.js';
|
|
2
|
+
/**
|
|
3
|
+
*
|
|
4
|
+
* @param validationMessages - BaseValidationMessages
|
|
5
|
+
* @returns ValidationRuleResult<T, D>
|
|
6
|
+
* @description Creates the rules for the schema.
|
|
7
|
+
*/
|
|
2
8
|
export const createRules = (validationMessages) => {
|
|
3
9
|
const checkVal = (val) => {
|
|
4
10
|
return val !== undefined && val !== null;
|
|
5
11
|
};
|
|
12
|
+
/**
|
|
13
|
+
*
|
|
14
|
+
* @param params - ValidationRuleParams<'string', LengthParams>
|
|
15
|
+
* @returns ValidationRuleResult<T, D>
|
|
16
|
+
* @description Checks if the value is a string and if it is within the length specified in the params.
|
|
17
|
+
*/
|
|
6
18
|
const string = (params) => {
|
|
7
19
|
const { message, length } = { ...params, message: { ...validationMessages.string, ...params?.message } };
|
|
8
20
|
return ({ val }) => {
|
|
@@ -22,6 +34,12 @@ export const createRules = (validationMessages) => {
|
|
|
22
34
|
return undefined;
|
|
23
35
|
};
|
|
24
36
|
};
|
|
37
|
+
/**
|
|
38
|
+
*
|
|
39
|
+
* @param params - ValidationRuleParams<'number', RangeParams>
|
|
40
|
+
* @returns ValidationRuleResult<T, D>
|
|
41
|
+
* @description Checks if the value is a whole number (integer) and if it is within the range specified in the params.
|
|
42
|
+
*/
|
|
25
43
|
const number = (params) => {
|
|
26
44
|
const { message, range } = { ...params, message: { ...validationMessages.number, ...params?.message } };
|
|
27
45
|
return ({ val }) => {
|
|
@@ -42,6 +60,12 @@ export const createRules = (validationMessages) => {
|
|
|
42
60
|
return undefined;
|
|
43
61
|
};
|
|
44
62
|
};
|
|
63
|
+
/**
|
|
64
|
+
*
|
|
65
|
+
* @param params - ValidationRuleParams<'finite', RangeParams & { maxDigitsAfterDot?: number }>
|
|
66
|
+
* @returns ValidationRuleResult<T, D>
|
|
67
|
+
* @description Checks if the value is a finite number and if it is within the range specified in the params.
|
|
68
|
+
*/
|
|
45
69
|
const finite = (params) => {
|
|
46
70
|
const { message, maxDigitsAfterDot, range } = { ...params, message: { ...validationMessages.finite, ...params?.message } };
|
|
47
71
|
return ({ val }) => {
|
|
@@ -65,6 +89,12 @@ export const createRules = (validationMessages) => {
|
|
|
65
89
|
return undefined;
|
|
66
90
|
};
|
|
67
91
|
};
|
|
92
|
+
/**
|
|
93
|
+
*
|
|
94
|
+
* @param params - ValidationRuleParams<'boolean', { expected?: boolean }>
|
|
95
|
+
* @returns ValidationRuleResult<T, D>
|
|
96
|
+
* @description Checks if the value is a boolean and if it is the expected value specified in the params.
|
|
97
|
+
*/
|
|
68
98
|
const boolean = (params) => {
|
|
69
99
|
const { message, expected } = { ...params, message: { ...validationMessages.boolean, ...params?.message } };
|
|
70
100
|
return ({ val }) => {
|
|
@@ -78,6 +108,12 @@ export const createRules = (validationMessages) => {
|
|
|
78
108
|
return undefined;
|
|
79
109
|
};
|
|
80
110
|
};
|
|
111
|
+
/**
|
|
112
|
+
*
|
|
113
|
+
* @param params - ValidationRuleParams<'array', ArrayParams<T>>
|
|
114
|
+
* @returns ValidationRuleResult<T>
|
|
115
|
+
* @description Checks if the value is an array and if it is within the length specified in the params. Can check every array item with the rules specified in the schema.
|
|
116
|
+
*/
|
|
81
117
|
const array = (params) => {
|
|
82
118
|
const { message, length = {}, schema } = { ...params, message: { ...validationMessages.array, ...params?.message } };
|
|
83
119
|
return ({ val, listValues, key }) => {
|
|
@@ -138,10 +174,15 @@ export const createRules = (validationMessages) => {
|
|
|
138
174
|
return undefined;
|
|
139
175
|
};
|
|
140
176
|
};
|
|
177
|
+
/**
|
|
178
|
+
*
|
|
179
|
+
* @param params - ValidationRuleParams<'phone'>
|
|
180
|
+
* @returns ValidationRuleResult<T, D>
|
|
181
|
+
* @description Checks if the value is a phone number and if it is valid.
|
|
182
|
+
*/
|
|
183
|
+
const countryCodes = new Set(Object.values(masks).map((country) => country.cc)).add('8');
|
|
141
184
|
const phone = (params) => {
|
|
142
185
|
const { message } = { ...params, message: params?.message ?? validationMessages.phone };
|
|
143
|
-
const countryCodes = new Set(Object.values(masks).map((country) => country.cc));
|
|
144
|
-
countryCodes.add('8');
|
|
145
186
|
return ({ val }) => {
|
|
146
187
|
if (checkVal(val)) {
|
|
147
188
|
// eslint-disable-next-line
|
|
@@ -198,6 +239,12 @@ export const createRules = (validationMessages) => {
|
|
|
198
239
|
return undefined;
|
|
199
240
|
};
|
|
200
241
|
};
|
|
242
|
+
/**
|
|
243
|
+
*
|
|
244
|
+
* @param params - ValidationRuleParams<'email'>
|
|
245
|
+
* @returns ValidationRuleResult<T, D>
|
|
246
|
+
* @description Checks if the value is a valid email address.
|
|
247
|
+
*/
|
|
201
248
|
const email = (params) => {
|
|
202
249
|
const { message } = { message: params?.message ?? validationMessages.email };
|
|
203
250
|
const emailRegExp =
|
|
@@ -211,6 +258,12 @@ export const createRules = (validationMessages) => {
|
|
|
211
258
|
return undefined;
|
|
212
259
|
};
|
|
213
260
|
};
|
|
261
|
+
/**
|
|
262
|
+
*
|
|
263
|
+
* @param params - ValidationRuleParams<'lettersOnly', { whiteSpaces?: boolean }>
|
|
264
|
+
* @returns ValidationRuleResult<T, D>
|
|
265
|
+
* @description Checks if the value is a string and if it contains only letters.
|
|
266
|
+
*/
|
|
214
267
|
const lettersOnly = (params) => {
|
|
215
268
|
const { message, whiteSpaces = false } = { ...params, message: params?.message ?? validationMessages.lettersOnly };
|
|
216
269
|
const lettersRegex = whiteSpaces ? /^[а-яА-Яa-zA-Z\s]+$/ : /^[а-яА-Яa-zA-Z]+$/;
|
|
@@ -222,6 +275,12 @@ export const createRules = (validationMessages) => {
|
|
|
222
275
|
return undefined;
|
|
223
276
|
};
|
|
224
277
|
};
|
|
278
|
+
/**
|
|
279
|
+
*
|
|
280
|
+
* @param params - ValidationRuleParams<'allowedOnly', { allowed?: unknown[] }>
|
|
281
|
+
* @returns ValidationRuleResult<T, D>
|
|
282
|
+
* @description Checks if the value is in the allowed values specified in the params.
|
|
283
|
+
*/
|
|
225
284
|
const allowedOnly = (params) => {
|
|
226
285
|
const { message, allowed } = { ...params, message: params?.message ?? validationMessages.allowedOnly };
|
|
227
286
|
return ({ val }) => {
|
|
@@ -239,6 +298,12 @@ export const createRules = (validationMessages) => {
|
|
|
239
298
|
return undefined;
|
|
240
299
|
};
|
|
241
300
|
};
|
|
301
|
+
/**
|
|
302
|
+
*
|
|
303
|
+
* @param params - ValidationRuleParams<'sameAs', { key: keyof T | string }>
|
|
304
|
+
* @returns ValidationRuleResult<T, D>
|
|
305
|
+
* @description Checks if the value is the same as the value of the field specified in the params.
|
|
306
|
+
*/
|
|
242
307
|
const sameAs = (params) => {
|
|
243
308
|
const { message, key } = { ...params, message: params?.message ?? validationMessages.sameAs };
|
|
244
309
|
return ({ val, listValues }) => {
|
|
@@ -252,7 +317,7 @@ export const createRules = (validationMessages) => {
|
|
|
252
317
|
return JSON.stringify(val) === JSON.stringify(listValues[key]) ? undefined : message(String(key));
|
|
253
318
|
}
|
|
254
319
|
catch {
|
|
255
|
-
return
|
|
320
|
+
return 'Parsing error';
|
|
256
321
|
}
|
|
257
322
|
default:
|
|
258
323
|
return String(val ?? '') === String(listValues?.[key] ?? '') ? undefined : message(String(key));
|
|
@@ -261,6 +326,12 @@ export const createRules = (validationMessages) => {
|
|
|
261
326
|
return undefined;
|
|
262
327
|
};
|
|
263
328
|
};
|
|
329
|
+
/**
|
|
330
|
+
*
|
|
331
|
+
* @param params - ValidationRuleParams<'notSameAs', { key: keyof T | string }>
|
|
332
|
+
* @returns ValidationRuleResult<T, D>
|
|
333
|
+
* @description Checks if the value is not the same as the value of the field specified in the params.
|
|
334
|
+
*/
|
|
264
335
|
const notSameAs = (params) => {
|
|
265
336
|
const { message, key } = { ...params, message: params?.message ?? validationMessages.notSameAs };
|
|
266
337
|
return ({ val, listValues }) => {
|
|
@@ -274,7 +345,7 @@ export const createRules = (validationMessages) => {
|
|
|
274
345
|
return JSON.stringify(val) !== JSON.stringify(listValues[key]) ? undefined : message(String(key));
|
|
275
346
|
}
|
|
276
347
|
catch {
|
|
277
|
-
return
|
|
348
|
+
return 'Parsing error';
|
|
278
349
|
}
|
|
279
350
|
default:
|
|
280
351
|
return String(val) === String(listValues?.[key]) ? undefined : message(String(key));
|
|
@@ -283,6 +354,12 @@ export const createRules = (validationMessages) => {
|
|
|
283
354
|
return undefined;
|
|
284
355
|
};
|
|
285
356
|
};
|
|
357
|
+
/**
|
|
358
|
+
*
|
|
359
|
+
* @param params - ValidationRuleParams<'required', { byCondition?: (params: ValidationParams<T, D, J>) => boolean }>
|
|
360
|
+
* @returns ValidationRuleResult<T, D, J>
|
|
361
|
+
* @description Marks the field as required. If the byCondition is specified, the field will be required only if the byCondition returns true.
|
|
362
|
+
*/
|
|
286
363
|
const required = (params) => {
|
|
287
364
|
const { message, byCondition } = { ...params, message: params?.message ?? validationMessages.required };
|
|
288
365
|
return ({ val, listValues, key }) => {
|
|
@@ -299,6 +376,12 @@ export const createRules = (validationMessages) => {
|
|
|
299
376
|
return undefined;
|
|
300
377
|
};
|
|
301
378
|
};
|
|
379
|
+
/**
|
|
380
|
+
*
|
|
381
|
+
* @param params - ValidationRuleParams<'password', { length?: number; specialChars?: boolean | number; numbers?: boolean | number; lowerUpperCasePattern?: boolean }>
|
|
382
|
+
* @returns ValidationRuleResult<T, D>
|
|
383
|
+
* @description Sets the password rules. Can check the length, the number of special characters, the number of numbers and the presence of uppercase and lowercase letters.
|
|
384
|
+
*/
|
|
302
385
|
const password = (params) => {
|
|
303
386
|
const { message, length = 8, specialChars, numbers, lowerUpperCasePattern } = { ...params, message: { ...validationMessages.password, ...params?.message } };
|
|
304
387
|
return ({ val }) => {
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import type { RequestErrors } from '../../delivery/schema/index.js';
|
|
2
2
|
import type { AsyncActionResponse } from '../../index.js';
|
|
3
|
+
type InitialData<FormData> = Partial<FormData> | Promise<Partial<FormData>> | (() => Partial<FormData> | Promise<Partial<FormData>>);
|
|
3
4
|
export interface FormConfig<FormData, Response> {
|
|
4
|
-
initialData?:
|
|
5
|
+
initialData?: InitialData<FormData>;
|
|
5
6
|
onSuccess?: (response: Response) => Promise<void> | void;
|
|
6
7
|
onError?: () => Promise<void> | void;
|
|
8
|
+
beforeSubmit?: (form: ActiveFormController<FormData>, abort: () => void) => Promise<void> | void;
|
|
9
|
+
waitForInitialData?: boolean;
|
|
7
10
|
}
|
|
8
11
|
export interface ActiveForm<FormData, Response, Custom> {
|
|
9
12
|
data: Partial<FormData>;
|
|
@@ -12,6 +15,12 @@ export interface ActiveForm<FormData, Response, Custom> {
|
|
|
12
15
|
reset: (toInitial?: boolean) => void;
|
|
13
16
|
pending: boolean;
|
|
14
17
|
dirty: boolean;
|
|
18
|
+
ready: Promise<Partial<FormData>>;
|
|
19
|
+
}
|
|
20
|
+
export interface ActiveFormController<FormData> {
|
|
21
|
+
data: Partial<FormData>;
|
|
22
|
+
errors: RequestErrors<FormData>;
|
|
23
|
+
reset: (toInitial?: boolean) => void;
|
|
15
24
|
}
|
|
16
25
|
type ExtractResponse<T> = T extends AsyncActionResponse<infer R, unknown, unknown> ? R : never;
|
|
17
26
|
type ExtractFormData<T> = T extends AsyncActionResponse<unknown, infer D, unknown> ? D : never;
|
|
@@ -1,12 +1,50 @@
|
|
|
1
1
|
import { ObjectUtil } from 'azure-net-tools';
|
|
2
2
|
export const createActiveForm = (onSubmit, config) => {
|
|
3
|
-
const
|
|
3
|
+
const isPromise = (value) => {
|
|
4
|
+
return typeof value?.then === 'function';
|
|
5
|
+
};
|
|
6
|
+
const resolveInitialSource = () => {
|
|
7
|
+
const source = config?.initialData;
|
|
8
|
+
if (!source) {
|
|
9
|
+
return { sync: true, value: {} };
|
|
10
|
+
}
|
|
11
|
+
const result = typeof source === 'function' ? source() : source;
|
|
12
|
+
if (isPromise(result)) {
|
|
13
|
+
return { sync: false, promise: result };
|
|
14
|
+
}
|
|
15
|
+
return { sync: true, value: (result ?? {}) };
|
|
16
|
+
};
|
|
17
|
+
const initialSource = resolveInitialSource();
|
|
18
|
+
let initial = initialSource.sync ? initialSource.value : {};
|
|
4
19
|
let formData = $state(ObjectUtil.deepClone(initial));
|
|
5
20
|
let formErrors = $state({});
|
|
6
21
|
let pending = $state(false);
|
|
7
22
|
const dirty = $derived(JSON.stringify(formData) !== JSON.stringify(initial));
|
|
23
|
+
const ready = (async () => {
|
|
24
|
+
if (!initialSource.sync) {
|
|
25
|
+
initial = (await initialSource.promise) ?? {};
|
|
26
|
+
if (config?.waitForInitialData !== false) {
|
|
27
|
+
formData = ObjectUtil.deepClone(initial);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return initial;
|
|
31
|
+
})();
|
|
8
32
|
const submit = async () => {
|
|
9
33
|
pending = true;
|
|
34
|
+
if (config?.beforeSubmit) {
|
|
35
|
+
let aborted = false;
|
|
36
|
+
const abort = () => {
|
|
37
|
+
aborted = true;
|
|
38
|
+
pending = false;
|
|
39
|
+
};
|
|
40
|
+
await config.beforeSubmit(formApi, () => abort());
|
|
41
|
+
if (aborted) {
|
|
42
|
+
return {
|
|
43
|
+
success: false,
|
|
44
|
+
response: undefined
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
}
|
|
10
48
|
try {
|
|
11
49
|
const result = await onSubmit($state.snapshot(formData));
|
|
12
50
|
if (result.error?.fields) {
|
|
@@ -28,7 +66,7 @@ export const createActiveForm = (onSubmit, config) => {
|
|
|
28
66
|
formData = toInitial ? ObjectUtil.deepClone(initial) : {};
|
|
29
67
|
formErrors = {};
|
|
30
68
|
};
|
|
31
|
-
|
|
69
|
+
const formApi = {
|
|
32
70
|
get data() {
|
|
33
71
|
return formData;
|
|
34
72
|
},
|
|
@@ -38,12 +76,20 @@ export const createActiveForm = (onSubmit, config) => {
|
|
|
38
76
|
get errors() {
|
|
39
77
|
return formErrors;
|
|
40
78
|
},
|
|
79
|
+
set errors(value) {
|
|
80
|
+
formErrors = value;
|
|
81
|
+
},
|
|
82
|
+
reset
|
|
83
|
+
};
|
|
84
|
+
return {
|
|
85
|
+
...formApi,
|
|
41
86
|
get dirty() {
|
|
42
87
|
return dirty;
|
|
43
88
|
},
|
|
44
89
|
get pending() {
|
|
45
90
|
return pending;
|
|
46
91
|
},
|
|
92
|
+
ready,
|
|
47
93
|
submit,
|
|
48
94
|
reset
|
|
49
95
|
};
|
|
@@ -52,7 +52,14 @@ export const createAsyncSignal = (handler, options = {}) => {
|
|
|
52
52
|
let status = $state('idle');
|
|
53
53
|
const pending = $derived(status === 'pending');
|
|
54
54
|
let abortController = null;
|
|
55
|
-
|
|
55
|
+
let currentPromise = null;
|
|
56
|
+
const ensurePromise = () => {
|
|
57
|
+
if (currentPromise)
|
|
58
|
+
return currentPromise;
|
|
59
|
+
currentPromise = run();
|
|
60
|
+
return currentPromise;
|
|
61
|
+
};
|
|
62
|
+
const run = async () => {
|
|
56
63
|
if (abortController) {
|
|
57
64
|
abortController.abort();
|
|
58
65
|
}
|
|
@@ -62,25 +69,34 @@ export const createAsyncSignal = (handler, options = {}) => {
|
|
|
62
69
|
try {
|
|
63
70
|
const result = await handler(abortController.signal);
|
|
64
71
|
if (abortController.signal.aborted) {
|
|
65
|
-
return;
|
|
72
|
+
return undefined;
|
|
66
73
|
}
|
|
67
74
|
data = result;
|
|
68
75
|
status = 'success';
|
|
69
76
|
if (options.onSuccess) {
|
|
70
77
|
options.onSuccess(result);
|
|
71
78
|
}
|
|
79
|
+
return result;
|
|
72
80
|
}
|
|
73
81
|
catch (err) {
|
|
74
82
|
if (err instanceof Error && err.name === 'AbortError') {
|
|
75
|
-
return;
|
|
83
|
+
return undefined;
|
|
76
84
|
}
|
|
77
85
|
error = err;
|
|
78
86
|
status = 'error';
|
|
79
87
|
if (options.onError) {
|
|
80
88
|
options.onError(err);
|
|
81
89
|
}
|
|
90
|
+
return undefined;
|
|
82
91
|
}
|
|
83
|
-
}
|
|
92
|
+
};
|
|
93
|
+
const execute = async () => {
|
|
94
|
+
if (status === 'pending' && currentPromise) {
|
|
95
|
+
await currentPromise;
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
await ensurePromise();
|
|
99
|
+
};
|
|
84
100
|
if (EnvironmentUtil.isBrowser) {
|
|
85
101
|
const signalKey = key ?? asyncSignalManager.generateKey();
|
|
86
102
|
asyncSignalManager.register(signalKey, () => execute());
|
|
@@ -127,12 +143,16 @@ export const createAsyncSignal = (handler, options = {}) => {
|
|
|
127
143
|
get pending() {
|
|
128
144
|
return pending;
|
|
129
145
|
},
|
|
146
|
+
get ready() {
|
|
147
|
+
return ensurePromise();
|
|
148
|
+
},
|
|
130
149
|
execute,
|
|
131
150
|
refresh: execute,
|
|
132
151
|
reset: () => {
|
|
133
152
|
data = undefined;
|
|
134
153
|
error = undefined;
|
|
135
154
|
status = 'idle';
|
|
155
|
+
currentPromise = null;
|
|
136
156
|
if (abortController) {
|
|
137
157
|
abortController.abort();
|
|
138
158
|
abortController = null;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export type QuerySignal = {
|
|
2
|
+
refresh: () => Promise<void>;
|
|
3
|
+
};
|
|
4
|
+
export interface CreateQueryOptions<T extends Record<string, unknown>> {
|
|
5
|
+
initial: T;
|
|
6
|
+
signal?: QuerySignal;
|
|
7
|
+
excludeKeys?: (keyof T)[];
|
|
8
|
+
debounceMs?: number;
|
|
9
|
+
autoRefresh?: boolean;
|
|
10
|
+
}
|
|
11
|
+
export interface QueryController<T extends Record<string, unknown>> {
|
|
12
|
+
data: T;
|
|
13
|
+
patch: (values: Partial<T>) => void;
|
|
14
|
+
set: <K extends keyof T>(key: K, value: T[K]) => void;
|
|
15
|
+
reset: () => void;
|
|
16
|
+
snapshot: () => T;
|
|
17
|
+
initial: () => T;
|
|
18
|
+
attachSignal: (signal?: QuerySignal) => void;
|
|
19
|
+
}
|
|
20
|
+
export declare const createQuery: <T extends Record<string, unknown>>(options: CreateQueryOptions<T>) => QueryController<T>;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { ObjectUtil } from 'azure-net-tools';
|
|
2
|
+
export const createQuery = (options) => {
|
|
3
|
+
const { initial: initialValue, signal: initialSignal, excludeKeys, debounceMs = 0, autoRefresh = true } = options;
|
|
4
|
+
const baseInitial = ObjectUtil.deepClone(initialValue);
|
|
5
|
+
let signal = initialSignal;
|
|
6
|
+
let data = $state(ObjectUtil.deepClone(baseInitial));
|
|
7
|
+
const resolveKeys = () => {
|
|
8
|
+
const keys = Object.keys(baseInitial).slice();
|
|
9
|
+
if (excludeKeys?.length) {
|
|
10
|
+
return keys.filter((key) => !excludeKeys.includes(key));
|
|
11
|
+
}
|
|
12
|
+
return keys;
|
|
13
|
+
};
|
|
14
|
+
const keys = resolveKeys();
|
|
15
|
+
let isFirstRun = true;
|
|
16
|
+
let debounceTimer = null;
|
|
17
|
+
const scheduleRefresh = () => {
|
|
18
|
+
if (!signal)
|
|
19
|
+
return;
|
|
20
|
+
if (debounceTimer)
|
|
21
|
+
clearTimeout(debounceTimer);
|
|
22
|
+
if (debounceMs > 0) {
|
|
23
|
+
debounceTimer = setTimeout(() => {
|
|
24
|
+
void signal?.refresh();
|
|
25
|
+
}, debounceMs);
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
void signal.refresh();
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
if (autoRefresh) {
|
|
32
|
+
$effect(() => {
|
|
33
|
+
keys.forEach((key) => {
|
|
34
|
+
void data[key];
|
|
35
|
+
});
|
|
36
|
+
if (isFirstRun) {
|
|
37
|
+
isFirstRun = false;
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
scheduleRefresh();
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
const patch = (values) => {
|
|
44
|
+
data = { ...data, ...values };
|
|
45
|
+
};
|
|
46
|
+
const set = (key, value) => {
|
|
47
|
+
data = { ...data, [key]: value };
|
|
48
|
+
};
|
|
49
|
+
const reset = () => {
|
|
50
|
+
data = ObjectUtil.deepClone(baseInitial);
|
|
51
|
+
};
|
|
52
|
+
const snapshot = () => ObjectUtil.deepClone(data);
|
|
53
|
+
const initial = () => ObjectUtil.deepClone(baseInitial);
|
|
54
|
+
const attachSignal = (nextSignal) => {
|
|
55
|
+
signal = nextSignal;
|
|
56
|
+
};
|
|
57
|
+
return {
|
|
58
|
+
get data() {
|
|
59
|
+
return data;
|
|
60
|
+
},
|
|
61
|
+
set data(value) {
|
|
62
|
+
data = value;
|
|
63
|
+
},
|
|
64
|
+
patch,
|
|
65
|
+
set,
|
|
66
|
+
reset,
|
|
67
|
+
snapshot,
|
|
68
|
+
initial,
|
|
69
|
+
attachSignal
|
|
70
|
+
};
|
|
71
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './Query.svelte.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './Query.svelte.js';
|