55 lines
3.1 KiB
JavaScript
55 lines
3.1 KiB
JavaScript
// SPDX-License-Identifier: LicenseRef-ConusAI-Template-1.0
|
|
// The Convex profile's generator entry (spec §5.4): `pnpm convex:gen`. Rebuilds the module
|
|
// library (the registry is read from the manifests, not from a snapshot) and rewrites
|
|
// convex/schema.ts and convex/generated/<module>.ts. The output is deterministic: regeneration
|
|
// on an unchanged registry is byte-identical, and the profile gate asserts it.
|
|
|
|
import { mkdir, readdir, rm, writeFile } from "node:fs/promises"
|
|
import { buildRegistry } from "@conusai-kit/core"
|
|
import { writeConvexFiles } from "@conusai-kit/data-convex"
|
|
import { convexModules } from "../convex/lib/convexModules.mjs"
|
|
// The registry is read from the modules' built library (`pnpm run build:libs` first — the
|
|
// package.json script chains it), filtered to the modules the Convex runtime can deploy
|
|
// (convex/lib/convexModules.mjs, one exclusion map shared with the runtime).
|
|
import { appModules } from "../modules/dist/index.js"
|
|
|
|
const SPDX = "// SPDX-License-Identifier: LicenseRef-ConusAI-Template-1.0\n"
|
|
|
|
// A module that declares its profiles and leaves out `convex` (knowledge, agent) is not deployed
|
|
// here: the runtime's module list (convex/lib/runtime.ts) and test/convex-profile.test.ts apply the
|
|
// same filter, so no wrapper is generated for a procedure the deployed registry does not hold.
|
|
const convexBound = appModules.filter((module) => module.profiles === undefined || module.profiles.includes("convex"))
|
|
const registry = buildRegistry([...convexModules(convexBound)])
|
|
const files = await writeConvexFiles(
|
|
registry,
|
|
new URL("../convex", import.meta.url).pathname,
|
|
{
|
|
mkdir,
|
|
writeFile,
|
|
},
|
|
{ header: SPDX },
|
|
)
|
|
const functionName = (name) => name.replace(/[^A-Za-z0-9_$]/g, "_")
|
|
const procedures = [...registry.procedures.values()]
|
|
.map(({ module, def }) => [def.name, { kind: def.kind, reference: `generated/${module}:${functionName(def.name)}` }])
|
|
.sort(([left], [right]) => left.localeCompare(right))
|
|
const procedureMap = `${SPDX}// Generated by @conusai-kit/data-convex (pnpm convex:gen). Do not edit by hand.\nexport const CONVEX_PROCEDURES = ${JSON.stringify(Object.fromEntries(procedures), null, 2)} as const\n`
|
|
await writeFile(new URL("../convex/generated/procedures.ts", import.meta.url), procedureMap)
|
|
|
|
// Convex bundles every exported .ts function it finds, whether or not another file imports it.
|
|
// Leaving a wrapper for an excluded module deploys a public endpoint whose runtime registry does
|
|
// not contain its procedure. Remove stale wrappers deterministically so generation is also the
|
|
// profile's deployment allowlist.
|
|
const expected = new Set([...files.map((file) => file.path.split("/").at(-1)), "procedures.ts"])
|
|
for (const entry of await readdir(new URL("../convex/generated/", import.meta.url), { withFileTypes: true })) {
|
|
if (entry.isFile() && entry.name.endsWith(".ts") && !expected.has(entry.name)) {
|
|
await rm(new URL(`../convex/generated/${entry.name}`, import.meta.url))
|
|
}
|
|
}
|
|
console.log(
|
|
`convex:gen: ${files.length + 1} file(s) written (${files
|
|
.map((f) => f.path)
|
|
.concat("generated/procedures.ts")
|
|
.join(", ")})`,
|
|
)
|