Ragdoll POS 雙 SQLite 資料庫架構完整知識庫。涵蓋 Mutable / Readonly 雙資料庫設計、 Drizzle ORM v1 + node:sqlite 設定、Schema 定義慣例與型別系統、Migration 產生與執行機制、 Operations 層五大操作(list / insert / update / remove / replace)、 以及 GraphQL Filter → Drizzle WHERE 條件轉換器。 以下情況必須參考此文件再動手: - 新增或修改 Drizzle schema(`database/schema/` 目錄) - 產生或執行 migration(`db:generate` / `db:push` / `db:migrate`) - 修改資料庫初始化流程(`database/index.ts`、client 檔案) - 修改 Operations 層的 CRUD 操作邏輯 - 修改 GraphQL Filter → WHERE 條件轉換邏輯 - 新增資料表或子表(需了解 TABLE_MAP 自動推導機制) - 處理 Worker 線程的資料庫存取 - 理解 `{ body, lines }` 資料格式的轉換流程 - 處理 .gz 離線資料庫版本管理 - 排查 migration 相容性問題(舊版 DB 升級)
程式碼位置:electron/main/database/
Ragdoll 採用雙 SQLite 資料庫架構,透過 Drizzle ORM v1 + node:sqlite 驅動,
所有資料以 { body, lines } 統一格式在 IPC / Next.js / Worker 之間流通。
┌─────────────────────────────────────────────────────────┐
│ Electron Main Process │
│ │
│ ┌──────────────────┐ ┌───────────────────────────┐ │
│ │ Mutable DB │ │ Readonly DB │ │
│ │ offline-mutable │ │ offline-readonly │ │
│ │ ─────────────── │ │ ─────────────────────── │ │
│ │ offline_sale │ │ item, pos_promotion ... │ │
│ │ issue_invoice │ │ (19 張遠端主檔快取表) │ │
│ │ ─────────────── │ │ ─────────────────────── │ │
│ │ WAL + FULL sync │ │ WAL + 64MB cache │ │
│ │ 不可刪除重建 │ │ 可刪除重建 + 全量同步 │ │
│ └──────────────────┘ └───────────────────────────┘ │
│ │ │ │
│ └────────┬────────────────┘ │
│ ▼ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ Operations Layer (dbOps) │ │
│ │ list / insert / update / remove / replace │ │
│ │ ─────────────────────────────────────────────── │ │
│ │ 動態表名路由 · { body, lines } 轉換 │ │
│ │ 自動 DB 選擇 · 子表級聯刪除 · 批次同步 │ │
│ └──────────────────────────────────────────────────┘ │
│ │ │
│ ┌────────────┼────────────┐ │
│ ▼ ▼ ▼ │
│ IPC Handler Worker Sync Layer │
└─────────────────────────────────────────────────────────┘
initialDatabase() 三步初始化流程.gz 離線資料庫版本管理機制(檔名解析、版本比對、解壓覆蓋)casing: 'snake_case' 自動轉換規則drizzle.config.mutable.ts / drizzle.config.readonly.ts 配置createReadonlyDrizzle() 建立獨立實例_lines_ 規則)commonColumns() 共用欄位(timestamps / lineId)與 $defaultFn 機制DatabaseRecord<B, L>、ToInsert<T>、NullableToOptional<T>TABLE_MAP 從 defineRelations 自動推導主表 ↔ 子表映射table-registry 表格分類(readonly / mutable / all)toRecord() 扁平結果 → { body, lines } 格式轉換{timestamp}_{name}/migration.sql + snapshot.json)drizzle-kit generate / push / check 指令用途與差異db:generate / db:push / db:check / db:migrate / db:reset:dev)ensureDrizzleMigrationTable() 舊版 DB 向後相容機制list / findOne / count:relational query + WHERE 建構 + 分頁insert:主表 + 子表交易寫入 + FK 自動填充update:body 更新 + lines upsert 回退邏輯remove:跨表 FK 探測 + 顯式級聯刪除(不用 ON DELETE CASCADE 的原因)replace:兩種同步模式(全量替換 vs 增量 upsert)+ 批次進度回調sanitizeValues():node:sqlite 型別轉換(undefined→null、bool→0/1、Date→timestamp)$in / $nin / $gte / $gt / $lte / $lt / $like)$in 包含 null 時的特殊處理(OR notExists)WhereFilter<R> 型別定義