UNPKG

zod-compiler

Version:

Compile Zod schemas to fast parsers or TypeScript types

1,090 lines (1,071 loc) 125 kB
Object.defineProperty(exports, '__esModule', { value: true }); var ts = require('typescript'); var standalone = require('./standalone.js'); var _apply_decs_2203_r = require('@swc/helpers/_/_apply_decs_2203_r'); var z = require('zod'); var _identity = require('@swc/helpers/_/_identity'); function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; } var ts__default = /*#__PURE__*/_interopDefault(ts); var standalone__default = /*#__PURE__*/_interopDefault(standalone); var z__default = /*#__PURE__*/_interopDefault(z); function uniqueIdentifier(name) { return ts.factory.createUniqueName(name, ts__default.default.GeneratedIdentifierFlags.ReservedInNestedScopes); } function local(ident, initializer, modifiable = false) { return ts.factory.createVariableStatement([], ts.factory.createVariableDeclarationList([ ts.factory.createVariableDeclaration(ident, undefined, undefined, initializer) ], !modifiable ? ts.NodeFlags.Const : ts.NodeFlags.Let)); } function objectLiteral(obj) { const entries = Object.entries(obj).filter(([k, v])=>!!v); return ts.factory.createObjectLiteralExpression(entries.map(([name, expr])=>ts.factory.createPropertyAssignment(ts.factory.createStringLiteral(name), expr)), entries.length > 1); } const IDENT_REGEX = /^[$A-Z_a-z][\w$]*$/; function identifierOrStringLiteral(value) { if (IDENT_REGEX.test(value)) { return ts.factory.createIdentifier(value); } else { return ts.factory.createStringLiteral(value); } } function propertyChain(start, elements) { for (let element of elements){ if (typeof element === 'string') { if (IDENT_REGEX.test(element)) { start = ts.factory.createPropertyAccessExpression(start, element); continue; } element = ts.factory.createStringLiteral(element); } start = ts.factory.createElementAccessExpression(start, element); } return start; } function print(node, hint = ts.EmitHint.Unspecified) { const file = ts__default.default.createSourceFile('print.ts', '', ts.ScriptTarget.ES2022, false, ts.ScriptKind.TS); const printer = ts__default.default.createPrinter(); return printer.printNode(hint, node, file); } function callHelper(verifierContext, helper, ...args) { return ts.factory.createCallExpression(propertyChain(verifierContext, [ 'helpers', helper ]), undefined, args); } class Path { constructor(parts){ this.parts = parts; } static empty() { return new Path([]); } get isEmpty() { return this.parts.length === 0; } clone() { return new Path([ ...this.parts ]); } push(fragment) { const parts = [ ...this.parts ]; if (typeof fragment === 'string') { parts.push(ts.factory.createStringLiteral(fragment)); } else if (typeof fragment === 'number') { parts.push(ts.factory.createNumericLiteral(fragment, ts.TokenFlags.None)); } else { parts.push(fragment); } return new Path(parts); } serialize() { return ts.factory.createArrayLiteralExpression(this.parts, false); } } /** * In JavaScript, there exist two main types of values - primitives like strings, numbers, and booleans; and objects like * arrays, `Map`s, `Set`s, and, well, *objects*. Two primitives with equal value are equal to each other: `42 === 42` and * `"foo" === "foo"`, however ***two objects will never be equal to each other***: `{} !== {}`, `[] !== []`. * * Since `zod-compiler` outputs source code which is then {@linkcode eval}uated, it has to get values defined in types * like `z.literal()` or `.default()` or `.catch()` from *somewhere*; for primitive types this is fine, and the value can * be directly pasted into the source code. However, for objects, this can lead to unexpected behavior if you, for example, * expect values returned by `.default()` to be equal to the original value provided in the schema definition. * * The default inlining mode is {@linkcode Default}, which inlines *primitives*, but not *objects*. This means that * any object values are defined as a **dependency**; they are the *exact same values* taken from the schema definition * that the compiled parser can use via a reference. This behavior provides the best compatibility for in-source usage of * `zod-compiler`. * * For **standalone** builds, however, that would mean that you'd have to provide these dependency references to the parser. * `zc.compile()` returns a dependency array which you could then pass to `standalone()`, though you'd have to figure * out where those values come from and extract them out of your source tree. Alternatively, the {@linkcode InliningMode.Aggressive Aggressive} * inlining mode *will* attempt to inline objects, arrays, `Map`s, and `Set`s. This does mean that these values would * no longer be equivalent to their definition, but there's a good chance you don't depend on that behavior anyway. */ var InliningMode = /*#__PURE__*/ function(InliningMode) { /** Does not inline any values; they will all be added as dependencies. */ InliningMode[InliningMode["None"] = 0] = "None"; /** Inlines most primitives: strings, numbers, `BigInt`s, booleans, and `null`/`undefined`. */ InliningMode[InliningMode["Default"] = 1] = "Default"; /** * Like {@linkcode InliningMode.Default Default}, but also inlines objects, arrays, `Map`s and `Set`s, and regular * expressions. * * Symbols and functions cannot be inlined. */ InliningMode[InliningMode["Aggressive"] = 2] = "Aggressive"; return InliningMode; }({}); class Dependencies { constructor(verifierContext, inliningMode){ this.verifierContext = verifierContext; this.inliningMode = inliningMode; this._dependencies = []; } add(value) { const i = this._dependencies.push(value) - 1; return propertyChain(this.verifierContext, [ 'dependencies', i ]); } addOrInline(value) { if (this.inliningMode === 0) { return this.add(value); } const expr = toLiteral(value, this.inliningMode); if (expr === null) { return this.add(value); } return expr; } get dependencies() { return this._dependencies; } } class AbstractGeneratorContextWithExprs { constructor(input, output, verifierContext, dependencies){ this._input = input; this._output = output; this._verifierContext = verifierContext; this._dependencies = dependencies; } get input() { return this._input; } get output() { return this._output; } get dependencies() { return this._dependencies; } get verifierContext() { return this._verifierContext; } *prelude() {} *postlude() {} *outputs(expr) { yield ts.factory.createExpressionStatement(ts.factory.createAssignment(this._output, expr)); } *report(issue, input = this.input) { yield ts.factory.createExpressionStatement(ts.factory.createCallExpression(propertyChain(this.verifierContext, [ 'reportIssue' ]), undefined, [ issue, input ])); } } class AbstractGeneratorContextWithExprsAndStatusVar extends AbstractGeneratorContextWithExprs { *prelude() { yield ts.factory.createVariableStatement([], ts.factory.createVariableDeclarationList([ ts.factory.createVariableDeclaration(this.statusVar, undefined, undefined, ts.factory.createNumericLiteral(standalone.ParseStatus.VALID)) ], ts.NodeFlags.Let)); } constructor(...args){ super(...args), this.statusVar = uniqueIdentifier('status'); } } class FunctionalGeneratorContext extends AbstractGeneratorContextWithExprsAndStatusVar { *postlude() { yield ts.factory.createReturnStatement(this.statusVar); } *status(status, allowShortCircuiting = true) { if (typeof status === 'number') { if (status === standalone.ParseStatus.INVALID && allowShortCircuiting) { yield ts.factory.createReturnStatement(ts.factory.createNumericLiteral(status)); } else { yield ts.factory.createExpressionStatement(ts.factory.createBinaryExpression(this.statusVar, ts.SyntaxKind.BarEqualsToken, ts.factory.createNumericLiteral(status))); } } else { if (allowShortCircuiting) { yield ts.factory.createIfStatement(ts.factory.createBitwiseAnd(status, ts.factory.createNumericLiteral(standalone.ParseStatus.INVALID)), ts.factory.createReturnStatement(status)); } yield ts.factory.createExpressionStatement(ts.factory.createBinaryExpression(this.statusVar, ts.SyntaxKind.BarEqualsToken, status)); } } withInput(expr) { const x = new FunctionalGeneratorContext(expr, this.output, this.verifierContext, this.dependencies); x.statusVar = this.statusVar; return x; } } var LabeledShortCircuitMode = /*#__PURE__*/ function(LabeledShortCircuitMode) { LabeledShortCircuitMode[LabeledShortCircuitMode["Continue"] = 0] = "Continue"; LabeledShortCircuitMode[LabeledShortCircuitMode["Break"] = 1] = "Break"; return LabeledShortCircuitMode; }({}); class LabeledBlockScopeGeneratorContext extends AbstractGeneratorContextWithExprsAndStatusVar { constructor(mode, label, input, output, verifierContext, dependencies){ super(input, output, verifierContext, dependencies), this.mode = mode, this.label = label; } *status(status, allowShortCircuiting = true) { yield ts.factory.createExpressionStatement(ts.factory.createBinaryExpression(this.statusVar, ts.SyntaxKind.BarEqualsToken, typeof status === 'number' ? ts.factory.createNumericLiteral(status) : status)); if (allowShortCircuiting) { const shortCircuit = ()=>{ switch(this.mode){ case 1: return ts.factory.createBreakStatement(this.label); case 0: return ts.factory.createContinueStatement(this.label); } }; if (status === standalone.ParseStatus.INVALID) { yield shortCircuit(); } else { yield ts.factory.createIfStatement(ts.factory.createBitwiseAnd(this.statusVar, ts.factory.createNumericLiteral(standalone.ParseStatus.INVALID)), shortCircuit()); } } } withInput(expr) { const x = new LabeledBlockScopeGeneratorContext(this.mode, this.label, expr, this.output, this.verifierContext, this.dependencies); x.statusVar = this.statusVar; return x; } } function toLiteral(value, mode) { switch(typeof value){ case 'string': return ts.factory.createStringLiteral(value); case 'number': return ts.factory.createNumericLiteral(value); case 'bigint': return ts.factory.createBigIntLiteral(value.toString()); case 'undefined': return ts.factory.createIdentifier('undefined'); case 'boolean': return value ? ts.factory.createTrue() : ts.factory.createFalse(); case 'object': if (value === null) { return ts.factory.createNull(); } if (mode === 2) { if (value instanceof RegExp) { return ts.factory.createRegularExpressionLiteral(value.toString()); } else if (value instanceof Map) { return ts.factory.createNewExpression(ts.factory.createIdentifier('Map'), undefined, [ ts.factory.createArrayLiteralExpression([ ...value.entries() ].map(([k, v])=>ts.factory.createArrayLiteralExpression([ toLiteral(k, mode), toLiteral(v, mode) ]))) ]); } else if (value instanceof Set) { return ts.factory.createNewExpression(ts.factory.createIdentifier('Set'), undefined, [ ts.factory.createArrayLiteralExpression([ ...value.values() ].map((v)=>toLiteral(v, mode))) ]); } else if (Array.isArray(value)) { return ts.factory.createArrayLiteralExpression(value.map((v)=>toLiteral(v, mode))); } else if (value instanceof Date) { return ts.factory.createNewExpression(ts.factory.createIdentifier('Date'), undefined, [ ts.factory.createNumericLiteral(value.getTime()) ]); } else if (value.constructor === Object) { return ts.factory.createObjectLiteralExpression(Object.entries(value).map(([k, v])=>ts.factory.createPropertyAssignment(identifierOrStringLiteral(k), toLiteral(v, mode)))); } else { throw new Error(`Value cannot be inlined: ${value}`); } } break; case 'function': case 'symbol': if (mode === 2) { throw new Error(`${typeof value === 'function' ? 'Functions' : 'Symbols'} cannot be inlined`); } break; } return null; } class AbstractCompiledType { constructor(type){ this.type = type; } } const registry = new Map(); function register(zodType) { return function(constructor, _context) { registry.set(zodType, constructor); }; } function compilable(type) { const typeName = type._def.typeName; if (typeName === undefined) { throw new TypeError('Third-party Zod types are not supported'); } const base = registry.get(typeName); if (!base) { throw new TypeError(`Unimplemented Zod type \`z.${typeName}\``); } return new base(type); } // Mirrors ZodParsedType from src/helpers/util.ts // Mirrors getParsedType from src/helpers/util.ts function typeOf(data) { switch(typeof data){ case 'undefined': return "undefined"; case 'string': return "string"; case 'number': return isNaN(data) ? "nan" : "number"; case 'boolean': return "boolean"; case 'function': return "function"; case 'bigint': return "bigint"; case 'symbol': return "symbol"; case 'object': if (Array.isArray(data)) { return "array"; } if (data === null) { return "null"; } if (typeof data.then === 'function' && typeof data.catch === 'function') { return "promise"; } if (data instanceof Map) { return "map"; } if (data instanceof Set) { return "set"; } if (data instanceof Date) { return "date"; } return "object"; default: return "unknown"; } } function stringify(obj) { return JSON.stringify(obj, (_, value)=>{ if (typeof value === 'bigint') { return value.toString(); } return value; }, 2 /* ugggghhhhhhhh */ ); } function joinValues(array, separator = ' | ') { return array.map((val)=>typeof val === 'string' ? `'${val}'` : val).join(separator); } class ZcError extends Error { get errors() { return this.issues; } constructor(issues){ super(), this.issues = issues; // TODO: why is this required? const actualProto = new.target.prototype; Object.setPrototypeOf(this, actualProto); this.name = 'ZcError'; } format(_mapper) { const mapper = _mapper ?? ((issue)=>issue.message); const fieldErrors = { _errors: [] }; const processError = (error)=>{ for (const issue of error.issues){ if (issue.code === "invalid_union") { issue.unionErrors.map(processError); } else if (issue.code === "invalid_return_type") { processError(issue.returnTypeError); } else if (issue.code === "invalid_arguments") { processError(issue.argumentsError); } else if (issue.path.length === 0) { fieldErrors._errors.push(mapper(issue)); } else { let curr = fieldErrors; let i = 0; while(i < issue.path.length){ const el = issue.path[i]; curr[el] ||= { _errors: [] }; const terminal = i === issue.path.length - 1; if (terminal) { curr[el]._errors.push(mapper(issue)); } curr = curr[el]; i++; } } } }; processError(this); return fieldErrors; } static create(issues) { return new ZcError(issues); } toString() { return this.message; } get message() { return stringify(this.issues); } get isEmpty() { return this.issues.length === 0; } addIssue(sub) { // why not push...? this.issues = [ ...this.issues, sub ]; } addIssues(subs = []) { this.issues = [ ...this.issues, ...subs ]; } flatten(mapper = (issue)=>issue.message) { const fieldErrors = {}; const formErrors = []; for (const sub of this.issues){ if (sub.path.length > 0) { fieldErrors[sub.path[0]] = fieldErrors[sub.path[0]] || []; fieldErrors[sub.path[0]].push(mapper(sub)); } else { formErrors.push(mapper(sub)); } } return { formErrors, fieldErrors }; } get formErrors() { return this.flatten(); //.formErrors?; } } var _dec$u, _initClass$u, _AbstractCompiledType$u; exports.ZcAny = void 0; _dec$u = register(z__default.default.ZodFirstPartyTypeKind.ZodAny); class ZcAny extends (_AbstractCompiledType$u = AbstractCompiledType) { static{ ({ c: [exports.ZcAny, _initClass$u] } = _apply_decs_2203_r._(this, [], [ _dec$u ], _AbstractCompiledType$u)); } compileType() { return ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword); } *compileParser(ctx, path) { yield* ctx.outputs(ctx.input); } static{ _initClass$u(); } } var _dec$t, _initClass$t, _AbstractCompiledType$t; class ArrayGeneratorContext extends LabeledBlockScopeGeneratorContext { constructor(input, output, verifierContext, dependencies, parentStatusSetter){ super(LabeledShortCircuitMode.Continue, undefined, input, output, verifierContext, dependencies), this.parentStatusSetter = parentStatusSetter; } *prelude() {} *status(status, allowShortCircuiting = true) { yield* this.parentStatusSetter(typeof status === 'number' ? ts.factory.createNumericLiteral(status) : status); if (allowShortCircuiting) { if (status === standalone.ParseStatus.INVALID) { yield ts.factory.createContinueStatement(); } else if (typeof status !== 'number') { yield ts.factory.createIfStatement(ts.factory.createBitwiseAnd(status, ts.factory.createNumericLiteral(standalone.ParseStatus.INVALID)), ts.factory.createContinueStatement()); } } } withInput(expr) { const x = new ArrayGeneratorContext(expr, this.output, this.verifierContext, this.dependencies, this.parentStatusSetter); x.statusVar = this.statusVar; return x; } } exports.ZcArray = void 0; _dec$t = register(z__default.default.ZodFirstPartyTypeKind.ZodArray); class ZcArray extends (_AbstractCompiledType$t = AbstractCompiledType) { static{ ({ c: [exports.ZcArray, _initClass$t] } = _apply_decs_2203_r._(this, [], [ _dec$t ], _AbstractCompiledType$t)); } compileType() { return ts.factory.createArrayTypeNode(compilable(this.type._def.type).compileType()); } *compileParser(ctx, path) { yield ts.factory.createIfStatement(ts.factory.createLogicalNot(ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('Array'), 'isArray'), undefined, [ ctx.input ])), ts.factory.createBlock([ ...ctx.report(objectLiteral({ path: path.serialize(), code: ts.factory.createStringLiteral('invalid_type'), expected: ts.factory.createStringLiteral('array'), received: callHelper(ctx.verifierContext, 'typeOf', ctx.input) })), ...ctx.status(standalone.ParseStatus.INVALID) ], true)); if (this.type._def.exactLength !== null) { const value = ts.factory.createNumericLiteral(this.type._def.exactLength.value); const lengthAccessor = ts.factory.createPropertyAccessExpression(ctx.input, 'length'); const tooBigIdent = uniqueIdentifier('tooBig'); const tooSmallIdent = uniqueIdentifier('tooSmall'); yield ts.factory.createIfStatement(ts.factory.createStrictInequality(lengthAccessor, value), ts.factory.createBlock([ local(tooBigIdent, ts.factory.createGreaterThan(lengthAccessor, value)), local(tooSmallIdent, ts.factory.createLessThan(lengthAccessor, value)), ...ctx.report(objectLiteral({ path: path.serialize(), code: ts.factory.createConditionalExpression(tooBigIdent, undefined, ts.factory.createStringLiteral('too_big'), undefined, ts.factory.createStringLiteral('too_small')), minimum: ts.factory.createConditionalExpression(tooSmallIdent, undefined, value, undefined, ts.factory.createIdentifier('undefined')), maximum: ts.factory.createConditionalExpression(tooBigIdent, undefined, value, undefined, ts.factory.createIdentifier('undefined')), type: ts.factory.createStringLiteral('array'), inclusive: ts.factory.createTrue(), exact: ts.factory.createTrue(), message: this.type._def.exactLength.message ? ts.factory.createStringLiteral(this.type._def.exactLength.message) : undefined })), ...ctx.status(standalone.ParseStatus.DIRTY) ], true)); } if (this.type._def.minLength !== null) { yield ts.factory.createIfStatement(ts.factory.createLessThan(ts.factory.createPropertyAccessExpression(ctx.input, 'length'), ts.factory.createNumericLiteral(this.type._def.minLength.value)), ts.factory.createBlock([ ...ctx.report(objectLiteral({ path: path.serialize(), code: ts.factory.createStringLiteral('too_small'), minimum: ts.factory.createNumericLiteral(this.type._def.minLength.value), type: ts.factory.createStringLiteral('array'), inclusive: ts.factory.createTrue(), exact: ts.factory.createFalse(), message: this.type._def.minLength.message ? ts.factory.createStringLiteral(this.type._def.minLength.message) : undefined })), ...ctx.status(standalone.ParseStatus.DIRTY) ], true)); } if (this.type._def.maxLength !== null) { yield ts.factory.createIfStatement(ts.factory.createGreaterThan(ts.factory.createPropertyAccessExpression(ctx.input, 'length'), ts.factory.createNumericLiteral(this.type._def.maxLength.value)), ts.factory.createBlock([ ...ctx.report(objectLiteral({ path: path.serialize(), code: ts.factory.createStringLiteral('too_big'), minimum: ts.factory.createNumericLiteral(this.type._def.maxLength.value), type: ts.factory.createStringLiteral('array'), inclusive: ts.factory.createTrue(), exact: ts.factory.createFalse(), message: this.type._def.maxLength.message ? ts.factory.createStringLiteral(this.type._def.maxLength.message) : undefined })), ...ctx.status(standalone.ParseStatus.DIRTY) ], true)); } const output = uniqueIdentifier('outputArray'); yield local(output, ts.factory.createNewExpression(ts.factory.createIdentifier('Array'), undefined, [ ts.factory.createPropertyAccessExpression(ctx.input, 'length') ])); const indexInitializer = ts.factory.createLoopVariable(true); const elInitializer = uniqueIdentifier('el'); const elOutput = ts.factory.createElementAccessExpression(output, indexInitializer); const childCtx = new ArrayGeneratorContext(elInitializer, elOutput, ctx.verifierContext, ctx.dependencies, (status)=>ctx.status(status, false)); yield ts.factory.createForOfStatement(undefined, ts.factory.createVariableDeclarationList([ ts.factory.createVariableDeclaration(ts.factory.createArrayBindingPattern([ ts.factory.createBindingElement(undefined, undefined, indexInitializer), ts.factory.createBindingElement(undefined, undefined, elInitializer) ])) ], ts.NodeFlags.Const), ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ctx.input, 'entries'), undefined, undefined), ts.factory.createBlock([ ...childCtx.prelude(), ...compilable(this.type._def.type).compileParser(childCtx, path.push(indexInitializer)), ...childCtx.postlude() ])); yield* ctx.outputs(output); } static{ _initClass$t(); } } var _dec$s, _initClass$s, _AbstractCompiledType$s; exports.ZcBigInt = void 0; _dec$s = register(z__default.default.ZodFirstPartyTypeKind.ZodBigInt); class ZcBigInt extends (_AbstractCompiledType$s = AbstractCompiledType) { static{ ({ c: [exports.ZcBigInt, _initClass$s] } = _apply_decs_2203_r._(this, [], [ _dec$s ], _AbstractCompiledType$s)); } compileType() { return ts.factory.createKeywordTypeNode(ts.SyntaxKind.BigIntKeyword); } *compileParser(ctx, path) { let input = ctx.input; if (this.type._def.coerce) { const ident = uniqueIdentifier('coercedInput'); yield local(ident, undefined, true); input = ident; yield ts.factory.createTryStatement(ts.factory.createBlock([ ts.factory.createExpressionStatement(ts.factory.createAssignment(ident, ts.factory.createCallExpression(ts.factory.createIdentifier('BigInt'), undefined, [ ctx.input ]))) ], true), ts.factory.createCatchClause(uniqueIdentifier('e'), ts.factory.createBlock([ ...ctx.report(objectLiteral({ path: path.serialize(), code: ts.factory.createStringLiteral('invalid_type'), expected: ts.factory.createStringLiteral('bigint'), received: callHelper(ctx.verifierContext, 'typeOf', input) }), input), // hopefully this causes a short circuit and the rest of the body doesn't get executed... ...ctx.status(standalone.ParseStatus.INVALID) ], true)), undefined); } let stmt = ts.factory.createIfStatement(ts.factory.createStrictInequality(ts.factory.createTypeOfExpression(input), ts.factory.createStringLiteral('bigint')), ts.factory.createBlock([ ...ctx.report(objectLiteral({ path: path.serialize(), code: ts.factory.createStringLiteral('invalid_type'), expected: ts.factory.createStringLiteral('bigint'), received: callHelper(ctx.verifierContext, 'typeOf', input) }), input), ...ctx.status(standalone.ParseStatus.INVALID) ], true)); const checkStmts = []; for (const check of this.type._def.checks){ switch(check.kind){ case 'min': checkStmts.push(ts.factory.createIfStatement(ts.factory[check.inclusive ? 'createLessThan' : 'createLessThanEquals'](input, ts.factory.createBigIntLiteral(check.value.toString())), ts.factory.createBlock([ ...ctx.report(objectLiteral({ path: path.serialize(), code: ts.factory.createStringLiteral('too_small'), minimum: ts.factory.createBigIntLiteral(check.value.toString()), type: ts.factory.createStringLiteral('bigint'), inclusive: check.inclusive ? ts.factory.createTrue() : ts.factory.createFalse(), exact: ts.factory.createFalse(), message: check.message ? ts.factory.createStringLiteral(check.message) : undefined }), input), ...ctx.status(standalone.ParseStatus.DIRTY) ], true))); break; case 'max': checkStmts.push(ts.factory.createIfStatement(ts.factory[check.inclusive ? 'createGreaterThan' : 'createGreaterThanEquals'](input, ts.factory.createBigIntLiteral(check.value.toString())), ts.factory.createBlock([ ...ctx.report(objectLiteral({ path: path.serialize(), code: ts.factory.createStringLiteral('too_big'), minimum: ts.factory.createBigIntLiteral(check.value.toString()), type: ts.factory.createStringLiteral('bigint'), inclusive: check.inclusive ? ts.factory.createTrue() : ts.factory.createFalse(), exact: ts.factory.createFalse(), message: check.message ? ts.factory.createStringLiteral(check.message) : undefined }), input), ...ctx.status(standalone.ParseStatus.DIRTY) ], true))); break; case 'multipleOf': checkStmts.push(ts.factory.createIfStatement(ts.factory.createStrictInequality(ts.factory.createModulo(input, ts.factory.createBigIntLiteral(check.value.toString())), ts.factory.createBigIntLiteral('0')), ts.factory.createBlock([ ...ctx.report(objectLiteral({ path: path.serialize(), code: ts.factory.createStringLiteral('not_multiple_of'), multipleOf: ts.factory.createBigIntLiteral(check.value.toString()), message: check.message ? ts.factory.createStringLiteral(check.message) : undefined }), input), ...ctx.status(standalone.ParseStatus.DIRTY) ], true))); break; default: throw new Error(`Unsupported ZcBigInt check: ${check}`); } } if (checkStmts.length === 0) { yield stmt; } else { stmt = ts.factory.updateIfStatement(stmt, stmt.expression, stmt.thenStatement, ts.factory.createBlock([ ...checkStmts ], true)); yield stmt; } yield* ctx.outputs(input); } static{ _initClass$s(); } } var _dec$r, _initClass$r, _AbstractCompiledType$r; exports.ZcBoolean = void 0; _dec$r = register(z__default.default.ZodFirstPartyTypeKind.ZodBoolean); class ZcBoolean extends (_AbstractCompiledType$r = AbstractCompiledType) { static{ ({ c: [exports.ZcBoolean, _initClass$r] } = _apply_decs_2203_r._(this, [], [ _dec$r ], _AbstractCompiledType$r)); } compileType() { return ts.factory.createKeywordTypeNode(ts.SyntaxKind.BooleanKeyword); } *compileParser(ctx, path) { let input = ctx.input; if (this.type._def.coerce) { const ident = uniqueIdentifier('coercedInput'); yield local(ident, ts.factory.createCallExpression(ts.factory.createIdentifier('Boolean'), [], [ ctx.input ]), false); input = ident; } yield ts.factory.createIfStatement(ts.factory.createStrictInequality(ts.factory.createTypeOfExpression(input), ts.factory.createStringLiteral('boolean')), ts.factory.createBlock([ ...ctx.report(objectLiteral({ path: path.serialize(), code: ts.factory.createStringLiteral('invalid_type'), expected: ts.factory.createStringLiteral('boolean'), received: callHelper(ctx.verifierContext, 'typeOf', ctx.input) }), input), ...ctx.status(standalone.ParseStatus.INVALID) ], true)); yield* ctx.outputs(ctx.input); } static{ _initClass$r(); } } var _dec$q, _initClass$q, _AbstractCompiledType$q; exports.ZcBranded = void 0; _dec$q = register(z__default.default.ZodFirstPartyTypeKind.ZodBranded); class ZcBranded extends (_AbstractCompiledType$q = AbstractCompiledType) { static{ ({ c: [exports.ZcBranded, _initClass$q] } = _apply_decs_2203_r._(this, [], [ _dec$q ], _AbstractCompiledType$q)); } compileType() { return compilable(this.type._def.type).compileType(); } *compileParser(ctx, path) { yield* compilable(this.type._def.type).compileParser(ctx, path); } static{ _initClass$q(); } } var _dec$p, _initClass$p, _AbstractCompiledType$p; class CatchGeneratorContext extends LabeledBlockScopeGeneratorContext { constructor(label, input, output, verifierContext, dependencies, statusVar){ super(LabeledShortCircuitMode.Break, label, input, output, verifierContext, dependencies); this.statusVar = statusVar; } *prelude() {} withInput(expr) { const x = new CatchGeneratorContext(this.label, expr, this.output, this.verifierContext, this.dependencies, this.statusVar); x.statusVar = this.statusVar; return x; } } exports.ZcCatch = void 0; _dec$p = register(z__default.default.ZodFirstPartyTypeKind.ZodCatch); class ZcCatch extends (_AbstractCompiledType$p = AbstractCompiledType) { static{ ({ c: [exports.ZcCatch, _initClass$p] } = _apply_decs_2203_r._(this, [], [ _dec$p ], _AbstractCompiledType$p)); } compileType() { return compilable(this.type._def.innerType).compileType(); } *compileParser(ctx, path) { const caughtStatus = uniqueIdentifier('caughtStatus'); yield local(caughtStatus, ts.factory.createNumericLiteral(standalone.ParseStatus.VALID), true); const output = uniqueIdentifier('caughtOutput'); yield local(output, undefined, true); const verifierCtxVar = uniqueIdentifier('variantCtx'); yield local(verifierCtxVar, ts.factory.createObjectLiteralExpression([ ts.factory.createSpreadAssignment(ctx.verifierContext), ts.factory.createPropertyAssignment('issues', ts.factory.createArrayLiteralExpression()) ], true)); const label = uniqueIdentifier('catch'); const childCtx = new CatchGeneratorContext(label, ctx.input, output, verifierCtxVar, ctx.dependencies, caughtStatus); const catchValue = ctx.dependencies.addOrInline(this.type._def.catchValue(null)); yield ts.factory.createLabeledStatement(label, ts.factory.createBlock([ ...childCtx.prelude(), ...compilable(this.type._def.innerType).compileParser(childCtx, path), ...childCtx.postlude() ])); yield ts.factory.createIfStatement(ts.factory.createStrictInequality(caughtStatus, ts.factory.createNumericLiteral(standalone.ParseStatus.VALID)), ts.factory.createBlock([ ...ctx.outputs(catchValue) ], true), ts.factory.createBlock([ ...ctx.outputs(output) ], true)); } static{ _initClass$p(); } } var _dec$o, _initClass$o, _AbstractCompiledType$o; exports.ZcDate = void 0; _dec$o = register(z__default.default.ZodFirstPartyTypeKind.ZodDate); class ZcDate extends (_AbstractCompiledType$o = AbstractCompiledType) { static{ ({ c: [exports.ZcDate, _initClass$o] } = _apply_decs_2203_r._(this, [], [ _dec$o ], _AbstractCompiledType$o)); } compileType() { return ts.factory.createTypeReferenceNode('Date'); } *compileParser(ctx, path) { let input = ctx.input; if (this.type._def.coerce) { const ident = uniqueIdentifier('coercedInput'); yield local(ident, ts.factory.createNewExpression(ts.factory.createIdentifier('Date'), [], [ ctx.input ]), false); input = ident; } let stmt = ts.factory.createIfStatement(ts.factory.createLogicalNot(ts.factory.createBinaryExpression(input, ts.SyntaxKind.InstanceOfKeyword, ts.factory.createIdentifier('Date'))), ts.factory.createBlock([ ...ctx.report(objectLiteral({ path: path.serialize(), code: ts.factory.createStringLiteral('invalid_type'), expected: ts.factory.createStringLiteral('date'), received: callHelper(ctx.verifierContext, 'typeOf', input) }), input), ...ctx.status(standalone.ParseStatus.INVALID) ], true)); const timeVar = uniqueIdentifier('time'); const checkStmts = [ local(timeVar, ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(input, 'getTime'), undefined, [])), ts.factory.createIfStatement(ts.factory.createCallExpression(ts.factory.createIdentifier('isNaN'), undefined, [ timeVar ]), ts.factory.createBlock([ ...ctx.report(objectLiteral({ path: path.serialize(), code: ts.factory.createStringLiteral('invalid_date') }), input), ...ctx.status(standalone.ParseStatus.INVALID) ], true)) ]; for (const check of this.type._def.checks){ switch(check.kind){ case 'min': checkStmts.push(ts.factory.createIfStatement(ts.factory.createLessThan(timeVar, ts.factory.createNumericLiteral(check.value)), ts.factory.createBlock([ ...ctx.report(objectLiteral({ path: path.serialize(), code: ts.factory.createStringLiteral('too_small'), minimum: ts.factory.createNumericLiteral(check.value), type: ts.factory.createStringLiteral('date'), inclusive: ts.factory.createTrue(), exact: ts.factory.createFalse(), message: check.message ? ts.factory.createStringLiteral(check.message) : undefined }), input), ...ctx.status(standalone.ParseStatus.DIRTY) ], true))); break; case 'max': checkStmts.push(ts.factory.createIfStatement(ts.factory.createGreaterThan(timeVar, ts.factory.createNumericLiteral(check.value)), ts.factory.createBlock([ ...ctx.report(objectLiteral({ path: path.serialize(), code: ts.factory.createStringLiteral('too_big'), minimum: ts.factory.createNumericLiteral(check.value), type: ts.factory.createStringLiteral('date'), inclusive: ts.factory.createTrue(), exact: ts.factory.createFalse(), message: check.message ? ts.factory.createStringLiteral(check.message) : undefined }), input), ...ctx.status(standalone.ParseStatus.DIRTY) ], true))); break; default: throw new Error(`Unsupported ZcDate check: ${check}`); } } yield ts.factory.updateIfStatement(stmt, stmt.expression, stmt.thenStatement, ts.factory.createBlock([ ...checkStmts ], true)); yield* ctx.outputs(input); } static{ _initClass$o(); } } var _dec$n, _initClass$n, _AbstractCompiledType$n; exports.ZcDefault = void 0; _dec$n = register(z__default.default.ZodFirstPartyTypeKind.ZodDefault); class ZcDefault extends (_AbstractCompiledType$n = AbstractCompiledType) { static{ ({ c: [exports.ZcDefault, _initClass$n] } = _apply_decs_2203_r._(this, [], [ _dec$n ], _AbstractCompiledType$n)); } compileType() { return compilable(this.type._def.innerType).compileType(); } *compileParser(ctx, path) { const newInput = uniqueIdentifier('defaultInput'); yield local(newInput, ctx.input, true); const defaultValue = ctx.dependencies.addOrInline(this.type._def.defaultValue()); yield ts.factory.createIfStatement(ts.factory.createStrictEquality(ts.factory.createTypeOfExpression(newInput), ts.factory.createStringLiteral('undefined')), ts.factory.createBlock([ ts.factory.createExpressionStatement(ts.factory.createAssignment(newInput, defaultValue)) ], true)); yield* compilable(this.type._def.innerType).compileParser(ctx.withInput(newInput), path); } static{ _initClass$n(); } } var _dec$m, _initClass$m, _AbstractCompiledType$m; class ObjectGeneratorContext extends LabeledBlockScopeGeneratorContext { constructor(label, input, output, verifierContext, dependencies, parentStatusSetter){ super(LabeledShortCircuitMode.Break, label, input, output, verifierContext, dependencies), this.parentStatusSetter = parentStatusSetter; } *prelude() {} *status(status, allowShortCircuiting = true) { yield* this.parentStatusSetter(typeof status === 'number' ? ts.factory.createNumericLiteral(status) : status); if (allowShortCircuiting) { if (status === standalone.ParseStatus.INVALID) { yield ts.factory.createBreakStatement(this.label); } else if (typeof status !== 'number') { yield ts.factory.createIfStatement(ts.factory.createBitwiseAnd(status, ts.factory.createNumericLiteral(standalone.ParseStatus.INVALID)), ts.factory.createBreakStatement(this.label)); } } } withInput(expr) { const x = new ObjectGeneratorContext(this.label, expr, this.output, this.verifierContext, this.dependencies, this.parentStatusSetter); x.statusVar = this.statusVar; return x; } } exports.ZcObject = void 0; _dec$m = register(z__default.default.ZodFirstPartyTypeKind.ZodObject); class ZcObject extends (_AbstractCompiledType$m = AbstractCompiledType) { static{ ({ c: [exports.ZcObject, _initClass$m] } = _apply_decs_2203_r._(this, [], [ _dec$m ], _AbstractCompiledType$m)); } compileType() { return ts.factory.createTypeLiteralNode(Object.entries(this.type._def.shape()).map(([key, value])=>{ const type = compilable(value); const isOptional = value._def.typeName === z__default.default.ZodFirstPartyTypeKind.ZodOptional || value.isOptional(); const node = ts.factory.createPropertySignature(undefined, identifierOrStringLiteral(key), isOptional && value._def.typeName !== z__default.default.ZodFirstPartyTypeKind.ZodDefault ? ts.factory.createToken(ts.SyntaxKind.QuestionToken) : undefined, type.compileType()); if (value.description) { ts__default.default.addSyntheticLeadingComment(node, ts.SyntaxKind.MultiLineCommentTrivia, `* ${value.description} `, true); } return node; })); } *compileParser(ctx, path) { if (!this.canSkipTypeCheck) { const typeIdentifier = uniqueIdentifier('type'); yield local(typeIdentifier, callHelper(ctx.verifierContext, 'typeOf', ctx.input)); yield ts.factory.createIfStatement(ts.factory.createStrictInequality(typeIdentifier, ts.factory.createStringLiteral('object')), ts.factory.createBlock([ ...ctx.report(objectLiteral({ path: path.serialize(), code: ts.factory.createStringLiteral('invalid_type'), expected: ts.factory.createStringLiteral('object'), received: typeIdentifier })), ...ctx.status(standalone.ParseStatus.INVALID) ], true)); } const shape = this.type._def.shape(); // TODO: catchall/passthrough/strict // const shapeKeysIdent = uniqueIdentifier('shapeKeys'); // yield local( // shapeKeysIdent, // factory.createNewExpression( // factory.createIdentifier('Set'), // [], // [ factory.createArrayLiteralExpression(Object.keys(shape).map(key => factory.createStringLiteral(key))) ] // ) // ); const output = uniqueIdentifier('outputObject'); yield local(output, ts.factory.createObjectLiteralExpression()); for (const [i, [key, value]] of Object.entries(shape).entries()){ const label = uniqueIdentifier(`prop${i}`); const inputExpr = propertyChain(ctx.input, [ key ]); const outputExpr = propertyChain(output, [ key ]); const childCtx = new ObjectGeneratorContext(label, inputExpr, outputExpr, ctx.verifierContext, ctx.dependencies, (status)=>ctx.status(status, false)); yield ts.factory.createLabeledStatement(label, ts.factory.createBlock([ ...compilable(value).compileParser(childCtx, path.push(key)) ])); } yield* ctx.outputs(output); } static{ _initClass$m(); } constructor(...args){ super(...args), // In the case of discriminated unions, we already check that the type is an object before passing off parsing // to a ZcObject. this.canSkipTypeCheck = false; } } var _dec$l, _initClass$l, _AbstractCompiledType$l; exports.ZcDiscriminatedUnion = void 0; _dec$l = register(z__default.default.ZodFirstPartyTypeKind.ZodDiscriminatedUnion); class ZcDiscriminatedUnion extends (_AbstractCompiledType$l = AbstractCompiledType) { static{ ({ c: [exports.ZcDiscriminatedUnion, _initClass$l] } = _apply_decs_2203_r._(this, [], [ _dec$l ], _AbstractCompiledType$l)); } compileType() { return ts.factory.createUnionTypeNode(this.type._def.options.map((ty)=>compilable(ty).compileType())); } *compileParser(ctx, path) { const typeIdentifier = uniqueIdentifier('type'); yield local(typeIdentifier, callHelper(ctx.verifierContext, 'typeOf', ctx.input)); yield ts.factory.createIfStatement(ts.factory.createStrictInequality(typeIdentifier, ts.factory.createStringLiteral('object')), ts.factory.createBlock([ ...ctx.report(objectLiteral({ path: path.serialize(), code: ts.factory.createStringLiteral('invalid_type'), expected: ts.factory.createStringLiteral('object'), received: typeIdentifier })), ...ctx.status(standalone.ParseStatus.INVALID) ], true)); yield ts.factory.createSwitchStatement(propertyChain(ctx.input, [ this.type._def.discriminator ]), ts.factory.createCaseBlock([ ...[ ...this.type._def.optionsMap.entries() ].map(([discriminator, zodTy])=>{ const ty = compilable(zodTy); if (ty instanceof exports.ZcObject) { // We've already checked that the input is an object. ty.canSkipTypeCheck = true; } return ts.factory.createCaseClause(ctx.dependencies.addOrInline(discriminator), [ ...ty.compileParser(ctx, path), ts.factory.createBreakStatement() ]); }), ts.factory.createDefaultClause([ ...ctx.report(objectLiteral({ path: path.push(this.type._def.discriminator).serialize(), code: ts.factory.createStringLiteral('invalid_union_discriminator'), options: ctx.dependencies.add(Array.from(this.type._def.optionsMap.keys())) })), ...ctx.status(standalone.ParseStatus.INVALID) ]) ])); } static{ _initClass$l(); } } var _dec$k, _init