Skip to content

Commit dfc714d

Browse files
feat: $path for collections now uses index while preserving cache
1 parent 1121a3c commit dfc714d

File tree

18 files changed

+270
-48
lines changed

18 files changed

+270
-48
lines changed

docs/src/core-concepts/rules/reusable-rules.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ export const myValidator = createRule({
108108
validator: (value: Maybe<string>, optionalArg?: number, otherOptional?: string) => {
109109
return true;
110110
},
111-
message: ({ $params: [optionalArg, ...anyOtherArg] }) => {
111+
message: ({ $params: [optionalArg, otherOptional] }) => {
112112
return 'This field is invalid';
113113
}
114114
});

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,8 @@
9595
},
9696
"engines": {
9797
"node": ">=20 < 23",
98-
"pnpm": ">=9.7.0"
98+
"pnpm": ">=10.12.1"
9999
},
100100
"license": "MIT",
101-
"packageManager": "pnpm@9.7.1"
101+
"packageManager": "pnpm@10.12.1+sha512.f0dda8580f0ee9481c5c79a1d927b9164f2c478e90992ad268bbb2465a736984391d6333d2c327913578b2804af33474ca554ba29c04a8b13060a717675ae3ac"
102102
}

packages/core/src/core/createRule/createRule.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1-
import type { InferRegleRule, RegleRuleInit, RegleRuleMetadataDefinition, RegleUniversalParams } from '../../types';
1+
import type {
2+
$InternalRegleRuleInit,
3+
InferRegleRule,
4+
RegleRuleInit,
5+
RegleRuleMetadataDefinition,
6+
RegleUniversalParams,
7+
} from '../../types';
28
import { defineRuleProcessors } from './defineRuleProcessors';
39
import { getFunctionParametersLength } from './unwrapRuleParameters';
410

