@matatbread/typia
Version:
Superfast runtime validators with only one line
1,104 lines (1,101 loc) • 45.5 kB
JavaScript
import ts from 'typescript';
import { ExpressionFactory } from '../factories/ExpressionFactory.mjs';
import { IdentifierFactory } from '../factories/IdentifierFactory.mjs';
import { MetadataCollection } from '../factories/MetadataCollection.mjs';
import { MetadataFactory } from '../factories/MetadataFactory.mjs';
import { StatementFactory } from '../factories/StatementFactory.mjs';
import { TypeFactory } from '../factories/TypeFactory.mjs';
import { ValueFactory } from '../factories/ValueFactory.mjs';
import { MetadataArray } from '../schemas/metadata/MetadataArray.mjs';
import { MetadataTuple } from '../schemas/metadata/MetadataTuple.mjs';
import { TransformerError } from '../transformers/TransformerError.mjs';
import { FeatureProgrammer } from './FeatureProgrammer.mjs';
import { IsProgrammer } from './IsProgrammer.mjs';
import { AtomicPredicator } from './helpers/AtomicPredicator.mjs';
import { OptionPredicator } from './helpers/OptionPredicator.mjs';
import { UnionExplorer } from './helpers/UnionExplorer.mjs';
import { check_array_length } from './internal/check_array_length.mjs';
import { check_bigint } from './internal/check_bigint.mjs';
import { check_native } from './internal/check_native.mjs';
import { check_number } from './internal/check_number.mjs';
import { check_string } from './internal/check_string.mjs';
import { check_template } from './internal/check_template.mjs';
import { decode_union_object } from './internal/decode_union_object.mjs';
import { postfix_of_tuple } from './internal/postfix_of_tuple.mjs';
import { wrap_metadata_rest_tuple } from './internal/wrap_metadata_rest_tuple.mjs';
var CheckerProgrammer;
(function (CheckerProgrammer) {
/* -----------------------------------------------------------
WRITERS
----------------------------------------------------------- */
CheckerProgrammer.compose = (props) => FeatureProgrammer.compose({
...props,
config: configure(props),
});
CheckerProgrammer.write = (props) => FeatureProgrammer.write({
config: configure(props),
context: props.context,
functor: props.functor,
type: props.type,
name: props.name,
});
CheckerProgrammer.write_object_functions = (props) => FeatureProgrammer.write_object_functions({
config: configure(props),
context: props.context,
collection: props.collection,
});
CheckerProgrammer.write_union_functions = (props) => FeatureProgrammer.write_union_functions({
config: configure({
context: props.context,
config: {
...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.constant({
name: `${props.config.prefix}a${i}`,
value: ts.factory.createArrowFunction(undefined, undefined, FeatureProgrammer.parameterDeclarations({
config: props.config,
type: TypeFactory.keyword("any"),
input: ts.factory.createIdentifier("input"),
}), TypeFactory.keyword("any"), undefined, decode_array_inline({
...props,
input: ts.factory.createIdentifier("input"),
array: 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.constant({
name: `${props.config.prefix}t${i}`,
value: ts.factory.createArrowFunction(undefined, undefined, FeatureProgrammer.parameterDeclarations({
config: props.config,
type: TypeFactory.keyword("any"),
input: ts.factory.createIdentifier("input"),
}), TypeFactory.keyword("any"), undefined, decode_tuple_inline({
config: props.config,
context: props.context,
functor: props.functor,
input: ts.factory.createIdentifier("input"),
tuple,
explore: {
tracable: props.config.trace,
source: "function",
from: "array",
postfix: "",
},
})),
}));
const configure = (props) => ({
types: {
input: () => TypeFactory.keyword("any"),
output: (type, name) => ts.factory.createTypePredicateNode(undefined, "input", ts.factory.createTypeReferenceNode(name ??
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();
const result = 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.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) => 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: {
...v.explore,
tracable: true,
},
}),
success: props.config.joiner.is ?? ((expr) => expr),
escaper: (v) => ts.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) => ts.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.keyword("boolean"),
},
generator: {
unions: props.config.numeric
? (collection) => FeatureProgrammer.write_union_functions({
config: configure({
...props,
config: {
...props.config,
numeric: false,
},
}),
collection,
})
: undefined,
arrays: (collection) => CheckerProgrammer.write_array_functions({
...props,
collection,
}),
tuples: (collection) => CheckerProgrammer.write_tuple_functions({
...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 ts.factory.createStringLiteral(value);
else if (typeof value === "bigint")
return ExpressionFactory.bigint(value);
return ts.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.NULL(),
});
else
create_add({
binaries: top,
default: props.input,
exact: props.metadata.nullable,
left: ValueFactory.NULL(),
});
// UNDEFINDABLE
if (checkOptional || !props.metadata.isRequired())
if (props.metadata.isRequired())
create_add({
binaries: top,
default: props.input,
exact: false,
left: ValueFactory.UNDEFINED(),
});
else
add({
exact: true,
left: ValueFactory.UNDEFINED(),
});
// FUNCTIONAL
if (props.metadata.functions.length)
if (OptionPredicator.functional(props.context.options) ||
props.metadata.size() !== 1)
add({
exact: true,
left: ts.factory.createStringLiteral("function"),
right: ValueFactory.TYPEOF(props.input),
});
else
binaries.push({
combined: false,
expression: props.config.success,
});
//----
// VALUES
//----
// CONSTANT VALUES
const constants = props.metadata.constants.filter((c) => 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: ts.factory.createTrue(),
right: ts.factory.createCallExpression(IdentifierFactory.access(props.functor.emplaceVariable(`${props.config.prefix}v${props.functor.increment()}`, ts.factory.createNewExpression(ts.factory.createIdentifier("Set"), undefined, [
ts.factory.createArrayLiteralExpression(values.map((v) => typeof v === "boolean"
? v === true
? ts.factory.createTrue()
: ts.factory.createFalse()
: typeof v === "bigint"
? ExpressionFactory.bigint(v)
: typeof v === "number"
? ExpressionFactory.number(v)
: ts.factory.createStringLiteral(v.toString()))),
])), "has"), undefined, [props.input]),
});
}
else
for (const c of constants)
if (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.atomic({
metadata: props.metadata,
name: atom.type,
}) === false)
continue;
else if (atom.type === "number")
binaries.push({
expression: props.config.atomist({
explore: props.explore,
entry: 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: 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: check_string({
context: props.context,
atomic: atom,
input: props.input,
}),
input: props.input,
}),
combined: false,
});
else
add({
exact: true,
left: ts.factory.createStringLiteral(atom.type),
right: ValueFactory.TYPEOF(props.input),
});
// TEMPLATE LITERAL VALUES
if (props.metadata.templates.length)
if (AtomicPredicator.template(props.metadata))
binaries.push({
expression: props.config.atomist({
explore: props.explore,
entry: 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: 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: 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: {
...props.explore,
from: "array",
},
}));
}
// MAPS
if (props.metadata.maps.length) {
const install = (body) => prepare({
head: 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: {
...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.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: {
...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: {
...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: {
...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: {
...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.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: {
...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(ts.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
? check_native({
name: props.metadata.escaped.original.natives[0].name,
input: props.input,
})
: ts.factory.createLogicalAnd(CheckerProgrammer.decode({
context: props.context,
config: props.config,
functor: props.functor,
metadata: props.metadata.escaped.original,
input: props.input,
explore: props.explore,
}), ts.factory.createLogicalAnd(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) => {
props.object.validated ||= true;
return FeatureProgrammer.decode_object(props);
};
const decode_array = (props) => {
if (props.array.type.recursive === false)
return decode_array_inline(props);
const arrayExplore = {
...props.explore,
source: "function",
from: "array",
};
return ts.factory.createLogicalOr(ts.factory.createCallExpression(ts.factory.createIdentifier(props.functor.useLocal(`${props.config.prefix}a${props.array.type.index}`)), undefined, FeatureProgrammer.argumentsArray({
config: props.config,
explore: {
...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 = check_array_length({
context: props.context,
array: props.array,
input: props.input,
});
const main = FeatureProgrammer.decode_array({
config: {
prefix: props.config.prefix,
trace: props.config.trace,
path: props.config.path,
decoder: (next) => CheckerProgrammer.decode({
...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
: ts.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({
...props,
tuple: props.tuple.type,
});
const arrayExplore = {
...props.explore,
source: "function",
from: "array",
};
return ts.factory.createLogicalOr(ts.factory.createCallExpression(ts.factory.createIdentifier(props.functor.useLocal(`${props.config.prefix}t${props.tuple.type.index}`)), undefined, FeatureProgrammer.argumentsArray({
config: props.config,
explore: {
...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: ts.factory.createElementAccessExpression(props.input, index),
metadata,
explore: {
...props.explore,
from: "array",
postfix: props.explore.postfix.length
? `${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: ts.factory.createCallExpression(IdentifierFactory.access(props.input, "slice"), undefined, [ExpressionFactory.number(props.tuple.elements.length - 1)]),
metadata: wrap_metadata_rest_tuple(props.tuple.elements.at(-1).rest),
explore: {
...props.explore,
start: props.tuple.elements.length - 1,
},
})
: null;
const arrayLength = ts.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: ts.factory.createStrictEquality(arrayLength, ExpressionFactory.number(props.tuple.elements.length)),
},
]
: [
{
combined: false,
expression: ts.factory.createLogicalAnd(ts.factory.createLessThanEquals(ExpressionFactory.number(props.tuple.elements.filter((t) => t.optional === false)
.length), arrayLength), ts.factory.createGreaterThanEquals(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) => ts.factory.createCallExpression(ts.factory.createParenthesizedExpression(ts.factory.createArrowFunction(undefined, undefined, [IdentifierFactory.parameter("input", TypeFactory.keyword("any"))], undefined, undefined, CheckerProgrammer.decode({
...props,
input: ts.factory.createIdentifier("input"),
}))), undefined, [
ts.factory.createCallExpression(IdentifierFactory.access(props.input, "toJSON"), undefined, []),
]);
/* -----------------------------------------------------------
UNION TYPE EXPLORERS
----------------------------------------------------------- */
const explore_sets = (props) => ts.factory.createCallExpression(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) => ts.factory.createReturnStatement(props.config.joiner.failure(v)),
},
parameters: [],
input: props.input,
sets: props.sets,
explore: props.explore,
}), undefined, undefined);
const explore_maps = (props) => ts.factory.createCallExpression(UnionExplorer.map({
config: {
checker: (v) => ts.factory.createLogicalAnd(CheckerProgrammer.decode({
config: props.config,
context: props.context,
functor: props.functor,
input: ts.factory.createElementAccessExpression(v.input, 0),
metadata: v.definition[0],
explore: {
...v.explore,
postfix: `${v.explore.postfix}[0]`,
},
}), CheckerProgrammer.decode({
config: props.config,
context: props.context,
functor: props.functor,
input: ts.factory.createElementAccessExpression(v.input, 1),
metadata: v.definition[1],
explore: {
...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) => ts.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.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) => ts.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.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) => ts.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.array_or_tuple({
config: {
checker: (v) => v.definition instanceof 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
? 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
? 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) => ts.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))
ts.factory.createCallExpression(arrow({
explore: props.explore,
input: props.input,
parameters: [],
}), undefined, []);
const arrayExplore = {
...props.explore,
source: "function",
from: "array",
};
return ts.factory.createLogicalOr(ts.factory.createCallExpression(ts.factory.createIdentifier(props.functor.emplaceUnion(props.config.prefix, props.definitions.map((e) => e.type.name).join(" | "), () => arrow({
parameters: FeatureProgrammer.parameterDeclarations({
config: props.config,
type: TypeFactory.keyword("any"),
input: ts.factory.createIdentifier("input"),
}),
explore: {
...arrayExplore,
postfix: "",
},
input: ts.factory.createIdentifier("input"),
}))), undefined, 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,
})
: ts.factory.createCallExpression(ts.factory.createIdentifier(props.functor.useLocal(`${props.config.prefix}u${props.metadata.union_index}`)), undefined, FeatureProgrammer.argumentsArray(props));
})(CheckerProgrammer || (CheckerProgrammer = {}));
const create_add = (props) => {
const factory = props.exact
? ts.factory.createStrictEquality
: ts.factory.createStrictInequality;
props.binaries.push({
expression: factory(props.left, props.right ?? props.default),
combined: false,
});
};
export { CheckerProgrammer };
//# sourceMappingURL=CheckerProgrammer.mjs.map