UNPKG

@proofkit/typegen

Version:

181 lines (180 loc) 7.51 kB
import { Project, ScriptKind } from "ts-morph"; import chalk from "chalk"; import { OttoAdapter } from "@proofkit/fmdapi/adapters/otto"; import DataApi from "@proofkit/fmdapi"; import { FetchAdapter } from "@proofkit/fmdapi/adapters/fetch"; import { memoryStore } from "@proofkit/fmdapi/tokenStore/memory"; import fs from "fs-extra"; import path from "path"; import { typegenConfig } from "./types.js"; import { defaultEnvNames, commentHeader, overrideCommentHeader } from "./constants.js"; import { getLayoutMetadata } from "./getLayoutMetadata.js"; import { buildSchema, buildOverrideFile } from "./buildSchema.js"; import { buildLayoutClient } from "./buildLayoutClient.js"; const generateTypedClients = async (config, options) => { const parsedConfig = typegenConfig.safeParse({ config }); if (!parsedConfig.success) { console.log(chalk.red("ERROR: Invalid config")); console.log(config); console.dir(parsedConfig.error, { depth: null }); return; } if (Array.isArray(parsedConfig.data.config)) { for (const option of parsedConfig.data.config) { await generateTypedClientsSingle(option, options); } } else { await generateTypedClientsSingle(parsedConfig.data.config, options); } }; const generateTypedClientsSingle = async (config, options) => { const { envNames, layouts, clientSuffix = "Client", generateClient = true, clearOldFiles = false, ...rest } = config; const { resetOverrides = false } = options ?? {}; const validator = rest.validator ?? "zod/v4"; const rootDir = rest.path ?? "schema"; const project = new Project({}); const server = process.env[(envNames == null ? void 0 : envNames.server) ?? defaultEnvNames.server]; const db = process.env[(envNames == null ? void 0 : envNames.db) ?? defaultEnvNames.db]; const apiKey = ((envNames == null ? void 0 : envNames.auth) && "apiKey" in envNames.auth ? process.env[envNames.auth.apiKey ?? defaultEnvNames.apiKey] : void 0) ?? process.env[defaultEnvNames.apiKey]; const username = ((envNames == null ? void 0 : envNames.auth) && "username" in envNames.auth ? process.env[envNames.auth.username ?? defaultEnvNames.username] : void 0) ?? process.env[defaultEnvNames.username]; const password = ((envNames == null ? void 0 : envNames.auth) && "password" in envNames.auth ? process.env[envNames.auth.password ?? defaultEnvNames.password] : void 0) ?? process.env[defaultEnvNames.password]; const auth = apiKey ? { apiKey } : { username: username ?? "", password: password ?? "" }; if (!server || !db || !apiKey && !username) { console.log(chalk.red("ERROR: Could not get all required config values")); console.log("Ensure the following environment variables are set:"); if (!server) console.log(`${(envNames == null ? void 0 : envNames.server) ?? defaultEnvNames.server}`); if (!db) console.log(`${(envNames == null ? void 0 : envNames.db) ?? defaultEnvNames.db}`); if (!apiKey) { const apiKeyNameToLog = (envNames == null ? void 0 : envNames.auth) && "apiKey" in envNames.auth && envNames.auth.apiKey ? envNames.auth.apiKey : defaultEnvNames.apiKey; const usernameNameToLog = (envNames == null ? void 0 : envNames.auth) && "username" in envNames.auth && envNames.auth.username ? envNames.auth.username : defaultEnvNames.username; const passwordNameToLog = (envNames == null ? void 0 : envNames.auth) && "password" in envNames.auth && envNames.auth.password ? envNames.auth.password : defaultEnvNames.password; console.log( `${apiKeyNameToLog} (or ${usernameNameToLog} and ${passwordNameToLog})` ); } console.log(); return; } await fs.ensureDir(rootDir); if (clearOldFiles) { fs.emptyDirSync(path.join(rootDir, "client")); fs.emptyDirSync(path.join(rootDir, "generated")); } const clientIndexFilePath = path.join(rootDir, "client", "index.ts"); fs.rmSync(clientIndexFilePath, { force: true }); let successCount = 0; let errorCount = 0; let totalCount = 0; for await (const item of layouts) { totalCount++; const client = "apiKey" in auth ? DataApi({ adapter: new OttoAdapter({ auth, server, db }), layout: item.layoutName }) : DataApi({ adapter: new FetchAdapter({ auth, server, db, tokenStore: memoryStore() }), layout: item.layoutName }); const result = await getLayoutMetadata({ client, valueLists: item.valueLists }); if (!result) { errorCount++; continue; } const { schema, portalSchema, valueLists } = result; const args = { schemaName: item.schemaName, schema, layoutName: item.layoutName, portalSchema, valueLists, type: validator === "zod/v4" || validator === "zod/v3" ? validator : "ts", strictNumbers: item.strictNumbers, webviewerScriptName: config.webviewerScriptName, envNames: { auth: "apiKey" in auth ? { apiKey: (envNames == null ? void 0 : envNames.auth) && "apiKey" in envNames.auth ? envNames.auth.apiKey : defaultEnvNames.apiKey } : { username: (envNames == null ? void 0 : envNames.auth) && "username" in envNames.auth ? envNames.auth.username : defaultEnvNames.username, password: (envNames == null ? void 0 : envNames.auth) && "password" in envNames.auth ? envNames.auth.password : defaultEnvNames.password }, db: (envNames == null ? void 0 : envNames.db) ?? defaultEnvNames.db, server: (envNames == null ? void 0 : envNames.server) ?? defaultEnvNames.server } }; const schemaFile = project.createSourceFile( path.join(rootDir, "generated", `${item.schemaName}.ts`), { leadingTrivia: commentHeader }, { overwrite: true, scriptKind: ScriptKind.TS } ); buildSchema(schemaFile, args); const overrideFilePath = path.join(rootDir, `${item.schemaName}.ts`); if (!fs.existsSync(overrideFilePath) || resetOverrides) { const overrideFile = project.createSourceFile( overrideFilePath, { leadingTrivia: overrideCommentHeader }, { overwrite: true, scriptKind: ScriptKind.TS } ); buildOverrideFile(overrideFile, schemaFile, args); } if (item.generateClient ?? generateClient) { await fs.ensureDir(path.join(rootDir, "client")); const layoutClientFile = project.createSourceFile( path.join(rootDir, "client", `${item.schemaName}.ts`), { leadingTrivia: commentHeader }, { overwrite: true, scriptKind: ScriptKind.TS } ); buildLayoutClient(layoutClientFile, args); await fs.ensureFile(clientIndexFilePath); const clientIndexFile = project.addSourceFileAtPath(clientIndexFilePath); clientIndexFile.addExportDeclaration({ namedExports: [ { name: "client", alias: `${item.schemaName}${clientSuffix}` } ], moduleSpecifier: `./${item.schemaName}` }); } else { console.log( chalk.yellow( `Skipping client generation for ${item.schemaName} because generateClient is false` ) ); } successCount++; } project.getSourceFiles().forEach((file) => { file.formatText({ baseIndentSize: 2 }); }); await project.save(); return { successCount, errorCount, totalCount }; }; export { generateTypedClients }; //# sourceMappingURL=typegen.js.map