UNPKG

dilswer

Version:

Blazingly fast data validation library with TypeScript integration.

926 lines (923 loc) 31.8 kB
var __defProp = Object.defineProperty; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); // src/validation-algorithms/compile-fast-validator.ts import { approximateComplexity } from "./approximate-complexity.mjs"; var KNOWN_GLOBAL_CLASSES = /* @__PURE__ */ new Map([ [Map, "Map"], [Set, "Set"], [RegExp, "RegExp"], [Date, "Date"], [Error, "Error"], [EvalError, "EvalError"], [RangeError, "RangeError"], [ReferenceError, "ReferenceError"], [SyntaxError, "SyntaxError"], [TypeError, "TypeError"], [URIError, "URIError"], [AggregateError, "AggregateError"], [Array, "Array"], [Object, "Object"], [WeakMap, "WeakMap"], [WeakSet, "WeakSet"], [Function, "Function"], [String, "String"], [Number, "Number"], [Boolean, "Boolean"], [Int8Array, "Int8Array"], [Uint8Array, "Uint8Array"], [Uint8ClampedArray, "Uint8ClampedArray"], [Int16Array, "Int16Array"], [Uint16Array, "Uint16Array"], [Int32Array, "Int32Array"], [Uint32Array, "Uint32Array"], [Float32Array, "Float32Array"], [Float64Array, "Float64Array"], [BigInt64Array, "BigInt64Array"], [BigUint64Array, "BigUint64Array"], [ArrayBuffer, "ArrayBuffer"], [DataView, "DataView"], [Promise, "Promise"] ]); if (typeof SharedArrayBuffer !== "undefined") { KNOWN_GLOBAL_CLASSES.set(SharedArrayBuffer, "SharedArrayBuffer"); } var propertyAccessor = (propertyName) => { if (propertyName.match(/^[a-zA-Z_$][a-zA-Z_$0-9]*$/)) { return `.${propertyName}`; } return `[${JSON.stringify(propertyName)}]`; }; var ConditionBuilder = class { constructor(type) { __publicField(this, "type", type); __publicField(this, "conditions", []); } add(condition) { this.conditions.push(condition); return this; } build() { if (this.conditions.length === 0) { return "true"; } if (this.conditions.length === 1) { const c = this.conditions[0]; return typeof c === "string" ? c : c.build(); } const separator = this.type === "||" ? " || " : " && "; return "(" + this.conditions.map((c) => typeof c === "string" ? c : c.build()).join(separator) + ")"; } }; var $dependency = (depName) => `_$getDependency(${JSON.stringify(depName)})`; var $condition = (type) => new ConditionBuilder(type); var $type = (varname, type) => { return `typeof ${varname} === "${type}"`; }; var _serialize = (value) => { return JSON.stringify(value); }; var $defineFn = (fnName, argName, body) => { return { declaration: `const ${fnName} = (${argName}) => ${body};`, $invokeWith(varname) { return `${fnName}(${varname})`; } }; }; var $defineRegexp = (name, regexp) => { return { declaration: `const ${name} = new RegExp(${JSON.stringify( regexp.source )}, ${JSON.stringify(regexp.flags)});`, $test(varname) { return `${name}.test(${varname})`; } }; }; var $lte = (name, value) => { return `${name} <= ${value}`; }; var $gte = (name, value) => { return `${name} >= ${value}`; }; var $equal = (varname, value) => { return `${varname} === ${_serialize(value)}`; }; var $notEqual = (varname, value) => { return `${varname} !== ${_serialize(value)}`; }; var $isArray = (varname) => { return `Array.isArray(${varname})`; }; var $isObject = (varname) => { return $condition("&&").add($type(varname, "object")).add($notEqual(varname, null)); }; var $isSet = (varname) => { return $equal(`${varname}[Symbol.toStringTag]`, "Set"); }; var $isInteger = (varname) => { return `Number.isInteger(${varname})`; }; var $notNaN = (varname) => { return `${varname} === ${varname}`; }; var $has = (varname, key) => { return `${_serialize(key)} in ${varname}`; }; var $ternary = (condition) => { return { then(thenValue) { return { else(elseValue) { return `(${typeof condition === "string" ? condition : condition.build()} ? ${thenValue} : ${elseValue})`; } }; } }; }; var $length = (varname, is, than) => { switch (is) { case "==": return `${varname}.length === ${than}`; case ">": return `${varname}.length > ${than}`; case "<": return `${varname}.length < ${than}`; case ">=": return `${varname}.length >= ${than}`; case "<=": return `${varname}.length <= ${than}`; } }; var $every = (generator, varname, predicate, startIndex) => { let inline = generator.shouldInline(); if (inline) { const iVar = generator.getUniqueVarName(); return `(() => { for (let ${iVar} = ${startIndex != null ? startIndex : 0}; ${iVar} < ${varname}.length; ${iVar}++) { if (!(${predicate(`${varname}[${iVar}]`, iVar)})) { return false; } }return true; })()`; } generator.includes.every = true; const elemName = generator.getUniqueVarName(); const indexName = generator.getUniqueVarName(); if (startIndex != null) { return `_$every(${varname}, (${elemName}, ${indexName}) => ${predicate(elemName, indexName)}, ${startIndex})`; } return `_$every(${varname}, (${elemName}, ${indexName}) => ${predicate(elemName, indexName)})`; }; var $everySome = (generator, varname, everyPredicate, somePredicate, startIdx) => { let inline = generator.shouldInline(); if (inline) { const satisfied = generator.getUniqueVarName("someSatisfied"); const iVar = generator.getUniqueVarName(); return `(() => { let ${satisfied} = false; for (let ${iVar} = ${startIdx != null ? startIdx : 0}; ${iVar} < ${varname}.length; ${iVar}++) { if (!(${everyPredicate(`${varname}[${iVar}]`, iVar)})) { return false; } if(!${satisfied}) { ${satisfied} = ${somePredicate(`${varname}[${iVar}]`, iVar)}; } } return ${satisfied}; })()`; } generator.includes.everySome = true; const elemName1 = generator.getUniqueVarName(); const indexName1 = generator.getUniqueVarName(); const elemName2 = generator.getUniqueVarName(); const indexName2 = generator.getUniqueVarName(); if (startIdx != null) { return `_$everySome(${varname}, (${elemName1}, ${indexName1}) => ${everyPredicate(elemName1, indexName1)}, (${elemName2}, ${indexName2}) => ${somePredicate(elemName2, indexName2)}, ${startIdx})`; } return `_$everySome(${varname}, (${elemName1}, ${indexName1}) => ${everyPredicate(elemName1, indexName1)}, (${elemName2}, ${indexName2}) => ${somePredicate(elemName2, indexName2)})`; }; var $everyObjectValue = (generator, varname, predicate) => { let inline = generator.shouldInline(); if (inline) { const iVar = generator.getUniqueVarName(); return `(() => { for (let ${iVar} in ${varname}) { if (!(${predicate(`${varname}[${iVar}]`)})) { return false; } }return true; })()`; } generator.includes.everyObjectValue = true; const elemName = generator.getUniqueVarName(); return `_$everyObjectValue(${varname}, (${elemName}) => ${predicate(elemName)})`; }; var $everyInSet = (generator, varname, predicate) => { let inline = generator.shouldInline(); if (inline) { const item = generator.getUniqueVarName(); return `(() => { for (let ${item} of ${varname}) { if (!(${predicate(item)})) { return false; } }return true; })()`; } generator.includes.everyInSet = true; const elemName = generator.getUniqueVarName(); return `_$everyInSet(${varname}, (${elemName}) => ${predicate(elemName)})`; }; var $charCode = (varname, is) => { if (Array.isArray(is)) { return `${varname}.charCodeAt(0) >= ${is[0]} && ${varname}.charCodeAt(0) <= ${is[1]}`; } return `${varname}.charCodeAt(0) === ${is}`; }; var $charCount = (generator, varname, char, is, expected) => { let inline = generator.shouldInline(); if (inline) { const counter = generator.getUniqueVarName("count"); const iVar = generator.getUniqueVarName(); return `(() => { let ${counter} = 0; for (let ${iVar} = 0; ${iVar} < ${varname}.length; ${iVar}++) { if (${varname}[${iVar}] === ${JSON.stringify(char)}) { ${counter}++; } }return ${counter}; })() ${is} ${expected}`; } generator.includes.charCount = true; return `_$countChar(${varname}, ${JSON.stringify(char)}) ${is} ${expected}`; }; var $instanceof = (generator, varname, constructor) => { if (KNOWN_GLOBAL_CLASSES.has(constructor)) { return `(${varname} instanceof ${KNOWN_GLOBAL_CLASSES.get(constructor)})`; } const name = generator.getUniqueVarName(); generator.addDependency(name, constructor); return `(${varname} instanceof ${$dependency(name)})`; }; var ValidateGenerator = class { constructor(t, get$validate) { __publicField(this, "t", t); __publicField(this, "get$validate", get$validate); __publicField(this, "_memo_complexity", null); } approxComplexity() { if (this._memo_complexity != null) { return this._memo_complexity; } return this._memo_complexity = approximateComplexity(this.t); } originalSchema() { return this.t; } isAlwaysTrue() { return false; } $buildValidate(varname) { const validate = this.get$validate(varname, this); if (typeof validate === "string") { return validate; } return validate.build(); } }; var TruthyGenerator = class { constructor(t) { __publicField(this, "t", t); } approxComplexity() { return 0; } originalSchema() { return this.t; } isAlwaysTrue() { return true; } $buildValidate() { return "true"; } }; var DataTypeValidatorVisitor = class { constructor(opts) { __publicField(this, "opts", opts); __publicField(this, "depth", 0); __publicField(this, "includes", { every: false, everySome: false, everyObjectValue: false, everyInSet: false, charCount: false, recursive: false, custom: false, instanceof: false }); __publicField(this, "circValidationFnNames", /* @__PURE__ */ new Map()); __publicField(this, "_counter1", 0); __publicField(this, "_counter2", 0); __publicField(this, "_counter3", 0); __publicField(this, "knownTypes", /* @__PURE__ */ new Map()); __publicField(this, "outerDeclarations", []); __publicField(this, "innerDeclarations", []); __publicField(this, "dependencies", []); } shouldInline() { if (this.opts && this.opts.inlineHelpers != null) { return this.opts.inlineHelpers; } return this.depth > 5 && this.depth <= 12; } canSkipPropertyCheck(t) { if (t.kind === "simple") { switch (t.simpleType) { case "null": case "unknown": case "undefined": return false; } return true; } return t.kind === "dictionary" || t.kind === "record"; } sortChildren(children) { return children.slice().sort( (a, b) => { const ac = "_isRecordOfVisitChild" in a ? a.child : a; const bc = "_isRecordOfVisitChild" in b ? b.child : b; const aSchema = ac.originalSchema(); const bSchema = bc.originalSchema(); const aKind = aSchema.kind; const bKind = bSchema.kind; const aCustom = aKind === "custom"; const bCustom = bKind === "custom"; if (aCustom !== bCustom && (aCustom || bCustom)) { return aCustom ? 1 : -1; } const aMaybeDiscriminator = aKind === "literal" || aKind === "enumMember" || aKind === "stringMatching" || aKind === "union" && aSchema.oneOf.every( (t) => t.kind === "literal" || t.kind === "enumMember" || t.kind === "stringMatching" ); const bMaybeDiscriminator = bKind === "literal" || bKind === "enumMember" || bKind === "stringMatching" || bKind === "union" && bSchema.oneOf.every( (t) => t.kind === "literal" || t.kind === "enumMember" || t.kind === "stringMatching" ); if (aMaybeDiscriminator !== bMaybeDiscriminator && (aMaybeDiscriminator || bMaybeDiscriminator)) { return aMaybeDiscriminator ? -1 : 1; } const aCplx = ac.approxComplexity(); const bCplx = bc.approxComplexity(); return aCplx - bCplx; } ); } addDeclaration(type, inlined) { if (type === "inner") { this.innerDeclarations.push(inlined); } else { this.outerDeclarations.push(inlined); } return this; } addDependency(name, value) { this.dependencies.push([name, value]); return this; } getUniqueStringForType(type) { if (this.knownTypes.has(type)) { return this.knownTypes.get(type); } const name = `_$t${++this._counter3}`; this.knownTypes.set(type, name); return name; } getUniqueVarName(name) { if (name) { return `_$a${++this._counter1}_${name}`; } return `_$a${++this._counter1}`; } getUniqueFnName() { return `_$v${++this._counter2}`; } visitPrimitive(type) { switch (type.simpleType) { case "boolean": return new ValidateGenerator( type, (varname) => $type(varname, "boolean") ); case "integer": return new ValidateGenerator(type, (varname) => { const cond = $condition("&&").add($type(varname, "number")).add($isInteger(varname)); if (type.options.max != null) { cond.add($lte(varname, type.options.max)); } if (type.options.min != null) { cond.add($gte(varname, type.options.min)); } return cond; }); case "null": return new ValidateGenerator(type, (varname) => $equal(varname, null)); case "number": return new ValidateGenerator(type, (varname) => { let cond = $condition("&&").add($type(varname, "number")).add($notNaN(varname)); if (type.options.max != null) { cond = cond.add($lte(varname, type.options.max)); } if (type.options.min != null) { cond = cond.add($gte(varname, type.options.min)); } return cond; }); case "string": return new ValidateGenerator(type, (varname) => { const cond = $condition("&&").add($type(varname, "string")); if (type.options.max != null) { cond.add($length(varname, "<=", type.options.max)); } if (type.options.min != null) { cond.add($length(varname, ">=", type.options.min)); } return cond; }); case "stringinteger": if (type.options.negative === false && type.options.positive === false) { return new ValidateGenerator(type, (varname) => $condition("&&").add($type(varname, "string")).add($length(varname, ">", 0)).add( $ternary($charCode(varname, 45 /* Minus */)).then($every( this, varname, (char) => $charCode(char, 48 /* Zero */), 1 // start from the second char )).else($every( this, varname, (char) => $charCode(char, 48 /* Zero */) )) )); } if (type.options.negative === false) { return new ValidateGenerator(type, (varname) => $condition("&&").add($type(varname, "string")).add($length(varname, ">", 0)).add( $everySome( this, varname, (char) => $charCode(char, [48 /* Zero */, 57 /* Nine */]), // each char must be a digit (char) => $charCode(char, [49 /* One */, 57 /* Nine */]) // at least one char must be a non-zero digit ) )); } if (type.options.positive === false) { return new ValidateGenerator(type, (varname) => $condition("&&").add($type(varname, "string")).add($length(varname, ">", 0)).add($charCode(varname, 45 /* Minus */)).add( $everySome( this, varname, (char) => $charCode(char, [48 /* Zero */, 57 /* Nine */]), // each char must be a digit (char) => $charCode(char, [49 /* One */, 57 /* Nine */]), // at least one char must be a non-zero digit 1 // start from the second char ) )); } return new ValidateGenerator(type, (varname) => $condition("&&").add($type(varname, "string")).add($length(varname, ">", 0)).add( $ternary($charCode(varname, 45 /* Minus */)).then($every( this, varname, (char) => $charCode(char, [48 /* Zero */, 57 /* Nine */]), 1 // start from the second char )).else($every( this, varname, (char) => $charCode(char, [48 /* Zero */, 57 /* Nine */]) )) )); case "stringnumeral": if (type.options.negative === false && type.options.positive === false) { return new ValidateGenerator(type, (varname) => $condition("&&").add($type(varname, "string")).add($length(varname, ">", 0)).add( $ternary($charCode(varname, 45 /* Minus */)).then( $every( this, varname, (char) => $condition("||").add($charCode(char, 48 /* Zero */)).add($charCode(char, 46 /* Dot */)).build(), 1 // start from the second char ) ).else( $every( this, varname, (char) => $condition("||").add($charCode(char, 48 /* Zero */)).add($charCode(char, 46 /* Dot */)).build() ) ) ).add($charCount(this, varname, ".", "<", 2))); } if (type.options.negative === false) { return new ValidateGenerator(type, (varname) => $condition("&&").add($type(varname, "string")).add($length(varname, ">", 0)).add( $everySome( this, varname, (char) => $condition("||").add($charCode(char, [48 /* Zero */, 57 /* Nine */])).add($charCode(char, 46 /* Dot */)).build(), (char) => $charCode(char, [49 /* One */, 57 /* Nine */]) ) ).add($charCount(this, varname, ".", "<", 2))); } if (type.options.positive === false) { return new ValidateGenerator(type, (varname) => $condition("&&").add($type(varname, "string")).add($length(varname, ">", 0)).add($charCode(varname, 45 /* Minus */)).add( $everySome( this, varname, (char) => $condition("||").add($charCode(char, [48 /* Zero */, 57 /* Nine */])).add($charCode(char, 46 /* Dot */)).build(), (char) => $charCode(char, [49 /* One */, 57 /* Nine */]), 1 ) ).add($charCount(this, varname, ".", "<", 2))); } return new ValidateGenerator(type, (varname) => $condition("&&").add($type(varname, "string")).add($length(varname, ">", 0)).add( $ternary($charCode(varname, 45 /* Minus */)).then($every( this, varname, (char) => $condition("||").add($charCode(char, [48 /* Zero */, 57 /* Nine */])).add($charCode(char, 46 /* Dot */)).build(), 1 )).else($every( this, varname, (char) => $condition("||").add($charCode(char, [48 /* Zero */, 57 /* Nine */])).add($charCode(char, 46 /* Dot */)).build() )) ).add($charCount(this, varname, ".", "<", 2))); case "function": return new ValidateGenerator( type, (varname) => $type(varname, "function") ); case "symbol": return new ValidateGenerator( type, (varname) => $type(varname, "symbol") ); case "undefined": return new ValidateGenerator( type, (varname) => $type(varname, "undefined") ); case "unknown": return new TruthyGenerator(type); } } visitArrayOf(type, children) { if (children && children.length > 0) { const oneof = this.visitOneOf(type["union"], children); return new ValidateGenerator(type, (varname) => { return $condition("&&").add($isArray(varname)).add($every(this, varname, (elem) => oneof.$buildValidate(elem))); }); } return new ValidateGenerator(type, (varname) => $isArray(varname)); } visitTuple(type, children) { return new ValidateGenerator(type, (varname) => { const cond = $condition("&&").add($isArray(varname)).add($length(varname, "==", type.tuple.length)); if (children && children.length > 0) { for (const [index, c] of children.entries()) { cond.add(c.$buildValidate(`${varname}[${index}]`)); } } return cond; }); } visitRecordOf(type, children = []) { children = this.sortChildren(children); const getRecordConditions = (varName) => { const cond = $isObject(varName); if (children && children.length > 0) { for (const c of children) { const accessor = propertyAccessor(c.propertyName); const nextName = `${varName}${accessor}`; if (c.required === true) { if (this.canSkipPropertyCheck(c.child.originalSchema())) { if (c.child.isAlwaysTrue()) { cond.add($has(varName, c.propertyName)); } else { cond.add(c.child.$buildValidate(nextName)); } } else { cond.add($has(varName, c.propertyName)); if (!c.child.isAlwaysTrue()) { cond.add(c.child.$buildValidate(nextName)); } } } else { if (!c.child.isAlwaysTrue()) { cond.add( $ternary($notEqual(nextName, void 0)).then(c.child.$buildValidate(nextName)).else("true") ); } } } } return cond; }; return new ValidateGenerator(type, (varname) => { if (varname.split(/\[|\./).length > 2) { const fnName = this.getUniqueFnName(); const argName = this.getUniqueVarName(); const validateFn = $defineFn( fnName, argName, getRecordConditions(argName).build() ); this.addDeclaration("inner", validateFn.declaration); return validateFn.$invokeWith(varname); } else { return getRecordConditions(varname); } }); } visitDict(type, children) { if (children && children.length > 0) { const oneof = this.visitOneOf(type["union"], children); return new ValidateGenerator( type, (varname) => $isObject(varname).add( $everyObjectValue( this, varname, (elem) => oneof.$buildValidate(elem) ) ) ); } else { return new ValidateGenerator( type, (varname) => $isObject(varname) ); } } visitSetOf(type, children = []) { children = this.sortChildren(children); const getBaseSetConditions = (varName) => { return $isObject(varName).add($isSet(varName)); }; if (children && children.length > 0) { const oneof = this.visitOneOf(type["union"], children); return new ValidateGenerator( type, (varname) => getBaseSetConditions(varname).add( $everyInSet(this, varname, (elem) => oneof.$buildValidate(elem)) ) ); } return new ValidateGenerator( type, (varname) => getBaseSetConditions(varname) ); } visitOneOf(type, children) { children = this.sortChildren(children); return new ValidateGenerator(type, (varname) => { const cond = $condition("||"); for (const c of children) { cond.add(c.$buildValidate(varname)); } return cond; }); } visitAllOf(type, children) { return new ValidateGenerator(type, (varname) => { const cond = $condition("&&"); for (const c of children) { cond.add(c.$buildValidate(varname)); } return cond; }); } visitLiteral(type) { return new ValidateGenerator( type, (varname) => $equal(varname, type.literal) ); } visitEnum(type) { const enumKeys = Object.keys(type.enumInstance).filter( (key) => Number.isNaN(Number(key)) ); return new ValidateGenerator(type, (varname) => { const cond = $condition("||"); for (const key of enumKeys) { const member = type.enumInstance[key]; cond.add($equal(varname, member)); } return cond; }); } visitEnumMember(type) { return new ValidateGenerator( type, (varname) => $equal(varname, type.enumMember) ); } visitInstanceOf(type) { if (!KNOWN_GLOBAL_CLASSES.has(type.instanceOf)) { this.includes.instanceof = true; } return new ValidateGenerator(type, (varname) => $condition("&&").add($instanceof(this, varname, type.instanceOf))); } visitCustom(type) { this.includes.custom = true; const customDepName = this.getUniqueVarName(); this.addDependency(customDepName, type.custom); return new ValidateGenerator( type, (varname) => `${$dependency(customDepName)}(${varname})` ); } visitStringMatching(type) { const regexp = $defineRegexp(this.getUniqueVarName(), type.pattern); this.addDeclaration("outer", regexp.declaration); return new ValidateGenerator(type, (varname) => $condition("&&").add($type(varname, "string")).add(regexp.$test(varname))); } visitRecursive(circular, children) { const [childSchema] = children; const child = circular.type; if (this.circValidationFnNames.has(child)) { const validatorFnName = this.circValidationFnNames.get(child); const argName = this.getUniqueVarName(); const typeUniqueName = this.getUniqueStringForType(child); const validateFn = $defineFn( validatorFnName, argName, $ternary( `_$wasRecursivelyValidated(${_serialize(typeUniqueName)}, ${argName})` ).then("true").else(childSchema.$buildValidate(argName)) ); this.includes.recursive = true; this.addDeclaration("inner", validateFn.declaration); return new ValidateGenerator( circular, (varname) => validateFn.$invokeWith(varname) ); } return childSchema; } visitRecursiveRef(type) { const referencedType = type._getReferencedType(); if (this.circValidationFnNames.has(referencedType)) { const validatorFnName2 = this.circValidationFnNames.get(referencedType); return new ValidateGenerator( type, (varname) => `${validatorFnName2}(${varname})` ); } const validatorFnName = this.getUniqueFnName(); this.circValidationFnNames.set(referencedType, validatorFnName); return new ValidateGenerator( type, (varname) => `${validatorFnName}(${varname})` ); } visit(type, children, depth) { if (depth > this.depth) { this.depth = depth; } switch (type.kind) { case "simple": return this.visitPrimitive(type); case "array": return this.visitArrayOf(type, children); case "tuple": return this.visitTuple(type, children); case "record": return this.visitRecordOf(type, children); case "dictionary": return this.visitDict(type, children); case "set": return this.visitSetOf(type, children); case "union": return this.visitOneOf(type, children); case "intersection": return this.visitAllOf(type, children); case "literal": return this.visitLiteral(type); case "enumUnion": return this.visitEnum(type); case "enumMember": return this.visitEnumMember(type); case "instanceOf": return this.visitInstanceOf(type); case "custom": return this.visitCustom(type); case "stringMatching": return this.visitStringMatching(type); case "circular": return this.visitRecursive(type, children); case "circularRef": return this.visitRecursiveRef(type); } } }; var e = eval; var recursiveTracker = ( /* js */ ` const _$validatedRecursiveValues = new Map(); function _$wasRecursivelyValidated(_$tn, _$d) { let _$set = _$validatedRecursiveValues.get(_$tn); if (!_$set) { _$set = new Set([_$d]); _$validatedRecursiveValues.set(_$tn, _$set); return false; } if (_$set.has(_$d)) { return true; } _$set.add(_$d); return false; }; `.trim() ); var compile = (dataType, options) => { const visitor = new DataTypeValidatorVisitor(options); const generator = dataType._acceptVisitor(visitor); const validation = generator.$buildValidate("data"); const outerDeclarations = []; const innerDeclarations = []; if (visitor.includes.every) { outerDeclarations.push("const _$every = " + _$every.toString()); } if (visitor.includes.everySome) { outerDeclarations.push("const _$everySome = " + _$everySome.toString()); } if (visitor.includes.everyInSet) { outerDeclarations.push("const _$everyInSet = " + _$everyInSet.toString()); } if (visitor.includes.everyObjectValue) { outerDeclarations.push( "const _$everyObjectValue = " + _$everyObjectValue.toString() ); } if (visitor.includes.charCount) { outerDeclarations.push("const _$countChar = " + _$countChar.toString()); } if (visitor.outerDeclarations) { outerDeclarations.push(...visitor.outerDeclarations); } if (visitor.includes.recursive) { innerDeclarations.push(recursiveTracker); } if (visitor.innerDeclarations) { innerDeclarations.push(...visitor.innerDeclarations); } const validatorStr = `(_$getDependency) => { ${outerDeclarations.join("\n ")} return function validate(data) { ${innerDeclarations.join("\n ")} return ${validation}; } }`; const deps = new Map(visitor.dependencies); const _$getDependency = (name) => { return deps.get(name); }; const evaluatedCode = e(validatorStr); const validator = evaluatedCode(_$getDependency); const { includes } = visitor; validator.asString = (name = "validate") => { if (includes.custom) { throw new Error( "Validators with Custom type validation cannot be compiled to standalone code" ); } if (includes.instanceof) { throw new Error( "Validators with InstanceOf type validation cannot be compiled to standalone code" ); } return [ ...outerDeclarations, `function ${name}(data) { ${innerDeclarations.join("\n ")} return ${validation} }` ].join("\n"); }; return validator; }; function _$every(_$arr, _$predicate, _$start = 0) { for (let _$i = _$start; _$i < _$arr.length; _$i++) { if (!_$predicate(_$arr[_$i], _$i)) { return false; } } return true; } function _$everySome(_$arr, _$everyPredicate, _$somePredicate, _$start = 0) { let _$someSatisfied = false; for (let _$i = _$start; _$i < _$arr.length; _$i++) { if (!_$everyPredicate(_$arr[_$i], _$i)) { return false; } if (!_$someSatisfied) { _$someSatisfied = _$somePredicate(_$arr[_$i], _$i); } } return _$someSatisfied; } function _$everyInSet(_$set, _$predicate) { for (let _$item of _$set) { if (!_$predicate(_$item)) { return false; } } return true; } function _$everyObjectValue(_$obj, _$predicate) { for (let _$key in _$obj) { if (!_$predicate(_$obj[_$key])) { return false; } } return true; } function _$countChar(_$str, _$char) { let _$count = 0; for (let _$i = 0; _$i < _$str.length; _$i++) { if (_$str[_$i] === _$char) { _$count++; } } return _$count; } export { compile };