UNPKG

zenstack

Version:

FullStack enhancement for Prisma ORM: seamless integration from database to UI

238 lines 8.98 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.makeFieldSchema = makeFieldSchema; exports.getFieldSchemaDefault = getFieldSchemaDefault; const sdk_1 = require("@zenstackhq/sdk"); const ast_1 = require("@zenstackhq/sdk/ast"); const upper_case_first_1 = require("upper-case-first"); const enhancer_utils_1 = require("../../enhancer/enhancer-utils"); function makeFieldSchema(field) { var _a, _b; if ((0, ast_1.isDataModel)((_a = field.type.reference) === null || _a === void 0 ? void 0 : _a.ref)) { if (field.type.array) { // array field is always optional return `z.array(z.unknown()).optional()`; } else { return field.type.optional ? `z.record(z.unknown()).optional()` : `z.record(z.unknown())`; } } let schema = makeZodSchema(field); const isDecimal = field.type.type === 'Decimal'; for (const attr of field.attributes) { const message = getAttrLiteralArg(attr, 'message'); const messageArg = message ? `, { message: ${JSON.stringify(message)} }` : ''; const messageArgFirst = message ? `{ message: ${JSON.stringify(message)} }` : ''; switch ((_b = attr.decl.ref) === null || _b === void 0 ? void 0 : _b.name) { case '@length': { const min = getAttrLiteralArg(attr, 'min'); if (min) { schema += `.min(${min}${messageArg})`; } const max = getAttrLiteralArg(attr, 'max'); if (max) { schema += `.max(${max}${messageArg})`; } break; } case '@contains': { const expr = getAttrLiteralArg(attr, 'text'); if (expr) { schema += `.includes(${JSON.stringify(expr)}${messageArg})`; } break; } case '@regex': { const expr = getAttrLiteralArg(attr, 'regex'); if (expr) { schema += `.regex(new RegExp(${JSON.stringify(expr)})${messageArg})`; } break; } case '@startsWith': { const text = getAttrLiteralArg(attr, 'text'); if (text) { schema += `.startsWith(${JSON.stringify(text)}${messageArg})`; } break; } case '@endsWith': { const text = getAttrLiteralArg(attr, 'text'); if (text) { schema += `.endsWith(${JSON.stringify(text)}${messageArg})`; } break; } case '@email': { schema += `.email(${messageArgFirst})`; break; } case '@url': { schema += `.url(${messageArgFirst})`; break; } case '@trim': { schema += `.trim()`; break; } case '@lower': { schema += `.toLowerCase()`; break; } case '@upper': { schema += `.toUpperCase()`; break; } case '@db.Uuid': { schema += `.uuid()`; break; } case '@datetime': { schema += `.datetime({ offset: true${message ? ', message: ' + JSON.stringify(message) : ''} })`; break; } case '@gt': { const value = getAttrLiteralArg(attr, 'value'); if (value !== undefined) { schema += isDecimal ? refineDecimal('gt', value, messageArg) : `.gt(${value}${messageArg})`; } break; } case '@gte': { const value = getAttrLiteralArg(attr, 'value'); if (value !== undefined) { schema += isDecimal ? refineDecimal('gte', value, messageArg) : `.gte(${value}${messageArg})`; } break; } case '@lt': { const value = getAttrLiteralArg(attr, 'value'); if (value !== undefined) { schema += isDecimal ? refineDecimal('lt', value, messageArg) : `.lt(${value}${messageArg})`; } break; } case '@lte': { const value = getAttrLiteralArg(attr, 'value'); if (value !== undefined) { schema += isDecimal ? refineDecimal('lte', value, messageArg) : `.lte(${value}${messageArg})`; } break; } } } if (field.attributes.some(enhancer_utils_1.isDefaultWithAuth)) { if (field.type.optional) { schema += '.nullish()'; } else { // field uses `auth()` in `@default()`, this was transformed into a pseudo default // value, while compiling to zod we should turn it into an optional field instead // of `.default()` schema += '.optional()'; } } else { const schemaDefault = getFieldSchemaDefault(field); if (schemaDefault !== undefined) { if (field.type.type === 'BigInt') { // we can't use the `n` BigInt literal notation, since it needs // ES2020 or later, which TypeScript doesn't use by default schema += `.default(BigInt("${schemaDefault}"))`; } else { schema += `.default(${schemaDefault})`; } } if (field.type.optional) { schema += '.nullish()'; } } return schema; } function makeZodSchema(field) { var _a, _b, _c; let schema; if ((_a = field.type.reference) === null || _a === void 0 ? void 0 : _a.ref) { if ((0, ast_1.isEnum)((_b = field.type.reference) === null || _b === void 0 ? void 0 : _b.ref)) { schema = `${(0, upper_case_first_1.upperCaseFirst)(field.type.reference.ref.name)}Schema`; } else if ((0, ast_1.isTypeDef)((_c = field.type.reference) === null || _c === void 0 ? void 0 : _c.ref)) { schema = `z.lazy(() => ${(0, upper_case_first_1.upperCaseFirst)(field.type.reference.ref.name)}Schema)`; } else { schema = 'z.any()'; } } else { switch (field.type.type) { case 'Int': case 'Float': schema = 'z.number()'; break; case 'Decimal': schema = 'DecimalSchema'; break; case 'BigInt': schema = 'z.bigint()'; break; case 'String': schema = 'z.string()'; break; case 'Boolean': schema = 'z.boolean()'; break; case 'DateTime': schema = 'z.coerce.date()'; break; case 'Bytes': schema = 'z.union([z.string(), z.custom<Buffer | Uint8Array>(data => data instanceof Uint8Array)])'; break; default: schema = 'z.any()'; break; } } if (field.type.array) { schema = `z.array(${schema})`; } return schema; } function getAttrLiteralArg(attr, paramName) { const arg = attr.args.find((arg) => { var _a; return ((_a = arg.$resolvedParam) === null || _a === void 0 ? void 0 : _a.name) === paramName; }); return arg && (0, sdk_1.getLiteral)(arg.value); } function refineDecimal(op, value, messageArg) { return `.refine(v => { try { return new Decimal(v.toString()).${op}(${value}); } catch { return false; } }${messageArg})`; } function getFieldSchemaDefault(field) { const attr = field.attributes.find((attr) => { var _a; return ((_a = attr.decl.ref) === null || _a === void 0 ? void 0 : _a.name) === '@default'; }); if (!attr) { return undefined; } const arg = attr.args.find((arg) => { var _a; return ((_a = arg.$resolvedParam) === null || _a === void 0 ? void 0 : _a.name) === 'value'; }); if (arg) { if ((0, ast_1.isStringLiteral)(arg.value)) { return JSON.stringify(arg.value.value); } else if ((0, ast_1.isNumberLiteral)(arg.value)) { return arg.value.value; } else if ((0, ast_1.isBooleanLiteral)(arg.value)) { return arg.value.value; } else if ((0, ast_1.isInvocationExpr)(arg.value) && (0, sdk_1.isFromStdlib)(arg.value.function.ref) && arg.value.function.$refText === 'now') { return `() => new Date()`; } } return undefined; } //# sourceMappingURL=schema-gen.js.map