- cli/lib/rt.ts: the runtime layer on node: modules (spawn / spawnSync with Bun's defaults, exit codes and "Executable not found", which with PATHEXT, sleep, serve, Glob, hasher, gunzip, stdin, SQLite, packageRoot, config imports with a type-stripping fallback for Node 20); every Bun.* use in cli/ goes through it - tools/gen-embedded.ts -> cli/lib/embedded.ts: templates/, cli/shots/*.html and Play's Data safety form embedded (replaces Bun text imports; the bundle and the compiled sidecar carry them), checked fresh by bun run ci - package.json: bin dist/storebound.mjs (Node ESM bundle, tools/build-node.ts, prepack), engines node >=20 - bun run ci: node bundle + node smoke (real node: --version, help, check same as Bun, scan, release plan --help, init, MCP handshake + tool call); Forgejo CI sets up Node 20; tests/node-compat.test.ts guards cli/ - install writes npx MCP commands when run with Node; bin/storebound falls back to Node - docs: npx storebound init (Node 20+) or bunx storebound init
60 lines
3.1 KiB
TypeScript
60 lines
3.1 KiB
TypeScript
#!/usr/bin/env bun
|
|
// Writes cli/lib/embedded.ts: the text files the CLI ships inside its code, so they work on every runtime and in every
|
|
// build without a files folder next to it: the Node bundle (dist/storebound.mjs), the compiled desktop sidecar
|
|
// (`bun build --compile`) and the sources. Bun's `import ... with { type: 'text' }` did this before, but Node cannot
|
|
// run that. Embedded: every file under templates/ (storebound init, web init), the shots pages (cli/shots/*.html,
|
|
// served by shots render / video) and Play's Data safety form export (cli/data/play-data-safety-form.csv).
|
|
// bun tools/gen-embedded.ts write cli/lib/embedded.ts
|
|
// bun tools/gen-embedded.ts --check exit 1 when the file is stale (bun run ci)
|
|
import { readdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
import { join, relative, resolve } from 'node:path';
|
|
|
|
const ROOT = resolve(import.meta.dir, '..');
|
|
export const OUT = join(ROOT, 'cli/lib/embedded.ts');
|
|
|
|
function walk(dir: string): string[] {
|
|
return readdirSync(dir, { withFileTypes: true }).flatMap(e => {
|
|
if (e.name === '.DS_Store') return [];
|
|
const p = join(dir, e.name);
|
|
return e.isDirectory() ? walk(p) : [p];
|
|
}).sort();
|
|
}
|
|
|
|
const rel = (base: string, p: string) => relative(base, p).split('\\').join('/');
|
|
const table = (entries: [string, string][]): string => entries.map(([k, v]) => ` ${JSON.stringify(k)}: ${JSON.stringify(v)},`).join('\n');
|
|
|
|
export function generate(root = ROOT): string {
|
|
const templates = walk(join(root, 'templates')).map(p => [rel(join(root, 'templates'), p), readFileSync(p, 'utf8')] as [string, string]);
|
|
const shots = readdirSync(join(root, 'cli/shots')).filter(f => f.endsWith('.html')).sort().map(f => [f, readFileSync(join(root, 'cli/shots', f), 'utf8')] as [string, string]);
|
|
const form = readFileSync(join(root, 'cli/data/play-data-safety-form.csv'), 'utf8');
|
|
return [
|
|
'// GENERATED by tools/gen-embedded.ts from templates/, cli/shots/*.html and cli/data/play-data-safety-form.csv.',
|
|
'// Do not edit: change those files and run `bun tools/gen-embedded.ts` (bun run ci checks it is fresh).',
|
|
'/* eslint-disable */',
|
|
'',
|
|
'/** Every file under templates/, by its path there (forward slashes). */',
|
|
'export const TEMPLATE_TEXT: Record<string, string> = {',
|
|
table(templates),
|
|
'};',
|
|
'',
|
|
'/** The pages shots render / video load (cli/shots/*.html), by file name. */',
|
|
'export const SHOTS_PAGES: Record<string, string> = {',
|
|
table(shots),
|
|
'};',
|
|
'',
|
|
"/** Play Console's Data safety form export (cli/data/play-data-safety-form.csv). */",
|
|
`export const PLAY_DATA_SAFETY_FORM = ${JSON.stringify(form)};`,
|
|
'',
|
|
].join('\n');
|
|
}
|
|
|
|
if (import.meta.main) {
|
|
const want = generate();
|
|
let have = '';
|
|
try { have = readFileSync(OUT, 'utf8'); } catch { /* missing */ }
|
|
if (process.argv.includes('--check')) {
|
|
if (have !== want) { console.error(`stale: ${rel(ROOT, OUT)} (run bun tools/gen-embedded.ts)`); process.exit(1); }
|
|
console.log(`${rel(ROOT, OUT)}: fresh`);
|
|
} else if (have !== want) { writeFileSync(OUT, want); console.log(`wrote ${rel(ROOT, OUT)}`); }
|
|
else console.log(`${rel(ROOT, OUT)}: unchanged`);
|
|
}
|