/
githubmirror
/
strapi
Обзор
Документация
Войти
/
githubmirror
/
strapi
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
develop
examples/complex/scripts/db-sqlite.ts
164 строки
5 KB
Ben Irvin
test(migration): version migration testing framework (#26060)
06 авг 2026, 15:39
Не верифицирован
06 авг 2026, 15:39
ac0c928
Код
Авторство
О чём код?
#!/usr/bin/env node const fs = require('fs'); const path = require('path'); const { assertSafeSnapshotName } = require('./db-utils'); const SCRIPT_DIR = __dirname; const COMPLEX_DIR = path.resolve(SCRIPT_DIR, '..'); const MONOREPO_ROOT = path.resolve(COMPLEX_DIR, '../..'); const V4_PROJECT_DIR = process.env.V4_OUTSIDE_DIR ? path.resolve(process.cwd(), process.env.V4_OUTSIDE_DIR) : path.resolve(MONOREPO_ROOT, '..', 'complex-v4'); /** * SQLite lives entirely as files; no container and no compose runtime. * * The v4 project stores its database under V4_PROJECT_DIR/.tmp/data.db. * v5 reads/writes the same file so snapshots are interchangeable. */ const DATABASE_FILENAME = process.env.SQLITE_DATABASE_FILENAME || process.env.DATABASE_FILENAME || path.join(V4_PROJECT_DIR, '.tmp', 'data.db'); const SNAPSHOTS_DIR = path.join(COMPLEX_DIR, 'snapshots'); const command = process.argv[2]; const snapshotName = process.argv[3]; function ensureSnapshotsDir() { if (!fs.existsSync(SNAPSHOTS_DIR)) { fs.mkdirSync(SNAPSHOTS_DIR, { recursive: true }); } } function snapshotPath(name) { return path.join(SNAPSHOTS_DIR, `sqlite-${name}.db`); } function requireBetterSqlite() { try { // eslint-disable-next-line global-require return require('better-sqlite3'); } catch (error) { throw new Error( 'better-sqlite3 is required for sqlite operations. It is a peer dep of @strapi/strapi and should be present via workspace hoisting; if not, install it in examples/complex.' ); } } switch (command) { case 'start': // No-op: sqlite is file-based. console.log('✅ SQLite is file-based; nothing to start.'); console.log(` Database file: ${DATABASE_FILENAME}`); break; case 'stop': // No-op: sqlite is file-based. console.log('✅ SQLite is file-based; nothing to stop.'); break; case 'snapshot': { if (!snapshotName) { console.error('Error: Snapshot name is required'); console.error('Usage: node --import tsx db-sqlite.ts snapshot <name>'); process.exit(1); } assertSafeSnapshotName(snapshotName); if (!fs.existsSync(DATABASE_FILENAME)) { console.error(`Error: Database file not found: ${DATABASE_FILENAME}`); console.error('Run the v4 app with `yarn develop:sqlite` and seed first to create it.'); process.exit(1); } ensureSnapshotsDir(); const target = snapshotPath(snapshotName); fs.copyFileSync(DATABASE_FILENAME, target); console.log(`✅ Snapshot created: ${target}`); break; } case 'restore': { if (!snapshotName) { console.error('Error: Snapshot name is required'); console.error('Usage: node --import tsx db-sqlite.ts restore <name>'); process.exit(1); } assertSafeSnapshotName(snapshotName); const source = snapshotPath(snapshotName); if (!fs.existsSync(source)) { console.error(`Error: Snapshot not found: ${source}`); process.exit(1); } // Remove walk-ahead / shared-memory sidecars so they don't conflict with the // restored file's transaction state. for (const suffix of ['', '-wal', '-shm', '-journal']) { const sidecar = `${DATABASE_FILENAME}${suffix}`; if (fs.existsSync(sidecar)) { try { fs.unlinkSync(sidecar); } catch { /* best-effort */ } } } fs.mkdirSync(path.dirname(DATABASE_FILENAME), { recursive: true }); fs.copyFileSync(source, DATABASE_FILENAME); console.log(`✅ Snapshot restored: ${snapshotName} -> ${DATABASE_FILENAME}`); break; } case 'wipe': for (const suffix of ['', '-wal', '-shm', '-journal']) { const f = `${DATABASE_FILENAME}${suffix}`; if (fs.existsSync(f)) { fs.unlinkSync(f); } } console.log(`✅ SQLite database file removed: ${DATABASE_FILENAME}`); break; case 'check': { if (!fs.existsSync(DATABASE_FILENAME)) { console.log('📊 No database file found (empty or wiped)'); break; } const Database = requireBetterSqlite(); const db = new Database(DATABASE_FILENAME, { readonly: true, fileMustExist: true }); try { const tables = db .prepare( "SELECT name FROM sqlite_master WHERE type = 'table' AND name NOT LIKE 'sqlite_%' ORDER BY name" ) .all(); if (tables.length === 0) { console.log('📊 No tables found (database is empty or wiped)'); break; } console.log('📊 Database Tables (row counts):\n'); console.log('Table Name | Row Count'); console.log('------------------------------------|----------'); for (const { name } of tables) { // SQLite doesn't keep approximate row stats; use exact COUNT(*) here. const { c } = db.prepare(`SELECT COUNT(*) AS c FROM "${name}"`).get(); const padded = name.padEnd(35); console.log(`${padded} | ${c}`); } } finally { db.close(); } break; } default: console.error('Error: Unknown command'); console.error( 'Usage: node --import tsx db-sqlite.ts <start|stop|snapshot|restore|wipe|check> [name]' ); process.exit(1); }