@regle/core 0.1.4 → 0.1.6

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.
@@ -0,0 +1,484 @@
1
+ import * as vue from 'vue';
2
+ import { MaybeRef, Ref, ComputedRef, UnwrapNestedRefs } from 'vue';
3
+
4
+ type Maybe<T = any> = T | null | undefined;
5
+ type MaybeGetter<T, V = any> = T | ((value: Ref<V>, index: number) => T);
6
+ type ExtractFromGetter<T extends MaybeGetter<any, any>> = T extends MaybeGetter<infer U, any> ? U : never;
7
+ type DeepMaybeRef<T extends Record<string, any>> = {
8
+ [K in keyof T]: MaybeRef<T[K]>;
9
+ };
10
+ type ExcludeByType<T, U> = {
11
+ [K in keyof T as T[K] extends U ? never : K]: T[K] extends U ? never : T[K];
12
+ };
13
+ type NonPresentKeys<TSource extends Record<string, any>, Target extends Record<string, any>> = Omit<Target, keyof TSource>;
14
+
15
+ type ArrayElement<T> = T extends Array<infer U> ? U : never;
16
+
17
+ declare global {
18
+ // eslint-disable-next-line @typescript-eslint/consistent-type-definitions -- It has to be an `interface` so that it can be merged.
19
+ interface SymbolConstructor {
20
+ readonly observable: symbol;
21
+ }
22
+ }
23
+
24
+ declare const emptyObjectSymbol: unique symbol;
25
+
26
+ /**
27
+ Represents a strictly empty plain object, the `{}` value.
28
+
29
+ When you annotate something as the type `{}`, it can be anything except `null` and `undefined`. This means that you cannot use `{}` to represent an empty plain object ([read more](https://stackoverflow.com/questions/47339869/typescript-empty-object-and-any-difference/52193484#52193484)).
30
+
31
+ @example
32
+ ```
33
+ import type {EmptyObject} from 'type-fest';
34
+
35
+ // The following illustrates the problem with `{}`.
36
+ const foo1: {} = {}; // Pass
37
+ const foo2: {} = []; // Pass
38
+ const foo3: {} = 42; // Pass
39
+ const foo4: {} = {a: 1}; // Pass
40
+
41
+ // With `EmptyObject` only the first case is valid.
42
+ const bar1: EmptyObject = {}; // Pass
43
+ const bar2: EmptyObject = 42; // Fail
44
+ const bar3: EmptyObject = []; // Fail
45
+ const bar4: EmptyObject = {a: 1}; // Fail
46
+ ```
47
+
48
+ Unfortunately, `Record<string, never>`, `Record<keyof any, never>` and `Record<never, never>` do not work. See {@link https://github.com/sindresorhus/type-fest/issues/395 #395}.
49
+
50
+ @category Object
51
+ */
52
+ type EmptyObject = {[emptyObjectSymbol]?: never};
53
+
54
+ interface RegleBehaviourOptions {
55
+ /**
56
+ * Only display error when calling `validateState()`
57
+ * @default false
58
+ */
59
+ lazy?: boolean;
60
+ /**
61
+ * Automaticaly set the dirty set without the need of `$value` or `$touch`
62
+ * @default true
63
+ */
64
+ autoDirty?: boolean;
65
+ /**
66
+ * The fields will turn valid when they are, but not invalid unless calling `validateState()`
67
+ * @default false
68
+ *
69
+ * @experimental report any bug
70
+ */
71
+ rewardEarly?: boolean;
72
+ }
73
+ interface LocalRegleBehaviourOptions<TState extends Record<string, any>, TRules extends ReglePartialValidationTree<TState, CustomRulesDeclarationTree>, TExternal extends RegleExternalErrorTree<TState>, TValidationGroups extends Record<string, RegleValidationGroupEntry[]>> {
74
+ externalErrors?: MaybeRef<TExternal>;
75
+ validationGroups?: (fields: RegleStatus<TState, TRules>['$fields']) => TValidationGroups;
76
+ }
77
+ type RegleValidationGroupEntry = RegleFieldStatus<any, any, any>;
78
+ interface RegleValidationGroupOutput {
79
+ $invalid: boolean;
80
+ $error: boolean;
81
+ $pending: boolean;
82
+ $dirty: boolean;
83
+ $valid: boolean;
84
+ $errors: string[];
85
+ $silentErrors: string[];
86
+ }
87
+ type FieldRegleBehaviourOptions = AddDollarToOptions<RegleBehaviourOptions> & {
88
+ $debounce?: number;
89
+ };
90
+ type AddDollarToOptions<T extends Record<string, any>> = {
91
+ [K in keyof T as `$${string & K}`]: T[K];
92
+ };
93
+
94
+ interface Regle<TState extends Record<string, any> = EmptyObject, TRules extends ReglePartialValidationTree<TState, CustomRulesDeclarationTree> = EmptyObject, TExternal extends RegleExternalErrorTree<TState> = never, TValidationGroups extends Record<string, RegleValidationGroupEntry[]> = never> {
95
+ regle: RegleStatus<TState, TRules, TValidationGroups>;
96
+ /** Show active errors based on your behaviour options (lazy, autoDirty)
97
+ * It allow you to skip scouting the `regle` object
98
+ */
99
+ errors: RegleErrorTree<TRules, TExternal>;
100
+ ready: ComputedRef<boolean>;
101
+ resetAll: () => void;
102
+ validateState: () => Promise<false | DeepSafeFormState<TState, TRules>>;
103
+ state: Ref<TState>;
104
+ }
105
+ type DeepReactiveState<T extends Record<string, any>> = {
106
+ [K in keyof T]: MaybeRef<T[K]>;
107
+ };
108
+ type DeepSafeFormState<TState extends Record<string, any>, TRules extends ReglePartialValidationTree<TState, CustomRulesDeclarationTree>> = [unknown] extends [TState] ? {} : {
109
+ [K in keyof TState as [SafeProperty<TState[K], TRules[K]>] extends [never] ? K : never]?: [
110
+ SafeProperty<TState[K], TRules[K]>
111
+ ] extends [never] ? TState[K] : SafeProperty<TState[K], TRules[K]>;
112
+ } & {
113
+ [K in keyof TState as [SafeProperty<TState[K], TRules[K]>] extends [never] ? never : K]-?: SafeProperty<TState[K], TRules[K]>;
114
+ };
115
+ type SafeProperty<TState, TRule extends RegleFormPropertyType<any, any> | undefined = never> = TRule extends RegleCollectionRuleDefinition<any, any> ? TState extends Array<any> ? SafeProperty<TState[number], ExtractFromGetter<TRule['$each']>>[] : never : TRule extends ReglePartialValidationTree<any, any> ? TState extends Record<string, any> ? DeepSafeFormState<TState, TRule> : TRule extends RegleRuleDecl<any, any> ? unknown extends TRule['required'] ? never : TRule['required'] extends undefined ? never : TRule['required'] extends RegleRuleDefinition<any, infer Params, any, any, any> ? Params extends never[] ? TState : never : never : never : never;
116
+
117
+ type ParamDecl<T = any> = MaybeRef<Maybe<T>> | (() => Maybe<T>);
118
+ type CreateFn<T extends any[]> = (...args: T) => any;
119
+ /**
120
+ * Transform normal parameters tuple declaration to a rich tuple declaration
121
+ *
122
+ * [foo: string, bar?: number] => [foo: MaybeRef<string> | (() => string), bar?: MaybeRef<number | undefined> | (() => number) | undefined]
123
+ */
124
+ type RegleUniversalParams<T extends any[] = [], F = CreateFn<T>> = [T] extends [[]] ? [] : Parameters<F extends (...args: infer Args) => any ? (...args: {
125
+ [K in keyof Args]: ParamDecl<Args[K]>;
126
+ }) => any : never>;
127
+ type UnwrapRegleUniversalParams<T extends ParamDecl[] = [], F = CreateFn<T>> = [T] extends [
128
+ [
129
+ ]
130
+ ] ? [] : Parameters<F extends (...args: infer Args) => any ? (...args: {
131
+ [K in keyof Args]: Args[K] extends ParamDecl<infer U> ? U : Args[K];
132
+ }) => any : never>;
133
+
134
+ /**
135
+ * Internal definition of the rule, can be used to reset or patch the rule
136
+ */
137
+ interface RegleInternalRuleDefs<TValue extends any = any, TParams extends any[] = [], TAsync extends boolean = false, TMetadata extends RegleRuleMetadataDefinition = boolean> {
138
+ _validator: (value: Maybe<TValue>, ...args: TParams) => TAsync extends false ? TMetadata : Promise<TMetadata>;
139
+ _message: string | string[] | ((value: Maybe<TValue>, metadata: PossibleRegleRuleMetadataConsumer) => string | string[]);
140
+ _active?: boolean | ((value: Maybe<TValue>, metadata: PossibleRegleRuleMetadataConsumer) => boolean);
141
+ _type?: string;
142
+ _patched: boolean;
143
+ _params?: RegleUniversalParams<TParams>;
144
+ _async: TAsync;
145
+ }
146
+ declare enum InternalRuleType {
147
+ Inline = "__inline",
148
+ Async = "__async"
149
+ }
150
+
151
+ /**
152
+ * Returned typed of rules created with `createRule`
153
+ * */
154
+ interface RegleRuleDefinition<TValue extends any = any, TParams extends any[] = [], TAsync extends boolean = boolean, TMetaData extends RegleRuleMetadataDefinition = RegleRuleMetadataDefinition, TFilteredValue extends any = TValue extends Date & File & infer M ? M : TValue> extends RegleInternalRuleDefs<TFilteredValue, TParams, TAsync, TMetaData> {
155
+ validator: RegleRuleDefinitionProcessor<TFilteredValue, TParams, TAsync extends false ? TMetaData : Promise<TMetaData>>;
156
+ message: RegleRuleDefinitionWithMetadataProcessor<TFilteredValue, PossibleRegleRuleMetadataConsumer, string | string[]>;
157
+ active: RegleRuleDefinitionWithMetadataProcessor<TFilteredValue, PossibleRegleRuleMetadataConsumer, boolean>;
158
+ type?: string;
159
+ exec: (value: Maybe<TFilteredValue>) => TAsync extends false ? TMetaData : Promise<TMetaData>;
160
+ }
161
+ /**
162
+ * Rules with params created with `createRules` are callable while being customizable
163
+ */
164
+ interface RegleRuleWithParamsDefinition<TValue extends any = any, TParams extends any[] = [], TAsync extends boolean = false, TMetadata extends RegleRuleMetadataDefinition = boolean> extends RegleRuleCore<TValue, TParams, TAsync, TMetadata>, RegleInternalRuleDefs<TValue, TParams, TAsync, TMetadata> {
165
+ (...params: RegleUniversalParams<TParams>): RegleRuleDefinition<TValue, TParams, TAsync, TMetadata>;
166
+ }
167
+ type RegleRuleMetadataExtended = {
168
+ $valid: boolean;
169
+ [x: string]: any;
170
+ };
171
+ /**
172
+ * Define a rule Metadata definition
173
+ */
174
+ type RegleRuleMetadataDefinition = RegleRuleMetadataExtended | boolean;
175
+ type DefaultMetadataProperties = Pick<ExcludeByType<RegleCommonStatus, Function>, '$invalid'>;
176
+ /**
177
+ * Will be used to consumme metadata on related helpers and rule status
178
+ */
179
+ type RegleRuleMetadataConsumer<TParams extends any[] = never, TMetadata extends RegleRuleMetadataDefinition = boolean> = DefaultMetadataProperties & (TParams extends never ? {} : {
180
+ $params: TParams;
181
+ }) & (Exclude<TMetadata, boolean> extends RegleRuleMetadataExtended ? TMetadata extends boolean ? Partial<Omit<Exclude<TMetadata, boolean>, '$valid'>> : Omit<Exclude<TMetadata, boolean>, '$valid'> : {});
182
+ /**
183
+ * Will be used to consumme metadata on related helpers and rule status
184
+ */
185
+ type PossibleRegleRuleMetadataConsumer = DefaultMetadataProperties & {
186
+ $params?: any[];
187
+ };
188
+ /**
189
+ * Generic types for a created RegleRule
190
+ */
191
+ type RegleRuleRaw<TValue extends any = any, TParams extends any[] = [], TAsync extends boolean = false, TMetaData extends RegleRuleMetadataDefinition = boolean> = RegleRuleDefinition<TValue, TParams, TAsync, TMetaData> | RegleRuleWithParamsDefinition<TValue, TParams, TAsync, TMetaData>;
192
+ /**
193
+ * Process the type of a created rule with `createRule`.
194
+ * For a rule with params it will return a function
195
+ * Otherwise it will return the rule definition
196
+ */
197
+ type InferRegleRule<TValue extends any = any, TParams extends any[] = [], TAsync extends boolean = false, TMetaData extends RegleRuleMetadataDefinition = boolean> = [TParams] extends [[]] ? RegleRuleDefinition<TValue, TParams, TAsync, TMetaData> : RegleRuleWithParamsDefinition<TValue, TParams, TAsync, TMetaData>;
198
+ type RegleRuleDefinitionProcessor<TValue extends any = any, TParams extends any[] = [], TReturn = any> = (value: Maybe<TValue>, ...params: TParams) => TReturn;
199
+ type RegleRuleDefinitionWithMetadataProcessor<TValue extends any, TMetadata extends RegleRuleMetadataConsumer<any, any>, TReturn = any> = ((value: Maybe<TValue>, metadata: TMetadata) => TReturn) | TReturn;
200
+ type RegleCollectionRuleDefinition<TValue = any[], TCustomRules extends Partial<AllRulesDeclarations> = Partial<AllRulesDeclarations>> = (RegleRuleDecl<NonNullable<TValue>, TCustomRules> & {
201
+ $each: MaybeGetter<RegleFormPropertyType<ArrayElement<NonNullable<TValue>>, TCustomRules>, ArrayElement<TValue>>;
202
+ }) | {
203
+ $each: MaybeGetter<RegleFormPropertyType<ArrayElement<NonNullable<TValue>>, TCustomRules>, ArrayElement<TValue>>;
204
+ };
205
+
206
+ /**
207
+ * @argument
208
+ * createRule arguments options
209
+ */
210
+ interface RegleRuleInit<TValue extends any, TParams extends [...any[]] = [], TReturn extends RegleRuleMetadataDefinition | Promise<RegleRuleMetadataDefinition> = boolean, TMetadata extends RegleRuleMetadataDefinition = RegleRuleMetadataDefinition, TAsync extends boolean = TReturn extends Promise<any> ? true : false> {
211
+ type?: string;
212
+ validator: (value: Maybe<TValue>, ...args: TParams) => TReturn;
213
+ message: string | string[] | ((value: Maybe<TValue>, metadata: RegleRuleMetadataConsumer<TParams, TMetadata>) => string | string[]);
214
+ active?: boolean | ((value: Maybe<TValue>, metadata: RegleRuleMetadataConsumer<TParams, TMetadata>) => boolean);
215
+ }
216
+ /**
217
+ * @argument
218
+ * Rule core
219
+ */
220
+ interface RegleRuleCore<TValue extends any, TParams extends any[] = [], TAsync extends boolean = false, TMetadata extends RegleRuleMetadataDefinition = boolean> {
221
+ validator: (value: Maybe<TValue>, ...args: TParams) => TAsync extends false ? TMetadata : Promise<TMetadata>;
222
+ message: string | ((value: Maybe<TValue>, metadata: RegleRuleMetadataConsumer<TParams, TMetadata>) => string | string[]);
223
+ active?: boolean | ((value: Maybe<TValue>, metadata: RegleRuleMetadataConsumer<TParams, TMetadata>) => boolean);
224
+ type?: string;
225
+ }
226
+
227
+ type DefaultValidators = {
228
+ alpha: RegleRuleDefinition<string>;
229
+ alphaNum: RegleRuleDefinition<string | number>;
230
+ between: RegleRuleWithParamsDefinition<number, [min: Maybe<number>, max: Maybe<number>]>;
231
+ checked: RegleRuleDefinition<boolean, [], false, boolean, boolean>;
232
+ contains: RegleRuleWithParamsDefinition<string, [part: Maybe<string>], false, boolean>;
233
+ dateAfter: RegleRuleWithParamsDefinition<string | Date, [
234
+ after: Maybe<string | Date>
235
+ ], false, true | {
236
+ $valid: false;
237
+ error: 'date-not-after';
238
+ } | {
239
+ $valid: false;
240
+ error: 'value-or-paramater-not-a-date';
241
+ }>;
242
+ dateBefore: RegleRuleWithParamsDefinition<string | Date, [
243
+ before: Maybe<string | Date>
244
+ ], false, true | {
245
+ $valid: false;
246
+ error: 'date-not-before';
247
+ } | {
248
+ $valid: false;
249
+ error: 'value-or-paramater-not-a-date';
250
+ }>;
251
+ dateBetween: RegleRuleWithParamsDefinition<string | Date, [
252
+ before: Maybe<string | Date>,
253
+ after: Maybe<string | Date>
254
+ ], false, boolean>;
255
+ decimal: RegleRuleDefinition<string | number, [], false, boolean, string | number>;
256
+ email: RegleRuleDefinition<string, [], false, boolean, string>;
257
+ endsWith: RegleRuleWithParamsDefinition<string, [part: Maybe<string>], false, boolean>;
258
+ exactLength: RegleRuleWithParamsDefinition<string | any[] | Record<PropertyKey, any>, [
259
+ count: number
260
+ ], false, boolean>;
261
+ integer: RegleRuleDefinition<string | number, [], false, boolean, string | number>;
262
+ ipAddress: RegleRuleDefinition<string, [], false, boolean, string>;
263
+ macAddress: RegleRuleWithParamsDefinition<string, [
264
+ separator?: string | undefined
265
+ ], false, boolean>;
266
+ maxLength: RegleRuleWithParamsDefinition<string | any[] | Record<PropertyKey, any>, [
267
+ count: number
268
+ ], false, boolean>;
269
+ maxValue: RegleRuleWithParamsDefinition<number, [count: number], false, boolean>;
270
+ minLength: RegleRuleWithParamsDefinition<string | any[] | Record<PropertyKey, any>, [
271
+ count: number
272
+ ], false, boolean>;
273
+ minValue: RegleRuleWithParamsDefinition<number, [count: number], false, boolean>;
274
+ numeric: RegleRuleDefinition<string | number, [], false, boolean, string | number>;
275
+ regex: RegleRuleWithParamsDefinition<string, [regexp: RegExp], false, boolean>;
276
+ required: RegleRuleDefinition<unknown, []>;
277
+ sameAs: RegleRuleWithParamsDefinition<unknown, [target: unknown], false, boolean>;
278
+ startsWith: RegleRuleWithParamsDefinition<string, [part: Maybe<string>], false, boolean>;
279
+ url: RegleRuleDefinition<string, [], false, boolean, string>;
280
+ };
281
+
282
+ type CustomRulesDeclarationTree = {
283
+ [x: string]: RegleRuleRaw<any, any, boolean, any> | undefined;
284
+ };
285
+ type AllRulesDeclarations = CustomRulesDeclarationTree & DefaultValidators;
286
+
287
+ /**
288
+ * @public
289
+ */
290
+ type ReglePartialValidationTree<TForm extends Record<string, any>, TCustomRules extends Partial<AllRulesDeclarations> = Partial<AllRulesDeclarations>> = {
291
+ [TKey in keyof TForm]?: RegleFormPropertyType<TForm[TKey], TCustomRules>;
292
+ };
293
+ /**
294
+ * @public
295
+ */
296
+ type RegleValidationTree<TForm extends Record<string, any>, TCustomRules extends Partial<AllRulesDeclarations> = Partial<AllRulesDeclarations>> = {
297
+ [TKey in keyof TForm]: RegleFormPropertyType<TForm[TKey], TCustomRules>;
298
+ };
299
+ /**
300
+ * @public
301
+ */
302
+ type RegleComputedRules<TForm extends MaybeRef<Record<string, any>>, TCustomRules extends Partial<AllRulesDeclarations> | Regle<any, any> = Partial<AllRulesDeclarations>, TState = TForm extends Ref<infer R> ? R : TForm, TCustom = TCustomRules extends Regle<any, infer R> ? R extends ReglePartialValidationTree<any, infer C> ? C : Partial<AllRulesDeclarations> : TCustomRules> = {
303
+ [TKey in keyof TState]?: RegleFormPropertyType<TState[TKey], TCustom extends Partial<AllRulesDeclarations> ? TCustom : {}>;
304
+ };
305
+ /**
306
+ * @public
307
+ */
308
+ type RegleFormPropertyType<TValue = any, TCustomRules extends Partial<AllRulesDeclarations> = Partial<AllRulesDeclarations>> = [NonNullable<TValue>] extends [never] ? RegleRuleDecl<TValue, TCustomRules> : NonNullable<TValue> extends Array<any> ? RegleCollectionRuleDecl<TValue, TCustomRules> : NonNullable<TValue> extends Date ? RegleRuleDecl<NonNullable<TValue>, TCustomRules> : NonNullable<TValue> extends File ? RegleRuleDecl<NonNullable<TValue>, TCustomRules> : NonNullable<TValue> extends Ref<infer V> ? RegleFormPropertyType<V, TCustomRules> : NonNullable<TValue> extends Record<string, any> ? ReglePartialValidationTree<NonNullable<TValue>, TCustomRules> : RegleRuleDecl<NonNullable<TValue>, TCustomRules>;
309
+ /**
310
+ * @public
311
+ * Rule tree for a form property
312
+ */
313
+ type RegleRuleDecl<TValue extends any = any, TCustomRules extends Partial<AllRulesDeclarations> = Partial<AllRulesDeclarations>> = FieldRegleBehaviourOptions & {
314
+ [TKey in keyof TCustomRules]?: NonNullable<TCustomRules[TKey]> extends RegleRuleWithParamsDefinition<any, infer TParams> ? RegleRuleDefinition<TValue, TParams, boolean> : NonNullable<TCustomRules[TKey]> extends RegleRuleDefinition<any, any, any, any> ? FormRuleDeclaration<TValue, any> : FormRuleDeclaration<TValue, any> | FieldRegleBehaviourOptions[keyof FieldRegleBehaviourOptions];
315
+ };
316
+ /**
317
+ * @public
318
+ */
319
+ type RegleCollectionRuleDeclKeyProperty = {
320
+ $key?: PropertyKey;
321
+ };
322
+ /**
323
+ * @public
324
+ */
325
+ type RegleCollectionRuleDecl<TValue = any[], TCustomRules extends Partial<AllRulesDeclarations> = Partial<AllRulesDeclarations>> = (RegleRuleDecl<NonNullable<TValue>, TCustomRules> & {
326
+ $each?: MaybeGetter<RegleFormPropertyType<ArrayElement<NonNullable<TValue>>, TCustomRules> & RegleCollectionRuleDeclKeyProperty, ArrayElement<TValue>>;
327
+ }) | {
328
+ $each?: MaybeGetter<RegleFormPropertyType<ArrayElement<NonNullable<TValue>>, TCustomRules>, ArrayElement<TValue>>;
329
+ };
330
+ /**
331
+ * @public
332
+ */
333
+ type InlineRuleDeclaration<TValue extends any = any, TParams extends any[] = any[], TReturn extends RegleRuleMetadataDefinition | Promise<RegleRuleMetadataDefinition> = RegleRuleMetadataDefinition | Promise<RegleRuleMetadataDefinition>> = (value: Maybe<TValue>, ...args: UnwrapRegleUniversalParams<TParams>) => TReturn;
334
+ /**
335
+ * @public
336
+ * Regroup inline and registered rules
337
+ * */
338
+ type FormRuleDeclaration<TValue extends any, TParams extends any[], TReturn extends RegleRuleMetadataDefinition | Promise<RegleRuleMetadataDefinition> = RegleRuleMetadataDefinition | Promise<RegleRuleMetadataDefinition>, TMetadata extends RegleRuleMetadataDefinition = TReturn extends Promise<infer M> ? M : TReturn, TAsync extends boolean = boolean> = InlineRuleDeclaration<TValue, TParams, TReturn> | RegleRuleDefinition<TValue, TParams, TAsync, TMetadata>;
339
+
340
+ type RegleErrorTree<TRules extends ReglePartialValidationTree<any, any>, TExternal extends RegleExternalErrorTree<Record<string, unknown>> = never> = {
341
+ readonly [K in keyof TRules]: RegleValidationErrors<TRules[K], K extends keyof TExternal ? TExternal[K] : never>;
342
+ } & {
343
+ readonly [K in keyof NonPresentKeys<TRules, TExternal>]: RegleExternalValidationErrorsReport<TExternal[K]>;
344
+ };
345
+ type RegleValidationErrors<TRule extends RegleFormPropertyType<any, any> | undefined = never, TExternalError extends RegleExternalValidationErrors<any> | undefined = never> = TRule extends RegleCollectionRuleDefinition ? RegleCollectionErrors<ExtractFromGetter<TRule['$each']>, TExternalError extends RegleExternalCollectionErrors ? ArrayElement<TExternalError['$each']> : never> : TRule extends RegleRuleDecl<any, any> ? string[] : TRule extends ReglePartialValidationTree<any, any> ? RegleErrorTree<TRule, TExternalError extends RegleExternalErrorTree ? TExternalError : never> : string[];
346
+ type RegleCollectionErrors<TRule extends RegleFormPropertyType<any, any> | undefined = never, TExternalError extends RegleExternalValidationErrors<any> | undefined = never> = {
347
+ readonly $errors: string[];
348
+ readonly $each: RegleValidationErrors<TRule, TExternalError>[];
349
+ };
350
+ type RegleExternalErrorTree<TState extends Record<string, any> = Record<string, any>> = {
351
+ [K in keyof TState]?: RegleExternalValidationErrors<TState[K]>;
352
+ };
353
+ type RegleExternalValidationErrors<TValue extends any> = [NonNullable<TValue>] extends [
354
+ never
355
+ ] ? string[] : TValue extends Array<infer U> ? RegleExternalCollectionErrors<U> : NonNullable<TValue> extends Date ? string[] : NonNullable<TValue> extends File ? string[] : TValue extends Record<string, any> ? RegleExternalErrorTree<TValue> : string[];
356
+ type RegleExternalCollectionErrors<TValue extends any = any> = {
357
+ $errors?: string[];
358
+ $each?: RegleExternalValidationErrors<TValue>[];
359
+ };
360
+ type RegleExternalValidationErrorsReport<TExternalError extends RegleExternalValidationErrors<any> | undefined = never> = TExternalError extends RegleExternalCollectionErrors ? RegleCollectionErrors<TExternalError['$each']> : TExternalError extends string[] ? string[] : TExternalError extends RegleExternalErrorTree<any> ? RegleErrorTree<TExternalError> : string[];
361
+
362
+ /**
363
+ * @public
364
+ */
365
+ type RegleStatus<TState extends Record<string, any> = Record<string, any>, TRules extends ReglePartialValidationTree<TState> = Record<string, any>, TValidationGroups extends Record<string, RegleValidationGroupEntry[]> = never> = RegleCommonStatus<TState> & {
366
+ readonly $fields: {
367
+ readonly [TKey in keyof TRules]: InferRegleStatusType<NonNullable<TRules[TKey]>, TState, TKey>;
368
+ };
369
+ readonly $errors: RegleErrorTree<TRules>;
370
+ readonly $silentErrors: RegleErrorTree<TRules>;
371
+ } & ([TValidationGroups] extends [never] ? {} : {
372
+ $groups: {
373
+ readonly [TKey in keyof TValidationGroups]: RegleValidationGroupOutput;
374
+ };
375
+ });
376
+ /**
377
+ * @public
378
+ */
379
+ type InferRegleStatusType<TRule extends RegleCollectionRuleDecl | RegleRuleDecl | ReglePartialValidationTree<any>, TState extends Record<PropertyKey, any> = any, TKey extends PropertyKey = string> = TRule extends RegleCollectionRuleDefinition<any, any> ? NonNullable<TState[TKey]> extends Array<Record<string, any> | any> ? ExtractFromGetter<TRule['$each']> extends RegleRuleDecl | ReglePartialValidationTree<any> ? RegleCollectionStatus<ExtractFromGetter<TRule['$each']>, TState[TKey], TRule> : never : RegleFieldStatus<TRule, TState, TKey> : TRule extends ReglePartialValidationTree<any> ? NonNullable<TState[TKey]> extends Array<any> ? RegleCommonStatus<TState[TKey]> : NonNullable<TState[TKey]> extends Record<PropertyKey, any> ? RegleStatus<TState[TKey], TRule> : RegleFieldStatus<TRule, TState, TKey> : RegleFieldStatus<TRule, TState, TKey>;
380
+ /**
381
+ * @public
382
+ */
383
+ interface RegleFieldStatus<TRules extends RegleFormPropertyType<any, Partial<AllRulesDeclarations>> = Record<string, any>, TState extends Record<PropertyKey, any> = any, TKey extends PropertyKey = string> extends RegleCommonStatus<TState> {
384
+ $value: UnwrapNestedRefs<TState[TKey]>;
385
+ readonly $errors: string[];
386
+ readonly $silentErrors: string[];
387
+ readonly $externalErrors?: string[];
388
+ readonly $rules: {
389
+ readonly [TRuleKey in keyof Omit<TRules, '$each' | keyof FieldRegleBehaviourOptions>]: RegleRuleStatus<TState[TKey], TRules[TRuleKey] extends RegleRuleDefinition<any, infer TParams, any> ? TParams : [], TRules[TRuleKey] extends RegleRuleDefinition<any, any, any, infer TMetadata> ? TMetadata : TRules[TRuleKey] extends InlineRuleDeclaration<any, any[], infer TMetadata> ? TMetadata extends Promise<infer P> ? P : TMetadata : never>;
390
+ };
391
+ }
392
+ /**
393
+ * @public
394
+ */
395
+ interface RegleCommonStatus<TValue = any> {
396
+ readonly $valid: boolean;
397
+ readonly $invalid: boolean;
398
+ readonly $dirty: boolean;
399
+ readonly $anyDirty: boolean;
400
+ readonly $pending: boolean;
401
+ readonly $error: boolean;
402
+ $id?: string;
403
+ $value: UnwrapNestedRefs<TValue>;
404
+ $touch(): void;
405
+ $reset(): void;
406
+ $validate(): Promise<boolean>;
407
+ $unwatch(): void;
408
+ $watch(): void;
409
+ $clearExternalErrors(): void;
410
+ }
411
+ /**
412
+ * @public
413
+ */
414
+ type RegleRuleStatus<TValue = any, TParams extends any[] = any[], TMetadata extends RegleRuleMetadataDefinition = never> = {
415
+ readonly $type: string;
416
+ readonly $message: string | string[];
417
+ readonly $active: boolean;
418
+ readonly $valid: boolean;
419
+ readonly $pending: boolean;
420
+ readonly $path: string;
421
+ readonly $metadata: TMetadata;
422
+ $validator: (value: TValue, ...args: TParams) => boolean | Promise<boolean>;
423
+ $validate(): Promise<boolean>;
424
+ $reset(): void;
425
+ } & ([TParams] extends [[]] ? {} : {
426
+ readonly $params: TParams;
427
+ });
428
+ /**
429
+ * @public
430
+ */
431
+ interface RegleCollectionStatus<TRules extends RegleRuleDecl | ReglePartialValidationTree<any>, TState extends any[], TFieldRule extends RegleCollectionRuleDecl<any, any> = never> extends Omit<RegleFieldStatus<TRules, TState>, '$errors' | '$silentErrors'> {
432
+ readonly $each: Array<InferRegleStatusType<NonNullable<TRules>, NonNullable<TState>, number>>;
433
+ readonly $field: RegleFieldStatus<TFieldRule, TState>;
434
+ readonly $errors: RegleErrorTree<TRules>;
435
+ readonly $silentErrors: RegleErrorTree<TRules>;
436
+ }
437
+
438
+ /**
439
+ * @description
440
+ * Create a typed custom rule that can be used like default rules.
441
+ * It can also be declared in the global options
442
+ *
443
+ * It will automatically detect if the rule is async
444
+ *
445
+ * @typeParam TValue - The input value the rule should receive
446
+ * @typeParam TParams - Tuple declaration of the rule parameters (if any)
447
+ *
448
+ * @param definition - The rule processors object
449
+ *
450
+ * @returns A rule definition that can be callable depending on params presence
451
+ *
452
+ * @exemple
453
+ *
454
+ * ```ts
455
+ * // Create a simple rule with no params
456
+ * import {ruleHelpers} from '@regle/rules';
457
+ *
458
+ * export const isFoo = createRule({
459
+ * validator(value: string) {
460
+ * if (ruleHelpers.isFilled(value)) {
461
+ * return value === 'foo';
462
+ * }
463
+ * return true
464
+ * },
465
+ * message: "The value should be 'foo'"
466
+ * })
467
+ * ```
468
+ */
469
+ declare function createRule<TValue extends any, TParams extends any[], TReturn extends RegleRuleMetadataDefinition | Promise<RegleRuleMetadataDefinition>, TMetadata extends RegleRuleMetadataDefinition = TReturn extends Promise<infer M> ? M : TReturn, TAsync extends boolean = TReturn extends Promise<any> ? true : false>(definition: RegleRuleInit<TValue, TParams, TReturn, TMetadata, TAsync>): InferRegleRule<TValue, TParams, TAsync, TMetadata>;
470
+
471
+ /**
472
+ * Returns a clean list of parameters
473
+ * Removing Ref and executing function to return the unwraped value
474
+ */
475
+ declare function unwrapRuleParameters<TParams extends any[]>(params: ParamDecl[]): TParams;
476
+
477
+ declare const useRegle: <TState extends Record<string, any>, TRules extends ReglePartialValidationTree<TState, Partial<AllRulesDeclarations>>, TExternal extends RegleExternalErrorTree<TState>, TValidationGroups extends Record<string, RegleValidationGroupEntry[]>, TValid = keyof TRules extends keyof TState ? true : false>(state: MaybeRef<TState> | DeepReactiveState<TState>, rulesFactory: TValid extends true ? TRules | ComputedRef<TRules> | (() => TRules) : never, options?: (Partial<DeepMaybeRef<RegleBehaviourOptions>> & LocalRegleBehaviourOptions<TState, TRules, TExternal, TValidationGroups>) | undefined) => Regle<TState, TRules, TExternal, TValidationGroups>;
478
+
479
+ declare function defineRegleConfig<TCustomRules extends Partial<AllRulesDeclarations>>({ rules, modifiers, }: {
480
+ rules?: () => TCustomRules;
481
+ modifiers?: RegleBehaviourOptions;
482
+ }): <TState extends Record<string, any>, TRules extends ReglePartialValidationTree<TState, Partial<AllRulesDeclarations> & TCustomRules>, TExternal extends RegleExternalErrorTree<TState>, TValidationGroups extends Record<string, RegleValidationGroupEntry[]>, TValid = keyof TRules extends keyof TState ? true : false>(state: vue.MaybeRef<TState> | DeepReactiveState<TState>, rulesFactory: TValid extends true ? TRules | vue.ComputedRef<TRules> | (() => TRules) : never, options?: (Partial<DeepMaybeRef<RegleBehaviourOptions>> & LocalRegleBehaviourOptions<TState, TRules, TExternal, TValidationGroups>) | undefined) => Regle<TState, TRules, TExternal, TValidationGroups>;
483
+
484
+ export { type DeepMaybeRef, type FormRuleDeclaration, type InlineRuleDeclaration, InternalRuleType, type LocalRegleBehaviourOptions, type Maybe, type ParamDecl, type Regle, type RegleBehaviourOptions, type RegleCollectionErrors, type RegleCollectionRuleDecl, type RegleCollectionRuleDefinition, type RegleCollectionStatus, type RegleCommonStatus, type RegleComputedRules, type RegleErrorTree, type RegleExternalCollectionErrors, type RegleExternalErrorTree, type RegleExternalValidationErrors, type RegleExternalValidationErrorsReport, type RegleFieldStatus, type RegleFormPropertyType, type RegleInternalRuleDefs, type ReglePartialValidationTree, type RegleRuleCore, type RegleRuleDecl, type RegleRuleDefinition, type RegleRuleDefinitionProcessor, type RegleRuleDefinitionWithMetadataProcessor, type RegleRuleInit, type RegleRuleMetadataConsumer, type RegleRuleMetadataDefinition, type RegleRuleRaw, type RegleRuleStatus, type RegleRuleWithParamsDefinition, type RegleStatus, type RegleUniversalParams, type RegleValidationErrors, type RegleValidationGroupEntry, type RegleValidationGroupOutput, type RegleValidationTree, type UnwrapRegleUniversalParams, createRule, defineRegleConfig, unwrapRuleParameters, useRegle };
package/dist/index.d.ts CHANGED
@@ -11,7 +11,6 @@ type ExcludeByType<T, U> = {
11
11
  [K in keyof T as T[K] extends U ? never : K]: T[K] extends U ? never : T[K];
12
12
  };
