vuelidify 1.0.1 → 2.0.1

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/README.md CHANGED
@@ -1,23 +1,24 @@
1
1
  # Vuelidify
2
2
 
3
-
4
3
  [Installation](#installation)
5
4
  [Types](#types)
6
5
  [Examples](#examples)
6
+ [Technical Details](#technical-details)
7
+ [Custom Validators](#custom-validators)
7
8
  ---
8
- *A simple and lightweight Vue 3 model based validation library with strong type support.*
9
+ *Vuelidify is a Vue 3 model-based validation library that makes complex form validation easy.*
9
10
 
10
- This library was inspired by Vuelidate but seeks to solve some of its biggest problems. This library does NOT support Vue2, and does NOT support commonJS. Technology must move forward.
11
+ This library was inspired by Vuelidate and sought to solve some of its biggest problems. This library does NOT support Vue2, and does NOT support commonJS. Technology must move forward.
11
12
 
12
- **✨ Simple** because it does exactly what it needs to with no dependencies other than Vue.
13
+ **✨ Powerful** because it handles complex validation scenarios easily and efficiently.
13
14
 
14
- **🪶 Lightweight** because the .mjs is <9KB (uncompressed), and ~3KB gzipped.
15
+ **🪶 Lightweight** because the .mjs is <9KB (uncompressed), and ~3KB gzipped; no bloat or useless dependencies.
15
16
 
16
- **📝 Model based** refers to validation being done in the script tag on an object. This is an alternative to template based validation, which uses template components and attributes to validate an object.
17
+ **📝 Model-based** refers to validation being done in your script alongside your data instead of in your templates.
17
18
 
18
- **💪 Strong types** makes setting up validation intuitive for developers. No more: "wait, how do I do that again?"
19
+ **💪 Strong types** makes setup intuitive for developers. No more, "wait, how do I do that again?"
19
20
 
20
- Too many validation libraries for Vue lack good type support; which negatively impacts maintainability. Changes to models would not indicate that validation needs to be updated as well. This library was created to fix that problem.
21
+ Too many validation libraries for Vue lack good type support, which makes maintaining codebases harder over time. When your data models change, there's often no clear signal that your validation needs updated as well. Vuelidify was built to solve this problem.
21
22
 
22
23
  ---
23
24
 
@@ -37,7 +38,7 @@ pnpm add vuelidify
37
38
 
38
39
  ## Types
39
40
 
40
- This was created for use in ```<script setup lang="ts">```, meaning you need TypeScript in order to get the full benefits of this library.
41
+ This was created for use in ```<script setup lang="ts">```. You need TypeScript in order to get the full benefits of this library.
41
42
 
42
43
  **useValidation()** is the starting point for validating your models.
43
44
 
@@ -52,62 +53,84 @@ This was created for use in ```<script setup lang="ts">```, meaning you need Typ
52
53
  Here is a breakdown of the configuration object the composable expects.
53
54
  ```ts
54
55
  {
55
- objectToValidate: T, // The ref, computed, or reactive object you want to validate.
56
+ model: T, // The ref, computed, or reactive object you want to validate.
56
57
  validation: Validation<T>, // Describes how to validate your object.
57
- args: A = undefined, // Can be anything! Will be passed into every validator.
58
+ args: A = undefined, // Can be anything and will be passed into every validator.
58
59
  delayReactiveValidation: boolean, // Should reactive validation be active immediately or only after calling validate()?
59
60
  }
60
61
  ```
61
62
  That's it, super simple!
62
63
 
63
- Just kidding, ```validation: Validation<T>``` isn't the full picture. The type here is quite complicated, but easy to use. Here's what you need to know.
64
+ Just kidding, ```validation: Validation<T>``` isn't the full picture. The type here is quite complicated, but easy to use. Here's what you need to know:
64
65
 
65
- 1. ```Validation<T>``` will copy the type of your object, down to the names of properties. Nested objects will also be copied, and their inner types as well. This type is recursive!
66
- 2. Properties which are primitives or arrays are the exit conditions to the recursive type. Instead they will present ```PrimitiveValidationTypes``` or ```ArrayValidationTypes``` respectively.
66
+ 1. ```Validation<T>``` will copy the layout of T's properties. Nested objects will also be copied. This type is recursive!
67
+ 2. Types which can be validated will have some unique properties available:
67
68
  ```ts
69
+
70
+ // foo is a string
71
+ foo: {
72
+ $reactive?: [],
73
+ $lazy?: []
74
+ }
75
+ // bar is an array
76
+ bar: {
77
+ $reactive?: [],
78
+ $lazy?: []
79
+ $each?: {},
80
+ }
81
+ // zaa is an object containing { foo: string, bar: array }
68
82
  {
69
- // foo is a string
70
- foo: {
83
+ $reactive?: [],
84
+ $lazy?: [],
85
+ bar: {
71
86
  $reactive?: [],
72
87
  $lazy?: []
73
- }
74
- // bar is an array
75
- bar: {
76
88
  $each?: {},
89
+ },
90
+ foo: {
77
91
  $reactive?: [],
78
92
  $lazy?: []
79
93
  }
80
94
  }
95
+
81
96
  ```
82
- 3. Arrays are special. If you have an array of objects that need validated, ```$each``` will be your friend. ```$each``` will be the same type as ```Validation<U>``` where ```U``` is the type of each object in the array. This loop can go on forever, as long as your object also has sufficiently many children and arrays!
83
- 4. ```$reactive``` is an array of validators that should be performed on that property reactively.
84
- 5. ```$lazy``` is an array of validators that should be performed on that property whenever ```validate()``` is called. This was added so you can control when more expensive validatiors are invoked.
97
+ 3. ```$each``` is the same type as ```Validation<U>``` where ```U``` is the type of each object in the array you are validating.
98
+ 4. ```$reactive``` is an array of validators that should be performed reactively on that property. [See technical details](#technical-details) for more information.
99
+ 5. ```$lazy``` is an array of validators that should be performed on that property whenever ```validate()``` is called. [See technical details](#technical-details) for more information.
85
100
 
86
- Here is the breakdown of the return of the composable
101
+ Here is the breakdown of the composable's return type
87
102
  ```ts
88
103
  {
104
+ // true after validate() is invoked once
89
105
  hasValidated: boolean,
90
- // True if you object has changed from the reference.
91
- // Useful for enabling save buttons after changes have been made
92
- isDirty: boolean,
93
- isValid: boolean,
106
+ // invokes every validator defined in the validation rules.
107
+ // returns whether or not they all passed
108
+ validate: () => Promise<boolean>
94
109
  isValidating: boolean,
95
- // Access the results of validation. This will copy the properties of your object.
96
- // Every "exit" condition have it's own type explained below
110
+ // Access the results of validation.
111
+ // This type is explained below.
97
112
  state: ValidationState<T>,
113
+ // true only if every validator passed
114
+ isValid: boolean,
115
+ // true if any validator failed
116
+ isErrored: boolean,
98
117
  // Set the comparison object for determining dirty state.
99
- // If your object must first load in asynchronously,
118
+ // If your object must load in asynchronously,
100
119
  // use this function to set the reference once it has loaded.
101
- setReference: (reference: T) => void,
102
- validate: () => Promise<boolean>
120
+ setReference: (reference: T) => void,
121
+ // True if your object has changed from the reference.
122
+ // Useful for enabling save buttons after changes have been made
123
+ isDirty: boolean,
103
124
  }
104
125
  ```
105
- Here is the breakdown of the validation state
126
+ Validation state also copies the layout of the model you provide. However, instead of providing validators, you now get access to `$state` and `$arrayState`. `$arrayState` is just an array of state objects created by validating an array object.
127
+
128
+ Here is the breakdown of `$state`
106
129
  ```ts
107
130
  {
108
131
  // The collected error messages returned from all the validators
109
132
  errorMessages: string[],
110
- // True if any validators returned false.
133
+ // True if any validators failed.
111
134
  // Not equivalent to !isValid, because !isValid is true even
112
135
  // when validation has not been ran yet.
113
136
  // Can be false when there are lazy validators that still need executed.
@@ -116,27 +139,29 @@ Here is the breakdown of the validation state
116
139
  isValid: boolean,
117
140
  isValidating: boolean,
118
141
  // A map for easily accessing named validation results.
119
- // This is the one spot without type support
142
+ // This is the one spot without good type support.
120
143
  results: { [key: string]: BaseValidationReturn<F> }
121
- // A 2D array of the validation results
144
+ // A collection of validator responses.
122
145
  resultsArray: Array<BaseValidationReturn<F>>
123
146
  }
124
147
  ```
125
- Here is the breakdown of the return type from validators.
148
+ Validators must return one of the following:
126
149
  ```ts
127
- // Validators must either return a BaseValidationReturn<F> object, undefined,
128
- // or an array of validators which will be invoked immediately.
129
- {
150
+ BaseValidationReturn<F> | Validator[] | undefined
151
+ ```
152
+ Here is the breakdown of the `BaseValidationReturn<F>`
153
+ ```ts
154
+ type BaseValidationReturn<F> = {
130
155
  // Name the result of this validator. This will put the validation result
131
156
  // into the results map in the validation state of this property.
132
157
  // Make sure your names are unique between your validators.
133
158
  name?: string,
134
- // the unique identifier for this validation result. Assigned interally.
159
+ // the unique identifier for this validation result. Assigned internally.
135
160
  // you can use this ID to identify your DOM elements that display error messages.
136
161
  id? string,
137
162
  // required for determining whether or not this validator passed
138
163
  isValid: boolean,
139
- errorMessage?: string,
164
+ message?: string,
140
165
  // Sometimes a true or false is not enough information for end users.
141
166
  // Use this to return any object to give additional information about the validation.
142
167
  // In order to access this custom data easily, make sure you give the result a name
@@ -145,27 +170,24 @@ Here is the breakdown of the return type from validators.
145
170
  ```
146
171
  Here is the breakdown of the parameters that are passed into validators
147
172
  ```ts
148
- {
173
+ type ValidatorParams<T,P,V,A> = {
149
174
  // The value of the property being validated
150
175
  value: T,
151
176
  // The top-most ancestor being validated. The object that was passed to the composable.
152
177
  parent: P,
153
178
  // The args that were specified in the composable configuration.
154
- // This type will only appear for you when args is NOT undefined.
155
179
  args: V,
156
- // Will only appear for properties nested in some array.
157
180
  // The type will be an ordered array of strongly typed objects.
158
- // Each element is a "parent" in the array, or an ancestor to the property you're validating.
159
- // Index 0 will be appear when you're 1 array deep, and index 1 will appear 2 arrays deep, etc.
160
- // The limit of nested arrays is currently 20, and I don't think you'll need more than that.
161
- // Extremely useful for complex validation of arrays where validation depends on the array object,
162
- // rather than the top-most parent object which contains the array.
163
- arrayParents: A
181
+ // Each index is an ancestor to what you're validating.
182
+ // Index 0 will appear when you're 1 array deep, and index 1 will appear 2 arrays deep, etc.
183
+ // Extremely useful for complex validation.
184
+ arrayAncestors: A
164
185
  }
165
186
  ```
166
187
 
167
188
  ## Examples
168
- #### Primitives
189
+ ### Validation Rules
190
+ #### Validating Primitives
169
191
  ```ts
170
192
  <script setup lang="ts">
171
193
  import { ref } from 'vue';
@@ -173,29 +195,42 @@ Here is the breakdown of the parameters that are passed into validators
173
195
 
174
196
  const string = ref("");
175
197
  const v$ = useValidation({
176
- objectToValidate: string,
198
+ model: string,
177
199
  validation: {
178
200
  $reactive: [minLength(10)] // Put as many validators as you want here
179
201
  }
180
202
  });
181
203
  </script>
182
204
  ```
183
- #### Simple Objects
205
+ #### Validating Simple Objects
184
206
  ```ts
185
207
  <script setup lang="ts">
186
- import { ref } from 'vue';
208
+ import { ref, type Ref } from 'vue';
187
209
  import { minLength, useValidation, minNumber } from "vuelidify";
188
210
 
189
- const obj = ref({
211
+ // Note this format may not have correctly typed validation when using strict TypeScript.
212
+ // const obj = ref({
213
+ // foo: "string",
214
+ // bar: true,
215
+ // zaa: 1
216
+ // });
217
+
218
+ type SimpleObject = {
219
+ foo: name;
220
+ bar: boolean;
221
+ zaa: number;
222
+ }
223
+ const obj: Ref<SimpleObject> = ref({
190
224
  foo: "string",
191
225
  bar: true,
192
226
  zaa: 1
193
- });
227
+ })
228
+
194
229
  const v$ = useValidation({
195
- objectToValidate: obj,
230
+ model: obj,
196
231
  validation: {
197
232
  foo: {
198
- // Validate foo when v$.validate is called.
233
+ // Validate foo when v$.validate() is invoked.
199
234
  $lazy: [minLength(10)]
200
235
  },
201
236
  bar: {
@@ -207,15 +242,15 @@ Here is the breakdown of the parameters that are passed into validators
207
242
  }]
208
243
  },
209
244
  zaa: {
210
- // Validate zaa reactively and when v$.validate is called.
211
- // Notice how validation can depend on other properties in the parent.
245
+ // Validate zaa reactively and when v$.validate() is invoked.
246
+ // Notice how you can validate using other properties in the model.
212
247
  $reactive: [minNumber(10)],
213
248
  $lazy: [
214
249
  (params) => {
215
- const isBar = params.parent.bar;
250
+ const isBar = params.model.bar;
216
251
  return {
217
252
  isValid: isBar ? params.value > 100 : true,
218
- errorMessage: "Must be greater than 100 when bar is true"
253
+ message: "Must be greater than 100 when bar is true"
219
254
  }
220
255
  }
221
256
  ]
@@ -224,7 +259,7 @@ Here is the breakdown of the parameters that are passed into validators
224
259
  });
225
260
  </script>
226
261
  ```
227
- #### Arrays
262
+ #### Validating Arrays
228
263
  ```ts
229
264
  <script setup lang="ts">
230
265
  import { ref } from 'vue';
@@ -235,9 +270,9 @@ Here is the breakdown of the parameters that are passed into validators
235
270
  isActive: boolean;
236
271
  }
237
272
 
238
- const array = ref<FooBar[]>([]);
273
+ const array: Ref<FooBar[]> = ref([]);
239
274
  const v$ = useValidation({
240
- objectToValidate: array,
275
+ model: array,
241
276
  validation: {
242
277
  // Validate each object in the array.
243
278
  $each: {
@@ -246,11 +281,12 @@ Here is the breakdown of the parameters that are passed into validators
246
281
  $reactive: [
247
282
  // Validate the length of the name only if the object's isActive property is true.
248
283
  (params) => {
249
- if (params.arrayParents[0].isActive !== true) {
250
- // Return undefined to ignore this validator when the condition is not true.
251
- // This check can even be asynchronous!
284
+ // arrayAncestors[0] is an object with ancestor, index, and the array it is in.
285
+ if (params.arrayAncestors[0].ancestor.isActive === false) {
286
+ // Return undefined to ignore this validator
252
287
  return;
253
288
  }
289
+ // Return an array of validators which are immediately invoked. Useful for conditional validation.
254
290
  return [minLength(10)]
255
291
  }
256
292
  ]
@@ -260,26 +296,26 @@ Here is the breakdown of the parameters that are passed into validators
260
296
  });
261
297
  </script>
262
298
  ```
263
- #### Complex Objects
264
- Sometimes your objects will contain other objects and arrays.
299
+ #### Validating Complex Objects
300
+ Sometimes your objects will contain objects and arrays.
265
301
  ```ts
266
302
  <script setup lang="ts">
267
303
  import { ref } from 'vue';
268
304
  import { minLength, minNumber, useValidation } from "vuelidify";
269
305
 
270
- type Person = {
306
+ type Example = {
271
307
  a: Person,
272
308
  b: Person[]
273
309
  }
274
-
310
+
275
311
  type Person = {
276
312
  name: string;
277
313
  age: number;
278
314
  }
279
315
 
280
- const complexObj = ref<Person>();
316
+ const complexObj: Ref<Example | undefined> = ref();
281
317
  const v$ = useValidation({
282
- objectToValidate: complexObj,
318
+ model: complexObj,
283
319
  validation: {
284
320
  a: {
285
321
  // Validate person a's age reactively
@@ -296,8 +332,9 @@ Sometimes your objects will contain other objects and arrays.
296
332
  // Make sure each person in the array is younger than person a
297
333
  (params) => {
298
334
  return {
299
- isValid: params.value < params.parent.a.age,
300
- errorMessage: "Must be younger than person a."
335
+ isValid: params.model?.a.age != undefined
336
+ && params.value < params.model.a.age,
337
+ message: "Must be younger than person a."
301
338
  }
302
339
  }
303
340
  ],
@@ -312,20 +349,34 @@ Sometimes your objects will contain other objects and arrays.
312
349
  });
313
350
  </script>
314
351
  ```
352
+ ### Validation State
353
+ All of the validation types present their results similarly. Just access `state` to get started! As long as you have TypeScript enabled in your workspace, you should have no problem understanding its layout. Here's a short example on what you can do with the state object.
354
+ ```ts
355
+ const v$ = useValidation({
356
+ // ... complex object validation provided earlier ...
357
+ })
358
+ // The error messages present on person a's age
359
+ const aAgeErrors: string[] | undefined = v$.state.a?.age?.$state?.errorMessages;
360
+ // An array of validation state objects on each person of property b.
361
+ const bErrors = v$.state.b?.$arrayState;
362
+ ```
363
+ Note, properties may show up in the intellisense, but they are undefinable *on purpose*. If validation rules are not provided for a property, its state object will not exist.
315
364
 
316
365
  ## Technical Details
317
366
  For those interested in the inner workings of the library without looking at the code:
318
367
 
319
- - Reactive validation is performed by a deep watcher on the parent object. This was done because of inter-property dependence. When a validator for one property relies on another property in the object, it needs to be reevaluated. This does come with the technical debt of running every *reactive* validator in your object every time the user enters a character. But I this is mediated by validator optimizations discussed later.
320
- - Lazy validation is only performed only when the validate() function is called. However, validate() will also invoke all reactive validators to guarantee all validation results are up-to-date with the model. Properties or the object itself may be valid before ever calling validate() if there were no lazy validators specified, and all reactive validators were true (or again none specified).
321
- - Async validators can be mixed with sync validators, so there is no way to distinguish them upon initialization. However, once they are invoked for the first time, it is possible to distinguish them. Optimizations can then be made on the sync and async validators to improve validation behavior and performance. Sync validators will be wrapped in a computed function which has the benefit of determining reactive dependencies and caching the result. This counteracts the downside of using a deep watcher discussed previously. Synchronous validators will not be needlessly reevaluated every time a character changes in an unrelated property because the computed determines it doesn't rely on it. Async validators will be optimized based on how long they take to return. If they return faster than 250ms, they will not be given any optimization; if they return less than 500ms they will be given a throttle of 250ms; if they return longer than that they will be given a buffer. Details of the throttles are below.
322
- - ```throttleQueueAsync``` is a custom function exported by this library which solves some of the problems I had with lodash's throttle function. This function throttles a function, can copy it's signature, and returns a promise for the result of the function. Calling this function will instantly execute the function if there is no active throttle. Calling this function with an active throttle will return a promise to call the function as soon as the throttle has expired. Calling the function multiple times during the throttle period will keep overriding the queued promise. Overridden queued promises will return undefined once the throttle expires. This function is very complicated, but extremely useful for returning control back to the caller and guaranteeing that the function gets called with the latest parameters. This are all problems with current implementation of debounce or throttle which use setTimeout() without being wrapped in a promise.
323
- - ```bufferAsync``` is another custom function exported by this library which offers a more aggressive throttling behavior than ```throttleQueueAsync```. Instead, this function creates an "invocation buffer" on the provided function, copies the functions signature, and returns a promise to the result of the function. Essentially, the function provided will only be ran once the previous invocation of the function has returned. This function also uses a queue to guarantee invocation of the desired function after the previous invocation has returned.
368
+ - Reactive validation is performed by a deep watcher on the provided model. This was done because of inter-property dependence. When a validator for one property relies on another property in the object, it needs to be reevaluated. This does come with the technical debt of running *every* reactive validator *every* time the model is changed. However, the problem is mediated by validator optimizations which is discussed later.
369
+ - Lazy validation is only performed only when the `validate()` function is called. However, `validate()` will also invoke all reactive validators to guarantee all validation results are up-to-date with the model. Properties or the model itself may be valid before ever calling `validate()` if there were no lazy validators provided, and all reactive validators were true (or again none specified).
370
+ - Async validators can be mixed with sync validators, so there is no way to distinguish them upon initialization. However, once they are invoked for the first time, it is possible to distinguish them. Optimizations can then be made on the sync and async validators to improve validation behavior and performance. Sync validators will be wrapped in a computed function which has the benefit of determining reactive dependencies and caching the result. This counteracts the downside of using a deep watcher discussed previously. Synchronous validators will not be needlessly reevaluated every time a character changes in an unrelated property because the computed determines it doesn't rely on it. Async validators will be optimized based on how long they take to return. If they return faster than 250ms, they will not be given any optimization; if they return in less than 500ms, they will be given a throttle of 250ms; if they return longer than that they will be given a buffer. Details of the throttles are below.
371
+ - `throttleAsync` is an async throttler that preserves your functions signature and always returns a Promise of its result. It executes immediately when idle; if called during the throttle interval, it buffers only the latest call and runs it once the interval elapses—earlier buffered calls resolve to `undefined`. This lets you schedule non-blocking, promise-based throttling without overlapping executions and guarantees you always call your function with the latest arguments. Note, you are unable to distinguish if your function returned `undefined` or `throttleAsync` returned `undefined`.
372
+ - `bufferAsync` is another custom function exported by this library that provides a more aggressive throttling behavior than `throttleAsync`. `bufferAsync` preserves the original function’s signature and returns a promise resolving to its result. It only remembers the latest invocation while the provided function is still executing. Once the current execution completes, only the remembered call will be invoked all intermediate calls will return `undefined`. This mechanism prevents overlapping executions and reduces redundant work, making it ideal for expensive async operations where only the most recent intent should be executed. Note, you are unable to distinguish if your function returned `undefined` or `bufferAsync` returned `undefined`.
373
+ - Returning arrays of validators from within other validators is powerful but complex. Initially, we aimed to optimize these nested validators, but their dynamic nature--varying instances, order, and presence between iterations--made this unreliable. Since their results merge with all other validators, Vuelidify tracks and removes outdated results when the "parent" validator is invoked again and the same results are not returned.
374
+ - This library uses `unknown` instead of `any` to align with Deno and strict TypeScript standards. While `Args` and `Ancestors` are logically `undefined` by default, using `undefined` as a type causes issues—`unknown` can't be assigned to `undefined`. This distinction is why some of Vuelidify’s types may seem unusual, especially when creating generic validators meant to work universally. Additionally, the default type of `Return` is `any` because it truly *can be* anything. If it was unknown, you would be unable to access it for anything. `Return` is the only part of Vuelidify that is not strongly-typed. Be sure to cast it to what you expect before using it.
324
375
 
325
- # Create your own validators
326
- There aren't many validators provided by this library on purpose. Mostly because I didn't want to think of what could be useful, and would rather rely on feedback for useful validators. Feel free to give me feedback on the github repo.
376
+ # Custom Validators
377
+ There aren't many validators provided by this library on purpose. Mostly because I would rather rely on feedback for useful validators. Feel free to give me feedback on the github repo.
327
378
 
328
- I highly encourage you to understand the types enough to create your own validators. It isn't too difficult, and you should be able to base it off some of the existing ones.
379
+ I highly encourage you to understand the types enough to create your own validators. It isn't too difficult, and you should be able to base your validator off of existing ones.
329
380
 
330
381
  Here is a breakdown of one of the validators exported by this library (expanded to make comments more readable):
331
382
 
@@ -333,16 +384,13 @@ Here is a breakdown of one of the validators exported by this library (expanded
333
384
  // always provide a header comment to explain what the validator does!
334
385
  /**
335
386
  * Checks if the string value is a valid looking email using RegEx.
336
- *
337
- * The RegEx was taken from https://stackoverflow.com/questions/46155/how-can-i-validate-an-email-address-in-javascript, and may be updated in the future.
338
- * @returns Synchronous validator
339
387
  */
340
388
  export function isEmailSync<
341
389
  // The type of the property you want to support validation for.
342
390
  // adding | undefined | null is good practice for writing more robust code
343
- // Furthermore, if you just did string here, it wouldn't work with string?
344
- T extends string | undefined | null,
345
- // The type for the parent object.
391
+ // Furthermore, if you just did string here, it wouldn't work with string | undefined
392
+ T extends string | undefined | null,
393
+ // The type for the model parameter.
346
394
  // Generally you don't put constraints on this.
347
395
  P,
348
396
  // The type for the args
@@ -355,8 +403,8 @@ export function isEmailSync<
355
403
  // But you have to accept this generic in order to pass the type forward to not mess up outside types.
356
404
  A
357
405
  >(
358
- // Specify any parameters you need here. They could be Refs, primitives, whatever!
359
- ): SyncValidator<T, P, V, R, A> // Strongly type the type of validator you'll be returning
406
+ // Specify any parameters you need here. This is a function that returns a validator.
407
+ ): SyncValidator<T, P, V, R, A> // Explicitly type the validator you'll be returning
360
408
  {
361
409
  // Return a validator function
362
410
  return (
@@ -368,11 +416,26 @@ export function isEmailSync<
368
416
  // In this case, we're checking the value of the property against an email regex.
369
417
  return {
370
418
  isValid: params.value ? RegExp(/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/).test(params.value) : false,
371
- errorMessage: "Invalid email format"
419
+ message: "Invalid email format"
372
420
  }
373
421
  };
374
422
  }
375
423
  ```
376
424
 
377
- The type system that makes all this possible is fairly fragile. These problems may well be a limitation of TypeScript rather than of this package.
378
- I have encountered such problems when trying to build certain generic custom validators. Feel free to post issues you may have with the package on the git repo!
425
+ Because every generic has a default value in `SyncValidator`, we can greatly simplify this validator definition to only what is required for constraints:
426
+
427
+ ```ts
428
+ /**
429
+ * Validates a string is a valid looking email using RegEx.
430
+ */
431
+ export function isEmailSync<T extends string | undefined | null>(): SyncValidator<T> {
432
+ return (params: ValidatorParams<T>) => ({
433
+ isValid: params.value ? RegExp(/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/).test(params.value) : false,
434
+ message: "Invalid email format"
435
+ });
436
+ }
437
+ ```
438
+
439
+ This validator is effectively: `SyncValidator<string | undefined | null, unknown, unknown, unknown, unknown>`
440
+
441
+ Feel free to post issues you may have with the package on the git repo! Happy validating!
package/dist/index.d.ts CHANGED
@@ -1,144 +1,162 @@
1
- import { Ref } from 'vue';
1
+ import { Ref, Reactive, ComputedRef } from 'vue';
2
2
 
3
3
  /** Shorthand union of the primitive types */
4
4
  type Primitive = string | number | boolean;
5
- /** Holds the latest results of validation for an object */
6
- type ValidationState<T, FValidationReturn> = T extends Array<infer U> ? ArrayValidationState<U, FValidationReturn> : T extends IndexableObject ? RecursiveValidationState<T, FValidationReturn> : T extends Primitive ? PrimitiveValidationState<FValidationReturn> : undefined;
7
- type RecursiveValidationState<T, FValidationReturn> = {
8
- [key in keyof T]?: ValidationState<T[key], FValidationReturn>;
5
+ /** Defines the layout of validation results. Copies the format of the object being validated. */
6
+ type ValidationState<T, Return = any> = T extends Array<infer U> ? ArrayValidationState<U, Return> : T extends IndexableRecord ? RecursiveValidationState<T, Return> : T extends Primitive ? PrimitiveValidationState<Return> : never;
7
+ /** Determines the validation state available to objects. */
8
+ type RecursiveValidationState<T extends IndexableRecord, Return = any> = BaseValidationState<Return> & {
9
+ [key in keyof T]?: ValidationState<T[key], Return>;
9
10
  };
10
- /** Contains the reactive state of validation for a property. */
11
- type PrimitiveValidationState<FValidationReturn> = {
12
- /** True if all the validators defined for this property have passed. False otherwise. */
13
- isValid: boolean;
14
- isValidating: boolean;
11
+ /** Describes the Vuelidify validation state. */
12
+ type BaseValidationState<Return = any> = {
15
13
  /**
16
- * True if there are any results that failed validation.
14
+ * The validation state for this object.
17
15
  *
18
- * Not quite the complement of {@link isValid} because !{@link isValid} can be true when no validators have been called yet.
19
- * This will only ever be true when validation results have returned.
16
+ * Is named this way to avoid naming conflicts with existing object properties.
20
17
  */
21
- isErrored: boolean;
22
- /** Easy collection of the error messages from the raw validation returns */
23
- errorMessages: string[];
24
- results: {
25
- [key: string]: BaseValidationReturn<FValidationReturn>;
18
+ $state?: {
19
+ /** True if all the validators defined have passed. False otherwise. */
20
+ isValid: boolean;
21
+ isValidating: boolean;
22
+ /**
23
+ * True if there are any results that failed validation.
24
+ *
25
+ * Not always equal to `!isValid` because `!isValid` can be true when validators haven't been invoked.
26
+ */
27
+ isErrored: boolean;
28
+ /** Collection of the error messages from validators */
29
+ errorMessages: string[];
30
+ /**
31
+ * An indexable object of the validators that returned with names.
32
+ *
33
+ * Useful for validators which return data you want to use.
34
+ */
35
+ results: {
36
+ [key: string]: BaseValidationReturn<Return> | undefined;
37
+ };
38
+ resultsArray: BaseValidationReturn<Return>[];
26
39
  };
27
- resultsArray: BaseValidationReturn<FValidationReturn>[];
28
40
  };
29
- type ArrayValidationState<U, FValidationReturn> = PrimitiveValidationState<FValidationReturn> & {
41
+ /** Defines the validation state for a primitive value. */
42
+ type PrimitiveValidationState<Return = any> = BaseValidationState<Return>;
43
+ /** Defines the validation state for an array. */
44
+ type ArrayValidationState<U, Return = any> = BaseValidationState<Return> & {
30
45
  /**
31
46
  * Contains the validation state for each element in the array.
32
47
  *
33
48
  * Maps 1:1 to the array which was validated.
34
49
  */
35
- arrayState: ValidationState<U, FValidationReturn>[];
36
- };
37
- type RecursiveValidation<T extends IndexableObject, KParent, ValidationArgs, FValidationReturn, ArrParent, NLevel extends number> = {
38
- [key in keyof Partial<T>]: Validation<T[key], ValidationArgs, FValidationReturn, KParent, ArrParent, NLevel>;
50
+ $arrayState: ValidationState<U, Return>[];
39
51
  };
40
- type PrimitiveValidation<T extends Primitive | undefined | null, KParent, Args, FValidationReturn, ArrParent> = PrimitiveValidatorTypes<T, KParent, Args, FValidationReturn, ArrParent>;
41
- type IndexableObject = {
42
- [key: string]: any;
52
+ /** Defines validation rules for records. */
53
+ type RecursiveValidation<T, KModel, ValidationArgs, Return, Ancestors, NLevel extends number> = ObjectValidationTypes<T, KModel, ValidationArgs, Return, Ancestors> & {
54
+ [key in keyof Partial<T>]: Validation<T[key], ValidationArgs, Return, KModel, Ancestors, NLevel>;
43
55
  };
44
- /** Separates the reactive and lazy validators of a primitive property. */
45
- type PrimitiveValidatorTypes<T, KParent, Args, FValidationReturn, ArrParent> = {
46
- /** The validators for this property that are invoked whenever the form is changed. */
47
- $reactive?: Validator<T, KParent, Args, FValidationReturn, ArrParent>[];
48
- /** The validators for this property that are invoked only after {@link validate()} is invoked. */
49
- $lazy?: Validator<T, KParent, Args, FValidationReturn, ArrParent>[];
56
+ /** Defines the validation rules for records */
57
+ type ObjectValidationTypes<T = unknown, KModel = unknown, Args = unknown, Return = any, Ancestors = unknown> = BaseValidation<T, KModel, Args, Return, Ancestors>;
58
+ type IndexableRecord = Record<string, unknown>;
59
+ /** Defines the validation rules for all supported objects. */
60
+ type BaseValidation<T = unknown, KModel = unknown, Args = unknown, Return = any, Ancestors = unknown> = {
61
+ /** Validators invoked whenever the model is changed. */
62
+ $reactive?: Validator<T, KModel, Args, Return, Ancestors>[];
63
+ /** Validators invoked only after {@link UseValidationReturn.validate | validate()} is invoked. */
64
+ $lazy?: Validator<T, KModel, Args, Return, Ancestors>[];
50
65
  };
51
- type ArrayValidatorTypes<U, T extends Array<U>, KParent, Args, FValidationReturn, ArrParent, NLevel extends number> = {
66
+ /** Defines the validation rules for an array. */
67
+ type ArrayValidation<U, T = U[], KModel = unknown, Args = unknown, Return = any, Ancestors = unknown, NLevel extends number = number> = BaseValidation<T, KModel, Args, Return, Ancestors> & {
52
68
  /**
53
- * Can only be used with object arrays. Not string, number, or boolean (primitive) arrays.
54
- *
55
- * Defines the validation that should be performed on each element of the array.
69
+ * Defines the validation rules for each element of an array.
56
70
  *
57
- * Element validation requires much more logic, which may introduce performance problems for large arrays.
71
+ * Works best with arrays of objects; see documentation for details.
58
72
  */
59
- $each?: Validation<U, Args, FValidationReturn, KParent, ArrParent extends undefined ? Array<any> & {
60
- [key in NLevel]: U;
61
- } : ArrParent & {
62
- [key in NLevel]: U;
73
+ $each?: Validation<U, Args, Return, KModel, Ancestors extends undefined ? {
74
+ [key in NLevel]: ArrayAncestor<U, T>;
75
+ } : Ancestors & {
76
+ [key in NLevel]: ArrayAncestor<U, T>;
63
77
  }, Increment<NLevel>>;
64
- /** The validators for the array that are invoked whenever the form is changed. */
65
- $reactive?: Validator<T, KParent, Args, FValidationReturn, ArrParent>[];
66
- /** The validators for the array that are invoked only when {@link validate()} is called. */
67
- $lazy?: Validator<T, KParent, Args, FValidationReturn, ArrParent>[];
68
78
  };
79
+ type ArrayAncestor<U = unknown, // the type of T's elements
80
+ T = unknown> = Readonly<{
81
+ /** The index this ancestor is at in `array` */
82
+ index: number;
83
+ /** The array which contains the ancestor. Useful for referencing this ancestor's siblings. */
84
+ array: T;
85
+ /** An object which contains the value you are validating. */
86
+ ancestor: U;
87
+ }>;
69
88
  /** A synchronous or asynchronous validator. */
70
- type Validator<T, KParent, Args, FValidationReturn, ArrParent> = (SyncValidator<T, KParent, Args, FValidationReturn, ArrParent> | AsyncValidator<T, KParent, Args, FValidationReturn, ArrParent>);
71
- type ValidatorTypes<T, KParent, Args, FValidationReturn, ArrParent, NLevel extends number> = T extends Array<infer U> ? ArrayValidatorTypes<U, T, KParent, Args, FValidationReturn, ArrParent, NLevel> : PrimitiveValidatorTypes<T, KParent, Args, FValidationReturn, ArrParent>;
72
- type BaseValidator<T, Parent, Args, Return, ArrParent> = (input: ValidatorParams<T, Parent, Args, ArrParent>) => Return;
73
- type SyncValidator<T, Parent, Args, Return, ArrParent> = BaseValidator<T, Parent, Args, BaseValidationReturn<Return> | Array<Validator<T, Parent, Args, Return, ArrParent>> | undefined, ArrParent>;
74
- type AsyncValidator<T, Parent, Args, Return, ArrParent> = BaseValidator<T, Parent, Args, Promise<BaseValidationReturn<Return> | Array<Validator<T, Parent, Args, Return, ArrParent>> | undefined>, ArrParent>;
75
- type BaseValidationReturn<F = any> = {
89
+ type Validator<T = unknown, KModel = unknown, Args = unknown, Return = any, Ancestors = unknown> = SyncValidator<T, KModel, Args, Return, Ancestors> | AsyncValidator<T, KModel, Args, Return, Ancestors>;
90
+ /** Defines a validator function */
91
+ type BaseValidator<T, Parent, Args, Return, Ancestors> = (input: ValidatorParams<T, Parent, Args, Ancestors>) => Return;
92
+ /** Defines a validator which always runs synchronously */
93
+ type SyncValidator<T = unknown, Parent = unknown, Args = unknown, Return = any, Ancestors = unknown> = BaseValidator<T, Parent, Args, BaseValidationReturn<Return> | Array<Validator<T, Parent, Args, Return, Ancestors>> | undefined, Ancestors>;
94
+ /** Defines a validator which returns a promise */
95
+ type AsyncValidator<T = unknown, Parent = unknown, Args = unknown, Return = any, Ancestors = unknown> = BaseValidator<T, Parent, Args, Promise<BaseValidationReturn<Return> | Array<Validator<T, Parent, Args, Return, Ancestors>> | undefined>, Ancestors>;
96
+ /** Defines the return value of validators */
97
+ type BaseValidationReturn<F = unknown> = {
76
98
  /**
77
- * Assign this validator's result a name.
78
- * The result will then be added to a map using the name as the key
79
- * so you can easily access the result.
99
+ * The validation result's name.
100
+ * The result will be added to a record using the name as the key
80
101
  *
81
- * Note, the map entry will not exist until this validator has been run at least once, so account for undefined.
102
+ * Note, the entry will not exist until this validator has been ran once, so account for undefined.
82
103
  */
83
104
  name?: string;
84
105
  /**
85
106
  * The unique identifier for this validation result.
86
107
  *
87
- * Assigned and used internally, but can be used as your element's ID or key attribute.
108
+ * Assigned and used internally, but can be used as an element's ID or key.
88
109
  */
89
110
  id?: string;
90
- /** Used to determine if validation was successful or not. */
111
+ /** Determines if this validator passed. */
91
112
  isValid: boolean;
92
- /** The message or messages to display if isValid is false. */
93
- errorMessage?: string;
113
+ /** The error message for this validator. */
114
+ message?: string;
94
115
  /**
95
- * Return a custom object from this validator.
116
+ * Return any extra data you want from this validator.
96
117
  *
97
- * Should be used for more sophisticated return types than a boolean.
98
- *
99
- * i.e. password strength, severity levels, functions, etc.
118
+ * Meant for more sophisticated validation which returns data instead of just an error message (e.g. password strength, severity levels, or arrays).
100
119
  */
101
120
  custom?: F;
102
121
  };
103
- type ArrayValidationReturn<U, FValidationReturn> = BaseValidationReturn<FValidationReturn> & {
104
- /** The raw list of results from validating every object in the array. */
105
- arrayResults?: ValidationState<U, FValidationReturn>[];
106
- };
107
- type Validation<T, Args = undefined, FValidationReturn = undefined, KParent = T, ArrParent = undefined, NLevel extends number = 0> = T extends Array<infer U> ? ArrayValidatorTypes<U, T, KParent, Args, FValidationReturn, ArrParent, NLevel> : T extends IndexableObject ? RecursiveValidation<T, KParent, Args, FValidationReturn, ArrParent, NLevel> : T extends boolean ? PrimitiveValidation<boolean | undefined | null, KParent | undefined | null, Args, FValidationReturn, ArrParent> : T extends Primitive ? PrimitiveValidation<T | undefined | null, KParent | undefined | null, Args, FValidationReturn, ArrParent> : undefined;
108
- type ValidationConfig<T, Args, FValidationReturn> = {
109
- /**
110
- * If the object you provided is not in a good state (i.e. it must be loaded in asynchronously first),
111
- * call the {@link setup()} method returned by this composable after it has loaded.
112
- *
113
- * Setting up validation on an incomplete object will mean that the properties of the object
114
- * can not be linked to the validation configured, thus causing problems.
115
- */
116
- objectToValidate: Ref<T | undefined | null>;
117
- validation: Validation<T, Args, FValidationReturn, T>;
122
+ /**
123
+ * The entry point for validation with Vuelidify.
124
+ *
125
+ * Defines the validation rules for all the supported object types.
126
+ */
127
+ type Validation<T, Args = unknown, Return = any, KModel = T, Ancestors = unknown, NLevel extends number = 0> = [
128
+ NonNullable<T>
129
+ ] extends [Array<infer U>] ? ArrayValidation<U, T, KModel, Args, Return, Ancestors, NLevel> : [NonNullable<T>] extends [IndexableRecord] ? RecursiveValidation<T, KModel, Args, Return, Ancestors, NLevel> : [NonNullable<T>] extends [Primitive] ? BaseValidation<T, KModel, Args, Return, Ancestors> : never;
130
+ /** Defines the configuration for the {@link useValidation | useValidation() } composable */
131
+ type ValidationConfig<T = unknown, Args = unknown, Return = any> = {
132
+ /** The object to validate */
133
+ model: Ref<T>;
134
+ /** Configures the validation on the model. */
135
+ validation: Validation<T, Args, Return, T>;
118
136
  /**
119
- * False - reactive validation will always be active.
137
+ * Controls when reactive validation is triggered.
120
138
  *
121
- * True - reactive validation will start after the first invocation of {@link validate()}.
139
+ * - `false`: Reactive validation is always active.
140
+ * - `true`: Reactive validation starts after the first invocation of {@link validate()}.
122
141
  *
123
- * Defaults to true.
142
+ * Defaults to `true`.
124
143
  */
125
144
  delayReactiveValidation?: boolean;
126
145
  /**
127
- * Provide an object, ref, or function that will be passed to each validator.
128
- * Particularly useful when defining validation in separate files and you want to use variables outside of the object being validated.
146
+ * Provide anything you want your validators to have access to.
147
+ *
148
+ * Particularly useful when defining validation in separate files and you want to reference local variables.
129
149
  */
130
150
  args?: Args;
131
151
  };
132
- /** Describes the parameter passed into validator functions */
133
- type ValidatorParams<T, KParent, Args, ArrParent> = {
152
+ /** Defines the parameters passed into every validator */
153
+ type ValidatorParams<T = unknown, KModel = unknown, Args = unknown, Ancestors = unknown> = {
134
154
  /** The current value of the property */
135
155
  value: T;
136
156
  /** The entire object that was passed into the useValidation() composable to be validated. */
137
- parent: KParent;
138
- } & (Args extends undefined ? unknown : {
157
+ model: KModel;
139
158
  /** The args passed in to the useValidation() composable configuration. */
140
159
  args: Args;
141
- }) & (ArrParent extends undefined ? unknown : {
142
160
  /**
143
161
  * An ordered list of objects that were traversed through while navigating to this validator.
144
162
  *
@@ -146,9 +164,9 @@ type ValidatorParams<T, KParent, Args, ArrParent> = {
146
164
  *
147
165
  * Useful for inter-property dependence when validating arrays of complex objects.
148
166
  */
149
- arrayParents: ArrParent;
150
- });
151
- /** Type that increments a provided integer (0-19). */
167
+ arrayAncestors: Ancestors;
168
+ };
169
+ /** Increments a provided integer. Only works for 0 through 19, inclusive. */
152
170
  type Increment<N extends number> = [
153
171
  1,
154
172
  2,
@@ -174,10 +192,18 @@ type Increment<N extends number> = [
174
192
  ][N];
175
193
 
176
194
  /**
177
- * Returns a function that will only execute the provided promise returning function
178
- * with the most recently specified params only if a previously created promise does not exist.
195
+ * Returns a function that will execute the provided function
196
+ * with the latest params only if a previously created promise does not exist.
197
+ * ```ts
198
+ * async function test(): Promise<boolean> {}
199
+ * // Call this constant instead of the function to get the buffer benefits
200
+ * const bufferedTest = bufferAsync<
201
+ * typeof test, // this type makes the return the same signature as test()
202
+ * Awaited<ReturnType<typeof test>> // this type makes the returned function have the same return type
203
+ * >(test);
204
+ * ```
179
205
  */
180
- declare function bufferAsync<F extends (...args: any) => any, K>(func: (...params: Parameters<F>) => Promise<K>): (...params: Parameters<typeof func>) => Promise<K | undefined>;
206
+ declare function bufferAsync<F extends (...args: any[]) => any, K>(func: (...params: Parameters<F>) => K | Promise<K>): (...params: Parameters<typeof func>) => Promise<K | undefined>;
181
207
  /**
182
208
  * Guarantees delay between invocations of the given function.
183
209
  *
@@ -186,66 +212,80 @@ declare function bufferAsync<F extends (...args: any) => any, K>(func: (...param
186
212
  * Subsequent invocations during the cool down return a promise to invoke the function after the remaining delay has passed.
187
213
  *
188
214
  * Once the interval has passed, all queued promises are executed, but only the latest promise will execute the function. The others will return undefined.
215
+ * ```ts
216
+ * async function test(): Promise<boolean> {}
217
+ * // Call this constant instead of the function to get the throttle benefits
218
+ * const throttledTest = throttleQueueAsync<
219
+ * typeof test, // this type makes the return the same signature as test()
220
+ * Awaited<ReturnType<typeof test>> // this type makes the returned function have the same return type
221
+ * >(test);
222
+ * ```
189
223
  * @param func the function to throttle
190
224
  * @param delay milliseconds required between invocations of the function.
191
225
  */
192
- declare function throttleQueueAsync<F extends (...args: any) => any, K>(func: (...params: Parameters<F>) => K | Promise<K>, delay: number): (...params: Parameters<typeof func>) => Promise<K | undefined>;
226
+ declare function throttleQueueAsync<F extends (...args: any[]) => any, K>(func: (...params: Parameters<F>) => K | Promise<K>, delay: number): (...params: Parameters<typeof func>) => Promise<K | undefined>;
193
227
 
194
228
  /**
195
- * Makes sure the object is not undefined and the trim length is greater than 0.
196
- * @param value
197
- * @returns Synchronous validator
229
+ * Validates the object is not loosely undefined.
198
230
  */
199
- declare function required<T, P, V, R, A>(): SyncValidator<T, P, V, R, A>;
231
+ declare function required(): SyncValidator;
200
232
  /**
201
- * Makes sure the string or number to validate has a length >= to the provided length.
233
+ * Validates a string or number has a length >= to the provided length. Undefined and null are 0 length.
202
234
  * @param minLength
203
- * @returns Synchronous validator
204
235
  */
205
- declare function minLength<T extends string | undefined | null, P, V, R, A>(minLength: number): SyncValidator<T, P, V, R, A>;
236
+ declare function minLength<T extends string | number | undefined | null>(minLength: number): SyncValidator<T>;
206
237
  /**
207
- * Makes sure the string or number to validate is less than the provided length. Undefined strings are treated as 0 length.
208
- * @param maxLength
209
- * @return Synchronous validator
238
+ * Validates a string or number's length. Undefined and null are 0 length.
239
+ * @param maxLength the maximum length of the string or number
210
240
  */
211
- declare function maxLength<T extends string | number | undefined | null, P, V, R, A>(maxLength: number): SyncValidator<T, P, V, R, A>;
241
+ declare function maxLength<T extends string | number | undefined | null>(maxLength: number): SyncValidator<T>;
212
242
  /**
213
- * Makes sure the number to validate is not undefined and is at least the provided value.
214
- * @param minNumber
215
- * @returns Synchronous validator
243
+ * Validates a number is defined and is at least some value.
244
+ * @param minNumber the minimum number the value can be
216
245
  */
217
- declare function minNumber<T extends number | undefined | null, P, V, R, A>(minNumber: number): SyncValidator<T, P, V, R, A>;
246
+ declare function minNumber<T extends number | undefined | null>(minNumber: number): SyncValidator<T>;
218
247
  /**
219
- * Makes sure the number to validate is not undefined and is at most the provided value.
220
- * @param maxNumber
221
- * @returns Synchronous validator
248
+ * Validates a number is defined and is at most some value.
249
+ * @param maxNumber the maximum number the value can be
222
250
  */
223
- declare function maxNumber<T extends number | undefined | null, P, V, R, A>(maxNumber: number): SyncValidator<T, P, V, R, A>;
251
+ declare function maxNumber<T extends number | undefined | null>(maxNumber: number): SyncValidator<T>;
224
252
  /**
225
- * Checks if the value of this property strictly equals the value returned by the provided getter.
253
+ * Validate the provided predicate function.
254
+ * @param fn predicate that returns true if the value is valid.
255
+ * @param errorMessage the message to display when the values are not equal.
226
256
  */
227
- declare function mustEqual<T, P, V, R, A>(getter: (params: ValidatorParams<T, P, V, A>) => T, errorMessage: string): SyncValidator<T, P, V, R, A>;
257
+ declare function must<T, K, V, R, A>(fn: (params: ValidatorParams<T, K, V, A>) => boolean, errorMessage: string): SyncValidator<T, K, V, R, A>;
228
258
  /**
229
- * Checks if the string value is a valid looking email using RegEx.
259
+ * Validates a string is a valid looking email using RegEx.
230
260
  *
231
261
  * The RegEx was taken from https://stackoverflow.com/questions/46155/how-can-i-validate-an-email-address-in-javascript, and may be updated in the future.
232
- * @returns Synchronous validator
233
- */
234
- declare function isEmailSync<T extends string | undefined | null, P, V, R, A>(): SyncValidator<T, P, V, R, A>;
262
+ s */
263
+ declare function isEmailSync<T extends string | undefined | null>(): SyncValidator<T>;
235
264
 
265
+ type UseValidationReturn<T = unknown, Return = any> = {
266
+ hasValidated: Ref<boolean>;
267
+ validate: () => Promise<boolean>;
268
+ isValidating: ComputedRef<boolean>;
269
+ /** Stores the results of validation */
270
+ state: ComputedRef<ValidationState<T, Return>>;
271
+ /** True only if all validators passed. */
272
+ isValid: ComputedRef<boolean>;
273
+ /** True if any of the validators failed. */
274
+ isErrored: ComputedRef<boolean>;
275
+ /** Sets the internal reference object for determining {@link isDirty} */
276
+ setReference: (reference: T) => void;
277
+ /**
278
+ * Reactively determines if the object being validated has changed from the reference state.
279
+ *
280
+ * The reference state can be changed using {@link setReference()}.
281
+ */
282
+ isDirty: ComputedRef<boolean>;
283
+ };
236
284
  /**
237
- * A simple and lightweight Vue3 model based validation library with strong type support.
285
+ * The starting point for validation with Vuelidify.
238
286
  *
239
287
  * @author Daniel Walbolt
240
288
  */
241
- declare function useValidation<T, Args = undefined, FValidationReturn = unknown>(validationConfig: ValidationConfig<T, Args | undefined, FValidationReturn>): {
242
- hasValidated: boolean;
243
- validate: () => Promise<boolean>;
244
- isValidating: boolean;
245
- propertyState: ValidationState<T, FValidationReturn>;
246
- isValid: boolean;
247
- setReference: (reference: T) => void;
248
- isDirty: boolean;
249
- };
289
+ declare function useValidation<T, Args = unknown, Return = any>(validationConfig: ValidationConfig<T, Args, Return>): Reactive<UseValidationReturn<T, Return>>;
250
290
 
251
- export { ArrayValidationReturn, ArrayValidationState, ArrayValidatorTypes, AsyncValidator, BaseValidationReturn, BaseValidator, Primitive, PrimitiveValidation, PrimitiveValidationState, PrimitiveValidatorTypes, RecursiveValidation, RecursiveValidationState, SyncValidator, Validation, ValidationConfig, ValidationState, Validator, ValidatorParams, ValidatorTypes, bufferAsync, isEmailSync, maxLength, maxNumber, minLength, minNumber, mustEqual, required, throttleQueueAsync, useValidation };
291
+ export { ArrayAncestor, ArrayValidation, ArrayValidationState, AsyncValidator, BaseValidation, BaseValidationReturn, BaseValidationState, BaseValidator, ObjectValidationTypes, Primitive, PrimitiveValidationState, RecursiveValidation, RecursiveValidationState, SyncValidator, Validation, ValidationConfig, ValidationState, Validator, ValidatorParams, bufferAsync, isEmailSync, maxLength, maxNumber, minLength, minNumber, must, required, throttleQueueAsync, useValidation };
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- var g=(a,e,t)=>new Promise((i,s)=>{var r=n=>{try{l(t.next(n))}catch(V){s(V)}},d=n=>{try{l(t.throw(n))}catch(V){s(V)}},l=n=>n.done?i(n.value):Promise.resolve(n.value).then(r,d);l((t=t.apply(a,e)).next())});function O(a){let e=0,t;return(...i)=>{var r;let s=++e;return t=(r=t==null?void 0:t.then(()=>{if(e===s)return t=a(...i).then(d=>(t=void 0,d)),t}))!=null?r:a(...i).then(d=>(t=void 0,d)),t}}function I(a,e){let t=0,i;return(...s)=>new Promise(r=>{let d=++t,l=new Date().getTime();i!=null||(i=l-e);let n=l-i-e;n<0?new Promise(V=>setTimeout(V,-1*n)).then(()=>{i=new Date().getTime(),d===t&&r(a(...s)),r(void 0)}):(i=l,r(a(...s)))})}function j(a,e=t=>t){return a.reduce((t,i)=>{if(i!==void 0){let s=e(i);s!==void 0&&t.push(s)}return t},[])}function aa(){return a=>({isValid:a.value!==void 0&&String(a.value).trim().length>0,errorMessage:"This field is required"})}function ea(a){return e=>{var i;let t=String((i=e.value)!=null?i:"");return{isValid:t.length>=a,errorMessage:`Too short (${t.length} / ${a})`}}}function ta(a){return e=>{var i;let t=String((i=e.value)!=null?i:"");return{isValid:t.length<=a,errorMessage:`Too long (${t.length} / ${a})`}}}function ia(a){return e=>({isValid:e.value!==void 0&&e.value>=a,errorMessage:`The minimum value is ${a}`})}function na(a){return e=>({isValid:e.value!==void 0&&e.value<=a,errorMessage:`The maximum value is ${a}`})}function ra(a,e){return t=>({isValid:t.value===a(t),errorMessage:e})}function oa(){return a=>({isValid:a.value?RegExp(/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/).test(a.value):!1,errorMessage:"Invalid email format"})}import{ref as B,computed as x,watch as W,reactive as q}from"vue";import{computed as Q}from"vue";import{computed as A,reactive as T,ref as b,toValue as J}from"vue";function M(){return`${Date.now()}-${Math.floor(Math.random()*1e3)}`}function k(a,e){let t,i;if(z(e)){let l=$(a,e);t=T(l.validationState),i=[l]}else{let l=L(a,e);t=T(l.state),i=l.validationConfigs}return{propertyState:t,validationConfigs:i}}function S(a,e,t){let i=[],s=()=>`${e?"reactive":"lazy"}-${M()}`;t!=null&&(s=r=>`${t}-${r}`);for(let[r,d]of a.entries())i.push({validatorId:s(r),validator:d,optimized:!1,isReactive:e,previouslyReturnedValidators:!1,previouslySpawnedValidators:{},spawnedValidators:{}});return i}function $(a,e,t=[]){var V,f,u,o;let i=T({isValid:A(()=>{var P,y;let c=(P=n.isLazyValid.value)!=null?P:!1,m=(y=n.isReactiveValid.value)!=null?y:!1;return c&&m}),isValidating:A(()=>n.isValidatingReactive.value||n.isValidatingLazy.value),isErrored:A(()=>i.resultsArray.some(c=>c.isValid===!1)),errorMessages:A(()=>j(i.resultsArray,c=>c.isValid?void 0:c.errorMessage)),results:A(()=>n.namedValidationResults.value),resultsArray:A(()=>n.validationResults.value),arrayState:A(()=>{if(Array.isArray(a.value)===!1||n.elementValidation===void 0)return[];console.time("Array state");let c=a.value,m=n.elementValidation,P=n.arrayConfigMap,y=[],p={},v,w=[];for(let R=0;R<c.length;R++){if(c[R]!==void 0&&typeof c[R]=="object"?(c[R].$ffId===void 0&&Object.defineProperty(c[R],"$ffId",{value:`${n.id}-${n.elementId++}`,writable:!1,configurable:!1,enumerable:!1}),v=c[R].$ffId):c[R]!==void 0&&(v=R),w.push(v),P[v]){y.push(P[v].validationState),p[v]=P[v];continue}if(z(m)){let G=A(()=>c[R]),K=$(G,m,n.arrayParents);P[v]={validationConfigs:[K],validationState:K.validationState}}else{let G=c[R],K=L(G,m,n.arrayParents.concat(G));P[v]={validationConfigs:K.validationConfigs,validationState:K.state}}y.push(P[v].validationState),p[v]=P[v]}return n.arrayConfigMap=p,console.timeEnd("Array state"),y})}),s=!(((f=(V=e.$lazy)==null?void 0:V.length)!=null?f:-1)>0),r=!(((o=(u=e.$reactive)==null?void 0:u.length)!=null?o:-1)>0),d=e.$reactive?S(e.$reactive,!0):[],l=e.$lazy?S(e.$lazy,!1):[],n={id:M(),validationIterationId:0,isReactiveValid:b(r),isValidatingReactive:b(!1),reactiveProcessedValidators:d,isLazyValid:b(s),isValidatingLazy:b(!1),lazyProcessedValidators:l,property:a,validation:e,validationState:i,validationResults:b([]),namedValidationResults:b({}),arrayConfigMap:{},elementId:0,elementValidation:e.$each,arrayParents:T(t)};return n}function L(a,e,t=[]){let i=[],s={};e!==void 0&&r(a,e);function r(d,l){for(let n in l){let V=A(()=>J(d)[n]);if(z(l[n])){let f=l[n],u=$(V,f,t);i.push(u),s[n]=u.validationState}else{let f={},u=l[n];s[n]=f,r(V,u)}}}return{validationConfigs:i,state:s}}function z(a){return(a==null?void 0:a.$reactive)!==void 0||(a==null?void 0:a.$lazy)!==void 0||(a==null?void 0:a.$each)!==void 0}var h=250;function D(a,e,t,i,s){return g(this,null,function*(){let r=!0,d=(V,f,u)=>{if(i!==V.validationIterationId)return;u.isValid===!1&&(r=!1),u.id=f.validatorId;let o=V.validationResults.value.find(c=>c.id===u.id);o!==void 0?(Object.assign(o,u),u.name!==void 0&&V.namedValidationResults[u.name]!==void 0&&Object.assign(V.namedValidationResults.value[u.name],u)):(V.validationResults.value.push(u),u.name!==void 0&&(V.namedValidationResults.value[u.name]=u))},{asyncPromises:l,validatorsWhichPreviouslyReturnedValidators:n}=N(a,e,t,i,s,d,!0,1);if(yield Promise.all(l),i===a.validationIterationId){for(let V of n)for(let f of Object.keys(V.previouslySpawnedValidators))if(V.spawnedValidators[f]==null){let u=a.validationResults.value.findIndex(o=>o.id===f);u!==-1&&a.validationResults.value.splice(u)}}return r})}function N(a,e,t,i,s,r,d,l){let n=a.property.value,V=[],f=[],u=[];for(let o of s){let c=!1;o.previouslyReturnedValidators&&(o.previouslySpawnedValidators=o.spawnedValidators,o.spawnedValidators={},c=!0),o.previouslyReturnedValidators=!1;let m;if(o.computedValidator===void 0){let P={value:n,parent:e,args:t,arrayParents:a.arrayParents};m=o.validator(P)}else m=o.computedValidator.value;if(m instanceof Promise){let P=Date.now();V.push(m.then(y=>g(this,null,function*(){if(y===void 0){c&&u.push(o);return}let p=Date.now()-P;if(d&&p>h&&o.optimized===!1&&(o.optimized=!0,p>h&&p<2*h?o.validator=I(o.validator,h):o.validator=O(o.validator)),Array.isArray(y)){let{asyncPromises:v,syncResults:w}=C(a,e,t,i,r,o,y,l);f.push(...w),yield Promise.all(v);return}else c&&u.push(o);r(a,o,y)})))}else if(Array.isArray(m)){let{asyncPromises:P,syncResults:y}=C(a,e,t,i,r,o,m,l);V.push(...P),f.push(...y)}else if(c&&u.push(o),m!==void 0){if(d&&o.optimized===!1){let P=o.validator;o.computedValidator=Q(()=>{let y={value:a.property.value,parent:e,args:t,arrayParents:a.arrayParents};return P(y)}),o.optimized=!0,o.validator=()=>o.computedValidator.value}f.push(m),r(a,o,m)}}return{asyncPromises:V,syncResults:f,validatorsWhichPreviouslyReturnedValidators:u}}function C(a,e,t,i,s,r,d,l){let n=S(d,r.isReactive,r.validatorId),V=N(a,e,t,i,n,s,!1,++l),f={};for(let u of n)f[u.validatorId]=u;return r.spawnedValidators=f,r.previouslyReturnedValidators=!0,V}function U(a,e,t,i){return g(this,null,function*(){a.isValidatingReactive.value=!0;let s=yield D(a,e,t,i,a.reactiveProcessedValidators);return i===a.validationIterationId&&(a.isReactiveValid.value=s,a.isValidatingReactive.value=!1),a.isReactiveValid.value})}function Z(a,e,t,i){return g(this,null,function*(){a.isValidatingLazy.value=!0;let s=a.lazyProcessedValidators,r=yield D(a,e,t,i,s);return i===a.validationIterationId&&(a.isLazyValid.value=r,a.isValidatingLazy.value=!1),a.isLazyValid.value})}function F(a,e,t,i,s){return g(this,null,function*(){let r=[];for(let d of a){let l=++d.validationIterationId;if(i&&d.validation.$reactive!==void 0&&r.push(yield U(d,e.value,t,l)),s&&d.validation.$lazy!==void 0&&r.push(yield Z(d,e.value,t,l)),d.elementValidation!==void 0){let n=[];for(let V in d.arrayConfigMap)n.push(...d.arrayConfigMap[V].validationConfigs);r.push(yield F(n,e,t,i,s))}}return Promise.all(r).then(d=>d.every(l=>l===!0))})}function H(a){var P;(P=a.delayReactiveValidation)!=null||(a.delayReactiveValidation=!0);let{objectToValidate:e,validation:t,delayReactiveValidation:i,args:s}=a,r=B(!1),d=x(()=>n.some(y=>y.validationState.isValidating)),l=x(()=>n.every(p=>p.isReactiveValid.value&&p.isLazyValid.value)),n=[],V=q({}),f=B(JSON.stringify(a.objectToValidate.value)),u=x(()=>f.value!==JSON.stringify(a.objectToValidate.value)),o=k(e,t);V=o.propertyState,n=o.validationConfigs,W(a.objectToValidate,()=>{i?r.value===!0&&F(n,e,s,!0,!1):F(n,e,s,!0,!1)},{deep:!0});function c(){return g(this,null,function*(){let y=yield F(n,e,s,!0,!0);return r.value=!0,y})}function m(y){f.value=JSON.stringify(y)}return q({hasValidated:r,validate:c,isValidating:d,propertyState:x(()=>V),isValid:l,setReference:m,isDirty:u})}export{O as bufferAsync,oa as isEmailSync,ta as maxLength,na as maxNumber,ea as minLength,ia as minNumber,ra as mustEqual,aa as required,I as throttleQueueAsync,H as useValidation};
1
+ function x(e){let t=0,i;return(...r)=>{let o=++t;return i=(i==null?void 0:i.then(()=>{if(t===o)return i=new Promise(n=>n(e(...r))).then(n=>(i=void 0,n)),i}))??new Promise(n=>n(e(...r))).then(n=>(i=void 0,n)),i}}function S(e,t){let i=0,r;return(...o)=>new Promise(n=>{let l=++i,f=new Date().getTime();r??(r=f-t);let d=f-r-t;d<0?new Promise(u=>setTimeout(u,-1*d)).then(()=>{r=new Date().getTime(),l===i&&n(e(...o)),n(void 0)}):(r=f,n(e(...o)))})}function I(e,t=i=>i){return e.reduce((i,r)=>{if(r!==void 0){let o=t(r);o!==void 0&&i.push(o)}return i},[])}function X(){return e=>({isValid:e.value!=null,message:"This field is required"})}function Y(e){return t=>{let i=String(t.value??"");return{isValid:i.length>=e,message:`Too short (${i.length} / ${e})`}}}function _(e){return t=>{let i=String(t.value??"");return{isValid:i.length<=e,message:`Too long (${i.length} / ${e})`}}}function ee(e){return t=>({isValid:t.value!=null&&t.value>=e,message:`The minimum value is ${e}`})}function ae(e){return t=>({isValid:t.value!=null&&t.value<=e,message:`The maximum value is ${e}`})}function te(e,t){return i=>({isValid:e(i),message:t})}function ie(){return e=>({isValid:e.value?RegExp(/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/).test(e.value):!1,message:"Invalid email format"})}import{computed as b,reactive as q,ref as N,watch as Z}from"vue";import{computed as U,toValue as G}from"vue";import{computed as R,reactive as O,ref as P,toValue as M}from"vue";function L(){return`${Date.now()}-${Math.floor(Math.random()*1e3)}`}function C(e,t){return D(e,t)}function A(e,t,i){let r=[],o=()=>`${t?"reactive":"lazy"}-${L()}`;i!=null&&(o=n=>`${i}-${n}`);for(let[n,l]of e.entries())r.push({validatorId:o(n),validator:l,optimized:!1,isReactive:t,previouslyReturnedValidators:!1,previouslySpawnedValidators:{},spawnedValidators:{}});return r}function K(e,t,i=[]){var u;let r=O({$state:{isValid:R(()=>{let s=d.isLazyValid.value??!1,c=d.isReactiveValid.value??!1;return s&&c}),isValidating:R(()=>d.isValidatingReactive.value||d.isValidatingLazy.value),isErrored:R(()=>{var s;return((s=r.$state)==null?void 0:s.resultsArray.some(c=>c.isValid===!1))??!1}),errorMessages:R(()=>{var s;return I(((s=r.$state)==null?void 0:s.resultsArray)??[],c=>c.isValid?void 0:c.message)}),results:R(()=>d.namedValidationResults.value),resultsArray:R(()=>d.validationResults.value)},$arrayState:R(()=>{if(Array.isArray(e.value)===!1||d.elementValidation===void 0)return[];let s=e.value,c=d.elementValidation,a=d.arrayConfigMap,v=[],m={},y,V=[];for(let p=0;p<s.length;p++){let T=s[p]!==void 0&&typeof s[p]=="object";if(T?(s[p].$ffId===void 0&&Object.defineProperty(s[p],"$ffId",{value:`${d.id}-${d.elementId++}`,writable:!1,configurable:!1,enumerable:!1}),y=s[p].$ffId):s[p]!==void 0&&(y=p),V.push(y),a[y]){v.push(a[y].validationState),m[y]=a[y];continue}let h=R(()=>s[p]),z=[...d.arrayAncestors];T&&z.push({ancestor:h,array:s,index:p});let k=D(h,c,z);a[y]={validationConfigs:k.validationConfigs,validationState:k.state},v.push(a[y].validationState),m[y]=a[y]}return d.arrayConfigMap=m,v})}),o=!0,n=!0,l=[],f=[];t.$reactive&&t.$reactive.length>0&&(n=!1,l=A(t.$reactive,!0)),t.$lazy&&((u=t.$lazy)==null?void 0:u.length)>0&&(o=!1,f=A(t.$lazy,!1));let d={id:L(),reactiveIterationId:0,lazyIterationId:0,isReactiveValid:P(n),isValidatingReactive:P(!1),reactiveProcessedValidators:l,isLazyValid:P(o),isValidatingLazy:P(!1),lazyProcessedValidators:f,target:e,validation:t,validationState:r,validationResults:P([]),namedValidationResults:P({}),arrayConfigMap:{},elementId:0,elementValidation:t.$each,arrayAncestors:O(i)};return d}function D(e,t,i=[]){let r=[],o={};if(j(t)){let l=R(()=>M(e)),f=K(l,t,i);r.push(f),o=f.validationState}t!=null&&n(e,t,o);function n(l,f,d){if($(f)!==!1)for(let u in f){if(u==="$reactive"||u==="$lazy"||u==="$each")continue;let s=R(()=>{let a=M(l);return $(a)?a[u]:(console.error(`Vuelidify Error: validation could not be setup correctly on ${a} because ${l} is not enumerable.`),null)}),c=f[u];if(j(c)){let a=K(s,c,i);r.push(a),d[u]=a.validationState}if($(c)){let a=d[u]??{};d[u]=a,n(s,c,a)}}}return{validationConfigs:r,state:o}}function j(e){return Array.isArray(e==null?void 0:e.$reactive)||Array.isArray(e==null?void 0:e.$lazy)||(e==null?void 0:e.$each)!==void 0}function $(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}var w=250;async function B(e,t,i,r,o,n){let l=!0,f=(s,c,a)=>{if(r!==G(o))return;a.isValid===!1&&(l=!1),a.id=c.validatorId;let v=s.validationResults.value.find(m=>m.id===a.id);v!==void 0?(Object.assign(v,a),a.name!==void 0&&s.namedValidationResults.value[a.name]!==void 0&&Object.assign(s.namedValidationResults.value[a.name],a)):(s.validationResults.value.push(a),a.name!==void 0&&(s.namedValidationResults.value[a.name]=a))},{asyncPromises:d,validatorsWhichPreviouslyReturnedValidators:u}=F(e,t,i,r,n,f,!0,1);if(await Promise.all(d),r===G(o)){for(let s of u)for(let c of Object.keys(s.previouslySpawnedValidators))if(s.spawnedValidators[c]==null){let a=e.validationResults.value.findIndex(v=>v.id===c);a!==-1&&e.validationResults.value.splice(a)}}return l}function F(e,t,i,r,o,n,l,f){let d=e.target.value,u=[],s=[],c=[];for(let a of o){let v=!1;a.previouslyReturnedValidators&&(a.previouslySpawnedValidators=a.spawnedValidators,a.spawnedValidators={},v=!0),a.previouslyReturnedValidators=!1;let m;if(a.computedValidator===void 0){let y={value:d,model:t,args:i,arrayAncestors:e.arrayAncestors};m=a.validator(y)}else m=a.computedValidator.value;if(m instanceof Promise){let y=Date.now();u.push(m.then(async V=>{if(V===void 0){v&&c.push(a);return}let p=Date.now()-y;if(l&&p>w&&a.optimized===!1&&(a.optimized=!0,p>w&&p<2*w?a.validator=S(a.validator,w):a.validator=x(a.validator)),Array.isArray(V)){let{asyncPromises:T,syncResults:h}=E(e,t,i,r,n,a,V,f);s.push(...h),await Promise.all(T);return}else v&&c.push(a);n(e,a,V)}))}else if(Array.isArray(m)){let{asyncPromises:y,syncResults:V}=E(e,t,i,r,n,a,m,f);u.push(...y),s.push(...V)}else if(v&&c.push(a),m!==void 0){if(l&&a.optimized===!1){let y=a.validator;a.computedValidator=U(()=>{let V={value:e.target.value,model:t,args:i,arrayAncestors:e.arrayAncestors};return y(V)}),a.optimized=!0,a.validator=()=>{var V;return(V=a.computedValidator)==null?void 0:V.value}}s.push(m),n(e,a,m)}}return{asyncPromises:u,syncResults:s,validatorsWhichPreviouslyReturnedValidators:c}}function E(e,t,i,r,o,n,l,f){let d=A(l,n.isReactive,n.validatorId),u=F(e,t,i,r,d,o,!1,++f),s={};for(let c of d)s[c.validatorId]=c;return n.spawnedValidators=s,n.previouslyReturnedValidators=!0,u}async function J(e,t,i,r,o){e.isValidatingReactive.value=!0;let n=await B(e,t,i,r,o,e.reactiveProcessedValidators);return r===G(o)&&(e.isReactiveValid.value=n,e.isValidatingReactive.value=!1),e.isReactiveValid.value??!1}async function Q(e,t,i,r,o){e.isValidatingLazy.value=!0;let n=await B(e,t,i,r,o,e.lazyProcessedValidators);return r===G(o)&&(e.isLazyValid.value=n,e.isValidatingLazy.value=!1),e.isLazyValid.value??!1}function g(e,t,i,r,o){let n=[];for(let l of e)if(r&&l.reactiveProcessedValidators.length>0&&n.push(J(l,t.value,i,++l.reactiveIterationId,()=>l.reactiveIterationId)),o&&l.lazyProcessedValidators.length>0&&n.push(Q(l,t.value,i,++l.lazyIterationId,()=>l.lazyIterationId)),Array.isArray(l.validationState.$arrayState)){let f=[];for(let d in l.arrayConfigMap)f.push(...l.arrayConfigMap[d].validationConfigs);n.push(g(f,t,i,r,o))}return Promise.all(n).then(l=>l.every(f=>f===!0))}function W(e){e.delayReactiveValidation??(e.delayReactiveValidation=!0);let{model:t,validation:i,delayReactiveValidation:r,args:o}=e,n=N(!1),l=b(()=>u.some(V=>V.isValidatingLazy.value||V.isValidatingReactive.value)),f=b(()=>u.some(V=>V.validationResults.value.some(p=>p.isValid===!1))),d=b(()=>u.every(p=>p.isReactiveValid.value&&p.isLazyValid.value)),u=[],s=N(JSON.stringify(e.model.value)),c=b(()=>s.value!==JSON.stringify(e.model.value)),a=C(t,i),v=a.state;u=a.validationConfigs,Z(e.model,()=>{r?n.value===!0&&g(u,t,o,!0,!1):g(u,t,o,!0,!1)},{deep:!0});async function m(){let V=await g(u,t,o,!0,!0);return n.value=!0,V}function y(V){s.value=JSON.stringify(V)}return q({hasValidated:n,validate:m,isValidating:l,state:b(()=>v),isValid:d,isErrored:f,setReference:y,isDirty:c})}export{x as bufferAsync,ie as isEmailSync,_ as maxLength,ae as maxNumber,Y as minLength,ee as minNumber,te as must,X as required,S as throttleQueueAsync,W as useValidation};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vuelidify",
3
- "version": "1.0.1",
3
+ "version": "2.0.1",
4
4
  "author": "Daniel Walbolt",
5
5
  "private": false,
6
6
  "main": "./dist/index.js",