ddlforge 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +326 -0
  3. package/dist/bin/ddlforge.d.ts +6 -0
  4. package/dist/bin/ddlforge.d.ts.map +1 -0
  5. package/dist/bin/ddlforge.js +14 -0
  6. package/dist/bin/ddlforge.js.map +1 -0
  7. package/dist/src/cli.d.ts +21 -0
  8. package/dist/src/cli.d.ts.map +1 -0
  9. package/dist/src/cli.js +262 -0
  10. package/dist/src/cli.js.map +1 -0
  11. package/dist/src/engine/analyzer.d.ts +30 -0
  12. package/dist/src/engine/analyzer.d.ts.map +1 -0
  13. package/dist/src/engine/analyzer.js +76 -0
  14. package/dist/src/engine/analyzer.js.map +1 -0
  15. package/dist/src/engine/locks.d.ts +26 -0
  16. package/dist/src/engine/locks.d.ts.map +1 -0
  17. package/dist/src/engine/locks.js +136 -0
  18. package/dist/src/engine/locks.js.map +1 -0
  19. package/dist/src/index.d.ts +12 -0
  20. package/dist/src/index.d.ts.map +1 -0
  21. package/dist/src/index.js +17 -0
  22. package/dist/src/index.js.map +1 -0
  23. package/dist/src/lexer/sqlTokenizer.d.ts +40 -0
  24. package/dist/src/lexer/sqlTokenizer.d.ts.map +1 -0
  25. package/dist/src/lexer/sqlTokenizer.js +494 -0
  26. package/dist/src/lexer/sqlTokenizer.js.map +1 -0
  27. package/dist/src/lexer/tokens.d.ts +35 -0
  28. package/dist/src/lexer/tokens.d.ts.map +1 -0
  29. package/dist/src/lexer/tokens.js +81 -0
  30. package/dist/src/lexer/tokens.js.map +1 -0
  31. package/dist/src/reporters/index.d.ts +7 -0
  32. package/dist/src/reporters/index.d.ts.map +1 -0
  33. package/dist/src/reporters/index.js +7 -0
  34. package/dist/src/reporters/index.js.map +1 -0
  35. package/dist/src/reporters/json.d.ts +20 -0
  36. package/dist/src/reporters/json.d.ts.map +1 -0
  37. package/dist/src/reporters/json.js +35 -0
  38. package/dist/src/reporters/json.js.map +1 -0
  39. package/dist/src/reporters/markdown.d.ts +6 -0
  40. package/dist/src/reporters/markdown.d.ts.map +1 -0
  41. package/dist/src/reporters/markdown.js +70 -0
  42. package/dist/src/reporters/markdown.js.map +1 -0
  43. package/dist/src/reporters/terminal.d.ts +10 -0
  44. package/dist/src/reporters/terminal.d.ts.map +1 -0
  45. package/dist/src/reporters/terminal.js +109 -0
  46. package/dist/src/reporters/terminal.js.map +1 -0
  47. package/dist/src/rules/addColumnNotNull.d.ts +9 -0
  48. package/dist/src/rules/addColumnNotNull.d.ts.map +1 -0
  49. package/dist/src/rules/addColumnNotNull.js +131 -0
  50. package/dist/src/rules/addColumnNotNull.js.map +1 -0
  51. package/dist/src/rules/foreignKeyNotValid.d.ts +9 -0
  52. package/dist/src/rules/foreignKeyNotValid.d.ts.map +1 -0
  53. package/dist/src/rules/foreignKeyNotValid.js +119 -0
  54. package/dist/src/rules/foreignKeyNotValid.js.map +1 -0
  55. package/dist/src/rules/index.d.ts +14 -0
  56. package/dist/src/rules/index.d.ts.map +1 -0
  57. package/dist/src/rules/index.js +28 -0
  58. package/dist/src/rules/index.js.map +1 -0
  59. package/dist/src/rules/indexConcurrently.d.ts +9 -0
  60. package/dist/src/rules/indexConcurrently.d.ts.map +1 -0
  61. package/dist/src/rules/indexConcurrently.js +92 -0
  62. package/dist/src/rules/indexConcurrently.js.map +1 -0
  63. package/dist/src/rules/prismaRenameDropAdd.d.ts +11 -0
  64. package/dist/src/rules/prismaRenameDropAdd.d.ts.map +1 -0
  65. package/dist/src/rules/prismaRenameDropAdd.js +144 -0
  66. package/dist/src/rules/prismaRenameDropAdd.js.map +1 -0
  67. package/dist/src/rules/setNotNullFullScan.d.ts +9 -0
  68. package/dist/src/rules/setNotNullFullScan.d.ts.map +1 -0
  69. package/dist/src/rules/setNotNullFullScan.js +93 -0
  70. package/dist/src/rules/setNotNullFullScan.js.map +1 -0
  71. package/dist/src/rules/transactionTrap.d.ts +9 -0
  72. package/dist/src/rules/transactionTrap.d.ts.map +1 -0
  73. package/dist/src/rules/transactionTrap.js +104 -0
  74. package/dist/src/rules/transactionTrap.js.map +1 -0
  75. package/dist/src/rules/types.d.ts +36 -0
  76. package/dist/src/rules/types.d.ts.map +1 -0
  77. package/dist/src/rules/types.js +5 -0
  78. package/dist/src/rules/types.js.map +1 -0
  79. package/dist/src/rules/unbatchedBackfill.d.ts +9 -0
  80. package/dist/src/rules/unbatchedBackfill.d.ts.map +1 -0
  81. package/dist/src/rules/unbatchedBackfill.js +58 -0
  82. package/dist/src/rules/unbatchedBackfill.js.map +1 -0
  83. package/package.json +44 -0
