vuelidify 2.0.2 → 2.0.3
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 +52 -18
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -7,10 +7,12 @@ Powerful and typed model-based validation for Vue 3
|
|
|
7
7
|
|
|
8
8
|
[Examples](#examples)
|
|
9
9
|
|
|
10
|
-
[
|
|
10
|
+
[Provided Validators](#provided-validators)
|
|
11
11
|
|
|
12
12
|
[Custom Validators](#custom-validators)
|
|
13
13
|
|
|
14
|
+
[Technical Details](#technical-details)
|
|
15
|
+
|
|
14
16
|
---
|
|
15
17
|
|
|
16
18
|
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.
|
|
@@ -367,23 +369,37 @@ const bErrors = v$.state.b?.$arrayState;
|
|
|
367
369
|
```
|
|
368
370
|
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.
|
|
369
371
|
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
-
|
|
372
|
+
# Provided Validators
|
|
373
|
+
Here are the validators that Vuelidify provides by default:
|
|
374
|
+
|
|
375
|
+
- ```ts
|
|
376
|
+
required()
|
|
377
|
+
```
|
|
378
|
+
- ```ts
|
|
379
|
+
minLength(min: number)
|
|
380
|
+
```
|
|
381
|
+
- ```ts
|
|
382
|
+
maxLength(max: number)
|
|
383
|
+
```
|
|
384
|
+
- ```ts
|
|
385
|
+
minNumber(min: number)
|
|
386
|
+
```
|
|
387
|
+
- ```ts
|
|
388
|
+
maxNumber(max: number)
|
|
389
|
+
```
|
|
390
|
+
- ```ts
|
|
391
|
+
must(fn: (params) => boolean, errorMessage: string)
|
|
392
|
+
```
|
|
393
|
+
- ```ts
|
|
394
|
+
isEmailSync()
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
There aren't many validators provided by this library on purpose. If you feel a validator would be useful for everyone to have, give us feedback on our GitHub repository. However, we highly encourage you to understand how to make your own!
|
|
380
398
|
|
|
381
399
|
# Custom Validators
|
|
382
|
-
|
|
400
|
+
This section guides you to create your own generic validators. Validators were designed to be easy to create and easier to use.
|
|
383
401
|
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
Here is a breakdown of one of the validators exported by this library (expanded to make comments more readable):
|
|
402
|
+
Here is a breakdown of one of the built-in validators (expanded to make comments more readable):
|
|
387
403
|
|
|
388
404
|
```ts
|
|
389
405
|
// always provide a header comment to explain what the validator does!
|
|
@@ -403,12 +419,11 @@ export function isEmailSync<
|
|
|
403
419
|
V,
|
|
404
420
|
// The type for the custom return from the validator
|
|
405
421
|
R,
|
|
406
|
-
// The type for the
|
|
422
|
+
// The type for the arrayAncestors parameter.
|
|
407
423
|
// Generally you don't put constraints on this.
|
|
408
|
-
// But you have to accept this generic in order to pass the type forward to not mess up outside types.
|
|
409
424
|
A
|
|
410
425
|
>(
|
|
411
|
-
// Specify any parameters you need here. This
|
|
426
|
+
// Specify any parameters you need here. This can be configuration (like a max length) or reactive variables.
|
|
412
427
|
): SyncValidator<T, P, V, R, A> // Explicitly type the validator you'll be returning
|
|
413
428
|
{
|
|
414
429
|
// Return a validator function
|
|
@@ -443,4 +458,23 @@ export function isEmailSync<T extends string | undefined | null>(): SyncValidato
|
|
|
443
458
|
|
|
444
459
|
This validator is effectively: `SyncValidator<string | undefined | null, unknown, unknown, unknown, unknown>`
|
|
445
460
|
|
|
461
|
+
## Technical Details
|
|
462
|
+
For those interested in the inner workings of the library without looking at the code:
|
|
463
|
+
|
|
464
|
+
- 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.
|
|
465
|
+
|
|
466
|
+
- 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).
|
|
467
|
+
|
|
468
|
+
- Validation results are ideally visible as soon as possible. Synchronous validation should not wait for async validation to finish before displaying errors. Vuelidify implements this by running all validators concurrently, and assimilating the validation results as they finish. This is fairly intuitive. However, what happens when you have lazy validation and reactive validation? You can't replace the array every time a new validation cycle happens, because that could lose the results from lazy validation! Each validator is assigned an ID internally. This ID is used for identifying the results from validators. When a result is returned, Vuelidify determines if it already exists in the results array. If it does, then Vuelidify updates all the data in that result to the data from the new result. This feature is particularly useful if you want to do animations on validation errors, because the error won't be leaving and re-entering the array every time validation is done.
|
|
469
|
+
|
|
470
|
+
- 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.
|
|
471
|
+
|
|
472
|
+
- `throttleAsync` is an async throttler that preserves your function’s 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`.
|
|
473
|
+
|
|
474
|
+
- `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`.
|
|
475
|
+
|
|
476
|
+
- 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.
|
|
477
|
+
|
|
478
|
+
- 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. `Return` is the only part of Vuelidify that is not strongly-typed. Be sure to cast it to what you expect before using it.
|
|
479
|
+
|
|
446
480
|
Feel free to post issues you may have with the package on the git repo! Happy validating!
|