#!/usr/bin/env node import fs from "node:fs"; import path from "node:path"; import { fileURLToPath } from "node:url"; const __dirname = path.dirname(fileURLToPath(import.meta.url)); const root = path.resolve(__dirname, ".."); const sourceFile = path.join(root, "src", "content", "site-config.json"); const defaultEndpoint = "http://localhost:1337/graphql"; const endpoint = process.env.STRAPI_GRAPHQL_URL ?? process.env.PUBLIC_GRAPHQL_URL ?? defaultEndpoint; const token = process.env.STRAPI_TOKEN ?? process.env.STRAPI_API_TOKEN ?? process.env.AUTH_TOKEN; const isDryRun = process.argv.includes("--dry-run"); function readSource() { if (!fs.existsSync(sourceFile)) { throw new Error(`Missing source file: ${path.relative(root, sourceFile)}`); } return JSON.parse(fs.readFileSync(sourceFile, "utf8")); } function buildInput(source) { const contacts = Array.isArray(source.contacts) ? source.contacts : []; const input = { title: source.title, description: source.description ?? null, contacts: contacts.map((contact) => ({ type: contact.type, value: contact.value, displayValue: contact.displayValue, })), }; // privacyPolicy / termsOfUse are relations (single types) referenced by id. // They are seeded separately; only forward them when an id is provided. if (source.privacyPolicy?.id) input.privacyPolicy = source.privacyPolicy.id; if (source.termsOfUse?.id) input.termsOfUse = source.termsOfUse.id; return input; } async function gql(query, variables = {}) { const headers = { "Content-Type": "application/json", Accept: "application/graphql-response+json, application/json", }; if (token) headers.Authorization = `Bearer ${token}`; const response = await fetch(endpoint, { method: "POST", headers, body: JSON.stringify({ query, variables }), }); if (!response.ok) { throw new Error(`GraphQL HTTP ${response.status}: ${response.statusText}`); } const payload = await response.json(); if (payload.errors?.length) { const messages = payload.errors.map((err) => err.message).join("; "); throw new Error(`GraphQL error: ${messages}`); } return payload.data; } async function updateSiteConfig(input) { const mutation = ` mutation UpdateSiteConfig($data: SiteConfigInput!) { updateSiteConfig(data: $data) { title contacts { type value } } } `; const data = await gql(mutation, { data: input }); return data?.updateSiteConfig; } async function main() { console.log(`Seeding site config to ${endpoint}${isDryRun ? " (dry-run)" : ""}`); if (!token) { console.warn("No STRAPI token provided. If endpoint is protected, set STRAPI_TOKEN."); } const source = readSource(); const input = buildInput(source); if (isDryRun) { console.log(JSON.stringify(input, null, 2)); console.log(`DRY-RUN UPDATE siteConfig (${input.contacts.length} contacts)`); return; } const updated = await updateSiteConfig(input); console.log( `UPDATE siteConfig -> ${updated.title} (${updated.contacts.length} contacts)` ); } main().catch((error) => { console.error(error); process.exit(1); });