vue3-form-validation
Version:
Vue composition function for form validation
1,062 lines (1,040 loc) • 35.9 kB
JavaScript
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
var vue = require('vue');
class LinkedListNode {
constructor(value) {
Object.defineProperty(this, "value", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "next", {
enumerable: true,
configurable: true,
writable: true,
value: null
});
Object.defineProperty(this, "prev", {
enumerable: true,
configurable: true,
writable: true,
value: null
});
this.value = value;
}
}
class LinkedList {
constructor() {
Object.defineProperty(this, "first", {
enumerable: true,
configurable: true,
writable: true,
value: null
});
Object.defineProperty(this, "last", {
enumerable: true,
configurable: true,
writable: true,
value: null
});
Object.defineProperty(this, "count", {
enumerable: true,
configurable: true,
writable: true,
value: 0
});
}
addFirst(value) {
const node = new LinkedListNode(value);
if (this.count === 0) {
this.first = node;
this.last = node;
}
else {
node.next = this.first;
this.first.prev = node;
this.first = node;
}
this.count++;
return node;
}
addLast(value) {
const node = new LinkedListNode(value);
if (this.count === 0) {
this.first = node;
this.last = node;
}
else {
node.prev = this.last;
this.last.next = node;
this.last = node;
}
this.count++;
return node;
}
remove(node) {
if (this.count === 0) {
return;
}
if (node === this.first) {
this.removeFirst();
}
else if (node === this.last) {
this.removeLast();
}
else {
node.prev.next = node.next;
node.next.prev = node.prev;
node.next = null;
node.prev = null;
this.count--;
}
}
removeFirst() {
if (this.count === 0) {
return;
}
if (this.count === 1) {
this.first = null;
this.last = null;
this.count--;
}
else {
this.first = this.first.next;
this.first.prev.next = null;
this.first.prev = null;
this.count--;
}
}
removeLast() {
if (this.count === 0) {
return;
}
if (this.count === 1) {
this.first = null;
this.last = null;
this.count--;
}
else {
this.last = this.last.prev;
this.last.next.prev = null;
this.last.next = null;
this.count--;
}
}
*nodesForwards() {
let node = this.first;
for (; node !== null; node = node.next) {
yield node;
}
}
*nodesBackwards() {
let node = this.last;
for (; node !== null; node = node.prev) {
yield node;
}
}
}
const isDefined = (x) => x !== null && x !== undefined;
const isRecord = (x) => typeof x === 'object' && x !== null && !Array.isArray(x);
const isArray = (x) => Array.isArray(x);
const isObject = (x) => typeof x === 'object' && x !== null;
function* deepIterator(obj, predicate = () => false) {
const stack = new LinkedList();
stack.addLast({ current: obj, parent: null, parentKey: '', path: [] });
while (stack.count > 0) {
const { current, parent, parentKey, path } = stack.last.value;
stack.removeLast();
let pushedItemsOnStack = false;
if (isObject(current) && !vue.isRef(current) && !predicate(current)) {
const entries = Object.entries(current);
pushedItemsOnStack = entries.length > 0;
for (let i = entries.length - 1; i >= 0; i--) {
const [key, value] = entries[i];
stack.addLast({
current: value,
parent: current,
parentKey: key,
path: [...path, key]
});
}
}
if (isObject(parent)) {
yield {
key: parentKey,
value: parent[parentKey],
parent,
path,
isLeaf: !pushedItemsOnStack
};
}
}
}
function set(obj, keys, value) {
if (keys.length === 0) {
return;
}
let o = obj;
for (let i = 0; i < keys.length - 1; i++) {
const key = keys[i];
const nextKey = keys[i + 1];
const value = o[key];
if (value === undefined) {
if (Number.isNaN(+nextKey)) {
o[key] = {};
}
else {
o[key] = [];
}
}
o = o[key];
}
o[keys[keys.length - 1]] = value;
}
function deepCopy(toClone) {
if (isObject(toClone)) {
const copy = isArray(toClone) ? [] : {};
for (const { value, path, isLeaf } of deepIterator(toClone)) {
if (isLeaf) {
set(copy, path, value);
}
}
return copy;
}
return toClone;
}
const trySet = (map) => ({ success, failure }) => (key, value) => {
const _value = map.get(key);
if (_value) {
failure === null || failure === void 0 ? void 0 : failure(_value);
}
else {
map.set(key, value);
success === null || success === void 0 ? void 0 : success(value);
}
};
const tryGet = (map) => ({ success, failure }) => (key) => {
const value = map.get(key);
if (value) {
success(value);
}
else {
failure === null || failure === void 0 ? void 0 : failure();
}
};
function path(path, obj) {
let value = obj[path[0]];
for (let i = 0; i < path.length; i++) {
const key = path[i];
if (value === null || value === undefined) {
return undefined;
}
if (i > 0) {
value = value[key];
}
}
return value;
}
let id = 1;
function uid() {
return id++;
}
function debounce(target, { wait }) {
let timerId = null;
function cancel() {
clearTimeout(timerId);
}
function debounced(...args) {
const effect = () => {
timerId = null;
target.apply(this, args);
};
clearTimeout(timerId);
timerId = setTimeout(effect, wait);
}
debounced.cancel = cancel;
return debounced;
}
class PromiseCancel {
constructor() {
Object.defineProperty(this, "promise", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "resolve", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "reject", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "isRacing", {
enumerable: true,
configurable: true,
writable: true,
value: false
});
this.assign();
}
cancelResolve(value) {
if (this.isRacing) {
this.isRacing = false;
this.resolve(value);
this.assign();
}
}
cancelReject(reason) {
if (this.isRacing) {
this.isRacing = false;
this.reject(reason);
this.assign();
}
}
race(...promises) {
this.isRacing = true;
return Promise.race([this.promise, ...promises]);
}
assign() {
this.promise = new Promise((resolve, reject) => {
this.resolve = resolve;
this.reject = reject;
});
}
}
class ValidationError extends Error {
constructor() {
super('One or more validation errors occurred.');
}
}
const isSimpleRule = (rule) => typeof rule === 'function';
const unpackRule = (rule) => (isSimpleRule(rule) ? rule : rule.rule);
class FormField {
constructor(form, uid, name, modelValue, ruleInfos) {
Object.defineProperty(this, "watchStopHandle", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "form", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "ruleInfos", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "rulesValidating", {
enumerable: true,
configurable: true,
writable: true,
value: vue.ref(0)
});
Object.defineProperty(this, "initialModelValue", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "uid", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "name", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "touched", {
enumerable: true,
configurable: true,
writable: true,
value: vue.ref(false)
});
Object.defineProperty(this, "dirty", {
enumerable: true,
configurable: true,
writable: true,
value: vue.ref(false)
});
Object.defineProperty(this, "modelValue", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "rawErrors", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "errors", {
enumerable: true,
configurable: true,
writable: true,
value: vue.computed(() => this.rawErrors.filter(isDefined))
});
Object.defineProperty(this, "validating", {
enumerable: true,
configurable: true,
writable: true,
value: vue.computed(() => this.rulesValidating.value > 0)
});
Object.defineProperty(this, "hasError", {
enumerable: true,
configurable: true,
writable: true,
value: vue.computed(() => this.errors.value.length > 0)
});
this.form = form;
this.uid = uid;
this.name = name;
this.modelValue = vue.ref(modelValue);
this.rawErrors = vue.reactive(ruleInfos.map(() => null));
this.initialModelValue = deepCopy(this.modelValue.value);
this.ruleInfos = ruleInfos.map((info, ruleNumber) => {
let validator;
const validatorNotDebounced = (modelValues, force, submit) => {
if (this.shouldValidate(ruleNumber, force, submit) === true) {
return this.validate(ruleNumber, modelValues);
}
};
let debouncedValidator;
let debounceInvokedTimes = 0;
let debounceResolve;
if (info.debounce) {
debouncedValidator = debounce(modelValues => {
debounceResolve(this.validate(ruleNumber, modelValues));
this.rulesValidating.value -= debounceInvokedTimes;
this.form.rulesValidating.value -= debounceInvokedTimes;
debounceInvokedTimes = 0;
}, {
wait: info.debounce
});
validator = (modelValues, force, submit) => {
if (this.shouldValidate(ruleNumber, force, submit) === true) {
debounceInvokedTimes++;
this.rulesValidating.value++;
this.form.rulesValidating.value++;
return new Promise(resolve => {
debounceResolve === null || debounceResolve === void 0 ? void 0 : debounceResolve();
debounceResolve = resolve;
debouncedValidator(modelValues, force, submit);
});
}
};
}
else {
validator = validatorNotDebounced;
}
return {
buffer: new LinkedList(),
rule: unpackRule(info.rule),
validator,
validatorNotDebounced,
validationBehavior: info.validationBehavior,
cancelDebounce: () => {
if (debouncedValidator) {
debounceInvokedTimes = 0;
debouncedValidator.cancel();
debounceResolve === null || debounceResolve === void 0 ? void 0 : debounceResolve();
}
}
};
});
this.watchStopHandle = this.setupWatcher();
}
async validate(ruleNumber, modelValues) {
var _a;
const { rule, buffer } = this.ruleInfos[ruleNumber];
if (!rule) {
return;
}
let error;
const ruleResult = rule(...modelValues);
if ((_a = buffer.last) === null || _a === void 0 ? void 0 : _a.value) {
buffer.last.value = false;
this.rulesValidating.value--;
this.form.rulesValidating.value--;
}
if (typeof (ruleResult === null || ruleResult === void 0 ? void 0 : ruleResult.then) === 'function') {
const shouldSetError = buffer.addLast(true);
this.rulesValidating.value++;
this.form.rulesValidating.value++;
try {
error = await ruleResult;
}
catch (err) {
error = err;
}
buffer.remove(shouldSetError);
if (shouldSetError.value) {
this.rulesValidating.value--;
this.form.rulesValidating.value--;
this.setError(ruleNumber, error);
}
else {
/**
* This branch is reached in one of two cases:
* 1. While this rule was validating the same async rule was invoked again.
* 2. While this rule was validating the field was reset.
*
* In both cases, no error is to be set but the promise should still reject
* if the rule returns a string.
*/
if (typeof error === 'string') {
throw error;
}
}
}
else {
error = ruleResult;
this.setError(ruleNumber, error);
}
}
reset(resetValue = this.initialModelValue) {
this.watchStopHandle();
this.touched.value = false;
this.dirty.value = false;
this.modelValue.value = deepCopy(resetValue);
this.rulesValidating.value = 0;
this.form.rulesValidating.value = 0;
for (let i = 0; i < this.ruleInfos.length; i++) {
this.rawErrors[i] = null;
this.ruleInfos[i].cancelDebounce();
for (const shouldSetError of this.ruleInfos[i].buffer.nodesForwards()) {
shouldSetError.value = false;
}
}
this.watchStopHandle = this.setupWatcher();
}
dispose() {
this.errors.effect.stop();
this.validating.effect.stop();
this.hasError.effect.stop();
this.watchStopHandle();
}
shouldValidate(ruleNumber, force, submit) {
return this.ruleInfos[ruleNumber].validationBehavior({
hasError: this.rawErrors[ruleNumber] !== null,
touched: this.touched.value,
dirty: this.dirty.value,
force,
submit,
value: this.modelValue.value
});
}
setError(ruleNumber, error) {
if (typeof error === 'string') {
this.rawErrors[ruleNumber] = error;
throw error;
}
else {
this.rawErrors[ruleNumber] = null;
}
}
setupWatcher() {
return vue.watch(this.modelValue, () => {
this.dirty.value = true;
this.form.validate(this.uid);
}, { deep: true });
}
}
class Form {
constructor() {
Object.defineProperty(this, "simpleValidators", {
enumerable: true,
configurable: true,
writable: true,
value: new Map()
});
Object.defineProperty(this, "keyedValidators", {
enumerable: true,
configurable: true,
writable: true,
value: new Map()
});
Object.defineProperty(this, "reactiveFields", {
enumerable: true,
configurable: true,
writable: true,
value: vue.shallowReactive(new Map())
});
Object.defineProperty(this, "tryGetSimpleValidators", {
enumerable: true,
configurable: true,
writable: true,
value: tryGet(this.simpleValidators)
});
Object.defineProperty(this, "trySetKeyedValidators", {
enumerable: true,
configurable: true,
writable: true,
value: trySet(this.keyedValidators)
});
Object.defineProperty(this, "tryGetKeyedValidators", {
enumerable: true,
configurable: true,
writable: true,
value: tryGet(this.keyedValidators)
});
Object.defineProperty(this, "rulesValidating", {
enumerable: true,
configurable: true,
writable: true,
value: vue.ref(0)
});
Object.defineProperty(this, "submitting", {
enumerable: true,
configurable: true,
writable: true,
value: vue.ref(false)
});
Object.defineProperty(this, "validating", {
enumerable: true,
configurable: true,
writable: true,
value: vue.computed(() => this.rulesValidating.value > 0)
});
Object.defineProperty(this, "hasError", {
enumerable: true,
configurable: true,
writable: true,
value: vue.computed(() => this.errors.value.length > 0)
});
Object.defineProperty(this, "errors", {
enumerable: true,
configurable: true,
writable: true,
value: vue.computed(() => {
const errors = [];
for (const field of this.reactiveFields.values()) {
errors.push(...field.errors.value);
}
return errors;
})
});
}
registerField(uid, name, modelValue, ruleInfos) {
const field = new FormField(this, uid, name, modelValue, ruleInfos);
const simpleValidators = {
validators: [],
validatorsNotDebounced: [],
meta: {
field,
keys: [],
rollbacks: []
}
};
ruleInfos.forEach(({ rule }, ruleNumber) => {
const validator = field.ruleInfos[ruleNumber].validator;
const validatorNotDebounced = field.ruleInfos[ruleNumber].validatorNotDebounced;
if (isSimpleRule(rule)) {
simpleValidators.validators.push(validator);
simpleValidators.validatorsNotDebounced.push(validatorNotDebounced);
}
else {
const keyedValidator = {
validator,
validatorNotDebounced,
meta: {
field
}
};
const rollback = () => {
this.tryGetKeyedValidators({
success: keyedValidators => {
keyedValidators.delete(keyedValidator);
if (keyedValidators.size === 0) {
this.keyedValidators.delete(rule.key);
}
}
})(rule.key);
};
simpleValidators.meta.keys.push(rule.key);
simpleValidators.meta.rollbacks.push(rollback);
this.trySetKeyedValidators({
failure: keyedValidators => keyedValidators.add(keyedValidator)
})(rule.key, new Set([keyedValidator]));
}
});
this.simpleValidators.set(uid, simpleValidators);
this.reactiveFields.set(uid, field);
return field;
}
validate(uid, force = false) {
const { validators, meta } = this.simpleValidators.get(uid);
return Promise.allSettled([
...validators.map(validator => validator([meta.field.modelValue.value], force, false)),
...this.collectValidatorResultsForKeysDebounced(meta.keys, force)
]);
}
async validateAll(names) {
const settledResults = await Promise.allSettled(this.collectValidatorResultsForNames(names));
for (const result of settledResults) {
if (result.status === 'rejected') {
throw new ValidationError();
}
}
}
dispose(uid) {
this.tryGetSimpleValidators({
success: ({ meta }) => {
meta.field.dispose();
meta.rollbacks.forEach(r => r());
}
})(uid);
this.simpleValidators.delete(uid);
this.reactiveFields.delete(uid);
}
resetFields() {
for (const { meta } of this.simpleValidators.values()) {
meta.field.reset();
}
}
getField(uid) {
const simpleValidators = this.simpleValidators.get(uid);
if (simpleValidators) {
return simpleValidators.meta.field;
}
}
/**
* Should only be called from `validateAll`
* (`force` and `submit` will default to `false` and `true`).
*
* @param keys The keys of the rules to validate
*/
*collectValidatorResultsForKeys(keys) {
for (const key of keys) {
const keyedValidators = this.keyedValidators.get(key);
const values = [...keyedValidators.values()];
const modelValues = values.map(({ meta }) => meta.field.modelValue.value);
for (const { validatorNotDebounced } of values) {
yield validatorNotDebounced(modelValues, false, true);
}
}
}
/**
* Should only be called from `validate`
* (`submit` will default to `false`).
* It will also check if every field of a key is touched before
* invoking the validator and not use the debounced version.
*
* @param keys The keys of the rules to validate
*/
*collectValidatorResultsForKeysDebounced(keys, force) {
for (const key of keys) {
const keyedValidators = this.keyedValidators.get(key);
if (this.isEveryFieldTouched(keyedValidators)) {
const values = [...keyedValidators.values()];
const modelValues = values.map(({ meta }) => meta.field.modelValue.value);
for (const { validator } of values) {
yield validator(modelValues, force, false);
}
}
}
}
*collectValidatorResultsForNames(names) {
if (names === undefined) {
for (const { validatorsNotDebounced, meta } of this.simpleValidators.values()) {
meta.field.touched.value = true;
for (const validator of validatorsNotDebounced) {
yield validator([meta.field.modelValue.value], false, true);
}
}
yield* this.collectValidatorResultsForKeys(this.keyedValidators.keys());
}
else if (names.length > 0) {
const uniqueNames = new Set(names);
for (const { validatorsNotDebounced, meta } of this.simpleValidators.values()) {
if (uniqueNames.has(meta.field.name)) {
meta.field.touched.value = true;
for (const validator of validatorsNotDebounced) {
yield validator([meta.field.modelValue.value], false, true);
}
yield* this.collectValidatorResultsForKeys(this.keyedValidators.keys());
}
}
}
}
isEveryFieldTouched(keyedValidators) {
for (const { meta } of keyedValidators) {
if (!meta.field.touched.value) {
return false;
}
}
return true;
}
}
class ValidationConfig {
constructor() {
Object.defineProperty(this, "defaultValidationBehavior", {
enumerable: true,
configurable: true,
writable: true,
value: null
});
Object.defineProperty(this, "validationBehavior", {
enumerable: true,
configurable: true,
writable: true,
value: new Map()
});
}
getDefaultValidationBehavior() {
if (this.defaultValidationBehavior === null) {
return () => true;
}
return this.validationBehavior.get(this.defaultValidationBehavior);
}
}
const VALIDATION_CONFIG = new ValidationConfig();
const isField = (x) => isRecord(x) ? '$value' in x : false;
const isTransformedField = (x) => isRecord(x) ? '$uid' in x && '$value' in x : false;
function mapFieldRules(fieldRules) {
const defaultValidationBehavior = VALIDATION_CONFIG.getDefaultValidationBehavior();
return fieldRules.map(fieldRule => {
if (typeof fieldRule === 'function') {
return {
validationBehavior: defaultValidationBehavior,
rule: fieldRule
};
}
if (Array.isArray(fieldRule)) {
const [first, second, third] = fieldRule;
if (typeof second === 'number') {
return {
validationBehavior: defaultValidationBehavior,
rule: first,
debounce: second
};
}
if (typeof first === 'function') {
return {
validationBehavior: first,
rule: second,
debounce: third
};
}
const validationBehavior = VALIDATION_CONFIG.validationBehavior.get(first);
if (validationBehavior !== undefined) {
return { validationBehavior, rule: second, debounce: third };
}
else {
throw new Error(`[useValidation] Validation behavior with name '${first}' does not exist. Valid values are: ${[
...VALIDATION_CONFIG.validationBehavior.keys()
].join(', ')}`);
}
}
else {
return {
validationBehavior: defaultValidationBehavior,
rule: fieldRule
};
}
});
}
function registerField(form, name, field) {
const { $value, $rules, ...fieldExtraProperties } = field;
const rules = $rules ? mapFieldRules($rules) : [];
const uid$1 = uid();
const formField = form.registerField(uid$1, name, $value, rules);
return {
...fieldExtraProperties,
$uid: uid$1,
$value: formField.modelValue,
$errors: formField.errors,
$hasError: formField.hasError,
$rawErrors: formField.rawErrors,
$validating: formField.validating,
$dirty: formField.dirty,
$touched: formField.touched,
async $validate({ setTouched, force } = {}) {
setTouched !== null && setTouched !== void 0 ? setTouched : (setTouched = true);
force !== null && force !== void 0 ? force : (force = true);
if (setTouched) {
formField.touched.value = true;
}
await form.validate(uid$1, force);
}
};
}
function transformFormData(form, formData) {
for (const { key, value, parent } of deepIterator(formData)) {
if (isField(value)) {
const transformedField = registerField(form, key, value);
parent[key] = transformedField;
}
}
}
function getResultFormData(transformedFormData, predicate = () => true) {
const result = {};
for (const { key, value, path, isLeaf } of deepIterator(transformedFormData, isTransformedField)) {
if (isLeaf) {
const unpackedValue = isTransformedField(value)
? value.$value
: vue.unref(value);
if (predicate({ key, value: unpackedValue, path }) === true) {
set(result, path, deepCopy(unpackedValue));
}
}
}
return result;
}
function disposeForm(form, deletedFormData) {
for (const { value } of deepIterator({ box: deletedFormData }, isTransformedField)) {
if (isTransformedField(value)) {
form.dispose(value.$uid);
}
}
}
function resetFields(form, data, transformedFormData) {
Object.entries(data).forEach(([key, value]) => {
const transformedValue = transformedFormData[key];
if (isTransformedField(transformedValue)) {
const field = form.getField(transformedValue.$uid);
field.reset(value);
return;
}
if (isObject(value)) {
resetFields(form, value, transformedFormData[key]);
}
});
}
/**
* Vue composition function for form validation.
*
* @remarks
* For type inference in `useValidation` make sure to define the structure of your
* form data upfront and pass it as the generic parameter `FormData`.
*
* @param formData - The structure of your form data
*
* @example
* ```
* type FormData = {
* name: Field<string>,
* password: Field<string>
* }
*
* const { form } = useValidation<FormData>({
* name: {
* $value: '',
* $rules: []
* },
* password: {
* $value: '',
* $rules: []
* }
* })
* ```
*/
function useValidation(formData) {
const form = new Form();
const promiseCancel = new PromiseCancel();
transformFormData(form, formData);
const transformedFormData = vue.reactive(formData);
return {
form: transformedFormData,
submitting: form.submitting,
validating: form.validating,
hasError: form.hasError,
errors: form.errors,
async validateFields({ names, predicate } = {}) {
form.submitting.value = true;
const resultFormData = getResultFormData(transformedFormData, predicate);
try {
await promiseCancel.race(form.validateAll(names));
}
finally {
form.submitting.value = false;
}
return resultFormData;
},
resetFields(formData) {
promiseCancel.cancelReject(new ValidationError());
if (formData === undefined) {
form.resetFields();
}
else {
resetFields(form, formData, transformedFormData);
}
},
add(path$1, value) {
const lastKey = path$1[path$1.length - 1];
if (lastKey !== undefined) {
const box = { [lastKey]: value };
transformFormData(form, box);
const transformedValue = box[lastKey];
const valueAtPath = path(path$1, transformedFormData);
if (Array.isArray(valueAtPath)) {
valueAtPath.push(transformedValue);
}
else {
set(transformedFormData, path$1, transformedValue);
}
}
},
remove(path$1) {
const lastKey = path$1.pop();
if (lastKey !== undefined) {
if (path$1.length === 0) {
disposeForm(form, transformedFormData[lastKey]);
delete transformedFormData[lastKey];
}
else {
const valueAtPath = path(path$1, transformedFormData);
if (Array.isArray(valueAtPath)) {
const deletedFormData = valueAtPath.splice(+lastKey, 1);
disposeForm(form, deletedFormData);
}
else {
disposeForm(form, valueAtPath[lastKey]);
delete valueAtPath[lastKey];
}
}
}
}
};
}
/**
* Configure the validation behavior of `useValidation`.
*
* @param configuration - The form validation configuration
*/
function createValidation(configuration) {
return {
install() {
var _a;
for (const [key, validationBehavior] of Object.entries((_a = configuration.validationBehavior) !== null && _a !== void 0 ? _a : {})) {
VALIDATION_CONFIG.validationBehavior.set(key, validationBehavior);
}
if (VALIDATION_CONFIG.validationBehavior.has(configuration.defaultValidationBehavior)) {
VALIDATION_CONFIG.defaultValidationBehavior =
configuration.defaultValidationBehavior;
}
else {
console.warn(`[useValidation] Default validation behavior '${configuration.defaultValidationBehavior}' is not valid. Valid values are`, VALIDATION_CONFIG.validationBehavior.keys());
}
}
};
}
exports.ValidationError = ValidationError;
exports.createValidation = createValidation;
exports.useValidation = useValidation;