#!/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 = ${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); });