Files
stanza/packages/internal/src/registry-build.ts
T
jake 0fcc225d85 feat: consolidate maintenance scripts into packages/internal and add module:new scaffolder
- rename `packages/registry-build` → `packages/internal` to serve as a single home for internal tooling
- add `module-new.ts`: interactive CLI (powered by `@clack/prompts`) that scaffolds a new first-party module under `registry/modules/<slot>-<id>/` with `module.ts`, `package.json`, `tsconfig.json`, `templates/.gitkeep`, and an optional `codemods/index.ts` stub
- expose `pnpm module:new [slot] [id]` at the repo root and update `registry:build` turbo filter to `@stanza/internal`
2026-05-20 12:12:59 -04:00

74 lines
2.4 KiB
TypeScript

#!/usr/bin/env bun
/**
* Static registry build. Scans `registry/modules/*`, imports each module's
* default export, writes:
* - dist/registry/index.json — registry index (slot/module summaries)
* - dist/registry/modules/<slot>-<id>.json — per-module full manifests
*
* The output directory is what gets uploaded to the CDN (Vercel) and what
* the CLI's HTTP loader hits at runtime.
*/
import fs from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";
import type { Module, RegistryIndex } from "@stanza/registry";
const here = path.dirname(fileURLToPath(import.meta.url));
const repoRoot = findRepoRoot(here);
const modulesDir = path.join(repoRoot, "registry", "modules");
const outDir = path.join(repoRoot, "dist", "registry");
await main();
async function main() {
fs.mkdirSync(path.join(outDir, "modules"), { recursive: true });
const dirs = fs
.readdirSync(modulesDir, { withFileTypes: true })
.filter((d) => d.isDirectory())
.map((d) => d.name);
const summaries = [];
for (const dir of dirs) {
const entry = path.join(modulesDir, dir, "module.ts");
const mod = ((await import(entry)) as { default: Module }).default;
if (!mod) throw new Error(`Module ${dir} has no default export.`);
fs.writeFileSync(
path.join(outDir, "modules", `${mod.slot}-${mod.id}.json`),
JSON.stringify(mod, null, 2),
);
summaries.push({
...mod,
adapters: mod.adapters.map((a) => ({ key: a.key, match: a.match })),
});
}
const index: RegistryIndex = {
generatedAt: new Date().toISOString(),
schemaVersion: 1,
slots: [
{ id: "framework", label: "Framework", description: "Web/native app framework." },
{ id: "styling", label: "Styling", description: "CSS / styling system." },
{ id: "db", label: "Database", description: "Database engine." },
{ id: "orm", label: "ORM", description: "Database query layer." },
{ id: "auth", label: "Auth", description: "Authentication provider." },
],
modules: summaries,
};
fs.writeFileSync(path.join(outDir, "index.json"), JSON.stringify(index, null, 2));
console.log(`Wrote ${summaries.length} modules to ${outDir}`);
}
function findRepoRoot(start: string): string {
let dir = start;
for (let i = 0; i < 8; i++) {
if (fs.existsSync(path.join(dir, "pnpm-workspace.yaml"))) return dir;
dir = path.dirname(dir);
}
throw new Error("Could not locate repo root from " + start);
}