13
13
  type NonPresentKeys<TSource extends Record<string, any>, Target extends Record<string, any>> = Omit<Target, keyof TSource>;
14
- type NoInferLegacy<A extends any> = [A][A extends any ? 0 : never];
15
14
 
16
15
  type ArrayElement<T> = T extends Array<infer U> ? U : never;
17
16
 
@@ -106,14 +105,14 @@ interface Regle<TState extends Record<string, any> = EmptyObject, TRules extends
106
105
  type DeepReactiveState<T extends Record<string, any>> = {
107
106
  [K in keyof T]: MaybeRef<T[K]>;
108
107
  };
109
- type DeepSafeFormState<TState extends Record<string, any>, TRules extends ReglePartialValidationTree<TState, CustomRulesDeclarationTree>> = [unknown] extends [TState] ? object : {
108
+ type DeepSafeFormState<TState extends Record<string, any>, TRules extends ReglePartialValidationTree<TState, CustomRulesDeclarationTree>> = [unknown] extends [TState] ? {} : {
110
109
  [K in keyof TState as [SafeProperty<TState[K], TRules[K]>] extends [never] ? K : never]?: [
111
110
  SafeProperty<TState[K], TRules[K]>
112
111
  ] extends [never] ? TState[K] : SafeProperty<TState[K], TRules[K]>;
113
112
  } & {
114
113
  [K in keyof TState as [SafeProperty<TState[K], TRules[K]>] extends [never] ? never : K]-?: SafeProperty<TState[K], TRules[K]>;
115
114
  };
116
- type SafeProperty<TState, TRule extends RegleFormPropertyType<any, any> | undefined = never> = TRule extends RegleCollectionRuleDefinition ? TState extends Array<any> ? SafeProperty<TState[number], ExtractFromGetter<TRule['$each']>>[] : never : TRule extends ReglePartialValidationTree<any, any> ? TState extends Record<string, any> ? DeepSafeFormState<TState, TRule> : never : TRule extends RegleRuleDecl<any, any> ? unknown extends TRule['required'] ? never : TRule['required'] extends undefined ? never : TRule['required'] extends RegleRuleDefinition<any, infer Params> ? Params extends never[] ? TState : never : never : never;
115
+ type SafeProperty<TState, TRule extends RegleFormPropertyType<any, any> | undefined = never> = TRule extends RegleCollectionRuleDefinition<any, any> ? TState extends Array<any> ? SafeProperty<TState[number], ExtractFromGetter<TRule['$each']>>[] : never : TRule extends ReglePartialValidationTree<any, any> ? TState extends Record<string, any> ? DeepSafeFormState<TState, TRule> : TRule extends RegleRuleDecl<any, any> ? unknown extends TRule['required'] ? never : TRule['required'] extends undefined ? never : TRule['required'] extends RegleRuleDefinition<any, infer Params, any, any, any> ? Params extends never[] ? TState : never : never : never : never;
117
116
 
118
117
  type ParamDecl<T = any> = MaybeRef<Maybe<T>> | (() => Maybe<T>);
119
118
  type CreateFn<T extends any[]> = (...args: T) => any;
@@ -208,11 +207,11 @@ type RegleCollectionRuleDefinition<TValue = any[], TCustomRules extends Partial<
208
207
  * @argument
209
208
  * createRule arguments options
210
209
  */
211
- interface RegleRuleInit<TValue extends any, TParams extends [...any[]], TReturn extends RegleRuleMetadataDefinition | Promise<RegleRuleMetadataDefinition>, TMetadata extends RegleRuleMetadataDefinition, TAsync extends boolean = TReturn extends Promise<any> ? true : false> {
210
+ interface RegleRuleInit<TValue extends any, TParams extends [...any[]] = [], TReturn extends RegleRuleMetadataDefinition | Promise<RegleRuleMetadataDefinition> = boolean, TMetadata extends RegleRuleMetadataDefinition = RegleRuleMetadataDefinition, TAsync extends boolean = TReturn extends Promise<any> ? true : false> {
212
211
  type?: string;
213
212
  validator: (value: Maybe<TValue>, ...args: TParams) => TReturn;
214
- message: string | string[] | ((value: Maybe<TValue>, metadata: RegleRuleMetadataConsumer<NoInferLegacy<TParams>, TMetadata>) => string | string[]);
215
- active?: boolean | ((value: Maybe<TValue>, metadata: RegleRuleMetadataConsumer<NoInferLegacy<TParams>, TMetadata>) => boolean);
213
+ message: string | string[] | ((value: Maybe<TValue>, metadata: RegleRuleMetadataConsumer<TParams, TMetadata>) => string | string[]);
214
+ active?: boolean | ((value: Maybe<TValue>, metadata: RegleRuleMetadataConsumer<TParams, TMetadata>) => boolean);
216
215
  }
217
216
  /**
218
217
  * @argument
@@ -228,29 +227,56 @@ interface RegleRuleCore<TValue extends any, TParams extends any[] = [], TAsync e
228
227
  type DefaultValidators = {
229
228
  alpha: RegleRuleDefinition<string>;
230
229
  alphaNum: RegleRuleDefinition<string | number>;
231
- between: RegleRuleWithParamsDefinition<number, [min: number, max: number]>;
230
+ between: RegleRuleWithParamsDefinition<number, [min: Maybe<number>, max: Maybe<number>]>;
232
231
  checked: RegleRuleDefinition<boolean, [], false, boolean, boolean>;
233
- dateAfter: RegleRuleWithParamsDefinition<Date, [after: Date]>;
234
- dateBefore: RegleRuleWithParamsDefinition<Date, [before: Date]>;
235
- dateBetween: RegleRuleWithParamsDefinition<Date, [before: Date, after: Date]>;
236
- decimal: RegleRuleDefinition<number | string>;
237
- email: RegleRuleDefinition<string>;
232
+ contains: RegleRuleWithParamsDefinition<string, [part: Maybe<string>], false, boolean>;
233
+ dateAfter: RegleRuleWithParamsDefinition<string | Date, [
234
+ after: Maybe<string | Date>
235
+ ], false, true | {
236
+ $valid: false;
237
+ error: 'date-not-after';
238
+ } | {
239
+ $valid: false;
240
+ error: 'value-or-paramater-not-a-date';
241
+ }>;
242
+ dateBefore: RegleRuleWithParamsDefinition<string | Date, [
243
+ before: Maybe<string | Date>
244
+ ], false, true | {
245
+ $valid: false;
246
+ error: 'date-not-before';
247
+ } | {
248
+ $valid: false;
249
+ error: 'value-or-paramater-not-a-date';
250
+ }>;
251
+ dateBetween: RegleRuleWithParamsDefinition<string | Date, [
252
+ before: Maybe<string | Date>,
253
+ after: Maybe<string | Date>
254
+ ], false, boolean>;
255
+ decimal: RegleRuleDefinition<string | number, [], false, boolean, string | number>;
256
+ email: RegleRuleDefinition<string, [], false, boolean, string>;
257
+ endsWith: RegleRuleWithParamsDefinition<string, [part: Maybe<string>], false, boolean>;
238
258
  exactLength: RegleRuleWithParamsDefinition<string | any[] | Record<PropertyKey, any>, [
239
259
  count: number
240
260
  ], false, boolean>;
241
- integer: RegleRuleDefinition<number | string>;
242
- ipAddress: RegleRuleDefinition<string, [], false>;
243
- macAddress: RegleRuleWithParamsDefinition<string, [separator?: string | undefined], false>;
244
- maxLength: RegleRuleWithParamsDefinition<string, [count: number]>;
245
- maxValue: RegleRuleWithParamsDefinition<number, [count: number]>;
246
- minLength: RegleRuleWithParamsDefinition<string | Record<PropertyKey, any> | any[], [
261
+ integer: RegleRuleDefinition<string | number, [], false, boolean, string | number>;
262
+ ipAddress: RegleRuleDefinition<string, [], false, boolean, string>;
263
+ macAddress: RegleRuleWithParamsDefinition<string, [
264
+ separator?: string | undefined
265
+ ], false, boolean>;
266
+ maxLength: RegleRuleWithParamsDefinition<string | any[] | Record<PropertyKey, any>, [
267
+ count: number
268
+ ], false, boolean>;
269
+ maxValue: RegleRuleWithParamsDefinition<number, [count: number], false, boolean>;
270
+ minLength: RegleRuleWithParamsDefinition<string | any[] | Record<PropertyKey, any>, [
247
271
  count: number
248
- ]>;
249
- minValue: RegleRuleWithParamsDefinition<number, [count: number]>;
250
- numeric: RegleRuleDefinition<number | string>;
272
+ ], false, boolean>;
273
+ minValue: RegleRuleWithParamsDefinition<number, [count: number], false, boolean>;
274
+ numeric: RegleRuleDefinition<string | number, [], false, boolean, string | number>;
275
+ regex: RegleRuleWithParamsDefinition<string, [regexp: RegExp], false, boolean>;
251
276
  required: RegleRuleDefinition<unknown, []>;
252
- sameAs: RegleRuleWithParamsDefinition<unknown, [target: unknown]>;
253
- url: RegleRuleDefinition<string>;
277
+ sameAs: RegleRuleWithParamsDefinition<unknown, [target: unknown], false, boolean>;
278
+ startsWith: RegleRuleWithParamsDefinition<string, [part: Maybe<string>], false, boolean>;
279
+ url: RegleRuleDefinition<string, [], false, boolean, string>;
254
280
  };
255
281
 
256
282
  type CustomRulesDeclarationTree = {
@@ -342,7 +368,7 @@ type RegleStatus<TState extends Record<string, any> = Record<string, any>, TRule
342
368
  };
343
369
  readonly $errors: RegleErrorTree<TRules>;
344
370
  readonly $silentErrors: RegleErrorTree<TRules>;
345
- } & ([TValidationGroups] extends [never] ? object : {
371
+ } & ([TValidationGroups] extends [never] ? {} : {
346
372
  $groups: {
347
373
  readonly [TKey in keyof TValidationGroups]: RegleValidationGroupOutput;
348
374
  };
@@ -396,7 +422,7 @@ type RegleRuleStatus<TValue = any, TParams extends any[] = any[], TMetadata exte
396
422
  $validator: (value: TValue, ...args: TParams) => boolean | Promise<boolean>;
397
423
  $validate(): Promise<boolean>;
398
424
  $reset(): void;
399
- } & ([TParams] extends [[]] ? object : {
425
+ } & ([TParams] extends [[]] ? {} : {
400
426
  readonly $params: TParams;
401
427
  });
402
428
  /**