pgterra 0.1.2 → 0.2.1

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 (4) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +177 -47
  3. package/dist/index.js +21562 -93270
  4. package/package.json +11 -7
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Terra Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,69 +1,94 @@
1
- # pgterra
1
+ <div align="center">
2
+ <img src="assets/readme-hero.png" alt="Terra - Declarative PostgreSQL schema management" />
3
+ <br />
4
+ <br />
5
+ <a href="https://github.com/elitan/terra/stargazers">
6
+ <img alt="GitHub Stars" src="https://img.shields.io/github/stars/elitan/terra?style=social" />
7
+ </a>
8
+ <a href="https://discord.gg/PtePt2wx7R">
9
+ <img alt="Discord" src="https://img.shields.io/badge/Discord-Join%20Chat-5865F2?logo=discord&logoColor=white" />
10
+ </a>
11
+ <a href="https://x.com/elitasson">
12
+ <img alt="Twitter Follow" src="https://img.shields.io/twitter/follow/elitasson?style=social" />
13
+ </a>
14
+ </div>
2
15
 
3
- Declarative schema management for Postgres. Define your desired schema, pgterra handles the migrations.
16
+ <br />
4
17
 
5
- ## Quick Start
18
+ # Terra
19
+
20
+ Declarative PostgreSQL schema management.
21
+
22
+ ## Install
6
23
 
7
24
  ```bash
8
25
  npm install -g pgterra
9
26
  ```
10
27
 
11
- ## How it works
28
+ ## Usage
12
29
 
13
- **1. Start with a schema:**
30
+ **1. Create schema.sql:**
14
31
 
15
32
  ```sql
16
- -- schema.sql
17
33
  CREATE TABLE users (
18
34
  id SERIAL PRIMARY KEY,
19
- email VARCHAR(255) NOT NULL UNIQUE,
20
- created_at TIMESTAMP DEFAULT NOW()
35
+ email VARCHAR(255) NOT NULL UNIQUE
21
36
  );
22
37
  ```
23
38
 
39
+ **2. Preview changes:**
40
+
41
+ ```bash
42
+ pgterra plan
43
+ ```
44
+
45
+ **3. Apply:**
46
+
24
47
  ```bash
25
- pgterra apply # Creates the table
48
+ pgterra apply
26
49
  ```
27
50
 
28
- **2. Update your schema declaratively:**
51
+ **4. Update schema.sql:**
29
52
 
30
53
  ```sql
31
- -- schema.sql
32
54
  CREATE TABLE users (
33
55
  id SERIAL PRIMARY KEY,
34
56
  email VARCHAR(255) NOT NULL UNIQUE,
35
- full_name VARCHAR(200) NOT NULL, -- new column
36
- is_active BOOLEAN DEFAULT true, -- another new column
37
- created_at TIMESTAMP DEFAULT NOW()
57
+ name VARCHAR(100) NOT NULL, -- added
58
+ active BOOLEAN DEFAULT true -- added
38
59
  );
39
60
 
40
- CREATE TABLE posts ( -- new table
61
+ CREATE TABLE posts ( -- added
41
62
  id SERIAL PRIMARY KEY,
42
63
  title VARCHAR(255) NOT NULL,
43
- user_id INTEGER REFERENCES users(id),
44
- created_at TIMESTAMP DEFAULT NOW()
64
+ user_id INTEGER NOT NULL,
65
+ CONSTRAINT fk_user FOREIGN KEY (user_id) REFERENCES users(id)
45
66
  );
67
+
68
+ CREATE INDEX idx_user_email ON users (LOWER(email)); -- added
46
69
  ```
47
70
 
48
- **3. pgterra calculates the migration:**
71
+ **5. Terra generates the ALTER statements:**
49
72
 
50
73
  ```bash
51
74
  $ pgterra plan
52
- 📋 Analyzing schema changes...
75
+ ALTER TABLE users ADD COLUMN name VARCHAR(100) NOT NULL
76
+ ALTER TABLE users ADD COLUMN active BOOLEAN DEFAULT true
77
+ CREATE TABLE posts (...)
78
+ CREATE INDEX idx_user_email ON users (LOWER(email))
53
79
 
54
- Planned changes:
55
- 1. ALTER TABLE users ADD COLUMN full_name VARCHAR(200) NOT NULL
56
- 2. ALTER TABLE users ADD COLUMN is_active BOOLEAN DEFAULT true
57
- 3. CREATE TABLE posts (id SERIAL PRIMARY KEY, title VARCHAR(255) NOT NULL, user_id INTEGER REFERENCES users(id), created_at TIMESTAMP DEFAULT NOW())
58
-
59
- $ pgterra apply # Applies the changes safely
80
+ $ pgterra apply
60
81
  ```
61
82
 
62
- **That's it.** No migration files, no manual ALTER statements, no dependency ordering. Just define what you want.
63
-
64
83
  ## Configuration
65
84
 
66
- Set your database connection:
85
+ Database connection via `DATABASE_URL` or individual variables:
86
+
87
+ ```bash
88
+ export DATABASE_URL="postgres://user:password@localhost:5432/mydb"
89
+ ```
90
+
91
+ Or:
67
92
 
68
93
  ```bash
69
94
  export DB_HOST=localhost
@@ -73,37 +98,142 @@ export DB_USER=postgres
73
98
  export DB_PASSWORD=password
74
99
  ```
75
100
 
