npm run dev now runs scripts/dev-env.ts first, which creates .dev/site.env with a known dev password and a random session secret, so a fresh clone serves a working admin without anyone hand-building a hash. Adds .vscode launch configurations and tasks for the dev server, one test file, and check-site, and brings scripts/ under typecheck, which it had been missing.
58 lines
1.7 KiB
TypeScript
58 lines
1.7 KiB
TypeScript
/**
|
|
* Prepares a local development Site so `npm run dev` has a working admin
|
|
* without anyone hand-building a password hash.
|
|
*
|
|
* Development only: the file it writes is gitignored, holds a fixed well-known
|
|
* password, and the dev server runs with SECURE_COOKIES=false over http.
|
|
*/
|
|
|
|
import { mkdir, readdir, readFile, writeFile } from 'node:fs/promises';
|
|
import { randomBytes } from 'node:crypto';
|
|
import path from 'node:path';
|
|
import { hashPassword } from '../src/auth.ts';
|
|
|
|
const DEV_PASSWORD = process.env['DEV_ADMIN_PASSWORD'] ?? 'menu-dev-password';
|
|
const root = path.resolve(process.env['MENU_ROOT'] ?? '.dev');
|
|
const envFile = path.join(root, 'site.env');
|
|
|
|
async function exists(target: string): Promise<boolean> {
|
|
try {
|
|
await readFile(target);
|
|
return true;
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
async function hasContent(dir: string): Promise<boolean> {
|
|
try {
|
|
return (await readdir(dir)).length > 0;
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (await exists(envFile)) {
|
|
console.log(`${envFile} already exists — using it (delete the file to reset the dev password)`);
|
|
} else {
|
|
await mkdir(root, { recursive: true });
|
|
const hash = await hashPassword(DEV_PASSWORD);
|
|
const secret = randomBytes(32).toString('base64url');
|
|
await writeFile(
|
|
envFile,
|
|
[
|
|
'# Development only, created by scripts/dev-env.ts. Gitignored.',
|
|
`ADMIN_PASSWORD_HASH=${hash}`,
|
|
`SESSION_SECRET=${secret}`,
|
|
'',
|
|
].join('\n'),
|
|
{ mode: 0o600 },
|
|
);
|
|
console.log(`wrote ${envFile}`);
|
|
console.log(` admin password: ${DEV_PASSWORD} (override with DEV_ADMIN_PASSWORD=...)`);
|
|
}
|
|
|
|
if (!(await hasContent(path.join(root, 'data', 'published')))) {
|
|
console.log('no published menus yet — run `npm run seed` for placeholder ones');
|
|
}
|