/** * Generator: zet een content-model om in D1-SQL die nieuwe emdash-collecties aanmaakt * op een AL-geseede database, door de exacte tabelstructuur van emdash te spiegelen * (overgenomen uit de echte `ec_paginas`-DDL). Per collectie: * - rij in _emdash_collections * - CREATE TABLE ec_ (systeemkolommen + veldkolommen) * - rij in _emdash_fields per veld * - content-rijen in ec_ * * Bewust GEEN "search"/FTS (geen searchable velden) → geen FTS-tabellen nodig, dus * de gegenereerde SQL blijft veilig en compleet. Run: `node scripts/gen-cms-sql.mjs`. */ import { ulid } from "ulidx"; import { writeFileSync, mkdirSync } from "node:fs"; import { pathToFileURL } from "node:url"; import { resolve } from "node:path"; const TYPE_COL = { string: "TEXT", text: "TEXT", select: "TEXT", datetime: "TEXT", slug: "TEXT", image: "TEXT", file: "TEXT", reference: "TEXT", number: "REAL", integer: "INTEGER", boolean: "INTEGER", portableText: "JSON", json: "JSON", multiSelect: "JSON", repeater: "JSON", }; // Systeemkolommen exact zoals emdash ze in ec_paginas aanmaakt. const SYSTEM_COLS = `"id" text primary key, "slug" text, "status" text default 'draft', ` + `"author_id" text, "primary_byline_id" text, ` + `"created_at" text default (datetime('now')), "updated_at" text default (datetime('now')), ` + `"published_at" text, "scheduled_at" text, "deleted_at" text, "version" integer default 1, ` + `"live_revision_id" text references "revisions" ("id"), ` + `"draft_revision_id" text references "revisions" ("id"), ` + `"locale" text default 'en' not null, "translation_group" text`; const q = (s) => "'" + String(s).replace(/'/g, "''") + "'"; function val(type, v) { if (v === null || v === undefined) return "NULL"; const col = TYPE_COL[type] || "TEXT"; if (col === "JSON") return q(JSON.stringify(v)); if (col === "INTEGER") return type === "boolean" ? (v ? "1" : "0") : String(parseInt(v, 10)); if (col === "REAL") return String(Number(v)); if ((type === "image" || type === "file") && typeof v === "object") return q(JSON.stringify(v)); return q(v); } export function generate(model) { const out = ["-- Auto-gegenereerd door scripts/gen-cms-sql.mjs — NIET met de hand bewerken."]; for (const c of model) { const collId = ulid(); const supports = JSON.stringify(c.supports ?? ["drafts", "revisions"]); out.push(`\n-- ===== collectie: ${c.slug} (${c.label}) =====`); out.push( `INSERT INTO _emdash_collections (id, slug, label, label_singular, supports, source, has_seo) ` + `VALUES (${q(collId)}, ${q(c.slug)}, ${q(c.label)}, ${q(c.labelSingular ?? c.label)}, ${q(supports)}, 'seed', 0);` ); const fieldCols = c.fields .map((f) => { const col = TYPE_COL[f.type] || "TEXT"; const nn = f.required && col === "TEXT" ? " NOT NULL DEFAULT ''" : ""; return `"${f.slug}" ${col}${nn}`; }) .join(", "); out.push( `CREATE TABLE "ec_${c.slug}" (${SYSTEM_COLS}, ${fieldCols}, ` + `constraint "ec_${c.slug}_slug_locale_unique" unique ("slug", "locale"));` ); c.fields.forEach((f, i) => { const col = TYPE_COL[f.type] || "TEXT"; // Repeater-velden krijgen hun rij-definitie (subFields) mee in de validation-kolom. const validation = f.subFields ? JSON.stringify({ subFields: f.subFields, minItems: f.minItems ?? 0, maxItems: f.maxItems ?? 20 }) : null; const cols = "id, collection_id, slug, label, type, column_type, required, sort_order, searchable, translatable" + (validation ? ", validation" : ""); const vals = `${q(ulid())}, ${q(collId)}, ${q(f.slug)}, ${q(f.label)}, ${q(f.type)}, ${q(col)}, ${f.required ? 1 : 0}, ${i}, 0, 1` + (validation ? `, ${q(validation)}` : ""); out.push(`INSERT INTO _emdash_fields (${cols}) VALUES (${vals});`); }); for (const entry of c.content ?? []) { const cols = [`"id"`, `"slug"`, `"status"`, `"locale"`]; const vals = [q(ulid()), q(entry.slug), q(entry.status ?? "published"), q("en")]; for (const f of c.fields) { if (entry.data && f.slug in entry.data) { cols.push(`"${f.slug}"`); vals.push(val(f.type, entry.data[f.slug])); } } out.push(`INSERT INTO "ec_${c.slug}" (${cols.join(", ")}) VALUES (${vals.join(", ")});`); } } return out.join("\n") + "\n"; } // ---- Run: genereer per wave een .sql-bestand ---- // Gebruik: node scripts/gen-cms-sql.mjs // Alleen uitvoeren wanneer dit script direct wordt aangeroepen (niet bij import van `generate`). const isMain = import.meta.url === pathToFileURL(process.argv[1] ?? "").href; if (isMain) { const [, , modelPath, outName] = process.argv; if (!modelPath || !outName) { console.error("usage: node scripts/gen-cms-sql.mjs "); process.exit(1); } const mod = await import(pathToFileURL(resolve(modelPath)).href); const model = Object.values(mod).find((v) => Array.isArray(v)); mkdirSync("migrations", { recursive: true }); writeFileSync(`migrations/${outName}`, generate(model), "utf8"); console.log("geschreven: migrations/" + outName); }