/** * Self-test for prisma-safety-check.mjs. * Verifies each DROP pattern fires and the safe-SQL path passes. * Run with: node scripts/test-safety-check.mjs */ const DROP_PATTERNS = [ /^\s*ALTER TABLE\s+\S+\s+DROP COLUMN\s+/im, /^\s*DROP TABLE\s+/im, /^\s*DROP CONSTRAINT\s+/im, /^\s*ALTER TABLE\s+\S+\s+DROP CONSTRAINT\s+/im, /^\s*ALTER COLUMN\s+\S+\s+DROP\s+/im, /^\s*DROP INDEX\s+/im, ]; function matches(sql) { return DROP_PATTERNS.some((p) => p.test(sql)); } const cases = [ // should block { sql: "ALTER TABLE \"User\" DROP COLUMN email;", expect: true, label: "DROP COLUMN" }, { sql: "DROP TABLE \"OldTable\";", expect: true, label: "DROP TABLE" }, { sql: "DROP CONSTRAINT fk_user_org;", expect: true, label: "DROP CONSTRAINT (bare)" }, { sql: "ALTER TABLE \"Brand\" DROP CONSTRAINT chk_plan;", expect: true, label: "DROP CONSTRAINT (alter)" }, { sql: "ALTER COLUMN status DROP NOT NULL;", expect: true, label: "ALTER COLUMN DROP" }, { sql: "DROP INDEX \"SiteEvent_sessionId_timestamp_idx\";",expect: true, label: "DROP INDEX (the incident)" }, { sql: "DROP INDEX IF EXISTS \"some_idx\";", expect: true, label: "DROP INDEX IF EXISTS" }, // should pass { sql: "CREATE INDEX idx ON \"SiteEvent\" (\"sessionId\");", expect: false, label: "CREATE INDEX (safe)" }, { sql: "ALTER TABLE \"Brand\" ADD COLUMN plan TEXT;", expect: false, label: "ADD COLUMN (safe)" }, { sql: "CREATE TABLE \"NewModel\" (id TEXT PRIMARY KEY);", expect: false, label: "CREATE TABLE (safe)" }, ]; let passed = 0; let failed = 0; for (const c of cases) { const got = matches(c.sql); const ok = got === c.expect; console.log(`${ok ? "PASS" : "FAIL"} [${c.label}]`); if (!ok) { console.log(` sql: ${c.sql}`); console.log(` expected: ${c.expect}, got: ${got}`); failed++; } else { passed++; } } console.log(`\n${passed} passed, ${failed} failed`); process.exit(failed > 0 ? 1 : 0);