@regle/core 0.0.7 → 0.0.9

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.cjs CHANGED
@@ -233,8 +233,9 @@ function useStorage() {
233
233
  const $pending = (0, import_vue2.ref)(false);
234
234
  const $valid = (0, import_vue2.ref)(true);
235
235
  const $metadata = (0, import_vue2.ref)({});
236
- ruleStatusStorage.value.set(path, { $pending, $valid, $metadata });
237
- return { $pending, $valid, $metadata };
236
+ const $validating = (0, import_vue2.ref)(false);
237
+ ruleStatusStorage.value.set(path, { $pending, $valid, $metadata, $validating });
238
+ return { $pending, $valid, $metadata, $validating };
238
239
  }
239
240
  }
240
241
  (0, import_vue2.onScopeDispose)(() => {
@@ -296,6 +297,35 @@ function isEmpty(value) {
296
297
  // src/utils/composables.ts
297
298
  var import_vue3 = require("vue");
298
299
 
300
+ // src/utils/debounce.ts
301
+ function debounce(func, wait, immediate) {
302
+ let timeout;
303
+ const debouncedFn = (...args) => new Promise((resolve) => {
304
+ clearTimeout(timeout);
305
+ timeout = setTimeout(() => {
306
+ timeout = void 0;
307
+ if (!immediate) {
308
+ void Promise.resolve(func.apply(this, [...args])).then(resolve);
309
+ }
310
+ }, wait);
311
+ if (immediate && !timeout) {
312
+ void Promise.resolve(func.apply(this, [...args])).then(resolve);
313
+ }
314
+ });
315
+ debouncedFn.cancel = () => {
316
+ clearTimeout(timeout);
317
+ timeout = void 0;
318
+ };
319
+ debouncedFn.doImmediately = (...args) => new Promise((resolve) => {
320
+ clearTimeout(timeout);
321
+ timeout = setTimeout(() => {
322
+ timeout = void 0;
323
+ void Promise.resolve(func.apply(this, [...args])).then(resolve);
324
+ }, 0);
325
+ });
326
+ return debouncedFn;
327
+ }
328
+
299
329
  // src/core/useRegle/guards/ruleDef.guards.ts
300
330
  function isNestedRulesDef(state, rule) {
301
331
  return isObject(state.value) && isObject(rule.value) && !Object.entries(rule.value).some((rule2) => isRuleDef(rule2));
@@ -336,7 +366,13 @@ function extractRulesErrors(rules, externalErrors) {
336
366
  return rule.$message;
337
367
  }
338
368
  return null;
339
- }).filter((msg) => !!msg).concat(externalErrors ?? []);
369
+ }).filter((msg) => !!msg).reduce((acc, value) => {
370
+ if (typeof value === "string") {
371
+ return acc?.concat([value]);
372
+ } else {
373
+ return acc?.concat(value);
374
+ }
375
+ }, []).concat(externalErrors ?? []);
340
376
  }
