@regle/core 1.11.0-beta.1 → 1.11.0-beta.2
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/regle-core.d.ts +1195 -3958
- package/dist/regle-core.js +1217 -1259
- package/dist/regle-core.min.js +1 -1
- package/package.json +8 -12
package/dist/regle-core.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { computed, effectScope, getCurrentInstance, getCurrentScope, isRef, markRaw, nextTick, onMounted, onScopeDispose, reactive, ref, shallowRef, toRef, toValue, triggerRef, unref, version, watch, watchEffect } from "vue";
|
|
2
2
|
import { setupDevtoolsPlugin } from "@vue/devtools-api";
|
|
3
3
|
|
|
4
|
-
//#region ../shared/utils/isFile.ts
|
|
5
4
|
/**
|
|
6
5
|
* Server side friendly way of checking for a File
|
|
7
6
|
*/
|
|
@@ -9,8 +8,6 @@ function isFile(value) {
|
|
|
9
8
|
return value?.constructor?.name == "File" || value?.constructor?.name == "FileList";
|
|
10
9
|
}
|
|
11
10
|
|
|
12
|
-
//#endregion
|
|
13
|
-
//#region ../shared/utils/isEmpty.ts
|
|
14
11
|
/**
|
|
15
12
|
* This is the inverse of isFilled. It will check if the value is in any way empty (including arrays and objects)
|
|
16
13
|
*
|
|
@@ -30,12 +27,8 @@ function isEmpty(value, considerEmptyArrayInvalid = true) {
|
|
|
30
27
|
return !String(value).length;
|
|
31
28
|
}
|
|
32
29
|
|
|
33
|
-
//#endregion
|
|
34
|
-
//#region ../shared/utils/symbol.ts
|
|
35
30
|
const RegleRuleSymbol = Symbol("regle-rule");
|
|
36
31
|
|
|
37
|
-
//#endregion
|
|
38
|
-
//#region ../shared/utils/cloneDeep.ts
|
|
39
32
|
function getRegExpFlags(regExp) {
|
|
40
33
|
if (typeof regExp.source.flags == "string") return regExp.source.flags;
|
|
41
34
|
else {
|
|
@@ -62,8 +55,6 @@ function cloneDeep(obj) {
|
|
|
62
55
|
return result;
|
|
63
56
|
}
|
|
64
57
|
|
|
65
|
-
//#endregion
|
|
66
|
-
//#region ../shared/utils/object.utils.ts
|
|
67
58
|
function isObject(obj) {
|
|
68
59
|
if (obj && (obj instanceof Date || obj.constructor.name == "File" || obj.constructor.name == "FileList")) return false;
|
|
69
60
|
return typeof obj === "object" && obj !== null && !Array.isArray(obj);
|
|
@@ -146,8 +137,6 @@ function dotPathObjectToNested(obj) {
|
|
|
146
137
|
return result;
|
|
147
138
|
}
|
|
148
139
|
|
|
149
|
-
//#endregion
|
|
150
|
-
//#region ../shared/utils/toDate.ts
|
|
151
140
|
/**
|
|
152
141
|
* This utility will coerce any string, number or Date value into a Date using the Date constructor.
|
|
153
142
|
*/
|
|
@@ -160,8 +149,6 @@ function toDate(argument) {
|
|
|
160
149
|
else return /* @__PURE__ */ new Date(NaN);
|
|
161
150
|
}
|
|
162
151
|
|
|
163
|
-
//#endregion
|
|
164
|
-
//#region ../shared/utils/debounce.ts
|
|
165
152
|
function debounce(func, wait, { immediate = false, trackDebounceRef } = {}) {
|
|
166
153
|
let timeout;
|
|
167
154
|
const debouncedFn = (...args) => {
|
|
@@ -202,8 +189,6 @@ function debounce(func, wait, { immediate = false, trackDebounceRef } = {}) {
|
|
|
202
189
|
return debouncedFn;
|
|
203
190
|
}
|
|
204
191
|
|
|
205
|
-
//#endregion
|
|
206
|
-
//#region ../shared/utils/isEqual.ts
|
|
207
192
|
function isEqual(a, b, deep = false, firstDeep = true) {
|
|
208
193
|
if (a === b) return true;
|
|
209
194
|
if (a && b && typeof a == "object" && typeof b == "object") {
|
|
@@ -236,8 +221,6 @@ function isEqual(a, b, deep = false, firstDeep = true) {
|
|
|
236
221
|
return a !== a && b !== b;
|
|
237
222
|
}
|
|
238
223
|
|
|
239
|
-
//#endregion
|
|
240
|
-
//#region ../shared/utils/abortablePromise.ts
|
|
241
224
|
var AbortError = class extends Error {
|
|
242
225
|
constructor(message = "Promise was aborted") {
|
|
243
226
|
super(message);
|
|
@@ -279,15 +262,11 @@ function abortablePromise(input) {
|
|
|
279
262
|
};
|
|
280
263
|
}
|
|
281
264
|
|
|
282
|
-
//#endregion
|
|
283
|
-
//#region src/types/rules/rule.internal.types.ts
|
|
284
265
|
const InternalRuleType = {
|
|
285
266
|
Inline: "__inline",
|
|
286
267
|
Async: "__async"
|
|
287
268
|
};
|
|
288
269
|
|
|
289
|
-
//#endregion
|
|
290
|
-
//#region src/types/utils/groups.ts
|
|
291
270
|
function mergeBooleanGroupProperties(entries, property) {
|
|
292
271
|
return entries.some((entry) => {
|
|
293
272
|
if (!property) return false;
|
|
@@ -302,8 +281,6 @@ function mergeArrayGroupProperties(entries, property) {
|
|
|
302
281
|
}, []);
|
|
303
282
|
}
|
|
304
283
|
|
|
305
|
-
//#endregion
|
|
306
|
-
//#region src/core/createRule/unwrapRuleParameters.ts
|
|
307
284
|
/**
|
|
308
285
|
* Returns a clean list of parameters
|
|
309
286
|
* Removing Ref and executing function to return the unwrapped value
|
|
@@ -335,8 +312,6 @@ function getFunctionParametersLength(func) {
|
|
|
335
312
|
return (paramsMatch[0] || paramsMatch[1] || paramsMatch[2] || paramsMatch[3] || paramsMatch[4] || "").split(",").map((p) => p.trim()).filter((p) => p.length > 0).length;
|
|
336
313
|
}
|
|
337
314
|
|
|
338
|
-
//#endregion
|
|
339
|
-
//#region src/core/createRule/defineRuleProcessors.ts
|
|
340
315
|
function defineRuleProcessors(definition, ...params) {
|
|
341
316
|
const { validator, type, async } = definition;
|
|
342
317
|
const isAsync = async || type === InternalRuleType.Async || validator.constructor.name === "AsyncFunction";
|
|
@@ -393,8 +368,6 @@ function defineRuleProcessors(definition, ...params) {
|
|
|
393
368
|
});
|
|
394
369
|
}
|
|
395
370
|
|
|
396
|
-
//#endregion
|
|
397
|
-
//#region src/core/createRule/createRule.ts
|
|
398
371
|
/**
|
|
399
372
|
* Create a typed custom rule that can be used like default rules.
|
|
400
373
|
* It can also be declared in the global options
|
|
@@ -458,8 +431,98 @@ function createRule(definition) {
|
|
|
458
431
|
throw new Error("[createRule] validator must be a function");
|
|
459
432
|
}
|
|
460
433
|
|
|
461
|
-
|
|
462
|
-
|
|
434
|
+
/**
|
|
435
|
+
* Checks if a Vue Ref is an object.
|
|
436
|
+
*
|
|
437
|
+
* @param obj - The Ref to check
|
|
438
|
+
* @returns True if the Ref is an object, false otherwise
|
|
439
|
+
*/
|
|
440
|
+
function isRefObject(obj) {
|
|
441
|
+
return isObject(obj.value);
|
|
442
|
+
}
|
|
443
|
+
/**
|
|
444
|
+
* Unwraps a collection ($each) getter function or returns the getter directly if it's not a function.
|
|
445
|
+
*
|
|
446
|
+
* @template T - The type of the getter function or the getter value
|
|
447
|
+
* @param getter - The getter function or value to unwrap
|
|
448
|
+
* @param value - The value to pass to the getter
|
|
449
|
+
* @param index - The index to pass to the getter
|
|
450
|
+
* @returns An object containing the scope and the unwrapped value
|
|
451
|
+
*/
|
|
452
|
+
function unwrapGetter(getter, value, index) {
|
|
453
|
+
const scope = effectScope();
|
|
454
|
+
let unwrapped;
|
|
455
|
+
if (getter instanceof Function) unwrapped = scope.run(() => getter(value, index ?? 0));
|
|
456
|
+
else unwrapped = getter;
|
|
457
|
+
return {
|
|
458
|
+
scope,
|
|
459
|
+
unwrapped
|
|
460
|
+
};
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
const VersionIs = {
|
|
464
|
+
LessThan: -1,
|
|
465
|
+
EqualTo: 0,
|
|
466
|
+
GreaterThan: 1
|
|
467
|
+
};
|
|
468
|
+
/**
|
|
469
|
+
* Compare two versions quickly.
|
|
470
|
+
* @param current Is this version greater, equal to, or less than the other?
|
|
471
|
+
* @param other The version to compare against the current version
|
|
472
|
+
* @return 1 if current is greater than other, 0 if they are equal or equivalent, and -1 if current is less than other
|
|
473
|
+
*/
|
|
474
|
+
function versionCompare(current, other) {
|
|
475
|
+
const cp = String(current).split(".");
|
|
476
|
+
const op = String(other).split(".");
|
|
477
|
+
for (let depth = 0; depth < Math.min(cp.length, op.length); depth++) {
|
|
478
|
+
const cn = Number(cp[depth]);
|
|
479
|
+
const on = Number(op[depth]);
|
|
480
|
+
if (cn > on) return VersionIs.GreaterThan;
|
|
481
|
+
if (on > cn) return VersionIs.LessThan;
|
|
482
|
+
if (!isNaN(cn) && isNaN(on)) return VersionIs.GreaterThan;
|
|
483
|
+
if (isNaN(cn) && !isNaN(on)) return VersionIs.LessThan;
|
|
484
|
+
}
|
|
485
|
+
return VersionIs.EqualTo;
|
|
486
|
+
}
|
|
487
|
+
const isVueSuperiorOrEqualTo3dotFive = versionCompare(version, "3.5.0") === -1 ? false : true;
|
|
488
|
+
|
|
489
|
+
function uniqueIDNuxt() {
|
|
490
|
+
return Math.floor(Math.random() * Date.now()).toString();
|
|
491
|
+
}
|
|
492
|
+
/**
|
|
493
|
+
* Generates a random SSR compatible ID.
|
|
494
|
+
*/
|
|
495
|
+
function randomId() {
|
|
496
|
+
if (typeof window === "undefined") return uniqueIDNuxt();
|
|
497
|
+
else return window.crypto.getRandomValues(new Uint32Array(1))[0].toString(10);
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
function tryOnScopeDispose(fn) {
|
|
501
|
+
if (getCurrentScope()) {
|
|
502
|
+
onScopeDispose(fn);
|
|
503
|
+
return true;
|
|
504
|
+
}
|
|
505
|
+
return false;
|
|
506
|
+
}
|
|
507
|
+
/**
|
|
508
|
+
* Creates a global state that is shared for scoped validation.
|
|
509
|
+
*
|
|
510
|
+
* @param stateFactory - The function that creates the state
|
|
511
|
+
* @returns The state factory function
|
|
512
|
+
*/
|
|
513
|
+
function createGlobalState(stateFactory) {
|
|
514
|
+
let initialized = false;
|
|
515
|
+
let state;
|
|
516
|
+
const scope = effectScope(true);
|
|
517
|
+
return ((...args) => {
|
|
518
|
+
if (!initialized) {
|
|
519
|
+
state = scope.run(() => stateFactory(...args));
|
|
520
|
+
initialized = true;
|
|
521
|
+
}
|
|
522
|
+
return state;
|
|
523
|
+
});
|
|
524
|
+
}
|
|
525
|
+
|
|
463
526
|
/**
|
|
464
527
|
* Inspired by Vuelidate storage
|
|
465
528
|
*/
|
|
@@ -580,108 +643,6 @@ function useStorage() {
|
|
|
580
643
|
};
|
|
581
644
|
}
|
|
582
645
|
|
|
583
|
-
//#endregion
|
|
584
|
-
//#region src/utils/object.utils.ts
|
|
585
|
-
/**
|
|
586
|
-
* Checks if a Vue Ref is an object.
|
|
587
|
-
*
|
|
588
|
-
* @param obj - The Ref to check
|
|
589
|
-
* @returns True if the Ref is an object, false otherwise
|
|
590
|
-
*/
|
|
591
|
-
function isRefObject(obj) {
|
|
592
|
-
return isObject(obj.value);
|
|
593
|
-
}
|
|
594
|
-
/**
|
|
595
|
-
* Unwraps a collection ($each) getter function or returns the getter directly if it's not a function.
|
|
596
|
-
*
|
|
597
|
-
* @template T - The type of the getter function or the getter value
|
|
598
|
-
* @param getter - The getter function or value to unwrap
|
|
599
|
-
* @param value - The value to pass to the getter
|
|
600
|
-
* @param index - The index to pass to the getter
|
|
601
|
-
* @returns An object containing the scope and the unwrapped value
|
|
602
|
-
*/
|
|
603
|
-
function unwrapGetter(getter, value, index) {
|
|
604
|
-
const scope = effectScope();
|
|
605
|
-
let unwrapped;
|
|
606
|
-
if (getter instanceof Function) unwrapped = scope.run(() => getter(value, index ?? 0));
|
|
607
|
-
else unwrapped = getter;
|
|
608
|
-
return {
|
|
609
|
-
scope,
|
|
610
|
-
unwrapped
|
|
611
|
-
};
|
|
612
|
-
}
|
|
613
|
-
|
|
614
|
-
//#endregion
|
|
615
|
-
//#region src/utils/version-compare.ts
|
|
616
|
-
const VersionIs = {
|
|
617
|
-
LessThan: -1,
|
|
618
|
-
EqualTo: 0,
|
|
619
|
-
GreaterThan: 1
|
|
620
|
-
};
|
|
621
|
-
/**
|
|
622
|
-
* Compare two versions quickly.
|
|
623
|
-
* @param current Is this version greater, equal to, or less than the other?
|
|
624
|
-
* @param other The version to compare against the current version
|
|
625
|
-
* @return 1 if current is greater than other, 0 if they are equal or equivalent, and -1 if current is less than other
|
|
626
|
-
*/
|
|
627
|
-
function versionCompare(current, other) {
|
|
628
|
-
const cp = String(current).split(".");
|
|
629
|
-
const op = String(other).split(".");
|
|
630
|
-
for (let depth = 0; depth < Math.min(cp.length, op.length); depth++) {
|
|
631
|
-
const cn = Number(cp[depth]);
|
|
632
|
-
const on = Number(op[depth]);
|
|
633
|
-
if (cn > on) return VersionIs.GreaterThan;
|
|
634
|
-
if (on > cn) return VersionIs.LessThan;
|
|
635
|
-
if (!isNaN(cn) && isNaN(on)) return VersionIs.GreaterThan;
|
|
636
|
-
if (isNaN(cn) && !isNaN(on)) return VersionIs.LessThan;
|
|
637
|
-
}
|
|
638
|
-
return VersionIs.EqualTo;
|
|
639
|
-
}
|
|
640
|
-
const isVueSuperiorOrEqualTo3dotFive = versionCompare(version, "3.5.0") === -1 ? false : true;
|
|
641
|
-
|
|
642
|
-
//#endregion
|
|
643
|
-
//#region src/utils/randomId.ts
|
|
644
|
-
function uniqueIDNuxt() {
|
|
645
|
-
return Math.floor(Math.random() * Date.now()).toString();
|
|
646
|
-
}
|
|
647
|
-
/**
|
|
648
|
-
* Generates a random SSR compatible ID.
|
|
649
|
-
*/
|
|
650
|
-
function randomId() {
|
|
651
|
-
if (typeof window === "undefined") return uniqueIDNuxt();
|
|
652
|
-
else return window.crypto.getRandomValues(new Uint32Array(1))[0].toString(10);
|
|
653
|
-
}
|
|
654
|
-
|
|
655
|
-
//#endregion
|
|
656
|
-
//#region src/utils/state.utils.ts
|
|
657
|
-
function tryOnScopeDispose(fn) {
|
|
658
|
-
if (getCurrentScope()) {
|
|
659
|
-
onScopeDispose(fn);
|
|
660
|
-
return true;
|
|
661
|
-
}
|
|
662
|
-
return false;
|
|
663
|
-
}
|
|
664
|
-
/**
|
|
665
|
-
* Creates a global state that is shared for scoped validation.
|
|
666
|
-
*
|
|
667
|
-
* @param stateFactory - The function that creates the state
|
|
668
|
-
* @returns The state factory function
|
|
669
|
-
*/
|
|
670
|
-
function createGlobalState(stateFactory) {
|
|
671
|
-
let initialized = false;
|
|
672
|
-
let state;
|
|
673
|
-
const scope = effectScope(true);
|
|
674
|
-
return ((...args) => {
|
|
675
|
-
if (!initialized) {
|
|
676
|
-
state = scope.run(() => stateFactory(...args));
|
|
677
|
-
initialized = true;
|
|
678
|
-
}
|
|
679
|
-
return state;
|
|
680
|
-
});
|
|
681
|
-
}
|
|
682
|
-
|
|
683
|
-
//#endregion
|
|
684
|
-
//#region src/core/useRegle/guards/ruleDef.guards.ts
|
|
685
646
|
function isNestedRulesDef(state, rules) {
|
|
686
647
|
return isRefObject(state) || isObject(rules.value) && !isEmpty(rules.value) && !Object.entries(rules.value).some(([_, rule]) => isRuleDef(rule) || typeof rule === "function");
|
|
687
648
|
}
|
|
@@ -702,8 +663,6 @@ function isFormRuleDefinition(rule) {
|
|
|
702
663
|
return true;
|
|
703
664
|
}
|
|
704
665
|
|
|
705
|
-
//#endregion
|
|
706
|
-
//#region src/core/useRegle/guards/rule.status.guards.ts
|
|
707
666
|
function isNestedRulesStatus(rule) {
|
|
708
667
|
return isObject(rule) && "$fields" in rule;
|
|
709
668
|
}
|
|
@@ -714,8 +673,6 @@ function isFieldStatus(rule) {
|
|
|
714
673
|
return !!rule && "$rules" in rule;
|
|
715
674
|
}
|
|
716
675
|
|
|
717
|
-
//#endregion
|
|
718
|
-
//#region src/core/useRegle/useErrors.ts
|
|
719
676
|
function extractRulesIssues({ field, silent = false }) {
|
|
720
677
|
const ruleIssues = Object.entries(field.$rules ?? {}).map(([key, rule]) => {
|
|
721
678
|
let message = "";
|
|
@@ -794,8 +751,6 @@ function iterateErrors(errors, includePath = false, _path) {
|
|
|
794
751
|
} else return Object.entries(errors).map(([key, value]) => iterateErrors(value, includePath, path?.concat(key))).flat();
|
|
795
752
|
}
|
|
796
753
|
|
|
797
|
-
//#endregion
|
|
798
|
-
//#region src/core/useRegle/root/createReactiveRuleStatus.ts
|
|
799
754
|
function createReactiveRuleStatus({ customMessages, rule, ruleKey, state, path, cachePath, storage, modifiers }) {
|
|
800
755
|
let scope = effectScope();
|
|
801
756
|
let scopeState = {};
|
|
@@ -970,8 +925,6 @@ function createReactiveRuleStatus({ customMessages, rule, ruleKey, state, path,
|
|
|
970
925
|
});
|
|
971
926
|
}
|
|
972
927
|
|
|
973
|
-
//#endregion
|
|
974
|
-
//#region src/core/useRegle/root/standard-schemas.ts
|
|
975
928
|
function createStandardSchema(validateFn) {
|
|
976
929
|
return { "~standard": {
|
|
977
930
|
version: 1,
|
|
@@ -987,8 +940,6 @@ function createStandardSchema(validateFn) {
|
|
|
987
940
|
} };
|
|
988
941
|
}
|
|
989
942
|
|
|
990
|
-
//#endregion
|
|
991
|
-
//#region src/core/useRegle/root/createReactiveFieldStatus.ts
|
|
992
943
|
function createReactiveFieldStatus({ state, rulesDef, customMessages, path, cachePath, fieldName, storage, options, externalErrors, schemaErrors, schemaMode, onUnwatch, $isArray, initialState, originalState, shortcuts, onValidate }) {
|
|
993
944
|
let scope = effectScope();
|
|
994
945
|
let scopeState;
|
|
@@ -1418,8 +1369,6 @@ function createReactiveFieldStatus({ state, rulesDef, customMessages, path, cach
|
|
|
1418
1369
|
});
|
|
1419
1370
|
}
|
|
1420
1371
|
|
|
1421
|
-
//#endregion
|
|
1422
|
-
//#region src/core/useRegle/root/collections/createReactiveCollectionElement.ts
|
|
1423
1372
|
function createCollectionElement({ $id, path, cachePath, index, options, storage, stateValue, customMessages, rules, externalErrors, schemaErrors, initialState, originalState, shortcuts, fieldName, schemaMode }) {
|
|
1424
1373
|
const $fieldId = stateValue.value?.$id ?? rules.$key ?? randomId();
|
|
1425
1374
|
let $cachePath = `${cachePath}.${String($fieldId)}`;
|
|
@@ -1458,8 +1407,6 @@ function createCollectionElement({ $id, path, cachePath, index, options, storage
|
|
|
1458
1407
|
return $status;
|
|
1459
1408
|
}
|
|
1460
1409
|
|
|
1461
|
-
//#endregion
|
|
1462
|
-
//#region src/core/useRegle/root/collections/createReactiveCollectionRoot.ts
|
|
1463
1410
|
function createReactiveCollectionStatus({ state, rulesDef, customMessages, path, storage, options, externalErrors, schemaErrors, schemaMode, initialState, originalState, shortcuts, fieldName }) {
|
|
1464
1411
|
let scope = effectScope();
|
|
1465
1412
|
let scopeState;
|
|
@@ -1866,8 +1813,6 @@ function createReactiveCollectionStatus({ state, rulesDef, customMessages, path,
|
|
|
1866
1813
|
});
|
|
1867
1814
|
}
|
|
1868
1815
|
|
|
1869
|
-
//#endregion
|
|
1870
|
-
//#region src/core/useRegle/root/createReactiveNestedStatus.ts
|
|
1871
1816
|
function createReactiveNestedStatus({ rulesDef, state, path = "", cachePath, rootRules, externalErrors, schemaErrors, rootSchemaErrors, validationGroups, initialState, originalState, fieldName,...commonArgs }) {
|
|
1872
1817
|
let scope = effectScope();
|
|
1873
1818
|
let scopeState;
|
|
@@ -2110,6 +2055,16 @@ function createReactiveNestedStatus({ rulesDef, state, path = "", cachePath, roo
|
|
|
2110
2055
|
return false;
|
|
2111
2056
|
});
|
|
2112
2057
|
const $name = computed(() => fieldName);
|
|
2058
|
+
const $modifiers = computed(() => {
|
|
2059
|
+
return {
|
|
2060
|
+
autoDirty: $autoDirty.value,
|
|
2061
|
+
lazy: unref(commonArgs.options.lazy) ?? false,
|
|
2062
|
+
rewardEarly: $rewardEarly.value,
|
|
2063
|
+
silent: $silent.value,
|
|
2064
|
+
clearExternalErrorsOnChange: unref(commonArgs.options.clearExternalErrorsOnChange) ?? false,
|
|
2065
|
+
id: unref(commonArgs.options.id)
|
|
2066
|
+
};
|
|
2067
|
+
});
|
|
2113
2068
|
function processShortcuts() {
|
|
2114
2069
|
if (commonArgs.shortcuts?.nested) Object.entries(commonArgs.shortcuts.nested).forEach(([key, value]) => {
|
|
2115
2070
|
const scope$1 = effectScope();
|
|
@@ -2135,7 +2090,8 @@ function createReactiveNestedStatus({ rulesDef, state, path = "", cachePath, roo
|
|
|
2135
2090
|
$fields,
|
|
2136
2091
|
$edited,
|
|
2137
2092
|
$anyEdited,
|
|
2138
|
-
$issues
|
|
2093
|
+
$issues,
|
|
2094
|
+
"~modifiers": unref(commonArgs.options)
|
|
2139
2095
|
}));
|
|
2140
2096
|
});
|
|
2141
2097
|
return result;
|
|
@@ -2184,7 +2140,8 @@ function createReactiveNestedStatus({ rulesDef, state, path = "", cachePath, roo
|
|
|
2184
2140
|
$localPending,
|
|
2185
2141
|
$autoDirty,
|
|
2186
2142
|
$silent,
|
|
2187
|
-
$value
|
|
2143
|
+
$value,
|
|
2144
|
+
$modifiers
|
|
2188
2145
|
};
|
|
2189
2146
|
});
|
|
2190
2147
|
}
|
|
@@ -2291,6 +2248,7 @@ function createReactiveNestedStatus({ rulesDef, state, path = "", cachePath, roo
|
|
|
2291
2248
|
$clearExternalErrors,
|
|
2292
2249
|
$extractDirtyFields,
|
|
2293
2250
|
$abort,
|
|
2251
|
+
...!!rootRules ? { "~modifiers": scopeState.$modifiers } : {},
|
|
2294
2252
|
...createStandardSchema($validate)
|
|
2295
2253
|
});
|
|
2296
2254
|
watchEffect(() => {
|
|
@@ -2335,171 +2293,132 @@ function createReactiveChildrenStatus({ rulesDef,...properties }) {
|
|
|
2335
2293
|
});
|
|
2336
2294
|
}
|
|
2337
2295
|
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2296
|
+
const COLORS = {
|
|
2297
|
+
ERROR: {
|
|
2298
|
+
text: 16777215,
|
|
2299
|
+
bg: 15680580
|
|
2300
|
+
},
|
|
2301
|
+
INVALID: {
|
|
2302
|
+
text: 16777215,
|
|
2303
|
+
bg: 16747520
|
|
2304
|
+
},
|
|
2305
|
+
VALID: {
|
|
2306
|
+
text: 16777215,
|
|
2307
|
+
bg: 1096065
|
|
2308
|
+
},
|
|
2309
|
+
PENDING: {
|
|
2310
|
+
text: 16777215,
|
|
2311
|
+
bg: 16096779
|
|
2312
|
+
},
|
|
2313
|
+
DIRTY: {
|
|
2314
|
+
text: 2042167,
|
|
2315
|
+
bg: 16708551
|
|
2316
|
+
},
|
|
2317
|
+
COMPONENT: {
|
|
2318
|
+
text: 16777215,
|
|
2319
|
+
bg: 6514417
|
|
2320
|
+
},
|
|
2321
|
+
PRISTINE: {
|
|
2322
|
+
text: 1120295,
|
|
2323
|
+
bg: 16777215
|
|
2324
|
+
},
|
|
2325
|
+
INACTIVE: {
|
|
2326
|
+
text: 0,
|
|
2327
|
+
bg: 11581118
|
|
2363
2328
|
}
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
state,
|
|
2388
|
-
customMessages: customRules?.(),
|
|
2389
|
-
storage,
|
|
2390
|
-
options,
|
|
2391
|
-
externalErrors: computedExternalErrors,
|
|
2392
|
-
initialState,
|
|
2393
|
-
originalState,
|
|
2394
|
-
shortcuts,
|
|
2395
|
-
fieldName: "root",
|
|
2396
|
-
path: "",
|
|
2397
|
-
cachePath: "",
|
|
2398
|
-
schemaMode,
|
|
2399
|
-
schemaErrors,
|
|
2400
|
-
onValidate
|
|
2401
|
-
});
|
|
2402
|
-
if (getCurrentScope()) onScopeDispose(() => {
|
|
2403
|
-
regle.value?.$unwatch();
|
|
2404
|
-
$unwatchComputedExternalErrors?.();
|
|
2405
|
-
$unwatchExternalErrors?.();
|
|
2406
|
-
});
|
|
2407
|
-
return reactive({ regle });
|
|
2408
|
-
}
|
|
2409
|
-
|
|
2410
|
-
//#endregion
|
|
2411
|
-
//#region src/core/useRegle/shared.rootRegle.ts
|
|
2412
|
-
function createRootRegleLogic({ state, rulesFactory, options, globalOptions, customRules, shortcuts }) {
|
|
2413
|
-
const definedRules = isRef(rulesFactory) ? rulesFactory : typeof rulesFactory === "function" ? void 0 : computed(() => rulesFactory);
|
|
2414
|
-
const resolvedOptions = {
|
|
2415
|
-
...globalOptions,
|
|
2416
|
-
...options
|
|
2417
|
-
};
|
|
2418
|
-
let unwatchRules;
|
|
2419
|
-
const watchableRulesGetters = shallowRef(definedRules ?? {});
|
|
2420
|
-
if (typeof rulesFactory === "function") unwatchRules = watchEffect(() => {
|
|
2421
|
-
watchableRulesGetters.value = rulesFactory(state);
|
|
2422
|
-
triggerRef(watchableRulesGetters);
|
|
2423
|
-
});
|
|
2424
|
-
const initialState = ref(isObject(state.value) ? { ...cloneDeep(state.value) } : cloneDeep(state.value));
|
|
2425
|
-
const originalState = isObject(state.value) ? { ...cloneDeep(state.value) } : cloneDeep(state.value);
|
|
2426
|
-
tryOnScopeDispose(() => {
|
|
2427
|
-
unwatchRules?.();
|
|
2428
|
-
});
|
|
2429
|
-
const regle = useRootStorage({
|
|
2430
|
-
scopeRules: watchableRulesGetters,
|
|
2431
|
-
state,
|
|
2432
|
-
options: resolvedOptions,
|
|
2433
|
-
initialState,
|
|
2434
|
-
originalState,
|
|
2435
|
-
customRules,
|
|
2436
|
-
shortcuts
|
|
2437
|
-
});
|
|
2438
|
-
if (process.env.NODE_ENV === "development" && regle.regle) registerRegleInstance(regle.regle, { name: toValue(resolvedOptions.id) });
|
|
2439
|
-
return regle;
|
|
2440
|
-
}
|
|
2329
|
+
};
|
|
2330
|
+
const PRIORITY_KEYS = {
|
|
2331
|
+
ROOT: [
|
|
2332
|
+
"$invalid",
|
|
2333
|
+
"$dirty",
|
|
2334
|
+
"$error",
|
|
2335
|
+
"$pending",
|
|
2336
|
+
"$valid",
|
|
2337
|
+
"$ready"
|
|
2338
|
+
],
|
|
2339
|
+
FIELD: [
|
|
2340
|
+
"$value",
|
|
2341
|
+
"$invalid",
|
|
2342
|
+
"$dirty",
|
|
2343
|
+
"$error",
|
|
2344
|
+
"$pending",
|
|
2345
|
+
"$errors"
|
|
2346
|
+
]
|
|
2347
|
+
};
|
|
2348
|
+
const INSPECTOR_IDS = {
|
|
2349
|
+
INSPECTOR: "regle-inspector",
|
|
2350
|
+
TIMELINE: "regle-timeline"
|
|
2351
|
+
};
|
|
2441
2352
|
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
const name = options?.name || `Regle #${this.idCounter}`;
|
|
2452
|
-
this.instances.set(id, {
|
|
2353
|
+
function useRegleDevtoolsRegistry() {
|
|
2354
|
+
const instances = shallowRef(/* @__PURE__ */ new Map());
|
|
2355
|
+
const watchers = shallowRef(/* @__PURE__ */ new Map());
|
|
2356
|
+
let idCounter = 0;
|
|
2357
|
+
const notifyCallbacks = shallowRef(/* @__PURE__ */ new Set());
|
|
2358
|
+
function register(r$, options) {
|
|
2359
|
+
const id = `${options?.uid?.toString() ?? "regle"}#${++idCounter}`;
|
|
2360
|
+
const name = options?.name || `Regle #${idCounter}`;
|
|
2361
|
+
instances.value.set(id, {
|
|
2453
2362
|
id,
|
|
2454
2363
|
name,
|
|
2455
2364
|
r$,
|
|
2456
2365
|
componentName: options?.componentName ? `<${options.componentName}>` : void 0
|
|
2457
2366
|
});
|
|
2458
|
-
|
|
2367
|
+
notifyDevtools();
|
|
2459
2368
|
return id;
|
|
2460
2369
|
}
|
|
2461
|
-
unregister(id) {
|
|
2462
|
-
|
|
2463
|
-
const watcher =
|
|
2370
|
+
function unregister(id) {
|
|
2371
|
+
instances.value.delete(id);
|
|
2372
|
+
const watcher = watchers.value.get(id);
|
|
2464
2373
|
if (watcher) {
|
|
2465
2374
|
watcher();
|
|
2466
|
-
|
|
2375
|
+
watchers.value.delete(id);
|
|
2467
2376
|
}
|
|
2468
|
-
|
|
2377
|
+
notifyDevtools();
|
|
2469
2378
|
}
|
|
2470
|
-
getAll() {
|
|
2471
|
-
return Array.from(
|
|
2379
|
+
function getAll() {
|
|
2380
|
+
return Array.from(instances.value.values());
|
|
2472
2381
|
}
|
|
2473
|
-
get(id) {
|
|
2474
|
-
return
|
|
2382
|
+
function get(id) {
|
|
2383
|
+
return instances.value.get(id);
|
|
2475
2384
|
}
|
|
2476
|
-
clear() {
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2385
|
+
function clear() {
|
|
2386
|
+
watchers.value.forEach((stop) => stop());
|
|
2387
|
+
watchers.value.clear();
|
|
2388
|
+
instances.value.clear();
|
|
2389
|
+
notifyDevtools();
|
|
2481
2390
|
}
|
|
2482
|
-
onInstancesChange(callback) {
|
|
2483
|
-
|
|
2391
|
+
function onInstancesChange(callback) {
|
|
2392
|
+
notifyCallbacks.value.add(callback);
|
|
2484
2393
|
return () => {
|
|
2485
|
-
|
|
2394
|
+
notifyCallbacks.value.delete(callback);
|
|
2486
2395
|
};
|
|
2487
2396
|
}
|
|
2488
|
-
addWatcher(id, stopHandle) {
|
|
2489
|
-
|
|
2397
|
+
function addWatcher(id, stopHandle) {
|
|
2398
|
+
watchers.value.set(id, stopHandle);
|
|
2490
2399
|
}
|
|
2491
|
-
notifyDevtools() {
|
|
2492
|
-
|
|
2400
|
+
function notifyDevtools() {
|
|
2401
|
+
notifyCallbacks.value.forEach((callback) => callback());
|
|
2493
2402
|
}
|
|
2494
|
-
|
|
2495
|
-
|
|
2403
|
+
return {
|
|
2404
|
+
register,
|
|
2405
|
+
unregister,
|
|
2406
|
+
getAll,
|
|
2407
|
+
get,
|
|
2408
|
+
clear,
|
|
2409
|
+
onInstancesChange,
|
|
2410
|
+
addWatcher
|
|
2411
|
+
};
|
|
2412
|
+
}
|
|
2413
|
+
const regleDevtoolsRegistry = useRegleDevtoolsRegistry();
|
|
2496
2414
|
function registerRegleInstance(r$, options) {
|
|
2497
2415
|
if (typeof window === "undefined") return;
|
|
2498
2416
|
const instance = getCurrentInstance();
|
|
2499
2417
|
const componentName = instance?.type?.name || instance?.type?.__name;
|
|
2500
2418
|
const id = regleDevtoolsRegistry.register(r$, {
|
|
2501
2419
|
name: options?.name,
|
|
2502
|
-
componentName
|
|
2420
|
+
componentName,
|
|
2421
|
+
uid: instance?.uid
|
|
2503
2422
|
});
|
|
2504
2423
|
tryOnScopeDispose(() => {
|
|
2505
2424
|
regleDevtoolsRegistry.unregister(id);
|
|
@@ -2514,1069 +2433,1108 @@ function watchRegleInstance(id, r$, onChange) {
|
|
|
2514
2433
|
return stopHandle;
|
|
2515
2434
|
}
|
|
2516
2435
|
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
function createUseRegleComposable(customRules, options, shortcuts) {
|
|
2520
|
-
const globalOptions = {
|
|
2521
|
-
autoDirty: options?.autoDirty,
|
|
2522
|
-
lazy: options?.lazy,
|
|
2523
|
-
rewardEarly: options?.rewardEarly,
|
|
2524
|
-
silent: options?.silent,
|
|
2525
|
-
clearExternalErrorsOnChange: options?.clearExternalErrorsOnChange
|
|
2526
|
-
};
|
|
2527
|
-
function useRegle$1(state, rulesFactory, options$1) {
|
|
2528
|
-
return { r$: createRootRegleLogic({
|
|
2529
|
-
state: isRef(state) ? state : ref(state),
|
|
2530
|
-
rulesFactory,
|
|
2531
|
-
options: options$1,
|
|
2532
|
-
globalOptions,
|
|
2533
|
-
customRules,
|
|
2534
|
-
shortcuts
|
|
2535
|
-
}).regle };
|
|
2536
|
-
}
|
|
2537
|
-
return useRegle$1;
|
|
2436
|
+
function isMethod(value) {
|
|
2437
|
+
return typeof value === "function";
|
|
2538
2438
|
}
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
* import { useRegle } from '@regle/core';
|
|
2550
|
-
import { required } from '@regle/rules';
|
|
2551
|
-
|
|
2552
|
-
const { r$ } = useRegle({ email: '' }, {
|
|
2553
|
-
email: { required }
|
|
2554
|
-
})
|
|
2555
|
-
* ```
|
|
2556
|
-
* Docs: {@link https://reglejs.dev/core-concepts/}
|
|
2557
|
-
*/
|
|
2558
|
-
const useRegle = createUseRegleComposable();
|
|
2559
|
-
|
|
2560
|
-
//#endregion
|
|
2561
|
-
//#region src/core/useRegle/inferRules.ts
|
|
2562
|
-
function createInferRuleHelper() {
|
|
2563
|
-
function inferRules$1(state, rulesFactory) {
|
|
2564
|
-
return rulesFactory;
|
|
2565
|
-
}
|
|
2566
|
-
return inferRules$1;
|
|
2439
|
+
function getPriorityProperties(obj, keys) {
|
|
2440
|
+
return keys.filter((key) => key in obj && !isMethod(obj[key])).map((key) => {
|
|
2441
|
+
let editable = false;
|
|
2442
|
+
if (key === "$value") editable = true;
|
|
2443
|
+
return {
|
|
2444
|
+
key,
|
|
2445
|
+
value: obj[key],
|
|
2446
|
+
editable
|
|
2447
|
+
};
|
|
2448
|
+
});
|
|
2567
2449
|
}
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
*/
|
|
2575
|
-
const inferRules = createInferRuleHelper();
|
|
2576
|
-
|
|
2577
|
-
//#endregion
|
|
2578
|
-
//#region src/core/useRegle/useRules.ts
|
|
2579
|
-
function registerRegleWithDevtools(regle, options) {
|
|
2580
|
-
try {
|
|
2581
|
-
registerRegleInstance(regle, { name: options?.devtoolsName });
|
|
2582
|
-
} catch (e) {}
|
|
2450
|
+
function getRemainingProperties(obj, excludeKeys) {
|
|
2451
|
+
return Object.entries(obj).filter(([key]) => !excludeKeys.includes(key) && key.startsWith("$") && !isMethod(obj[key])).map(([key, value]) => ({
|
|
2452
|
+
key,
|
|
2453
|
+
value,
|
|
2454
|
+
editable: false
|
|
2455
|
+
}));
|
|
2583
2456
|
}
|
|
2584
|
-
function
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
else result[key] = null;
|
|
2592
|
-
}
|
|
2593
|
-
return result;
|
|
2457
|
+
function parseFieldNodeId(nodeId) {
|
|
2458
|
+
if (!nodeId.includes(":field:")) return null;
|
|
2459
|
+
const [instanceId, , fieldName] = nodeId.split(":");
|
|
2460
|
+
return {
|
|
2461
|
+
instanceId,
|
|
2462
|
+
fieldName
|
|
2463
|
+
};
|
|
2594
2464
|
}
|
|
2595
|
-
function
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2465
|
+
function createFieldNodeId(instanceId, fieldName) {
|
|
2466
|
+
return `${instanceId}:field:${fieldName}`;
|
|
2467
|
+
}
|
|
2468
|
+
function parseRuleNodeId(nodeId) {
|
|
2469
|
+
if (!nodeId.includes(":rule:")) return null;
|
|
2470
|
+
const parts = nodeId.split(":rule:");
|
|
2471
|
+
if (parts.length !== 2) return null;
|
|
2472
|
+
const fieldPart = parts[0];
|
|
2473
|
+
const ruleName = parts[1];
|
|
2474
|
+
const fieldInfo = parseFieldNodeId(fieldPart);
|
|
2475
|
+
if (!fieldInfo) return null;
|
|
2476
|
+
return {
|
|
2477
|
+
...fieldInfo,
|
|
2478
|
+
ruleName
|
|
2602
2479
|
};
|
|
2603
|
-
function useRules$1(rulesFactory, options$1) {
|
|
2604
|
-
const definedRules = isRef(rulesFactory) ? rulesFactory : typeof rulesFactory === "function" ? void 0 : computed(() => rulesFactory);
|
|
2605
|
-
const regle = createRootRegleLogic({
|
|
2606
|
-
state: ref(createEmptyRuleState(definedRules?.value)),
|
|
2607
|
-
rulesFactory: definedRules,
|
|
2608
|
-
options: options$1,
|
|
2609
|
-
globalOptions,
|
|
2610
|
-
customRules,
|
|
2611
|
-
shortcuts
|
|
2612
|
-
});
|
|
2613
|
-
registerRegleWithDevtools(regle.regle, options$1);
|
|
2614
|
-
return regle.regle;
|
|
2615
|
-
}
|
|
2616
|
-
return useRules$1;
|
|
2617
2480
|
}
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
* It accepts the following inputs:
|
|
2622
|
-
*
|
|
2623
|
-
* @param rules - Your rules object
|
|
2624
|
-
* @param modifiers - Customize regle behaviour
|
|
2625
|
-
*
|
|
2626
|
-
* ```ts
|
|
2627
|
-
* import { useRules } from '@regle/core';
|
|
2628
|
-
import { required } from '@regle/rules';
|
|
2481
|
+
function createRuleNodeId(instanceId, fieldName, ruleName) {
|
|
2482
|
+
return `${createFieldNodeId(instanceId, fieldName)}:rule:${ruleName}`;
|
|
2483
|
+
}
|
|
2629
2484
|
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
})
|
|
2633
|
-
* ```
|
|
2485
|
+
/**
|
|
2486
|
+
* Build state for a field node
|
|
2634
2487
|
*/
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2488
|
+
function buildFieldState(fieldStatus) {
|
|
2489
|
+
const state = {};
|
|
2490
|
+
const priorityProperties = getPriorityProperties(fieldStatus, PRIORITY_KEYS.FIELD);
|
|
2491
|
+
if (priorityProperties.length > 0) state["State"] = priorityProperties;
|
|
2492
|
+
const remainingProperties = getRemainingProperties(fieldStatus, [
|
|
2493
|
+
...PRIORITY_KEYS.FIELD,
|
|
2494
|
+
"$rules",
|
|
2495
|
+
"$fields"
|
|
2496
|
+
]);
|
|
2497
|
+
if (remainingProperties.length > 0) state["Other Properties"] = remainingProperties;
|
|
2498
|
+
return state;
|
|
2499
|
+
}
|
|
2639
2500
|
/**
|
|
2640
|
-
*
|
|
2641
|
-
* - Customize built-in rules messages
|
|
2642
|
-
* - Add your custom rules
|
|
2643
|
-
* - Define global modifiers
|
|
2644
|
-
* - Define shortcuts
|
|
2645
|
-
*
|
|
2646
|
-
* It will return:
|
|
2647
|
-
*
|
|
2648
|
-
* - a `useRegle` composable that can typecheck your custom rules
|
|
2649
|
-
* - an `inferRules` helper that can typecheck your custom rules
|
|
2501
|
+
* Build state for a rule node
|
|
2650
2502
|
*/
|
|
2651
|
-
function
|
|
2652
|
-
const
|
|
2653
|
-
const
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
|
|
2662
|
-
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
|
|
2503
|
+
function buildRuleState(ruleStatus) {
|
|
2504
|
+
const state = {};
|
|
2505
|
+
const ruleKeys = [
|
|
2506
|
+
"$type",
|
|
2507
|
+
"$valid",
|
|
2508
|
+
"$active",
|
|
2509
|
+
"$pending",
|
|
2510
|
+
"$message",
|
|
2511
|
+
"$tooltip"
|
|
2512
|
+
];
|
|
2513
|
+
const priorityProperties = getPriorityProperties(ruleStatus, ruleKeys);
|
|
2514
|
+
if (priorityProperties.length > 0) state["Rule State"] = priorityProperties;
|
|
2515
|
+
if (ruleStatus.$params && Array.isArray(ruleStatus.$params) && ruleStatus.$params.length > 0) state["Parameters"] = [{
|
|
2516
|
+
key: "$params",
|
|
2517
|
+
value: ruleStatus.$params,
|
|
2518
|
+
editable: false
|
|
2519
|
+
}];
|
|
2520
|
+
if (ruleStatus.$metadata !== void 0 && ruleStatus.$metadata !== true && ruleStatus.$metadata !== false) state["Metadata"] = [{
|
|
2521
|
+
key: "$metadata",
|
|
2522
|
+
value: ruleStatus.$metadata,
|
|
2523
|
+
objectType: "reactive",
|
|
2524
|
+
editable: false
|
|
2525
|
+
}];
|
|
2526
|
+
const remainingProperties = getRemainingProperties(ruleStatus, [
|
|
2527
|
+
...ruleKeys,
|
|
2528
|
+
"$params",
|
|
2529
|
+
"$metadata",
|
|
2530
|
+
"$haveAsync",
|
|
2531
|
+
"$validating",
|
|
2532
|
+
"$fieldDirty",
|
|
2533
|
+
"$fieldInvalid",
|
|
2534
|
+
"$fieldPending",
|
|
2535
|
+
"$fieldCorrect",
|
|
2536
|
+
"$fieldError",
|
|
2537
|
+
"$maybePending",
|
|
2538
|
+
"$externalErrors"
|
|
2539
|
+
]);
|
|
2540
|
+
if (remainingProperties.length > 0) state["Other Properties"] = remainingProperties;
|
|
2541
|
+
return state;
|
|
2669
2542
|
}
|
|
2670
|
-
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
const
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
|
|
2695
|
-
|
|
2543
|
+
function buildRootState(r$) {
|
|
2544
|
+
const state = {};
|
|
2545
|
+
const priorityProperties = getPriorityProperties(r$, PRIORITY_KEYS.ROOT);
|
|
2546
|
+
if (priorityProperties.length > 0) state["State"] = priorityProperties;
|
|
2547
|
+
const remainingProperties = getRemainingProperties(r$, [...PRIORITY_KEYS.ROOT, "$fields"]);
|
|
2548
|
+
if (remainingProperties.length > 0) state["Other Properties"] = remainingProperties;
|
|
2549
|
+
if (r$["~modifiers"]) state["Modifiers"] = Object.entries(r$["~modifiers"]).map(([key, value]) => ({
|
|
2550
|
+
key,
|
|
2551
|
+
value,
|
|
2552
|
+
editable: false
|
|
2553
|
+
}));
|
|
2554
|
+
return state;
|
|
2555
|
+
}
|
|
2556
|
+
function resolveFieldByPath(fields, path) {
|
|
2557
|
+
if (!fields || !path) return null;
|
|
2558
|
+
const segments = path.match(/[^.\[\]]+/g);
|
|
2559
|
+
if (!segments) return null;
|
|
2560
|
+
let current = fields;
|
|
2561
|
+
for (const segment of segments) {
|
|
2562
|
+
if (!current) return null;
|
|
2563
|
+
const index = parseInt(segment);
|
|
2564
|
+
if (!isNaN(index)) if (isCollectionRulesStatus(current) && Array.isArray(current.$each)) current = current.$each[index];
|
|
2565
|
+
else return null;
|
|
2566
|
+
else if (isNestedRulesStatus(current) && current.$fields && current.$fields[segment]) current = current.$fields[segment];
|
|
2567
|
+
else if (current[segment]) current = current[segment];
|
|
2568
|
+
else return null;
|
|
2569
|
+
}
|
|
2570
|
+
return current;
|
|
2571
|
+
}
|
|
2572
|
+
function buildInspectorState(nodeId, getInstance) {
|
|
2573
|
+
const ruleInfo = parseRuleNodeId(nodeId);
|
|
2574
|
+
if (ruleInfo) {
|
|
2575
|
+
const { instanceId, fieldName, ruleName } = ruleInfo;
|
|
2576
|
+
const instance$1 = getInstance(instanceId);
|
|
2577
|
+
if (!instance$1 || !instance$1.r$.$fields) return null;
|
|
2578
|
+
const fieldStatus = resolveFieldByPath(instance$1.r$.$fields, fieldName);
|
|
2579
|
+
if (!fieldStatus || !("$rules" in fieldStatus)) return null;
|
|
2580
|
+
const ruleStatus = fieldStatus.$rules[ruleName];
|
|
2581
|
+
if (!ruleStatus) return null;
|
|
2582
|
+
return buildRuleState(ruleStatus);
|
|
2583
|
+
}
|
|
2584
|
+
const fieldInfo = parseFieldNodeId(nodeId);
|
|
2585
|
+
if (fieldInfo) {
|
|
2586
|
+
const { instanceId, fieldName } = fieldInfo;
|
|
2587
|
+
const instance$1 = getInstance(instanceId);
|
|
2588
|
+
if (!instance$1 || !instance$1.r$.$fields) return null;
|
|
2589
|
+
const fieldStatus = resolveFieldByPath(instance$1.r$.$fields, fieldName);
|
|
2590
|
+
if (!fieldStatus) return null;
|
|
2591
|
+
return buildFieldState(fieldStatus);
|
|
2592
|
+
}
|
|
2593
|
+
const instance = getInstance(nodeId);
|
|
2594
|
+
if (!instance) return null;
|
|
2595
|
+
return buildRootState(instance.r$);
|
|
2696
2596
|
}
|
|
2697
2597
|
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
get
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
set: (value) => {
|
|
2708
|
-
if (!scoped) {
|
|
2709
|
-
if (typeof value === "object") Object.entries(value).forEach(([key, newValue]) => regles[key].$value = newValue);
|
|
2710
|
-
}
|
|
2598
|
+
function handleValidateAction(nodeId, api) {
|
|
2599
|
+
if (nodeId.includes(":rule:")) return;
|
|
2600
|
+
const fieldInfo = parseFieldNodeId(nodeId);
|
|
2601
|
+
if (fieldInfo) {
|
|
2602
|
+
const { instanceId, fieldName } = fieldInfo;
|
|
2603
|
+
const instance = regleDevtoolsRegistry.get(instanceId);
|
|
2604
|
+
if (instance && instance.r$.$fields) {
|
|
2605
|
+
const fieldStatus = resolveFieldByPath(instance.r$.$fields, fieldName);
|
|
2606
|
+
if (fieldStatus && typeof fieldStatus.$validate === "function") fieldStatus.$validate();
|
|
2711
2607
|
}
|
|
2712
|
-
}
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2608
|
+
} else {
|
|
2609
|
+
const instance = regleDevtoolsRegistry.get(nodeId);
|
|
2610
|
+
if (instance && typeof instance.r$.$validate === "function") instance.r$.$validate();
|
|
2611
|
+
}
|
|
2612
|
+
emitInspectorState(api);
|
|
2613
|
+
}
|
|
2614
|
+
function handleResetAction(nodeId, api, resetState = false) {
|
|
2615
|
+
const fieldInfo = parseFieldNodeId(nodeId);
|
|
2616
|
+
if (fieldInfo) {
|
|
2617
|
+
const { instanceId, fieldName } = fieldInfo;
|
|
2618
|
+
const instance = regleDevtoolsRegistry.get(instanceId);
|
|
2619
|
+
if (instance && instance.r$.$fields) {
|
|
2620
|
+
const fieldStatus = resolveFieldByPath(instance.r$.$fields, fieldName);
|
|
2621
|
+
if (fieldStatus && typeof fieldStatus.$reset === "function") fieldStatus.$reset({ toInitialState: resetState });
|
|
2717
2622
|
}
|
|
2623
|
+
} else {
|
|
2624
|
+
const instance = regleDevtoolsRegistry.get(nodeId);
|
|
2625
|
+
if (instance && typeof instance.r$.$reset === "function") instance.r$.$reset({ toInitialState: resetState });
|
|
2626
|
+
}
|
|
2627
|
+
emitInspectorState(api);
|
|
2628
|
+
}
|
|
2629
|
+
function handleEditInspectorState(payload, api) {
|
|
2630
|
+
const { nodeId, path, state } = payload;
|
|
2631
|
+
if (!path.includes("$value")) return;
|
|
2632
|
+
if (!parseFieldNodeId(nodeId)) return;
|
|
2633
|
+
const [instanceId, _, fieldPath] = nodeId.split(":");
|
|
2634
|
+
const instance = regleDevtoolsRegistry.get(instanceId);
|
|
2635
|
+
if (instance && instance.r$.$fields) {
|
|
2636
|
+
const fieldStatus = resolveFieldByPath(instance.r$.$fields, fieldPath);
|
|
2637
|
+
if (fieldStatus && "$value" in fieldStatus) fieldStatus.$value = state.value;
|
|
2638
|
+
}
|
|
2639
|
+
emitInspectorState(api);
|
|
2640
|
+
}
|
|
2641
|
+
function emitInspectorState(api) {
|
|
2642
|
+
setTimeout(() => {
|
|
2643
|
+
api.sendInspectorState(INSPECTOR_IDS.INSPECTOR);
|
|
2644
|
+
api.sendInspectorTree(INSPECTOR_IDS.INSPECTOR);
|
|
2645
|
+
}, 100);
|
|
2646
|
+
}
|
|
2647
|
+
|
|
2648
|
+
function buildNodeTags(fieldOrR$, componentName) {
|
|
2649
|
+
const tags = [];
|
|
2650
|
+
if (fieldOrR$.$error) tags.push({
|
|
2651
|
+
label: "error",
|
|
2652
|
+
textColor: COLORS.ERROR.text,
|
|
2653
|
+
backgroundColor: COLORS.ERROR.bg
|
|
2718
2654
|
});
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
});
|
|
2655
|
+
else if (fieldOrR$.$correct) tags.push({
|
|
2656
|
+
label: "correct",
|
|
2657
|
+
textColor: COLORS.VALID.text,
|
|
2658
|
+
backgroundColor: COLORS.VALID.bg
|
|
2724
2659
|
});
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2660
|
+
if (fieldOrR$.$pending) tags.push({
|
|
2661
|
+
label: "pending",
|
|
2662
|
+
textColor: COLORS.PENDING.text,
|
|
2663
|
+
backgroundColor: COLORS.PENDING.bg
|
|
2729
2664
|
});
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
|
|
2665
|
+
if (fieldOrR$.$dirty) tags.push({
|
|
2666
|
+
label: "dirty",
|
|
2667
|
+
textColor: COLORS.DIRTY.text,
|
|
2668
|
+
backgroundColor: COLORS.DIRTY.bg
|
|
2734
2669
|
});
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
});
|
|
2670
|
+
else if ("$rules" in fieldOrR$) tags.push({
|
|
2671
|
+
label: "pristine",
|
|
2672
|
+
textColor: COLORS.PRISTINE.text,
|
|
2673
|
+
backgroundColor: COLORS.PRISTINE.bg
|
|
2740
2674
|
});
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2675
|
+
if (componentName) tags.push({
|
|
2676
|
+
label: componentName,
|
|
2677
|
+
textColor: COLORS.COMPONENT.text,
|
|
2678
|
+
backgroundColor: COLORS.COMPONENT.bg
|
|
2745
2679
|
});
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
|
|
2680
|
+
return tags;
|
|
2681
|
+
}
|
|
2682
|
+
function buildRuleTags(rule) {
|
|
2683
|
+
const tags = [];
|
|
2684
|
+
if (!rule.$active) tags.push({
|
|
2685
|
+
label: "inactive",
|
|
2686
|
+
textColor: COLORS.INACTIVE.text,
|
|
2687
|
+
backgroundColor: COLORS.INACTIVE.bg
|
|
2751
2688
|
});
|
|
2752
|
-
|
|
2753
|
-
|
|
2754
|
-
|
|
2755
|
-
|
|
2689
|
+
else if (!rule.$valid) tags.push({
|
|
2690
|
+
label: "invalid",
|
|
2691
|
+
textColor: COLORS.INVALID.text,
|
|
2692
|
+
backgroundColor: COLORS.INVALID.bg
|
|
2756
2693
|
});
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
else return Object.fromEntries(Object.entries(regles).map(([key, regle]) => {
|
|
2762
|
-
return [key, regle.$issues];
|
|
2763
|
-
}));
|
|
2764
|
-
});
|
|
2765
|
-
const $silentIssues = computed(() => {
|
|
2766
|
-
if (scoped) return Object.entries(regles).map(([_, regle]) => {
|
|
2767
|
-
return regle.$silentIssues;
|
|
2768
|
-
});
|
|
2769
|
-
else return Object.fromEntries(Object.entries(regles).map(([key, regle]) => {
|
|
2770
|
-
return [key, regle.$silentIssues];
|
|
2771
|
-
}));
|
|
2772
|
-
});
|
|
2773
|
-
const $errors = computed(() => {
|
|
2774
|
-
if (scoped) return Object.entries(regles).map(([_, regle]) => {
|
|
2775
|
-
return regle.$errors;
|
|
2776
|
-
});
|
|
2777
|
-
else return Object.fromEntries(Object.entries(regles).map(([key, regle]) => {
|
|
2778
|
-
return [key, regle.$errors];
|
|
2779
|
-
}));
|
|
2780
|
-
});
|
|
2781
|
-
const $silentErrors = computed(() => {
|
|
2782
|
-
if (scoped) return Object.entries(regles).map(([_, regle]) => {
|
|
2783
|
-
return regle.$silentErrors;
|
|
2784
|
-
});
|
|
2785
|
-
else return Object.fromEntries(Object.entries(regles).map(([key, regle]) => {
|
|
2786
|
-
return [key, regle.$silentErrors];
|
|
2787
|
-
}));
|
|
2788
|
-
});
|
|
2789
|
-
const $edited = computed(() => {
|
|
2790
|
-
const entries = Object.entries(regles);
|
|
2791
|
-
return !!entries.length && entries.every(([_, regle]) => {
|
|
2792
|
-
return regle?.$edited;
|
|
2793
|
-
});
|
|
2794
|
-
});
|
|
2795
|
-
const $anyEdited = computed(() => {
|
|
2796
|
-
return Object.entries(regles).some(([_, regle]) => {
|
|
2797
|
-
return regle?.$anyEdited;
|
|
2798
|
-
});
|
|
2694
|
+
else if (rule.$valid) tags.push({
|
|
2695
|
+
label: "valid",
|
|
2696
|
+
textColor: COLORS.VALID.text,
|
|
2697
|
+
backgroundColor: COLORS.VALID.bg
|
|
2799
2698
|
});
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2699
|
+
if (rule.$pending) tags.push({
|
|
2700
|
+
label: "pending",
|
|
2701
|
+
textColor: COLORS.PENDING.text,
|
|
2702
|
+
backgroundColor: COLORS.PENDING.bg
|
|
2803
2703
|
});
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
|
|
2818
|
-
Object.values(regles).forEach((regle) => {
|
|
2819
|
-
regle.$clearExternalErrors();
|
|
2820
|
-
});
|
|
2821
|
-
}
|
|
2822
|
-
async function $validate(forceValues) {
|
|
2823
|
-
try {
|
|
2824
|
-
if (forceValues) $value.value = forceValues;
|
|
2825
|
-
const data = $value.value;
|
|
2826
|
-
return {
|
|
2827
|
-
valid: (await Promise.allSettled(Object.values(regles).map((regle) => {
|
|
2828
|
-
return regle.$validate();
|
|
2829
|
-
}))).every((value) => {
|
|
2830
|
-
if (value.status === "fulfilled") return value.value.valid === true;
|
|
2831
|
-
else return false;
|
|
2832
|
-
}),
|
|
2833
|
-
data,
|
|
2834
|
-
errors: $errors.value,
|
|
2835
|
-
issues: $issues.value
|
|
2836
|
-
};
|
|
2837
|
-
} catch {
|
|
2838
|
-
return {
|
|
2839
|
-
valid: false,
|
|
2840
|
-
data: $value.value,
|
|
2841
|
-
errors: $errors.value,
|
|
2842
|
-
issues: $issues.value
|
|
2843
|
-
};
|
|
2704
|
+
return tags;
|
|
2705
|
+
}
|
|
2706
|
+
function buildRuleNodes(fieldStatus, instanceId, fieldPath) {
|
|
2707
|
+
const children = [];
|
|
2708
|
+
if (!fieldStatus.$rules || typeof fieldStatus.$rules !== "object") return children;
|
|
2709
|
+
Object.entries(fieldStatus.$rules).forEach(([ruleName, ruleStatus]) => {
|
|
2710
|
+
if (ruleStatus && typeof ruleStatus === "object") {
|
|
2711
|
+
const ruleTags = buildRuleTags(ruleStatus);
|
|
2712
|
+
children.push({
|
|
2713
|
+
id: createRuleNodeId(instanceId, fieldPath, ruleName),
|
|
2714
|
+
label: `⚙️ ${ruleName}`,
|
|
2715
|
+
tags: ruleTags,
|
|
2716
|
+
children: []
|
|
2717
|
+
});
|
|
2844
2718
|
}
|
|
2845
|
-
}
|
|
2846
|
-
return reactive({
|
|
2847
|
-
...!scoped && { $silentValue },
|
|
2848
|
-
$errors,
|
|
2849
|
-
$issues,
|
|
2850
|
-
$silentIssues,
|
|
2851
|
-
$silentErrors,
|
|
2852
|
-
$instances,
|
|
2853
|
-
$value,
|
|
2854
|
-
$dirty,
|
|
2855
|
-
$anyDirty,
|
|
2856
|
-
$invalid,
|
|
2857
|
-
$correct,
|
|
2858
|
-
$error,
|
|
2859
|
-
$pending,
|
|
2860
|
-
$ready,
|
|
2861
|
-
$edited,
|
|
2862
|
-
$anyEdited,
|
|
2863
|
-
$reset,
|
|
2864
|
-
$touch,
|
|
2865
|
-
$validate,
|
|
2866
|
-
$extractDirtyFields,
|
|
2867
|
-
$clearExternalErrors
|
|
2868
2719
|
});
|
|
2720
|
+
return children;
|
|
2869
2721
|
}
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
function collectRegles(r$Instances) {
|
|
2887
|
-
if (computedNamespace.value) return mergeRegles(r$Instances[computedNamespace.value] ?? {}, !options.asRecord);
|
|
2888
|
-
else return mergeRegles(r$Instances["~~global"] ?? {}, !options.asRecord);
|
|
2722
|
+
function buildCollectionItemNodes(fieldStatus, instanceId, fieldPath) {
|
|
2723
|
+
const children = [];
|
|
2724
|
+
if (!fieldStatus.$each || !Array.isArray(fieldStatus.$each)) return children;
|
|
2725
|
+
fieldStatus.$each.forEach((item, index) => {
|
|
2726
|
+
if (item && typeof item === "object") {
|
|
2727
|
+
const itemTags = buildNodeTags(item);
|
|
2728
|
+
const itemPath = `${fieldPath}[${index}]`;
|
|
2729
|
+
let itemChildren = [];
|
|
2730
|
+
if (isNestedRulesStatus(item)) itemChildren = buildNestedFieldNodes(item.$fields, instanceId, itemPath);
|
|
2731
|
+
else if (isFieldStatus(item)) itemChildren = buildRuleNodes(item, instanceId, itemPath);
|
|
2732
|
+
children.push({
|
|
2733
|
+
id: createFieldNodeId(instanceId, itemPath),
|
|
2734
|
+
label: `[${index}]`,
|
|
2735
|
+
tags: itemTags,
|
|
2736
|
+
children: itemChildren
|
|
2737
|
+
});
|
|
2889
2738
|
}
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
return { useCollectScope: useCollectScope$1 };
|
|
2739
|
+
});
|
|
2740
|
+
return children;
|
|
2893
2741
|
}
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
watch(computedNamespace, (newName, oldName) => {
|
|
2911
|
-
dispose(oldName);
|
|
2912
|
-
register();
|
|
2913
|
-
});
|
|
2914
|
-
if (getCurrentInstance()) onMounted(() => {
|
|
2915
|
-
const currentInstance = getCurrentInstance();
|
|
2916
|
-
if (typeof window !== "undefined" && currentInstance?.proxy?.$el?.parentElement) {
|
|
2917
|
-
if (document.documentElement && !document.documentElement.contains(currentInstance?.proxy?.$el?.parentElement)) dispose();
|
|
2918
|
-
}
|
|
2919
|
-
});
|
|
2920
|
-
function dispose(oldName) {
|
|
2921
|
-
const nameToClean = oldName ?? computedNamespace.value;
|
|
2922
|
-
if (nameToClean) {
|
|
2923
|
-
if (instances.value[nameToClean]) delete instances.value[nameToClean][instanceName.value];
|
|
2924
|
-
} else if (instances.value["~~global"][instanceName.value]) delete instances.value["~~global"][instanceName.value];
|
|
2742
|
+
function buildNestedFieldNodes(fields, instanceId, parentPath) {
|
|
2743
|
+
const children = [];
|
|
2744
|
+
Object.entries(fields).forEach(([fieldName, fieldStatus]) => {
|
|
2745
|
+
if (fieldStatus && typeof fieldStatus === "object") {
|
|
2746
|
+
const fieldPath = parentPath ? `${parentPath}.${fieldName}` : fieldName;
|
|
2747
|
+
const fieldTags = buildNodeTags(fieldStatus);
|
|
2748
|
+
let fieldChildren = [];
|
|
2749
|
+
if (isCollectionRulesStatus(fieldStatus)) fieldChildren = buildCollectionItemNodes(fieldStatus, instanceId, fieldPath);
|
|
2750
|
+
else if (isNestedRulesStatus(fieldStatus)) fieldChildren = buildNestedFieldNodes(fieldStatus.$fields, instanceId, fieldPath);
|
|
2751
|
+
else if (isFieldStatus(fieldStatus)) fieldChildren = buildRuleNodes(fieldStatus, instanceId, fieldPath);
|
|
2752
|
+
children.push({
|
|
2753
|
+
id: createFieldNodeId(instanceId, fieldPath),
|
|
2754
|
+
label: `${fieldName}`,
|
|
2755
|
+
tags: fieldTags,
|
|
2756
|
+
children: fieldChildren
|
|
2757
|
+
});
|
|
2925
2758
|
}
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
|
|
2759
|
+
});
|
|
2760
|
+
return children;
|
|
2761
|
+
}
|
|
2762
|
+
function buildRootChildrenNodes(r$, instanceId) {
|
|
2763
|
+
const children = [];
|
|
2764
|
+
if (isFieldStatus(r$)) return buildRuleNodes(r$, instanceId, "root");
|
|
2765
|
+
if (!r$.$fields || typeof r$.$fields !== "object") return children;
|
|
2766
|
+
Object.entries(r$.$fields).forEach(([fieldName, fieldStatus]) => {
|
|
2767
|
+
if (fieldStatus && typeof fieldStatus === "object") {
|
|
2768
|
+
const fieldTags = buildNodeTags(fieldStatus);
|
|
2769
|
+
let fieldChildren = [];
|
|
2770
|
+
if (isCollectionRulesStatus(fieldStatus)) fieldChildren = buildCollectionItemNodes(fieldStatus, instanceId, fieldName);
|
|
2771
|
+
else if (isNestedRulesStatus(fieldStatus)) fieldChildren = buildNestedFieldNodes(fieldStatus.$fields, instanceId, fieldName);
|
|
2772
|
+
else if (isFieldStatus(fieldStatus)) fieldChildren = buildRuleNodes(fieldStatus, instanceId, fieldName);
|
|
2773
|
+
children.push({
|
|
2774
|
+
id: createFieldNodeId(instanceId, fieldName),
|
|
2775
|
+
label: fieldName,
|
|
2776
|
+
tags: fieldTags,
|
|
2777
|
+
children: fieldChildren
|
|
2778
|
+
});
|
|
2934
2779
|
}
|
|
2780
|
+
});
|
|
2781
|
+
return children;
|
|
2782
|
+
}
|
|
2783
|
+
function buildInspectorTree(instances, filter) {
|
|
2784
|
+
const nodes = instances.map((instance) => {
|
|
2785
|
+
const { r$, id, name, componentName } = instance;
|
|
2935
2786
|
return {
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2787
|
+
id,
|
|
2788
|
+
label: name,
|
|
2789
|
+
tags: buildNodeTags(r$, componentName),
|
|
2790
|
+
children: buildRootChildrenNodes(r$, id)
|
|
2939
2791
|
};
|
|
2940
2792
|
});
|
|
2941
|
-
|
|
2793
|
+
if (!filter || filter.trim() === "") return nodes;
|
|
2794
|
+
return filterInspectorTree(nodes, filter);
|
|
2942
2795
|
}
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
|
|
2946
|
-
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
|
|
2952
|
-
|
|
2953
|
-
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
const { useScopedRegle: useScopedRegle$1 } = createUseScopedRegleComposable(instances, options?.customUseRegle);
|
|
2957
|
-
const { useCollectScope: useCollectScope$1 } = createUseCollectScope(instances, { asRecord: options?.asRecord });
|
|
2958
|
-
return {
|
|
2959
|
-
useScopedRegle: useScopedRegle$1,
|
|
2960
|
-
useCollectScope: useCollectScope$1
|
|
2961
|
-
};
|
|
2796
|
+
function filterInspectorTree(nodes, filter) {
|
|
2797
|
+
const lowerFilter = filter.toLowerCase();
|
|
2798
|
+
const filtered = [];
|
|
2799
|
+
for (const node of nodes) {
|
|
2800
|
+
const labelMatches = node.label.toLowerCase().includes(lowerFilter);
|
|
2801
|
+
const tagMatches = node.tags?.some((tag) => tag.label.toLowerCase().includes(lowerFilter)) ?? false;
|
|
2802
|
+
const filteredChildren = node.children ? filterInspectorTree(node.children, filter) : [];
|
|
2803
|
+
if (labelMatches || tagMatches || filteredChildren.length > 0) filtered.push({
|
|
2804
|
+
...node,
|
|
2805
|
+
children: filteredChildren.length > 0 ? filteredChildren : node.children
|
|
2806
|
+
});
|
|
2807
|
+
}
|
|
2808
|
+
return filtered;
|
|
2962
2809
|
}
|
|
2963
|
-
const { useCollectScope, useScopedRegle } = createScopedUseRegle();
|
|
2964
2810
|
|
|
2965
|
-
|
|
2966
|
-
|
|
2967
|
-
|
|
2968
|
-
|
|
2969
|
-
|
|
2970
|
-
|
|
2971
|
-
|
|
2972
|
-
|
|
2973
|
-
|
|
2974
|
-
|
|
2975
|
-
|
|
2976
|
-
|
|
2977
|
-
|
|
2978
|
-
|
|
2979
|
-
|
|
2980
|
-
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
|
|
2987
|
-
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
|
|
2811
|
+
function createDevtools(app) {
|
|
2812
|
+
setupDevtoolsPlugin({
|
|
2813
|
+
id: "regle-devtools",
|
|
2814
|
+
label: "Regle",
|
|
2815
|
+
logo: "https://reglejs.dev/logo_main.png",
|
|
2816
|
+
packageName: "@regle/core",
|
|
2817
|
+
homepage: "https://reglejs.dev",
|
|
2818
|
+
componentStateTypes: [],
|
|
2819
|
+
app
|
|
2820
|
+
}, (api) => {
|
|
2821
|
+
api.addInspector({
|
|
2822
|
+
id: INSPECTOR_IDS.INSPECTOR,
|
|
2823
|
+
label: "Regle",
|
|
2824
|
+
noSelectionText: "No instance selected",
|
|
2825
|
+
icon: "rule",
|
|
2826
|
+
treeFilterPlaceholder: "Filter",
|
|
2827
|
+
stateFilterPlaceholder: "Filter validation status",
|
|
2828
|
+
nodeActions: [
|
|
2829
|
+
{
|
|
2830
|
+
icon: "check_circle",
|
|
2831
|
+
tooltip: "Validate (with `$validate`)",
|
|
2832
|
+
action: (nodeId) => {
|
|
2833
|
+
handleValidateAction(nodeId, api);
|
|
2834
|
+
}
|
|
2835
|
+
},
|
|
2836
|
+
{
|
|
2837
|
+
icon: "refresh",
|
|
2838
|
+
tooltip: "Reset validation state (with `$reset`)",
|
|
2839
|
+
action: (nodeId) => {
|
|
2840
|
+
handleResetAction(nodeId, api);
|
|
2841
|
+
}
|
|
2842
|
+
},
|
|
2843
|
+
{
|
|
2844
|
+
icon: "restore",
|
|
2845
|
+
tooltip: "Restore to initial state (with `$reset`)",
|
|
2846
|
+
action: (nodeId) => {
|
|
2847
|
+
handleResetAction(nodeId, api, true);
|
|
2848
|
+
}
|
|
2849
|
+
}
|
|
2850
|
+
]
|
|
2851
|
+
});
|
|
2852
|
+
setupInstanceWatchers(api);
|
|
2853
|
+
let componentInstances = [];
|
|
2854
|
+
let selectedNodeId = null;
|
|
2855
|
+
api.on.getInspectorTree(async (payload) => {
|
|
2856
|
+
api.unhighlightElement();
|
|
2857
|
+
if (payload.inspectorId === INSPECTOR_IDS.INSPECTOR) {
|
|
2858
|
+
const nodes = buildInspectorTree(regleDevtoolsRegistry.getAll(), payload.filter);
|
|
2859
|
+
if (nodes.length > 0) payload.rootNodes = nodes;
|
|
2860
|
+
else payload.rootNodes = [{
|
|
2861
|
+
id: "empty-regles",
|
|
2862
|
+
label: "No Regles instances found",
|
|
2863
|
+
children: []
|
|
2864
|
+
}];
|
|
2865
|
+
componentInstances = await api.getComponentInstances(app);
|
|
2994
2866
|
}
|
|
2995
2867
|
});
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
|
|
2868
|
+
api.on.getInspectorState((payload) => {
|
|
2869
|
+
api.unhighlightElement();
|
|
2870
|
+
if (payload.inspectorId === INSPECTOR_IDS.INSPECTOR) {
|
|
2871
|
+
const state = buildInspectorState(payload.nodeId, (id) => regleDevtoolsRegistry.get(id));
|
|
2872
|
+
const instance = componentInstances.find((instance$1) => {
|
|
2873
|
+
const [componentName] = payload.nodeId.split("#");
|
|
2874
|
+
return instance$1.uid.toString() === componentName;
|
|
2875
|
+
});
|
|
2876
|
+
if (instance?.uid && selectedNodeId !== payload.nodeId) {
|
|
2877
|
+
selectedNodeId = payload.nodeId;
|
|
2878
|
+
if (!parseFieldNodeId(payload.nodeId)) api.highlightElement(instance);
|
|
2879
|
+
}
|
|
2880
|
+
if (state) payload.state = state;
|
|
2881
|
+
else payload.state = {};
|
|
2882
|
+
}
|
|
2883
|
+
});
|
|
2884
|
+
api.on.editInspectorState((payload) => {
|
|
2885
|
+
if (payload.inspectorId === INSPECTOR_IDS.INSPECTOR) handleEditInspectorState(payload, api);
|
|
2886
|
+
});
|
|
3002
2887
|
});
|
|
3003
2888
|
}
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
|
|
3016
|
-
|
|
3017
|
-
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
flush: "pre"
|
|
2889
|
+
function setupInstanceWatchers(api) {
|
|
2890
|
+
const watchedInstances = /* @__PURE__ */ new Set();
|
|
2891
|
+
const setupWatchers = () => {
|
|
2892
|
+
regleDevtoolsRegistry.getAll().forEach((instance) => {
|
|
2893
|
+
const { r$, id } = instance;
|
|
2894
|
+
if (watchedInstances.has(id)) return;
|
|
2895
|
+
const stopHandle = watchRegleInstance(id, r$, () => {
|
|
2896
|
+
api.sendInspectorState(INSPECTOR_IDS.INSPECTOR);
|
|
2897
|
+
api.sendInspectorTree(INSPECTOR_IDS.INSPECTOR);
|
|
2898
|
+
});
|
|
2899
|
+
regleDevtoolsRegistry.addWatcher(id, stopHandle);
|
|
2900
|
+
watchedInstances.add(id);
|
|
2901
|
+
});
|
|
2902
|
+
};
|
|
2903
|
+
setupWatchers();
|
|
2904
|
+
regleDevtoolsRegistry.onInstancesChange(() => {
|
|
2905
|
+
const currentIds = new Set(regleDevtoolsRegistry.getAll().map((i) => i.id));
|
|
2906
|
+
for (const id of watchedInstances) if (!currentIds.has(id)) watchedInstances.delete(id);
|
|
2907
|
+
api.sendInspectorTree(INSPECTOR_IDS.INSPECTOR);
|
|
2908
|
+
api.sendInspectorState(INSPECTOR_IDS.INSPECTOR);
|
|
2909
|
+
setupWatchers();
|
|
3026
2910
|
});
|
|
3027
|
-
return returnedRef;
|
|
3028
|
-
}
|
|
3029
|
-
|
|
3030
|
-
//#endregion
|
|
3031
|
-
//#region src/core/refineRules.ts
|
|
3032
|
-
/**
|
|
3033
|
-
* Helper method to wrap an raw rules object
|
|
3034
|
-
*
|
|
3035
|
-
* Similar to:
|
|
3036
|
-
*
|
|
3037
|
-
* ```ts
|
|
3038
|
-
* const rules = {...} satisfies RegleUnknownRulesTree
|
|
3039
|
-
* ```
|
|
3040
|
-
*/
|
|
3041
|
-
function defineRules(rules) {
|
|
3042
|
-
return rules;
|
|
3043
|
-
}
|
|
3044
|
-
/**
|
|
3045
|
-
* Refine a raw rules object to set rules that depends on the state values.
|
|
3046
|
-
*
|
|
3047
|
-
* @example
|
|
3048
|
-
*
|
|
3049
|
-
* ```ts
|
|
3050
|
-
* const rules = refineRules({
|
|
3051
|
-
* password: { required, type: type<string>() },
|
|
3052
|
-
* }, (state) => {
|
|
3053
|
-
* return {
|
|
3054
|
-
* confirmPassword: { required, sameAs: sameAs(() => state.value.password)}
|
|
3055
|
-
* }
|
|
3056
|
-
* })
|
|
3057
|
-
* ```
|
|
3058
|
-
*/
|
|
3059
|
-
function refineRules(rules, refinement) {
|
|
3060
|
-
return (state) => merge({ ...rules }, refinement(state));
|
|
3061
2911
|
}
|
|
3062
2912
|
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
const
|
|
3066
|
-
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
text: 16777215,
|
|
3080
|
-
bg: 16096779
|
|
3081
|
-
},
|
|
3082
|
-
DIRTY: {
|
|
3083
|
-
text: 2042167,
|
|
3084
|
-
bg: 16708551
|
|
3085
|
-
},
|
|
3086
|
-
COMPONENT: {
|
|
3087
|
-
text: 16777215,
|
|
3088
|
-
bg: 6514417
|
|
2913
|
+
function useRootStorage({ initialState, originalState, options, scopeRules, state, customRules, shortcuts, schemaErrors, schemaMode = false, onValidate }) {
|
|
2914
|
+
const storage = useStorage();
|
|
2915
|
+
const regle = ref();
|
|
2916
|
+
const computedExternalErrors = ref();
|
|
2917
|
+
let $unwatchExternalErrors;
|
|
2918
|
+
let $unwatchComputedExternalErrors;
|
|
2919
|
+
function defineExternalErrorsWatchSource() {
|
|
2920
|
+
$unwatchExternalErrors = watch(() => options.externalErrors?.value, () => {
|
|
2921
|
+
$unwatchComputedExternalErrors?.();
|
|
2922
|
+
if (options.externalErrors?.value && Object.keys(options.externalErrors.value).some((key) => key.includes("."))) computedExternalErrors.value = dotPathObjectToNested(options.externalErrors.value);
|
|
2923
|
+
else computedExternalErrors.value = options.externalErrors?.value;
|
|
2924
|
+
defineComputedExternalErrorsWatchSource();
|
|
2925
|
+
}, {
|
|
2926
|
+
immediate: true,
|
|
2927
|
+
deep: true
|
|
2928
|
+
});
|
|
3089
2929
|
}
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
|
|
3115
|
-
|
|
3116
|
-
|
|
3117
|
-
return typeof value === "function";
|
|
3118
|
-
}
|
|
3119
|
-
function getPriorityProperties(obj, keys) {
|
|
3120
|
-
return keys.filter((key) => key in obj && !isMethod(obj[key])).map((key) => {
|
|
3121
|
-
let editable = false;
|
|
3122
|
-
if (key === "$value") editable = true;
|
|
3123
|
-
return {
|
|
3124
|
-
key,
|
|
3125
|
-
value: obj[key],
|
|
3126
|
-
editable
|
|
3127
|
-
};
|
|
2930
|
+
function defineComputedExternalErrorsWatchSource() {
|
|
2931
|
+
$unwatchComputedExternalErrors = watch(() => computedExternalErrors.value, () => {
|
|
2932
|
+
$unwatchExternalErrors?.();
|
|
2933
|
+
if (options.externalErrors?.value) options.externalErrors.value = computedExternalErrors.value;
|
|
2934
|
+
defineExternalErrorsWatchSource();
|
|
2935
|
+
}, { deep: true });
|
|
2936
|
+
}
|
|
2937
|
+
defineExternalErrorsWatchSource();
|
|
2938
|
+
if (isNestedRulesDef(state, scopeRules)) regle.value = createReactiveNestedStatus({
|
|
2939
|
+
rootRules: scopeRules,
|
|
2940
|
+
rulesDef: scopeRules,
|
|
2941
|
+
state,
|
|
2942
|
+
customMessages: customRules?.(),
|
|
2943
|
+
storage,
|
|
2944
|
+
options,
|
|
2945
|
+
externalErrors: computedExternalErrors,
|
|
2946
|
+
validationGroups: options.validationGroups,
|
|
2947
|
+
initialState,
|
|
2948
|
+
originalState,
|
|
2949
|
+
shortcuts,
|
|
2950
|
+
fieldName: "root",
|
|
2951
|
+
path: "",
|
|
2952
|
+
cachePath: "",
|
|
2953
|
+
schemaErrors,
|
|
2954
|
+
rootSchemaErrors: schemaErrors,
|
|
2955
|
+
schemaMode,
|
|
2956
|
+
onValidate
|
|
3128
2957
|
});
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
|
|
3144
|
-
|
|
3145
|
-
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
|
|
3149
|
-
|
|
3150
|
-
|
|
3151
|
-
if (
|
|
3152
|
-
|
|
3153
|
-
const ruleName = parts[1];
|
|
3154
|
-
const fieldInfo = parseFieldNodeId(fieldPart);
|
|
3155
|
-
if (!fieldInfo) return null;
|
|
3156
|
-
return {
|
|
3157
|
-
...fieldInfo,
|
|
3158
|
-
ruleName
|
|
3159
|
-
};
|
|
3160
|
-
}
|
|
3161
|
-
function createRuleNodeId(instanceId, fieldName, ruleName) {
|
|
3162
|
-
return `${createFieldNodeId(instanceId, fieldName)}:rule:${ruleName}`;
|
|
2958
|
+
else if (isValidatorRulesDef(scopeRules)) regle.value = createReactiveFieldStatus({
|
|
2959
|
+
rulesDef: scopeRules,
|
|
2960
|
+
state,
|
|
2961
|
+
customMessages: customRules?.(),
|
|
2962
|
+
storage,
|
|
2963
|
+
options,
|
|
2964
|
+
externalErrors: computedExternalErrors,
|
|
2965
|
+
initialState,
|
|
2966
|
+
originalState,
|
|
2967
|
+
shortcuts,
|
|
2968
|
+
fieldName: "root",
|
|
2969
|
+
path: "",
|
|
2970
|
+
cachePath: "",
|
|
2971
|
+
schemaMode,
|
|
2972
|
+
schemaErrors,
|
|
2973
|
+
onValidate
|
|
2974
|
+
});
|
|
2975
|
+
if (getCurrentScope()) onScopeDispose(() => {
|
|
2976
|
+
regle.value?.$unwatch();
|
|
2977
|
+
$unwatchComputedExternalErrors?.();
|
|
2978
|
+
$unwatchExternalErrors?.();
|
|
2979
|
+
});
|
|
2980
|
+
if (typeof window !== "undefined" && regle.value) registerRegleInstance(regle.value, { name: toValue(options.id) });
|
|
2981
|
+
return reactive({ regle });
|
|
3163
2982
|
}
|
|
3164
2983
|
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
|
|
3170
|
-
|
|
3171
|
-
|
|
3172
|
-
const
|
|
3173
|
-
if (
|
|
3174
|
-
|
|
3175
|
-
|
|
3176
|
-
|
|
3177
|
-
|
|
3178
|
-
|
|
3179
|
-
|
|
3180
|
-
|
|
3181
|
-
}
|
|
3182
|
-
|
|
3183
|
-
|
|
3184
|
-
|
|
3185
|
-
|
|
3186
|
-
|
|
3187
|
-
|
|
3188
|
-
|
|
3189
|
-
|
|
3190
|
-
|
|
3191
|
-
"$pending",
|
|
3192
|
-
"$message",
|
|
3193
|
-
"$tooltip"
|
|
3194
|
-
];
|
|
3195
|
-
const priorityProperties = getPriorityProperties(ruleStatus, ruleKeys);
|
|
3196
|
-
if (priorityProperties.length > 0) state["Rule State"] = priorityProperties;
|
|
3197
|
-
if (ruleStatus.$params && Array.isArray(ruleStatus.$params) && ruleStatus.$params.length > 0) state["Parameters"] = [{
|
|
3198
|
-
key: "$params",
|
|
3199
|
-
value: ruleStatus.$params,
|
|
3200
|
-
editable: false
|
|
3201
|
-
}];
|
|
3202
|
-
if (ruleStatus.$metadata !== void 0 && ruleStatus.$metadata !== true && ruleStatus.$metadata !== false) state["Metadata"] = [{
|
|
3203
|
-
key: "$metadata",
|
|
3204
|
-
value: ruleStatus.$metadata,
|
|
3205
|
-
editable: false
|
|
3206
|
-
}];
|
|
3207
|
-
const remainingProperties = getRemainingProperties(ruleStatus, [
|
|
3208
|
-
...ruleKeys,
|
|
3209
|
-
"$params",
|
|
3210
|
-
"$metadata",
|
|
3211
|
-
"$validator",
|
|
3212
|
-
"$parse",
|
|
3213
|
-
"$reset",
|
|
3214
|
-
"$unwatch",
|
|
3215
|
-
"$watch",
|
|
3216
|
-
"$haveAsync",
|
|
3217
|
-
"$validating",
|
|
3218
|
-
"$fieldDirty",
|
|
3219
|
-
"$fieldInvalid",
|
|
3220
|
-
"$fieldPending",
|
|
3221
|
-
"$fieldCorrect",
|
|
3222
|
-
"$fieldError",
|
|
3223
|
-
"$maybePending",
|
|
3224
|
-
"$externalErrors"
|
|
3225
|
-
]);
|
|
3226
|
-
if (remainingProperties.length > 0) state["Other Properties"] = remainingProperties;
|
|
3227
|
-
return state;
|
|
3228
|
-
}
|
|
3229
|
-
function buildRootState(r$) {
|
|
3230
|
-
const state = {};
|
|
3231
|
-
const priorityProperties = getPriorityProperties(r$, PRIORITY_KEYS.ROOT);
|
|
3232
|
-
if (priorityProperties.length > 0) state["State"] = priorityProperties;
|
|
3233
|
-
const remainingProperties = getRemainingProperties(r$, [...PRIORITY_KEYS.ROOT, "$fields"]);
|
|
3234
|
-
if (remainingProperties.length > 0) state["Other Properties"] = remainingProperties;
|
|
3235
|
-
return state;
|
|
2984
|
+
function createRootRegleLogic({ state, rulesFactory, options, globalOptions, customRules, shortcuts }) {
|
|
2985
|
+
const definedRules = isRef(rulesFactory) ? rulesFactory : typeof rulesFactory === "function" ? void 0 : computed(() => rulesFactory);
|
|
2986
|
+
const resolvedOptions = {
|
|
2987
|
+
...globalOptions,
|
|
2988
|
+
...options
|
|
2989
|
+
};
|
|
2990
|
+
let unwatchRules;
|
|
2991
|
+
const watchableRulesGetters = shallowRef(definedRules ?? {});
|
|
2992
|
+
if (typeof rulesFactory === "function") unwatchRules = watchEffect(() => {
|
|
2993
|
+
watchableRulesGetters.value = rulesFactory(state);
|
|
2994
|
+
triggerRef(watchableRulesGetters);
|
|
2995
|
+
});
|
|
2996
|
+
const initialState = ref(isObject(state.value) ? { ...cloneDeep(state.value) } : cloneDeep(state.value));
|
|
2997
|
+
const originalState = isObject(state.value) ? { ...cloneDeep(state.value) } : cloneDeep(state.value);
|
|
2998
|
+
tryOnScopeDispose(() => {
|
|
2999
|
+
unwatchRules?.();
|
|
3000
|
+
});
|
|
3001
|
+
return useRootStorage({
|
|
3002
|
+
scopeRules: watchableRulesGetters,
|
|
3003
|
+
state,
|
|
3004
|
+
options: resolvedOptions,
|
|
3005
|
+
initialState,
|
|
3006
|
+
originalState,
|
|
3007
|
+
customRules,
|
|
3008
|
+
shortcuts
|
|
3009
|
+
});
|
|
3236
3010
|
}
|
|
3237
|
-
|
|
3238
|
-
|
|
3239
|
-
const
|
|
3240
|
-
|
|
3241
|
-
|
|
3242
|
-
|
|
3243
|
-
|
|
3244
|
-
|
|
3245
|
-
|
|
3246
|
-
|
|
3247
|
-
|
|
3248
|
-
|
|
3249
|
-
|
|
3011
|
+
|
|
3012
|
+
function createUseRegleComposable(customRules, options, shortcuts) {
|
|
3013
|
+
const globalOptions = {
|
|
3014
|
+
autoDirty: options?.autoDirty,
|
|
3015
|
+
lazy: options?.lazy,
|
|
3016
|
+
rewardEarly: options?.rewardEarly,
|
|
3017
|
+
silent: options?.silent,
|
|
3018
|
+
clearExternalErrorsOnChange: options?.clearExternalErrorsOnChange
|
|
3019
|
+
};
|
|
3020
|
+
function useRegle$1(state, rulesFactory, options$1) {
|
|
3021
|
+
return { r$: createRootRegleLogic({
|
|
3022
|
+
state: isRef(state) ? state : ref(state),
|
|
3023
|
+
rulesFactory,
|
|
3024
|
+
options: options$1,
|
|
3025
|
+
globalOptions,
|
|
3026
|
+
customRules,
|
|
3027
|
+
shortcuts
|
|
3028
|
+
}).regle };
|
|
3250
3029
|
}
|
|
3251
|
-
return
|
|
3030
|
+
return useRegle$1;
|
|
3252
3031
|
}
|
|
3253
|
-
|
|
3254
|
-
|
|
3255
|
-
|
|
3256
|
-
|
|
3257
|
-
|
|
3258
|
-
|
|
3259
|
-
|
|
3260
|
-
|
|
3261
|
-
|
|
3262
|
-
|
|
3263
|
-
|
|
3264
|
-
|
|
3265
|
-
|
|
3266
|
-
|
|
3267
|
-
|
|
3268
|
-
|
|
3269
|
-
|
|
3270
|
-
|
|
3271
|
-
|
|
3272
|
-
|
|
3032
|
+
/**
|
|
3033
|
+
* useRegle serves as the foundation for validation logic.
|
|
3034
|
+
*
|
|
3035
|
+
* It accepts the following inputs:
|
|
3036
|
+
*
|
|
3037
|
+
* @param state - This can be a plain object, a ref, a reactive object, or a structure containing nested refs.
|
|
3038
|
+
* @param rules - These should align with the structure of your state.
|
|
3039
|
+
* @param modifiers - Customize regle behaviour
|
|
3040
|
+
*
|
|
3041
|
+
* ```ts
|
|
3042
|
+
* import { useRegle } from '@regle/core';
|
|
3043
|
+
import { required } from '@regle/rules';
|
|
3044
|
+
|
|
3045
|
+
const { r$ } = useRegle({ email: '' }, {
|
|
3046
|
+
email: { required }
|
|
3047
|
+
})
|
|
3048
|
+
* ```
|
|
3049
|
+
* Docs: {@link https://reglejs.dev/core-concepts/}
|
|
3050
|
+
*/
|
|
3051
|
+
const useRegle = createUseRegleComposable();
|
|
3052
|
+
|
|
3053
|
+
function createInferRuleHelper() {
|
|
3054
|
+
function inferRules$1(state, rulesFactory) {
|
|
3055
|
+
return rulesFactory;
|
|
3273
3056
|
}
|
|
3274
|
-
|
|
3275
|
-
if (!instance) return null;
|
|
3276
|
-
return buildRootState(instance.r$);
|
|
3057
|
+
return inferRules$1;
|
|
3277
3058
|
}
|
|
3059
|
+
/**
|
|
3060
|
+
* Rule type helper to provide autocomplete and typecheck to your form rules or part of your form rules
|
|
3061
|
+
* It will just return the rules without any processing.
|
|
3062
|
+
*
|
|
3063
|
+
* @param state - The state reference
|
|
3064
|
+
* @param rules - Your rule tree
|
|
3065
|
+
*/
|
|
3066
|
+
const inferRules = createInferRuleHelper();
|
|
3278
3067
|
|
|
3279
|
-
|
|
3280
|
-
|
|
3281
|
-
|
|
3282
|
-
|
|
3283
|
-
|
|
3284
|
-
|
|
3285
|
-
|
|
3286
|
-
|
|
3287
|
-
if (instance && instance.r$.$fields) {
|
|
3288
|
-
const fieldStatus = resolveFieldByPath(instance.r$.$fields, fieldName);
|
|
3289
|
-
if (fieldStatus && typeof fieldStatus.$validate === "function") fieldStatus.$validate();
|
|
3290
|
-
}
|
|
3291
|
-
} else {
|
|
3292
|
-
const instance = regleDevtoolsRegistry.get(nodeId);
|
|
3293
|
-
if (instance && typeof instance.r$.$validate === "function") instance.r$.$validate();
|
|
3068
|
+
function createEmptyRuleState(rules) {
|
|
3069
|
+
const result = {};
|
|
3070
|
+
if (Object.entries(rules).some(([_, rule]) => isRuleDef(rule) || typeof rule === "function")) return null;
|
|
3071
|
+
for (const key in rules) {
|
|
3072
|
+
const item = rules[key];
|
|
3073
|
+
if (!!item && isObject(item) && "$each" in item && item["$each"] && isObject(item["$each"])) result[key] = [createEmptyRuleState(item["$each"])];
|
|
3074
|
+
else if (isObject(item) && !isEmpty(item) && !Object.entries(item).some(([_, rule]) => isRuleDef(rule) || typeof rule === "function")) result[key] = createEmptyRuleState(item);
|
|
3075
|
+
else result[key] = null;
|
|
3294
3076
|
}
|
|
3295
|
-
|
|
3077
|
+
return result;
|
|
3296
3078
|
}
|
|
3297
|
-
function
|
|
3298
|
-
const
|
|
3299
|
-
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
|
|
3304
|
-
|
|
3305
|
-
|
|
3306
|
-
|
|
3307
|
-
|
|
3308
|
-
|
|
3079
|
+
function createUseRulesComposable(customRules, options, shortcuts) {
|
|
3080
|
+
const globalOptions = {
|
|
3081
|
+
autoDirty: options?.autoDirty,
|
|
3082
|
+
lazy: options?.lazy,
|
|
3083
|
+
rewardEarly: options?.rewardEarly,
|
|
3084
|
+
silent: options?.silent,
|
|
3085
|
+
clearExternalErrorsOnChange: options?.clearExternalErrorsOnChange
|
|
3086
|
+
};
|
|
3087
|
+
function useRules$1(rulesFactory, options$1) {
|
|
3088
|
+
const definedRules = isRef(rulesFactory) ? rulesFactory : typeof rulesFactory === "function" ? void 0 : computed(() => rulesFactory);
|
|
3089
|
+
return createRootRegleLogic({
|
|
3090
|
+
state: ref(createEmptyRuleState(definedRules?.value)),
|
|
3091
|
+
rulesFactory: definedRules,
|
|
3092
|
+
options: options$1,
|
|
3093
|
+
globalOptions,
|
|
3094
|
+
customRules,
|
|
3095
|
+
shortcuts
|
|
3096
|
+
}).regle;
|
|
3309
3097
|
}
|
|
3310
|
-
|
|
3098
|
+
return useRules$1;
|
|
3311
3099
|
}
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
|
|
3317
|
-
|
|
3318
|
-
|
|
3319
|
-
|
|
3320
|
-
|
|
3321
|
-
|
|
3322
|
-
|
|
3100
|
+
/**
|
|
3101
|
+
* useRules is a clone of useRegle, without the need to provide a state.
|
|
3102
|
+
*
|
|
3103
|
+
* It accepts the following inputs:
|
|
3104
|
+
*
|
|
3105
|
+
* @param rules - Your rules object
|
|
3106
|
+
* @param modifiers - Customize regle behaviour
|
|
3107
|
+
*
|
|
3108
|
+
* ```ts
|
|
3109
|
+
* import { useRules } from '@regle/core';
|
|
3110
|
+
import { required } from '@regle/rules';
|
|
3111
|
+
|
|
3112
|
+
const { r$ } = useRules({
|
|
3113
|
+
email: { required }
|
|
3114
|
+
})
|
|
3115
|
+
* ```
|
|
3116
|
+
*/
|
|
3117
|
+
const useRules = createUseRulesComposable();
|
|
3118
|
+
|
|
3119
|
+
/**
|
|
3120
|
+
* Define a global regle configuration, where you can:
|
|
3121
|
+
* - Customize built-in rules messages
|
|
3122
|
+
* - Add your custom rules
|
|
3123
|
+
* - Define global modifiers
|
|
3124
|
+
* - Define shortcuts
|
|
3125
|
+
*
|
|
3126
|
+
* It will return:
|
|
3127
|
+
*
|
|
3128
|
+
* - a `useRegle` composable that can typecheck your custom rules
|
|
3129
|
+
* - an `inferRules` helper that can typecheck your custom rules
|
|
3130
|
+
*/
|
|
3131
|
+
function defineRegleConfig({ rules, modifiers, shortcuts }) {
|
|
3132
|
+
const useRegle$1 = createUseRegleComposable(rules, modifiers, shortcuts);
|
|
3133
|
+
const useRules$1 = createUseRulesComposable(rules, modifiers, shortcuts);
|
|
3134
|
+
useRegle$1.__config = {
|
|
3135
|
+
rules,
|
|
3136
|
+
modifiers,
|
|
3137
|
+
shortcuts
|
|
3138
|
+
};
|
|
3139
|
+
useRules$1.__config = {
|
|
3140
|
+
rules,
|
|
3141
|
+
modifiers,
|
|
3142
|
+
shortcuts
|
|
3143
|
+
};
|
|
3144
|
+
return {
|
|
3145
|
+
useRegle: useRegle$1,
|
|
3146
|
+
inferRules: createInferRuleHelper(),
|
|
3147
|
+
useRules: useRules$1
|
|
3148
|
+
};
|
|
3323
3149
|
}
|
|
3324
|
-
|
|
3325
|
-
|
|
3326
|
-
|
|
3327
|
-
|
|
3328
|
-
|
|
3150
|
+
/**
|
|
3151
|
+
* Extend an already created custom `useRegle` (as the first parameter)
|
|
3152
|
+
*
|
|
3153
|
+
* It will return:
|
|
3154
|
+
*
|
|
3155
|
+
* - a `useRegle` composable that can typecheck your custom rules
|
|
3156
|
+
* - an `inferRules` helper that can typecheck your custom rules
|
|
3157
|
+
*/
|
|
3158
|
+
function extendRegleConfig(regle, { rules, modifiers, shortcuts }) {
|
|
3159
|
+
const rootConfig = regle.__config ?? {};
|
|
3160
|
+
const newRules = () => ({
|
|
3161
|
+
...rootConfig.rules?.(),
|
|
3162
|
+
...rules?.()
|
|
3163
|
+
});
|
|
3164
|
+
const newModifiers = rootConfig.modifiers && modifiers ? merge(rootConfig.modifiers, modifiers) : rootConfig.modifiers ?? modifiers;
|
|
3165
|
+
const newShortcuts = rootConfig.shortcuts && shortcuts ? merge(rootConfig.shortcuts, shortcuts) : rootConfig.shortcuts ?? shortcuts;
|
|
3166
|
+
const useRegle$1 = createUseRegleComposable(newRules, newModifiers, newShortcuts);
|
|
3167
|
+
useRegle$1.__config = {
|
|
3168
|
+
rules: newRules,
|
|
3169
|
+
modifiers: newModifiers,
|
|
3170
|
+
shortcuts: newShortcuts
|
|
3171
|
+
};
|
|
3172
|
+
return {
|
|
3173
|
+
useRegle: useRegle$1,
|
|
3174
|
+
inferRules: createInferRuleHelper()
|
|
3175
|
+
};
|
|
3329
3176
|
}
|
|
3330
3177
|
|
|
3331
|
-
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
|
|
3335
|
-
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
|
|
3178
|
+
function mergeRegles(regles, _scoped) {
|
|
3179
|
+
const scoped = _scoped == null ? false : _scoped;
|
|
3180
|
+
const $value = computed({
|
|
3181
|
+
get: () => {
|
|
3182
|
+
if (scoped) return Object.values(regles).map((r) => r.$value);
|
|
3183
|
+
else return Object.fromEntries(Object.entries(regles).map(([key, r]) => [key, r.$value]));
|
|
3184
|
+
},
|
|
3185
|
+
set: (value) => {
|
|
3186
|
+
if (!scoped) {
|
|
3187
|
+
if (typeof value === "object") Object.entries(value).forEach(([key, newValue]) => regles[key].$value = newValue);
|
|
3188
|
+
}
|
|
3189
|
+
}
|
|
3190
|
+
});
|
|
3191
|
+
const $silentValue = computed({
|
|
3192
|
+
get: () => Object.fromEntries(Object.entries(regles).map(([key, r]) => [key, r.$silentValue])),
|
|
3193
|
+
set: (value) => {
|
|
3194
|
+
if (typeof value === "object") Object.entries(value).forEach(([key, newValue]) => regles[key].$silentValue = newValue);
|
|
3195
|
+
}
|
|
3339
3196
|
});
|
|
3340
|
-
|
|
3341
|
-
|
|
3342
|
-
|
|
3343
|
-
|
|
3197
|
+
const $dirty = computed(() => {
|
|
3198
|
+
const entries = Object.entries(regles);
|
|
3199
|
+
return !!entries.length && entries.every(([_, regle]) => {
|
|
3200
|
+
return regle?.$dirty;
|
|
3201
|
+
});
|
|
3344
3202
|
});
|
|
3345
|
-
|
|
3346
|
-
|
|
3347
|
-
|
|
3348
|
-
|
|
3203
|
+
const $anyDirty = computed(() => {
|
|
3204
|
+
return Object.entries(regles).some(([_, regle]) => {
|
|
3205
|
+
return regle?.$anyDirty;
|
|
3206
|
+
});
|
|
3349
3207
|
});
|
|
3350
|
-
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
|
|
3208
|
+
const $invalid = computed(() => {
|
|
3209
|
+
return Object.entries(regles).some(([_, regle]) => {
|
|
3210
|
+
return regle?.$invalid;
|
|
3211
|
+
});
|
|
3354
3212
|
});
|
|
3355
|
-
|
|
3356
|
-
|
|
3357
|
-
|
|
3358
|
-
|
|
3213
|
+
const $correct = computed(() => {
|
|
3214
|
+
const entries = Object.entries(regles);
|
|
3215
|
+
return !!entries.length && entries.every(([_, regle]) => {
|
|
3216
|
+
return regle?.$correct || regle.$anyDirty && !regle.$invalid;
|
|
3217
|
+
});
|
|
3359
3218
|
});
|
|
3360
|
-
|
|
3361
|
-
|
|
3362
|
-
|
|
3363
|
-
|
|
3364
|
-
if (!rule.$active) tags.push({
|
|
3365
|
-
label: "inactive",
|
|
3366
|
-
textColor: 10265519,
|
|
3367
|
-
backgroundColor: 15987958
|
|
3219
|
+
const $error = computed(() => {
|
|
3220
|
+
return Object.entries(regles).some(([_, regle]) => {
|
|
3221
|
+
return regle?.$error;
|
|
3222
|
+
});
|
|
3368
3223
|
});
|
|
3369
|
-
|
|
3370
|
-
|
|
3371
|
-
|
|
3372
|
-
|
|
3224
|
+
const $ready = computed(() => {
|
|
3225
|
+
const entries = Object.entries(regles);
|
|
3226
|
+
return !!entries.length && entries.every(([_, regle]) => {
|
|
3227
|
+
return regle?.$ready;
|
|
3228
|
+
});
|
|
3373
3229
|
});
|
|
3374
|
-
|
|
3375
|
-
|
|
3376
|
-
|
|
3377
|
-
|
|
3230
|
+
const $pending = computed(() => {
|
|
3231
|
+
return Object.entries(regles).some(([_, regle]) => {
|
|
3232
|
+
return regle?.$pending;
|
|
3233
|
+
});
|
|
3378
3234
|
});
|
|
3379
|
-
|
|
3380
|
-
|
|
3381
|
-
|
|
3382
|
-
|
|
3235
|
+
const $issues = computed(() => {
|
|
3236
|
+
if (scoped) return Object.entries(regles).map(([_, regle]) => {
|
|
3237
|
+
return regle.$issues;
|
|
3238
|
+
});
|
|
3239
|
+
else return Object.fromEntries(Object.entries(regles).map(([key, regle]) => {
|
|
3240
|
+
return [key, regle.$issues];
|
|
3241
|
+
}));
|
|
3383
3242
|
});
|
|
3384
|
-
|
|
3385
|
-
|
|
3386
|
-
|
|
3387
|
-
|
|
3388
|
-
|
|
3389
|
-
|
|
3390
|
-
|
|
3391
|
-
const ruleTags = buildRuleTags(ruleStatus);
|
|
3392
|
-
children.push({
|
|
3393
|
-
id: createRuleNodeId(instanceId, fieldPath, ruleName),
|
|
3394
|
-
label: ruleName,
|
|
3395
|
-
tags: ruleTags,
|
|
3396
|
-
children: []
|
|
3397
|
-
});
|
|
3398
|
-
}
|
|
3243
|
+
const $silentIssues = computed(() => {
|
|
3244
|
+
if (scoped) return Object.entries(regles).map(([_, regle]) => {
|
|
3245
|
+
return regle.$silentIssues;
|
|
3246
|
+
});
|
|
3247
|
+
else return Object.fromEntries(Object.entries(regles).map(([key, regle]) => {
|
|
3248
|
+
return [key, regle.$silentIssues];
|
|
3249
|
+
}));
|
|
3399
3250
|
});
|
|
3400
|
-
|
|
3401
|
-
|
|
3402
|
-
|
|
3403
|
-
|
|
3404
|
-
|
|
3405
|
-
|
|
3406
|
-
|
|
3407
|
-
const itemTags = buildNodeTags(item);
|
|
3408
|
-
const itemPath = `${fieldPath}[${index}]`;
|
|
3409
|
-
let itemChildren = [];
|
|
3410
|
-
if (isNestedRulesStatus(item)) itemChildren = buildNestedFieldNodes(item.$fields, instanceId, itemPath);
|
|
3411
|
-
else if (isFieldStatus(item)) itemChildren = buildRuleNodes(item, instanceId, itemPath);
|
|
3412
|
-
children.push({
|
|
3413
|
-
id: createFieldNodeId(instanceId, itemPath),
|
|
3414
|
-
label: `[${index}]`,
|
|
3415
|
-
tags: itemTags,
|
|
3416
|
-
children: itemChildren
|
|
3417
|
-
});
|
|
3418
|
-
}
|
|
3251
|
+
const $errors = computed(() => {
|
|
3252
|
+
if (scoped) return Object.entries(regles).map(([_, regle]) => {
|
|
3253
|
+
return regle.$errors;
|
|
3254
|
+
});
|
|
3255
|
+
else return Object.fromEntries(Object.entries(regles).map(([key, regle]) => {
|
|
3256
|
+
return [key, regle.$errors];
|
|
3257
|
+
}));
|
|
3419
3258
|
});
|
|
3420
|
-
|
|
3421
|
-
|
|
3422
|
-
|
|
3423
|
-
|
|
3424
|
-
|
|
3425
|
-
|
|
3426
|
-
|
|
3427
|
-
const fieldTags = buildNodeTags(fieldStatus);
|
|
3428
|
-
let fieldChildren = [];
|
|
3429
|
-
if (isCollectionRulesStatus(fieldStatus)) fieldChildren = buildCollectionItemNodes(fieldStatus, instanceId, fieldPath);
|
|
3430
|
-
else if (isNestedRulesStatus(fieldStatus)) fieldChildren = buildNestedFieldNodes(fieldStatus.$fields, instanceId, fieldPath);
|
|
3431
|
-
else if (isFieldStatus(fieldStatus)) fieldChildren = buildRuleNodes(fieldStatus, instanceId, fieldPath);
|
|
3432
|
-
children.push({
|
|
3433
|
-
id: createFieldNodeId(instanceId, fieldPath),
|
|
3434
|
-
label: fieldName,
|
|
3435
|
-
tags: fieldTags,
|
|
3436
|
-
children: fieldChildren
|
|
3437
|
-
});
|
|
3438
|
-
}
|
|
3259
|
+
const $silentErrors = computed(() => {
|
|
3260
|
+
if (scoped) return Object.entries(regles).map(([_, regle]) => {
|
|
3261
|
+
return regle.$silentErrors;
|
|
3262
|
+
});
|
|
3263
|
+
else return Object.fromEntries(Object.entries(regles).map(([key, regle]) => {
|
|
3264
|
+
return [key, regle.$silentErrors];
|
|
3265
|
+
}));
|
|
3439
3266
|
});
|
|
3440
|
-
|
|
3441
|
-
|
|
3442
|
-
|
|
3443
|
-
|
|
3444
|
-
|
|
3445
|
-
if (!r$.$fields || typeof r$.$fields !== "object") return children;
|
|
3446
|
-
Object.entries(r$.$fields).forEach(([fieldName, fieldStatus]) => {
|
|
3447
|
-
if (fieldStatus && typeof fieldStatus === "object") {
|
|
3448
|
-
const fieldTags = buildNodeTags(fieldStatus);
|
|
3449
|
-
let fieldChildren = [];
|
|
3450
|
-
if (isCollectionRulesStatus(fieldStatus)) fieldChildren = buildCollectionItemNodes(fieldStatus, instanceId, fieldName);
|
|
3451
|
-
else if (isNestedRulesStatus(fieldStatus)) fieldChildren = buildNestedFieldNodes(fieldStatus.$fields, instanceId, fieldName);
|
|
3452
|
-
else if (isFieldStatus(fieldStatus)) fieldChildren = buildRuleNodes(fieldStatus, instanceId, fieldName);
|
|
3453
|
-
children.push({
|
|
3454
|
-
id: createFieldNodeId(instanceId, fieldName),
|
|
3455
|
-
label: fieldName,
|
|
3456
|
-
tags: fieldTags,
|
|
3457
|
-
children: fieldChildren
|
|
3458
|
-
});
|
|
3459
|
-
}
|
|
3267
|
+
const $edited = computed(() => {
|
|
3268
|
+
const entries = Object.entries(regles);
|
|
3269
|
+
return !!entries.length && entries.every(([_, regle]) => {
|
|
3270
|
+
return regle?.$edited;
|
|
3271
|
+
});
|
|
3460
3272
|
});
|
|
3461
|
-
|
|
3462
|
-
|
|
3463
|
-
|
|
3464
|
-
|
|
3465
|
-
|
|
3466
|
-
|
|
3467
|
-
|
|
3468
|
-
|
|
3469
|
-
|
|
3470
|
-
|
|
3471
|
-
|
|
3273
|
+
const $anyEdited = computed(() => {
|
|
3274
|
+
return Object.entries(regles).some(([_, regle]) => {
|
|
3275
|
+
return regle?.$anyEdited;
|
|
3276
|
+
});
|
|
3277
|
+
});
|
|
3278
|
+
const $instances = computed(() => {
|
|
3279
|
+
if (scoped) return Object.values(regles);
|
|
3280
|
+
else return regles;
|
|
3281
|
+
});
|
|
3282
|
+
function $reset(options) {
|
|
3283
|
+
Object.values(regles).forEach((regle) => {
|
|
3284
|
+
regle.$reset(options);
|
|
3285
|
+
});
|
|
3286
|
+
}
|
|
3287
|
+
function $touch() {
|
|
3288
|
+
Object.values(regles).forEach((regle) => {
|
|
3289
|
+
regle.$touch();
|
|
3290
|
+
});
|
|
3291
|
+
}
|
|
3292
|
+
function $extractDirtyFields(filterNullishValues = true) {
|
|
3293
|
+
return Object.values(regles).map((regle) => regle.$extractDirtyFields(filterNullishValues));
|
|
3294
|
+
}
|
|
3295
|
+
function $clearExternalErrors() {
|
|
3296
|
+
Object.values(regles).forEach((regle) => {
|
|
3297
|
+
regle.$clearExternalErrors();
|
|
3298
|
+
});
|
|
3299
|
+
}
|
|
3300
|
+
async function $validate(forceValues) {
|
|
3301
|
+
try {
|
|
3302
|
+
if (forceValues) $value.value = forceValues;
|
|
3303
|
+
const data = $value.value;
|
|
3304
|
+
return {
|
|
3305
|
+
valid: (await Promise.allSettled(Object.values(regles).map((regle) => {
|
|
3306
|
+
return regle.$validate();
|
|
3307
|
+
}))).every((value) => {
|
|
3308
|
+
if (value.status === "fulfilled") return value.value.valid === true;
|
|
3309
|
+
else return false;
|
|
3310
|
+
}),
|
|
3311
|
+
data,
|
|
3312
|
+
errors: $errors.value,
|
|
3313
|
+
issues: $issues.value
|
|
3314
|
+
};
|
|
3315
|
+
} catch {
|
|
3316
|
+
return {
|
|
3317
|
+
valid: false,
|
|
3318
|
+
data: $value.value,
|
|
3319
|
+
errors: $errors.value,
|
|
3320
|
+
issues: $issues.value
|
|
3321
|
+
};
|
|
3322
|
+
}
|
|
3323
|
+
}
|
|
3324
|
+
return reactive({
|
|
3325
|
+
...!scoped && { $silentValue },
|
|
3326
|
+
$errors,
|
|
3327
|
+
$issues,
|
|
3328
|
+
$silentIssues,
|
|
3329
|
+
$silentErrors,
|
|
3330
|
+
$instances,
|
|
3331
|
+
$value,
|
|
3332
|
+
$dirty,
|
|
3333
|
+
$anyDirty,
|
|
3334
|
+
$invalid,
|
|
3335
|
+
$correct,
|
|
3336
|
+
$error,
|
|
3337
|
+
$pending,
|
|
3338
|
+
$ready,
|
|
3339
|
+
$edited,
|
|
3340
|
+
$anyEdited,
|
|
3341
|
+
$reset,
|
|
3342
|
+
$touch,
|
|
3343
|
+
$validate,
|
|
3344
|
+
$extractDirtyFields,
|
|
3345
|
+
$clearExternalErrors
|
|
3472
3346
|
});
|
|
3473
|
-
if (!filter || filter.trim() === "") return nodes;
|
|
3474
|
-
return filterInspectorTree(nodes, filter);
|
|
3475
3347
|
}
|
|
3476
|
-
|
|
3477
|
-
|
|
3478
|
-
|
|
3479
|
-
|
|
3480
|
-
|
|
3481
|
-
const
|
|
3482
|
-
const
|
|
3483
|
-
|
|
3484
|
-
|
|
3485
|
-
|
|
3486
|
-
|
|
3348
|
+
|
|
3349
|
+
function createUseCollectScope(instances, options) {
|
|
3350
|
+
function useCollectScope$1(namespace) {
|
|
3351
|
+
const computedNamespace = computed(() => toValue(namespace));
|
|
3352
|
+
setEmptyNamespace();
|
|
3353
|
+
const r$ = ref(collectRegles(instances.value));
|
|
3354
|
+
const regle = reactive({ r$ });
|
|
3355
|
+
function setEmptyNamespace() {
|
|
3356
|
+
if (computedNamespace.value && !instances.value[computedNamespace.value]) instances.value[computedNamespace.value] = {};
|
|
3357
|
+
}
|
|
3358
|
+
watch(computedNamespace, setEmptyNamespace);
|
|
3359
|
+
watch(instances, (newInstances) => {
|
|
3360
|
+
r$.value = collectRegles(newInstances);
|
|
3361
|
+
}, { deep: true });
|
|
3362
|
+
function collectRegles(r$Instances) {
|
|
3363
|
+
if (computedNamespace.value) return mergeRegles(r$Instances[computedNamespace.value] ?? {}, !options.asRecord);
|
|
3364
|
+
else return mergeRegles(r$Instances["~~global"] ?? {}, !options.asRecord);
|
|
3365
|
+
}
|
|
3366
|
+
return { r$: regle.r$ };
|
|
3487
3367
|
}
|
|
3488
|
-
return
|
|
3368
|
+
return { useCollectScope: useCollectScope$1 };
|
|
3489
3369
|
}
|
|
3490
3370
|
|
|
3491
|
-
|
|
3492
|
-
|
|
3493
|
-
|
|
3494
|
-
|
|
3495
|
-
|
|
3496
|
-
|
|
3497
|
-
|
|
3498
|
-
|
|
3499
|
-
|
|
3500
|
-
componentStateTypes: [],
|
|
3501
|
-
app
|
|
3502
|
-
}, (api) => {
|
|
3503
|
-
api.addInspector({
|
|
3504
|
-
id: INSPECTOR_IDS.INSPECTOR,
|
|
3505
|
-
label: "Regle",
|
|
3506
|
-
noSelectionText: "No instance selected",
|
|
3507
|
-
icon: "rule",
|
|
3508
|
-
treeFilterPlaceholder: "Filter",
|
|
3509
|
-
stateFilterPlaceholder: "Filter validation status",
|
|
3510
|
-
nodeActions: [
|
|
3511
|
-
{
|
|
3512
|
-
icon: "check_circle",
|
|
3513
|
-
tooltip: "Validate (with `$validate`)",
|
|
3514
|
-
action: (nodeId) => {
|
|
3515
|
-
handleValidateAction(nodeId, api);
|
|
3516
|
-
}
|
|
3517
|
-
},
|
|
3518
|
-
{
|
|
3519
|
-
icon: "refresh",
|
|
3520
|
-
tooltip: "Reset validation state (with `$reset`)",
|
|
3521
|
-
action: (nodeId) => {
|
|
3522
|
-
handleResetAction(nodeId, api);
|
|
3523
|
-
}
|
|
3524
|
-
},
|
|
3525
|
-
{
|
|
3526
|
-
icon: "restore",
|
|
3527
|
-
tooltip: "Restore to initial state (with `$reset`)",
|
|
3528
|
-
action: (nodeId) => {
|
|
3529
|
-
handleResetAction(nodeId, api, true);
|
|
3530
|
-
}
|
|
3531
|
-
}
|
|
3532
|
-
]
|
|
3371
|
+
function createUseScopedRegleComposable(instances, customUseRegle) {
|
|
3372
|
+
const scopedUseRegle = customUseRegle ?? useRegle;
|
|
3373
|
+
const useScopedRegle$1 = ((state, rulesFactory, options) => {
|
|
3374
|
+
const { namespace, scopeKey: _scopeKey,...restOptions } = options ?? {};
|
|
3375
|
+
scopedUseRegle.__config ??= {};
|
|
3376
|
+
const computedNamespace = computed(() => toValue(namespace));
|
|
3377
|
+
const $id = ref(`${Object.keys(instances.value).length + 1}-${randomId()}`);
|
|
3378
|
+
const instanceName = computed(() => {
|
|
3379
|
+
return options?.scopeKey ?? `instance-${$id.value}`;
|
|
3533
3380
|
});
|
|
3534
|
-
|
|
3535
|
-
|
|
3536
|
-
|
|
3381
|
+
const { r$ } = scopedUseRegle(state, rulesFactory, restOptions);
|
|
3382
|
+
register();
|
|
3383
|
+
tryOnScopeDispose(dispose);
|
|
3384
|
+
watch(computedNamespace, (newName, oldName) => {
|
|
3385
|
+
dispose(oldName);
|
|
3386
|
+
register();
|
|
3537
3387
|
});
|
|
3538
|
-
|
|
3539
|
-
|
|
3540
|
-
|
|
3541
|
-
if (
|
|
3388
|
+
if (getCurrentInstance()) onMounted(() => {
|
|
3389
|
+
const currentInstance = getCurrentInstance();
|
|
3390
|
+
if (typeof window !== "undefined" && currentInstance?.proxy?.$el?.parentElement) {
|
|
3391
|
+
if (document.documentElement && !document.documentElement.contains(currentInstance?.proxy?.$el?.parentElement)) dispose();
|
|
3542
3392
|
}
|
|
3543
3393
|
});
|
|
3544
|
-
|
|
3545
|
-
|
|
3546
|
-
|
|
3394
|
+
function dispose(oldName) {
|
|
3395
|
+
const nameToClean = oldName ?? computedNamespace.value;
|
|
3396
|
+
if (nameToClean) {
|
|
3397
|
+
if (instances.value[nameToClean]) delete instances.value[nameToClean][instanceName.value];
|
|
3398
|
+
} else if (instances.value["~~global"][instanceName.value]) delete instances.value["~~global"][instanceName.value];
|
|
3399
|
+
}
|
|
3400
|
+
function register() {
|
|
3401
|
+
if (computedNamespace.value) {
|
|
3402
|
+
if (!instances.value[computedNamespace.value]) instances.value[computedNamespace.value] = {};
|
|
3403
|
+
instances.value[computedNamespace.value][instanceName.value] = r$;
|
|
3404
|
+
} else {
|
|
3405
|
+
if (!instances.value["~~global"]) instances.value["~~global"] = {};
|
|
3406
|
+
instances.value["~~global"][instanceName.value] = r$;
|
|
3407
|
+
}
|
|
3408
|
+
}
|
|
3409
|
+
return {
|
|
3410
|
+
r$,
|
|
3411
|
+
dispose,
|
|
3412
|
+
register
|
|
3413
|
+
};
|
|
3547
3414
|
});
|
|
3415
|
+
return { useScopedRegle: useScopedRegle$1 };
|
|
3548
3416
|
}
|
|
3549
|
-
|
|
3550
|
-
|
|
3551
|
-
const
|
|
3552
|
-
|
|
3553
|
-
|
|
3554
|
-
if (
|
|
3555
|
-
|
|
3556
|
-
|
|
3557
|
-
|
|
3558
|
-
|
|
3559
|
-
|
|
3560
|
-
|
|
3561
|
-
|
|
3417
|
+
|
|
3418
|
+
function createScopedUseRegle(options) {
|
|
3419
|
+
const instances = (options?.customStore ? () => {
|
|
3420
|
+
if (options.customStore) {
|
|
3421
|
+
if (!options.customStore?.value["~~global"]) options.customStore.value["~~global"] = {};
|
|
3422
|
+
else if (options.customStore?.value) options.customStore.value = { "~~global": {} };
|
|
3423
|
+
}
|
|
3424
|
+
return options.customStore;
|
|
3425
|
+
} : createGlobalState(() => {
|
|
3426
|
+
return ref({ "~~global": {} });
|
|
3427
|
+
}))();
|
|
3428
|
+
const { useScopedRegle: useScopedRegle$1 } = createUseScopedRegleComposable(instances, options?.customUseRegle);
|
|
3429
|
+
const { useCollectScope: useCollectScope$1 } = createUseCollectScope(instances, { asRecord: options?.asRecord });
|
|
3430
|
+
return {
|
|
3431
|
+
useScopedRegle: useScopedRegle$1,
|
|
3432
|
+
useCollectScope: useCollectScope$1
|
|
3562
3433
|
};
|
|
3563
|
-
|
|
3564
|
-
|
|
3565
|
-
|
|
3566
|
-
|
|
3567
|
-
|
|
3568
|
-
|
|
3434
|
+
}
|
|
3435
|
+
const { useCollectScope, useScopedRegle } = createScopedUseRegle();
|
|
3436
|
+
|
|
3437
|
+
/**
|
|
3438
|
+
* Declare variations of state that depends on one value
|
|
3439
|
+
*
|
|
3440
|
+
* Autocomplete may not work here because of https://github.com/microsoft/TypeScript/issues/49547
|
|
3441
|
+
*
|
|
3442
|
+
* ```ts
|
|
3443
|
+
* // ⚠️ Use getter syntax for your rules () => {} or a computed one
|
|
3444
|
+
* const {r$} = useRegle(state, () => {
|
|
3445
|
+
* const variant = createVariant(state, 'type', [
|
|
3446
|
+
* {type: { literal: literal('EMAIL')}, email: { required, email }},
|
|
3447
|
+
* {type: { literal: literal('GITHUB')}, username: { required }},
|
|
3448
|
+
* {type: { required }},
|
|
3449
|
+
* ]);
|
|
3450
|
+
*
|
|
3451
|
+
* return {
|
|
3452
|
+
* ...variant.value,
|
|
3453
|
+
* };
|
|
3454
|
+
* })
|
|
3455
|
+
* ```
|
|
3456
|
+
*/
|
|
3457
|
+
function createVariant(root, discriminantKey, variants) {
|
|
3458
|
+
const watchableRoot = computed(() => toValue(root)[discriminantKey]);
|
|
3459
|
+
return computed(() => {
|
|
3460
|
+
const selectedVariant = variants.find((variant) => {
|
|
3461
|
+
if (variant[discriminantKey] && "literal" in variant[discriminantKey]) {
|
|
3462
|
+
const literalRule = variant[discriminantKey]["literal"];
|
|
3463
|
+
if (isRuleDef(literalRule)) return unref(literalRule._params?.[0]) === watchableRoot.value;
|
|
3464
|
+
}
|
|
3465
|
+
});
|
|
3466
|
+
if (selectedVariant) return selectedVariant;
|
|
3467
|
+
else {
|
|
3468
|
+
const anyDiscriminantRules = variants.find((variant) => isObject(variant[discriminantKey]) && !Object.keys(variant[discriminantKey]).some((key) => key === "literal"));
|
|
3469
|
+
if (anyDiscriminantRules) return anyDiscriminantRules;
|
|
3470
|
+
else return {};
|
|
3471
|
+
}
|
|
3472
|
+
});
|
|
3473
|
+
}
|
|
3474
|
+
/**
|
|
3475
|
+
* Narrow a nested variant field to a discriminated value
|
|
3476
|
+
*
|
|
3477
|
+
* ```ts
|
|
3478
|
+
* if (narrowVariant(r$, 'type', 'EMAIL')) {
|
|
3479
|
+
* r$.email.$value = 'foo';
|
|
3480
|
+
* }
|
|
3481
|
+
* ```
|
|
3482
|
+
*/
|
|
3483
|
+
function narrowVariant(root, discriminantKey, discriminantValue) {
|
|
3484
|
+
return isObject(root[discriminantKey]) && "$value" in root[discriminantKey] && root[discriminantKey]?.$value === discriminantValue;
|
|
3485
|
+
}
|
|
3486
|
+
function variantToRef(root, discriminantKey, discriminantValue, _options) {
|
|
3487
|
+
const fromRoot = isRef(root) ? toRef(root.value, "$fields") : toRef(root, "$fields");
|
|
3488
|
+
const returnedRef = ref();
|
|
3489
|
+
watch(fromRoot, async () => {
|
|
3490
|
+
await nextTick();
|
|
3491
|
+
if (narrowVariant(fromRoot.value, discriminantKey, discriminantValue)) returnedRef.value = toRef(root).value;
|
|
3492
|
+
else returnedRef.value = void 0;
|
|
3493
|
+
}, {
|
|
3494
|
+
immediate: true,
|
|
3495
|
+
flush: "pre"
|
|
3569
3496
|
});
|
|
3497
|
+
return returnedRef;
|
|
3498
|
+
}
|
|
3499
|
+
|
|
3500
|
+
/**
|
|
3501
|
+
* Helper method to wrap an raw rules object
|
|
3502
|
+
*
|
|
3503
|
+
* Similar to:
|
|
3504
|
+
*
|
|
3505
|
+
* ```ts
|
|
3506
|
+
* const rules = {...} satisfies RegleUnknownRulesTree
|
|
3507
|
+
* ```
|
|
3508
|
+
*/
|
|
3509
|
+
function defineRules(rules) {
|
|
3510
|
+
return rules;
|
|
3511
|
+
}
|
|
3512
|
+
/**
|
|
3513
|
+
* Refine a raw rules object to set rules that depends on the state values.
|
|
3514
|
+
*
|
|
3515
|
+
* @example
|
|
3516
|
+
*
|
|
3517
|
+
* ```ts
|
|
3518
|
+
* const rules = refineRules({
|
|
3519
|
+
* password: { required, type: type<string>() },
|
|
3520
|
+
* }, (state) => {
|
|
3521
|
+
* return {
|
|
3522
|
+
* confirmPassword: { required, sameAs: sameAs(() => state.value.password)}
|
|
3523
|
+
* }
|
|
3524
|
+
* })
|
|
3525
|
+
* ```
|
|
3526
|
+
*/
|
|
3527
|
+
function refineRules(rules, refinement) {
|
|
3528
|
+
return (state) => merge({ ...rules }, refinement(state));
|
|
3570
3529
|
}
|
|
3571
3530
|
|
|
3572
|
-
|
|
3573
|
-
|
|
3574
|
-
const __USE_DEVTOOLS__ = process.env.NODE_ENV === "development";
|
|
3531
|
+
var version$1 = "1.11.0-beta.2";
|
|
3532
|
+
|
|
3575
3533
|
const regleSymbol = Symbol("regle");
|
|
3534
|
+
|
|
3576
3535
|
const RegleVuePlugin = { install(app) {
|
|
3577
|
-
app.provide(regleSymbol,
|
|
3578
|
-
if (typeof window !== "undefined" &&
|
|
3536
|
+
app.provide(regleSymbol, version$1);
|
|
3537
|
+
if (typeof window !== "undefined" && true) createDevtools(app);
|
|
3579
3538
|
} };
|
|
3580
3539
|
|
|
3581
|
-
|
|
3582
|
-
export { InternalRuleType, RegleVuePlugin, createRule, createScopedUseRegle, createVariant, defineRegleConfig, defineRules, extendRegleConfig, flatErrors, inferRules, mergeRegles, narrowVariant, refineRules, registerRegleInstance, unwrapRuleParameters, useCollectScope, useRegle, useRootStorage, useRules, useScopedRegle, variantToRef };
|
|
3540
|
+
export { InternalRuleType, RegleVuePlugin, createRule, createScopedUseRegle, createVariant, defineRegleConfig, defineRules, extendRegleConfig, flatErrors, inferRules, mergeRegles, narrowVariant, refineRules, unwrapRuleParameters, useCollectScope, useRegle, useRootStorage, useRules, useScopedRegle, variantToRef };
|