UNPKG

@matatbread/typia

Version:

Superfast runtime validators with only one line

1,019 lines 47.8 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.CheckerProgrammer = void 0; const typescript_1 = __importDefault(require("typescript")); const ExpressionFactory_1 = require("../factories/ExpressionFactory"); const IdentifierFactory_1 = require("../factories/IdentifierFactory"); const MetadataCollection_1 = require("../factories/MetadataCollection"); const MetadataFactory_1 = require("../factories/MetadataFactory"); const StatementFactory_1 = require("../factories/StatementFactory"); const TypeFactory_1 = require("../factories/TypeFactory"); const ValueFactory_1 = require("../factories/ValueFactory"); const MetadataArray_1 = require("../schemas/metadata/MetadataArray"); const MetadataTuple_1 = require("../schemas/metadata/MetadataTuple"); const TransformerError_1 = require("../transformers/TransformerError"); const FeatureProgrammer_1 = require("./FeatureProgrammer"); const IsProgrammer_1 = require("./IsProgrammer"); const AtomicPredicator_1 = require("./helpers/AtomicPredicator"); const OptionPredicator_1 = require("./helpers/OptionPredicator"); const UnionExplorer_1 = require("./helpers/UnionExplorer"); const check_array_length_1 = require("./internal/check_array_length"); const check_bigint_1 = require("./internal/check_bigint"); const check_native_1 = require("./internal/check_native"); const check_number_1 = require("./internal/check_number"); const check_string_1 = require("./internal/check_string"); const check_template_1 = require("./internal/check_template"); const decode_union_object_1 = require("./internal/decode_union_object"); const postfix_of_tuple_1 = require("./internal/postfix_of_tuple"); const wrap_metadata_rest_tuple_1 = require("./internal/wrap_metadata_rest_tuple"); var CheckerProgrammer; (function (CheckerProgrammer) { /* ----------------------------------------------------------- WRITERS ----------------------------------------------------------- */ CheckerProgrammer.compose = (props) => FeatureProgrammer_1.FeatureProgrammer.compose(Object.assign(Object.assign({}, props), { config: configure(props) })); CheckerProgrammer.write = (props) => FeatureProgrammer_1.FeatureProgrammer.write({ config: configure(props), context: props.context, functor: props.functor, type: props.type, name: props.name, }); CheckerProgrammer.write_object_functions = (props) => FeatureProgrammer_1.FeatureProgrammer.write_object_functions({ config: configure(props), context: props.context, collection: props.collection, }); CheckerProgrammer.write_union_functions = (props) => FeatureProgrammer_1.FeatureProgrammer.write_union_functions({ config: configure({ context: props.context, config: Object.assign(Object.assign({}, props.config), { numeric: false }), functor: props.functor, }), collection: props.collection, }); CheckerProgrammer.write_array_functions = (props) => props.collection .arrays() .filter((a) => a.recursive) .map((type, i) => StatementFactory_1.StatementFactory.constant({ name: `${props.config.prefix}a${i}`, value: typescript_1.default.factory.createArrowFunction(undefined, undefined, FeatureProgrammer_1.FeatureProgrammer.parameterDeclarations({ config: props.config, type: TypeFactory_1.TypeFactory.keyword("any"), input: typescript_1.default.factory.createIdentifier("input"), }), TypeFactory_1.TypeFactory.keyword("any"), undefined, decode_array_inline(Object.assign(Object.assign({}, props), { input: typescript_1.default.factory.createIdentifier("input"), array: MetadataArray_1.MetadataArray.create({ type, tags: [], }), explore: { tracable: props.config.trace, source: "function", from: "array", postfix: "", } }))), })); CheckerProgrammer.write_tuple_functions = (props) => props.collection .tuples() .filter((t) => t.recursive) .map((tuple, i) => StatementFactory_1.StatementFactory.constant({ name: `${props.config.prefix}t${i}`, value: typescript_1.default.factory.createArrowFunction(undefined, undefined, FeatureProgrammer_1.FeatureProgrammer.parameterDeclarations({ config: props.config, type: TypeFactory_1.TypeFactory.keyword("any"), input: typescript_1.default.factory.createIdentifier("input"), }), TypeFactory_1.TypeFactory.keyword("any"), undefined, decode_tuple_inline({ config: props.config, context: props.context, functor: props.functor, input: typescript_1.default.factory.createIdentifier("input"), tuple, explore: { tracable: props.config.trace, source: "function", from: "array", postfix: "", }, })), })); const configure = (props) => ({ types: { input: () => TypeFactory_1.TypeFactory.keyword("any"), output: (type, name) => typescript_1.default.factory.createTypePredicateNode(undefined, "input", typescript_1.default.factory.createTypeReferenceNode(name !== null && name !== void 0 ? name : TypeFactory_1.TypeFactory.getFullName({ checker: props.context.checker, type }))), }, trace: props.config.trace, path: props.config.path, prefix: props.config.prefix, initializer: (next) => { const collection = new MetadataCollection_1.MetadataCollection(); const result = MetadataFactory_1.MetadataFactory.analyze({ checker: next.context.checker, transformer: next.context.transformer, options: { escape: false, constant: true, absorb: true, }, collection, type: next.type, }); if (result.success === false) throw TransformerError_1.TransformerError.from({ code: next.functor.method, errors: result.errors, }); return { collection, metadata: result.data, }; }, addition: props.config.addition, decoder: props.config.decoder ? (next) => props.config.decoder(next) : (next) => CheckerProgrammer.decode({ context: props.context, config: props.config, functor: props.functor, input: next.input, metadata: next.metadata, explore: next.explore, }), objector: { checker: props.config.decoder ? (next) => props.config.decoder(next) : (next) => CheckerProgrammer.decode({ context: props.context, config: props.config, functor: props.functor, input: next.input, metadata: next.metadata, explore: next.explore, }), decoder: (next) => CheckerProgrammer.decode_object({ config: props.config, functor: props.functor, input: next.input, object: next.object, explore: next.explore, }), joiner: props.config.joiner.object, unionizer: props.config.equals ? (next) => { var _a; return (0, decode_union_object_1.decode_union_object)({ checker: (v) => CheckerProgrammer.decode_object({ config: props.config, functor: props.functor, object: v.object, input: v.input, explore: v.explore, }), decoder: (v) => CheckerProgrammer.decode_object({ config: props.config, functor: props.functor, input: v.input, object: v.object, explore: Object.assign(Object.assign({}, v.explore), { tracable: true }), }), success: (_a = props.config.joiner.is) !== null && _a !== void 0 ? _a : ((expr) => expr), escaper: (v) => typescript_1.default.factory.createReturnStatement(props.config.joiner.failure(v)), input: next.input, objects: next.objects, explore: next.explore, }); } : (next) => props.config.combiner({ logic: "or", explore: next.explore, input: next.input, binaries: next.objects.map((object) => ({ expression: CheckerProgrammer.decode_object({ config: props.config, functor: props.functor, object, input: next.input, explore: next.explore, }), combined: true, })), expected: `(${next.objects.map((t) => t.name).join(" | ")})`, }), failure: (next) => typescript_1.default.factory.createReturnStatement(props.config.joiner.failure(next)), is: props.config.joiner.is, required: props.config.joiner.required, full: props.config.joiner.full ? (next) => props.config.joiner.full(next) : undefined, type: TypeFactory_1.TypeFactory.keyword("boolean"), }, generator: { unions: props.config.numeric ? (collection) => FeatureProgrammer_1.FeatureProgrammer.write_union_functions({ config: configure(Object.assign(Object.assign({}, props), { config: Object.assign(Object.assign({}, props.config), { numeric: false }) })), collection, }) : undefined, arrays: (collection) => CheckerProgrammer.write_array_functions(Object.assign(Object.assign({}, props), { collection })), tuples: (collection) => CheckerProgrammer.write_tuple_functions(Object.assign(Object.assign({}, props), { collection })), }, }); /* ----------------------------------------------------------- DECODERS ----------------------------------------------------------- */ CheckerProgrammer.decode = (props) => { if (props.metadata.any) return props.config.success; const top = []; const binaries = []; const add = (next) => create_add({ binaries, left: next.left, right: next.right, exact: next.exact, default: props.input, }); const getConstantValue = (value) => { if (typeof value === "string") return typescript_1.default.factory.createStringLiteral(value); else if (typeof value === "bigint") return ExpressionFactory_1.ExpressionFactory.bigint(value); return typescript_1.default.factory.createIdentifier(value.toString()); }; //---- // CHECK OPTIONAL //---- // @todo -> should be elaborated const checkOptional = props.metadata.empty() || props.metadata.isUnionBucket(); // NULLABLE if (checkOptional || props.metadata.nullable) if (props.metadata.nullable) add({ exact: props.metadata.nullable, left: ValueFactory_1.ValueFactory.NULL(), }); else create_add({ binaries: top, default: props.input, exact: props.metadata.nullable, left: ValueFactory_1.ValueFactory.NULL(), }); // UNDEFINDABLE if (checkOptional || !props.metadata.isRequired()) if (props.metadata.isRequired()) create_add({ binaries: top, default: props.input, exact: false, left: ValueFactory_1.ValueFactory.UNDEFINED(), }); else add({ exact: true, left: ValueFactory_1.ValueFactory.UNDEFINED(), }); // FUNCTIONAL if (props.metadata.functions.length) if (OptionPredicator_1.OptionPredicator.functional(props.context.options) || props.metadata.size() !== 1) add({ exact: true, left: typescript_1.default.factory.createStringLiteral("function"), right: ValueFactory_1.ValueFactory.TYPEOF(props.input), }); else binaries.push({ combined: false, expression: props.config.success, }); //---- // VALUES //---- // CONSTANT VALUES const constants = props.metadata.constants.filter((c) => AtomicPredicator_1.AtomicPredicator.constant({ metadata: props.metadata, name: c.type, })); const constantLength = constants .map((c) => c.values.length) .reduce((a, b) => a + b, 0); if (constantLength >= 10) { const values = constants .map((c) => c.values.map((v) => v.value)) .flat(); add({ exact: true, left: typescript_1.default.factory.createTrue(), right: typescript_1.default.factory.createCallExpression(IdentifierFactory_1.IdentifierFactory.access(props.functor.emplaceVariable(`${props.config.prefix}v${props.functor.increment()}`, typescript_1.default.factory.createNewExpression(typescript_1.default.factory.createIdentifier("Set"), undefined, [ typescript_1.default.factory.createArrayLiteralExpression(values.map((v) => typeof v === "boolean" ? v === true ? typescript_1.default.factory.createTrue() : typescript_1.default.factory.createFalse() : typeof v === "bigint" ? ExpressionFactory_1.ExpressionFactory.bigint(v) : typeof v === "number" ? ExpressionFactory_1.ExpressionFactory.number(v) : typescript_1.default.factory.createStringLiteral(v.toString()))), ])), "has"), undefined, [props.input]), }); } else for (const c of constants) if (AtomicPredicator_1.AtomicPredicator.constant({ metadata: props.metadata, name: c.type, })) for (const v of c.values) add({ exact: true, left: getConstantValue(v.value), }); // ATOMIC VALUES for (const atom of props.metadata.atomics) if (AtomicPredicator_1.AtomicPredicator.atomic({ metadata: props.metadata, name: atom.type, }) === false) continue; else if (atom.type === "number") binaries.push({ expression: props.config.atomist({ explore: props.explore, entry: (0, check_number_1.check_number)({ context: props.context, numeric: props.config.numeric, atomic: atom, input: props.input, }), input: props.input, }), combined: false, }); else if (atom.type === "bigint") binaries.push({ expression: props.config.atomist({ explore: props.explore, entry: (0, check_bigint_1.check_bigint)({ context: props.context, atomic: atom, input: props.input, }), input: props.input, }), combined: false, }); else if (atom.type === "string") binaries.push({ expression: props.config.atomist({ explore: props.explore, entry: (0, check_string_1.check_string)({ context: props.context, atomic: atom, input: props.input, }), input: props.input, }), combined: false, }); else add({ exact: true, left: typescript_1.default.factory.createStringLiteral(atom.type), right: ValueFactory_1.ValueFactory.TYPEOF(props.input), }); // TEMPLATE LITERAL VALUES if (props.metadata.templates.length) if (AtomicPredicator_1.AtomicPredicator.template(props.metadata)) binaries.push({ expression: props.config.atomist({ explore: props.explore, entry: (0, check_template_1.check_template)({ templates: props.metadata.templates, input: props.input, }), input: props.input, }), combined: false, }); // NATIVE CLASSES for (const native of props.metadata.natives) binaries.push({ expression: (0, check_native_1.check_native)({ name: native.name, input: props.input, }), combined: false, }); const instances = []; const prepare = (next) => instances.push(next); // SETS if (props.metadata.sets.length) { const install = (body) => prepare({ head: (0, check_native_1.check_native)({ name: "Set", input: props.input, }), expected: props.metadata.sets .map((elem) => `Set<${elem.getName()}>`) .join(" | "), body, }); if (props.metadata.sets.some((elem) => elem.value.any)) install(null); else install(explore_sets({ config: props.config, context: props.context, functor: props.functor, sets: props.metadata.sets, input: props.input, explore: Object.assign(Object.assign({}, props.explore), { from: "array" }), })); } // MAPS if (props.metadata.maps.length) { const install = (body) => prepare({ head: (0, check_native_1.check_native)({ name: "Map", input: props.input, }), expected: props.metadata.maps .map(({ key, value }) => `Map<${key}, ${value}>`) .join(" | "), body, }); if (props.metadata.maps.some((elem) => elem.key.any && elem.value.any)) install(null); else install(explore_maps({ config: props.config, context: props.context, functor: props.functor, maps: props.metadata.maps, input: props.input, explore: Object.assign(Object.assign({}, props.explore), { from: "array" }), })); } // ARRAYS AND TUPLES if (props.metadata.tuples.length + props.metadata.arrays.length > 0) { const install = (body) => prepare({ head: props.config.atomist({ explore: props.explore, entry: { expected: [ ...props.metadata.tuples.map((t) => t.type.name), ...props.metadata.arrays.map((a) => a.getName()), ].join(" | "), expression: ExpressionFactory_1.ExpressionFactory.isArray(props.input), conditions: [], }, input: props.input, }), expected: [...props.metadata.tuples, ...props.metadata.arrays] .map((elem) => elem.type.name) .join(" | "), body, }); if (props.metadata.arrays.length === 0) if (props.metadata.tuples.length === 1) install(decode_tuple({ config: props.config, context: props.context, functor: props.functor, tuple: props.metadata.tuples[0], input: props.input, explore: Object.assign(Object.assign({}, props.explore), { from: "array" }), })); // TUPLE ONLY else install(explore_tuples({ config: props.config, context: props.context, functor: props.functor, tuples: props.metadata.tuples, input: props.input, explore: Object.assign(Object.assign({}, props.explore), { from: "array" }), })); else if (props.metadata.arrays.some((elem) => elem.type.value.any)) install(null); else if (props.metadata.tuples.length === 0) if (props.metadata.arrays.length === 1) // ARRAY ONLY install(decode_array({ config: props.config, context: props.context, functor: props.functor, array: props.metadata.arrays[0], input: props.input, explore: Object.assign(Object.assign({}, props.explore), { from: "array" }), })); else install(explore_arrays({ config: props.config, context: props.context, functor: props.functor, arrays: props.metadata.arrays, input: props.input, explore: Object.assign(Object.assign({}, props.explore), { from: "array" }), })); else install(explore_arrays_and_tuples({ config: props.config, context: props.context, functor: props.functor, definitions: [...props.metadata.tuples, ...props.metadata.arrays], input: props.input, explore: props.explore, })); } // OBJECT if (props.metadata.objects.length > 0) prepare({ head: ExpressionFactory_1.ExpressionFactory.isObject({ checkNull: true, checkArray: props.metadata.objects.some((obj) => obj.type.properties.every((prop) => !prop.key.isSoleLiteral() || !prop.value.isRequired())), input: props.input, }), expected: props.metadata.objects .map((obj) => obj.type.name) .join(" | "), body: explore_objects({ config: props.config, functor: props.functor, metadata: props.metadata, input: props.input, explore: Object.assign(Object.assign({}, props.explore), { from: "object" }), }), }); if (instances.length) { const transformer = (merge) => (instance) => instance.body ? { expression: merge(instance.head, instance.body), combined: true, } : { expression: instance.head, combined: false, }; if (instances.length === 1) binaries.push(transformer((head, body) => props.config.combiner({ explore: props.explore, logic: "and", input: props.input, binaries: [head, body].map((expression) => ({ expression, combined: expression !== head, })), expected: props.metadata.getName(), }))(instances[0])); else binaries.push({ expression: props.config.combiner({ explore: props.explore, logic: "or", input: props.input, binaries: instances.map(transformer(typescript_1.default.factory.createLogicalAnd)), expected: props.metadata.getName(), }), combined: true, }); } // ESCAPED CASE if (props.metadata.escaped !== null) binaries.push({ combined: false, expression: props.metadata.escaped.original.size() === 1 && props.metadata.escaped.original.natives.length === 1 ? (0, check_native_1.check_native)({ name: props.metadata.escaped.original.natives[0].name, input: props.input, }) : typescript_1.default.factory.createLogicalAnd(CheckerProgrammer.decode({ context: props.context, config: props.config, functor: props.functor, metadata: props.metadata.escaped.original, input: props.input, explore: props.explore, }), typescript_1.default.factory.createLogicalAnd(IsProgrammer_1.IsProgrammer.decode_to_json({ checkNull: false, input: props.input, }), decode_escaped({ config: props.config, context: props.context, functor: props.functor, metadata: props.metadata.escaped.returns, input: props.input, explore: props.explore, }))), }); //---- // COMBINE CONDITIONS //---- return top.length && binaries.length ? props.config.combiner({ explore: props.explore, logic: "and", input: props.input, binaries: [ ...top, { expression: props.config.combiner({ explore: props.explore, logic: "or", input: props.input, binaries, expected: props.metadata.getName(), }), combined: true, }, ], expected: props.metadata.getName(), }) : binaries.length ? props.config.combiner({ explore: props.explore, logic: "or", input: props.input, binaries, expected: props.metadata.getName(), }) : props.config.success; }; CheckerProgrammer.decode_object = (props) => { var _a; (_a = props.object).validated || (_a.validated = true); return FeatureProgrammer_1.FeatureProgrammer.decode_object(props); }; const decode_array = (props) => { if (props.array.type.recursive === false) return decode_array_inline(props); const arrayExplore = Object.assign(Object.assign({}, props.explore), { source: "function", from: "array" }); return typescript_1.default.factory.createLogicalOr(typescript_1.default.factory.createCallExpression(typescript_1.default.factory.createIdentifier(props.functor.useLocal(`${props.config.prefix}a${props.array.type.index}`)), undefined, FeatureProgrammer_1.FeatureProgrammer.argumentsArray({ config: props.config, explore: Object.assign(Object.assign({}, arrayExplore), { source: "function", from: "array" }), input: props.input, })), props.config.joiner.failure({ input: props.input, expected: props.array.type.name, explore: arrayExplore, })); }; const decode_array_inline = (props) => { const length = (0, check_array_length_1.check_array_length)({ context: props.context, array: props.array, input: props.input, }); const main = FeatureProgrammer_1.FeatureProgrammer.decode_array({ config: { prefix: props.config.prefix, trace: props.config.trace, path: props.config.path, decoder: (next) => CheckerProgrammer.decode(Object.assign(Object.assign({}, props), next)), }, functor: props.functor, combiner: props.config.joiner.array, array: props.array, input: props.input, explore: props.explore, }); return length.expression === null && length.conditions.length === 0 ? main : typescript_1.default.factory.createLogicalAnd(props.config.atomist({ explore: props.explore, input: props.input, entry: length, }), main); }; const decode_tuple = (props) => { if (props.tuple.type.recursive === false) return decode_tuple_inline(Object.assign(Object.assign({}, props), { tuple: props.tuple.type })); const arrayExplore = Object.assign(Object.assign({}, props.explore), { source: "function", from: "array" }); return typescript_1.default.factory.createLogicalOr(typescript_1.default.factory.createCallExpression(typescript_1.default.factory.createIdentifier(props.functor.useLocal(`${props.config.prefix}t${props.tuple.type.index}`)), undefined, FeatureProgrammer_1.FeatureProgrammer.argumentsArray({ config: props.config, explore: Object.assign(Object.assign({}, arrayExplore), { source: "function" }), input: props.input, })), props.config.joiner.failure({ input: props.input, expected: props.tuple.type.name, explore: arrayExplore, })); }; const decode_tuple_inline = (props) => { const binaries = props.tuple.elements .filter((metadata) => metadata.rest === null) .map((metadata, index) => CheckerProgrammer.decode({ context: props.context, config: props.config, functor: props.functor, input: typescript_1.default.factory.createElementAccessExpression(props.input, index), metadata, explore: Object.assign(Object.assign({}, props.explore), { from: "array", postfix: props.explore.postfix.length ? `${(0, postfix_of_tuple_1.postfix_of_tuple)(props.explore.postfix)}[${index}]"` : `"[${index}]"` }), })); const rest = props.tuple.elements.length && props.tuple.elements.at(-1).rest !== null ? CheckerProgrammer.decode({ config: props.config, context: props.context, functor: props.functor, input: typescript_1.default.factory.createCallExpression(IdentifierFactory_1.IdentifierFactory.access(props.input, "slice"), undefined, [ExpressionFactory_1.ExpressionFactory.number(props.tuple.elements.length - 1)]), metadata: (0, wrap_metadata_rest_tuple_1.wrap_metadata_rest_tuple)(props.tuple.elements.at(-1).rest), explore: Object.assign(Object.assign({}, props.explore), { start: props.tuple.elements.length - 1 }), }) : null; const arrayLength = typescript_1.default.factory.createPropertyAccessExpression(props.input, "length"); return props.config.combiner({ explore: props.explore, logic: "and", input: props.input, binaries: [ ...(rest === null ? props.tuple.elements.every((t) => t.optional === false) ? [ { combined: false, expression: typescript_1.default.factory.createStrictEquality(arrayLength, ExpressionFactory_1.ExpressionFactory.number(props.tuple.elements.length)), }, ] : [ { combined: false, expression: typescript_1.default.factory.createLogicalAnd(typescript_1.default.factory.createLessThanEquals(ExpressionFactory_1.ExpressionFactory.number(props.tuple.elements.filter((t) => t.optional === false) .length), arrayLength), typescript_1.default.factory.createGreaterThanEquals(ExpressionFactory_1.ExpressionFactory.number(props.tuple.elements.length), arrayLength)), }, ] : []), ...(props.config.joiner.tuple ? [ { expression: props.config.joiner.tuple(binaries), combined: true, }, ] : binaries.map((expression) => ({ expression, combined: true, }))), ...(rest !== null ? [ { expression: rest, combined: true, }, ] : []), ], expected: `[${props.tuple.elements.map((t) => t.getName()).join(", ")}]`, }); }; const decode_escaped = (props) => typescript_1.default.factory.createCallExpression(typescript_1.default.factory.createParenthesizedExpression(typescript_1.default.factory.createArrowFunction(undefined, undefined, [IdentifierFactory_1.IdentifierFactory.parameter("input", TypeFactory_1.TypeFactory.keyword("any"))], undefined, undefined, CheckerProgrammer.decode(Object.assign(Object.assign({}, props), { input: typescript_1.default.factory.createIdentifier("input") })))), undefined, [ typescript_1.default.factory.createCallExpression(IdentifierFactory_1.IdentifierFactory.access(props.input, "toJSON"), undefined, []), ]); /* ----------------------------------------------------------- UNION TYPE EXPLORERS ----------------------------------------------------------- */ const explore_sets = (props) => typescript_1.default.factory.createCallExpression(UnionExplorer_1.UnionExplorer.set({ config: { checker: (v) => CheckerProgrammer.decode({ context: props.context, config: props.config, functor: props.functor, input: v.input, metadata: v.definition, explore: v.explore, }), decoder: (v) => decode_array({ config: props.config, context: props.context, functor: props.functor, array: v.definition, input: v.input, explore: v.explore, }), empty: props.config.success, success: props.config.success, failure: (v) => typescript_1.default.factory.createReturnStatement(props.config.joiner.failure(v)), }, parameters: [], input: props.input, sets: props.sets, explore: props.explore, }), undefined, undefined); const explore_maps = (props) => typescript_1.default.factory.createCallExpression(UnionExplorer_1.UnionExplorer.map({ config: { checker: (v) => typescript_1.default.factory.createLogicalAnd(CheckerProgrammer.decode({ config: props.config, context: props.context, functor: props.functor, input: typescript_1.default.factory.createElementAccessExpression(v.input, 0), metadata: v.definition[0], explore: Object.assign(Object.assign({}, v.explore), { postfix: `${v.explore.postfix}[0]` }), }), CheckerProgrammer.decode({ config: props.config, context: props.context, functor: props.functor, input: typescript_1.default.factory.createElementAccessExpression(v.input, 1), metadata: v.definition[1], explore: Object.assign(Object.assign({}, v.explore), { postfix: `${v.explore.postfix}[1]` }), })), decoder: (v) => decode_array({ context: props.context, config: props.config, functor: props.functor, array: v.definition, input: v.input, explore: v.explore, }), empty: props.config.success, success: props.config.success, failure: (v) => typescript_1.default.factory.createReturnStatement(props.config.joiner.failure(v)), }, parameters: [], input: props.input, maps: props.maps, explore: props.explore, }), undefined, undefined); const explore_tuples = (props) => explore_array_like_union_types({ config: props.config, functor: props.functor, factory: (next) => UnionExplorer_1.UnionExplorer.tuple({ config: { checker: (v) => decode_tuple({ context: props.context, config: props.config, functor: props.functor, input: v.input, tuple: v.definition, explore: v.explore, }), decoder: (v) => decode_tuple({ context: props.context, config: props.config, functor: props.functor, tuple: v.definition, input: v.input, explore: v.explore, }), empty: props.config.success, success: props.config.success, failure: (v) => typescript_1.default.factory.createReturnStatement(props.config.joiner.failure(v)), }, parameters: next.parameters, tuples: next.definitions, input: next.input, explore: next.explore, }), definitions: props.tuples, input: props.input, explore: props.explore, }); const explore_arrays = (props) => explore_array_like_union_types({ config: props.config, functor: props.functor, factory: (next) => UnionExplorer_1.UnionExplorer.array({ config: { checker: (v) => CheckerProgrammer.decode({ context: props.context, config: props.config, functor: props.functor, metadata: v.definition, input: v.input, explore: v.explore, }), decoder: (v) => decode_array({ context: props.context, config: props.config, functor: props.functor, array: v.definition, input: v.input, explore: v.explore, }), empty: props.config.success, success: props.config.success, failure: (v) => typescript_1.default.factory.createReturnStatement(props.config.joiner.failure(v)), }, parameters: next.parameters, arrays: next.definitions, input: next.input, explore: next.explore, }), definitions: props.arrays, input: props.input, explore: props.explore, }); const explore_arrays_and_tuples = (props) => explore_array_like_union_types({ config: props.config, functor: props.functor, factory: (next) => UnionExplorer_1.UnionExplorer.array_or_tuple({ config: { checker: (v) => v.definition instanceof MetadataTuple_1.MetadataTuple ? decode_tuple({ config: props.config, context: props.context, functor: props.functor, input: v.input, tuple: v.definition, explore: v.explore, }) : props.config.atomist({ explore: v.explore, entry: { expected: props.definitions .map((elem) => elem instanceof MetadataArray_1.MetadataArray ? elem.getName() : elem.type.name) .join(" | "), expression: CheckerProgrammer.decode({ functor: props.functor, context: props.context, config: props.config, metadata: v.definition, input: v.input, explore: v.explore, }), conditions: [], }, input: v.container, }), decoder: (v) => v.definition instanceof MetadataTuple_1.MetadataTuple ? decode_tuple({ context: props.context, config: props.config, functor: props.functor, input: v.input, tuple: v.definition, explore: v.explore, }) : decode_array({ context: props.context, config: props.config, functor: props.functor, input: v.input, array: v.definition, explore: v.explore, }), empty: props.config.success, success: props.config.success, failure: (v) => typescript_1.default.factory.createReturnStatement(props.config.joiner.failure(v)), }, parameters: next.parameters, definitions: next.definitions, input: next.input, explore: next.explore, }), input: props.input, definitions: props.definitions, explore: props.explore, }); const explore_array_like_union_types = (props) => { const arrow = (next) => props.factory({ parameters: next.parameters, definitions: props.definitions, input: next.input, explore: next.explore, }); if (props.definitions.every((e) => e.type.recursive === false)) typescript_1.default.factory.createCallExpression(arrow({ explore: props.explore, input: props.input, parameters: [], }), undefined, []); const arrayExplore = Object.assign(Object.assign({}, props.explore), { source: "function", from: "array" }); return typescript_1.default.factory.createLogicalOr(typescript_1.default.factory.createCallExpression(typescript_1.default.factory.createIdentifier(props.functor.emplaceUnion(props.config.prefix, props.definitions.map((e) => e.type.name).join(" | "), () => arrow({ parameters: FeatureProgrammer_1.FeatureProgrammer.parameterDeclarations({ config: props.config, type: TypeFactory_1.TypeFactory.keyword("any"), input: typescript_1.default.factory.createIdentifier("input"), }), explore: Object.assign(Object.assign({}, arrayExplore), { postfix: "" }), input: typescript_1.default.factory.createIdentifier("input"), }))), undefined, FeatureProgrammer_1.FeatureProgrammer.argumentsArray(props)), props.config.joiner.failure({ input: props.input, expected: props.definitions.map((e) => e.type.name).join(" | "), explore: arrayExplore, })); }; const explore_objects = (props) => props.metadata.objects.length === 1 ? CheckerProgrammer.decode_object({ config: props.config, functor: props.functor, object: props.metadata.objects[0].type, input: props.input, explore: props.explore, }) : typescript_1.default.factory.createCallExpression(typescript_1.default.factory.createIdentifier(props.functor.useLocal(`${props.config.prefix}u${props.metadata.union_index}`)), undefined, FeatureProgrammer_1.FeatureProgrammer.argumentsArray(props)); })(CheckerProgrammer || (exports.CheckerProgrammer = CheckerProgrammer = {})); const create_add = (props) => { var _a; const factory = props.exact ? typescript_1.default.factory.createStrictEquality : typescript_1.default.factory.createStrictInequality; props.binaries.push({ expression: factory(props.left, (_a = props.right) !== null && _a !== void 0 ? _a : props.default), combined: false, }); }; //# sourceMappingURL=CheckerProgrammer.js.map