341
377
  function processFieldErrors(fieldStatus) {
342
378
  if (isNestedRulesStatus(fieldStatus)) {
@@ -427,7 +463,9 @@ function createReactiveRuleStatus({
427
463
  }) {
428
464
  let scope = (0, import_vue5.effectScope)();
429
465
  let scopeState;
430
- const { $pending, $valid, $metadata } = storage.trySetRuleStatusRef(`${path}.${ruleKey}`);
466
+ const { $pending, $valid, $metadata, $validating } = storage.trySetRuleStatusRef(
467
+ `${path}.${ruleKey}`
468
+ );
431
469
  function $watch() {
432
470
  scopeState = scope.run(() => {
433
471
  const $defaultMetadata = (0, import_vue5.computed)(() => ({
@@ -448,26 +486,28 @@ function createReactiveRuleStatus({
448
486
  });
449
487
  const $message = (0, import_vue5.computed)(() => {
450
488
  let message = "";
451
- const customMessageRule = customMessages ? customMessages[ruleKey]?.message : void 0;
452
- if (customMessageRule) {
453
- if (typeof customMessageRule === "function") {
454
- message = customMessageRule(state.value, $defaultMetadata.value);
455
- } else {
456
- message = customMessageRule;
457
- }
458
- }
459
- if (isFormRuleDefinition(rule)) {
460
- if (!(customMessageRule && !rule.value._patched)) {
461
- if (typeof rule.value.message === "function") {
462
- message = rule.value.message(state.value, $defaultMetadata.value);
489
+ if ($dirty.value && !$validating.value) {
490
+ const customMessageRule = customMessages ? customMessages[ruleKey]?.message : void 0;
491
+ if (customMessageRule) {
492
+ if (typeof customMessageRule === "function") {
493
+ message = customMessageRule(state.value, $defaultMetadata.value);
463
494
  } else {
464
- message = rule.value.message;
495
+ message = customMessageRule;
465
496
  }
466
497
  }
467
- }
468
- if (isEmpty(message)) {
469
- message = "Error";
470
- console.warn(`No error message defined for ${ruleKey}`);
498
+ if (isFormRuleDefinition(rule)) {
499
+ if (!(customMessageRule && !rule.value._patched)) {
500
+ if (typeof rule.value.message === "function") {
501
+ message = rule.value.message(state.value, $defaultMetadata.value);
502
+ } else {
503
+ message = rule.value.message;
504
+ }
505
+ }
506
+ }
507
+ if (isEmpty(message)) {
508
+ message = "Error";
509
+ console.warn(`No error message defined for ${ruleKey}`);
510
+ }
471
511
  }
472
512
  return message;
473
513
  });
@@ -507,43 +547,48 @@ function createReactiveRuleStatus({
507
547
  deep: true
508
548
  });
509
549
  async function $validate() {
510
- const validator = scopeState.$validator.value;
511
- let ruleResult = false;
512
- const resultOrPromise = validator(state.value, ...scopeState.$params.value);
513
- if (resultOrPromise instanceof Promise) {
514
- if ($dirty.value && !$pending.value) {
515
- try {
516
- $valid.value = true;
517
- $pending.value = true;
518
- const promiseResult = await resultOrPromise;
519
- if (typeof promiseResult === "boolean") {
520
- ruleResult = promiseResult;
550
+ try {
551
+ $validating.value = true;
552
+ const validator = scopeState.$validator.value;
553
+ let ruleResult = false;
554
+ const resultOrPromise = validator(state.value, ...scopeState.$params.value);
555
+ if (resultOrPromise instanceof Promise) {
556
+ if ($dirty.value && !$pending.value) {
557
+ try {
558
+ $valid.value = true;
559
+ $pending.value = true;
560
+ const promiseResult = await resultOrPromise;
561
+ if (typeof promiseResult === "boolean") {
562
+ ruleResult = promiseResult;
563
+ } else {
564
+ const { $valid: $valid2, ...rest } = promiseResult;
565
+ ruleResult = $valid2;
566
+ $metadata.value = rest;
567
+ }
568
+ } catch (e) {
569
+ ruleResult = false;
570
+ } finally {
571
+ $pending.value = false;
572
+ }
573
+ }
574
+ } else {
575
+ if (resultOrPromise != null) {
576
+ if (typeof resultOrPromise === "boolean") {
577
+ ruleResult = resultOrPromise;
521
578
  } else {
522
- const { $valid: $valid2, ...rest } = promiseResult;
579
+ const { $valid: $valid2, ...rest } = resultOrPromise;
523
580
  ruleResult = $valid2;
524
581
  $metadata.value = rest;
525
582
  }
526
- } catch (e) {
527
- ruleResult = false;
528
- } finally {
529
- $pending.value = false;
530
583
  }
531
584
  }
532
- } else {
533
- if (resultOrPromise != null) {
534
- if (typeof resultOrPromise === "boolean") {
535
- ruleResult = resultOrPromise;
536
- } else {
537
- const { $valid: $valid2, ...rest } = resultOrPromise;
538
- ruleResult = $valid2;
539
- $metadata.value = rest;
540
- }
585
+ $valid.value = ruleResult;
586
+ if (options.$externalErrors) {
541
587
  }
588
+ return ruleResult;
589
+ } finally {
590
+ $validating.value = false;
542
591
  }
543
- $valid.value = ruleResult;
544
- if (options.$externalErrors) {
545
- }
546
- return ruleResult;
547
592
  }
548
593
  function $unwatch() {
549
594
  $unwatchState();
@@ -586,8 +631,11 @@ function createReactiveFieldStatus({
586
631
  function createReactiveRulesResult() {
587
632
  const declaredRules = rulesDef.value;
588
633
  const storeResult = storage.checkRuleDeclEntry(path, declaredRules);
634
+ $localOptions.value = Object.fromEntries(
635
+ Object.entries(declaredRules).filter(([ruleKey]) => ruleKey.startsWith("$"))
636
+ );
589
637
  $rules.value = Object.fromEntries(
590
- Object.entries(declaredRules).map(([ruleKey, rule]) => {
638
+ Object.entries(declaredRules).filter(([ruleKey]) => !ruleKey.startsWith("$")).map(([ruleKey, rule]) => {
591
639
  if (rule) {
592
640
  const ruleRef = (0, import_vue6.toRef)(() => rule);
593
641
  return [
@@ -620,15 +668,17 @@ function createReactiveFieldStatus({
620
668
  storage.setDirtyEntry(path, $dirty.value);
621
669
  });
622
670
  const $unwatchState = (0, import_vue6.watch)(state, () => {
623
- if ((0, import_vue6.unref)(options.autoDirty)) {
671
+ if (scopeState.$autoDirty.value) {
624
672
  if (!$dirty.value) {
625
673
  $dirty.value = true;
626
674
  }
627
675
  }
628
- if (!(0, import_vue6.unref)(options.lazy)) {
676
+ if (!scopeState.$lazy.value) {
629
677
  $commit();
678
+ if (!scopeState.$rewardEarly.value !== false) {
679
+ $clearExternalErrors();
680
+ }
630
681
  }
631
- $externalErrors.value = [];
632
682
  });
633
683
  function $unwatch() {
634
684
  if ($rules.value) {
@@ -648,11 +698,32 @@ function createReactiveFieldStatus({
648
698
  }
649
699
  function $watch() {
650
700
  scopeState = scope.run(() => {
701
+ const $debounce = (0, import_vue6.computed)(() => {
702
+ return $localOptions.value.$debounce;
703
+ });
704
+ const $lazy = (0, import_vue6.computed)(() => {
705
+ if ($localOptions.value.$lazy) {
706
+ return $localOptions.value.$lazy;
707
+ }
708
+ return (0, import_vue6.unref)(options.lazy);
709
+ });
710
+ const $rewardEarly = (0, import_vue6.computed)(() => {
711
+ if ($localOptions.value.$rewardEarly) {
712
+ return $localOptions.value.$rewardEarly;
713
+ }
714
+ return (0, import_vue6.unref)(options.rewardEarly);
715
+ });
716
+ const $autoDirty = (0, import_vue6.computed)(() => {
717
+ if ($localOptions.value.$autoDirty) {
718
+ return $localOptions.value.$autoDirty;
719
+ }
720
+ return (0, import_vue6.unref)(options.autoDirty);
721
+ });
651
722
  const $error = (0, import_vue6.computed)(() => {
652
723
  return $invalid.value && !$pending.value && $dirty.value;
653
724
  });
654
725
  const $pending = (0, import_vue6.computed)(() => {
655
- if (triggerPunishment.value || !(0, import_vue6.unref)(options.rewardEarly)) {
726
+ if (triggerPunishment.value || !$rewardEarly.value) {
656
727
  return Object.entries($rules.value).some(([key, ruleResult]) => {
657
728
  return ruleResult.$pending;
658
729
  });
@@ -660,7 +731,9 @@ function createReactiveFieldStatus({
660
731
  return false;
661
732
  });
662
733
  const $invalid = (0, import_vue6.computed)(() => {
663
- if (triggerPunishment.value || !(0, import_vue6.unref)(options.rewardEarly)) {
734
+ if ($externalErrors.value?.length) {
735
+ return true;
736
+ } else if (triggerPunishment.value || !$rewardEarly.value) {
664
737
  return Object.entries($rules.value).some(([key, ruleResult]) => {
665
738
  return !ruleResult.$valid;
666
739
  });
@@ -668,7 +741,9 @@ function createReactiveFieldStatus({
668
741
  return false;
669
742
  });
670
743
  const $valid = (0, import_vue6.computed)(() => {
671
- if ((0, import_vue6.unref)(options.rewardEarly)) {
744
+ if ($externalErrors.value?.length) {
745
+ return false;
746
+ } else if ($rewardEarly.value) {
672
747
  return Object.entries($rules.value).every(([key, ruleResult]) => {
673
748
  return ruleResult.$valid;
674
749
  });
@@ -680,14 +755,19 @@ function createReactiveFieldStatus({
680
755
  $error,
681
756
  $pending,
682
757
  $invalid,
683
- $valid
758
+ $valid,
759
+ $debounce,
760
+ $lazy,
761
+ $rewardEarly,
762
+ $autoDirty
684
763
  };
685
764
  });
686
765
  }
687
766
  const $rules = (0, import_vue6.ref)();
767
+ const $localOptions = (0, import_vue6.ref)();
688
768
  createReactiveRulesResult();
689
769
  const $unwatchValid = (0, import_vue6.watch)(scopeState.$valid, (valid) => {
690
- if ((0, import_vue6.unref)(options.rewardEarly) && valid) {
770
+ if (scopeState.$rewardEarly.value && valid) {
691
771
  triggerPunishment.value = false;
692
772
  }
693
773
  });
@@ -698,15 +778,18 @@ function createReactiveFieldStatus({
698
778
  function $touch() {
699
779
  $dirty.value = true;
700
780
  }
701
- function $commit() {
781
+ const $commit = debounce($commitHandler, scopeState.$debounce.value ?? 0);
782
+ function $commitHandler() {
702
783
  Object.entries($rules.value).map(([key, rule]) => {
703
784
  return rule.$validate();
704
785
  });
705
786
  }
706
- async function $validate() {
787
+ const $validate = debounce($validateHandler, scopeState.$debounce.value ?? 0);
788
+ async function $validateHandler() {
707
789
  try {
790
+ $clearExternalErrors();
708
791
  triggerPunishment.value = true;
709
- const results = await Promise.all(
792
+ const results = await Promise.allSettled(
710
793
  Object.entries($rules.value).map(([key, rule]) => {
711
794
  return rule.$validate();
712
795
  })