import { readFile } from 'node:fs/promises'; import path from 'node:path'; import process from 'node:process'; import { fileURLToPath, pathToFileURL } from 'node:url'; const projectRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..'); async function readJson(relativePath) { return JSON.parse(await readFile(path.join(projectRoot, relativePath), 'utf8')); } function publicationTime() { const configured = process.env.PAGES_PUBLICATION_TIME; const value = configured ? Date.parse(configured) : Date.now(); if (!Number.isFinite(value)) throw new Error('PAGES_PUBLICATION_TIME must be a valid ISO-8601 date.'); return value; } const now = publicationTime(); const policy = await readJson('pages/publication-policy.json'); const cards = await readJson('src/lib/data/cards-summary.json'); const boards = await readJson('src/lib/data/boards-summary.json'); const memory = await readJson('src/lib/data/memory-summary.json'); const charts = await readJson('src/lib/data/exact-chart-catalog.json'); const { events } = await import(pathToFileURL(path.join(projectRoot, 'src/lib/data/events.ts')).href); const approvedVersion = policy.approvedMasterDataVersion; const versions = new Map([ ['cards-summary.json', cards.masterDataVersion], ['boards-summary.json', boards.masterDataVersion], ['memory-summary.json', memory.masterDataVersion] ]); const mismatchedVersions = [...versions].filter(([, version]) => version !== approvedVersion); if (mismatchedVersions.length > 0) { throw new Error(`Unapproved master data: ${mismatchedVersions.map(([file, version]) => `${file}=${version}`).join(', ')}`); } const approvedNotBefore = Date.parse(policy.approvedNotBefore); if (!Number.isFinite(approvedNotBefore) || now < approvedNotBefore) { throw new Error(`The approved master data cannot be published before ${policy.approvedNotBefore}.`); } const unreleasedCharts = charts.charts.filter((chart) => !Number.isFinite(chart.releaseTime) || chart.releaseTime > now); if (unreleasedCharts.length > 0) { throw new Error(`Pages build contains ${unreleasedCharts.length} unreleased or undated charts: ${unreleasedCharts.map((chart) => `${chart.songId}/${chart.difficulty}`).join(', ')}`); } const unreleasedEvents = events.filter((event) => { const startsAt = Date.parse(event.startsAt); return !Number.isFinite(startsAt) || startsAt > now; }); if (unreleasedEvents.length > 0) { throw new Error(`Pages build contains unreleased or undated events: ${unreleasedEvents.map((event) => event.id).join(', ')}`); } process.stdout.write(`Pages public-data gate passed at ${new Date(now).toISOString()}.\n`); process.stdout.write(`Approved master data: ${approvedVersion}; cards=${cards.cards.length}; charts=${charts.charts.length}; events=${events.length}.\n`);