@@ -0,0 +1,20 @@
1
+ /**
2
+ * ddlforge - Machine-readable JSON output reporter
3
+ */
4
+ import { AnalysisResult } from '../engine/analyzer.js';
5
+ import { Finding } from '../rules/types.js';
6
+ export interface JsonReport {
7
+ status: 'passed' | 'failed';
8
+ summary: {
9
+ filesScanned: number;
10
+ statementsAnalyzed: number;
11
+ blockers: number;
12
+ warnings: number;
13
+ advisories: number;
14
+ durationMs: number;
15
+ passed: boolean;
16
+ };
17
+ findings: Finding[];
18
+ }
19
+ export declare function formatJson(results: AnalysisResult[], pretty?: boolean): string;
20
+ //# sourceMappingURL=json.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json.d.ts","sourceRoot":"","sources":["../../../src/reporters/json.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAE5C,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC5B,OAAO,EAAE;QACP,YAAY,EAAE,MAAM,CAAC;QACrB,kBAAkB,EAAE,MAAM,CAAC;QAC3B,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;QACjB,UAAU,EAAE,MAAM,CAAC;QACnB,UAAU,EAAE,MAAM,CAAC;QACnB,MAAM,EAAE,OAAO,CAAC;KACjB,CAAC;IACF,QAAQ,EAAE,OAAO,EAAE,CAAC;CACrB;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,cAAc,EAAE,EAAE,MAAM,GAAE,OAAc,GAAG,MAAM,CAiCpF"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * ddlforge - Machine-readable JSON output reporter
3
+ */
4
+ export function formatJson(results, pretty = true) {
5
+ let filesScanned = results.length;
6
+ let statementsAnalyzed = 0;
7
+ let blockers = 0;
8
+ let warnings = 0;
9
+ let advisories = 0;
10
+ let durationMs = 0;
11
+ const allFindings = [];
12
+ for (const res of results) {
13
+ statementsAnalyzed += res.statementsAnalyzed;
14
+ blockers += res.blockersCount;
15
+ warnings += res.warningsCount;
16
+ advisories += res.advisoriesCount;
17
+ durationMs += res.durationMs;
18
+ allFindings.push(...res.findings);
19
+ }
20
+ const report = {
21
+ status: blockers === 0 ? 'passed' : 'failed',
22
+ summary: {
23
+ filesScanned,
24
+ statementsAnalyzed,
25
+ blockers,
26
+ warnings,
27
+ advisories,
28
+ durationMs: Math.round(durationMs * 100) / 100,
29
+ passed: blockers === 0,
30
+ },
31
+ findings: allFindings,
32
+ };
33
+ return pretty ? JSON.stringify(report, null, 2) : JSON.stringify(report);
34
+ }
35
+ //# sourceMappingURL=json.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json.js","sourceRoot":"","sources":["../../../src/reporters/json.ts"],"names":[],"mappings":"AAAA;;GAEG;AAmBH,MAAM,UAAU,UAAU,CAAC,OAAyB,EAAE,MAAM,GAAY,IAAI;IAC1E,IAAI,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;IAClC,IAAI,kBAAkB,GAAG,CAAC,CAAC;IAC3B,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,MAAM,WAAW,GAAc,EAAE,CAAC;IAElC,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;QAC1B,kBAAkB,IAAI,GAAG,CAAC,kBAAkB,CAAC;QAC7C,QAAQ,IAAI,GAAG,CAAC,aAAa,CAAC;QAC9B,QAAQ,IAAI,GAAG,CAAC,aAAa,CAAC;QAC9B,UAAU,IAAI,GAAG,CAAC,eAAe,CAAC;QAClC,UAAU,IAAI,GAAG,CAAC,UAAU,CAAC;QAC7B,WAAW,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,QAAQ,CAAC,CAAC;IACpC,CAAC;IAED,MAAM,MAAM,GAAe;QACzB,MAAM,EAAE,QAAQ,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ;QAC5C,OAAO,EAAE;YACP,YAAY;YACZ,kBAAkB;YAClB,QAAQ;YACR,QAAQ;YACR,UAAU;YACV,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,GAAG,CAAC,GAAG,GAAG;YAC9C,MAAM,EAAE,QAAQ,KAAK,CAAC;SACvB;QACD,QAAQ,EAAE,WAAW;KACtB,CAAC;IAEF,OAAO,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;AAC3E,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * ddlforge - CI PR Comment / Markdown Report Formatter
3
+ */
4
+ import { AnalysisResult } from '../engine/analyzer.js';
5
+ export declare function formatMarkdown(results: AnalysisResult[]): string;
6
+ //# sourceMappingURL=markdown.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../../src/reporters/markdown.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD,wBAAgB,cAAc,CAAC,OAAO,EAAE,cAAc,EAAE,GAAG,MAAM,CA6EhE"}
@@ -0,0 +1,70 @@
1
+ /**
2
+ * ddlforge - CI PR Comment / Markdown Report Formatter
3
+ */
4
+ export function formatMarkdown(results) {
5
+ let filesScanned = results.length;
6
+ let statementsAnalyzed = 0;
7
+ let blockers = 0;
8
+ let warnings = 0;
9
+ let advisories = 0;
10
+ let durationMs = 0;
11
+ for (const res of results) {
12
+ statementsAnalyzed += res.statementsAnalyzed;
13
+ blockers += res.blockersCount;
14
+ warnings += res.warningsCount;
15
+ advisories += res.advisoriesCount;
16
+ durationMs += res.durationMs;
17
+ }
18
+ const lines = [];
19
+ lines.push('## 🛡️ ddlforge Migration Lock & Safety Report');
20
+ lines.push('');
21
+ const statusEmoji = blockers > 0 ? '❌ **FAILED**' : warnings > 0 ? '⚠️ **PASSED WITH WARNINGS**' : '✅ **PASSED**';
22
+ lines.push(`**Status:** ${statusEmoji} (${durationMs.toFixed(1)}ms)`);
23
+ lines.push('');
24
+ // Summary Table
25
+ lines.push('| Metric | Count |');
26
+ lines.push('|:---|:---|');
27
+ lines.push(`| 🛑 **Blocking Violations** | \`${blockers}\` |`);
28
+ lines.push(`| ⚠️ **Warnings / Advisories** | \`${warnings + advisories}\` |`);
29
+ lines.push(`| 📄 **Files Scanned** | \`${filesScanned}\` |`);
30
+ lines.push(`| ⚡ **Statements Analyzed** | \`${statementsAnalyzed}\` |`);
31
+ lines.push('');
32
+ if (blockers === 0 && warnings === 0 && advisories === 0) {
33
+ lines.push('> ✨ **All migrations are safe!** No dangerous table locks or destructive data loss patterns detected.');
34
+ return lines.join('\n');
35
+ }
36
+ lines.push('### Detailed Findings');
37
+ lines.push('');
38
+ for (const res of results) {
39
+ if (res.findings.length === 0)
40
+ continue;
41
+ lines.push(`#### 📁 \`${res.file}\``);
42
+ lines.push('');
43
+ for (const finding of res.findings) {
44
+ const badge = finding.severity === 'BLOCKER' ? '🛑 `BLOCKER`' : '⚠️ `WARNING`';
45
+ const lock = finding.lockLevel !== 'NONE' ? ` · Lock: \`${finding.lockLevel}\`` : '';
46
+ lines.push(`<details ${finding.severity === 'BLOCKER' ? 'open' : ''}>`);
47
+ lines.push(`<summary>${badge} <b>${finding.message}</b> (Line ${finding.line})${lock}</summary>`);
48
+ lines.push('');
49
+ lines.push(`- **Rule:** \`${finding.ruleId}\``);
50
+ lines.push(`- **Location:** \`${res.file}:${finding.line}:${finding.column}\``);
51
+ lines.push(`- **Impact:** ${finding.detail}`);
52
+ lines.push('');
53
+ lines.push('```sql');
54
+ lines.push(finding.codeSnippet);
55
+ lines.push('```');
56
+ lines.push('');
57
+ lines.push('**Suggested Zero-Downtime Fix:**');
58
+ lines.push('```sql');
59
+ lines.push(finding.suggestion);
60
+ lines.push('```');
61
+ lines.push('');
62
+ lines.push('</details>');
63
+ lines.push('');
64
+ }
65
+ }
66
+ lines.push('---');
67
+ lines.push('*Automated by [ddlforge](https://github.com/ddlforge/ddlforge) — Zero-runtime-dependency Postgres Lock Linter*');
68
+ return lines.join('\n');
69
+ }
70
+ //# sourceMappingURL=markdown.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown.js","sourceRoot":"","sources":["../../../src/reporters/markdown.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * ddlforge - Clean, colorized TTY terminal reporter with code spans
3
+ */
4
+ import { AnalysisResult } from '../engine/analyzer.js';
5
+ export interface TerminalReporterOptions {
6
+ quiet?: boolean;
7
+ color?: boolean;
8
+ }
9
+ export declare function formatTerminal(results: AnalysisResult[], options?: TerminalReporterOptions): string;
10
+ //# sourceMappingURL=terminal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"terminal.d.ts","sourceRoot":"","sources":["../../../src/reporters/terminal.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD,MAAM,WAAW,uBAAuB;IACtC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AASD,wBAAgB,cAAc,CAAC,OAAO,EAAE,cAAc,EAAE,EAAE,OAAO,GAAE,uBAA4B,GAAG,MAAM,CAyGvG"}
@@ -0,0 +1,109 @@
1
+ /**
2
+ * ddlforge - Clean, colorized TTY terminal reporter with code spans
3
+ */
4
+ const supportsColor = (override) => {
5
+ if (override !== undefined)
6
+ return override;
7
+ if (process.env.NO_COLOR || process.env.NODE_DISABLE_COLORS)
8
+ return false;
9
+ if (process.env.FORCE_COLOR)
10
+ return true;
11
+ return process.stdout.isTTY ?? false;
12
+ };
13
+ export function formatTerminal(results, options = {}) {
14
+ const useColor = supportsColor(options.color);
15
+ const quiet = options.quiet ?? false;
16
+ const c = {
17
+ reset: useColor ? '\x1b[0m' : '',
18
+ bold: useColor ? '\x1b[1m' : '',
19
+ dim: useColor ? '\x1b[2m' : '',
20
+ red: useColor ? '\x1b[31m' : '',
21
+ green: useColor ? '\x1b[32m' : '',
22
+ yellow: useColor ? '\x1b[33m' : '',
23
+ blue: useColor ? '\x1b[34m' : '',
24
+ magenta: useColor ? '\x1b[35m' : '',
25
+ cyan: useColor ? '\x1b[36m' : '',
26
+ gray: useColor ? '\x1b[90m' : '',
27
+ bgRed: useColor ? '\x1b[41m\x1b[37m' : '',
28
+ bgYellow: useColor ? '\x1b[43m\x1b[30m' : '',
29
+ };
30
+ const lines = [];
31
+ let totalBlockers = 0;
32
+ let totalWarnings = 0;
33
+ let totalAdvisories = 0;
34
+ let totalStatements = 0;
35
+ let totalDuration = 0;
36
+ let totalFilesScanned = results.length;
37
+ for (const res of results) {
38
+ totalBlockers += res.blockersCount;
39
+ totalWarnings += res.warningsCount;
40
+ totalAdvisories += res.advisoriesCount;
41
+ totalStatements += res.statementsAnalyzed;
42
+ totalDuration += res.durationMs;
43
+ const visibleFindings = quiet
44
+ ? res.findings.filter(f => f.severity === 'BLOCKER')
45
+ : res.findings;
46
+ if (visibleFindings.length === 0)
47
+ continue;
48
+ lines.push('');
49
+ lines.push(`${c.bold}${c.cyan}📁 ${res.file}${c.reset} ${c.gray}(${res.statementsAnalyzed} statements)${c.reset}`);
50
+ lines.push(c.gray + '─'.repeat(70) + c.reset);
51
+ for (const finding of visibleFindings) {
52
+ const severityBadge = formatSeverityBadge(finding.severity, c);
53
+ const lockBadge = finding.lockLevel !== 'NONE'
54
+ ? ` ${c.magenta}[LOCK: ${finding.lockLevel}]${c.reset}`
55
+ : '';
56
+ lines.push(`${severityBadge} ${c.bold}${finding.message}${c.reset}${lockBadge}`);
57
+ lines.push(` ${c.gray}at ${res.file}:${finding.line}:${finding.column}${c.reset} ${c.dim}(rule: ${finding.ruleId})${c.reset}`);
58
+ if (finding.codeSnippet) {
59
+ lines.push('');
60
+ const snippetLines = finding.codeSnippet.split('\n');
61
+ snippetLines.forEach((snipLine, i) => {
62
+ const lineNum = String(finding.line + i).padStart(4, ' ');
63
+ lines.push(` ${c.dim}${lineNum} │${c.reset} ${c.yellow}${snipLine}${c.reset}`);
64
+ });
65
+ }
66
+ if (finding.detail) {
67
+ lines.push(` ${c.dim}Why:${c.reset} ${finding.detail}`);
68
+ }
69
+ if (finding.suggestion) {
70
+ lines.push(` ${c.green}${c.bold}Fix:${c.reset}`);
71
+ const suggestionLines = finding.suggestion.split('\n');
72
+ for (const sLine of suggestionLines) {
73
+ lines.push(` ${c.green}${sLine}${c.reset}`);
74
+ }
75
+ }
76
+ lines.push('');
77
+ }
78
+ }
79
+ // Summary footer
80
+ lines.push('');
81
+ lines.push(c.gray + '━'.repeat(70) + c.reset);
82
+ const durationStr = `${totalDuration.toFixed(1)}ms`;
83
+ if (totalBlockers > 0) {
84
+ lines.push(`${c.red}${c.bold}✖ FAILED:${c.reset} Found ${c.bold}${c.red}${totalBlockers} blocker(s)${c.reset}` +
85
+ (totalWarnings > 0 ? `, ${c.yellow}${totalWarnings} warning(s)${c.reset}` : '') +
86
+ ` across ${totalFilesScanned} file(s) [${durationStr}]`);
87
+ lines.push(`${c.dim}Run with --quiet to display blockers only.${c.reset}`);
88
+ }
89
+ else if (totalWarnings > 0) {
90
+ lines.push(`${c.yellow}${c.bold}⚠ PASSED WITH ADVISORIES:${c.reset} 0 blockers, ${c.yellow}${totalWarnings} warning(s)${c.reset}` +
91
+ ` across ${totalFilesScanned} file(s) [${durationStr}]`);
92
+ }
93
+ else {
94
+ lines.push(`${c.green}${c.bold}✔ ALL CLEAR:${c.reset} Checked ${totalFilesScanned} migration file(s) ` +
95
+ `(${totalStatements} statements) with zero lock or data-loss violations [${durationStr}]`);
96
+ }
97
+ return lines.join('\n');
98
+ }
99
+ function formatSeverityBadge(severity, c) {
100
+ switch (severity) {
101
+ case 'BLOCKER':
102
+ return `${c.bgRed} BLOCKER ${c.reset}`;
103
+ case 'WARNING':
104
+ return `${c.bgYellow} WARNING ${c.reset}`;
105
+ case 'ADVISORY':
106
+ return `${c.cyan}[ADVISORY]${c.reset}`;
107
+ }
108
+ }
109
+ //# sourceMappingURL=terminal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"terminal.js","sourceRoot":"","sources":["../../../src/reporters/terminal.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * ddlforge Rule: ADD COLUMN NOT NULL without DEFAULT
3
+ *
4
+ * Severity: BLOCKER
5
+ * Lock: ACCESS EXCLUSIVE
6
+ */
7
+ import { Rule } from './types.js';
8
+ export declare const addColumnNotNullRule: Rule;
9
+ //# sourceMappingURL=addColumnNotNull.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"addColumnNotNull.d.ts","sourceRoot":"","sources":["../../../src/rules/addColumnNotNull.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,IAAI,EAAwB,MAAM,YAAY,CAAC;AAoGxD,eAAO,MAAM,oBAAoB,EAAE,IAqDlC,CAAC"}
@@ -0,0 +1,131 @@
1
+ /**
2
+ * ddlforge Rule: ADD COLUMN NOT NULL without DEFAULT
3
+ *
4
+ * Severity: BLOCKER
5
+ * Lock: ACCESS EXCLUSIVE
6
+ */
7
+ import { PostgresLockLevel } from '../engine/locks.js';
8
+ function extractAddColumnClauses(tokens) {
9
+ const clauses = [];
10
+ let parenDepth = 0;
11
+ let i = 0;
12
+ while (i < tokens.length) {
13
+ if (tokens[i].value === '(') {
14
+ parenDepth++;
15
+ i++;
16
+ continue;
17
+ }
18
+ if (tokens[i].value === ')') {
19
+ parenDepth--;
20
+ i++;
21
+ continue;
22
+ }
23
+ // Check for ADD [COLUMN] at top level (parenDepth === 0)
24
+ if (parenDepth === 0 && tokens[i].value === 'ADD') {
25
+ let clauseIdx = i + 1;
26
+ if (tokens[clauseIdx]?.value === 'COLUMN') {
27
+ clauseIdx++;
28
+ }
29
+ // If next is IF NOT EXISTS, skip
30
+ if (tokens[clauseIdx]?.value === 'IF' && tokens[clauseIdx + 1]?.value === 'NOT' && tokens[clauseIdx + 2]?.value === 'EXISTS') {
31
+ clauseIdx += 3;
32
+ }
33
+ // Check if next token is CONSTRAINT or standard column definition
34
+ if (tokens[clauseIdx]?.value === 'CONSTRAINT') {
35
+ // Constraint definition, not a column
36
+ i++;
37
+ continue;
38
+ }
39
+ const columnName = tokens[clauseIdx]?.raw ?? 'column';
40
+ clauseIdx++;
41
+ // Collect tokens until next top-level comma or end of tokens
42
+ let hasNotNull = false;
43
+ let hasDefault = false;
44
+ let hasGenerated = false;
45
+ const clauseTokens = [];
46
+ let subParen = 0;
47
+ while (clauseIdx < tokens.length) {
48
+ const t = tokens[clauseIdx];
49
+ if (t.value === '(')
50
+ subParen++;
51
+ if (t.value === ')')
52
+ subParen--;
53
+ if (subParen === 0 && t.value === ',') {
54
+ break; // next subcommand
55
+ }
56
+ clauseTokens.push(t);
57
+ if (t.value === 'NOT' && tokens[clauseIdx + 1]?.value === 'NULL') {
58
+ hasNotNull = true;
59
+ }
60
+ if (t.value === 'DEFAULT') {
61
+ hasDefault = true;
62
+ }
63
+ if (t.value === 'GENERATED') {
64
+ hasGenerated = true;
65
+ }
66
+ clauseIdx++;
67
+ }
68
+ clauses.push({
69
+ columnName,
70
+ hasNotNull,
71
+ hasDefault,
72
+ hasGenerated,
73
+ tokens: clauseTokens,
74
+ });
75
+ i = clauseIdx;
76
+ continue;
77
+ }
78
+ i++;
79
+ }
80
+ return clauses;
81
+ }
82
+ export const addColumnNotNullRule = {
83
+ id: 'add-column-not-null-without-default',
84
+ name: 'ADD COLUMN NOT NULL without DEFAULT',
85
+ description: 'Adding a NOT NULL column without a DEFAULT value will immediately fail on non-empty tables and hold an ACCESS EXCLUSIVE lock.',
86
+ defaultSeverity: 'BLOCKER',
87
+ lockLevel: PostgresLockLevel.ACCESS_EXCLUSIVE,
88
+ check(context) {
89
+ const findings = [];
90
+ for (const stmt of context.statements) {
91
+ if (stmt.hasIgnore(this.id))
92
+ continue;
93
+ const tokens = stmt.tokens;
94
+ if (tokens.length < 5)
95
+ continue;
96
+ if (tokens[0].value !== 'ALTER' || tokens[1].value !== 'TABLE')
97
+ continue;
98
+ // Extract table name
99
+ let idx = 2;
100
+ if (tokens[idx]?.value === 'ONLY')
101
+ idx++;
102
+ if (tokens[idx]?.value === 'IF' && tokens[idx + 1]?.value === 'EXISTS')
103
+ idx += 2;
104
+ const tableName = tokens[idx]?.raw ?? 'table';
105
+ idx++;
106
+ // Scan through subcommands separated by comma (at top parentheses depth)
107
+ const clauses = extractAddColumnClauses(tokens.slice(idx));
108
+ for (const clause of clauses) {
109
+ if (clause.hasNotNull && !clause.hasDefault && !clause.hasGenerated) {
110
+ findings.push({
111
+ ruleId: this.id,
112
+ ruleName: this.name,
113
+ severity: this.defaultSeverity,
114
+ lockLevel: this.lockLevel,
115
+ message: `Column "${clause.columnName}" added as NOT NULL without a DEFAULT value on table "${tableName}".`,
116
+ detail: `Adding a NOT NULL column without a DEFAULT on non-empty table "${tableName}" will immediately fail ` +
117
+ 'with `column "..." contains null values` while holding an ACCESS EXCLUSIVE table lock.',
118
+ suggestion: `Provide a DEFAULT value: \`ALTER TABLE ${tableName} ADD COLUMN ${clause.columnName} <type> DEFAULT <val> NOT NULL;\` ` +
119
+ `or add nullable first, backfill rows in batches, and apply a validated NOT NULL constraint.`,
120
+ file: context.filePath,
121
+ line: stmt.startLine,
122
+ column: stmt.startColumn,
123
+ codeSnippet: stmt.raw,
124
+ });
125
+ }
126
+ }
127
+ }
128
+ return findings;
129
+ },
130
+ };
131
+ //# sourceMappingURL=addColumnNotNull.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"addColumnNotNull.js","sourceRoot":"","sources":["../../../src/rules/addColumnNotNull.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * ddlforge Rule: ADD CONSTRAINT ... FOREIGN KEY without NOT VALID
3
+ *
4
+ * Severity: BLOCKER
5
+ * Lock: SHARE ROW EXCLUSIVE on child table + SHARE on parent table
6
+ */
7
+ import { Rule } from './types.js';
8
+ export declare const foreignKeyNotValidRule: Rule;
9
+ //# sourceMappingURL=foreignKeyNotValid.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"foreignKeyNotValid.d.ts","sourceRoot":"","sources":["../../../src/rules/foreignKeyNotValid.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,IAAI,EAAwB,MAAM,YAAY,CAAC;AA+ExD,eAAO,MAAM,sBAAsB,EAAE,IA2DpC,CAAC"}
@@ -0,0 +1,119 @@
1
+ /**
2
+ * ddlforge Rule: ADD CONSTRAINT ... FOREIGN KEY without NOT VALID
3
+ *
4
+ * Severity: BLOCKER
5
+ * Lock: SHARE ROW EXCLUSIVE on child table + SHARE on parent table
6
+ */
7
+ import { PostgresLockLevel } from '../engine/locks.js';
8
+ function extractForeignKeyClauses(tokens) {
9
+ const clauses = [];
10
+ let parenDepth = 0;
11
+ let i = 0;
12
+ while (i < tokens.length) {
13
+ if (tokens[i].value === '(') {
14
+ parenDepth++;
15
+ i++;
16
+ continue;
17
+ }
18
+ if (tokens[i].value === ')') {
19
+ parenDepth--;
20
+ i++;
21
+ continue;
22
+ }
23
+ if (parenDepth === 0 && tokens[i].value === 'ADD') {
24
+ let currentIdx = i + 1;
25
+ let constraintName;
26
+ if (tokens[currentIdx]?.value === 'CONSTRAINT') {
27
+ currentIdx++;
28
+ constraintName = tokens[currentIdx]?.raw;
29
+ currentIdx++;
30
+ }
31
+ // Check if this clause is FOREIGN KEY
32
+ if (tokens[currentIdx]?.value === 'FOREIGN' && tokens[currentIdx + 1]?.value === 'KEY') {
33
+ // Collect all tokens for this constraint until top-level comma or end
34
+ const clauseTokens = [];
35
+ let hasNotValid = false;
36
+ let subParen = 0;
37
+ while (currentIdx < tokens.length) {
38
+ const t = tokens[currentIdx];
39
+ if (t.value === '(')
40
+ subParen++;
41
+ if (t.value === ')')
42
+ subParen--;
43
+ if (subParen === 0 && t.value === ',') {
44
+ break;
45
+ }
46
+ clauseTokens.push(t);
47
+ if (t.value === 'NOT' && tokens[currentIdx + 1]?.value === 'VALID') {
48
+ hasNotValid = true;
49
+ }
50
+ currentIdx++;
51
+ }
52
+ clauses.push({
53
+ constraintName,
54
+ hasNotValid,
55
+ tokens: clauseTokens,
56
+ });
57
+ i = currentIdx;
58
+ continue;
59
+ }
60
+ }
61
+ i++;
62
+ }
63
+ return clauses;
64
+ }
65
+ export const foreignKeyNotValidRule = {
66
+ id: 'foreign-key-missing-not-valid',
67
+ name: 'ADD CONSTRAINT FOREIGN KEY without NOT VALID',
68
+ description: 'Adding a foreign key constraint without NOT VALID performs a full table scan under SHARE ROW EXCLUSIVE lock, blocking concurrent writes on both tables.',
69
+ defaultSeverity: 'BLOCKER',
70
+ lockLevel: PostgresLockLevel.SHARE_ROW_EXCLUSIVE,
71
+ check(context) {
72
+ const findings = [];
73
+ for (const stmt of context.statements) {
74
+ if (stmt.hasIgnore(this.id))
75
+ continue;
76
+ const tokens = stmt.tokens;
77
+ if (tokens.length < 6)
78
+ continue;
79
+ if (tokens[0].value !== 'ALTER' || tokens[1].value !== 'TABLE')
80
+ continue;
81
+ // Extract table name
82
+ let idx = 2;
83
+ if (tokens[idx]?.value === 'ONLY')
84
+ idx++;
85
+ if (tokens[idx]?.value === 'IF' && tokens[idx + 1]?.value === 'EXISTS')
86
+ idx += 2;
87
+ const tableName = tokens[idx]?.raw ?? 'table';
88
+ idx++;
89
+ const fkClauses = extractForeignKeyClauses(tokens.slice(idx));
90
+ for (const fk of fkClauses) {
91
+ if (!fk.hasNotValid) {
92
+ const cName = fk.constraintName ? ` "${fk.constraintName}"` : '';
93
+ const validateSuggestion = fk.constraintName
94
+ ? `ALTER TABLE ${tableName} VALIDATE CONSTRAINT ${fk.constraintName};`
95
+ : `ALTER TABLE ${tableName} VALIDATE CONSTRAINT <constraint_name>;`;
96
+ findings.push({
97
+ ruleId: this.id,
98
+ ruleName: this.name,
99
+ severity: this.defaultSeverity,
100
+ lockLevel: this.lockLevel,
101
+ message: `Foreign key constraint${cName} on table "${tableName}" added without NOT VALID.`,
102
+ detail: `Validating foreign keys inline holds a SHARE ROW EXCLUSIVE lock on "${tableName}" and a SHARE lock on the referenced table, ` +
103
+ 'blocking all concurrent writes (INSERT, UPDATE, DELETE) for the entire duration of the table scan.',
104
+ suggestion: `1. Add constraint with NOT VALID:\n` +
105
+ ` ALTER TABLE ${tableName} ADD CONSTRAINT ${fk.constraintName ?? 'fk_name'} FOREIGN KEY (...) REFERENCES (...) NOT VALID;\n` +
106
+ `2. Validate concurrently without blocking writes:\n` +
107
+ ` ${validateSuggestion}`,
108
+ file: context.filePath,
109
+ line: stmt.startLine,
110
+ column: stmt.startColumn,
111
+ codeSnippet: stmt.raw,
112
+ });
113
+ }
114
+ }
115
+ }
116
+ return findings;
117
+ },
118
+ };
119
+ //# sourceMappingURL=foreignKeyNotValid.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"foreignKeyNotValid.js","sourceRoot":"","sources":["../../../src/rules/foreignKeyNotValid.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * ddlforge - Rules registry
3
+ */
4
+ export * from './types.js';
5
+ export { indexConcurrentlyRule } from './indexConcurrently.js';
6
+ export { transactionTrapRule } from './transactionTrap.js';
7
+ export { addColumnNotNullRule } from './addColumnNotNull.js';
8
+ export { foreignKeyNotValidRule } from './foreignKeyNotValid.js';
9
+ export { prismaRenameDropAddRule } from './prismaRenameDropAdd.js';
10
+ export { setNotNullFullScanRule } from './setNotNullFullScan.js';
11
+ export { unbatchedBackfillRule } from './unbatchedBackfill.js';
12
+ import { Rule } from './types.js';
13
+ export declare const ALL_RULES: Rule[];
14
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/rules/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAE/D,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AASlC,eAAO,MAAM,SAAS,EAAE,IAAI,EAQ3B,CAAC"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * ddlforge - Rules registry
3
+ */
4
+ export * from './types.js';
5
+ export { indexConcurrentlyRule } from './indexConcurrently.js';
6
+ export { transactionTrapRule } from './transactionTrap.js';
7
+ export { addColumnNotNullRule } from './addColumnNotNull.js';
8
+ export { foreignKeyNotValidRule } from './foreignKeyNotValid.js';
9
+ export { prismaRenameDropAddRule } from './prismaRenameDropAdd.js';
10
+ export { setNotNullFullScanRule } from './setNotNullFullScan.js';
11
+ export { unbatchedBackfillRule } from './unbatchedBackfill.js';
12
+ import { indexConcurrentlyRule } from './indexConcurrently.js';
13
+ import { transactionTrapRule } from './transactionTrap.js';
14
+ import { addColumnNotNullRule } from './addColumnNotNull.js';
15
+ import { foreignKeyNotValidRule } from './foreignKeyNotValid.js';
16
+ import { prismaRenameDropAddRule } from './prismaRenameDropAdd.js';
17
+ import { setNotNullFullScanRule } from './setNotNullFullScan.js';
18
+ import { unbatchedBackfillRule } from './unbatchedBackfill.js';
19
+ export const ALL_RULES = [
20
+ indexConcurrentlyRule,
21
+ transactionTrapRule,
22
+ addColumnNotNullRule,
23
+ foreignKeyNotValidRule,
24
+ prismaRenameDropAddRule,
25
+ setNotNullFullScanRule,
26
+ unbatchedBackfillRule,
27
+ ];
28
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/rules/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAG/D,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAE/D,MAAM,CAAC,MAAM,SAAS,GAAW;IAC/B,qBAAqB;IACrB,mBAAmB;IACnB,oBAAoB;IACpB,sBAAsB;IACtB,uBAAuB;IACvB,sBAAsB;IACtB,qBAAqB;CACtB,CAAC"}