123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774 |
- import { isReactive, isReadonly, computed, unref, ref, watch, isRef, reactive, nextTick, inject, provide, getCurrentInstance, onBeforeMount, onBeforeUnmount } from 'vue-demi';
- function ownKeys(object, enumerableOnly) {
- var keys = Object.keys(object);
- if (Object.getOwnPropertySymbols) {
- var symbols = Object.getOwnPropertySymbols(object);
- enumerableOnly && (symbols = symbols.filter(function (sym) {
- return Object.getOwnPropertyDescriptor(object, sym).enumerable;
- })), keys.push.apply(keys, symbols);
- }
- return keys;
- }
- function _objectSpread2(target) {
- for (var i = 1; i < arguments.length; i++) {
- var source = null != arguments[i] ? arguments[i] : {};
- i % 2 ? ownKeys(Object(source), !0).forEach(function (key) {
- _defineProperty(target, key, source[key]);
- }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) {
- Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
- });
- }
- return target;
- }
- function _defineProperty(obj, key, value) {
- if (key in obj) {
- Object.defineProperty(obj, key, {
- value: value,
- enumerable: true,
- configurable: true,
- writable: true
- });
- } else {
- obj[key] = value;
- }
- return obj;
- }
- function unwrapObj(obj) {
- let ignoreKeys = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
- return Object.keys(obj).reduce((o, k) => {
- if (ignoreKeys.includes(k)) return o;
- o[k] = unref(obj[k]);
- return o;
- }, {});
- }
- function isFunction(val) {
- return typeof val === 'function';
- }
- function isProxy(value) {
- return isReactive(value) || isReadonly(value);
- }
- function get(obj, stringPath, def) {
- let current = obj;
- const path = stringPath.split('.');
- for (let i = 0; i < path.length; i++) {
- if (!current[path[i]]) return def;
- current = current[path[i]];
- }
- return current;
- }
- function gatherBooleanGroupProperties(group, nestedResults, property) {
- return computed(() => {
- return group.some(path => {
- return get(nestedResults, path, {
- [property]: false
- })[property];
- });
- });
- }
- function gatherArrayGroupProperties(group, nestedResults, property) {
- return computed(() => {
- return group.reduce((all, path) => {
- const fetchedProperty = get(nestedResults, path, {
- [property]: false
- })[property] || [];
- return all.concat(fetchedProperty);
- }, []);
- });
- }
- function callRule(rule, value, siblingState, instance) {
- return rule.call(instance, unref(value), unref(siblingState), instance);
- }
- function normalizeValidatorResponse(result) {
- return result.$valid !== undefined ? !result.$valid : !result;
- }
- function createAsyncResult(rule, model, $pending, $dirty, _ref, $response, instance) {
- let {
- $lazy,
- $rewardEarly
- } = _ref;
- let watchTargets = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : [];
- let siblingState = arguments.length > 8 ? arguments[8] : undefined;
- let $lastInvalidState = arguments.length > 9 ? arguments[9] : undefined;
- let $lastCommittedOn = arguments.length > 10 ? arguments[10] : undefined;
- const $invalid = ref(!!$dirty.value);
- const $pendingCounter = ref(0);
- $pending.value = false;
- const $unwatch = watch([model, $dirty].concat(watchTargets, $lastCommittedOn), () => {
- if ($lazy && !$dirty.value || $rewardEarly && !$lastInvalidState.value && !$pending.value) {
- return;
- }
- let ruleResult;
- try {
- ruleResult = callRule(rule, model, siblingState, instance);
- } catch (err) {
- ruleResult = Promise.reject(err);
- }
- $pendingCounter.value++;
- $pending.value = !!$pendingCounter.value;
- $invalid.value = false;
- Promise.resolve(ruleResult).then(data => {
- $pendingCounter.value--;
- $pending.value = !!$pendingCounter.value;
- $response.value = data;
- $invalid.value = normalizeValidatorResponse(data);
- }).catch(error => {
- $pendingCounter.value--;
- $pending.value = !!$pendingCounter.value;
- $response.value = error;
- $invalid.value = true;
- });
- }, {
- immediate: true,
- deep: typeof model === 'object'
- });
- return {
- $invalid,
- $unwatch
- };
- }
- function createSyncResult(rule, model, $dirty, _ref2, $response, instance, siblingState, $lastInvalidState) {
- let {
- $lazy,
- $rewardEarly
- } = _ref2;
- const $unwatch = () => ({});
- const $invalid = computed(() => {
- if ($lazy && !$dirty.value || $rewardEarly && !$lastInvalidState.value) {
- return false;
- }
- let returnValue = true;
- try {
- const result = callRule(rule, model, siblingState, instance);
- $response.value = result;
- returnValue = normalizeValidatorResponse(result);
- } catch (err) {
- $response.value = err;
- }
- return returnValue;
- });
- return {
- $unwatch,
- $invalid
- };
- }
- function createValidatorResult(rule, model, $dirty, config, instance, validatorName, propertyKey, propertyPath, siblingState, $lastInvalidState, $lastCommittedOn) {
- const $pending = ref(false);
- const $params = rule.$params || {};
- const $response = ref(null);
- let $invalid;
- let $unwatch;
- if (rule.$async) {
- ({
- $invalid,
- $unwatch
- } = createAsyncResult(rule.$validator, model, $pending, $dirty, config, $response, instance, rule.$watchTargets, siblingState, $lastInvalidState, $lastCommittedOn));
- } else {
- ({
- $invalid,
- $unwatch
- } = createSyncResult(rule.$validator, model, $dirty, config, $response, instance, siblingState, $lastInvalidState));
- }
- const message = rule.$message;
- const $message = isFunction(message) ? computed(() => message(unwrapObj({
- $pending,
- $invalid,
- $params: unwrapObj($params),
- $model: model,
- $response,
- $validator: validatorName,
- $propertyPath: propertyPath,
- $property: propertyKey
- }))) : message || '';
- return {
- $message,
- $params,
- $pending,
- $invalid,
- $response,
- $unwatch
- };
- }
- function sortValidations() {
- let validationsRaw = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
- const validations = unref(validationsRaw);
- const validationKeys = Object.keys(validations);
- const rules = {};
- const nestedValidators = {};
- const config = {};
- let validationGroups = null;
- validationKeys.forEach(key => {
- const v = validations[key];
- switch (true) {
- case isFunction(v.$validator):
- rules[key] = v;
- break;
- case isFunction(v):
- rules[key] = {
- $validator: v
- };
- break;
- case key === '$validationGroups':
- validationGroups = v;
- break;
- case key.startsWith('$'):
- config[key] = v;
- break;
- default:
- nestedValidators[key] = v;
- }
- });
- return {
- rules,
- nestedValidators,
- config,
- validationGroups
- };
- }
- const ROOT_PATH = '__root';
- function createValidationResults(rules, model, key, resultsCache, path, config, instance, externalResults, siblingState) {
- const ruleKeys = Object.keys(rules);
- const cachedResult = resultsCache.get(path, rules);
- const $dirty = ref(false);
- const $lastInvalidState = ref(false);
- const $lastCommittedOn = ref(0);
- if (cachedResult) {
- if (!cachedResult.$partial) return cachedResult;
- cachedResult.$unwatch();
- $dirty.value = cachedResult.$dirty.value;
- }
- const result = {
- $dirty,
- $path: path,
- $touch: () => {
- if (!$dirty.value) $dirty.value = true;
- },
- $reset: () => {
- if ($dirty.value) $dirty.value = false;
- },
- $commit: () => {}
- };
- if (!ruleKeys.length) {
- cachedResult && resultsCache.set(path, rules, result);
- return result;
- }
- ruleKeys.forEach(ruleKey => {
- result[ruleKey] = createValidatorResult(rules[ruleKey], model, result.$dirty, config, instance, ruleKey, key, path, siblingState, $lastInvalidState, $lastCommittedOn);
- });
- result.$externalResults = computed(() => {
- if (!externalResults.value) return [];
- return [].concat(externalResults.value).map((stringError, index) => ({
- $propertyPath: path,
- $property: key,
- $validator: '$externalResults',
- $uid: `${path}-externalResult-${index}`,
- $message: stringError,
- $params: {},
- $response: null,
- $pending: false
- }));
- });
- result.$invalid = computed(() => {
- const r = ruleKeys.some(ruleKey => unref(result[ruleKey].$invalid));
- $lastInvalidState.value = r;
- return !!result.$externalResults.value.length || r;
- });
- result.$pending = computed(() => ruleKeys.some(ruleKey => unref(result[ruleKey].$pending)));
- result.$error = computed(() => result.$dirty.value ? result.$pending.value || result.$invalid.value : false);
- result.$silentErrors = computed(() => ruleKeys.filter(ruleKey => unref(result[ruleKey].$invalid)).map(ruleKey => {
- const res = result[ruleKey];
- return reactive({
- $propertyPath: path,
- $property: key,
- $validator: ruleKey,
- $uid: `${path}-${ruleKey}`,
- $message: res.$message,
- $params: res.$params,
- $response: res.$response,
- $pending: res.$pending
- });
- }).concat(result.$externalResults.value));
- result.$errors = computed(() => result.$dirty.value ? result.$silentErrors.value : []);
- result.$unwatch = () => ruleKeys.forEach(ruleKey => {
- result[ruleKey].$unwatch();
- });
- result.$commit = () => {
- $lastInvalidState.value = true;
- $lastCommittedOn.value = Date.now();
- };
- resultsCache.set(path, rules, result);
- return result;
- }
- function collectNestedValidationResults(validations, nestedState, path, resultsCache, config, instance, nestedExternalResults) {
- const nestedValidationKeys = Object.keys(validations);
- if (!nestedValidationKeys.length) return {};
- return nestedValidationKeys.reduce((results, nestedKey) => {
- results[nestedKey] = setValidations({
- validations: validations[nestedKey],
- state: nestedState,
- key: nestedKey,
- parentKey: path,
- resultsCache,
- globalConfig: config,
- instance,
- externalResults: nestedExternalResults
- });
- return results;
- }, {});
- }
- function createMetaFields(results, nestedResults, childResults) {
- const allResults = computed(() => [nestedResults, childResults].filter(res => res).reduce((allRes, res) => {
- return allRes.concat(Object.values(unref(res)));
- }, []));
- const $dirty = computed({
- get() {
- return results.$dirty.value || (allResults.value.length ? allResults.value.every(r => r.$dirty) : false);
- },
- set(v) {
- results.$dirty.value = v;
- }
- });
- const $silentErrors = computed(() => {
- const modelErrors = unref(results.$silentErrors) || [];
- const nestedErrors = allResults.value.filter(result => (unref(result).$silentErrors || []).length).reduce((errors, result) => {
- return errors.concat(...result.$silentErrors);
- }, []);
- return modelErrors.concat(nestedErrors);
- });
- const $errors = computed(() => {
- const modelErrors = unref(results.$errors) || [];
- const nestedErrors = allResults.value.filter(result => (unref(result).$errors || []).length).reduce((errors, result) => {
- return errors.concat(...result.$errors);
- }, []);
- return modelErrors.concat(nestedErrors);
- });
- const $invalid = computed(() => allResults.value.some(r => r.$invalid) || unref(results.$invalid) || false);
- const $pending = computed(() => allResults.value.some(r => unref(r.$pending)) || unref(results.$pending) || false);
- const $anyDirty = computed(() => allResults.value.some(r => r.$dirty) || allResults.value.some(r => r.$anyDirty) || $dirty.value);
- const $error = computed(() => $dirty.value ? $pending.value || $invalid.value : false);
- const $touch = () => {
- results.$touch();
- allResults.value.forEach(result => {
- result.$touch();
- });
- };
- const $commit = () => {
- results.$commit();
- allResults.value.forEach(result => {
- result.$commit();
- });
- };
- const $reset = () => {
- results.$reset();
- allResults.value.forEach(result => {
- result.$reset();
- });
- };
- if (allResults.value.length && allResults.value.every(nr => nr.$dirty)) $touch();
- return {
- $dirty,
- $errors,
- $invalid,
- $anyDirty,
- $error,
- $pending,
- $touch,
- $reset,
- $silentErrors,
- $commit
- };
- }
- function setValidations(_ref) {
- let {
- validations,
- state,
- key,
- parentKey,
- childResults,
- resultsCache,
- globalConfig = {},
- instance,
- externalResults
- } = _ref;
- const path = parentKey ? `${parentKey}.${key}` : key;
- const {
- rules,
- nestedValidators,
- config,
- validationGroups
- } = sortValidations(validations);
- const mergedConfig = _objectSpread2(_objectSpread2({}, globalConfig), config);
- const nestedState = key ? computed(() => {
- const s = unref(state);
- return s ? unref(s[key]) : undefined;
- }) : state;
- const cachedExternalResults = _objectSpread2({}, unref(externalResults) || {});
- const nestedExternalResults = computed(() => {
- const results = unref(externalResults);
- if (!key) return results;
- return results ? unref(results[key]) : undefined;
- });
- const results = createValidationResults(rules, nestedState, key, resultsCache, path, mergedConfig, instance, nestedExternalResults, state);
- const nestedResults = collectNestedValidationResults(nestedValidators, nestedState, path, resultsCache, mergedConfig, instance, nestedExternalResults);
- const $validationGroups = {};
- if (validationGroups) {
- Object.entries(validationGroups).forEach(_ref2 => {
- let [key, group] = _ref2;
- $validationGroups[key] = {
- $invalid: gatherBooleanGroupProperties(group, nestedResults, '$invalid'),
- $error: gatherBooleanGroupProperties(group, nestedResults, '$error'),
- $pending: gatherBooleanGroupProperties(group, nestedResults, '$pending'),
- $errors: gatherArrayGroupProperties(group, nestedResults, '$errors'),
- $silentErrors: gatherArrayGroupProperties(group, nestedResults, '$silentErrors')
- };
- });
- }
- const {
- $dirty,
- $errors,
- $invalid,
- $anyDirty,
- $error,
- $pending,
- $touch,
- $reset,
- $silentErrors,
- $commit
- } = createMetaFields(results, nestedResults, childResults);
- const $model = key ? computed({
- get: () => unref(nestedState),
- set: val => {
- $dirty.value = true;
- const s = unref(state);
- const external = unref(externalResults);
- if (external) {
- external[key] = cachedExternalResults[key];
- }
- if (isRef(s[key])) {
- s[key].value = val;
- } else {
- s[key] = val;
- }
- }
- }) : null;
- if (key && mergedConfig.$autoDirty) {
- watch(nestedState, () => {
- if (!$dirty.value) $touch();
- const external = unref(externalResults);
- if (external) {
- external[key] = cachedExternalResults[key];
- }
- }, {
- flush: 'sync'
- });
- }
- async function $validate() {
- $touch();
- if (mergedConfig.$rewardEarly) {
- $commit();
- await nextTick();
- }
- await nextTick();
- return new Promise(resolve => {
- if (!$pending.value) return resolve(!$invalid.value);
- const unwatch = watch($pending, () => {
- resolve(!$invalid.value);
- unwatch();
- });
- });
- }
- function $getResultsForChild(key) {
- return (childResults.value || {})[key];
- }
- function $clearExternalResults() {
- if (isRef(externalResults)) {
- externalResults.value = cachedExternalResults;
- } else {
- if (Object.keys(cachedExternalResults).length === 0) {
- Object.keys(externalResults).forEach(k => {
- delete externalResults[k];
- });
- } else {
- Object.assign(externalResults, cachedExternalResults);
- }
- }
- }
- return reactive(_objectSpread2(_objectSpread2(_objectSpread2({}, results), {}, {
- $model,
- $dirty,
- $error,
- $errors,
- $invalid,
- $anyDirty,
- $pending,
- $touch,
- $reset,
- $path: path || ROOT_PATH,
- $silentErrors,
- $validate,
- $commit
- }, childResults && {
- $getResultsForChild,
- $clearExternalResults,
- $validationGroups
- }), nestedResults));
- }
- class ResultsStorage {
- constructor() {
- this.storage = new Map();
- }
- set(path, rules, result) {
- this.storage.set(path, {
- rules,
- result
- });
- }
- checkRulesValidity(path, rules, storedRules) {
- const storedRulesKeys = Object.keys(storedRules);
- const newRulesKeys = Object.keys(rules);
- if (newRulesKeys.length !== storedRulesKeys.length) return false;
- const hasAllValidators = newRulesKeys.every(ruleKey => storedRulesKeys.includes(ruleKey));
- if (!hasAllValidators) return false;
- return newRulesKeys.every(ruleKey => {
- if (!rules[ruleKey].$params) return true;
- return Object.keys(rules[ruleKey].$params).every(paramKey => {
- return unref(storedRules[ruleKey].$params[paramKey]) === unref(rules[ruleKey].$params[paramKey]);
- });
- });
- }
- get(path, rules) {
- const storedRuleResultPair = this.storage.get(path);
- if (!storedRuleResultPair) return undefined;
- const {
- rules: storedRules,
- result
- } = storedRuleResultPair;
- const isValidCache = this.checkRulesValidity(path, rules, storedRules);
- const $unwatch = result.$unwatch ? result.$unwatch : () => ({});
- if (!isValidCache) return {
- $dirty: result.$dirty,
- $partial: true,
- $unwatch
- };
- return result;
- }
- }
- const CollectFlag = {
- COLLECT_ALL: true,
- COLLECT_NONE: false
- };
- const VuelidateInjectChildResults = Symbol('vuelidate#injectChildResults');
- const VuelidateRemoveChildResults = Symbol('vuelidate#removeChildResults');
- function nestedValidations(_ref) {
- let {
- $scope,
- instance
- } = _ref;
- const childResultsRaw = {};
- const childResultsKeys = ref([]);
- const childResults = computed(() => childResultsKeys.value.reduce((results, key) => {
- results[key] = unref(childResultsRaw[key]);
- return results;
- }, {}));
- function injectChildResultsIntoParent(results, _ref2) {
- let {
- $registerAs: key,
- $scope: childScope,
- $stopPropagation
- } = _ref2;
- if ($stopPropagation || $scope === CollectFlag.COLLECT_NONE || childScope === CollectFlag.COLLECT_NONE || $scope !== CollectFlag.COLLECT_ALL && $scope !== childScope) return;
- childResultsRaw[key] = results;
- childResultsKeys.value.push(key);
- }
- instance.__vuelidateInjectInstances = [].concat(instance.__vuelidateInjectInstances || [], injectChildResultsIntoParent);
- function removeChildResultsFromParent(key) {
- childResultsKeys.value = childResultsKeys.value.filter(childKey => childKey !== key);
- delete childResultsRaw[key];
- }
- instance.__vuelidateRemoveInstances = [].concat(instance.__vuelidateRemoveInstances || [], removeChildResultsFromParent);
- const sendValidationResultsToParent = inject(VuelidateInjectChildResults, []);
- provide(VuelidateInjectChildResults, instance.__vuelidateInjectInstances);
- const removeValidationResultsFromParent = inject(VuelidateRemoveChildResults, []);
- provide(VuelidateRemoveChildResults, instance.__vuelidateRemoveInstances);
- return {
- childResults,
- sendValidationResultsToParent,
- removeValidationResultsFromParent
- };
- }
- function ComputedProxyFactory(target) {
- return new Proxy(target, {
- get(target, prop) {
- return typeof target[prop] === 'object' ? ComputedProxyFactory(target[prop]) : computed(() => target[prop]);
- }
- });
- }
- let uid = 0;
- function useVuelidate(validations, state) {
- var _getCurrentInstance;
- let globalConfig = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
- if (arguments.length === 1) {
- globalConfig = validations;
- validations = undefined;
- state = undefined;
- }
- let {
- $registerAs,
- $scope = CollectFlag.COLLECT_ALL,
- $stopPropagation,
- $externalResults,
- currentVueInstance
- } = globalConfig;
- const instance = currentVueInstance || ((_getCurrentInstance = getCurrentInstance()) === null || _getCurrentInstance === void 0 ? void 0 : _getCurrentInstance.proxy);
- const componentOptions = instance ? instance.$options : {};
- if (!$registerAs) {
- uid += 1;
- $registerAs = `_vuelidate_${uid}`;
- }
- const validationResults = ref({});
- const resultsCache = new ResultsStorage();
- const {
- childResults,
- sendValidationResultsToParent,
- removeValidationResultsFromParent
- } = instance ? nestedValidations({
- $scope,
- instance
- }) : {
- childResults: ref({})
- };
- if (!validations && componentOptions.validations) {
- const rules = componentOptions.validations;
- state = ref({});
- onBeforeMount(() => {
- state.value = instance;
- watch(() => isFunction(rules) ? rules.call(state.value, new ComputedProxyFactory(state.value)) : rules, validations => {
- validationResults.value = setValidations({
- validations,
- state,
- childResults,
- resultsCache,
- globalConfig,
- instance,
- externalResults: $externalResults || instance.vuelidateExternalResults
- });
- }, {
- immediate: true
- });
- });
- globalConfig = componentOptions.validationsConfig || globalConfig;
- } else {
- const validationsWatchTarget = isRef(validations) || isProxy(validations) ? validations : reactive(validations || {});
- watch(validationsWatchTarget, newValidationRules => {
- validationResults.value = setValidations({
- validations: newValidationRules,
- state,
- childResults,
- resultsCache,
- globalConfig,
- instance: instance !== null && instance !== void 0 ? instance : {},
- externalResults: $externalResults
- });
- }, {
- immediate: true
- });
- }
- if (instance) {
- sendValidationResultsToParent.forEach(f => f(validationResults, {
- $registerAs,
- $scope,
- $stopPropagation
- }));
- onBeforeUnmount(() => removeValidationResultsFromParent.forEach(f => f($registerAs)));
- }
- return computed(() => {
- return _objectSpread2(_objectSpread2({}, unref(validationResults.value)), childResults.value);
- });
- }
- export { CollectFlag, useVuelidate as default, useVuelidate };
|