Files
minibits_wallet/__tests__/dbSchema.test.ts
T
minibits-cashandClaude Opus 4.8 63d89bb6f8 Split SQLite monolith into focused db/ modules
Pure reorganization behind the existing Database facade — no behavior change.
The 1646-line services/sqlite.ts is broken into services/db/:

  errors.ts          dbError() helper
  connection.ts      op-sqlite adapter (from previous commit)
  schema.ts          table column definitions (single source of truth)
  migrations.ts      _dbVersion, getDatabaseVersion, ordered migration registry
  mappers.ts         transaction row normalizers
  instance.ts        _db singleton, getInstance, schema bootstrap, cleanAll
  transactionsRepo.ts / proofsRepo.ts / reservationsRepo.ts
  index.ts           assembles the Database facade, re-exports public types

services/sqlite.ts is now a thin `export * from './db'` barrel so every
existing import path (services, services/sqlite, ../../sqlite) resolves
unchanged. The Database.* contract and the exported types
(TransactionSearchFilters, LockedProofSnapshot, ReservationRow,
ReservationTransactionUpdate) are preserved.

Notable refactors folded in:
  - schema single source of truth: proofs/reservations columns are defined
    once; first-run CREATE and the v25 rebuild / v26 add are generated from
    them so they cannot drift. PROOFS_COLUMN_NAMES (drives the v25 copy) is
    tested to stay in sync with the table.
  - migration if-chain replaced by an ordered MIGRATIONS registry; adding a
    migration is now a one-line append.
  - updateStatusesAsync and expireAllAfterRecovery now use getInstance()
    instead of reaching for the module-global _db directly (the only two
    functions that did; behavior-equivalent, more robust before init).

New: __tests__/dbSchema.test.ts validates the generated DDL against node:sqlite.
Tests: 125/125 pass (was 121 + 4 new), no regressions.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 21:46:15 +02:00

65 lines
2.1 KiB
TypeScript

/**
* Schema generation tests (Tier 2 module split).
*
* Validates that the generated DDL in services/db/schema.ts parses under real
* SQLite and produces the expected table columns. schema.ts only imports a TYPE
* from ./connection (elided at runtime), so it loads here without the native
* op-sqlite module.
*
* @jest-environment node
*/
import {DatabaseSync} from 'node:sqlite'
import {
createSchemaQueries,
createTable,
PROOFS_COLUMNS,
PROOFS_COLUMN_NAMES,
} from '../src/services/db/schema'
const columnNames = (db: DatabaseSync, table: string): string[] =>
db.prepare(`PRAGMA table_info(${table})`).all().map((r: any) => r.name as string)
describe('db schema generation', () => {
it('applies createSchemaQueries without error and creates all tables', () => {
const db = new DatabaseSync(':memory:')
for (const [sql] of createSchemaQueries) db.exec(sql)
const tables = db
.prepare(`SELECT name FROM sqlite_master WHERE type='table' ORDER BY name`)
.all()
.map((r: any) => r.name)
expect(tables).toEqual(
expect.arrayContaining(['transactions', 'proofs', 'dbversion', 'reservations']),
)
db.close()
})
it('creates the proofs table with the canonical columns', () => {
const db = new DatabaseSync(':memory:')
for (const [sql] of createSchemaQueries) db.exec(sql)
expect(columnNames(db, 'proofs')).toEqual([
'id', 'amount', 'secret', 'C', 'dleq_r', 'dleq_s', 'dleq_e',
'unit', 'tId', 'mintUrl', 'state', 'updatedAt',
])
db.close()
})
it('PROOFS_COLUMN_NAMES lists every proofs column in declaration order', () => {
const db = new DatabaseSync(':memory:')
db.exec(createTable('p', PROOFS_COLUMNS, false))
const declared = columnNames(db, 'p').join(', ')
expect(PROOFS_COLUMN_NAMES).toBe(declared)
db.close()
})
it('builds an identical proofs table under a different name (v25 rebuild path)', () => {
const db = new DatabaseSync(':memory:')
db.exec(createTable('proofs', PROOFS_COLUMNS))
db.exec(createTable('proofs_v25', PROOFS_COLUMNS, false))
expect(columnNames(db, 'proofs_v25')).toEqual(columnNames(db, 'proofs'))
db.close()
})
})