80 lines
2.5 KiB
JavaScript
80 lines
2.5 KiB
JavaScript
#!/usr/bin/env node
|
|
import { promises as fs } from "fs";
|
|
import path from "path";
|
|
import { fileURLToPath } from "url";
|
|
|
|
const __filename = fileURLToPath(import.meta.url);
|
|
const __dirname = path.dirname(__filename);
|
|
const projectRoot = path.resolve(__dirname, "..");
|
|
const funnelsDir = path.join(projectRoot, "public", "funnels");
|
|
const outputFile = path.join(projectRoot, "src", "lib", "funnel", "bakedFunnels.ts");
|
|
|
|
function formatFunnelRecord(funnels) {
|
|
const entries = Object.entries(funnels)
|
|
.map(([funnelId, definition]) => {
|
|
const serialized = JSON.stringify(definition, null, 2);
|
|
const indented = serialized
|
|
.split("\n")
|
|
.map((line, index) => (index === 0 ? line : ` ${line}`))
|
|
.join("\n");
|
|
return ` "${funnelId}": ${indented}`;
|
|
})
|
|
.join(",\n\n");
|
|
|
|
return `{
|
|
${entries}\n}`;
|
|
}
|
|
|
|
async function bakeFunnels() {
|
|
const dirExists = await fs
|
|
.access(funnelsDir)
|
|
.then(() => true)
|
|
.catch(() => false);
|
|
|
|
if (!dirExists) {
|
|
throw new Error(`Funnels directory not found: ${funnelsDir}`);
|
|
}
|
|
|
|
const files = (await fs.readdir(funnelsDir)).sort((a, b) => a.localeCompare(b));
|
|
const funnels = {};
|
|
|
|
for (const file of files) {
|
|
if (!file.endsWith(".json")) continue;
|
|
|
|
const filePath = path.join(funnelsDir, file);
|
|
const raw = await fs.readFile(filePath, "utf8");
|
|
|
|
let parsed;
|
|
try {
|
|
parsed = JSON.parse(raw);
|
|
} catch (error) {
|
|
throw new Error(`Failed to parse ${file}: ${error.message}`);
|
|
}
|
|
|
|
const funnelId = parsed?.meta?.id ?? parsed?.id ?? file.replace(/\.json$/, "");
|
|
|
|
if (!funnelId || typeof funnelId !== "string") {
|
|
throw new Error(
|
|
`Unable to determine funnel id for '${file}'. Ensure the file contains an 'id' or 'meta.id' field.`
|
|
);
|
|
}
|
|
|
|
funnels[funnelId] = parsed;
|
|
}
|
|
|
|
const headerComment = `/**\n * This file is auto-generated by scripts/bake-funnels.mjs.\n * Do not edit this file manually; update the source JSON files instead.\n */`;
|
|
|
|
const recordLiteral = formatFunnelRecord(funnels);
|
|
const contents = `${headerComment}\n\nimport type { FunnelDefinition } from "./types";\n\nexport const BAKED_FUNNELS: Record<string, FunnelDefinition> = ${recordLiteral};\n`;
|
|
|
|
await fs.mkdir(path.dirname(outputFile), { recursive: true });
|
|
await fs.writeFile(outputFile, contents, "utf8");
|
|
|
|
console.log(`Baked ${Object.keys(funnels).length} funnel(s) into ${path.relative(projectRoot, outputFile)}`);
|
|
}
|
|
|
|
bakeFunnels().catch((error) => {
|
|
console.error(error);
|
|
process.exit(1);
|
|
});
|