@@ -44,9 +50,12 @@ export function createRule<
4450
): InferRegleRule<TValue, TParams, TAsync, TMetadata> {
4551
if (typeof definition.validator === 'function') {
4652
let fakeParams: any[] = [];
47-
const staticProcessors = defineRuleProcessors(definition as any, ...fakeParams);
48-
4953
const isAsync = definition.async ?? definition.validator.constructor.name === 'AsyncFunction';
54+
const staticProcessors = defineRuleProcessors(
55+
{ ...definition, async: isAsync } as $InternalRegleRuleInit,
56+
...fakeParams
57+
);
58+
5059
// For validators needing a params like maxLength or requiredIf
5160
if (getFunctionParametersLength(definition.validator) > 1) {
5261
// For validators with param, return a function providing params for all the rule processors

packages/core/src/core/createRule/defineRuleProcessors.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ export function defineRuleProcessors(
1313
definition: $InternalRegleRuleInit,
1414
...params: any[]
1515
): $InternalRegleRuleDefinition {
16-
const { validator, type } = definition;
16+
const { validator, type, async } = definition;
1717

18-
const isAsync = type === InternalRuleType.Async || validator.constructor.name === 'AsyncFunction';
18+
const isAsync = async || type === InternalRuleType.Async || validator.constructor.name === 'AsyncFunction';
1919

2020
const defaultProcessors = {
2121
validator(value: any, ...args: any[]) {
@@ -79,6 +79,7 @@ export function defineRuleProcessors(
7979

8080
const processors = markRaw({
8181
...defaultProcessors,
82+
type,
8283
_validator: definition.validator as any,
8384
_message: definition.message,
8485
_active: definition.active,

packages/core/src/core/useRegle/root/collections/createReactiveCollectionElement.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ interface CreateCollectionElementArgs extends CommonResolverOptions {
2525
export function createCollectionElement({
2626
$id,
2727
path,
28+
cachePath,
2829
index,
2930
options,
3031
storage,
@@ -39,7 +40,8 @@ export function createCollectionElement({
3940
schemaMode,
4041
}: CreateCollectionElementArgs): $InternalRegleStatusType | undefined {
4142
const $fieldId = rules.$key ? rules.$key : randomId();
42-
let $path = `${path}.${String($fieldId)}`;
43+
let $cachePath = `${path}.${String($fieldId)}`;
44+
let $path = `${path}.${index}`;
4345

4446
if (typeof stateValue.value === 'object' && stateValue.value != null) {
4547
if (!stateValue.value.$id) {
@@ -52,7 +54,7 @@ export function createCollectionElement({
5254
},
5355
});
5456
} else {
55-
$path = `${path}.${stateValue.value.$id}`;
57+
$cachePath = `${path}.${stateValue.value.$id}`;
5658
}
5759
}
5860

@@ -64,6 +66,7 @@ export function createCollectionElement({
6466
rulesDef: toRef(() => rules),
6567
customMessages,
6668
path: $path,
69+
cachePath: $cachePath,
6770
storage,
6871
options,
6972
externalErrors: $externalErrors,

packages/core/src/core/useRegle/root/collections/createReactiveCollectionRoot.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ export function createReactiveCollectionStatus({
153153
const element = createCollectionElement({
154154
$id: $id.value,
155155
path,
156+
cachePath: path,
156157
customMessages,
157158
rules: unwrapped ?? {},
158159
stateValue: toRef(() => value),
@@ -182,6 +183,7 @@ export function createReactiveCollectionStatus({
182183
rulesDef,
183184
customMessages,
184185
path,
186+
cachePath: path,
185187
storage,
186188
options,
187189
externalErrors: toRef(externalErrors?.value ?? {}, `$self`),
@@ -220,6 +222,7 @@ export function createReactiveCollectionStatus({
220222
const element = createCollectionElement({
221223
$id: $id.value,
222224
path,
225+
cachePath: path,
223226
customMessages,
224227
rules: unwrapped ?? {},
225228
stateValue: currentValue,
@@ -424,6 +427,7 @@ export function createReactiveCollectionStatus({
424427
reactive({
425428
$dirty,
426429
$error,
430+
$path: path,
427431
$silentValue: $silentValue as any,
428432
$pending,
429433
$invalid,
@@ -596,6 +600,7 @@ export function createReactiveCollectionStatus({
596600
$self: $selfStatus,
597601
...restScopeState,
598602
...$shortcuts,
603+
$path: path,
599604
$each: $eachStatus,
600605
$value: state,
601606
$validate,

packages/core/src/core/useRegle/root/common/common-types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export type StateWithId = unknown & { $id?: string };
1111
export interface CommonResolverOptions {
1212
customMessages: CustomRulesDeclarationTree | undefined;
1313
path: string;
14+
cachePath: string;
1415
index?: number;
1516
storage: RegleStorage;
1617
options: ResolvedRegleBehaviourOptions;

packages/core/src/core/useRegle/root/createReactiveFieldStatus.ts

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ export function createReactiveFieldStatus({
3434
rulesDef,
3535
customMessages,
3636
path,
37+
cachePath,
3738
fieldName,
3839
storage,
3940
options,
@@ -75,7 +76,6 @@ export function createReactiveFieldStatus({
7576
let fieldScopes: EffectScope[] = [];
7677

7778
let $unwatchState: WatchStopHandle;
78-
let $unwatchValid: WatchStopHandle;
7979
let $unwatchDirty: WatchStopHandle;
8080
let $unwatchAsync: WatchStopHandle;
8181
let $unwatchRuleFieldValues: WatchStopHandle;
@@ -84,7 +84,7 @@ export function createReactiveFieldStatus({
8484

8585
function createReactiveRulesResult() {
8686
const declaredRules = rulesDef.value as RegleRuleDecl<any, any>;
87-
const storeResult = storage.checkRuleDeclEntry(path, declaredRules);
87+
const storeResult = storage.checkRuleDeclEntry(cachePath, declaredRules);
8888

8989
$localOptions.value = Object.fromEntries(
9090
Object.entries(declaredRules).filter(([ruleKey]) => ruleKey.startsWith('$'))
@@ -109,7 +109,8 @@ export function createReactiveFieldStatus({
109109
rule: ruleRef as any,
110110
ruleKey,
111111
state,
112-
path,
112+
path: path,
113+
cachePath: cachePath,
113114
storage,
114115
$debounce: $localOptions.value.$debounce,
115116
}),
@@ -126,7 +127,7 @@ export function createReactiveFieldStatus({
126127
define$commit();
127128

128129
if (storeResult?.valid != null) {
129-
scopeState.$dirty.value = storage.getDirtyState(path);
130+
scopeState.$dirty.value = storage.getDirtyState(cachePath);
130131
if (
131132
(scopeState.$dirty.value && !scopeState.$silent.value) ||
132133
(scopeState.$rewardEarly.value && scopeState.$error.value)
@@ -135,7 +136,7 @@ export function createReactiveFieldStatus({
135136
}
136137
}
137138

138-
storage.addRuleDeclEntry(path, declaredRules);
139+
storage.addRuleDeclEntry(cachePath, declaredRules);
139140
}
140141

141142
function define$commit() {
@@ -154,7 +155,7 @@ export function createReactiveFieldStatus({
154155
$unwatchDirty();
155156
$unwatchRuleFieldValues?.();
156157
if (scopeState.$dirty.value) {
157-
storage.setDirtyEntry(path, scopeState.$dirty.value);
158+
storage.setDirtyEntry(cachePath, scopeState.$dirty.value);
158159
}
159160

160161
$unwatchState?.();
@@ -457,7 +458,7 @@ export function createReactiveFieldStatus({
457458
define$watchState();
458459

459460
$unwatchDirty = watch(scopeState.$dirty, (newDirty) => {
460-
storage.setDirtyEntry(path, newDirty);
461+
storage.setDirtyEntry(cachePath, newDirty);
461462
Object.values($rules.value).forEach((rule) => {
462463
rule.$fieldDirty = newDirty;
463464
});
@@ -516,7 +517,7 @@ export function createReactiveFieldStatus({
516517
function $reset(options?: ResetOptions<unknown>, fromParent?: boolean): void {
517518
$clearExternalErrors();
518519
scopeState.$dirty.value = false;
519-
storage.setDirtyEntry(path, false);
520+
storage.setDirtyEntry(cachePath, false);
520521

521522
if (!fromParent) {
522523
if (options?.toInitialState) {
@@ -651,6 +652,7 @@ export function createReactiveFieldStatus({
651652
$value: state,
652653
$rules: $rules,
653654
...$shortcuts,
655+
$path: path,
654656
$reset,
655657
$touch,
656658
$validate,

packages/core/src/core/useRegle/root/createReactiveNestedStatus.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ export function createReactiveNestedStatus({
4141
rulesDef,
4242
state,
4343
path = '',
44+
cachePath,
4445
rootRules,
4546
externalErrors,
4647
schemaErrors,
@@ -94,6 +95,7 @@ export function createReactiveNestedStatus({
9495
state: stateRef,
9596
rulesDef: statePropRulesRef,
9697
path: path ? `${path}.${statePropKey}` : statePropKey,
98+
cachePath: cachePath ? `${cachePath}.${statePropKey}` : statePropKey,
9799
externalErrors: $externalErrors,
98100
schemaErrors: $schemaErrors,
99101
initialState: initialStateRef,
@@ -114,12 +116,14 @@ export function createReactiveNestedStatus({
114116
const $externalErrors = toRef(externalErrors?.value ?? {}, key);
115117
const $schemaErrors = computed(() => schemaErrors?.value?.[key]);
116118
const initialStateRef = toRef(initialState?.value ?? {}, key);
119+
117120
return [
118121
key,
119122
createReactiveChildrenStatus({
120123
state: stateRef,
121124
rulesDef: computed(() => ({})),
122125
path: path ? `${path}.${key}` : key,
126+
cachePath: cachePath ? `${cachePath}.${key}` : key,
123127
externalErrors: $externalErrors,
124128
schemaErrors: $schemaErrors,
125129
initialState: initialStateRef,
@@ -136,13 +140,15 @@ export function createReactiveNestedStatus({
136140
const $externalErrors = toRef(externalErrors?.value ?? {}, key);
137141
const $schemaErrors = computed(() => schemaErrors?.value?.[key]);
138142
const initialStateRef = toRef(initialState?.value ?? {}, key);
143+
const computedPath = path ? `${path}.${key}` : key;
139144

140145
return [
141146
key,
142147
createReactiveChildrenStatus({
143148
state: stateRef,
144149
rulesDef: computed(() => ({})),
145150
path: path ? `${path}.${key}` : key,
151+
cachePath: cachePath ? `${cachePath}.${key}` : key,
146152
externalErrors: $externalErrors,
147153
schemaErrors: $schemaErrors,
148154
initialState: initialStateRef,
@@ -171,6 +177,7 @@ export function createReactiveNestedStatus({
171177
state: stateRef,
172178
rulesDef: computed(() => ({})),
173179
path: path ? `${path}.${key}` : key,
180+
cachePath: cachePath ? `${cachePath}.${key}` : key,
174181
externalErrors: $externalErrors,
175182
schemaErrors: $schemaErrors,
176183
initialState: initialStateRef,
@@ -415,6 +422,7 @@ export function createReactiveNestedStatus({
415422
result.value = value(
416423
reactive({
417424
$dirty,
425+
$path: path,
418426
$value: state as any,
419427
$silentValue: $silentValue as any,
420428
$error,
@@ -631,6 +639,7 @@ export function createReactiveNestedStatus({
631639
return reactive({
632640
...restScopeState,
633641
...$shortcuts,
642+
$path: path,
634643
$fields,
635644
$reset,
636645
$touch,

packages/core/src/core/useRegle/root/createReactiveRuleStatus.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ interface CreateReactiveRuleStatusOptions {
2525
};
2626
customMessages: CustomRulesDeclarationTree | undefined;
2727
path: string;
28+
cachePath: string;
2829
storage: RegleStorage;
2930
$debounce?: number;
3031
}
@@ -35,6 +36,7 @@ export function createReactiveRuleStatus({
3536
ruleKey,
3637
state,
3738
path,
39+
cachePath,
3840
storage,
3941
$debounce,
4042
modifiers,
@@ -63,7 +65,7 @@ export function createReactiveRuleStatus({
6365
const $haveAsync = ref(false);
6466
const $maybePending = ref(false);
6567

66-
const { $pending, $valid, $metadata, $validating } = storage.trySetRuleStatusRef(`${path}.${ruleKey}`);
68+
const { $pending, $valid, $metadata, $validating } = storage.trySetRuleStatusRef(`${cachePath}.${ruleKey}`);
6769

6870
function $watch() {
6971
scope = effectScope();

0 commit comments

Comments
 (0)