78 lines
2.3 KiB
JavaScript
78 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 outputArgument = process.argv[2];
|
|
const timestamp = new Date()
|
|
.toISOString()
|
|
.replaceAll(':', '-')
|
|
.replace(/\.\d{3}Z$/, 'Z');
|
|
const outputPath = resolve(
|
|
outputArgument || `./data/backups/shd-stage-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 staging 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-stage-bootstrap',
|
|
version: 1,
|
|
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(
|
|
`Staging bootstrap bundle includes ${avatars.length} avatars and ${gameIcons.length} game-data icons.`,
|
|
);
|
|
console.log(`Bootstrap bundle: ${outputPath}`);
|
|
} finally {
|
|
await rm(temporaryBackupPath, { force: true });
|
|
}
|