@regle/core 0.0.3 → 0.0.4-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,6 +8,16 @@ 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) {
@@ -15,26 +25,17 @@ function defineRuleProcessors(definition, ...params) {
15
25
  const processors = {
16
26
  message(value, ...args) {
17
27
  if (typeof definition.message === "function") {
18
- return definition.message(
19
- value,
20
- ...unwrapRuleParameters(args.length ? args : params)
21
- );
28
+ return definition.message(value, ...args.length ? args : params);
22
29
  } else {
23
30
  return definition.message;
24
31
  }
25
32
  },
26
33
  validator(value, ...args) {
27
- return definition.validator(
28
- value,
29
- ...unwrapRuleParameters(args.length ? args : params)
30
- );
34
+ return definition.validator(value, ...args.length ? args : params);
31
35
  },
32
36
  active(value, ...args) {
33
37
  if (typeof definition.active === "function") {
34
- return definition.active(
35
- value,
36
- ...unwrapRuleParameters(args.length ? args : params)
37
- );
38
+ return definition.active(value, ...args.length ? args : params);
38
39
  } else {
39
40
  return definition.active ?? true;
40
41
  }
@@ -46,7 +47,7 @@ function defineRuleProcessors(definition, ...params) {
46
47
  _active: definition.active,
47
48
  _type: definition.type,
48
49
  _patched: false,
49
- _params: params
50
+ _params: createReactiveParams(params)
50
51
  }
51
52
  };
52
53
  return processors;
@@ -79,18 +80,21 @@ function createRule(definition) {
79
80
  }
80
81
 
81
82
  // src/core/useRegle/useRegle.ts
82
- import { computed as computed4, isRef, shallowRef, toRaw } from "vue";
83
+ import { computed as computed5, isRef as isRef2, shallowRef as shallowRef2, toRaw } from "vue";
83
84
 
84
85
  // src/core/useRegle/useStateProperties/useStateProperties.ts
85
- import { ref as ref3 } from "vue";
86
+ import { reactive as reactive5 } from "vue";
86
87
 
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";
88
+ // src/core/useRegle/useErrors.ts
89
+ import { computed } from "vue";
89
90
 
90
91
  // src/utils/object.utils.ts
91
92
  function isObject(obj) {
92
93
  return typeof obj === "object" && obj !== null && !Array.isArray(obj);
93
94
  }
95
+ function isRefObject(obj) {
96
+ return isObject(obj.value);
97
+ }
94
98
 
95
99
  // src/utils/isEmpty.ts
96
100
  function isEmpty(value) {
@@ -115,6 +119,9 @@ function isEmpty(value) {
115
119
  return !String(value).trim().length;
116
120
  }
117
121
 
122
+ // src/utils/composables.ts
123
+ import { effectScope, getCurrentScope, onScopeDispose } from "vue";
124
+
118
125
  // src/core/useRegle/guards/ruleDef.guards.ts
119
126
  function isNestedRulesDef(state, rule) {
120
127
  return isObject(state.value) && isObject(rule.value) && !Object.entries(rule.value).some((rule2) => isRuleDef(rule2));
@@ -131,9 +138,6 @@ function isRuleDef(rule) {
131
138
  function isFormRuleDefinition(rule) {
132
139
  return !(typeof rule.value === "function");
133
140
  }
134
- function isFormInline(rule) {
135
- return typeof rule.value === "function";
136
- }
137
141
 
138
142
  // src/core/useRegle/guards/rule.status.guards.ts
139
143
  function isNestedRulesStatus(rule) {
@@ -146,8 +150,72 @@ function isFieldStatus(rule) {
146
150
  return !!rule && "$rules" in rule;
147
151
  }
148
152
 
153
+ // src/core/useRegle/useErrors.ts
154
+ function extractRulesErrors(rules) {
155
+ return Object.entries(rules).map(([ruleKey, rule]) => {
156
+ if (!rule.$valid) {
157
+ return rule.$message;
158
+ }
159
+ return null;
160
+ }).filter((msg) => !!msg);
161
+ }
162
+ function processFieldErrors(fieldStatus) {
163
+ if (isNestedRulesStatus(fieldStatus)) {
164
+ return extractNestedErrors(fieldStatus.$fields);
165
+ } else if (isCollectionRulesStatus(fieldStatus)) {
166
+ return {
167
+ $errors: fieldStatus.$rules ? extractRulesErrors(fieldStatus.$rules) : [],
168
+ $each: fieldStatus.$each.map(processFieldErrors)
169
+ };
170
+ } else if (isFieldStatus(fieldStatus) && fieldStatus.$error) {
171
+ return extractRulesErrors(fieldStatus.$rules);
172
+ }
173
+ return [];
174
+ }
175
+ function extractCollectionError(field) {
176
+ return field.$each.map(processFieldErrors);
177
+ }
178
+ function extractNestedErrors(fields) {
179
+ return Object.fromEntries(
180
+ Object.entries(fields).map(([fieldKey, fieldStatus]) => {
181
+ if (isNestedRulesStatus(fieldStatus)) {
182
+ return [fieldKey, extractNestedErrors(fieldStatus.$fields)];
183
+ } else if (isCollectionRulesStatus(fieldStatus)) {
184
+ return [
185
+ fieldKey,
186
+ {
187
+ ...fieldStatus.$rules && { $errors: extractRulesErrors(fieldStatus.$rules) },
188
+ $each: extractCollectionError(fieldStatus)
189
+ }
190
+ ];
191
+ } else if (isFieldStatus(fieldStatus) && fieldStatus.$error) {
192
+ return [fieldKey, extractRulesErrors(fieldStatus.$rules)];
193
+ }
194
+ return [fieldKey, []];
195
+ })
196
+ );
197
+ }
198
+ function useErrors($regle) {
199
+ const errors = computed(() => {
200
+ return extractNestedErrors($regle.$fields);
201
+ });
202
+ return errors;
203
+ }
204
+
205
+ // src/core/useRegle/useStateProperties/createReactiveNestedStatus.ts
206
+ import {
207
+ computed as computed4,
208
+ effectScope as effectScope4,
209
+ reactive as reactive4,
210
+ toRef as toRef4,
211
+ watch as watch4
212
+ } from "vue";
213
+
214
+ // src/core/useRegle/useStateProperties/createReactiveFieldStatus.ts
215
+ import { computed as computed3, effectScope as effectScope3, reactive as reactive2, ref as ref2, toRef as toRef2, watch as watch2 } from "vue";
216
+
149
217
  // src/core/useRegle/useStateProperties/createReactiveRuleStatus.ts
150
- import { computed, reactive, ref, watch } from "vue";
218
+ import { computed as computed2, effectScope as effectScope2, reactive, watch } from "vue";
151
219
 
152
220
  // src/types/rules/rule.internal.types.ts
153
221
  var InternalRuleType = /* @__PURE__ */ ((InternalRuleType2) => {
@@ -162,311 +230,595 @@ function createReactiveRuleStatus({
162
230
  customMessages,
163
231
  rule,
164
232
  ruleKey,
165
- state
233
+ state,
234
+ path,
235
+ storage
166
236
  }) {
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;
177
- }
178
- }
179
- });
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;
188
- }
189
- }
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);
237
+ let scope = effectScope2();
238
+ let scopeState;
239
+ const { $pending, $valid } = storage.trySetRuleStatusRef(`${path}.${ruleKey}`);
240
+ function $watch() {
241
+ scopeState = scope.run(() => {
242
+ const $active = computed2(() => {
243
+ if (isFormRuleDefinition(rule)) {
244
+ if (typeof rule.value.active === "function") {
245
+ return rule.value.active(state.value, ...$params.value);
246
+ } else {
247
+ return rule.value.active;
248
+ }
194
249
  } else {
195
- message = rule.value.message;
250
+ return true;
196
251
  }
197
- }
198
- }
199
- if (isEmpty(message)) {
200
- message = "Error";
201
- console.warn(`No error message defined for ${ruleKey}`);
202
- }
203
- return message;
204
- });
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;
210
- }
211
- });
212
- const $validator = computed(
213
- () => {
214
- if (isFormInline(rule)) {
215
- return rule.value;
216
- } else {
217
- return rule.value.validator;
218
- }
219
- }
220
- );
221
- const $params = computed(() => {
222
- if (typeof rule.value === "function") {
223
- return [];
224
- }
225
- return unwrapRuleParameters(rule.value._params ?? []);
226
- });
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;
252
+ });
253
+ const $message = computed2(() => {
254
+ let message = "";
255
+ const customMessageRule = customMessages[ruleKey]?.message;
256
+ if (customMessageRule) {
257
+ if (typeof customMessageRule === "function") {
258
+ message = customMessageRule(state.value, ...$params.value);
259
+ } else {
260
+ message = customMessageRule;
244
261
  }
245
262
  }
246
- } else {
247
- ruleResult = resultOrPromise;
263
+ if (isFormRuleDefinition(rule)) {
264
+ if (!(customMessageRule && !rule.value._patched)) {
265
+ if (typeof rule.value.message === "function") {
266
+ message = rule.value.message(state.value, ...$params.value);
267
+ } else {
268
+ message = rule.value.message;
269
+ }
270
+ }
271
+ }
272
+ if (isEmpty(message)) {
273
+ message = "Error";
274
+ console.warn(`No error message defined for ${ruleKey}`);
275
+ }
276
+ return message;
277
+ });
278
+ const $type = computed2(() => {
279
+ if (isFormRuleDefinition(rule)) {
280
+ return Object.values(InternalRuleType).includes(rule.value.type) ? ruleKey : rule.value.type;
281
+ } else {
282
+ return ruleKey;
283
+ }
284
+ });
285
+ const $validator = computed2(() => {
286
+ if (isFormRuleDefinition(rule)) {
287
+ return rule.value.validator;
288
+ } else {
289
+ return rule.value;
290
+ }
291
+ });
292
+ const $params = computed2(() => {
293
+ if (typeof rule.value === "function") {
294
+ return [];
295
+ }
296
+ return unwrapRuleParameters(rule.value._params ?? []);
297
+ });
298
+ const $path = computed2(() => `${path}.${$type.value}`);
299
+ return {
300
+ $active,
301
+ $message,
302
+ $type,
303
+ $validator,
304
+ $params,
305
+ $path
306
+ };
307
+ });
308
+ $validate();
309
+ }
310
+ $watch();
311
+ const $unwatchState = watch(scopeState.$params, $validate, {
312
+ deep: true
313
+ });
314
+ async function $validate() {
315
+ const validator = scopeState.$validator.value;
316
+ let ruleResult = false;
317
+ const resultOrPromise = validator(state.value, ...scopeState.$params.value);
318
+ if (resultOrPromise instanceof Promise) {
319
+ if ($dirty.value && !$pending.value) {
320
+ try {
321
+ $valid.value = true;
322
+ $pending.value = true;
323
+ const promiseResult = await resultOrPromise;
324
+ ruleResult = promiseResult;
325
+ } catch (e) {
326
+ ruleResult = false;
327
+ } finally {
328
+ $pending.value = false;
329
+ }
248
330
  }
249
- $valid.value = ruleResult;
250
- },
251
- { immediate: true, deep: true }
252
- );
331
+ } else {
332
+ ruleResult = resultOrPromise;
333
+ }
334
+ $valid.value = ruleResult;
335
+ return ruleResult;
336
+ }
337
+ function $unwatch() {
338
+ $unwatchState();
339
+ scope.stop();
340
+ scope = effectScope2();
341
+ scopeState = null;
342
+ }
253
343
  return reactive({
254
- $message,
255
- $active,
344
+ ...scopeState,
256
345
  $pending,
257
- $type,
258
346
  $valid,
259
- $validator,
260
- ...$params.value.length && { $params }
347
+ $validate,
348
+ $unwatch,
349
+ $watch
261
350
  });
