pgterra 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 (3) hide show
  1. package/README.md +544 -0
  2. package/dist/index.js +75 -0
  3. package/package.json +72 -0
package/README.md ADDED
@@ -0,0 +1,544 @@
1
+ # PGTerra
2
+
3
+ A declarative Infrastructure as Code tool for PostgreSQL databases, similar to Terraform but specifically designed for database schema management.
4
+
5
+ ## 🔍 Overview
6
+
7
+ PGTerra follows a declarative approach where you define your **desired database state** in a `schema.sql` file, and the tool automatically figures out what changes are needed to bring your database to that state. No more writing manual migration scripts - just describe what you want and let PGTerra handle the rest!
8
+
9
+ ### Key Concepts
10
+
11
+ - **Declarative, Not Imperative**: You describe WHAT you want, not HOW to get there
12
+ - **State-Based Management**: Compare current vs desired state and generate minimal changes
13
+ - **Safety First**: Preview changes with `plan` before applying them
14
+ - **Idempotent Operations**: Running the same schema multiple times is safe
15
+
16
+ ## 🏗️ How It Works
17
+
18
+ ```mermaid
19
+ graph TD
20
+ A["schema.sql<br/>(Desired State)"] --> B["Schema Parser"]
21
+ C["PostgreSQL Database<br/>(Current State)"] --> D["Database Inspector"]
22
+
23
+ B --> E["Desired Schema<br/>(Parsed Objects)"]
24
+ D --> F["Current Schema<br/>(Queried Objects)"]
25
+
26
+ E --> G["Schema Differ"]
27
+ F --> G
28
+
29
+ G --> H["Migration Plan<br/>(SQL Statements)"]
30
+
31
+ H --> I{"Command Type"}
32
+ I -->|plan| J["Display Changes"]
33
+ I -->|apply| K["Execute Changes"]
34
+
35
+ K --> L["Updated Database"]
36
+ ```
37
+
38
+ ### Architecture Components
39
+
40
+ #### 1. **Schema Parser**
41
+
42
+ - Converts your `schema.sql` file into structured objects
43
+ - Uses `sql-parser-cst` for robust SQL parsing
44
+ - Handles CREATE TABLE statements with columns, constraints, and data types
45
+
46
+ #### 2. **Database Inspector**
47
+
48
+ - Queries the current database structure using PostgreSQL's `information_schema`
49
+ - Extracts table definitions, column details, constraints, and metadata
50
+ - Normalizes database state into the same format as parsed schema
51
+
52
+ #### 3. **Schema Differ**
53
+
54
+ - Compares desired vs current state
55
+ - Generates optimized migration plan with proper operation ordering
56
+ - Handles complex scenarios like type conversions, constraint changes, and data preservation
57
+
58
+ #### 4. **Migration Planner & Executor**
59
+
60
+ - Orchestrates the diffing process safely
61
+ - Executes SQL statements with proper error handling
62
+ - Provides detailed feedback on changes applied
63
+
64
+ ## 🔄 Step-by-Step Process
65
+
66
+ ```mermaid
67
+ sequenceDiagram
68
+ participant CLI as CLI Command<br/>(plan/apply)
69
+ participant SS as Schema Service
70
+ participant SP as Schema Parser
71
+ participant DI as Database Inspector
72
+ participant SD as Schema Differ
73
+ participant ME as Migration Executor
74
+ participant DB as PostgreSQL Database
75
+
76
+ CLI->>SS: plan("schema.sql")
77
+ SS->>SP: parseSchemaFile("schema.sql")
78
+ SP->>SP: Parse CREATE TABLE statements
79
+ SP-->>SS: Desired Schema (Table[])
80
+
81
+ SS->>DB: Connect
82
+ SS->>DI: getCurrentSchema(client)
83
+ DI->>DB: Query information_schema
84
+ DB-->>DI: Table metadata
85
+ DI-->>SS: Current Schema (Table[])
86
+
87
+ SS->>SD: generateMigrationPlan(desired, current)
88
+ SD->>SD: Compare schemas
89
+ SD->>SD: Generate SQL statements
90
+ SD-->>SS: Migration Plan
91
+
92
+ alt Command is "plan"
93
+ SS->>CLI: Display changes
94
+ else Command is "apply"
95
+ SS->>ME: executePlan(client, plan)
96
+ ME->>DB: Execute SQL statements
97
+ DB-->>ME: Success/Failure
98
+ ME-->>SS: Results
99
+ end
100
+
101
+ SS->>DB: Disconnect
102
+ ```
103
+
104
+ ## 📝 Simple Example
105
+
106
+ Let's walk through a simple example to see how PGTerra works:
107
+
108
+ ### Starting Point: Empty Database
109
+
110
+ ```sql
111
+ -- Database has no tables
112
+ ```
113
+
114
+ ### Define Desired State: `schema.sql`
115
+
116
+ ```sql
117
+ CREATE TABLE users (
118
+ id SERIAL PRIMARY KEY,
119
+ email VARCHAR(255) NOT NULL,
120
+ name VARCHAR(100) NOT NULL,
121
+ created_at TIMESTAMP DEFAULT NOW()
122
+ );
123
+ ```
124
+
125
+ ### Run Plan Command
126
+
127
+ ```bash
128
+ pgterra plan
129
+ ```
130
+
131
+ **Output:**
132
+
133
+ ```
134
+ 📋 Analyzing schema changes...
135
+ 📝 Found 1 change(s) to apply:
136
+
137
+ 1. CREATE TABLE users (id SERIAL PRIMARY KEY, email VARCHAR(255) NOT NULL, name VARCHAR(100) NOT NULL, created_at TIMESTAMP DEFAULT NOW());
138
+ ```
139
+
140
+ ### Apply Changes
141
+
142
+ ```bash
143
+ pgterra apply
144
+ ```
145
+
146
+ **Result:** The `users` table is created in your database.
147
+
148
+ ## 🔄 Schema Evolution Example
149
+
150
+ Now let's modify the existing table:
151
+
152
+ ### Current Database State:
153
+
154
+ ```sql
155
+ CREATE TABLE users (
156
+ id SERIAL PRIMARY KEY,
157
+ email VARCHAR(255) NOT NULL,
158
+ name VARCHAR(100) NOT NULL,
159
+ created_at TIMESTAMP DEFAULT NOW()
160
+ );
161
+ ```
162
+
163
+ ### Update Desired State: `schema.sql`
164
+
165
+ ```sql
166
+ CREATE TABLE users (
167
+ id SERIAL PRIMARY KEY,
168
+ email VARCHAR(255) NOT NULL,
169
+ full_name VARCHAR(200) NOT NULL, -- renamed and expanded
170
+ created_at TIMESTAMP DEFAULT NOW(),
171
+ is_active BOOLEAN DEFAULT true -- new column
172
+ );
173
+ ```
174
+
175
+ ### Generated Migration Plan:
176
+
177
+ ```sql
178
+ ALTER TABLE users ADD COLUMN full_name VARCHAR(200) NOT NULL;
179
+ ALTER TABLE users ADD COLUMN is_active BOOLEAN DEFAULT true;
180
+ ALTER TABLE users DROP COLUMN name;
181
+ ```
182
+
183
+ **PGTerra automatically:**
184
+
185
+ - Detected the new `full_name` column
186
+ - Added the new `is_active` column with default
187
+ - Removed the old `name` column
188
+ - Preserved all existing data
189
+
190
+ ## 🛠️ Advanced Features
191
+
192
+ ### Smart Type Conversions
193
+
194
+ When changing column types, PGTerra automatically handles complex conversions:
195
+
196
+ ```sql
197
+ -- Before: age VARCHAR(10)
198
+ -- After: age INTEGER
199
+
200
+ -- Generated migration:
201
+ ALTER TABLE users ALTER COLUMN age TYPE INTEGER USING age::INTEGER;
202
+ ```
203
+
204
+ ### Constraint Management
205
+
206
+ PGTerra intelligently handles constraint changes:
207
+
208
+ ```mermaid
209
+ flowchart TD
210
+ A["Column Modification"] --> B["Drop Conflicting Defaults"]
211
+ B --> C["Change Data Type"]
212
+ C --> D["Set New Default"]
213
+ D --> E["Add/Drop NOT NULL"]
214
+
215
+ F["Complex Example:"] --> G["VARCHAR → INTEGER<br/>with new DEFAULT"]
216
+ G --> H["1. DROP DEFAULT"]
217
+ H --> I["2. ALTER TYPE USING"]
218
+ I --> J["3. SET DEFAULT"]
219
+ J --> K["4. SET NOT NULL"]
220
+ ```
221
+
222
+ ### Operation Ordering
223
+
224
+ The differ carefully orders operations to avoid conflicts:
225
+
226
+ 1. Drop conflicting defaults
227
+ 2. Change data types (with USING clauses when needed)
228
+ 3. Set new defaults
229
+ 4. Modify NULL/NOT NULL constraints
230
+
231
+ ## 🚀 Installation & Usage
232
+
233
+ ### Prerequisites
234
+
235
+ - Node.js 18+ with Bun package manager
236
+ - PostgreSQL database
237
+ - Database connection configured
238
+
239
+ ### Installation
240
+
241
+ ```bash
242
+ bun install
243
+ ```
244
+
245
+ ### Commands
246
+
247
+ #### Plan Changes
248
+
249
+ Preview what changes would be made without applying them:
250
+
251
+ ```bash
252
+ bun run cli plan
253
+ ```
254
+
255
+ #### Apply Changes
256
+
257
+ Execute the planned changes:
258
+
259
+ ```bash
260
+ bun run cli apply
261
+ ```
262
+
263
+ #### Use Custom Schema File
264
+
265
+ ```bash
266
+ bun run cli plan --file custom-schema.sql
267
+ bun run cli apply --file custom-schema.sql
268
+ ```
269
+
270
+ ### Configuration
271
+
272
+ Create a configuration file (e.g., `pgterra.config.json`):
273
+
274
+ ```json
275
+ {
276
+ "database": {
277
+ "host": "localhost",
278
+ "port": 5432,
279
+ "database": "myapp",
280
+ "username": "postgres",
281
+ "password": "password"
282
+ }
283
+ }
284
+ ```
285
+
286
+ ## 📁 Project Structure
287
+
288
+ ```
289
+ pgterra/
290
+ ├── src/
291
+ │ ├── cli/
292
+ │ │ └── commands/ # CLI command handlers
293
+ │ ├── core/
294
+ │ │ ├── database/ # Database connection & client
295
+ │ │ ├── migration/ # Migration planning & execution
296
+ │ │ └── schema/ # Schema parsing, inspection, diffing
297
+ │ ├── types/ # TypeScript type definitions
298
+ │ └── utils/ # Shared utilities
299
+ ├── schema.sql # Your database schema definition
300
+ └── README.md
301
+ ```
302
+
303
+ ## 🔧 Technical Deep Dive
304
+
305
+ ### Schema Differ Logic
306
+
307
+ The `SchemaDiffer` contains the most sophisticated logic:
308
+
309
+ ```mermaid
310
+ flowchart TD
311
+ A["Compare Schemas"] --> B["Check Tables"]
312
+
313
+ B --> C["New Tables"]
314
+ B --> D["Existing Tables"]
315
+ B --> E["Dropped Tables"]
316
+
317
+ C --> F["Generate CREATE TABLE"]
318
+ E --> G["Generate DROP TABLE"]
319
+
320
+ D --> H["Compare Columns"]
321
+
322
+ H --> I["New Columns"]
323
+ H --> J["Modified Columns"]
324
+ H --> K["Dropped Columns"]
325
+
326
+ I --> L["Generate ADD COLUMN"]
327
+ K --> M["Generate DROP COLUMN"]
328
+
329
+ J --> N["Check What Changed"]
330
+ N --> O["Data Type"]
331
+ N --> P["Default Value"]
332
+ N --> Q["Nullable"]
333
+
334
+ O --> R["ALTER COLUMN TYPE<br/>(with USING if needed)"]
335
+ P --> S["SET/DROP DEFAULT"]
336
+ Q --> T["SET/DROP NOT NULL"]
337
+
338
+ R --> U["Order Operations<br/>Carefully"]
339
+ S --> U
340
+ T --> U
341
+
342
+ U --> V["Final SQL Statements"]
343
+ ```
344
+
345
+ ### Data Structure
346
+
347
+ Tables and columns are represented as TypeScript interfaces:
348
+
349
+ ```typescript
350
+ interface Column {
351
+ name: string;
352
+ type: string;
353
+ nullable: boolean;
354
+ default?: string;
355
+ primary?: boolean;
356
+ }
357
+
358
+ interface Table {
359
+ name: string;
360
+ columns: Column[];
361
+ }
362
+ ```
363
+
364
+ ## 🎯 Design Principles
365
+
366
+ ```mermaid
367
+ graph LR
368
+ A["Declarative<br/>Approach"] --> B["You describe<br/>WHAT you want"]
369
+ B --> C["Tool figures out<br/>HOW to get there"]
370
+
371
+ D["State-Based<br/>Management"] --> E["Compare current vs desired"]
372
+ E --> F["Generate minimal<br/>change set"]
373
+
374
+ G["Safety First"] --> H["Preview changes<br/>with 'plan'"]
375
+ H --> I["Explicit 'apply'<br/>to execute"]
376
+ ```
377
+
378
+ ## 🚦 Current Status & Roadmap
379
+
380
+ ### ✅ **Implemented Features**
381
+
382
+ #### **Core Table Operations**
383
+
384
+ - ✅ **Table Creation** - Create new tables from schema definitions
385
+ - ✅ **Table Dropping** - Remove tables not in desired schema
386
+ - ✅ **Mixed Table Operations** - Add, keep, and remove tables in single migration
387
+
388
+ #### **Column Management**
389
+
390
+ - ✅ **Column Addition** - Add new columns with various data types
391
+ - ✅ **Column Removal** - Remove columns while preserving data
392
+ - ✅ **Column Type Changes** - Convert between compatible data types
393
+ - ✅ **Default Values** - Handle columns with default values and constraints
394
+ - ✅ **Nullable Constraints** - Manage NOT NULL/NULL constraints
395
+
396
+ #### **Advanced Type Conversions**
397
+
398
+ - ✅ **String Type Conversions** - VARCHAR ↔ TEXT with length handling
399
+ - ✅ **Numeric Type Conversions** - INTEGER ↔ BIGINT, DECIMAL precision changes
400
+ - ✅ **Boolean Type Conversions** - All PostgreSQL boolean representations
401
+ - ✅ **Smart USING Clauses** - Automatic type conversion logic
402
+ - ✅ **Unicode Support** - Full Unicode, emoji, and multi-byte character handling
403
+
404
+ #### **Data Integrity & Safety**
405
+
406
+ - ✅ **Data Preservation** - All migrations preserve existing data
407
+ - ✅ **Operation Ordering** - Smart ordering to avoid constraint conflicts
408
+ - ✅ **Boundary Value Testing** - Edge cases for all data types
409
+ - ✅ **Large Dataset Support** - Performance-tested with large tables
410
+
411
+ #### **Performance & Reliability**
412
+
413
+ - ✅ **Performance Monitoring** - Benchmark tracking and regression detection
414
+ - ✅ **Concurrent Operations** - Lock management and concurrent access
415
+ - ✅ **Memory Efficiency** - Optimized for large datasets
416
+ - ✅ **Error Handling** - Graceful handling of edge cases and failures
417
+
418
+ #### **CLI & Tooling**
419
+
420
+ - ✅ **Plan Command** - Preview changes before applying
421
+ - ✅ **Apply Command** - Execute migrations safely
422
+ - ✅ **Schema File Support** - Custom schema file paths
423
+ - ✅ **Database Configuration** - Connection management
424
+ - ✅ **Comprehensive Testing** - 20+ test suites covering edge cases
425
+
426
+ ### 🔄 **In Progress**
427
+
428
+ #### **Primary Key Support**
429
+
430
+ - 🔄 **Primary Key Detection** - Currently handles SERIAL PRIMARY KEY
431
+ - 🔄 **Composite Primary Keys** - Multi-column primary keys
432
+ - 🔄 **Primary Key Changes** - Adding/removing/modifying primary keys
433
+
434
+ ### 📋 **Planned Features**
435
+
436
+ #### **Core Schema Objects**
437
+
438
+ - [ ] **Indexes**
439
+ - B-tree, GIN, GiST, BRIN, Hash indexes
440
+ - Unique, partial, expression indexes
441
+ - Concurrent creation and REINDEX operations
442
+ - [ ] **Advanced Constraints**
443
+ - Foreign Keys with CASCADE/RESTRICT/SET NULL actions
444
+ - Unique Constraints (multi-column)
445
+ - Check Constraints with custom expressions
446
+ - DEFERRABLE constraints
447
+
448
+ #### **Advanced PostgreSQL Features**
449
+
450
+ - [ ] **Sequences**
451
+ - Custom sequences with start/increment/min/max
452
+ - Sequence ownership and dependencies
453
+ - [ ] **Views & Materialized Views**
454
+ - Standard view creation and OR REPLACE
455
+ - Materialized view management and refresh
456
+ - [ ] **Custom Types**
457
+ - ENUMs with value management
458
+ - Composite Types for complex data structures
459
+ - Domain types with constraints
460
+
461
+ #### **Functions & Triggers**
462
+
463
+ - [ ] **Stored Functions/Procedures**
464
+ - PL/pgSQL and SQL functions
465
+ - Parameter and return type management
466
+ - Function versioning (OR REPLACE)
467
+ - [ ] **Triggers**
468
+ - BEFORE/AFTER/INSTEAD OF triggers
469
+ - Row-level and statement-level triggers
470
+ - Trigger enabling/disabling
471
+
472
+ #### **Database Administration**
473
+
474
+ - [ ] **Extensions**
475
+ - Enable/disable PostgreSQL extensions
476
+ - Extension version management
477
+ - [ ] **Roles & Security**
478
+ - User and role management
479
+ - Permission grants and revokes
480
+ - Role membership hierarchy
481
+ - [ ] **Schema Namespaces**
482
+ - Multi-schema support
483
+ - Schema ownership and search paths
484
+ - [ ] **Tablespaces**
485
+ - Custom tablespace management
486
+ - Table and index tablespace assignment
487
+
488
+ #### **Enhanced Features**
489
+
490
+ - [ ] **Comments & Documentation**
491
+ - Object-level comments and descriptions
492
+ - Schema documentation generation
493
+ - [ ] **Advanced Rules**
494
+ - Query rewrite rules
495
+ - Rule creation and management
496
+ - [ ] **Event Triggers**
497
+ - DDL event triggers
498
+ - Database-level event handling
499
+
500
+ #### **Tooling & DevEx Improvements**
501
+
502
+ - [ ] **Configuration Management**
503
+ - Multiple environment support
504
+ - Configuration file formats (JSON/YAML)
505
+ - [ ] **Migration History**
506
+ - Track applied migrations
507
+ - Rollback capabilities
508
+ - [ ] **Schema Validation**
509
+ - Pre-migration validation
510
+ - Dependency checking
511
+ - [ ] **Import/Export**
512
+ - Import from existing databases
513
+ - Export current schema to files
514
+
515
+ ### 📊 **Current Test Coverage**
516
+
517
+ The project has comprehensive test coverage with **20+ test suites** covering:
518
+
519
+ - **Table Operations**: 6 core scenarios
520
+ - **Column Operations**: 15+ test suites
521
+ - **Type Conversions**: String, Numeric, Boolean edge cases
522
+ - **Performance Testing**: Large datasets, concurrent operations
523
+ - **Unicode Support**: Emoji, multi-byte characters, escape sequences
524
+ - **Data Integrity**: Boundary values, NULL handling, constraint management
525
+
526
+ ### 🎯 **Next Milestones**
527
+
528
+ **v0.2.0 - Primary Key & Index Support**
529
+
530
+ - Complete primary key constraint management
531
+ - Basic index creation and management
532
+ - Performance improvements for large schemas
533
+
534
+ **v0.3.0 - Foreign Keys & Advanced Constraints**
535
+
536
+ - Foreign key relationships with actions
537
+ - Unique and check constraints
538
+ - Constraint dependency resolution
539
+
540
+ **v0.4.0 - Views & Functions**
541
+
542
+ - Standard and materialized views
543
+ - Basic stored function support
544
+ - Enhanced schema validation