UNPKG

convex

Version:

Client for the Convex Cloud

292 lines (291 loc) 8.19 kB
"use strict"; import path from "path"; import prettier from "prettier"; import { mkdtemp, nodeFs } from "../../bundler/fs.js"; import { entryPoints, walkDir } from "../../bundler/index.js"; import { apiCodegen } from "../codegen_templates/api.js"; import { apiCjsCodegen } from "../codegen_templates/api_cjs.js"; import { dataModel, dataModelWithoutSchema } from "../codegen_templates/dataModel.js"; import { readmeCodegen } from "../codegen_templates/readme.js"; import { serverCodegen } from "../codegen_templates/server.js"; import { tsconfigCodegen } from "../codegen_templates/tsconfig.js"; import { logError, logMessage, logOutput } from "../../bundler/context.js"; import { typeCheckFunctionsInMode } from "./typecheck.js"; import { readProjectConfig } from "./config.js"; function format(source, filetype) { return prettier.format(source, { parser: filetype, pluginSearchDirs: false }); } async function writeFile(ctx, filename, source, dir, dryRun, debug, quiet, filetype = "typescript") { const formattedSource = await format(source, filetype); const dest = path.join(dir.tmpPath, filename); if (debug) { logOutput(ctx, `# ${filename}`); logOutput(ctx, formattedSource); return; } if (dryRun) { if (ctx.fs.exists(dest)) { const fileText = ctx.fs.readUtf8File(dest); if (fileText !== formattedSource) { logOutput(ctx, `Command would replace file: ${dest}`); } } else { logOutput(ctx, `Command would create file: ${dest}`); } return; } if (!quiet) { logMessage(ctx, `writing ${filename}`); } nodeFs.writeUtf8File(dest, formattedSource); } async function writeJsWithTypes(ctx, name, content, codegenDir, dryRun, debug, quiet) { const [jsName, dtsName] = name.endsWith(".cjs") ? [name, `${name.slice(0, -4)}.d.cts`] : name.endsWith(".mjs") ? [name, `${name.slice(0, -4)}.d.mts`] : name.endsWith(".js") ? [name, `${name.slice(0, -3)}.d.ts`] : [`${name}.js`, `${name}.d.ts`]; await writeFile(ctx, dtsName, content.DTS, codegenDir, dryRun, debug, quiet); if (content.JS) { await writeFile(ctx, jsName, content.JS, codegenDir, dryRun, debug, quiet); } } async function doServerCodegen(ctx, codegenDir, dryRun, hasSchemaFile, debug, quiet = false) { if (hasSchemaFile) { await writeJsWithTypes( ctx, "dataModel", dataModel, codegenDir, dryRun, debug, quiet ); } else { await writeJsWithTypes( ctx, "dataModel", dataModelWithoutSchema, codegenDir, dryRun, debug, quiet ); } await writeJsWithTypes( ctx, "server", serverCodegen(), codegenDir, dryRun, debug, quiet ); } async function doApiCodegen(ctx, functionsDir, codegenDir, dryRun, debug, quiet = false, commonjs = false) { const modulePaths = (await entryPoints(ctx, functionsDir, false)).map( (entryPoint) => path.relative(functionsDir, entryPoint) ); await writeJsWithTypes( ctx, "api", apiCodegen(modulePaths), codegenDir, dryRun, debug, quiet ); if (commonjs) { await writeJsWithTypes( ctx, "api_cjs.cjs", apiCjsCodegen(modulePaths), codegenDir, dryRun, debug, quiet ); } } export async function doCodegen({ ctx, functionsDirectoryPath, typeCheckMode, dryRun = false, debug = false, quiet = false, generateCommonJSApi = false }) { const { projectConfig } = await readProjectConfig(ctx); const legacyCodegenPath = path.join(functionsDirectoryPath, "_generated.ts"); if (ctx.fs.exists(legacyCodegenPath)) { if (!dryRun) { logError(ctx, `Deleting legacy codegen file: ${legacyCodegenPath}}`); ctx.fs.unlink(legacyCodegenPath); } else { logError( ctx, `Command would delete legacy codegen file: ${legacyCodegenPath}}` ); } } ctx.fs.mkdir(functionsDirectoryPath, { allowExisting: true }); const schemaPath = path.join(functionsDirectoryPath, "schema.ts"); const hasSchemaFile = ctx.fs.exists(schemaPath); await mkdtemp("_generated", async (tempCodegenDir) => { await doServerCodegen( ctx, tempCodegenDir, dryRun, hasSchemaFile, debug, quiet ); await doApiCodegen( ctx, functionsDirectoryPath, tempCodegenDir, dryRun, debug, quiet, generateCommonJSApi || projectConfig.generateCommonJSApi ); if (!debug && !dryRun) { const codegenDir = path.join(functionsDirectoryPath, "_generated"); if (!canSkipSync(ctx, tempCodegenDir, codegenDir)) { syncFromTemp(ctx, tempCodegenDir, codegenDir, true); } } await typeCheckFunctionsInMode(ctx, typeCheckMode, functionsDirectoryPath); }); } function zipLongest(a, b) { return [...Array(Math.max(a.length, b.length)).keys()].map((i) => [ a[i], b[i] ]); } function canSkipSync(ctx, tempDir, destDir) { if (!ctx.fs.exists(destDir)) return false; for (const [tmp, dest] of zipLongest( [...walkDir(ctx.fs, tempDir.tmpPath)], [...walkDir(ctx.fs, destDir)] )) { if (!tmp || !dest) return false; const tmpRelPath = path.relative(tempDir.tmpPath, tmp.path); const destRelPath = path.relative(destDir, dest.path); if (tmpRelPath !== destRelPath) return false; if (tmp.isDir !== dest.isDir) return false; if (tmp.isDir) continue; if (ctx.fs.readUtf8File(tmp.path) !== ctx.fs.readUtf8File(dest.path)) { return false; } } return true; } function syncFromTemp(ctx, tempDir, destDir, eliminateExtras) { ctx.fs.mkdir(destDir, { allowExisting: true }); const added = /* @__PURE__ */ new Set(); for (const { isDir, path: fpath } of Array.from( walkDir(ctx.fs, tempDir.tmpPath) )) { const relPath = path.relative(tempDir.tmpPath, fpath); const destPath = path.join(destDir, relPath); if (ctx.fs.exists(destPath)) { if (ctx.fs.stat(destPath).isDirectory()) { if (!isDir) { ctx.fs.rm(destPath, { recursive: true }); } } else { ctx.fs.unlink(destPath); } } if (isDir) { ctx.fs.mkdir(destPath, { allowExisting: true }); } else { ctx.fs.renameFile(fpath, destPath); } added.add(destPath); } if (eliminateExtras) { const destEntries = Array.from(walkDir(ctx.fs, destDir)).reverse(); for (const { isDir, path: fpath } of destEntries) { if (!added.has(fpath)) { if (isDir) { ctx.fs.rmdir(fpath); } else { ctx.fs.unlink(fpath); } } } } } export async function doInitCodegen({ ctx, functionsDirectoryPath, dryRun = false, debug = false, quiet = false, overwrite = false }) { await mkdtemp("convex", async (tempFunctionsDir) => { await doReadmeCodegen( ctx, tempFunctionsDir, dryRun, debug, quiet, overwrite ? void 0 : functionsDirectoryPath ); await doTsconfigCodegen( ctx, tempFunctionsDir, dryRun, debug, quiet, overwrite ? void 0 : functionsDirectoryPath ); syncFromTemp(ctx, tempFunctionsDir, functionsDirectoryPath, false); }); } async function doReadmeCodegen(ctx, tempFunctionsDir, dryRun = false, debug = false, quiet = false, dontOverwriteFinalDestination) { if (dontOverwriteFinalDestination && ctx.fs.exists(path.join(dontOverwriteFinalDestination, "README.md"))) { logMessage(ctx, `not overwriting README.md`); return; } await writeFile( ctx, "README.md", readmeCodegen(), tempFunctionsDir, dryRun, debug, quiet, "markdown" ); } async function doTsconfigCodegen(ctx, tempFunctionsDir, dryRun = false, debug = false, quiet = false, dontOverwriteFinalDestination) { if (dontOverwriteFinalDestination && ctx.fs.exists(path.join(dontOverwriteFinalDestination, "tsconfig.json"))) { logMessage(ctx, `not overwriting tsconfig.json`); return; } await writeFile( ctx, "tsconfig.json", tsconfigCodegen(), tempFunctionsDir, dryRun, debug, quiet, "json" ); } //# sourceMappingURL=codegen.js.map