@regle/core 0.7.4-beta.3 → 0.7.5

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.
@@ -1,4 +1,4 @@
1
- import { toValue, version, ref, getCurrentScope, onScopeDispose, reactive, computed, shallowRef, effectScope, isRef, toRef, unref, watch, watchEffect } from 'vue';
1
+ import { toValue, version, ref, getCurrentScope, onScopeDispose, reactive, computed, shallowRef, effectScope, isRef, toRef, unref, watch, getCurrentInstance, onMounted, watchEffect } from 'vue';
2
2
 
3
3
  // ../shared/utils/isEmpty.ts
4
4
  function isEmpty(value, considerEmptyArrayInvalid = true) {
@@ -69,28 +69,6 @@ function isObject(obj) {
69
69
  return typeof obj === "object" && obj !== null && !Array.isArray(obj);
70
70
  }
71
71
 
72
- // ../shared/utils/isDate.ts
73
- function isDate(value) {
74
- if (isEmpty(value)) {
75
- return false;
76
- }
77
- try {
78
- let possibleDate = null;
79
- if (value instanceof Date) {
80
- possibleDate = value;
81
- } else if (typeof value === "string") {
82
- const date = new Date(value);
83
- if (date.toString() === "Invalid Date") {
84
- return false;
85
- }
86
- possibleDate = date;
87
- }
88
- return !!possibleDate;
89
- } catch (e) {
90
- return false;
91
- }
92
- }
93
-
94
72
  // ../shared/utils/toDate.ts
95
73
  function toDate(argument) {
96
74
  const argStr = Object.prototype.toString.call(argument);
@@ -442,6 +420,25 @@ function randomId() {
442
420
  return uint32.toString(10);
443
421
  }
444
422
  }
423
+ function tryOnScopeDispose(fn) {
424
+ if (getCurrentScope()) {
425
+ onScopeDispose(fn);
426
+ return true;
427
+ }
428
+ return false;
429
+ }
430
+ function createGlobalState(stateFactory) {
431
+ let initialized = false;
432
+ let state;
433
+ const scope = effectScope(true);
434
+ return (...args) => {
435
+ if (!initialized) {
436
+ state = scope.run(() => stateFactory(...args));
437
+ initialized = true;
438
+ }
439
+ return state;
440
+ };
441
+ }
445
442
 
446
443
  // src/core/useRegle/guards/ruleDef.guards.ts
447
444
  function isNestedRulesDef(state, rules) {
@@ -474,7 +471,7 @@ function extractRulesErrors({
474
471
  silent = false
475
472
  }) {
476
473
  return Object.entries(field.$rules ?? {}).map(([_, rule]) => {
477
- if (silent) {
474
+ if (silent && !rule.$valid) {
478
475
  return rule.$message;
479
476
  } else if (!rule.$valid && field.$error && !rule.$validating) {
480
477
  return rule.$message;
@@ -874,27 +871,27 @@ function createReactiveFieldStatus({
874
871
  const $errors = computed(() => {
875
872
  return extractRulesErrors({
876
873
  field: {
874
+ $rules: $rules.value,
877
875
  $error: $error.value,
878
876
  $externalErrors: externalErrors?.value,
879
- $schemaErrors: schemaErrors?.value,
880
- $rules: $rules.value
877
+ $schemaErrors: schemaErrors?.value
881
878
  }
882
879
  });
883
880
  });
884
881
  const $silentErrors = computed(() => {
885
882
  return extractRulesErrors({
886
883
  field: {
887
- $error: true,
884
+ $rules: $rules.value,
885
+ $error: $error.value,
888
886
  $externalErrors: externalErrors?.value,
889
- $schemaErrors: schemaErrors?.value,
890
- $rules: $rules.value
887
+ $schemaErrors: schemaErrors?.value
891
888
  },
892
889
  silent: true
893
890
  });
894
891
  });
895
892
  const $edited = computed(() => {
896
893
  if ($dirty.value) {
897
- if (isDate(initialState.value) && isDate(state.value)) {
894
+ if (initialState.value instanceof Date && state.value instanceof Date) {
898
895
  return toDate(initialState.value).getDate() !== toDate(state.value).getDate();
899
896
  }
900
897
  if (initialState.value == null) {
@@ -2256,10 +2253,18 @@ function defineRegleConfig({
2256
2253
  function mergeRegles(regles, _scoped) {
2257
2254
  const scoped = _scoped == null ? false : _scoped;
2258
2255
  const $value = computed({
2259
- get: () => Object.fromEntries(Object.entries(regles).map(([key, r]) => [key, r.$value])),
2256
+ get: () => {
2257
+ if (scoped) {
2258
+ return Object.values(regles).map((r) => r.$value);
2259
+ } else {
2260
+ return Object.fromEntries(Object.entries(regles).map(([key, r]) => [key, r.$value]));
2261
+ }
2262
+ },
2260
2263
  set: (value) => {
2261
- if (typeof value === "object") {
2262
- Object.entries(value).forEach(([key, newValue]) => regles[key].$value = newValue);
2264
+ if (!scoped) {
2265
+ if (typeof value === "object") {
2266
+ Object.entries(value).forEach(([key, newValue]) => regles[key].$value = newValue);
2267
+ }
2263
2268
  }
2264
2269
  }
2265
2270
  });
@@ -2272,7 +2277,8 @@ function mergeRegles(regles, _scoped) {
2272
2277
  }
2273
2278
  });
2274
2279
  const $dirty = computed(() => {
2275
- return Object.entries(regles).every(([_, regle]) => {
2280
+ const entries = Object.entries(regles);
2281
+ return !!entries.length && entries.every(([_, regle]) => {
2276
2282
  return regle?.$dirty;
2277
2283
  });
2278
2284
  });
@@ -2287,8 +2293,9 @@ function mergeRegles(regles, _scoped) {
2287
2293
  });
2288
2294
  });
2289
2295
  const $valid = computed(() => {
2290
- return Object.entries(regles).every(([_, regle]) => {
2291
- return regle?.$invalid;
2296
+ const entries = Object.entries(regles);
2297
+ return !!entries.length && entries.every(([_, regle]) => {
2298
+ return regle?.$valid;
2292
2299
  });
2293
2300
  });
2294
2301
  const $error = computed(() => {
@@ -2297,7 +2304,8 @@ function mergeRegles(regles, _scoped) {
2297
2304
  });
2298
2305
  });
2299
2306
  const $ready = computed(() => {
2300
- return Object.entries(regles).every(([_, regle]) => {
2307
+ const entries = Object.entries(regles);
2308
+ return !!entries.length && entries.every(([_, regle]) => {
2301
2309
  return regle?.$ready;
2302
2310
  });
2303
2311
  });
@@ -2307,21 +2315,34 @@ function mergeRegles(regles, _scoped) {
2307
2315
  });
2308
2316
  });
2309
2317
  const $errors = computed(() => {
2310
- return Object.fromEntries(
2311
- Object.entries(regles).map(([key, regle]) => {
2312
- return [key, regle.$errors];
2313
- })
2314
- );
2318
+ if (scoped) {
2319
+ return Object.entries(regles).map(([_, regle]) => {
2320
+ return regle.$errors;
2321
+ });
2322
+ } else {
2323
+ return Object.fromEntries(
2324
+ Object.entries(regles).map(([key, regle]) => {
2325
+ return [key, regle.$errors];
2326
+ })
2327
+ );
2328
+ }
2315
2329
  });
2316
2330
  const $silentErrors = computed(() => {
2317
- return Object.fromEntries(
2318
- Object.entries(regles).map(([key, regle]) => {
2319
- return [key, regle.$silentErrors];
2320
- })
2321
- );
2331
+ if (scoped) {
2332
+ return Object.entries(regles).map(([_, regle]) => {
2333
+ return regle.$silentErrors;
2334
+ });
2335
+ } else {
2336
+ return Object.fromEntries(
2337
+ Object.entries(regles).map(([key, regle]) => {
2338
+ return [key, regle.$silentErrors];
2339
+ })
2340
+ );
2341
+ }
2322
2342
  });
2323
2343
  const $edited = computed(() => {
2324
- return Object.entries(regles).every(([_, regle]) => {
2344
+ const entries = Object.entries(regles);
2345
+ return !!entries.length && entries.every(([_, regle]) => {
2325
2346
  return regle?.$edited;
2326
2347
  });
2327
2348
  });
@@ -2331,7 +2352,11 @@ function mergeRegles(regles, _scoped) {
2331
2352
  });
2332
2353
  });
2333
2354
  const $instances = computed(() => {
2334
- return regles;
2355
+ if (scoped) {
2356
+ return Object.values(regles);
2357
+ } else {
2358
+ return regles;
2359
+ }
2335
2360
  });
2336
2361
  function $reset() {
2337
2362
  Object.values(regles).forEach((regle) => {
@@ -2378,12 +2403,12 @@ function mergeRegles(regles, _scoped) {
2378
2403
  }
2379
2404
  return reactive({
2380
2405
  ...!scoped && {
2381
- $instances,
2382
- $value,
2383
- $silentValue,
2384
- $errors,
2385
- $silentErrors
2406
+ $silentValue
2386
2407
  },
2408
+ $errors,
2409
+ $silentErrors,
2410
+ $instances,
2411
+ $value,
2387
2412
  $dirty,
2388
2413
  $anyDirty,
2389
2414
  $invalid,
@@ -2401,42 +2426,112 @@ function mergeRegles(regles, _scoped) {
2401
2426
  $clearExternalErrors
2402
2427
  });
2403
2428
  }
2404
- function createUseCollectScopedValidations(instances) {
2405
- function useCollectScopedValidations() {
2406
- const r$ = ref(mergeRegles(instances.value, true));
2429
+ function createUseCollectScope(instances) {
2430
+ function useCollectScope(namespace) {
2431
+ const computedNamespace = computed(() => toValue(namespace));
2432
+ setEmptyNamespace();
2433
+ const r$ = ref(collectRegles(instances.value));
2407
2434
  const regle = reactive({ r$ });
2408
- watch(instances, (newInstances) => {
2409
- r$.value = mergeRegles(newInstances, true);
2410
- });
2435
+ function setEmptyNamespace() {
2436
+ if (computedNamespace.value && !instances.value[computedNamespace.value]) {
2437
+ instances.value[computedNamespace.value] = {};
2438
+ }
2439
+ }
2440
+ watch(computedNamespace, setEmptyNamespace);
2441
+ watch(
2442
+ instances,
2443
+ (newInstances) => {
2444
+ r$.value = collectRegles(newInstances);
2445
+ },
2446
+ { deep: true }
2447
+ );
2448
+ function collectRegles(r$Instances) {
2449
+ if (computedNamespace.value) {
2450
+ const namespaceInstances = r$Instances[computedNamespace.value] ?? {};
2451
+ return mergeRegles(namespaceInstances, true);
2452
+ } else {
2453
+ return mergeRegles(r$Instances["~~global"] ?? {}, true);
2454
+ }
2455
+ }
2411
2456
  return { r$: regle.r$ };
2412
2457
  }
2413
- return { useCollectScopedValidations };
2458
+ return { useCollectScope };
2414
2459
  }
2415
- function createUseScopedRegleComposable(customUseRegle) {
2460
+ function createUseScopedRegleComposable(instances, customUseRegle) {
2416
2461
  const scopedUseRegle = customUseRegle ?? useRegle;
2417
- const instances = ref({});
2418
2462
  const useScopedRegle = (state, rulesFactory, options) => {
2419
- const $id = randomId();
2420
- const { r$ } = scopedUseRegle(state, rulesFactory, options);
2421
- instances.value[$id] = r$;
2422
- onScopeDispose(() => {
2423
- delete instances.value[$id];
2463
+ const { namespace, ...restOptions } = options ?? {};
2464
+ const computedNamespace = computed(() => toValue(namespace));
2465
+ const $id = ref(`${Object.keys(instances.value).length + 1}-${randomId()}`);
2466
+ const instanceName = computed(() => {
2467
+ return `instance-${$id.value}`;
2468
+ });
2469
+ const { r$ } = scopedUseRegle(state, rulesFactory, restOptions);
2470
+ register();
2471
+ tryOnScopeDispose(dispose);
2472
+ watch(computedNamespace, (newName, oldName) => {
2473
+ dispose(oldName);
2474
+ register();
2424
2475
  });
2425
- function $dispose() {
2426
- delete instances.value[$id];
2476
+ if (getCurrentInstance()) {
2477
+ onMounted(() => {
2478
+ const currentInstance = getCurrentInstance();
2479
+ if (typeof window !== "undefined" && currentInstance?.proxy?.$el?.parentElement) {
2480
+ if (document.documentElement && !document.documentElement.contains(currentInstance?.proxy?.$el?.parentElement)) {
2481
+ dispose();
2482
+ }
2483
+ }
2484
+ });
2485
+ }
2486
+ function dispose(oldName) {
2487
+ const nameToClean = oldName ?? computedNamespace.value;
2488
+ if (nameToClean) {
2489
+ if (instances.value[nameToClean]) {
2490
+ delete instances.value[nameToClean][instanceName.value];
2491
+ }
2492
+ } else if (instances.value["~~global"][instanceName.value]) {
2493
+ delete instances.value["~~global"][instanceName.value];
2494
+ }
2427
2495
  }
2428
- return { r$, $dispose };
2496
+ function register() {
2497
+ if (computedNamespace.value) {
2498
+ if (!instances.value[computedNamespace.value]) {
2499
+ instances.value[computedNamespace.value] = {};
2500
+ }
2501
+ instances.value[computedNamespace.value][instanceName.value] = r$;
2502
+ } else {
2503
+ if (!instances.value["~~global"]) {
2504
+ instances.value["~~global"] = {};
2505
+ }
2506
+ instances.value["~~global"][instanceName.value] = r$;
2507
+ }
2508
+ }
2509
+ return { r$, dispose, register };
2429
2510
  };
2430
- return { useScopedRegle, instances };
2511
+ return { useScopedRegle };
2431
2512
  }
2432
2513
 
2433
2514
  // src/core/createScopedUseRegle/createScopedUseRegle.ts
2434
- function createScopedUseRegle(customUseRegle) {
2435
- const { instances, useScopedRegle } = createUseScopedRegleComposable(customUseRegle);
2436
- const { useCollectScopedValidations } = createUseCollectScopedValidations(instances);
2515
+ function createScopedUseRegle(options) {
2516
+ const useInstances = options?.customStore ? () => {
2517
+ if (options.customStore) {
2518
+ if (!options.customStore?.value["~~global"]) {
2519
+ options.customStore.value["~~global"] = {};
2520
+ } else if (options.customStore?.value) {
2521
+ options.customStore.value = { "~~global": {} };
2522
+ }
2523
+ }
2524
+ return options.customStore;
2525
+ } : createGlobalState(() => {
2526
+ const $inst = ref({ "~~global": {} });
2527
+ return $inst;
2528
+ });
2529
+ const instances = useInstances();
2530
+ const { useScopedRegle } = createUseScopedRegleComposable(instances, options?.customUseRegle);
2531
+ const { useCollectScope } = createUseCollectScope(instances);
2437
2532
  return {
2438
2533
  useScopedRegle,
2439
- useCollectScopedValidations
2534
+ useCollectScope
2440
2535
  };
2441
2536
  }
2442
2537
 
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@regle/core",
3
- "version": "0.7.4-beta.3",
3
+ "version": "0.7.5",
4
4
  "description": "Type safe form validation library for Vue 3",
5
5
  "peerDependencies": {
6
- "vue": ">=3.3.0",
7
- "pinia": ">=2.2.5"
6
+ "pinia": ">=2.2.5",
7
+ "vue": ">=3.3.0"
8
8
  },
9
9
  "peerDependenciesMeta": {
10
10
  "pinia": {
@@ -13,12 +13,12 @@
13
13
  },
14
14
  "devDependencies": {
15
15
  "@total-typescript/ts-reset": "0.6.1",
16
- "@types/node": "22.10.5",
17
- "@typescript-eslint/eslint-plugin": "8.19.1",
18
- "@typescript-eslint/parser": "8.19.1",
16
+ "@types/node": "22.10.7",
17
+ "@typescript-eslint/eslint-plugin": "8.21.0",
18
+ "@typescript-eslint/parser": "8.21.0",
19
19
  "@vue/test-utils": "2.4.6",
20
- "bumpp": "9.10.0",
21
- "changelogithub": "0.13.11",
20
+ "bumpp": "9.10.2",
21
+ "changelogithub": "13.12.1",
22
22
  "cross-env": "7.0.3",
23
23
  "eslint": "9.15.0",
24
24
  "eslint-config-prettier": "9.1.0",
@@ -26,7 +26,7 @@
26
26
  "expect-type": "1.1.0",
27
27
  "prettier": "3.3.3",
28
28
  "tsup": "8.3.5",
29
- "type-fest": "4.32.0",
29
+ "type-fest": "4.33.0",
30
30
  "typescript": "5.6.3",
31
31
  "vitest": "2.1.8",
32
32
  "vue": "3.5.13",