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