typia
Version:
Superfast runtime validators with only one line
240 lines • 14.9 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ValidateProgrammer = void 0;
const typescript_1 = __importDefault(require("typescript"));
const ExpressionFactory_1 = require("../factories/ExpressionFactory");
const IdentifierFactory_1 = require("../factories/IdentifierFactory");
const StatementFactory_1 = require("../factories/StatementFactory");
const TypeFactory_1 = require("../factories/TypeFactory");
const CheckerProgrammer_1 = require("./CheckerProgrammer");
const FeatureProgrammer_1 = require("./FeatureProgrammer");
const IsProgrammer_1 = require("./IsProgrammer");
const FunctionProgrammer_1 = require("./helpers/FunctionProgrammer");
const OptionPredicator_1 = require("./helpers/OptionPredicator");
const check_everything_1 = require("./internal/check_everything");
const check_object_1 = require("./internal/check_object");
var ValidateProgrammer;
(function (ValidateProgrammer) {
ValidateProgrammer.decompose = (props) => {
var _a;
const is = IsProgrammer_1.IsProgrammer.decompose(props);
const composed = CheckerProgrammer_1.CheckerProgrammer.compose(Object.assign(Object.assign({}, props), { config: {
prefix: "_v",
path: true,
trace: true,
numeric: OptionPredicator_1.OptionPredicator.numeric(props.context.options),
equals: props.config.equals,
atomist: (next) => [
...(next.entry.expression ? [next.entry.expression] : []),
...(next.entry.conditions.length === 0
? []
: next.entry.conditions.length === 1
? next.entry.conditions[0].map((cond) => typescript_1.default.factory.createLogicalOr(cond.expression, create_report_call({
exceptionable: next.explore.from === "top"
? typescript_1.default.factory.createTrue()
: typescript_1.default.factory.createIdentifier("_exceptionable"),
path: typescript_1.default.factory.createIdentifier(next.explore.postfix
? `_path + ${next.explore.postfix}`
: "_path"),
expected: cond.expected,
value: next.input,
})))
: [
typescript_1.default.factory.createLogicalOr(next.entry.conditions
.map((set) => set
.map((s) => s.expression)
.reduce((a, b) => typescript_1.default.factory.createLogicalAnd(a, b)))
.reduce((a, b) => typescript_1.default.factory.createLogicalOr(a, b)), create_report_call({
exceptionable: next.explore.from === "top"
? typescript_1.default.factory.createTrue()
: typescript_1.default.factory.createIdentifier("_exceptionable"),
path: typescript_1.default.factory.createIdentifier(next.explore.postfix
? `_path + ${next.explore.postfix}`
: "_path"),
expected: next.entry.expected,
value: next.input,
})),
]),
].reduce((x, y) => typescript_1.default.factory.createLogicalAnd(x, y)),
combiner: combine(props),
joiner: joiner(props),
success: typescript_1.default.factory.createTrue(),
} }));
const arrow = typescript_1.default.factory.createArrowFunction(undefined, undefined, [IdentifierFactory_1.IdentifierFactory.parameter("input", TypeFactory_1.TypeFactory.keyword("any"))], props.context.importer.type({
file: "typia",
name: "IValidation",
arguments: [
typescript_1.default.factory.createTypeReferenceNode((_a = props.name) !== null && _a !== void 0 ? _a : TypeFactory_1.TypeFactory.getFullName({
checker: props.context.checker,
type: props.type,
})),
],
}), undefined, typescript_1.default.factory.createBlock([
// validate when false === is<T>(input)
typescript_1.default.factory.createIfStatement(typescript_1.default.factory.createStrictEquality(typescript_1.default.factory.createFalse(), typescript_1.default.factory.createCallExpression(typescript_1.default.factory.createIdentifier("__is"), undefined, [typescript_1.default.factory.createIdentifier("input")])), typescript_1.default.factory.createBlock([
// prepare errors
typescript_1.default.factory.createExpressionStatement(typescript_1.default.factory.createBinaryExpression(typescript_1.default.factory.createIdentifier("errors"), typescript_1.default.factory.createToken(typescript_1.default.SyntaxKind.EqualsToken), typescript_1.default.factory.createArrayLiteralExpression([]))),
typescript_1.default.factory.createExpressionStatement(typescript_1.default.factory.createBinaryExpression(typescript_1.default.factory.createIdentifier("_report"), typescript_1.default.factory.createToken(typescript_1.default.SyntaxKind.EqualsToken), typescript_1.default.factory.createCallExpression(typescript_1.default.factory.createAsExpression(props.context.importer.internal("validateReport"), TypeFactory_1.TypeFactory.keyword("any")), [], [typescript_1.default.factory.createIdentifier("errors")]))),
typescript_1.default.factory.createExpressionStatement(typescript_1.default.factory.createCallExpression(typescript_1.default.factory.createArrowFunction(undefined, undefined, composed.parameters, undefined, undefined, composed.body), undefined, [
typescript_1.default.factory.createIdentifier("input"),
typescript_1.default.factory.createStringLiteral("$input"),
typescript_1.default.factory.createTrue(),
])),
StatementFactory_1.StatementFactory.constant({
name: "success",
value: typescript_1.default.factory.createStrictEquality(ExpressionFactory_1.ExpressionFactory.number(0), typescript_1.default.factory.createIdentifier("errors.length")),
}),
typescript_1.default.factory.createReturnStatement(typescript_1.default.factory.createAsExpression(create_output(), TypeFactory_1.TypeFactory.keyword("any"))),
])),
typescript_1.default.factory.createReturnStatement(typescript_1.default.factory.createAsExpression(typescript_1.default.factory.createObjectLiteralExpression([
typescript_1.default.factory.createPropertyAssignment("success", typescript_1.default.factory.createTrue()),
typescript_1.default.factory.createPropertyAssignment("data", typescript_1.default.factory.createIdentifier("input")),
], true), TypeFactory_1.TypeFactory.keyword("any"))),
], true));
return {
functions: Object.assign(Object.assign({}, is.functions), composed.functions),
statements: [
...is.statements,
...composed.statements,
StatementFactory_1.StatementFactory.constant({
name: "__is",
value: is.arrow,
}),
StatementFactory_1.StatementFactory.mut({ name: "errors" }),
StatementFactory_1.StatementFactory.mut({ name: "_report" }),
],
arrow,
};
};
ValidateProgrammer.write = (props) => {
const functor = new FunctionProgrammer_1.FunctionProgrammer(props.modulo.getText());
const result = ValidateProgrammer.decompose({
config: props.config,
context: props.context,
modulo: props.modulo,
functor,
type: props.type,
name: props.name,
});
return FeatureProgrammer_1.FeatureProgrammer.writeDecomposed({
modulo: props.modulo,
functor,
result,
returnWrapper: props.config.standardSchema
? (arrow) => typescript_1.default.factory.createCallExpression(props.context.importer.internal("createStandardSchema"), undefined, [arrow])
: undefined,
});
};
})(ValidateProgrammer || (exports.ValidateProgrammer = ValidateProgrammer = {}));
const combine = (props) => (next) => {
if (next.explore.tracable === false)
return IsProgrammer_1.IsProgrammer.configure({
options: {
object: (v) => validate_object({
context: props.context,
functor: props.functor,
config: props.config,
entries: v.entries,
input: v.input,
}),
numeric: true,
},
context: props.context,
functor: props.functor,
}).combiner(next);
const path = next.explore.postfix
? `_path + ${next.explore.postfix}`
: "_path";
return next.logic === "and"
? next.binaries
.map((binary) => binary.combined
? binary.expression
: typescript_1.default.factory.createLogicalOr(binary.expression, create_report_call({
exceptionable: next.explore.source === "top"
? typescript_1.default.factory.createTrue()
: typescript_1.default.factory.createIdentifier("_exceptionable"),
path: typescript_1.default.factory.createIdentifier(path),
expected: next.expected,
value: next.input,
})))
.reduce(typescript_1.default.factory.createLogicalAnd)
: typescript_1.default.factory.createLogicalOr(next.binaries
.map((binary) => binary.expression)
.reduce(typescript_1.default.factory.createLogicalOr), create_report_call({
exceptionable: next.explore.source === "top"
? typescript_1.default.factory.createTrue()
: typescript_1.default.factory.createIdentifier("_exceptionable"),
path: typescript_1.default.factory.createIdentifier(path),
expected: next.expected,
value: next.input,
}));
};
const validate_object = (props) => (0, check_object_1.check_object)({
config: {
equals: props.config.equals,
undefined: true,
assert: false,
reduce: typescript_1.default.factory.createLogicalAnd,
positive: typescript_1.default.factory.createTrue(),
superfluous: (input, description) => create_report_call({
path: typescript_1.default.factory.createAdd(typescript_1.default.factory.createIdentifier("_path"), typescript_1.default.factory.createCallExpression(props.context.importer.internal("accessExpressionAsString"), undefined, [typescript_1.default.factory.createIdentifier("key")])),
expected: "undefined",
value: input,
description,
}),
halt: (expr) => typescript_1.default.factory.createLogicalOr(typescript_1.default.factory.createStrictEquality(typescript_1.default.factory.createFalse(), typescript_1.default.factory.createIdentifier("_exceptionable")), expr),
},
context: props.context,
entries: props.entries,
input: props.input,
});
const joiner = (props) => ({
object: (v) => validate_object({
context: props.context,
functor: props.functor,
config: props.config,
entries: v.entries,
input: v.input,
}),
array: (props) => (0, check_everything_1.check_everything)(typescript_1.default.factory.createCallExpression(IdentifierFactory_1.IdentifierFactory.access(props.input, "map"), undefined, [props.arrow])),
failure: (next) => {
var _a, _b;
return create_report_call({
exceptionable: ((_a = next.explore) === null || _a === void 0 ? void 0 : _a.from) === "top"
? typescript_1.default.factory.createTrue()
: typescript_1.default.factory.createIdentifier("_exceptionable"),
path: typescript_1.default.factory.createIdentifier(((_b = next.explore) === null || _b === void 0 ? void 0 : _b.postfix) ? `_path + ${next.explore.postfix}` : "_path"),
expected: next.expected,
value: next.input,
});
},
tuple: (binaries) => (0, check_everything_1.check_everything)(typescript_1.default.factory.createArrayLiteralExpression(binaries, true)),
});
const create_output = () => typescript_1.default.factory.createConditionalExpression(typescript_1.default.factory.createIdentifier("success"), undefined, typescript_1.default.factory.createObjectLiteralExpression([
typescript_1.default.factory.createShorthandPropertyAssignment("success"),
typescript_1.default.factory.createPropertyAssignment("data", typescript_1.default.factory.createIdentifier("input")),
], true), undefined, typescript_1.default.factory.createObjectLiteralExpression([
typescript_1.default.factory.createShorthandPropertyAssignment("success"),
typescript_1.default.factory.createShorthandPropertyAssignment("errors"),
typescript_1.default.factory.createPropertyAssignment("data", typescript_1.default.factory.createIdentifier("input")),
], true));
const create_report_call = (props) => {
var _a;
return typescript_1.default.factory.createCallExpression(typescript_1.default.factory.createIdentifier("_report"), undefined, [
(_a = props.exceptionable) !== null && _a !== void 0 ? _a : typescript_1.default.factory.createIdentifier("_exceptionable"),
typescript_1.default.factory.createObjectLiteralExpression([
typescript_1.default.factory.createPropertyAssignment("path", props.path),
typescript_1.default.factory.createPropertyAssignment("expected", typescript_1.default.factory.createStringLiteral(props.expected)),
typescript_1.default.factory.createPropertyAssignment("value", props.value),
...(props.description
? [
typescript_1.default.factory.createPropertyAssignment("description", props.description),
]
: []),
], true),
]);
};
//# sourceMappingURL=ValidateProgrammer.js.map