Eerste commit voor Helvoirt Gevelreiniging

This commit is contained in:
Joery Disselhof
2026-08-26 13:57:08 +02:00
commit 276dba07a2
225 changed files with 23121 additions and 0 deletions
+109
View File
@@ -0,0 +1,109 @@
/**
* 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_<slug> (systeemkolommen + veldkolommen)
* - rij in _emdash_fields per veld
* - content-rijen in ec_<slug>
*
* 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 <model-bestand> <output.sql>
// 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 <model.mjs> <out.sql>");
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);
}