76
- ## Features
101
+ ## What's supported
102
+
103
+ **Tables & Columns:**
104
+ All PostgreSQL column types, default values, NOT NULL constraints
105
+
106
+ **Functions & Procedures:**
107
+ User-defined functions and procedures with full PostgreSQL feature support
108
+
109
+ **Triggers:**
110
+ Table triggers with BEFORE/AFTER/INSTEAD OF timing
111
+
112
+ **Sequences:**
113
+ Custom sequences with configurable properties
114
+
115
+ **Constraints:**
116
+ ```sql
117
+ -- Primary keys
118
+ id SERIAL PRIMARY KEY
119
+
120
+ -- Foreign keys with actions
121
+ CONSTRAINT fk_user FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
122
+
123
+ -- Check constraints
124
+ CONSTRAINT check_positive CHECK (quantity > 0)
125
+
126
+ -- Unique constraints
127
+ email VARCHAR(255) UNIQUE
128
+ CONSTRAINT unique_email UNIQUE (email, domain)
129
+ ```
130
+
131
+ **Indexes:**
132
+ ```sql
133
+ -- Basic
134
+ CREATE INDEX idx_email ON users (email);
135
+
136
+ -- Partial
137
+ CREATE INDEX idx_active_users ON users (email) WHERE active = true;
138
+
139
+ -- Expression
140
+ CREATE INDEX idx_lower_email ON users (LOWER(email));
141
+
142
+ -- Concurrent (built automatically when safe)
143
+ ```
144
+
145
+ **ENUM types:**
146
+ ```sql
147
+ CREATE TYPE status AS ENUM ('pending', 'active', 'inactive');
148
+
149
+ CREATE TABLE users (
150
+ id SERIAL PRIMARY KEY,
151
+ status status NOT NULL
152
+ );
153
+ ```
154
+
155
+ **Views:**
156
+ ```sql
157
+ CREATE VIEW active_users AS
158
+ SELECT id, email FROM users WHERE active = true;
159
+
160
+ CREATE MATERIALIZED VIEW user_stats AS
161
+ SELECT COUNT(*) as total FROM users;
162
+ ```
163
+
164
+ **Functions:**
165
+ ```sql
166
+ CREATE FUNCTION calculate_total(quantity INT, price DECIMAL)
167
+ RETURNS DECIMAL
168
+ AS $$
169
+ SELECT quantity * price
170
+ $$
171
+ LANGUAGE SQL IMMUTABLE;
172
+ ```
77
173
 
78
- - ✅ Tables, columns, and data types
79
- - ✅ Primary keys, foreign keys, check constraints, unique constraints
80
- - Indexes (btree, gin, gist, partial, expression-based)
81
- - ✅ ENUM types
82
- - ✅ Dependency resolution for complex schemas
83
- - Data-safe migrations with validation
84
- - ✅ Destructive operation protection
174
+ **Procedures:**
175
+ ```sql
176
+ CREATE PROCEDURE archive_old_posts(days_old INT)
177
+ LANGUAGE SQL
178
+ AS $$
179
+ DELETE FROM posts WHERE created_at < NOW() - INTERVAL '1 day' * days_old;
180
+ $$;
181
+ ```
182
+
183
+ **Triggers:**
184
+ ```sql
185
+ -- First create a trigger function
186
+ CREATE FUNCTION update_modified_timestamp()
187
+ RETURNS TRIGGER
188
+ AS $$
189
+ BEGIN
190
+ NEW.modified_at = NOW();
191
+ RETURN NEW;
192
+ END;
193
+ $$
194
+ LANGUAGE plpgsql;
195
+
196
+ -- Then create the trigger
197
+ CREATE TRIGGER set_modified_timestamp
198
+ BEFORE UPDATE ON users
199
+ FOR EACH ROW
200
+ EXECUTE FUNCTION update_modified_timestamp();
201
+ ```
85
202
 
86
- ## Why declarative?
203
+ **Sequences:**
204
+ ```sql
205
+ CREATE SEQUENCE custom_id_seq
206
+ START 1000
207
+ INCREMENT 1
208
+ CACHE 20;
209
+ ```
87
210
 
88
- Like Terraform for infrastructure, pgterra lets you define *what* you want, not *how* to get there:
211
+ ## Commands
89
212
 
90
- - **Version control your complete schema** - not scattered migration files
91
- - **No migration ordering issues** - pgterra handles dependencies
92
- - **Easier code reviews** - see the full schema state, not just changes
93
- - **Safe schema changes** - preview before applying, with rollback support
213
+ ```bash
214
+ pgterra plan # Preview changes
215
+ pgterra plan -f custom.sql # Use custom schema file
216
+ pgterra apply # Apply changes
217
+ pgterra apply -f custom.sql # Apply from custom file
218
+ ```
94
219
 
95
220
  ## Development
96
221
 
222
+ Requires [Bun](https://bun.sh):
223
+
97
224
  ```bash
98
- git clone https://github.com/elitan/pgterra.git
99
- cd pgterra
225
+ git clone https://github.com/elitan/terra.git
226
+ cd terra
100
227
  bun install
101
228
 
102
- # Set up test database connection
103
- export DATABASE_URL="postgres://user:password@localhost:5432/test_db"
229
+ # Start test database
230
+ docker compose up -d
104
231
 
105
232
  # Run tests
233
+ export DATABASE_URL="postgres://test_user:test_password@localhost:5487/sql_terraform_test"
106
234
  bun test
107
235
  ```
108
236
 
109
- **Note:** Tests require a `DATABASE_URL` environment variable pointing to a PostgreSQL database. The tests will create and drop tables as needed, so use a dedicated test database.
237
+ ## License
238
+
239
+ MIT