larpaso-website/admin/lib/build.js
Pascal Scholz 93178a24e3 Add login-protected admin editor for content and design
Adds a self-service editor at admin.larpaso.de so texts, images, links,
Impressum/Datenschutz, fonts, font sizes and colors can be changed without
a developer. All homepage/legal content moves into content/site.json and
a new content/theme.json drives every CSS color/font/size token; the
Astro pages read from these at build time.

The admin/ service (Node/Express) provides bcrypt+session login with
rate limiting, a schema-driven form UI (including a hex/RGB/alpha color
picker), image upload, and a publish action that runs the Astro build
and republishes into a volume shared with the nginx website container -
so edits go live without redeploying that container.

See DEPLOYMENT_ADMIN.md for the server-side setup steps.
2026-09-21 21:35:09 +02:00

62 lines
1.9 KiB
JavaScript

const { spawn } = require('child_process');
const fs = require('fs');
const path = require('path');
const PROJECT_DIR = process.env.PROJECT_DIR || path.resolve(__dirname, '..', '..');
const DIST_TARGET_DIR = process.env.DIST_TARGET_DIR || '';
function copyDirRecursive(src, dest) {
fs.mkdirSync(dest, { recursive: true });
for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
const srcPath = path.join(src, entry.name);
const destPath = path.join(dest, entry.name);
if (entry.isDirectory()) {
copyDirRecursive(srcPath, destPath);
} else {
fs.copyFileSync(srcPath, destPath);
}
}
}
/** Runs `npm run build` in the Astro project and, if configured, publishes
* the resulting dist/ into the shared volume nginx serves from. */
function runBuild() {
return new Promise((resolve) => {
let child;
try {
child = spawn('npm', ['run', 'build'], { cwd: PROJECT_DIR, shell: true });
} catch (err) {
resolve({ ok: false, output: '', error: `Build konnte nicht gestartet werden: ${err.message}` });
return;
}
let output = '';
child.stdout.on('data', (chunk) => (output += chunk.toString()));
child.stderr.on('data', (chunk) => (output += chunk.toString()));
child.on('error', (err) => {
resolve({ ok: false, output, error: `Build konnte nicht gestartet werden: ${err.message}` });
});
child.on('close', (code) => {
if (code !== 0) {
resolve({ ok: false, output, error: `Build fehlgeschlagen (Exit-Code ${code}).` });
return;
}
if (DIST_TARGET_DIR) {
try {
const distDir = path.join(PROJECT_DIR, 'dist');
copyDirRecursive(distDir, DIST_TARGET_DIR);
} catch (err) {
resolve({ ok: false, output, error: `Build ok, aber Kopieren fehlgeschlagen: ${err.message}` });
return;
}
}
resolve({ ok: true, output });
});
});
}
module.exports = { runBuild };