@regle/core 0.0.3 → 0.0.5-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/core/createRule/unwrapRuleParameters.ts
2
- import { unref } from "vue";
2
+ import { isRef, toRef, unref } from "vue";
3
3
  function unwrapRuleParameters(params) {
4
4
  return params.map((param) => {
5
5
  if (param instanceof Function) {
@@ -8,33 +8,35 @@ function unwrapRuleParameters(params) {
8
8
  return unref(param);
9
9
  });
10
10
  }
11
+ function createReactiveParams(params) {
12
+ return params.map((param) => {
13
+ if (param instanceof Function) {
14
+ return param;
15
+ } else if (isRef(param)) {
16
+ return param;
17
+ }
18
+ return toRef(() => param);
19
+ });
20
+ }
11
21
 
12
22
  // src/core/createRule/defineRuleProcessors.ts
13
23
  function defineRuleProcessors(definition, ...params) {
14
24
  const { message, validator, active, ...properties } = definition;
25
+ const isAsync = validator.constructor.name === "AsyncFunction";
15
26
  const processors = {
16
27
  message(value, ...args) {
17
28
  if (typeof definition.message === "function") {
18
- return definition.message(
19
- value,
20
- ...unwrapRuleParameters(args.length ? args : params)
21
- );
29
+ return definition.message(value, ...args.length ? args : params);
22
30
  } else {
23
31
  return definition.message;
24
32
  }
25
33
  },
26
34
  validator(value, ...args) {
27
- return definition.validator(
28
- value,
29
- ...unwrapRuleParameters(args.length ? args : params)
30
- );
35
+ return definition.validator(value, ...args.length ? args : params);
31
36
  },
32
37
  active(value, ...args) {
33
38
  if (typeof definition.active === "function") {
34
- return definition.active(
35
- value,
36
- ...unwrapRuleParameters(args.length ? args : params)
37
- );
39
+ return definition.active(value, ...args.length ? args : params);
38
40
  } else {
39
41
  return definition.active ?? true;
40
42
  }
@@ -46,7 +48,8 @@ function defineRuleProcessors(definition, ...params) {
46
48
  _active: definition.active,
47
49
  _type: definition.type,
48
50
  _patched: false,
49
- _params: params
51
+ _async: isAsync,
52
+ _params: createReactiveParams(params)
50
53
  }
51
54
  };
52
55
  return processors;
@@ -57,6 +60,7 @@ function createRule(definition) {
57
60
  if (typeof definition.validator === "function") {
58
61
  let fakeParams = [];
59
62
  const staticProcessors = defineRuleProcessors(definition, ...fakeParams);
63
+ const isAsync = definition.validator.constructor.name === "AsyncFunction";
60
64
  if (definition.validator.length > 1) {
61
65
  const ruleFactory = function(...params) {
62
66
  return defineRuleProcessors(definition, ...params);
@@ -70,6 +74,7 @@ function createRule(definition) {
70
74
  ruleFactory._active = definition.active;
71
75
  ruleFactory._type = definition.type;
72
76
  ruleFactory._patched = false;
77
+ ruleFactory._async = isAsync;
73
78
  return ruleFactory;
74
79
  } else {
75
80
  return staticProcessors;
@@ -79,18 +84,21 @@ function createRule(definition) {
79
84
  }
80
85
 
81
86
  // src/core/useRegle/useRegle.ts
82
- import { computed as computed4, isRef, shallowRef, toRaw } from "vue";
87
+ import { computed as computed5, isRef as isRef2, shallowRef as shallowRef2, toRaw } from "vue";
83
88
 
84
89
  // src/core/useRegle/useStateProperties/useStateProperties.ts
85
- import { ref as ref3 } from "vue";
90
+ import { reactive as reactive5 } from "vue";
86
91
 
87
- // src/core/useRegle/useStateProperties/createReactiveStatus.ts
88
- import { computed as computed2, reactive as reactive2, ref as ref2, toRef, toRefs, watch as watch2 } from "vue";
92
+ // src/core/useRegle/useErrors.ts
93
+ import { computed } from "vue";
89
94
 
90
95
  // src/utils/object.utils.ts
91
96
  function isObject(obj) {
92
97
  return typeof obj === "object" && obj !== null && !Array.isArray(obj);
93
98
  }
99
+ function isRefObject(obj) {
100
+ return isObject(obj.value);
101
+ }
94
102
 
95
103
  // src/utils/isEmpty.ts
96
104
  function isEmpty(value) {
@@ -115,6 +123,9 @@ function isEmpty(value) {
115
123
  return !String(value).trim().length;
116
124
  }
117
125
 
126
+ // src/utils/composables.ts
127
+ import { effectScope, getCurrentScope, onScopeDispose } from "vue";
128
+
118
129
  // src/core/useRegle/guards/ruleDef.guards.ts
119
130
  function isNestedRulesDef(state, rule) {
120
131
  return isObject(state.value) && isObject(rule.value) && !Object.entries(rule.value).some((rule2) => isRuleDef(rule2));
@@ -131,9 +142,6 @@ function isRuleDef(rule) {
131
142
  function isFormRuleDefinition(rule) {
132
143
  return !(typeof rule.value === "function");
133
144
  }
134
- function isFormInline(rule) {
135
- return typeof rule.value === "function";
136
- }
137
145
 
138
146
  // src/core/useRegle/guards/rule.status.guards.ts
139
147
  function isNestedRulesStatus(rule) {
@@ -146,8 +154,77 @@ function isFieldStatus(rule) {
146
154
  return !!rule && "$rules" in rule;
147
155
  }
148
156
 
157
+ // src/core/useRegle/useErrors.ts
158
+ function extractRulesErrors(rules) {
159
+ return Object.entries(rules).map(([ruleKey, rule]) => {
160
+ if (!rule.$valid) {
161
+ return rule.$message;
162
+ }
163
+ return null;
164
+ }).filter((msg) => !!msg);
165
+ }
166
+ function processFieldErrors(fieldStatus) {
167
+ if (isNestedRulesStatus(fieldStatus)) {
168
+ return extractNestedErrors(fieldStatus.$fields);
169
+ } else if (isCollectionRulesStatus(fieldStatus)) {
170
+ return {
171
+ $errors: fieldStatus.$rules ? extractRulesErrors(fieldStatus.$rules) : [],
172
+ $each: fieldStatus.$each.map(processFieldErrors)
173
+ };
174
+ } else if (isFieldStatus(fieldStatus) && fieldStatus.$error) {
175
+ return extractRulesErrors(fieldStatus.$rules);
176
+ }
177
+ return [];
178
+ }
179
+ function extractCollectionError(field) {
180
+ return field.$each.map(processFieldErrors);
181
+ }
182
+ function extractNestedErrors(fields) {
183
+ return Object.fromEntries(
184
+ Object.entries(fields).map(([fieldKey, fieldStatus]) => {
185
+ if (isNestedRulesStatus(fieldStatus)) {
186
+ return [fieldKey, extractNestedErrors(fieldStatus.$fields)];
187
+ } else if (isCollectionRulesStatus(fieldStatus)) {
188
+ return [
189
+ fieldKey,
190
+ {
191
+ ...fieldStatus.$rules && { $errors: extractRulesErrors(fieldStatus.$rules) },
192
+ $each: extractCollectionError(fieldStatus)
193
+ }
194
+ ];
195
+ } else if (isFieldStatus(fieldStatus) && fieldStatus.$error) {
196
+ return [fieldKey, extractRulesErrors(fieldStatus.$rules)];
197
+ }
198
+ return [fieldKey, []];
199
+ })
200
+ );
201
+ }
202
+ function useErrors($regle) {
203
+ const errors = computed(() => {
204
+ return extractNestedErrors($regle.$fields);
205
+ });
206
+ return errors;
207
+ }
208
+
209
+ // src/core/useRegle/useStateProperties/createReactiveNestedStatus.ts
210
+ import { computed as computed4, effectScope as effectScope4, reactive as reactive4, toRef as toRef4, watch as watch4 } from "vue";
211
+
212
+ // src/core/useRegle/useStateProperties/createReactiveCollectionStatus.ts
213
+ import { reactive as reactive3, ref as ref3, toRef as toRef3, toRefs, watch as watch3 } from "vue";
214
+
215
+ // src/core/useRegle/useStateProperties/createReactiveFieldStatus.ts
216
+ import {
217
+ computed as computed3,
218
+ effectScope as effectScope3,
219
+ reactive as reactive2,
220
+ ref as ref2,
221
+ toRef as toRef2,
222
+ unref as unref2,
223
+ watch as watch2
224
+ } from "vue";
225
+
149
226
  // src/core/useRegle/useStateProperties/createReactiveRuleStatus.ts
150
- import { computed, reactive, ref, watch } from "vue";
227
+ import { computed as computed2, effectScope as effectScope2, reactive, watch } from "vue";
151
228
 
152
229
  // src/types/rules/rule.internal.types.ts
153
230
  var InternalRuleType = /* @__PURE__ */ ((InternalRuleType2) => {
@@ -162,343 +239,799 @@ function createReactiveRuleStatus({
162
239
  customMessages,
163
240
  rule,
164
241
  ruleKey,
165
- state
242
+ state,
243
+ path,
244
+ storage,
245
+ options
166
246
  }) {
167
- const $pending = ref(false);
168
- const $valid = ref(true);
169
- const $active = computed(() => {
170
- if (isFormInline(rule)) {
171
- return true;
172
- } else {
173
- if (typeof rule.value.active === "function") {
174
- return rule.value.active(state.value, ...$params.value);
175
- } else {
176
- return rule.value.active;
247
+ let scope = effectScope2();
248
+ let scopeState;
249
+ const { $pending, $valid } = storage.trySetRuleStatusRef(`${path}.${ruleKey}`);
250
+ function $watch() {
251
+ scopeState = scope.run(() => {
252
+ const $active = computed2(() => {
253
+ if (isFormRuleDefinition(rule)) {
254
+ if (typeof rule.value.active === "function") {
255
+ return rule.value.active(state.value, ...$params.value);
256
+ } else {
257
+ return rule.value.active;
258
+ }
259
+ } else {
260
+ return true;
261
+ }
262
+ });
263
+ const $message = computed2(() => {
264
+ let message = "";
265
+ const customMessageRule = customMessages ? customMessages[ruleKey]?.message : void 0;
266
+ if (customMessageRule) {
267
+ if (typeof customMessageRule === "function") {
268
+ message = customMessageRule(state.value, ...$params.value);
269
+ } else {
270
+ message = customMessageRule;
271
+ }
272
+ }
273
+ if (isFormRuleDefinition(rule)) {
274
+ if (!(customMessageRule && !rule.value._patched)) {
275
+ if (typeof rule.value.message === "function") {
276
+ message = rule.value.message(state.value, ...$params.value);
277
+ } else {
278
+ message = rule.value.message;
279
+ }
280
+ }
281
+ }
282
+ if (isEmpty(message)) {
283
+ message = "Error";
284
+ console.warn(`No error message defined for ${ruleKey}`);
285
+ }
286
+ return message;
287
+ });
288
+ const $type = computed2(() => {
289
+ if (isFormRuleDefinition(rule)) {
290
+ return Object.values(InternalRuleType).includes(rule.value.type) ? ruleKey : rule.value.type;
291
+ } else {
292
+ return ruleKey;
293
+ }
294
+ });
295
+ const $validator = computed2(() => {
296
+ if (isFormRuleDefinition(rule)) {
297
+ return rule.value.validator;
298
+ } else {
299
+ return rule.value;
300
+ }
301
+ });
302
+ const $params = computed2(() => {
303
+ if (typeof rule.value === "function") {
304
+ return [];
305
+ }
306
+ return unwrapRuleParameters(rule.value._params ?? []);
307
+ });
308
+ const $path = computed2(() => `${path}.${$type.value}`);
309
+ return {
310
+ $active,
311
+ $message,
312
+ $type,
313
+ $validator,
314
+ $params,
315
+ $path
316
+ };
317
+ });
318
+ }
319
+ $watch();
320
+ const $unwatchState = watch(scopeState.$params, $validate, {
321
+ deep: true
322
+ });
323
+ async function $validate() {
324
+ const validator = scopeState.$validator.value;
325
+ let ruleResult = false;
326
+ const resultOrPromise = validator(state.value, ...scopeState.$params.value);
327
+ if (resultOrPromise instanceof Promise) {
328
+ if ($dirty.value && !$pending.value) {
329
+ try {
330
+ $valid.value = true;
331
+ $pending.value = true;
332
+ const promiseResult = await resultOrPromise;
333
+ ruleResult = promiseResult;
334
+ } catch (e) {
335
+ ruleResult = false;
336
+ } finally {
337
+ $pending.value = false;
338
+ }
177
339
  }
340
+ } else {
341
+ ruleResult = resultOrPromise;
178
342
  }
343
+ $valid.value = ruleResult;
344
+ return ruleResult;
345
+ }
346
+ function $unwatch() {
347
+ $unwatchState();
348
+ scope.stop();
349
+ scope = effectScope2();
350
+ }
351
+ return reactive({
352
+ ...scopeState,
353
+ $pending,
354
+ $valid,
355
+ $validate,
356
+ $unwatch,
357
+ $watch
179
358
  });
180
- const $message = computed(() => {
181
- let message = "";
182
- const customMessageRule = customMessages[ruleKey]?.message;
183
- if (customMessageRule) {
184
- if (typeof customMessageRule === "function") {
185
- message = customMessageRule(state.value, ...$params.value);
186
- } else {
187
- message = customMessageRule;
359
+ }
360
+
361
+ // src/core/useRegle/useStateProperties/createReactiveFieldStatus.ts
362
+ function createReactiveFieldStatus({
363
+ state,
364
+ rulesDef,
365
+ customMessages,
366
+ path,
367
+ storage,
368
+ options
369
+ }) {
370
+ let scope = effectScope3();
371
+ let scopeState;
372
+ const $dirty = ref2(false);
373
+ const $anyDirty = computed3(() => $dirty.value);
374
+ const triggerPunishment = ref2(false);
375
+ function createReactiveRulesResult() {
376
+ const declaredRules = rulesDef.value;
377
+ const storeResult = storage.checkRuleDeclEntry(path, declaredRules);
378
+ $rules.value = Object.fromEntries(
379
+ Object.entries(declaredRules).map(([ruleKey, rule]) => {
380
+ if (rule) {
381
+ const ruleRef = toRef2(() => rule);
382
+ return [
383
+ ruleKey,
384
+ createReactiveRuleStatus({
385
+ $dirty,
386
+ customMessages,
387
+ rule: ruleRef,
388
+ ruleKey,
389
+ state,
390
+ path,
391
+ storage,
392
+ options
393
+ })
394
+ ];
395
+ }
396
+ return [];
397
+ }).filter((ruleDef) => !!ruleDef.length)
398
+ );
399
+ $watch();
400
+ if (storeResult?.valid != null) {
401
+ $dirty.value = storage.getDirtyState(path);
402
+ }
403
+ storage.addRuleDeclEntry(path, declaredRules);
404
+ }
405
+ const $unwatchDirty = watch2($dirty, () => {
406
+ storage.setDirtyEntry(path, $dirty.value);
407
+ });
408
+ const $unwatchState = watch2(state, () => {
409
+ if (unref2(options.autoDirty)) {
410
+ if (!$dirty.value) {
411
+ $dirty.value = true;
188
412
  }
189
413
  }
190
- if (isFormRuleDefinition(rule)) {
191
- if (!(customMessageRule && !rule.value._patched)) {
192
- if (typeof rule.value.message === "function") {
193
- message = rule.value.message(state.value, ...$params.value);
414
+ if (!unref2(options.lazy)) {
415
+ $commit();
416
+ }
417
+ });
418
+ function $unwatch() {
419
+ if ($rules.value) {
420
+ Object.entries($rules.value).forEach(([_, rule]) => {
421
+ rule.$unwatch();
422
+ });
423
+ }
424
+ $unwatchDirty();
425
+ if ($dirty.value) {
426
+ storage.setDirtyEntry(path, $dirty.value);
427
+ }
428
+ $unwatchState();
429
+ $unwatchValid();
430
+ scope.stop();
431
+ scope = effectScope3();
432
+ }
433
+ function $watch() {
434
+ scopeState = scope.run(() => {
435
+ const $error = computed3(() => {
436
+ return $invalid.value && !$pending.value && $dirty.value;
437
+ });
438
+ const $pending = computed3(() => {
439
+ if (triggerPunishment.value || !unref2(options.rewardEarly)) {
440
+ return Object.entries($rules.value).some(([key, ruleResult]) => {
441
+ return ruleResult.$pending;
442
+ });
443
+ }
444
+ return false;
445
+ });
446
+ const $invalid = computed3(() => {
447
+ if (triggerPunishment.value || !unref2(options.rewardEarly)) {
448
+ return Object.entries($rules.value).some(([key, ruleResult]) => {
449
+ return !ruleResult.$valid;
450
+ });
451
+ }
452
+ return false;
453
+ });
454
+ const $valid = computed3(() => {
455
+ if (unref2(options.rewardEarly)) {
456
+ return Object.entries($rules.value).every(([key, ruleResult]) => {
457
+ return ruleResult.$valid;
458
+ });
194
459
  } else {
195
- message = rule.value.message;
460
+ return !$invalid.value;
196
461
  }
197
- }
198
- }
199
- if (isEmpty(message)) {
200
- message = "Error";
201
- console.warn(`No error message defined for ${ruleKey}`);
462
+ });
463
+ return {
464
+ $error,
465
+ $pending,
466
+ $invalid,
467
+ $valid
468
+ };
469
+ });
470
+ }
471
+ const $rules = ref2();
472
+ createReactiveRulesResult();
473
+ const $unwatchValid = watch2(scopeState.$valid, (valid) => {
474
+ if (unref2(options.rewardEarly) && valid) {
475
+ triggerPunishment.value = false;
202
476
  }
203
- return message;
204
477
  });
205
- const $type = computed(() => {
206
- if (isFormInline(rule)) {
207
- return ruleKey;
208
- } else {
209
- return Object.values(InternalRuleType).includes(rule.value.type) ? ruleKey : rule.value.type;
478
+ function $reset() {
479
+ $dirty.value = false;
480
+ }
481
+ function $touch() {
482
+ $dirty.value = true;
483
+ }
484
+ function $commit() {
485
+ Object.entries($rules.value).map(([key, rule]) => {
486
+ return rule.$validate();
487
+ });
488
+ }
489
+ async function $validate() {
490
+ try {
491
+ triggerPunishment.value = true;
492
+ const results = await Promise.all(
493
+ Object.entries($rules.value).map(([key, rule]) => {
494
+ return rule.$validate();
495
+ })
496
+ );
497
+ return results.every((value) => !!value);
498
+ } catch (e) {
499
+ return false;
210
500
  }
501
+ }
502
+ return reactive2({
503
+ $dirty,
504
+ $anyDirty,
505
+ $invalid: scopeState.$invalid,
506
+ $error: scopeState.$error,
507
+ $pending: scopeState.$pending,
508
+ $valid: scopeState.$valid,
509
+ $value: state,
510
+ $rules,
511
+ $reset,
512
+ $touch,
513
+ $validate,
514
+ $unwatch,
515
+ $watch
211
516
  });
212
- const $validator = computed(
213
- () => {
214
- if (isFormInline(rule)) {
215
- return rule.value;
216
- } else {
217
- return rule.value.validator;
517
+ }
518
+
519
+ // src/utils/randomId.ts
520
+ function randomId() {
521
+ const uint32 = window.crypto.getRandomValues(new Uint32Array(1))[0];
522
+ return uint32.toString(8);
523
+ }
524
+
525
+ // src/core/useRegle/useStateProperties/createReactiveCollectionStatus.ts
526
+ function createCollectionElement({
527
+ path,
528
+ index,
529
+ options,
530
+ storage,
531
+ value,
532
+ customMessages,
533
+ rules
534
+ }) {
535
+ const $path = `${path}.${index}`;
536
+ const $id = randomId();
537
+ if (!value[index].$id) {
538
+ Object.defineProperties(value[index], {
539
+ $id: {
540
+ value: $id
218
541
  }
219
- }
220
- );
221
- const $params = computed(() => {
222
- if (typeof rule.value === "function") {
223
- return [];
224
- }
225
- return unwrapRuleParameters(rule.value._params ?? []);
542
+ });
543
+ }
544
+ const $state = toRefs(value);
545
+ const $status = createReactiveChildrenStatus({
546
+ state: $state[index],
547
+ rulesDef: toRef3(() => rules),
548
+ customMessages,
549
+ path: $path,
550
+ storage,
551
+ options
226
552
  });
227
- watch(
228
- [state, $dirty, $params],
229
- async () => {
230
- const validator = $validator.value;
231
- let ruleResult = false;
232
- const resultOrPromise = validator(state.value, ...$params.value);
233
- if (resultOrPromise instanceof Promise) {
234
- if ($dirty.value) {
235
- try {
236
- $valid.value = true;
237
- $pending.value = true;
238
- const promiseResult = await resultOrPromise;
239
- ruleResult = promiseResult;
240
- } catch (e) {
241
- ruleResult = false;
242
- } finally {
243
- $pending.value = false;
553
+ if ($status) {
554
+ $status.$id = value[index].$id ?? $id;
555
+ storage.addArrayStatus($status.$id, $status);
556
+ }
557
+ return $status;
558
+ }
559
+ function createReactiveCollectionStatus({
560
+ state,
561
+ rulesDef,
562
+ customMessages,
563
+ path,
564
+ storage,
565
+ options
566
+ }) {
567
+ if (Array.isArray(state.value) && !rulesDef.value.$each) {
568
+ return null;
569
+ }
570
+ let $unwatchState = null;
571
+ const $fieldStatus = ref3({});
572
+ const $eachStatus = storage.getCollectionsEntry(path);
573
+ createStatus();
574
+ $watch();
575
+ function createStatus() {
576
+ const { $each, ...otherFields } = rulesDef.value;
577
+ $fieldStatus.value = createReactiveFieldStatus({
578
+ state,
579
+ rulesDef: toRef3(() => otherFields),
580
+ customMessages,
581
+ path,
582
+ storage,
583
+ options
584
+ });
585
+ if (Array.isArray(state.value) && $each) {
586
+ $eachStatus.value = state.value.map((value, index) => {
587
+ return createCollectionElement({
588
+ path,
589
+ rules: $each,
590
+ value: state.value,
591
+ index,
592
+ options,
593
+ storage
594
+ });
595
+ }).filter((f) => !!f);
596
+ } else {
597
+ $eachStatus.value = [];
598
+ }
599
+ }
600
+ function updateChildrenStatus() {
601
+ const { $each } = rulesDef.value;
602
+ if (Array.isArray(state.value) && $eachStatus.value && $each) {
603
+ state.value.forEach((value, index) => {
604
+ if (value.$id) {
605
+ const previousStatus = storage.getArrayStatus(value.$id);
606
+ if (previousStatus) {
607
+ $eachStatus.value[index] = previousStatus;
608
+ }
609
+ } else {
610
+ const newElement = createCollectionElement({
611
+ value: state.value,
612
+ rules: $each,
613
+ customMessages,
614
+ path,
615
+ storage,
616
+ options,
617
+ index
618
+ });
619
+ if (newElement) {
620
+ $eachStatus.value[index] = newElement;
244
621
  }
245
622
  }
246
- } else {
247
- ruleResult = resultOrPromise;
248
- }
249
- $valid.value = ruleResult;
250
- },
251
- { immediate: true, deep: true }
252
- );
253
- return reactive({
254
- $message,
255
- $active,
256
- $pending,
257
- $type,
258
- $valid,
259
- $validator,
260
- ...$params.value.length && { $params }
623
+ });
624
+ }
625
+ if ($eachStatus.value) {
626
+ const deletedItems = $eachStatus.value.filter(($each2) => {
627
+ return Array.isArray(state.value) && !state.value.find((val) => val.$id === $each2.$id);
628
+ });
629
+ deletedItems.forEach((item) => item.$unwatch());
630
+ }
631
+ }
632
+ function $unwatch() {
633
+ if ($unwatchState) {
634
+ $unwatchState();
635
+ }
636
+ if ($fieldStatus.value) {
637
+ $fieldStatus.value.$unwatch();
638
+ }
639
+ if ($eachStatus.value) {
640
+ $eachStatus.value.forEach((element) => {
641
+ element.$unwatch();
642
+ });
643
+ }
644
+ }
645
+ function $watch() {
646
+ $unwatchState = watch3(
647
+ state,
648
+ () => {
649
+ updateChildrenStatus();
650
+ },
651
+ { deep: true, flush: "sync" }
652
+ );
653
+ }
654
+ function $touch() {
655
+ $fieldStatus.value.$touch();
656
+ $eachStatus.value.forEach(($each) => {
657
+ $each.$touch();
658
+ });
659
+ }
660
+ function $reset() {
661
+ $fieldStatus.value.$reset();
662
+ $eachStatus.value.forEach(($each) => {
663
+ $each.$reset();
664
+ });
665
+ }
666
+ async function $validate() {
667
+ try {
668
+ const results = await Promise.all(
669
+ $eachStatus.value.map((rule) => {
670
+ return rule.$validate();
671
+ })
672
+ );
673
+ return results.every((value) => !!value);
674
+ } catch (e) {
675
+ return false;
676
+ }
677
+ }
678
+ return reactive3({
679
+ ...$fieldStatus.value,
680
+ $each: $eachStatus,
681
+ $validate,
682
+ $unwatch,
683
+ $watch,
684
+ $touch,
685
+ $reset
261
686
  });
262
687
  }
263
688
 
264
- // src/core/useRegle/useStateProperties/createReactiveStatus.ts
265
- function createReactiveNestedStatus(scopeRules, state, customRules) {
266
- const $fields = reactive2(
267
- Object.fromEntries(
689
+ // src/core/useRegle/useStateProperties/createReactiveNestedStatus.ts
690
+ function createReactiveNestedStatus({
691
+ scopeRules,
692
+ state,
693
+ customMessages,
694
+ path = "",
695
+ rootRules,
696
+ storage,
697
+ options
698
+ }) {
699
+ let scope = effectScope4();
700
+ let scopeState;
701
+ let $unwatchFields;
702
+ function createReactiveFieldsStatus() {
703
+ $fields.value = Object.fromEntries(
268
704
  Object.entries(scopeRules.value).map(([statePropKey, statePropRules]) => {
269
705
  if (statePropRules) {
270
- const stateRef = toRef(state.value, statePropKey);
271
- const statePropRulesRef = toRef(() => statePropRules);
706
+ const stateRef = toRef4(state.value, statePropKey);
707
+ const statePropRulesRef = toRef4(() => statePropRules);
272
708
  return [
273
709
  statePropKey,
274
- createReactiveFieldStatus(stateRef, statePropRulesRef, customRules)
710
+ createReactiveChildrenStatus({
711
+ state: stateRef,
712
+ rulesDef: statePropRulesRef,
713
+ customMessages,
714
+ path: path ? `${path}.${statePropKey}` : statePropKey,
715
+ storage,
716
+ options
717
+ })
275
718
  ];
276
719
  }
277
720
  return [];
278
721
  }).filter(
279
722
  (rule) => !!rule.length && rule[1] != null
280
723
  )
281
- )
282
- );
283
- const $dirty = computed2(() => {
284
- return Object.entries($fields).every(([key, statusOrField]) => {
285
- return statusOrField.$dirty;
286
- });
287
- });
288
- const $anyDirty = computed2(() => {
289
- return Object.entries($fields).some(([key, statusOrField]) => {
290
- return statusOrField.$dirty;
291
- });
292
- });
293
- const $invalid = computed2(() => {
294
- return Object.entries($fields).some(([key, statusOrField]) => {
295
- return statusOrField.$invalid;
296
- });
297
- });
298
- const $error = computed2(() => {
299
- return Object.entries($fields).some(([key, statusOrField]) => {
300
- return statusOrField.$error;
301
- });
302
- });
303
- const $pending = computed2(() => {
304
- return Object.entries($fields).some(([key, statusOrField]) => {
305
- return statusOrField.$pending;
306
- });
307
- });
724
+ );
725
+ $watch();
726
+ }
727
+ const $fields = storage.getFieldsEntry(path);
728
+ createReactiveFieldsStatus();
308
729
  function $reset() {
309
- Object.entries($fields).forEach(([key, statusOrField]) => {
730
+ Object.entries($fields.value).forEach(([_, statusOrField]) => {
310
731
  statusOrField.$reset();
311
732
  });
312
733
  }
313
734
  function $touch() {
314
- Object.entries($fields).forEach(([key, statusOrField]) => {
735
+ Object.entries($fields.value).forEach(([_, statusOrField]) => {
315
736
  statusOrField.$touch();
316
737
  });
317
738
  }
318
- const $valid = computed2(() => !$invalid.value);
319
- return reactive2({
320
- $dirty,
321
- $anyDirty,
322
- $invalid,
323
- $valid,
324
- $error,
325
- $pending,
326
- $value: state,
739
+ async function $validate() {
740
+ try {
741
+ const results = await Promise.all(
742
+ Object.entries($fields.value).map(([_, statusOrField]) => {
743
+ return statusOrField.$validate();
744
+ })
745
+ );
746
+ return results.every((value) => !!value);
747
+ } catch (e) {
748
+ return false;
749
+ }
750
+ }
751
+ function $watch() {
752
+ if (rootRules) {
753
+ $unwatchFields = watch4(
754
+ rootRules,
755
+ () => {
756
+ $unwatch();
757
+ createReactiveFieldsStatus();
758
+ },
759
+ { deep: true, flush: "post" }
760
+ );
761
+ }
762
+ scopeState = scope.run(() => {
763
+ const $dirty = computed4(() => {
764
+ return Object.entries($fields.value).every(([key, statusOrField]) => {
765
+ return statusOrField.$dirty;
766
+ });
767
+ });
768
+ const $anyDirty = computed4(() => {
769
+ return Object.entries($fields.value).some(([key, statusOrField]) => {
770
+ return statusOrField.$dirty;
771
+ });
772
+ });
773
+ const $invalid = computed4(() => {
774
+ return Object.entries($fields.value).some(([key, statusOrField]) => {
775
+ return statusOrField.$invalid;
776
+ });
777
+ });
778
+ const $valid = computed4(() => !$invalid.value);
779
+ const $error = computed4(() => {
780
+ return Object.entries($fields.value).some(([key, statusOrField]) => {
781
+ return statusOrField.$error;
782
+ });
783
+ });
784
+ const $pending = computed4(() => {
785
+ return Object.entries($fields.value).some(([key, statusOrField]) => {
786
+ return statusOrField.$pending;
787
+ });
788
+ });
789
+ return {
790
+ $dirty,
791
+ $anyDirty,
792
+ $invalid,
793
+ $valid,
794
+ $error,
795
+ $pending
796
+ };
797
+ });
798
+ }
799
+ function $unwatch() {
800
+ if ($fields.value) {
801
+ Object.entries($fields.value).forEach(([_, field]) => {
802
+ field.$unwatch();
803
+ });
804
+ }
805
+ if ($unwatchFields) {
806
+ $unwatchFields();
807
+ }
808
+ scope.stop();
809
+ scope = effectScope4();
810
+ }
811
+ return reactive4({
812
+ ...scopeState,
327
813
  $fields,
814
+ $value: state,
328
815
  $reset,
329
- $touch
816
+ $touch,
817
+ $validate,
818
+ $unwatch,
819
+ $watch
330
820
  });
331
821
  }
332
- function createReactiveFieldStatus(state, rulesDef, customRules) {
822
+ function createReactiveChildrenStatus({
823
+ state,
824
+ rulesDef,
825
+ customMessages,
826
+ path,
827
+ storage,
828
+ options
829
+ }) {
333
830
  if (isCollectionRulesDef(rulesDef)) {
334
- const { $each, ...otherFields } = toRefs(reactive2(rulesDef.value));
335
- if (Array.isArray(state.value) && $each?.value) {
336
- const values = toRefs(state.value);
337
- return reactive2({
338
- ...!isEmpty(otherFields) && createReactiveFieldStatus(state, toRef(reactive2(otherFields)), customRules),
339
- $each: values.map((value) => {
340
- return createReactiveFieldStatus(value, $each, customRules);
341
- }).filter((f) => !!f)
342
- });
343
- }
344
- return null;
345
- } else if (isNestedRulesDef(state, rulesDef)) {
346
- return createReactiveNestedStatus(rulesDef, state, customRules);
347
- } else if (isValidatorRulesDef(rulesDef)) {
348
- let $reset2 = function() {
349
- $dirty.value = false;
350
- }, $touch2 = function() {
351
- $dirty.value = true;
352
- };
353
- var $reset = $reset2, $touch = $touch2;
354
- const customMessages = customRules();
355
- const $dirty = ref2(false);
356
- const $anyDirty = computed2(() => $dirty.value);
357
- const $rules = reactive2(
358
- Object.fromEntries(
359
- Object.entries(rulesDef.value).map(([ruleKey, rule]) => {
360
- if (rule) {
361
- const ruleRef = toRef(() => rule);
362
- return [
363
- ruleKey,
364
- createReactiveRuleStatus({
365
- $dirty,
366
- customMessages,
367
- rule: ruleRef,
368
- ruleKey,
369
- state
370
- })
371
- ];
372
- }
373
- return [];
374
- }).filter((ruleDef) => !!ruleDef.length)
375
- )
376
- );
377
- const $error = computed2(() => {
378
- return $invalid.value && !$pending.value && $dirty.value;
379
- });
380
- const $pending = computed2(() => {
381
- return Object.entries($rules).some(([key, rule]) => {
382
- return rule.$pending;
383
- });
384
- });
385
- const $invalid = computed2(() => {
386
- return Object.entries($rules).some(([key, ruleResult]) => {
387
- return !ruleResult.$valid;
388
- });
831
+ return createReactiveCollectionStatus({
832
+ state,
833
+ rulesDef,
834
+ customMessages,
835
+ path,
836
+ storage,
837
+ options
389
838
  });
390
- const $valid = computed2(() => !$invalid.value);
391
- watch2(state, () => {
392
- console.log(state);
393
- if (!$dirty.value) {
394
- $dirty.value = true;
395
- }
839
+ } else if (isNestedRulesDef(state, rulesDef) && isRefObject(state)) {
840
+ return createReactiveNestedStatus({
841
+ scopeRules: rulesDef,
842
+ state,
843
+ customMessages,
844
+ path,
845
+ storage,
846
+ options
396
847
  });
397
- console.log(state);
398
- return reactive2({
399
- $dirty,
400
- $anyDirty,
401
- $invalid,
402
- $error,
403
- $pending,
404
- $valid,
405
- $reset: $reset2,
406
- $touch: $touch2,
407
- $value: state,
408
- $rules
848
+ } else if (isValidatorRulesDef(rulesDef)) {
849
+ return createReactiveFieldStatus({
850
+ state,
851
+ rulesDef,
852
+ customMessages,
853
+ path,
854
+ storage,
855
+ options
409
856
  });
410
857
  }
411
858
  return null;
412
859
  }
413
860
 
414
- // src/core/useRegle/useErrors.ts
415
- import { computed as computed3 } from "vue";
416
- function extractRulesErrors(rules) {
417
- return Object.entries(rules).map(([ruleKey, rule]) => {
418
- if (!rule.$valid) {
419
- return rule.$message;
861
+ // src/core/useStorage/useStorage.ts
862
+ import { ref as ref4, shallowRef } from "vue";
863
+ function useStorage() {
864
+ const ruleDeclStorage = shallowRef(/* @__PURE__ */ new Map());
865
+ const fieldsStorage = shallowRef(
866
+ /* @__PURE__ */ new Map()
867
+ );
868
+ const collectionsStorage = shallowRef(/* @__PURE__ */ new Map());
869
+ const dirtyStorage = shallowRef(/* @__PURE__ */ new Map());
870
+ const ruleStatusStorage = shallowRef(/* @__PURE__ */ new Map());
871
+ const arrayStatusStorage = shallowRef(/* @__PURE__ */ new Map());
872
+ function getFieldsEntry($path) {
873
+ const existingFields = fieldsStorage.value.get($path);
874
+ if (existingFields) {
875
+ return existingFields;
876
+ } else {
877
+ const $fields = ref4({});
878
+ fieldsStorage.value.set($path, $fields);
879
+ return $fields;
420
880
  }
421
- return null;
422
- }).filter((msg) => !!msg);
423
- }
424
- function processFieldErrors(fieldStatus) {
425
- if (isNestedRulesStatus(fieldStatus)) {
426
- return extractNestedErrors(fieldStatus.$fields);
427
- } else if (isCollectionRulesStatus(fieldStatus)) {
428
- return {
429
- $errors: fieldStatus.$error ? extractRulesErrors(fieldStatus.$rules) : [],
430
- $each: fieldStatus.$each.map(processFieldErrors)
431
- };
432
- } else if (isFieldStatus(fieldStatus) && fieldStatus.$error) {
433
- return extractRulesErrors(fieldStatus.$rules);
434
881
  }
435
- return [];
436
- }
437
- function extractCollectionError(field) {
438
- return field.$each.map(processFieldErrors);
439
- }
440
- function extractNestedErrors(fields) {
441
- return Object.fromEntries(
442
- Object.entries(fields).map(([fieldKey, fieldStatus]) => {
443
- if (isNestedRulesStatus(fieldStatus)) {
444
- return [fieldKey, extractNestedErrors(fieldStatus.$fields)];
445
- } else if (isCollectionRulesStatus(fieldStatus)) {
446
- return [
447
- fieldKey,
448
- {
449
- ...fieldStatus.$rules && { $errors: extractRulesErrors(fieldStatus.$rules) },
450
- $each: extractCollectionError(fieldStatus)
451
- }
452
- ];
453
- } else if (isFieldStatus(fieldStatus) && fieldStatus.$error) {
454
- return [fieldKey, extractRulesErrors(fieldStatus.$rules)];
455
- }
456
- return [fieldKey, []];
457
- })
458
- );
459
- }
460
- function useErrors($regle) {
461
- const errors = computed3(() => {
462
- return extractNestedErrors($regle.value.$fields);
463
- });
464
- return errors;
882
+ function getCollectionsEntry($path) {
883
+ const existingEach = collectionsStorage.value.get($path);
884
+ if (existingEach) {
885
+ return existingEach;
886
+ } else {
887
+ const $each = ref4([]);
888
+ collectionsStorage.value.set($path, $each);
889
+ return $each;
890
+ }
891
+ }
892
+ function addArrayStatus($id, value) {
893
+ arrayStatusStorage.value.set($id, value);
894
+ }
895
+ function getArrayStatus($id) {
896
+ return arrayStatusStorage.value.get($id);
897
+ }
898
+ function setDirtyEntry($path, dirty) {
899
+ dirtyStorage.value.set($path, dirty);
900
+ }
901
+ function getDirtyState(path) {
902
+ return dirtyStorage.value.get(path) ?? false;
903
+ }
904
+ function addRuleDeclEntry($path, options) {
905
+ ruleDeclStorage.value.set($path, options);
906
+ }
907
+ function checkRuleDeclEntry($path, newRules) {
908
+ const storedRulesDefs = ruleDeclStorage.value.get($path);
909
+ if (!storedRulesDefs)
910
+ return void 0;
911
+ const storedRules = storedRulesDefs;
912
+ const isValidCache = areRulesChanged(newRules, storedRules);
913
+ if (!isValidCache)
914
+ return { valid: false };
915
+ return { valid: true };
916
+ }
917
+ function areRulesChanged(newRules, storedRules) {
918
+ const storedRulesKeys = Object.keys(storedRules);
919
+ const newRulesKeys = Object.keys(newRules);
920
+ if (newRulesKeys.length !== storedRulesKeys.length)
921
+ return false;
922
+ const hasAllValidators = newRulesKeys.every((ruleKey) => storedRulesKeys.includes(ruleKey));
923
+ if (!hasAllValidators)
924
+ return false;
925
+ return newRulesKeys.every((ruleKey) => {
926
+ const newRuleElement = newRules[ruleKey];
927
+ const storedRuleElement = storedRules[ruleKey];
928
+ if (!storedRuleElement || !newRuleElement || typeof newRuleElement === "function" || typeof storedRuleElement === "function")
929
+ return false;
930
+ if (!newRuleElement._params)
931
+ return true;
932
+ return newRuleElement._params?.every((paramKey, index) => {
933
+ const storedParams = unwrapRuleParameters(storedRuleElement._params);
934
+ const newParams = unwrapRuleParameters(newRuleElement._params);
935
+ return storedParams?.[index] === newParams?.[index];
936
+ });
937
+ });
938
+ }
939
+ function trySetRuleStatusRef(path) {
940
+ const ruleStatus = ruleStatusStorage.value.get(path);
941
+ if (ruleStatus) {
942
+ return ruleStatus;
943
+ } else {
944
+ const $pending = ref4(false);
945
+ const $valid = ref4(true);
946
+ ruleStatusStorage.value.set(path, { $pending, $valid });
947
+ return { $pending, $valid };
948
+ }
949
+ }
950
+ return {
951
+ addRuleDeclEntry,
952
+ setDirtyEntry,
953
+ checkRuleDeclEntry,
954
+ getDirtyState,
955
+ trySetRuleStatusRef,
956
+ getFieldsEntry,
957
+ getCollectionsEntry,
958
+ getArrayStatus,
959
+ addArrayStatus
960
+ };
465
961
  }
466
962
 
467
963
  // src/core/useRegle/useStateProperties/useStateProperties.ts
468
- function useStateProperties(scopeRules, state, customRules) {
469
- const $regle = ref3(createReactiveNestedStatus(scopeRules, state, customRules));
964
+ function useStateProperties(scopeRules, state, options, customRules) {
965
+ const storage = useStorage();
966
+ const $regle = reactive5(
967
+ createReactiveNestedStatus({
968
+ rootRules: scopeRules,
969
+ scopeRules,
970
+ state,
971
+ customMessages: customRules?.(),
972
+ storage,
973
+ options
974
+ })
975
+ );
470
976
  const errors = useErrors($regle);
471
977
  return { $regle, errors };
472
978
  }
473
979
 
474
980
  // src/core/useRegle/useRegle.ts
475
- function createUseRegleComposable(customRules) {
476
- function useRegle(state, rulesFactory) {
477
- const scopeRules = isRef(rulesFactory) ? rulesFactory : computed4(rulesFactory);
478
- const initialState = shallowRef(structuredClone(toRaw(state.value)));
981
+ function createUseRegleComposable(customRules, options) {
982
+ const globalOptions = {
983
+ autoDirty: options?.autoDirty ?? true,
984
+ lazy: options?.lazy ?? false,
985
+ rewardEarly: options?.rewardEarly ?? false
986
+ };
987
+ function useRegle2(state, rulesFactory, options2) {
988
+ const scopeRules = isRef2(rulesFactory) ? rulesFactory : computed5(rulesFactory);
989
+ const resolvedOptions = {
990
+ ...globalOptions,
991
+ ...options2
992
+ };
993
+ const initialState = shallowRef2(structuredClone(toRaw(state.value)));
479
994
  const { $regle, errors } = useStateProperties(
480
995
  scopeRules,
481
996
  state,
997
+ resolvedOptions,
482
998
  customRules
483
999
  );
1000
+ function resetForm() {
1001
+ state.value = toRaw(initialState.value);
1002
+ $regle.$reset();
1003
+ }
1004
+ async function validateForm() {
1005
+ $regle.$touch();
1006
+ const result = await $regle.$validate();
1007
+ if (result) {
1008
+ return state.value;
1009
+ }
1010
+ return false;
1011
+ }
484
1012
  return {
485
1013
  state,
486
1014
  $regle,
487
- errors
1015
+ errors,
1016
+ resetForm,
1017
+ validateForm
488
1018
  };
489
1019
  }
490
- return useRegle;
1020
+ return useRegle2;
491
1021
  }
1022
+ var useRegle = createUseRegleComposable();
492
1023
 
493
- // src/core/defineCustomValidators.ts
494
- function defineCustomValidators(customRules) {
495
- const useRegle = createUseRegleComposable(customRules);
496
- return {
497
- useRegle
498
- };
1024
+ // src/core/defineRegleOptions.ts
1025
+ function defineRegleOptions({
1026
+ rules,
1027
+ options
1028
+ }) {
1029
+ const useRegle2 = createUseRegleComposable(rules, options);
1030
+ return useRegle2;
499
1031
  }
500
1032
  export {
501
1033
  InternalRuleType,
502
1034
  createRule,
503
- defineCustomValidators
1035
+ defineRegleOptions,
1036
+ unwrapRuleParameters
504
1037
  };