UNPKG

@proofkit/typegen

Version:

`@proofkit/typegen` is a tool for generating TypeScript types from FileMaker database schemas, making it easier to work with FileMaker data in modern TypeScript projects.

334 lines (333 loc) 9.54 kB
import { VariableDeclarationKind } from "ts-morph"; import { varname } from "./constants.js"; function buildSchema(schemaFile, { type, ...args }) { args.schema.reduce( (acc, el) => acc.find((o) => o.name === el.name) ? acc : [...acc, el], [] ); const { schema, schemaName, portalSchema = [], valueLists = [], strictNumbers = false } = args; const hasPortals = portalSchema.length > 0; if (type === "zod" || type === "zod/v4" || type === "zod/v3") { schemaFile.addImportDeclaration({ moduleSpecifier: type, namedImports: ["z"] }); if (hasPortals) { schemaFile.addImportDeclaration({ moduleSpecifier: "@proofkit/fmdapi", namedImports: ["InferZodPortals"] }); } } for (const p of portalSchema) { if (type === "ts") { buildTypeTS(schemaFile, { schemaName: p.schemaName, schema: p.schema, strictNumbers }); } else { buildTypeZod(schemaFile, { schemaName: p.schemaName, schema: p.schema, strictNumbers }); } } for (const vls of valueLists) { if (vls.values.length > 0) { if (type === "ts") { buildValueListTS(schemaFile, { name: vls.name, values: vls.values }); } else { buildValueListZod(schemaFile, { name: vls.name, values: vls.values }); } } } if (type === "ts") { buildTypeTS(schemaFile, { schemaName, schema, strictNumbers }); } else { buildTypeZod(schemaFile, { schemaName, schema, strictNumbers }); } if (portalSchema.length > 0) { if (type === "ts") { schemaFile.addTypeAlias({ name: `T${varname(schemaName)}Portals`, type: (writer) => { writer.block(() => { portalSchema.forEach((p) => { writer.write(`${p.schemaName}: T${varname(p.schemaName)}`); }); }); }, isExported: true }); } else { schemaFile.addVariableStatement({ isExported: true, declarationKind: VariableDeclarationKind.Const, declarations: [ { name: `Z${varname(schemaName)}Portals`, initializer: (writer) => { writer.write(`{`).newLine().indent(() => { portalSchema.forEach((p, i) => { writer.quote(p.schemaName).write(": ").write(`Z${varname(p.schemaName)}`); writer.conditionalWrite(i !== portalSchema.length - 1, ","); writer.newLine(); }); }).write(`}`); } } ] }); schemaFile.addTypeAlias({ name: `T${varname(schemaName)}Portals`, type: `InferZodPortals<typeof Z${varname(schemaName)}Portals>`, isExported: true }); } } } function buildTypeTS(schemaFile, { schemaName, schema, strictNumbers = false }) { schemaFile.addTypeAlias({ name: `T${varname(schemaName)}`, type: (writer) => { writer.inlineBlock(() => { schema.forEach((field) => { var _a; writer.quote(field.name).write(": "); if (field.type === "string") { writer.write("string"); } else if (field.type === "fmnumber") { if (strictNumbers) { writer.write("number | null"); } else { writer.write("string | number"); } } else if (field.type === "valueList") { writer.write(`"${(_a = field.values) == null ? void 0 : _a.join('" | "')}"`); } else { writer.write("any"); } writer.write(",").newLine(); }); }); }, isExported: true }); } function buildValueListTS(schemaFile, { name, values }) { schemaFile.addTypeAlias({ name: `TVL${varname(name)}`, type: `"${values.join('" | "')}"`, isExported: true }); } function buildTypeZod(schemaFile, { schemaName, schema, strictNumbers = false }) { schemaFile.addVariableStatement({ isExported: true, declarationKind: VariableDeclarationKind.Const, declarations: [ { name: `Z${varname(schemaName)}`, initializer: (writer) => { writer.write(`z.object(`).inlineBlock(() => { schema.forEach((field) => { var _a, _b; writer.quote(field.name).write(": "); if (field.type === "string") { writer.write("z.string()"); } else if (field.type === "fmnumber") { if (strictNumbers) { writer.write("z.coerce.number().nullable().catch(null)"); } else { writer.write("z.union([z.string(), z.number()])"); } } else if (field.type === "valueList") { writer.write(`z.enum([`); (_a = field.values) == null ? void 0 : _a.map( (v, i) => writer.quote(v).conditionalWrite( i !== (field.values ?? []).length - 1, ", " ) ); writer.write("])"); writer.conditionalWrite( (_b = field.values) == null ? void 0 : _b.includes(""), `.catch("")` ); } else { writer.write("z.any()"); } writer.write(",").newLine(); }); }).write(")"); } } ] }); schemaFile.addTypeAlias({ name: `T${varname(schemaName)}`, type: `z.infer<typeof Z${varname(schemaName)}>`, isExported: true }); } function buildValueListZod(schemaFile, { name, values }) { schemaFile.addVariableStatement({ isExported: true, declarationKind: VariableDeclarationKind.Const, declarations: [ { name: `ZVL${varname(name)}`, initializer: (writer) => { writer.write(`z.enum([`); values.map( (v, i) => writer.quote(v).conditionalWrite(i !== values.length - 1, ", ") ); writer.write("])"); } } ] }); schemaFile.addTypeAlias({ name: `TVL${varname(name)}`, type: `z.infer<typeof ZVL${varname(name)}>`, isExported: true }); } function buildOverrideFile(overrideFile, schemaFile, { type, ...args }) { if (type === "zod" || type === "zod/v4" || type === "zod/v3") { overrideFile.addImportDeclaration({ moduleSpecifier: type, namedImports: ["z"] }); } const { schemaName, portalSchema = [] } = args; const namedExportNames = schemaFile.getExportSymbols().map((symbol) => symbol.getName()).filter((name) => { if (type === "zod" || type === "zod/v4" || type === "zod/v3") { return name.startsWith("Z"); } else { return name.startsWith("T"); } }).filter((name) => !name.endsWith("Portals")); overrideFile.addImportDeclaration({ moduleSpecifier: `./generated/${args.schemaName}`, namedImports: namedExportNames.map((name) => ({ name, alias: `${name}_generated`, isTypeOnly: type === "ts" })) }); const hasPortals = portalSchema.length > 0; if (hasPortals && (type === "zod" || type === "zod/v4" || type === "zod/v3")) { overrideFile.addImportDeclaration({ moduleSpecifier: "@proofkit/fmdapi", namedImports: ["InferZodPortals"] }); } namedExportNames.forEach((name) => { if (type === "zod" || type === "zod/v4" || type === "zod/v3") { overrideFile.addVariableStatement({ isExported: true, declarationKind: VariableDeclarationKind.Const, declarations: [ { name, initializer: (writer) => { writer.write(`${name}_generated`); } } ] }); overrideFile.addTypeAlias({ name: name.replace(/^Z/, "T"), type: `z.infer<typeof ${name}>`, isExported: true }); } else if (type === "ts") { overrideFile.addTypeAlias({ name, type: `${name}_generated`, isExported: true }); } }); if (hasPortals) { if (type === "ts") { overrideFile.addTypeAlias({ name: `T${varname(schemaName)}Portals`, type: (writer) => { writer.block(() => { portalSchema.forEach((p) => { writer.write(`${p.schemaName}: T${varname(p.schemaName)}`); }); }); }, isExported: true }); } else { overrideFile.addVariableStatement({ isExported: true, declarationKind: VariableDeclarationKind.Const, declarations: [ { name: `Z${varname(schemaName)}Portals`, initializer: (writer) => { writer.write(`{`).newLine().indent(() => { portalSchema.forEach((p, i) => { writer.quote(p.schemaName).write(": ").write(`Z${varname(p.schemaName)}`); writer.conditionalWrite(i !== portalSchema.length - 1, ","); writer.newLine(); }); }).write(`}`); } } ] }); overrideFile.addTypeAlias({ name: `T${varname(schemaName)}Portals`, type: `InferZodPortals<typeof Z${varname(schemaName)}Portals>`, isExported: true }); } } } export { buildOverrideFile, buildSchema }; //# sourceMappingURL=buildSchema.js.map