55 lines
2.3 KiB
JavaScript
55 lines
2.3 KiB
JavaScript
import { spawnSync } from 'node:child_process';
|
|
import { mkdir, readFile, readdir, rm, writeFile } from 'node:fs/promises';
|
|
import { dirname, join, resolve } from 'node:path';
|
|
import process from 'node:process';
|
|
|
|
const target = process.argv[2];
|
|
if (!['staging', 'production'].includes(target)) {
|
|
console.error('Usage: node scripts/environment-bootstrap-export.mjs <staging|production> [output.json]');
|
|
process.exit(2);
|
|
}
|
|
const outputArgument = process.argv[3];
|
|
const timestamp = new Date().toISOString().replaceAll(':', '-').replace(/\.\d{3}Z$/, 'Z');
|
|
const outputPath = resolve(outputArgument || `./data/backups/shd-${target}-bootstrap-${timestamp}.json`);
|
|
const temporaryBackupPath = `${outputPath}.database.json`;
|
|
const databaseBackup = spawnSync(process.execPath, ['scripts/db-backup.mjs', temporaryBackupPath], {
|
|
cwd: process.cwd(),
|
|
stdio: 'inherit',
|
|
env: process.env
|
|
});
|
|
if (databaseBackup.error) throw databaseBackup.error;
|
|
if (databaseBackup.status !== 0) throw new Error(`Database backup failed; no ${target} bootstrap bundle was created.`);
|
|
|
|
async function collectFiles(directory, pattern) {
|
|
try {
|
|
const names = (await readdir(directory)).filter((name) => pattern.test(name)).sort();
|
|
return await Promise.all(names.map(async (name) => ({
|
|
name,
|
|
contentBase64: (await readFile(join(directory, name))).toString('base64')
|
|
})));
|
|
} catch (error) {
|
|
if (error?.code === 'ENOENT') return [];
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
try {
|
|
const database = JSON.parse(await readFile(temporaryBackupPath, 'utf8'));
|
|
const avatars = await collectFiles(resolve(process.env.TDR_AVATAR_STORAGE_PATH || './data/avatars'), /^[0-9a-f-]{36}\.webp$/i);
|
|
const gameIcons = await collectFiles(resolve(process.env.TDR_GAME_ICON_STORAGE_PATH || './data/game-icons'), /^[a-z_]+-[0-9a-f-]{36}\.webp$/i);
|
|
const bundle = {
|
|
format: 'shd-build-environment-bootstrap',
|
|
version: 1,
|
|
target,
|
|
createdAt: new Date().toISOString(),
|
|
database,
|
|
files: { avatars, gameIcons }
|
|
};
|
|
await mkdir(dirname(outputPath), { recursive: true });
|
|
await writeFile(outputPath, `${JSON.stringify(bundle, null, 2)}\n`, { encoding: 'utf8', flag: 'wx' });
|
|
console.log(`${target} bootstrap bundle includes ${avatars.length} avatars and ${gameIcons.length} game-data icons.`);
|
|
console.log(`Bootstrap bundle: ${outputPath}`);
|
|
} finally {
|
|
await rm(temporaryBackupPath, { force: true });
|
|
}
|