262
351
  }
263
352
 
264
- // src/core/useRegle/useStateProperties/createReactiveStatus.ts
265
- function createReactiveNestedStatus(scopeRules, state, customRules) {
266
- const $fields = reactive2(
267
- Object.fromEntries(
268
- Object.entries(scopeRules.value).map(([statePropKey, statePropRules]) => {
269
- if (statePropRules) {
270
- const stateRef = toRef(state.value, statePropKey);
271
- const statePropRulesRef = toRef(() => statePropRules);
353
+ // src/core/useRegle/useStateProperties/createReactiveFieldStatus.ts
354
+ function createReactiveFieldStatus({
355
+ state,
356
+ rulesDef,
357
+ customMessages,
358
+ path,
359
+ storage
360
+ }) {
361
+ let scope = effectScope3();
362
+ let scopeState;
363
+ const $dirty = ref2(false);
364
+ const $anyDirty = computed3(() => $dirty.value);
365
+ function createReactiveRulesResult() {
366
+ const declaredRules = rulesDef.value;
367
+ const storeResult = storage.checkRuleDeclEntry(path, declaredRules);
368
+ $rules.value = Object.fromEntries(
369
+ Object.entries(declaredRules).map(([ruleKey, rule]) => {
370
+ if (rule) {
371
+ const ruleRef = toRef2(() => rule);
272
372
  return [
273
- statePropKey,
274
- createReactiveFieldStatus(stateRef, statePropRulesRef, customRules)
373
+ ruleKey,
374
+ createReactiveRuleStatus({
375
+ $dirty,
376
+ customMessages,
377
+ rule: ruleRef,
378
+ ruleKey,
379
+ state,
380
+ path,
381
+ storage
382
+ })
275
383
  ];
276
384
  }
277
385
  return [];
278
- }).filter(
279
- (rule) => !!rule.length && rule[1] != null
280
- )
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
- });
386
+ }).filter((ruleDef) => !!ruleDef.length)
387
+ );
388
+ $watch();
389
+ if (storeResult?.valid != null) {
390
+ $dirty.value = storage.getDirtyState(path);
391
+ }
392
+ storage.addRuleDeclEntry(path, declaredRules);
393
+ }
394
+ const $unwatchDirty = watch2($dirty, () => {
395
+ storage.setDirtyEntry(path, $dirty.value);
297
396
  });
298
- const $error = computed2(() => {
299
- return Object.entries($fields).some(([key, statusOrField]) => {
300
- return statusOrField.$error;
301
- });
397
+ const $unwatchState = watch2(state, () => {
398
+ if (!$dirty.value) {
399
+ $dirty.value = true;
400
+ }
401
+ $validate();
302
402
  });
303
- const $pending = computed2(() => {
304
- return Object.entries($fields).some(([key, statusOrField]) => {
305
- return statusOrField.$pending;
403
+ function $unwatch() {
404
+ if ($rules.value) {
405
+ Object.entries($rules.value).forEach(([_, rule]) => {
406
+ rule.$unwatch();
407
+ });
408
+ }
409
+ $unwatchDirty();
410
+ if ($dirty.value) {
411
+ storage.setDirtyEntry(path, $dirty.value);
412
+ }
413
+ $unwatchState();
414
+ scope.stop();
415
+ scope = effectScope3();
416
+ scopeState = null;
417
+ }
418
+ function $watch() {
419
+ scopeState = scope.run(() => {
420
+ const $error = computed3(() => {
421
+ return $invalid.value && !$pending.value && $dirty.value;
422
+ });
423
+ const $pending = computed3(() => {
424
+ return Object.entries($rules.value).some(([key, rule]) => {
425
+ return rule.$pending;
426
+ });
427
+ });
428
+ const $invalid = computed3(() => {
429
+ return Object.entries($rules.value).some(([key, ruleResult]) => {
430
+ return !ruleResult.$valid;
431
+ });
432
+ });
433
+ const $valid = computed3(() => !$invalid.value);
434
+ return {
435
+ $error,
436
+ $pending,
437
+ $invalid,
438
+ $valid
439
+ };
306
440
  });
307
- });
441
+ }
442
+ const $rules = ref2();
443
+ createReactiveRulesResult();
308
444
  function $reset() {
309
- Object.entries($fields).forEach(([key, statusOrField]) => {
310
- statusOrField.$reset();
311
- });
445
+ $dirty.value = false;
312
446
  }
313
447
  function $touch() {
314
- Object.entries($fields).forEach(([key, statusOrField]) => {
315
- statusOrField.$touch();
316
- });
448
+ $dirty.value = true;
449
+ $validate();
450
+ }
451
+ async function $validate() {
452
+ try {
453
+ const results = await Promise.all(
454
+ Object.entries($rules.value).map(([key, rule]) => {
455
+ return rule.$validate();
456
+ })
457
+ );
458
+ return results.every((value) => !!value);
459
+ } catch (e) {
460
+ return false;
461
+ }
317
462
  }
318
- const $valid = computed2(() => !$invalid.value);
319
463
  return reactive2({
320
464
  $dirty,
321
465
  $anyDirty,
322
- $invalid,
323
- $valid,
324
- $error,
325
- $pending,
466
+ $invalid: scopeState.$invalid,
467
+ $error: scopeState.$error,
468
+ $pending: scopeState.$pending,
469
+ $valid: scopeState.$valid,
326
470
  $value: state,
327
- $fields,
471
+ $rules,
328
472
  $reset,
329
- $touch
473
+ $touch,
474
+ $validate,
475
+ $unwatch,
476
+ $watch
330
477
  });
331
478
  }
332
- function createReactiveFieldStatus(state, rulesDef, customRules) {
333
- 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)
479
+
480
+ // src/core/useRegle/useStateProperties/createReactiveCollectionStatus.ts
481
+ import { reactive as reactive3, ref as ref3, toRef as toRef3, watch as watch3 } from "vue";
482
+ function createReactiveCollectionStatus({
483
+ state,
484
+ rulesDef,
485
+ customMessages,
486
+ path,
487
+ storage
488
+ }) {
489
+ if (Array.isArray(state.value) && !rulesDef.value.$each) {
490
+ return null;
491
+ }
492
+ let $unwatchState = null;
493
+ const $fieldStatus = ref3({});
494
+ const $eachStatus = storage.getCollectionsEntry(path);
495
+ createStatus();
496
+ $watch();
497
+ function createStatus() {
498
+ const { $each, ...otherFields } = rulesDef.value;
499
+ $fieldStatus.value = createReactiveFieldStatus({
500
+ state,
501
+ rulesDef: toRef3(() => otherFields),
502
+ customMessages,
503
+ path,
504
+ storage
505
+ });
506
+ if (Array.isArray(state.value) && $each) {
507
+ $eachStatus.value = state.value.map((value, index) => {
508
+ const $path = `${path}.${index}`;
509
+ return createReactiveChildrenStatus({
510
+ state: toRef3(() => value),
511
+ rulesDef: toRef3(() => $each),
512
+ customMessages,
513
+ path: $path,
514
+ storage
515
+ });
516
+ }).filter((f) => !!f);
517
+ } else {
518
+ $eachStatus.value = [];
519
+ }
520
+ }
521
+ function $unwatch() {
522
+ if ($unwatchState) {
523
+ $unwatchState();
524
+ }
525
+ if ($fieldStatus.value) {
526
+ $fieldStatus.value.$unwatch();
527
+ }
528
+ if ($eachStatus.value) {
529
+ $eachStatus.value.forEach((element) => {
530
+ element.$unwatch();
342
531
  });
343
532
  }
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)
533
+ }
534
+ function $watch() {
535
+ $unwatchState = watch3(
536
+ state,
537
+ () => {
538
+ createStatus();
539
+ },
540
+ { deep: true, flush: "sync" }
541
+ );
542
+ }
543
+ return reactive3({
544
+ ...$fieldStatus.value,
545
+ $each: $eachStatus,
546
+ $unwatch,
547
+ $watch
548
+ });
549
+ }
550
+
551
+ // src/core/useRegle/useStateProperties/createReactiveNestedStatus.ts
552
+ function createReactiveNestedStatus({
553
+ scopeRules,
554
+ state,
555
+ customMessages,
556
+ path = "",
557
+ rootRules,
558
+ storage
559
+ }) {
560
+ let scope = effectScope4();
561
+ let scopeState;
562
+ let $unwatchFields;
563
+ function createReactiveFieldsStatus() {
564
+ $fields.value = Object.fromEntries(
565
+ Object.entries(scopeRules.value).map(([statePropKey, statePropRules]) => {
566
+ if (statePropRules) {
567
+ const stateRef = toRef4(state.value, statePropKey);
568
+ const statePropRulesRef = toRef4(() => statePropRules);
569
+ return [
570
+ statePropKey,
571
+ createReactiveChildrenStatus({
572
+ state: stateRef,
573
+ rulesDef: statePropRulesRef,
574
+ customMessages,
575
+ path: path ? `${path}.${statePropKey}` : statePropKey,
576
+ storage
577
+ })
578
+ ];
579
+ }
580
+ return [];
581
+ }).filter(
582
+ (rule) => !!rule.length && rule[1] != null
375
583
  )
376
584
  );
377
- const $error = computed2(() => {
378
- return $invalid.value && !$pending.value && $dirty.value;
585
+ $watch();
586
+ }
587
+ const $fields = storage.getFieldsEntry(path);
588
+ createReactiveFieldsStatus();
589
+ function $reset() {
590
+ Object.entries($fields.value).forEach(([_, statusOrField]) => {
591
+ statusOrField.$reset();
379
592
  });
380
- const $pending = computed2(() => {
381
- return Object.entries($rules).some(([key, rule]) => {
382
- return rule.$pending;
593
+ }
594
+ function $touch() {
595
+ Object.entries($fields.value).forEach(([_, statusOrField]) => {
596
+ statusOrField.$touch();
597
+ });
598
+ }
599
+ async function $validate() {
600
+ try {
601
+ const results = await Promise.all(
602
+ Object.entries($fields.value).map(([_, statusOrField]) => {
603
+ return statusOrField.$validate();
604
+ })
605
+ );
606
+ return results.every((value) => !!value);
607
+ } catch (e) {
608
+ return false;
609
+ }
610
+ }
611
+ function $watch() {
612
+ if (rootRules) {
613
+ $unwatchFields = watch4(
614
+ rootRules,
615
+ () => {
616
+ $unwatch();
617
+ createReactiveFieldsStatus();
618
+ },
619
+ { deep: true, flush: "post" }
620
+ );
621
+ }
622
+ scopeState = scope.run(() => {
623
+ const $dirty = computed4(() => {
624
+ return Object.entries($fields.value).every(([key, statusOrField]) => {
625
+ return statusOrField.$dirty;
626
+ });
627
+ });
628
+ const $anyDirty = computed4(() => {
629
+ return Object.entries($fields.value).some(([key, statusOrField]) => {
630
+ return statusOrField.$dirty;
631
+ });
632
+ });
633
+ const $invalid = computed4(() => {
634
+ return Object.entries($fields.value).some(([key, statusOrField]) => {
635
+ return statusOrField.$invalid;
636
+ });
637
+ });
638
+ const $valid = computed4(() => !$invalid.value);
639
+ const $error = computed4(() => {
640
+ return Object.entries($fields.value).some(([key, statusOrField]) => {
641
+ return statusOrField.$error;
642
+ });
643
+ });
644
+ const $pending = computed4(() => {
645
+ return Object.entries($fields.value).some(([key, statusOrField]) => {
646
+ return statusOrField.$pending;
647
+ });
383
648
  });
649
+ return {
650
+ $dirty,
651
+ $anyDirty,
652
+ $invalid,
653
+ $valid,
654
+ $error,
655
+ $pending
656
+ };
384
657
  });
385
- const $invalid = computed2(() => {
386
- return Object.entries($rules).some(([key, ruleResult]) => {
387
- return !ruleResult.$valid;
658
+ }
659
+ function $unwatch() {
660
+ if ($fields.value) {
661
+ Object.entries($fields.value).forEach(([_, field]) => {
662
+ field.$unwatch();
388
663
  });
664
+ }
665
+ if ($unwatchFields) {
666
+ $unwatchFields();
667
+ }
668
+ scope.stop();
669
+ scope = effectScope4();
670
+ scopeState = null;
671
+ }
672
+ return reactive4({
673
+ ...scopeState,
674
+ $fields,
675
+ $reset,
676
+ $touch,
677
+ $validate,
678
+ $unwatch,
679
+ $watch
680
+ });
681
+ }
682
+ function createReactiveChildrenStatus({
683
+ state,
684
+ rulesDef,
685
+ customMessages,
686
+ path,
687
+ storage
688
+ }) {
689
+ if (isCollectionRulesDef(rulesDef)) {
690
+ return createReactiveCollectionStatus({
691
+ state,
692
+ rulesDef,
693
+ customMessages,
694
+ path,
695
+ storage
389
696
  });
390
- const $valid = computed2(() => !$invalid.value);
391
- watch2(state, () => {
392
- console.log(state);
393
- if (!$dirty.value) {
394
- $dirty.value = true;
395
- }
697
+ } else if (isNestedRulesDef(state, rulesDef) && isRefObject(state)) {
698
+ return createReactiveNestedStatus({
699
+ scopeRules: rulesDef,
700
+ state,
701
+ customMessages,
702
+ path,
703
+ storage
396
704
  });
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
705
+ } else if (isValidatorRulesDef(rulesDef)) {
706
+ return createReactiveFieldStatus({
707
+ state,
708
+ rulesDef,
709
+ customMessages,
710
+ path,
711
+ storage
409
712
  });
410
713
  }
411
714
  return null;
412
715
  }
413
716
 
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;
717
+ // src/core/useStorage/useStorage.ts
718
+ import { ref as ref5, shallowRef } from "vue";
719
+ function useStorage() {
720
+ const ruleDeclStorage = shallowRef(/* @__PURE__ */ new Map());
721
+ const fieldsStorage = shallowRef(
722
+ /* @__PURE__ */ new Map()
723
+ );
724
+ const collectionsStorage = shallowRef(/* @__PURE__ */ new Map());
725
+ const dirtyStorage = shallowRef(/* @__PURE__ */ new Map());
726
+ const ruleStatusStorage = shallowRef(/* @__PURE__ */ new Map());
727
+ function getFieldsEntry($path) {
728
+ const existingFields = fieldsStorage.value.get($path);
729
+ if (existingFields) {
730
+ return existingFields;
731
+ } else {
732
+ const $fields = ref5({});
733
+ fieldsStorage.value.set($path, $fields);
734
+ return $fields;
420
735
  }
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
736
  }
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;
737
+ function getCollectionsEntry($path) {
738
+ const existingEach = collectionsStorage.value.get($path);
739
+ if (existingEach) {
740
+ return existingEach;
741
+ } else {
742
+ const $each = ref5([]);
743
+ collectionsStorage.value.set($path, $each);
744
+ return $each;
745
+ }
746
+ }
747
+ function setDirtyEntry($path, dirty) {
748
+ dirtyStorage.value.set($path, dirty);
749
+ }
750
+ function getDirtyState(path) {
751
+ return dirtyStorage.value.get(path) ?? false;
752
+ }
753
+ function addRuleDeclEntry($path, options) {
754
+ ruleDeclStorage.value.set($path, options);
755
+ }
756
+ function checkRuleDeclEntry($path, newRules) {
757
+ const storedRulesDefs = ruleDeclStorage.value.get($path);
758
+ if (!storedRulesDefs)
759
+ return void 0;
760
+ const storedRules = storedRulesDefs;
761
+ const isValidCache = areRulesChanged(newRules, storedRules);
762
+ if (!isValidCache)
763
+ return { valid: false };
764
+ return { valid: true };
765
+ }
766
+ function areRulesChanged(newRules, storedRules) {
767
+ const storedRulesKeys = Object.keys(storedRules);
768
+ const newRulesKeys = Object.keys(newRules);
769
+ if (newRulesKeys.length !== storedRulesKeys.length)
770
+ return false;
771
+ const hasAllValidators = newRulesKeys.every((ruleKey) => storedRulesKeys.includes(ruleKey));
772
+ if (!hasAllValidators)
773
+ return false;
774
+ return newRulesKeys.every((ruleKey) => {
775
+ const newRuleElement = newRules[ruleKey];
776
+ const storedRuleElement = storedRules[ruleKey];
777
+ if (!storedRuleElement || !newRuleElement || typeof newRuleElement === "function" || typeof storedRuleElement === "function")
778
+ return false;
779
+ if (!newRuleElement._params)
780
+ return true;
781
+ return newRuleElement._params?.every((paramKey, index) => {
782
+ const storedParams = unwrapRuleParameters(storedRuleElement._params);
783
+ const newParams = unwrapRuleParameters(newRuleElement._params);
784
+ return storedParams?.[index] === newParams?.[index];
785
+ });
786
+ });
787
+ }
788
+ function trySetRuleStatusRef(path) {
789
+ const ruleStatus = ruleStatusStorage.value.get(path);
790
+ if (ruleStatus) {
791
+ return ruleStatus;
792
+ } else {
793
+ const $pending = ref5(false);
794
+ const $valid = ref5(true);
795
+ ruleStatusStorage.value.set(path, { $pending, $valid });
796
+ return { $pending, $valid };
797
+ }
798
+ }
799
+ return {
800
+ addRuleDeclEntry,
801
+ setDirtyEntry,
802
+ checkRuleDeclEntry,
803
+ getDirtyState,
804
+ trySetRuleStatusRef,
805
+ getFieldsEntry,
806
+ getCollectionsEntry
807
+ };
465
808
  }
466
809
 
467
810
  // src/core/useRegle/useStateProperties/useStateProperties.ts
468
811
  function useStateProperties(scopeRules, state, customRules) {
469
- const $regle = ref3(createReactiveNestedStatus(scopeRules, state, customRules));
812
+ const storage = useStorage();
813
+ const $regle = reactive5(
814
+ createReactiveNestedStatus({
815
+ rootRules: scopeRules,
816
+ scopeRules,
817
+ state,
818
+ customMessages: customRules(),
819
+ storage
820
+ })
821
+ );
470
822
  const errors = useErrors($regle);
471
823
  return { $regle, errors };
472
824
  }
@@ -474,17 +826,27 @@ function useStateProperties(scopeRules, state, customRules) {
474
826
  // src/core/useRegle/useRegle.ts
475
827
  function createUseRegleComposable(customRules) {
476
828
  function useRegle(state, rulesFactory) {
477
- const scopeRules = isRef(rulesFactory) ? rulesFactory : computed4(rulesFactory);
478
- const initialState = shallowRef(structuredClone(toRaw(state.value)));
829
+ const scopeRules = isRef2(rulesFactory) ? rulesFactory : computed5(rulesFactory);
830
+ const initialState = shallowRef2(structuredClone(toRaw(state.value)));
479
831
  const { $regle, errors } = useStateProperties(
480
832
  scopeRules,
481
833
  state,
482
834
  customRules
483
835
  );
836
+ function resetForm() {
837
+ state.value = toRaw(initialState.value);
838
+ $regle.$reset();
839
+ }
840
+ async function validateForm() {
841
+ $regle.$touch();
842
+ return await $regle.$validate();
843
+ }
484
844
  return {
485
845
  state,
486
846
  $regle,
487
- errors
847
+ errors,
848
+ resetForm,
849
+ validateForm
488
850
  };
489
851
  }
490
852
  return useRegle;