UNPKG

validierung

Version:

Vue Composition Function for Form Validation

2 lines (1 loc) 11.7 kB
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var o=require("vue-demi");const j=s=>s!=null,k=s=>v(s)&&!Array.isArray(s),m=s=>Array.isArray(s),v=s=>typeof s=="object"&&s!==null&&!(s instanceof File);function O(s,e){for(const[t,i]of Object.entries(s))v(i)?(e[t]=m(i)?[]:{},O(i,e[t])):e[t]=i}function R(s){if(!v(s))return s;const e=m(s)?[]:{};return O(s,e),e}function $(s,e){let t=e[s[0]];for(let i=0;i<s.length;i++){const l=s[i];if(t==null)return;i>0&&(t=t[l])}return t}function H(s,e,t){if(e.length!==0){for(let i=0;i<e.length-1;i++){const l=e[i],a=e[i+1];s[l]===void 0&&(typeof a=="symbol"||Number.isNaN(+a)?s[l]={}:s[l]=[]),s=s[l]}o.isVue3?s[e[e.length-1]]=t:o.set(s,e[e.length-1],t)}}let _=1;function C(){return _++}function I(s){if(v(s))for(const e of Object.values(s))I(e);if(m(s))for(let e=0;e<s.length;++e)k(s[e])&&!o.isRef(s[e])&&o.reactive(s[e])}function D(s){return o.isVue2&&v(s)&&I(s),o.reactive(s)}function W(s,{wait:e}){let t=null;function i(){clearTimeout(t),t=null}function l(...a){const r=()=>{t=null,s.apply(this,a)};clearTimeout(t),t=setTimeout(r,e)}return l.cancel=i,l}class K{constructor(e){this.next=null,this.prev=null,this.value=e}}class q{constructor(){this.first=null,this.last=null,this.count=0}addFirst(e){const t=new K(e);return this.count===0?(this.first=t,this.last=t):(t.next=this.first,this.first.prev=t,this.first=t),this.count++,t}addLast(e){const t=new K(e);return this.count===0?(this.first=t,this.last=t):(t.prev=this.last,this.last.next=t,this.last=t),this.count++,t}remove(e){this.count!==0&&(e===this.first?this.removeFirst():e===this.last?this.removeLast():(e.prev.next=e.next,e.next.prev=e.prev,e.next=null,e.prev=null,this.count--))}removeFirst(){this.count!==0&&(this.count===1?(this.first=null,this.last=null,this.count--):(this.first=this.first.next,this.first.prev.next=null,this.first.prev=null,this.count--))}removeLast(){this.count!==0&&(this.count===1?(this.first=null,this.last=null,this.count--):(this.last=this.last.prev,this.last.next.prev=null,this.last.next=null,this.count--))}*[Symbol.iterator](){for(let e=this.first;e!==null;e=e.next)yield e}}class z{constructor(){this.isRacing=!1,this.assign()}cancelResolve(e){this.isRacing&&(this.isRacing=!1,this.resolve(e),this.assign())}cancelReject(e){this.isRacing&&(this.isRacing=!1,this.reject(e),this.assign())}race(...e){return this.isRacing=!0,Promise.race([this.promise,...e])}assign(){this.promise=new Promise((e,t)=>{this.resolve=e,this.reject=t})}}class x extends Error{constructor(){super("One or more validation errors occurred")}}const G=s=>typeof s=="function",P=s=>G(s)?[s,void 0]:[s.rule,s.key];class J{constructor(e,t,i,l,a){this.touched=o.ref(!1),this.dirty=o.ref(!1),this.rulesValidating=o.ref(0),this.validating=o.computed(()=>this.rulesValidating.value>0),this.errors=o.computed(()=>this.rawErrors.value.filter(j)),this.hasError=o.computed(()=>this.hasErrors.value.some(r=>r)),this.simpleValidators=[],this.keyedValidators={},this.form=e,this.uid=t,this.name=i,this.modelValue=o.ref(l),this.rawErrors=o.ref(a.map(()=>null)),this.hasErrors=o.ref(a.map(()=>!1)),this.initialModelValue=R(this.modelValue.value),this.ruleInfos=a.map((r,u)=>{const[n,d]=P(r.rule),f=(V,F,b=this.modelValue,M=!1)=>{if(n&&(M||this.shouldValidate(u,V,F)))return this.validate(u,b)};let y=f,p,c=0,h;r.debounce&&(p=W(V=>{h(this.validate(u,V)),this.rulesValidating.value-=c,this.form.rulesValidating.value-=c,c=0},{wait:r.debounce}),y=(V,F,b=this.modelValue,M=!1)=>{if(n&&(M||this.shouldValidate(u,V,F)))return c++,this.rulesValidating.value++,this.form.rulesValidating.value++,new Promise(T=>{h==null||h(),h=T,p(b)})});const w={ruleNumber:u,validator:y,validatorNotDebounced:f};if(d){const V=this.keyedValidators[d];V===void 0?this.keyedValidators[d]=n?[w]:[]:n&&V.push(w)}else this.simpleValidators.push(w);return{buffer:new q,rule:n,validator:y,validatorNotDebounced:f,vbf:r.vbf,cancelDebounce:()=>{p&&(c=0,p.cancel(),h==null||h())}}}),this.watchStopHandle=this.setupWatcher()}async validate(e,t){var i;const{rule:l,buffer:a}=this.ruleInfos[e];let r;const u=o.isRef(t)?l(t.value):l(...t.map(n=>n.value));if(((i=a.last)==null?void 0:i.value)&&(a.last.value=!1,this.rulesValidating.value--,this.form.rulesValidating.value--),typeof(u==null?void 0:u.then)=="function"){const n=a.addLast(!0);this.rulesValidating.value++,this.form.rulesValidating.value++;try{r=await u}catch(d){r=d}if(a.remove(n),n.value)this.rulesValidating.value--,this.form.rulesValidating.value--,this.setError(e,r);else if(typeof r=="string"||typeof r=="symbol")throw r}else r=u,this.setError(e,r)}reset(e=this.initialModelValue){this.watchStopHandle(),this.touched.value=!1,this.dirty.value=!1,this.modelValue.value=R(e),this.rulesValidating.value=0,this.form.rulesValidating.value=0;for(let t=0;t<this.ruleInfos.length;++t){o.isVue3?(this.rawErrors.value[t]=null,this.hasErrors.value[t]=!1):(o.set(this.rawErrors.value,t,null),o.set(this.hasErrors.value,t,!1)),this.ruleInfos[t].cancelDebounce();for(const i of this.ruleInfos[t].buffer)i.value=!1}this.watchStopHandle=this.setupWatcher()}dispose(){o.isVue3&&(this.errors.effect.stop(),this.validating.effect.stop(),this.hasError.effect.stop()),this.watchStopHandle()}shouldValidateForKey(e,t,i){for(let l=0;l<this.keyedValidators[e].length;++l)if(!this.shouldValidate(this.keyedValidators[e][l].ruleNumber,t,i))return!1;return!0}shouldValidate(e,t,i){return this.ruleInfos[e].vbf({hasError:this.rawErrors.value[e]!==null,touched:this.touched.value,dirty:this.dirty.value,force:t,submit:i,value:this.modelValue.value})}setError(e,t){const i=typeof t=="string";if(i||typeof t=="symbol")throw o.isVue3?(i&&(this.rawErrors.value[e]=t),this.hasErrors.value[e]=!0):(i&&o.set(this.rawErrors.value,e,t),o.set(this.hasErrors.value,e,!0)),t;o.isVue3?(this.rawErrors.value[e]=null,this.hasErrors.value[e]=!1):(o.set(this.rawErrors.value,e,null),o.set(this.hasErrors.value,e,!1))}setupWatcher(){return o.watch(this.modelValue,()=>{this.dirty.value=!0,this.form.validate(this.uid)},{deep:!0})}}class Q{constructor(){this.simpleMap=new Map,this.keyedMap=new Map,this.reactiveFieldMap=o.shallowReactive(new Map),this.rulesValidating=o.ref(0),this.submitting=o.ref(!1),this.validating=o.computed(()=>this.rulesValidating.value>0),this.hasError=o.computed(()=>this.errors.value.length>0),this.errors=o.computed(()=>{const e=[];for(const t of this.reactiveFieldMap.values())e.push(...t.errors.value);return e})}registerField(e,t,i,l){const a=new J(this,e,t,i,l),r={rollbacks:[],field:a},u=new Set;return l.forEach(n=>{const d=P(n.rule)[1];if(d){let f=this.keyedMap.get(d);f===void 0?this.keyedMap.set(d,{fields:[a],modelValues:[a.modelValue]}):u.has(d)||(f.fields.push(a),f.modelValues.push(a.modelValue)),f=this.keyedMap.get(d),u.add(d);const y=()=>{let p=-1,c=-1;for(let h=0;h<f.fields.length;++h)f.fields[h]===a&&(p=h),f.modelValues[h]===a.modelValue&&(c=h);p>=0&&f.fields.splice(p,1),c>=0&&f.modelValues.splice(c,1),f.fields.length===0&&this.keyedMap.delete(d)};r.rollbacks.push(y)}}),this.simpleMap.set(e,r),this.reactiveFieldMap.set(e,a),a}validate(e,t=!1){const{field:i}=this.simpleMap.get(e);return Promise.allSettled([...i.simpleValidators.map(({validator:l})=>l(t,!1)),...this.collectValidatorResultsForKeys(i,t,!1)])}async validateAll(e){const t=await Promise.allSettled(this.collectValidatorResultsForNames(e));for(const i of t)if(i.status==="rejected")throw new x}dispose(e){const t=this.simpleMap.get(e);t&&(t.field.dispose(),t.rollbacks.forEach(i=>i())),this.simpleMap.delete(e),this.reactiveFieldMap.delete(e)}resetFields(){for(const{field:e}of this.simpleMap.values())e.reset()}getField(e){const t=this.simpleMap.get(e);if(t)return t.field}*collectValidatorResultsForKeys(e,t,i,l=Object.keys(e.keyedValidators)){for(let a=0;a<l.length;++a){const{fields:r,modelValues:u}=this.keyedMap.get(l[a]);if(this.isEveryOtherFieldTouched(e,r)&&e.shouldValidateForKey(l[a],t,i))for(let n=0;n<r.length;++n){const d=r[n].keyedValidators[l[a]];for(let f=0;f<d.length;++f)yield i?d[f].validatorNotDebounced(t,i,u,r[n]===e):d[f].validator(t,i,u,r[n]===e)}}}*collectValidatorResultsForNames(e){if(e===void 0){for(const{field:t}of this.simpleMap.values()){t.touched.value=!0;for(let i=0;i<t.simpleValidators.length;++i)yield t.simpleValidators[i].validatorNotDebounced(!1,!0)}for(const[t,{fields:i,modelValues:l}]of this.keyedMap.entries())for(let a=0;a<i.length;++a){const r=i[a].keyedValidators[t];for(let u=0;u<r.length;++u)yield r[u].validatorNotDebounced(!1,!0,l)}}else if(e.length>0){const t=new Set(e),i=new Set;for(const{field:l}of this.simpleMap.values())t.has(l.name)&&(l.touched.value=!0);for(const{field:l}of this.simpleMap.values())if(t.has(l.name)){for(let a=0;a<l.simpleValidators.length;++a)yield l.simpleValidators[a].validatorNotDebounced(!1,!0);for(const a of Object.keys(l.keyedValidators))i.has(a)||(i.add(a),yield*this.collectValidatorResultsForKeys(l,!1,!0,[a]))}}}isEveryOtherFieldTouched(e,t){for(let i=0;i<t.length;++i)if(e!==t[i]&&!t[i].touched.value)return!1;return!0}}const U=s=>k(s)?"$value"in s:!1,S=s=>k(s)?"$uid"in s&&"$value"in s:!1;function E(s,e){for(const t of Object.values(e)){if(S(t)){s.dispose(t.$uid);continue}v(t)&&E(s,t)}}function B(s,e,t,i){let l=0;for(const[a,r]of Object.entries(s)){const u=m(s)?+a-l:a,n=S(r),d=n?R(r.$value):o.unref(r);if(i({key:a,value:d,path:t}))e[u]=d;else{++l;continue}n||v(r)&&(e[u]=m(r)?[]:{},B(r,e[u],[...t,a],i))}}function X(s,e=()=>!0){const t=m(s)?[]:{};return B(s,t,[],e),t}function L(s,e,t){Object.entries(e).forEach(([i,l])=>{const a=t[i];if(S(a)){s.getField(a.$uid).reset(l);return}v(l)&&L(s,l,t[i])})}class Y{constructor(){this.defaultValidationBehavior=null,this.vbfMap=new Map}getDefaultVbf(){return this.defaultValidationBehavior===null?()=>!0:this.vbfMap.get(this.defaultValidationBehavior)}}const g=new Y;function Z(s){const e=g.getDefaultVbf();return s.map(t=>{if(typeof t=="function")return{vbf:e,rule:t};if(Array.isArray(t)){const[i,l,a]=t;if(typeof l=="number")return{vbf:e,rule:i,debounce:l};if(typeof i=="function")return{vbf:i,rule:l,debounce:a};const r=g.vbfMap.get(i);if(r!==void 0)return{vbf:r,rule:l,debounce:a}}else return{vbf:e,rule:t}})}function N(s,e,t){const{$value:i,$rules:l,...a}=t,r=l?Z(l):[],u=C(),n=s.registerField(u,e,i,r);return{...a,$uid:u,$value:n.modelValue,$errors:n.errors,$hasError:n.hasError,$validating:n.validating,$dirty:n.dirty,$touched:n.touched,async $validate({setTouched:d,force:f}={}){d!=null||(d=!0),f!=null||(f=!0),d&&(n.touched.value=!0),await s.validate(u,f)}}}function A(s,e){for(const[t,i]of Object.entries(e)){if(U(i)){const l=N(s,t,i);e[t]=l;continue}v(i)&&A(s,i)}}function ee(s){const e=new Q,t=new z;A(e,s);const i=D(s);return{form:i,submitting:e.submitting,validating:e.validating,hasError:e.hasError,errors:e.errors,async validateFields({names:l,predicate:a}={}){e.submitting.value=!0;const r=X(i,a);try{await t.race(e.validateAll(l))}finally{e.submitting.value=!1}return r},resetFields(l){t.cancelReject(new x),l===void 0?e.resetFields():L(e,l,i)},add(l,a){const r=l[l.length-1];if(r!==void 0){const u={[r]:a};A(e,u);let n=u[r];const d=$(l,i);o.isVue2&&(n=D(n)),Array.isArray(d)?d.push(n):H(i,l,n)}},remove(l){const a=l.pop();if(a!==void 0)if(l.length===0)E(e,i[a]),o.isVue3?delete i[a]:o.del(i,a);else{const r=$(l,i);if(Array.isArray(r)){const u=r.splice(+a,1);E(e,u)}else E(e,r[a]),o.isVue3?delete r[a]:o.del(r,a)}}}}function te(s){return{install(){var e;for(const[t,i]of Object.entries((e=s.validationBehavior)!=null?e:{}))g.vbfMap.set(t,i);g.vbfMap.has(s.defaultValidationBehavior)&&(g.defaultValidationBehavior=s.defaultValidationBehavior)}}}exports.ValidationError=x,exports.createValidation=te,exports.useValidation=ee;