import { DatabaseSync } from "node:sqlite"; const opts = `'[{"key":"A"},{"key":"B"}]'`; const base = `CREATE TABLE decisions (seq INTEGER PRIMARY KEY AUTOINCREMENT, id TEXT NOT NULL UNIQUE, rec TEXT NOT NULL) STRICT; CREATE TRIGGER d_no_update BEFORE UPDATE ON decisions BEGIN SELECT RAISE(ABORT,'append-only'); END; CREATE TRIGGER d_no_delete BEFORE DELETE ON decisions BEGIN SELECT RAISE(ABORT,'append-only'); END; INSERT INTO decisions (id,rec) VALUES ('d-1','B');`; const guard = `CREATE TRIGGER d_no_replace BEFORE INSERT ON decisions WHEN EXISTS (SELECT 1 FROM decisions WHERE seq = NEW.seq OR id = NEW.id) BEGIN SELECT RAISE(ABORT,'append-only: key exists'); END;`; for (const [label, extra, pragma] of [["triggers only", "", false], ["recursive_triggers on", "", true], ["insert guard", guard, false]]) { const db = new DatabaseSync(":memory:"); if (pragma) db.exec("PRAGMA recursive_triggers = ON"); db.exec(base + extra); for (const sql of ["INSERT OR REPLACE INTO decisions (id,rec) VALUES ('d-1','A')", "REPLACE INTO decisions (seq,id,rec) VALUES (1,'d-x','A')"]) { try { db.exec(sql); console.log(label, "| ALLOWED:", sql.slice(0, 30), "->", JSON.stringify(db.prepare("SELECT seq,id,rec FROM decisions").all())); } catch (e) { console.log(label, "| refused:", sql.slice(0, 30), "->", e.message); } } }