@regle/core 1.10.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 +14 -1335
- package/dist/regle-core.js +741 -176
- package/dist/regle-core.min.js +1 -1
- package/package.json +10 -12
package/dist/regle-core.js
CHANGED
|
@@ -1,6 +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
|
+
import { setupDevtoolsPlugin } from "@vue/devtools-api";
|
|
2
3
|
|
|
3
|
-
//#region ../shared/utils/isFile.ts
|
|
4
4
|
/**
|
|
5
5
|
* Server side friendly way of checking for a File
|
|
6
6
|
*/
|
|
@@ -8,8 +8,6 @@ function isFile(value) {
|
|
|
8
8
|
return value?.constructor?.name == "File" || value?.constructor?.name == "FileList";
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
//#endregion
|
|
12
|
-
//#region ../shared/utils/isEmpty.ts
|
|
13
11
|
/**
|
|
14
12
|
* This is the inverse of isFilled. It will check if the value is in any way empty (including arrays and objects)
|
|
15
13
|
*
|
|
@@ -29,12 +27,8 @@ function isEmpty(value, considerEmptyArrayInvalid = true) {
|
|
|
29
27
|
return !String(value).length;
|
|
30
28
|
}
|
|
31
29
|
|
|
32
|
-
//#endregion
|
|
33
|
-
//#region ../shared/utils/symbol.ts
|
|
34
30
|
const RegleRuleSymbol = Symbol("regle-rule");
|
|
35
31
|
|
|
36
|
-
//#endregion
|
|
37
|
-
//#region ../shared/utils/cloneDeep.ts
|
|
38
32
|
function getRegExpFlags(regExp) {
|
|
39
33
|
if (typeof regExp.source.flags == "string") return regExp.source.flags;
|
|
40
34
|
else {
|
|
@@ -61,8 +55,6 @@ function cloneDeep(obj) {
|
|
|
61
55
|
return result;
|
|
62
56
|
}
|
|
63
57
|
|
|
64
|
-
//#endregion
|
|
65
|
-
//#region ../shared/utils/object.utils.ts
|
|
66
58
|
function isObject(obj) {
|
|
67
59
|
if (obj && (obj instanceof Date || obj.constructor.name == "File" || obj.constructor.name == "FileList")) return false;
|
|
68
60
|
return typeof obj === "object" && obj !== null && !Array.isArray(obj);
|
|
@@ -145,8 +137,6 @@ function dotPathObjectToNested(obj) {
|
|
|
145
137
|
return result;
|
|
146
138
|
}
|
|
147
139
|
|
|
148
|
-
//#endregion
|
|
149
|
-
//#region ../shared/utils/toDate.ts
|
|
150
140
|
/**
|
|
151
141
|
* This utility will coerce any string, number or Date value into a Date using the Date constructor.
|
|
152
142
|
*/
|
|
@@ -159,8 +149,6 @@ function toDate(argument) {
|
|
|
159
149
|
else return /* @__PURE__ */ new Date(NaN);
|
|
160
150
|
}
|
|
161
151
|
|
|
162
|
-
//#endregion
|
|
163
|
-
//#region ../shared/utils/debounce.ts
|
|
164
152
|
function debounce(func, wait, { immediate = false, trackDebounceRef } = {}) {
|
|
165
153
|
let timeout;
|
|
166
154
|
const debouncedFn = (...args) => {
|
|
@@ -201,8 +189,6 @@ function debounce(func, wait, { immediate = false, trackDebounceRef } = {}) {
|
|
|
201
189
|
return debouncedFn;
|
|
202
190
|
}
|
|
203
191
|
|
|
204
|
-
//#endregion
|
|
205
|
-
//#region ../shared/utils/isEqual.ts
|
|
206
192
|
function isEqual(a, b, deep = false, firstDeep = true) {
|
|
207
193
|
if (a === b) return true;
|
|
208
194
|
if (a && b && typeof a == "object" && typeof b == "object") {
|
|
@@ -235,8 +221,6 @@ function isEqual(a, b, deep = false, firstDeep = true) {
|
|
|
235
221
|
return a !== a && b !== b;
|
|
236
222
|
}
|
|
237
223
|
|
|
238
|
-
//#endregion
|
|
239
|
-
//#region ../shared/utils/abortablePromise.ts
|
|
240
224
|
var AbortError = class extends Error {
|
|
241
225
|
constructor(message = "Promise was aborted") {
|
|
242
226
|
super(message);
|
|
@@ -278,15 +262,11 @@ function abortablePromise(input) {
|
|
|
278
262
|
};
|
|
279
263
|
}
|
|
280
264
|
|
|
281
|
-
//#endregion
|
|
282
|
-
//#region src/types/rules/rule.internal.types.ts
|
|
283
265
|
const InternalRuleType = {
|
|
284
266
|
Inline: "__inline",
|
|
285
267
|
Async: "__async"
|
|
286
268
|
};
|
|
287
269
|
|
|
288
|
-
//#endregion
|
|
289
|
-
//#region src/types/utils/groups.ts
|
|
290
270
|
function mergeBooleanGroupProperties(entries, property) {
|
|
291
271
|
return entries.some((entry) => {
|
|
292
272
|
if (!property) return false;
|
|
@@ -301,8 +281,6 @@ function mergeArrayGroupProperties(entries, property) {
|
|
|
301
281
|
}, []);
|
|
302
282
|
}
|
|
303
283
|
|
|
304
|
-
//#endregion
|
|
305
|
-
//#region src/core/createRule/unwrapRuleParameters.ts
|
|
306
284
|
/**
|
|
307
285
|
* Returns a clean list of parameters
|
|
308
286
|
* Removing Ref and executing function to return the unwrapped value
|
|
@@ -334,8 +312,6 @@ function getFunctionParametersLength(func) {
|
|
|
334
312
|
return (paramsMatch[0] || paramsMatch[1] || paramsMatch[2] || paramsMatch[3] || paramsMatch[4] || "").split(",").map((p) => p.trim()).filter((p) => p.length > 0).length;
|
|
335
313
|
}
|
|
336
314
|
|
|
337
|
-
//#endregion
|
|
338
|
-
//#region src/core/createRule/defineRuleProcessors.ts
|
|
339
315
|
function defineRuleProcessors(definition, ...params) {
|
|
340
316
|
const { validator, type, async } = definition;
|
|
341
317
|
const isAsync = async || type === InternalRuleType.Async || validator.constructor.name === "AsyncFunction";
|
|
@@ -392,8 +368,6 @@ function defineRuleProcessors(definition, ...params) {
|
|
|
392
368
|
});
|
|
393
369
|
}
|
|
394
370
|
|
|
395
|
-
//#endregion
|
|
396
|
-
//#region src/core/createRule/createRule.ts
|
|
397
371
|
/**
|
|
398
372
|
* Create a typed custom rule that can be used like default rules.
|
|
399
373
|
* It can also be declared in the global options
|
|
@@ -457,8 +431,98 @@ function createRule(definition) {
|
|
|
457
431
|
throw new Error("[createRule] validator must be a function");
|
|
458
432
|
}
|
|
459
433
|
|
|
460
|
-
|
|
461
|
-
|
|
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
|
+
|
|
462
526
|
/**
|
|
463
527
|
* Inspired by Vuelidate storage
|
|
464
528
|
*/
|
|
@@ -522,9 +586,10 @@ function useStorage() {
|
|
|
522
586
|
if (!storedRuleElement || !newRuleElement || typeof newRuleElement === "function" || typeof storedRuleElement === "function") return false;
|
|
523
587
|
if (typeof newRuleElement === "number") return false;
|
|
524
588
|
else if (typeof newRuleElement === "boolean") return false;
|
|
589
|
+
else if (typeof newRuleElement === "string") return false;
|
|
525
590
|
else if (!newRuleElement._params) return true;
|
|
526
591
|
else return newRuleElement._params?.every((paramKey, index) => {
|
|
527
|
-
if (typeof storedRuleElement === "number" || typeof storedRuleElement === "boolean") return true;
|
|
592
|
+
if (typeof storedRuleElement === "number" || typeof storedRuleElement === "boolean" || typeof storedRuleElement === "string") return true;
|
|
528
593
|
else {
|
|
529
594
|
const storedParams = unwrapRuleParameters(storedRuleElement._params);
|
|
530
595
|
const newParams = unwrapRuleParameters(newRuleElement._params);
|
|
@@ -578,108 +643,6 @@ function useStorage() {
|
|
|
578
643
|
};
|
|
579
644
|
}
|
|
580
645
|
|
|
581
|
-
//#endregion
|
|
582
|
-
//#region src/utils/object.utils.ts
|
|
583
|
-
/**
|
|
584
|
-
* Checks if a Vue Ref is an object.
|
|
585
|
-
*
|
|
586
|
-
* @param obj - The Ref to check
|
|
587
|
-
* @returns True if the Ref is an object, false otherwise
|
|
588
|
-
*/
|
|
589
|
-
function isRefObject(obj) {
|
|
590
|
-
return isObject(obj.value);
|
|
591
|
-
}
|
|
592
|
-
/**
|
|
593
|
-
* Unwraps a collection ($each) getter function or returns the getter directly if it's not a function.
|
|
594
|
-
*
|
|
595
|
-
* @template T - The type of the getter function or the getter value
|
|
596
|
-
* @param getter - The getter function or value to unwrap
|
|
597
|
-
* @param value - The value to pass to the getter
|
|
598
|
-
* @param index - The index to pass to the getter
|
|
599
|
-
* @returns An object containing the scope and the unwrapped value
|
|
600
|
-
*/
|
|
601
|
-
function unwrapGetter(getter, value, index) {
|
|
602
|
-
const scope = effectScope();
|
|
603
|
-
let unwrapped;
|
|
604
|
-
if (getter instanceof Function) unwrapped = scope.run(() => getter(value, index ?? 0));
|
|
605
|
-
else unwrapped = getter;
|
|
606
|
-
return {
|
|
607
|
-
scope,
|
|
608
|
-
unwrapped
|
|
609
|
-
};
|
|
610
|
-
}
|
|
611
|
-
|
|
612
|
-
//#endregion
|
|
613
|
-
//#region src/utils/version-compare.ts
|
|
614
|
-
const VersionIs = {
|
|
615
|
-
LessThan: -1,
|
|
616
|
-
EqualTo: 0,
|
|
617
|
-
GreaterThan: 1
|
|
618
|
-
};
|
|
619
|
-
/**
|
|
620
|
-
* Compare two versions quickly.
|
|
621
|
-
* @param current Is this version greater, equal to, or less than the other?
|
|
622
|
-
* @param other The version to compare against the current version
|
|
623
|
-
* @return 1 if current is greater than other, 0 if they are equal or equivalent, and -1 if current is less than other
|
|
624
|
-
*/
|
|
625
|
-
function versionCompare(current, other) {
|
|
626
|
-
const cp = String(current).split(".");
|
|
627
|
-
const op = String(other).split(".");
|
|
628
|
-
for (let depth = 0; depth < Math.min(cp.length, op.length); depth++) {
|
|
629
|
-
const cn = Number(cp[depth]);
|
|
630
|
-
const on = Number(op[depth]);
|
|
631
|
-
if (cn > on) return VersionIs.GreaterThan;
|
|
632
|
-
if (on > cn) return VersionIs.LessThan;
|
|
633
|
-
if (!isNaN(cn) && isNaN(on)) return VersionIs.GreaterThan;
|
|
634
|
-
if (isNaN(cn) && !isNaN(on)) return VersionIs.LessThan;
|
|
635
|
-
}
|
|
636
|
-
return VersionIs.EqualTo;
|
|
637
|
-
}
|
|
638
|
-
const isVueSuperiorOrEqualTo3dotFive = versionCompare(version, "3.5.0") === -1 ? false : true;
|
|
639
|
-
|
|
640
|
-
//#endregion
|
|
641
|
-
//#region src/utils/randomId.ts
|
|
642
|
-
function uniqueIDNuxt() {
|
|
643
|
-
return Math.floor(Math.random() * Date.now()).toString();
|
|
644
|
-
}
|
|
645
|
-
/**
|
|
646
|
-
* Generates a random SSR compatible ID.
|
|
647
|
-
*/
|
|
648
|
-
function randomId() {
|
|
649
|
-
if (typeof window === "undefined") return uniqueIDNuxt();
|
|
650
|
-
else return window.crypto.getRandomValues(new Uint32Array(1))[0].toString(10);
|
|
651
|
-
}
|
|
652
|
-
|
|
653
|
-
//#endregion
|
|
654
|
-
//#region src/utils/state.utils.ts
|
|
655
|
-
function tryOnScopeDispose(fn) {
|
|
656
|
-
if (getCurrentScope()) {
|
|
657
|
-
onScopeDispose(fn);
|
|
658
|
-
return true;
|
|
659
|
-
}
|
|
660
|
-
return false;
|
|
661
|
-
}
|
|
662
|
-
/**
|
|
663
|
-
* Creates a global state that is shared for scoped validation.
|
|
664
|
-
*
|
|
665
|
-
* @param stateFactory - The function that creates the state
|
|
666
|
-
* @returns The state factory function
|
|
667
|
-
*/
|
|
668
|
-
function createGlobalState(stateFactory) {
|
|
669
|
-
let initialized = false;
|
|
670
|
-
let state;
|
|
671
|
-
const scope = effectScope(true);
|
|
672
|
-
return ((...args) => {
|
|
673
|
-
if (!initialized) {
|
|
674
|
-
state = scope.run(() => stateFactory(...args));
|
|
675
|
-
initialized = true;
|
|
676
|
-
}
|
|
677
|
-
return state;
|
|
678
|
-
});
|
|
679
|
-
}
|
|
680
|
-
|
|
681
|
-
//#endregion
|
|
682
|
-
//#region src/core/useRegle/guards/ruleDef.guards.ts
|
|
683
646
|
function isNestedRulesDef(state, rules) {
|
|
684
647
|
return isRefObject(state) || isObject(rules.value) && !isEmpty(rules.value) && !Object.entries(rules.value).some(([_, rule]) => isRuleDef(rule) || typeof rule === "function");
|
|
685
648
|
}
|
|
@@ -700,17 +663,16 @@ function isFormRuleDefinition(rule) {
|
|
|
700
663
|
return true;
|
|
701
664
|
}
|
|
702
665
|
|
|
703
|
-
//#endregion
|
|
704
|
-
//#region src/core/useRegle/guards/rule.status.guards.ts
|
|
705
666
|
function isNestedRulesStatus(rule) {
|
|
706
667
|
return isObject(rule) && "$fields" in rule;
|
|
707
668
|
}
|
|
669
|
+
function isCollectionRulesStatus(rule) {
|
|
670
|
+
return !!rule && "$each" in rule;
|
|
671
|
+
}
|
|
708
672
|
function isFieldStatus(rule) {
|
|
709
673
|
return !!rule && "$rules" in rule;
|
|
710
674
|
}
|
|
711
675
|
|
|
712
|
-
//#endregion
|
|
713
|
-
//#region src/core/useRegle/useErrors.ts
|
|
714
676
|
function extractRulesIssues({ field, silent = false }) {
|
|
715
677
|
const ruleIssues = Object.entries(field.$rules ?? {}).map(([key, rule]) => {
|
|
716
678
|
let message = "";
|
|
@@ -789,8 +751,6 @@ function iterateErrors(errors, includePath = false, _path) {
|
|
|
789
751
|
} else return Object.entries(errors).map(([key, value]) => iterateErrors(value, includePath, path?.concat(key))).flat();
|
|
790
752
|
}
|
|
791
753
|
|
|
792
|
-
//#endregion
|
|
793
|
-
//#region src/core/useRegle/root/createReactiveRuleStatus.ts
|
|
794
754
|
function createReactiveRuleStatus({ customMessages, rule, ruleKey, state, path, cachePath, storage, modifiers }) {
|
|
795
755
|
let scope = effectScope();
|
|
796
756
|
let scopeState = {};
|
|
@@ -965,8 +925,6 @@ function createReactiveRuleStatus({ customMessages, rule, ruleKey, state, path,
|
|
|
965
925
|
});
|
|
966
926
|
}
|
|
967
927
|
|
|
968
|
-
//#endregion
|
|
969
|
-
//#region src/core/useRegle/root/standard-schemas.ts
|
|
970
928
|
function createStandardSchema(validateFn) {
|
|
971
929
|
return { "~standard": {
|
|
972
930
|
version: 1,
|
|
@@ -982,8 +940,6 @@ function createStandardSchema(validateFn) {
|
|
|
982
940
|
} };
|
|
983
941
|
}
|
|
984
942
|
|
|
985
|
-
//#endregion
|
|
986
|
-
//#region src/core/useRegle/root/createReactiveFieldStatus.ts
|
|
987
943
|
function createReactiveFieldStatus({ state, rulesDef, customMessages, path, cachePath, fieldName, storage, options, externalErrors, schemaErrors, schemaMode, onUnwatch, $isArray, initialState, originalState, shortcuts, onValidate }) {
|
|
988
944
|
let scope = effectScope();
|
|
989
945
|
let scopeState;
|
|
@@ -1413,8 +1369,6 @@ function createReactiveFieldStatus({ state, rulesDef, customMessages, path, cach
|
|
|
1413
1369
|
});
|
|
1414
1370
|
}
|
|
1415
1371
|
|
|
1416
|
-
//#endregion
|
|
1417
|
-
//#region src/core/useRegle/root/collections/createReactiveCollectionElement.ts
|
|
1418
1372
|
function createCollectionElement({ $id, path, cachePath, index, options, storage, stateValue, customMessages, rules, externalErrors, schemaErrors, initialState, originalState, shortcuts, fieldName, schemaMode }) {
|
|
1419
1373
|
const $fieldId = stateValue.value?.$id ?? rules.$key ?? randomId();
|
|
1420
1374
|
let $cachePath = `${cachePath}.${String($fieldId)}`;
|
|
@@ -1453,8 +1407,6 @@ function createCollectionElement({ $id, path, cachePath, index, options, storage
|
|
|
1453
1407
|
return $status;
|
|
1454
1408
|
}
|
|
1455
1409
|
|
|
1456
|
-
//#endregion
|
|
1457
|
-
//#region src/core/useRegle/root/collections/createReactiveCollectionRoot.ts
|
|
1458
1410
|
function createReactiveCollectionStatus({ state, rulesDef, customMessages, path, storage, options, externalErrors, schemaErrors, schemaMode, initialState, originalState, shortcuts, fieldName }) {
|
|
1459
1411
|
let scope = effectScope();
|
|
1460
1412
|
let scopeState;
|
|
@@ -1861,8 +1813,6 @@ function createReactiveCollectionStatus({ state, rulesDef, customMessages, path,
|
|
|
1861
1813
|
});
|
|
1862
1814
|
}
|
|
1863
1815
|
|
|
1864
|
-
//#endregion
|
|
1865
|
-
//#region src/core/useRegle/root/createReactiveNestedStatus.ts
|
|
1866
1816
|
function createReactiveNestedStatus({ rulesDef, state, path = "", cachePath, rootRules, externalErrors, schemaErrors, rootSchemaErrors, validationGroups, initialState, originalState, fieldName,...commonArgs }) {
|
|
1867
1817
|
let scope = effectScope();
|
|
1868
1818
|
let scopeState;
|
|
@@ -2105,6 +2055,16 @@ function createReactiveNestedStatus({ rulesDef, state, path = "", cachePath, roo
|
|
|
2105
2055
|
return false;
|
|
2106
2056
|
});
|
|
2107
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
|
+
});
|
|
2108
2068
|
function processShortcuts() {
|
|
2109
2069
|
if (commonArgs.shortcuts?.nested) Object.entries(commonArgs.shortcuts.nested).forEach(([key, value]) => {
|
|
2110
2070
|
const scope$1 = effectScope();
|
|
@@ -2130,7 +2090,8 @@ function createReactiveNestedStatus({ rulesDef, state, path = "", cachePath, roo
|
|
|
2130
2090
|
$fields,
|
|
2131
2091
|
$edited,
|
|
2132
2092
|
$anyEdited,
|
|
2133
|
-
$issues
|
|
2093
|
+
$issues,
|
|
2094
|
+
"~modifiers": unref(commonArgs.options)
|
|
2134
2095
|
}));
|
|
2135
2096
|
});
|
|
2136
2097
|
return result;
|
|
@@ -2179,7 +2140,8 @@ function createReactiveNestedStatus({ rulesDef, state, path = "", cachePath, roo
|
|
|
2179
2140
|
$localPending,
|
|
2180
2141
|
$autoDirty,
|
|
2181
2142
|
$silent,
|
|
2182
|
-
$value
|
|
2143
|
+
$value,
|
|
2144
|
+
$modifiers
|
|
2183
2145
|
};
|
|
2184
2146
|
});
|
|
2185
2147
|
}
|
|
@@ -2286,6 +2248,7 @@ function createReactiveNestedStatus({ rulesDef, state, path = "", cachePath, roo
|
|
|
2286
2248
|
$clearExternalErrors,
|
|
2287
2249
|
$extractDirtyFields,
|
|
2288
2250
|
$abort,
|
|
2251
|
+
...!!rootRules ? { "~modifiers": scopeState.$modifiers } : {},
|
|
2289
2252
|
...createStandardSchema($validate)
|
|
2290
2253
|
});
|
|
2291
2254
|
watchEffect(() => {
|
|
@@ -2330,8 +2293,623 @@ function createReactiveChildrenStatus({ rulesDef,...properties }) {
|
|
|
2330
2293
|
});
|
|
2331
2294
|
}
|
|
2332
2295
|
|
|
2333
|
-
|
|
2334
|
-
|
|
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
|
|
2328
|
+
}
|
|
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
|
+
};
|
|
2352
|
+
|
|
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, {
|
|
2362
|
+
id,
|
|
2363
|
+
name,
|
|
2364
|
+
r$,
|
|
2365
|
+
componentName: options?.componentName ? `<${options.componentName}>` : void 0
|
|
2366
|
+
});
|
|
2367
|
+
notifyDevtools();
|
|
2368
|
+
return id;
|
|
2369
|
+
}
|
|
2370
|
+
function unregister(id) {
|
|
2371
|
+
instances.value.delete(id);
|
|
2372
|
+
const watcher = watchers.value.get(id);
|
|
2373
|
+
if (watcher) {
|
|
2374
|
+
watcher();
|
|
2375
|
+
watchers.value.delete(id);
|
|
2376
|
+
}
|
|
2377
|
+
notifyDevtools();
|
|
2378
|
+
}
|
|
2379
|
+
function getAll() {
|
|
2380
|
+
return Array.from(instances.value.values());
|
|
2381
|
+
}
|
|
2382
|
+
function get(id) {
|
|
2383
|
+
return instances.value.get(id);
|
|
2384
|
+
}
|
|
2385
|
+
function clear() {
|
|
2386
|
+
watchers.value.forEach((stop) => stop());
|
|
2387
|
+
watchers.value.clear();
|
|
2388
|
+
instances.value.clear();
|
|
2389
|
+
notifyDevtools();
|
|
2390
|
+
}
|
|
2391
|
+
function onInstancesChange(callback) {
|
|
2392
|
+
notifyCallbacks.value.add(callback);
|
|
2393
|
+
return () => {
|
|
2394
|
+
notifyCallbacks.value.delete(callback);
|
|
2395
|
+
};
|
|
2396
|
+
}
|
|
2397
|
+
function addWatcher(id, stopHandle) {
|
|
2398
|
+
watchers.value.set(id, stopHandle);
|
|
2399
|
+
}
|
|
2400
|
+
function notifyDevtools() {
|
|
2401
|
+
notifyCallbacks.value.forEach((callback) => callback());
|
|
2402
|
+
}
|
|
2403
|
+
return {
|
|
2404
|
+
register,
|
|
2405
|
+
unregister,
|
|
2406
|
+
getAll,
|
|
2407
|
+
get,
|
|
2408
|
+
clear,
|
|
2409
|
+
onInstancesChange,
|
|
2410
|
+
addWatcher
|
|
2411
|
+
};
|
|
2412
|
+
}
|
|
2413
|
+
const regleDevtoolsRegistry = useRegleDevtoolsRegistry();
|
|
2414
|
+
function registerRegleInstance(r$, options) {
|
|
2415
|
+
if (typeof window === "undefined") return;
|
|
2416
|
+
const instance = getCurrentInstance();
|
|
2417
|
+
const componentName = instance?.type?.name || instance?.type?.__name;
|
|
2418
|
+
const id = regleDevtoolsRegistry.register(r$, {
|
|
2419
|
+
name: options?.name,
|
|
2420
|
+
componentName,
|
|
2421
|
+
uid: instance?.uid
|
|
2422
|
+
});
|
|
2423
|
+
tryOnScopeDispose(() => {
|
|
2424
|
+
regleDevtoolsRegistry.unregister(id);
|
|
2425
|
+
});
|
|
2426
|
+
}
|
|
2427
|
+
function watchRegleInstance(id, r$, onChange) {
|
|
2428
|
+
const stopHandle = watch(() => r$, onChange, {
|
|
2429
|
+
deep: true,
|
|
2430
|
+
flush: "post"
|
|
2431
|
+
});
|
|
2432
|
+
regleDevtoolsRegistry.addWatcher(id, stopHandle);
|
|
2433
|
+
return stopHandle;
|
|
2434
|
+
}
|
|
2435
|
+
|
|
2436
|
+
function isMethod(value) {
|
|
2437
|
+
return typeof value === "function";
|
|
2438
|
+
}
|
|
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
|
+
});
|
|
2449
|
+
}
|
|
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
|
+
}));
|
|
2456
|
+
}
|
|
2457
|
+
function parseFieldNodeId(nodeId) {
|
|
2458
|
+
if (!nodeId.includes(":field:")) return null;
|
|
2459
|
+
const [instanceId, , fieldName] = nodeId.split(":");
|
|
2460
|
+
return {
|
|
2461
|
+
instanceId,
|
|
2462
|
+
fieldName
|
|
2463
|
+
};
|
|
2464
|
+
}
|
|
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
|
|
2479
|
+
};
|
|
2480
|
+
}
|
|
2481
|
+
function createRuleNodeId(instanceId, fieldName, ruleName) {
|
|
2482
|
+
return `${createFieldNodeId(instanceId, fieldName)}:rule:${ruleName}`;
|
|
2483
|
+
}
|
|
2484
|
+
|
|
2485
|
+
/**
|
|
2486
|
+
* Build state for a field node
|
|
2487
|
+
*/
|
|
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
|
+
}
|
|
2500
|
+
/**
|
|
2501
|
+
* Build state for a rule node
|
|
2502
|
+
*/
|
|
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;
|
|
2542
|
+
}
|
|
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$);
|
|
2596
|
+
}
|
|
2597
|
+
|
|
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();
|
|
2607
|
+
}
|
|
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 });
|
|
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
|
|
2654
|
+
});
|
|
2655
|
+
else if (fieldOrR$.$correct) tags.push({
|
|
2656
|
+
label: "correct",
|
|
2657
|
+
textColor: COLORS.VALID.text,
|
|
2658
|
+
backgroundColor: COLORS.VALID.bg
|
|
2659
|
+
});
|
|
2660
|
+
if (fieldOrR$.$pending) tags.push({
|
|
2661
|
+
label: "pending",
|
|
2662
|
+
textColor: COLORS.PENDING.text,
|
|
2663
|
+
backgroundColor: COLORS.PENDING.bg
|
|
2664
|
+
});
|
|
2665
|
+
if (fieldOrR$.$dirty) tags.push({
|
|
2666
|
+
label: "dirty",
|
|
2667
|
+
textColor: COLORS.DIRTY.text,
|
|
2668
|
+
backgroundColor: COLORS.DIRTY.bg
|
|
2669
|
+
});
|
|
2670
|
+
else if ("$rules" in fieldOrR$) tags.push({
|
|
2671
|
+
label: "pristine",
|
|
2672
|
+
textColor: COLORS.PRISTINE.text,
|
|
2673
|
+
backgroundColor: COLORS.PRISTINE.bg
|
|
2674
|
+
});
|
|
2675
|
+
if (componentName) tags.push({
|
|
2676
|
+
label: componentName,
|
|
2677
|
+
textColor: COLORS.COMPONENT.text,
|
|
2678
|
+
backgroundColor: COLORS.COMPONENT.bg
|
|
2679
|
+
});
|
|
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
|
|
2688
|
+
});
|
|
2689
|
+
else if (!rule.$valid) tags.push({
|
|
2690
|
+
label: "invalid",
|
|
2691
|
+
textColor: COLORS.INVALID.text,
|
|
2692
|
+
backgroundColor: COLORS.INVALID.bg
|
|
2693
|
+
});
|
|
2694
|
+
else if (rule.$valid) tags.push({
|
|
2695
|
+
label: "valid",
|
|
2696
|
+
textColor: COLORS.VALID.text,
|
|
2697
|
+
backgroundColor: COLORS.VALID.bg
|
|
2698
|
+
});
|
|
2699
|
+
if (rule.$pending) tags.push({
|
|
2700
|
+
label: "pending",
|
|
2701
|
+
textColor: COLORS.PENDING.text,
|
|
2702
|
+
backgroundColor: COLORS.PENDING.bg
|
|
2703
|
+
});
|
|
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
|
+
});
|
|
2718
|
+
}
|
|
2719
|
+
});
|
|
2720
|
+
return children;
|
|
2721
|
+
}
|
|
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
|
+
});
|
|
2738
|
+
}
|
|
2739
|
+
});
|
|
2740
|
+
return children;
|
|
2741
|
+
}
|
|
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
|
+
});
|
|
2758
|
+
}
|
|
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
|
+
});
|
|
2779
|
+
}
|
|
2780
|
+
});
|
|
2781
|
+
return children;
|
|
2782
|
+
}
|
|
2783
|
+
function buildInspectorTree(instances, filter) {
|
|
2784
|
+
const nodes = instances.map((instance) => {
|
|
2785
|
+
const { r$, id, name, componentName } = instance;
|
|
2786
|
+
return {
|
|
2787
|
+
id,
|
|
2788
|
+
label: name,
|
|
2789
|
+
tags: buildNodeTags(r$, componentName),
|
|
2790
|
+
children: buildRootChildrenNodes(r$, id)
|
|
2791
|
+
};
|
|
2792
|
+
});
|
|
2793
|
+
if (!filter || filter.trim() === "") return nodes;
|
|
2794
|
+
return filterInspectorTree(nodes, filter);
|
|
2795
|
+
}
|
|
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;
|
|
2809
|
+
}
|
|
2810
|
+
|
|
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);
|
|
2866
|
+
}
|
|
2867
|
+
});
|
|
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
|
+
});
|
|
2887
|
+
});
|
|
2888
|
+
}
|
|
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();
|
|
2910
|
+
});
|
|
2911
|
+
}
|
|
2912
|
+
|
|
2335
2913
|
function useRootStorage({ initialState, originalState, options, scopeRules, state, customRules, shortcuts, schemaErrors, schemaMode = false, onValidate }) {
|
|
2336
2914
|
const storage = useStorage();
|
|
2337
2915
|
const regle = ref();
|
|
@@ -2399,11 +2977,10 @@ function useRootStorage({ initialState, originalState, options, scopeRules, stat
|
|
|
2399
2977
|
$unwatchComputedExternalErrors?.();
|
|
2400
2978
|
$unwatchExternalErrors?.();
|
|
2401
2979
|
});
|
|
2980
|
+
if (typeof window !== "undefined" && regle.value) registerRegleInstance(regle.value, { name: toValue(options.id) });
|
|
2402
2981
|
return reactive({ regle });
|
|
2403
2982
|
}
|
|
2404
2983
|
|
|
2405
|
-
//#endregion
|
|
2406
|
-
//#region src/core/useRegle/shared.rootRegle.ts
|
|
2407
2984
|
function createRootRegleLogic({ state, rulesFactory, options, globalOptions, customRules, shortcuts }) {
|
|
2408
2985
|
const definedRules = isRef(rulesFactory) ? rulesFactory : typeof rulesFactory === "function" ? void 0 : computed(() => rulesFactory);
|
|
2409
2986
|
const resolvedOptions = {
|
|
@@ -2432,8 +3009,6 @@ function createRootRegleLogic({ state, rulesFactory, options, globalOptions, cus
|
|
|
2432
3009
|
});
|
|
2433
3010
|
}
|
|
2434
3011
|
|
|
2435
|
-
//#endregion
|
|
2436
|
-
//#region src/core/useRegle/useRegle.ts
|
|
2437
3012
|
function createUseRegleComposable(customRules, options, shortcuts) {
|
|
2438
3013
|
const globalOptions = {
|
|
2439
3014
|
autoDirty: options?.autoDirty,
|
|
@@ -2475,8 +3050,6 @@ email: { required }
|
|
|
2475
3050
|
*/
|
|
2476
3051
|
const useRegle = createUseRegleComposable();
|
|
2477
3052
|
|
|
2478
|
-
//#endregion
|
|
2479
|
-
//#region src/core/useRegle/inferRules.ts
|
|
2480
3053
|
function createInferRuleHelper() {
|
|
2481
3054
|
function inferRules$1(state, rulesFactory) {
|
|
2482
3055
|
return rulesFactory;
|
|
@@ -2492,8 +3065,6 @@ function createInferRuleHelper() {
|
|
|
2492
3065
|
*/
|
|
2493
3066
|
const inferRules = createInferRuleHelper();
|
|
2494
3067
|
|
|
2495
|
-
//#endregion
|
|
2496
|
-
//#region src/core/useRegle/useRules.ts
|
|
2497
3068
|
function createEmptyRuleState(rules) {
|
|
2498
3069
|
const result = {};
|
|
2499
3070
|
if (Object.entries(rules).some(([_, rule]) => isRuleDef(rule) || typeof rule === "function")) return null;
|
|
@@ -2545,8 +3116,6 @@ email: { required }
|
|
|
2545
3116
|
*/
|
|
2546
3117
|
const useRules = createUseRulesComposable();
|
|
2547
3118
|
|
|
2548
|
-
//#endregion
|
|
2549
|
-
//#region src/core/defineRegleConfig.ts
|
|
2550
3119
|
/**
|
|
2551
3120
|
* Define a global regle configuration, where you can:
|
|
2552
3121
|
* - Customize built-in rules messages
|
|
@@ -2606,8 +3175,6 @@ function extendRegleConfig(regle, { rules, modifiers, shortcuts }) {
|
|
|
2606
3175
|
};
|
|
2607
3176
|
}
|
|
2608
3177
|
|
|
2609
|
-
//#endregion
|
|
2610
|
-
//#region src/core/mergeRegles.ts
|
|
2611
3178
|
function mergeRegles(regles, _scoped) {
|
|
2612
3179
|
const scoped = _scoped == null ? false : _scoped;
|
|
2613
3180
|
const $value = computed({
|
|
@@ -2779,8 +3346,6 @@ function mergeRegles(regles, _scoped) {
|
|
|
2779
3346
|
});
|
|
2780
3347
|
}
|
|
2781
3348
|
|
|
2782
|
-
//#endregion
|
|
2783
|
-
//#region src/core/createScopedUseRegle/useCollectScope.ts
|
|
2784
3349
|
function createUseCollectScope(instances, options) {
|
|
2785
3350
|
function useCollectScope$1(namespace) {
|
|
2786
3351
|
const computedNamespace = computed(() => toValue(namespace));
|
|
@@ -2803,8 +3368,6 @@ function createUseCollectScope(instances, options) {
|
|
|
2803
3368
|
return { useCollectScope: useCollectScope$1 };
|
|
2804
3369
|
}
|
|
2805
3370
|
|
|
2806
|
-
//#endregion
|
|
2807
|
-
//#region src/core/createScopedUseRegle/useScopedRegle.ts
|
|
2808
3371
|
function createUseScopedRegleComposable(instances, customUseRegle) {
|
|
2809
3372
|
const scopedUseRegle = customUseRegle ?? useRegle;
|
|
2810
3373
|
const useScopedRegle$1 = ((state, rulesFactory, options) => {
|
|
@@ -2852,8 +3415,6 @@ function createUseScopedRegleComposable(instances, customUseRegle) {
|
|
|
2852
3415
|
return { useScopedRegle: useScopedRegle$1 };
|
|
2853
3416
|
}
|
|
2854
3417
|
|
|
2855
|
-
//#endregion
|
|
2856
|
-
//#region src/core/createScopedUseRegle/createScopedUseRegle.ts
|
|
2857
3418
|
function createScopedUseRegle(options) {
|
|
2858
3419
|
const instances = (options?.customStore ? () => {
|
|
2859
3420
|
if (options.customStore) {
|
|
@@ -2873,8 +3434,6 @@ function createScopedUseRegle(options) {
|
|
|
2873
3434
|
}
|
|
2874
3435
|
const { useCollectScope, useScopedRegle } = createScopedUseRegle();
|
|
2875
3436
|
|
|
2876
|
-
//#endregion
|
|
2877
|
-
//#region src/core/variants/createVariant.ts
|
|
2878
3437
|
/**
|
|
2879
3438
|
* Declare variations of state that depends on one value
|
|
2880
3439
|
*
|
|
@@ -2938,8 +3497,6 @@ function variantToRef(root, discriminantKey, discriminantValue, _options) {
|
|
|
2938
3497
|
return returnedRef;
|
|
2939
3498
|
}
|
|
2940
3499
|
|
|
2941
|
-
//#endregion
|
|
2942
|
-
//#region src/core/refineRules.ts
|
|
2943
3500
|
/**
|
|
2944
3501
|
* Helper method to wrap an raw rules object
|
|
2945
3502
|
*
|
|
@@ -2971,5 +3528,13 @@ function refineRules(rules, refinement) {
|
|
|
2971
3528
|
return (state) => merge({ ...rules }, refinement(state));
|
|
2972
3529
|
}
|
|
2973
3530
|
|
|
2974
|
-
|
|
2975
|
-
|
|
3531
|
+
var version$1 = "1.11.0-beta.2";
|
|
3532
|
+
|
|
3533
|
+
const regleSymbol = Symbol("regle");
|
|
3534
|
+
|
|
3535
|
+
const RegleVuePlugin = { install(app) {
|
|
3536
|
+
app.provide(regleSymbol, version$1);
|
|
3537
|
+
if (typeof window !== "undefined" && true) createDevtools(app);
|
|
3538
|
+
} };
|
|
3539
|
+
|
|
3540
|
+
export { InternalRuleType, RegleVuePlugin, createRule, createScopedUseRegle, createVariant, defineRegleConfig, defineRules, extendRegleConfig, flatErrors, inferRules, mergeRegles, narrowVariant, refineRules, unwrapRuleParameters, useCollectScope, useRegle, useRootStorage, useRules, useScopedRegle, variantToRef };
|