/** * Re-apply the bundled theme seed. * * POST /_emdash/api/settings/reseed * * The seed embedded in the deployed bundle is the theme's source of truth: * everything it defines is re-applied update-on-conflict (content included), * anything the site added on its own is left alone. Site identity (title, * tagline, URL) belongs to the admin, so those seed settings are skipped. * Used by the hosting platform's roll to re-sync provisioned instances with * their theme after a bundle update. */ import type { APIRoute } from "astro"; import { requirePerm } from "#api/authorize.js"; import { apiError, apiSuccess, handleError } from "#api/error.js"; import { applySeed } from "#seed/apply.js"; import { loadSeed } from "#seed/load.js"; export const prerender = false; const IDENTITY_KEYS = ["title", "tagline", "url"] as const; export const POST: APIRoute = async ({ locals }) => { const { emdash, user } = locals; if (!emdash?.db) return apiError("NOT_CONFIGURED", "EmDash is not initialized", 500); const denied = requirePerm(user, "settings:manage"); if (denied) return denied; try { const seed = await loadSeed(); if (seed.settings) { const settings = { ...seed.settings } as Record; for (const k of IDENTITY_KEYS) delete settings[k]; seed.settings = settings as typeof seed.settings; } const result = await applySeed(emdash.db, seed, { includeContent: true, onConflict: "update", storage: emdash.storage ?? undefined, }); return apiSuccess(result); } catch (error) { return handleError(error, "Failed to re-apply seed", "SEED_ERROR"); } };