Files
freedak f7a720204a Update: 将子项目从 submodule 转为完整内容
- 移除 GovAI, nomifun-tauri, 算力盒子 的 submodule 引用
- 添加所有子项目的完整源代码
- 保留原始 .git 为 .git.bak 备份
2026-07-04 19:20:46 +08:00

71 lines
2.8 KiB
JavaScript

#!/usr/bin/env bun
/**
* Seed the dev-channel data dir (…/NomiFun/Nomi-dev) from production
* (…/NomiFun/Nomi), so an auto-isolated dev build can reproduce prod state.
*
* Auto-isolation (NOMI_CHANNEL=dev → `Nomi-dev`) gives a dev build its own empty
* DB. This is the escape hatch for when you need prod's conversations /
* providers / login in dev to reproduce a bug — it restores the "troubleshoot
* one place" convenience that channel isolation otherwise trades away.
*
* SAFETY: close ALL NomiFun instances (the installed app, `bun run serve:web`,
* `nomicore`, and any running dev build) before seeding — copying a live SQLite
* database yields a torn snapshot. Lock and runtime files are never copied.
*
* Usage: bun scripts/seed-dev-from-prod.mjs [--force]
* --force overwrite an existing non-empty Nomi-dev (its state is discarded)
*/
import { cpSync, existsSync, readdirSync, rmSync } from 'node:fs';
import { homedir, platform } from 'node:os';
import { basename, join } from 'node:path';
/** Mirror `nomifun_app::cli::default_data_dir`'s vendor base, per-OS. */
function nomifunBase() {
const home = homedir();
switch (platform()) {
case 'darwin':
return join(home, 'Library', 'Application Support', 'NomiFun');
case 'win32':
return join(process.env.LOCALAPPDATA ?? join(home, 'AppData', 'Local'), 'NomiFun');
default:
return join(process.env.XDG_DATA_HOME ?? join(home, '.local', 'share'), 'NomiFun');
}
}
// Lock + runtime artifacts that must never be copied (mirrors relocate.rs's
// EXCLUDED_ENTRIES intent: the lock lives on the handle, not the file).
const EXCLUDED = new Set(['server.lock', 'server.lock.info', 'port.json', '.relocating.lock', '.relocating']);
const force = process.argv.includes('--force');
const base = nomifunBase();
const prod = join(base, 'Nomi');
const dev = join(base, 'Nomi-dev');
if (!existsSync(prod)) {
console.error(`✗ prod data dir not found: ${prod}`);
console.error(' Nothing to seed from — launch the installed app once to create it.');
process.exit(1);
}
if (existsSync(dev) && readdirSync(dev).length > 0) {
if (!force) {
console.error(`✗ dev data dir already exists and is non-empty: ${dev}`);
console.error(' Re-run with --force to overwrite it (the current dev state is discarded).');
process.exit(1);
}
console.warn(`! --force: removing existing dev data dir ${dev}`);
rmSync(dev, { recursive: true, force: true });
}
console.log('Seeding dev from prod:');
console.log(` ${prod}`);
console.log(`${dev}`);
console.log(' Ensure ALL NomiFun instances are closed; lock/runtime files are skipped.');
cpSync(prod, dev, {
recursive: true,
filter: (src) => !EXCLUDED.has(basename(src)),
});
console.log('✓ done. Run `bun run dev` to launch the dev build on the seeded state.');