stepwise-migrations 1.0.16 → 1.0.18

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.
@@ -0,0 +1,35 @@
1
+ # This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node
2
+ # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs
3
+
4
+ name: Node.js CI
5
+
6
+ on:
7
+ push:
8
+ branches: [main]
9
+ pull_request:
10
+ branches: [main]
11
+ jobs:
12
+ build:
13
+ runs-on: ubuntu-latest
14
+
15
+ strategy:
16
+ matrix:
17
+ node-version: [18.x, 20.x, 22.x]
18
+ # See supported Node.js release schedule at https://nodejs.org/en/about/releases/
19
+
20
+ steps:
21
+ - uses: actions/checkout@v4
22
+
23
+ - name: Run docker-compose
24
+ uses: hoverkraft-tech/compose-action@v2.0.1
25
+ with:
26
+ compose-file: "./docker-compose.yml"
27
+
28
+ - name: Use Node.js ${{ matrix.node-version }}
29
+ uses: actions/setup-node@v4
30
+ with:
31
+ node-version: ${{ matrix.node-version }}
32
+ cache: "npm"
33
+ - run: npm ci
34
+ - run: npm run build
35
+ - run: npm test
package/README.md CHANGED
@@ -1,18 +1,48 @@
1
1
  # Stepwise Migrations
2
2
 
3
- [![npm version](https://badge.fury.io/js/stepwise-migrations.svg?icon=si%3Anpm&)](https://badge.fury.io/js/stepwise-migrations)
4
-
5
- A tool for managing Raw SQL migrations in a Postgres database.
3
+ A JavaScript CLI tool for managing Raw SQL migrations in a Postgres database.
6
4
  Loosely based on flyway.
7
5
 
6
+ [![npm version](https://badge.fury.io/js/stepwise-migrations.svg?icon=si%3Anpm&)](https://badge.fury.io/js/stepwise-migrations)
7
+ ![test workflow](https://github.com/github/docs/actions/workflows/test.yml/badge.svg)
8
+
9
+ ## Table of Contents
10
+
11
+ - [Stepwise Migrations](#stepwise-migrations)
12
+ - [Instructions](#instructions)
13
+ - [Usage](#usage)
14
+ - [Examples](#examples)
15
+ - [Migrate](#migrate)
16
+ - [Undo](#undo)
17
+ - [Validate](#validate)
18
+ - [Audit](#audit)
19
+ - [Info](#info)
20
+ - [Get Applied Script](#get-applied-script)
21
+ - [Drop](#drop)
22
+
8
23
  ## Instructions
9
24
 
10
- Up migrations are first sorted in ascending order based on filename.
11
- No subdirectories are read below the migration directory.
25
+ There are three types of migrations:
26
+
27
+ <b>Versioned migrations</b>
28
+
29
+ - The filename must end with `.sql`.
30
+ - These are always applied in ascending order based on filename.
31
+ - Once applied, the file cannot be altered or else an error will be thrown.
12
32
 
13
- Name the "up" migration files as `.sql` and the "down" migration files with the same name but suffixed with `.undo.sql`.
14
- e.g. `v1_users.sql` and `v1_users.undo.sql`.
15
- Down migrations are optional.
33
+ <b>Repeatable migrations</b>
34
+
35
+ - Are identified by the filename ending with `.repeatable.sql`
36
+ - For things like trigger functions
37
+ - Are always applied after all versioned migrations
38
+ - When altered, the new script is applied on next migration run
39
+
40
+ <b>Undo migrations</b>
41
+
42
+ - Run on the "undo" command
43
+ - Can only be run on versioned migrations
44
+ - Are applied in reverse order of the versioned migrations
45
+ - Must have the same filename as the versioned migration but suffixed with `.undo.sql`
16
46
 
17
47
  ## Usage
18
48
 
@@ -41,18 +71,20 @@ Options:
41
71
  --path <path> The path to the migrations directory
42
72
  --ssl true/false Whether to use SSL for the connection (default: false)
43
73
  --napply Number of up migrations to apply (default: all)
44
- --nundo Number of down migrations to apply (default: 1)
74
+ --nundo Number of undo migrations to apply (default: 1)
45
75
  --filename The filename to get the script for (default: last applied migration)
46
76
 
47
77
  Example:
48
78
  npx stepwise-migrations migrate \
49
79
  --connection=postgresql://postgres:postgres@127.0.0.1:5432/mydatabase \
50
80
  --schema=myschema \
51
- --path=./db/migration/
81
+ --path=./test/migrations-template/
52
82
  ```
53
83
 
54
84
  ## Examples
55
85
 
86
+ [comment]: <> (Start of examples)
87
+
56
88
  ### Migrate
57
89
 
58
90
  If all files are in a valid state, runs all the "up" migrations that have not been applied yet.
@@ -61,7 +93,7 @@ If all files are in a valid state, runs all the "up" migrations that have not be
61
93
  npx stepwise-migrations migrate \
62
94
  --connection=postgresql://postgres:postgres@127.0.0.1:5432/mydb \
63
95
  --schema=myschema \
64
- --path=./db/migration/
96
+ --path=./test/migrations-template/
65
97
  ```
66
98
 
67
99
  <details>
@@ -71,36 +103,46 @@ npx stepwise-migrations migrate \
71
103
  ```text
72
104
  Creating schema myschema... done!
73
105
  Creating stepwise_migration_events table... done!
74
- Applying migration v1_connect_session_table.sql... done!
75
- Applying migration v2_auth.sql... done!
76
- All done! Applied 2 migrations
77
- Migration state:
78
- ┌─────────┬────┬────────────────────────────────┬────────────┬──────────────────────────────┐
79
- (index) id │ name │ applied_by │ applied_at │
80
- ├─────────┼────┼────────────────────────────────┼────────────┼──────────────────────────────┤
81
- 0 │ 1 'v1_connect_session_table.sql''postgres''2024-11-24 05:40:41.211617'
82
- │ 1 │ 2 │ 'v2_auth.sql' │ 'postgres' │ '2024-11-24 05:40:41.214732' │
83
- └─────────┴────┴────────────────────────────────┴────────────┴──────────────────────────────┘
84
- Unapplied migrations:
106
+ Applying versioned migration v1_first.sql... done!
107
+ Applying versioned migration v2_second.sql... done!
108
+ Applying versioned migration v3_third.sql... done!
109
+ Applying repeatable migration v0_get_number.repeatable.sql... done!
110
+ All done! Applied 4 migrations
111
+ All applied versioned migrations:
112
+ ┌─────────┬────┬─────────────┬─────────────────┬────────────┬──────────────────────────────┐
113
+ (index)idtype │ filename applied_by applied_at
114
+ ├─────────┼────┼─────────────┼─────────────────┼────────────┼──────────────────────────────┤
115
+ │ 0 │ 1 │ 'versioned' │ 'v1_first.sql' │ 'postgres' │ '2024-11-25 15:25:55.799253' │
116
+ 1 │ 2 │ 'versioned' │ 'v2_second.sql' │ 'postgres' │ '2024-11-25 15:25:55.80306' │
117
+ │ 2 │ 3 │ 'versioned' │ 'v3_third.sql' │ 'postgres' │ '2024-11-25 15:25:55.80534' │
118
+ └─────────┴────┴─────────────┴─────────────────┴────────────┴──────────────────────────────┘
119
+ All applied repeatable migrations:
120
+ ┌─────────┬────┬──────────────┬────────────────────────────────┬────────────┬──────────────────────────────┐
121
+ │ (index) │ id │ type │ filename │ applied_by │ applied_at │
122
+ ├─────────┼────┼──────────────┼────────────────────────────────┼────────────┼──────────────────────────────┤
123
+ │ 0 │ 4 │ 'repeatable' │ 'v0_get_number.repeatable.sql' │ 'postgres' │ '2024-11-25 15:25:55.807375' │
124
+ └─────────┴────┴──────────────┴────────────────────────────────┴────────────┴──────────────────────────────┘
125
+ Unapplied versioned migrations:
85
126
  ┌─────────┐
86
127
  │ (index) │
87
128
  ├─────────┤
129
+ └─────────┘
88
130
  ```
89
131
 
90
132
  </details>
91
133
 
92
134
  ### Undo
93
135
 
94
- Runs a single down migration for the last applied migration.
95
- Can run multiple down migrations if the `--nundo` option is provided.
136
+ Runs a single undo migration for the last applied migration.
137
+ Can run multiple undo migrations if the `--nundo` option is provided.
96
138
 
97
139
  Command:
98
140
 
99
141
  ```bash
100
- npx stepwise-migrations down \
142
+ npx stepwise-migrations undo \
101
143
  --connection=postgresql://postgres:postgres@127.0.0.1:5432/mydb \
102
144
  --schema=myschema \
103
- --path=./db/migration/
145
+ --path=./test/migrations-template/
104
146
  ```
105
147
 
106
148
  <details>
@@ -108,20 +150,34 @@ npx stepwise-migrations down \
108
150
  <summary>Example output</summary>
109
151
 
110
152
  ```text
111
- Applying down migration v2_auth.undo.sql... done!
112
- All done! Applied 1 down migration
113
- Migration state:
114
- ┌─────────┬────┬────────────────────────────────┬────────────┬──────────────────────────────┐
115
- (index) id │ name │ applied_by │ applied_at │
116
- ├─────────┼────┼────────────────────────────────┼────────────┼──────────────────────────────┤
117
- │ 0 │ 1 │ 'v1_connect_session_table.sql' │ 'postgres' │ '2024-11-24 05:40:41.211617' │
118
- └─────────┴────┴────────────────────────────────┴────────────┴──────────────────────────────┘
119
- Unapplied migrations:
120
- ┌─────────┬───────────────┐
121
- │ (index) │ filename │
122
- ├─────────┼───────────────┤
123
- │ 0 │ 'v2_auth.sql' │
124
- └─────────┴───────────────┘
153
+ [
154
+ {
155
+ type: 'undo',
156
+ filename: 'v3_third.undo.sql',
157
+ script: 'drop table third;'
158
+ }
159
+ ]
160
+ Applying undo migration v3_third.undo.sql... done!
161
+ All done! Performed 1 undo migration
162
+ All applied versioned migrations:
163
+ ┌─────────┬────┬─────────────┬─────────────────┬────────────┬──────────────────────────────┐
164
+ │ (index) │ id │ type │ filename │ applied_by │ applied_at │
165
+ ├─────────┼────┼─────────────┼─────────────────┼────────────┼──────────────────────────────┤
166
+ │ 0 │ 1 │ 'versioned' │ 'v1_first.sql' │ 'postgres' │ '2024-11-25 15:25:55.799253' │
167
+ │ 1 │ 2 │ 'versioned' │ 'v2_second.sql' │ 'postgres' │ '2024-11-25 15:25:55.80306' │
168
+ │ 2 │ 3 │ 'versioned' │ 'v3_third.sql' │ 'postgres' │ '2024-11-25 15:25:55.80534' │
169
+ └─────────┴────┴─────────────┴─────────────────┴────────────┴──────────────────────────────┘
170
+ All applied repeatable migrations:
171
+ ┌─────────┬────┬──────────────┬────────────────────────────────┬────────────┬──────────────────────────────┐
172
+ │ (index) │ id │ type │ filename │ applied_by │ applied_at │
173
+ ├─────────┼────┼──────────────┼────────────────────────────────┼────────────┼──────────────────────────────┤
174
+ │ 0 │ 4 │ 'repeatable' │ 'v0_get_number.repeatable.sql' │ 'postgres' │ '2024-11-25 15:25:55.807375' │
175
+ └─────────┴────┴──────────────┴────────────────────────────────┴────────────┴──────────────────────────────┘
176
+ Unapplied versioned migrations:
177
+ ┌─────────┐
178
+ │ (index) │
179
+ ├─────────┤
180
+ └─────────┘
125
181
  ```
126
182
 
127
183
  </details>
@@ -134,7 +190,7 @@ Validates the migration files and the stepwise_migration_events table.
134
190
  npx stepwise-migrations validate \
135
191
  --connection=postgresql://postgres:postgres@127.0.0.1:5432/mydb \
136
192
  --schema=myschema \
137
- --path=./db/migration/
193
+ --path=./test/migrations-template/
138
194
  ```
139
195
 
140
196
  <details>
@@ -143,18 +199,25 @@ npx stepwise-migrations validate \
143
199
 
144
200
  ```text
145
201
  Validation passed
146
- Migration state:
147
- ┌─────────┬────┬────────────────────────────────┬────────────┬──────────────────────────────┐
148
- │ (index) │ id │ name │ applied_by │ applied_at │
149
- ├─────────┼────┼────────────────────────────────┼────────────┼──────────────────────────────┤
150
- │ 0 │ 1 │ 'v1_connect_session_table.sql' │ 'postgres' │ '2024-11-24 05:40:41.211617' │
151
- └─────────┴────┴────────────────────────────────┴────────────┴──────────────────────────────┘
152
- Unapplied migrations:
153
- ┌─────────┬───────────────┐
154
- │ (index) │ filename │
155
- ├─────────┼───────────────┤
156
- │ 0 │ 'v2_auth.sql' │
157
- └─────────┴───────────────┘
202
+ All applied versioned migrations:
203
+ ┌─────────┬────┬─────────────┬─────────────────┬────────────┬──────────────────────────────┐
204
+ │ (index) │ id │ type filename │ applied_by │ applied_at │
205
+ ├─────────┼────┼─────────────┼─────────────────┼────────────┼──────────────────────────────┤
206
+ │ 0 │ 1 │ 'versioned' │ 'v1_first.sql' │ 'postgres' │ '2024-11-25 15:25:55.799253' │
207
+ │ 1 │ 2 │ 'versioned' │ 'v2_second.sql' │ 'postgres' │ '2024-11-25 15:25:55.80306' │
208
+ └─────────┴────┴─────────────┴─────────────────┴────────────┴──────────────────────────────┘
209
+ All applied repeatable migrations:
210
+ ┌─────────┬────┬──────────────┬────────────────────────────────┬────────────┬──────────────────────────────┐
211
+ │ (index) │ id │ type │ filename │ applied_by │ applied_at │
212
+ ├─────────┼────┼──────────────┼────────────────────────────────┼────────────┼──────────────────────────────┤
213
+ │ 0 │ 4 │ 'repeatable' │ 'v0_get_number.repeatable.sql' │ 'postgres' │ '2024-11-25 15:25:55.807375' │
214
+ └─────────┴────┴──────────────┴────────────────────────────────┴────────────┴──────────────────────────────┘
215
+ Unapplied versioned migrations:
216
+ ┌─────────┬─────────────┬────────────────┐
217
+ │ (index) │ type │ filename │
218
+ ├─────────┼─────────────┼────────────────┤
219
+ │ 0 │ 'versioned' │ 'v3_third.sql' │
220
+ └─────────┴─────────────┴────────────────┘
158
221
  ```
159
222
 
160
223
  </details>
@@ -163,16 +226,17 @@ Unapplied migrations:
163
226
 
164
227
  <summary>Example output - script changed error</summary>
165
228
 
166
- ```sql
167
- Error: migration v1_connect_session_table.sql has been modified, aborting.
168
- "expire" timestamp(6) NOT NULL
169
- )
170
- WITH (OIDS=FALSE);
171
- -ALTER TABLE "session" ADD CONSTRAINT "session_pkey" PRIMARY KEY ("sid") NOT DEFERRABLE INITIALLY IMMEDIATE;
172
-
173
- +ALTER TABLE "session" ADD CONSTRAINT "session_pkey" PRIMARY KEY ("sid") NOT DEFERRABLE INITIALLY IMMEDIATE;
229
+ ```
230
+ There were errors loading the migration state. Please fix the errors and try again.
231
+ - Versioned migration v1_first.sql has been altered. Cannot migrate in current state.
232
+
233
+ @@ -2,3 +2,5 @@ create table first (
234
+ id serial primary key,
235
+ name text not null
236
+ );
174
237
  +
175
- +ALTER TABLE "session" ADD INDEX "session_sid" ON "session" (sid);
238
+ +ALTER TABLE first ADD COLUMN age int;
239
+
176
240
  ```
177
241
 
178
242
  </details>
@@ -185,7 +249,7 @@ Shows the audit history for the migrations in the database.
185
249
  npx stepwise-migrations audit \
186
250
  --connection=postgresql://postgres:postgres@127.0.0.1:5432/mydb \
187
251
  --schema=myschema \
188
- --path=./db/migration/
252
+ --path=./test/migrations-template/
189
253
  ```
190
254
 
191
255
  <details>
@@ -193,14 +257,16 @@ npx stepwise-migrations audit \
193
257
  <summary>Example output</summary>
194
258
 
195
259
  ```text
196
- Audit history:
197
- ┌─────────┬────┬────────┬────────────────────────────────┬────────────┬──────────────────────────────┐
198
- │ (index) │ id │ type name │ applied_by │ applied_at │
199
- ├─────────┼────┼────────┼────────────────────────────────┼────────────┼──────────────────────────────┤
200
- │ 0 │ 1 │ 'up' │ 'v1_connect_session_table.sql' │ 'postgres' │ '2024-11-24 05:40:41.211617' │
201
- │ 1 │ 2 │ 'up' │ 'v2_auth.sql' │ 'postgres' │ '2024-11-24 05:40:41.214732'
202
- │ 2 │ 3 │ 'down' │ 'v2_auth.undo.sql' │ 'postgres' │ '2024-11-24 05:41:34.541462'
203
- └─────────┴────┴────────┴────────────────────────────────┴────────────┴──────────────────────────────┘
260
+ Event history:
261
+ ┌─────────┬────┬──────────────┬────────────────────────────────┬────────────┬──────────────────────────────┐
262
+ │ (index) │ id │ type filename │ applied_by │ applied_at │
263
+ ├─────────┼────┼──────────────┼────────────────────────────────┼────────────┼──────────────────────────────┤
264
+ │ 0 │ 1 │ 'versioned' │ 'v1_first.sql' │ 'postgres' │ '2024-11-25 15:25:55.799253' │
265
+ │ 1 │ 2 │ 'versioned' │ 'v2_second.sql' │ 'postgres' │ '2024-11-25 15:25:55.80306'
266
+ │ 2 │ 3 │ 'versioned' │ 'v3_third.sql' │ 'postgres' │ '2024-11-25 15:25:55.80534'
267
+ │ 3 │ 4 │ 'repeatable' │ 'v0_get_number.repeatable.sql' │ 'postgres' │ '2024-11-25 15:25:55.807375' │
268
+ │ 4 │ 5 │ 'undo' │ 'v3_third.undo.sql' │ 'postgres' │ '2024-11-25 15:25:56.588007' │
269
+ └─────────┴────┴──────────────┴────────────────────────────────┴────────────┴──────────────────────────────┘
204
270
  ```
205
271
 
206
272
  </details>
@@ -215,7 +281,7 @@ Command:
215
281
  npx stepwise-migrations info \
216
282
  --connection=postgresql://postgres:postgres@127.0.0.1:5432/mydb \
217
283
  --schema=myschema \
218
- --path=./db/migration/
284
+ --path=./test/migrations-template/
219
285
  ```
220
286
 
221
287
  <details>
@@ -223,17 +289,30 @@ npx stepwise-migrations info \
223
289
  <summary>Example output</summary>
224
290
 
225
291
  ```text
226
- Migration state:
227
- ┌─────────┬────┬────────────────────────────────┬────────────┬──────────────────────────────┐
228
- │ (index) │ id │ name │ applied_by │ applied_at │
229
- ├─────────┼────┼────────────────────────────────┼────────────┼──────────────────────────────┤
230
- │ 0 │ 1 │ 'v1_connect_session_table.sql' │ 'postgres' │ '2024-11-24 05:40:41.211617' │
231
- └─────────┴────┴────────────────────────────────┴────────────┴──────────────────────────────┘
292
+ All applied versioned migrations:
293
+ ┌─────────┬────┬─────────────┬─────────────────┬────────────┬──────────────────────────────┐
294
+ │ (index) │ id │ type filename │ applied_by │ applied_at │
295
+ ├─────────┼────┼─────────────┼─────────────────┼────────────┼──────────────────────────────┤
296
+ │ 0 │ 1 │ 'versioned' │ 'v1_first.sql' │ 'postgres' │ '2024-11-25 15:25:55.799253' │
297
+ │ 1 │ 2 │ 'versioned' │ 'v2_second.sql' │ 'postgres' │ '2024-11-25 15:25:55.80306' │
298
+ └─────────┴────┴─────────────┴─────────────────┴────────────┴──────────────────────────────┘
299
+ All applied repeatable migrations:
300
+ ┌─────────┬────┬──────────────┬────────────────────────────────┬────────────┬──────────────────────────────┐
301
+ │ (index) │ id │ type │ filename │ applied_by │ applied_at │
302
+ ├─────────┼────┼──────────────┼────────────────────────────────┼────────────┼──────────────────────────────┤
303
+ │ 0 │ 4 │ 'repeatable' │ 'v0_get_number.repeatable.sql' │ 'postgres' │ '2024-11-25 15:25:55.807375' │
304
+ └─────────┴────┴──────────────┴────────────────────────────────┴────────────┴──────────────────────────────┘
305
+ Unapplied versioned migrations:
306
+ ┌─────────┬─────────────┬────────────────┐
307
+ │ (index) │ type │ filename │
308
+ ├─────────┼─────────────┼────────────────┤
309
+ │ 0 │ 'versioned' │ 'v3_third.sql' │
310
+ └─────────┴─────────────┴────────────────┘
232
311
  ```
233
312
 
234
313
  </details>
235
314
 
236
- ### Get Script
315
+ ### Get Applied Script
237
316
 
238
317
  Gets the script for the last applied migration.
239
318
  Can get the script for a specific migration if the `--filename` option is provided.
@@ -241,24 +320,22 @@ Can get the script for a specific migration if the `--filename` option is provid
241
320
  Command:
242
321
 
243
322
  ```bash
244
- npx stepwise-migrations get-script --filename v2_auth.sql \
323
+ npx stepwise-migrations get-applied-script --filename v1_first.sql \
245
324
  --connection=postgresql://postgres:postgres@127.0.0.1:5432/mydb \
246
325
  --schema=myschema \
247
- --path=./db/migration/
326
+ --path=./test/migrations-template/
248
327
  ```
249
328
 
250
329
  <details>
251
330
 
252
331
  <summary>Example output</summary>
253
332
 
254
- ```sql
255
- CREATE TABLE "users" (
256
- id bigserial primary key,
257
- email text unique not null,
258
- first_name text not null,
259
- last_name text not null,
260
- created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
333
+ ```text
334
+ create table first (
335
+ id serial primary key,
336
+ name text not null
261
337
  );
338
+
262
339
  ```
263
340
 
264
341
  </details>
@@ -272,7 +349,8 @@ Command:
272
349
  ```bash
273
350
  npx stepwise-migrations drop \
274
351
  --connection=postgresql://postgres:postgres@127.0.0.1:5432/mydb \
275
- --schema=myschema
352
+ --schema=myschema \
353
+ --path=./test/migrations-template/
276
354
  ```
277
355
 
278
356
  <details>
@@ -280,7 +358,9 @@ npx stepwise-migrations drop \
280
358
  <summary>Example output</summary>
281
359
 
282
360
  ```text
283
- Dropping the tables, schema and migration stepwise_migration_events table... done!
361
+ Dropping the tables, schema and migration history table... done!
284
362
  ```
285
363
 
286
364
  </details>
365
+
366
+ [comment]: <> (End of examples)
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ const promises_1 = __importDefault(require("fs/promises"));
16
+ const utils_1 = require("../test/utils");
17
+ const next = (readme, from) => __awaiter(void 0, void 0, void 0, function* () {
18
+ const end = readme.indexOf("[comment]: <> (End of examples)");
19
+ if (readme.indexOf("```bash", from) < from ||
20
+ readme.indexOf("```bash", from) >= end) {
21
+ return { nextReadme: readme, nextIndex: -1 };
22
+ }
23
+ const startScript = readme.indexOf("```bash", from) + 8;
24
+ const endScript = readme.indexOf("```", startScript);
25
+ const script = readme.slice(startScript, endScript);
26
+ console.log(script);
27
+ const { output } = yield (0, utils_1.execute)(script);
28
+ // console.log(output);
29
+ const startOutput = readme.indexOf("```text", endScript) + 8;
30
+ const endOutput = readme.indexOf("```", startOutput);
31
+ return {
32
+ nextReadme: readme.slice(0, startOutput) + output + readme.slice(endOutput),
33
+ nextIndex: endOutput + 3,
34
+ };
35
+ });
36
+ (() => __awaiter(void 0, void 0, void 0, function* () {
37
+ let readme = yield promises_1.default.readFile("./README.md", "utf8");
38
+ const { output } = yield (0, utils_1.execute)(`npm exec stepwise-migrations drop -- \\
39
+ --connection=postgresql://postgres:postgres@127.0.0.1:5432/mydb \
40
+ --schema=myschema \\
41
+ --path=./test/migrations-template/ `);
42
+ let index = readme.indexOf("[comment]: <> (Start of examples)");
43
+ let i = 0;
44
+ while (true) {
45
+ const { nextReadme, nextIndex } = yield next(readme, index);
46
+ if (nextIndex === -1) {
47
+ break;
48
+ }
49
+ readme = nextReadme;
50
+ index = nextIndex;
51
+ i++;
52
+ // if (i > 1) break;
53
+ }
54
+ yield promises_1.default.writeFile("./README.md", readme);
55
+ }))();
package/dist/src/state.js CHANGED
@@ -103,7 +103,7 @@ const eventsToApplied = (events) => {
103
103
  }
104
104
  else if ((0, exports.getUndoFilename)(appliedVersionedMigrations[appliedVersionedMigrations.length - 1]
105
105
  .filename) !== event.filename) {
106
- errors.push("Events table is in a bad state: down migration does not match the most recently applied migration");
106
+ errors.push("Events table is in a bad state: undo migration does not match the most recently applied migration");
107
107
  break;
108
108
  }
109
109
  else {
package/dist/src/utils.js CHANGED
@@ -14,6 +14,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.sliceFromFirstNull = exports.exitIfNotInitialized = exports.abortIfErrors = exports.fileExists = exports.printMigrationHistory = exports.printMigrationHistoryAndUnappliedMigrations = exports.readMigrationFiles = exports.filenameToType = exports.validateArgs = exports.usage = void 0;
16
16
  const promises_1 = __importDefault(require("fs/promises"));
17
+ const git_diff_1 = __importDefault(require("git-diff"));
17
18
  const path_1 = __importDefault(require("path"));
18
19
  exports.usage = `
19
20
  Usage: stepwise-migrations [command] [options]
@@ -34,7 +35,7 @@ Options:
34
35
  --path <path> The path to the migrations directory
35
36
  --ssl true/false Whether to use SSL for the connection (default: false)
36
37
  --napply Number of up migrations to apply (default: all)
37
- --nundo Number of down migrations to apply (default: 1)
38
+ --nundo Number of undo migrations to apply (default: 1)
38
39
 
39
40
  Example:
40
41
  npx stepwise-migrations migrate \\
@@ -87,7 +88,9 @@ const readMigrationFiles = (directory, appliedVersionedMigrations) => __awaiter(
87
88
  if (file &&
88
89
  file.type === "versioned" &&
89
90
  file.script !== appliedMigration.script) {
90
- errors.push(`Versioned migration ${appliedMigration.filename} has been altered. Cannot migrate in current state.`);
91
+ errors.push(`Versioned migration ${appliedMigration.filename} has been altered. Cannot migrate in current state. \n\n${(0, git_diff_1.default)(appliedMigration.script, file.script, {
92
+ color: true,
93
+ })}\n\n`);
91
94
  }
92
95
  }
93
96
  return { files: results, errors };
@@ -16,8 +16,8 @@ const node_assert_1 = __importDefault(require("node:assert"));
16
16
  const node_fs_1 = __importDefault(require("node:fs"));
17
17
  const node_test_1 = require("node:test");
18
18
  const utils_1 = require("./utils");
19
- const connection = "postgresql://postgres:postgres@127.0.0.1:5432/stepwise-db";
20
- const schema = "stepwise";
19
+ const connection = "postgresql://postgres:postgres@127.0.0.1:5432/mydb";
20
+ const schema = "testschema";
21
21
  const paths = {
22
22
  valid: "./test/migrations-valid",
23
23
  invalid: "./test/migrations-invalid",
@@ -1,9 +1,9 @@
1
1
  services:
2
- stepwise-db:
3
- container_name: stepwise-db
2
+ mydb:
3
+ container_name: mydb
4
4
  image: postgres:17.2
5
5
  environment:
6
- POSTGRES_DB: stepwise-db
6
+ POSTGRES_DB: mydb
7
7
  POSTGRES_USER: postgres
8
8
  POSTGRES_PASSWORD: postgres
9
9
  healthcheck:
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "stepwise-migrations",
3
- "version": "1.0.16",
3
+ "version": "1.0.18",
4
4
  "description": "",
5
- "main": "dist/src/index.js",
5
+ "main": "./dist/src/index.js",
6
6
  "scripts": {
7
7
  "build": "tsc",
8
8
  "test": "npm run build; glob -c \"tsx --test --test-reporter spec \" \"./test/**/*.test.ts\"",
@@ -24,7 +24,7 @@
24
24
  "tsx": "^4.19.2"
25
25
  },
26
26
  "bin": {
27
- "stepwise-migrations": "dist/src/index.js"
27
+ "stepwise-migrations": "./dist/src/index.js"
28
28
  },
29
29
  "dependencies": {
30
30
  "git-diff": "^2.0.6",
@@ -0,0 +1,50 @@
1
+ import fs from "fs/promises";
2
+ import { execute } from "../test/utils";
3
+
4
+ const next = async (readme: string, from: number) => {
5
+ const end = readme.indexOf("[comment]: <> (End of examples)");
6
+
7
+ if (
8
+ readme.indexOf("```bash", from) < from ||
9
+ readme.indexOf("```bash", from) >= end
10
+ ) {
11
+ return { nextReadme: readme, nextIndex: -1 };
12
+ }
13
+
14
+ const startScript = readme.indexOf("```bash", from) + 8;
15
+ const endScript = readme.indexOf("```", startScript);
16
+ const script = readme.slice(startScript, endScript);
17
+ console.log(script);
18
+ const { output } = await execute(script);
19
+ // console.log(output);
20
+ const startOutput = readme.indexOf("```text", endScript) + 8;
21
+ const endOutput = readme.indexOf("```", startOutput);
22
+ return {
23
+ nextReadme: readme.slice(0, startOutput) + output + readme.slice(endOutput),
24
+ nextIndex: endOutput + 3,
25
+ };
26
+ };
27
+
28
+ (async () => {
29
+ let readme = await fs.readFile("./README.md", "utf8");
30
+ const { output } = await execute(`npm exec stepwise-migrations drop -- \\
31
+ --connection=postgresql://postgres:postgres@127.0.0.1:5432/mydb \
32
+ --schema=myschema \\
33
+ --path=./test/migrations-template/ `);
34
+
35
+ let index = readme.indexOf("[comment]: <> (Start of examples)");
36
+ let i = 0;
37
+ while (true) {
38
+ const { nextReadme, nextIndex } = await next(readme, index);
39
+ if (nextIndex === -1) {
40
+ break;
41
+ }
42
+
43
+ readme = nextReadme;
44
+ index = nextIndex;
45
+ i++;
46
+ // if (i > 1) break;
47
+ }
48
+
49
+ await fs.writeFile("./README.md", readme);
50
+ })();
package/src/state.ts CHANGED
@@ -146,7 +146,7 @@ export const eventsToApplied = (
146
146
  ) !== event.filename
147
147
  ) {
148
148
  errors.push(
149
- "Events table is in a bad state: down migration does not match the most recently applied migration"
149
+ "Events table is in a bad state: undo migration does not match the most recently applied migration"
150
150
  );
151
151
  break;
152
152
  } else {
package/src/utils.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import fs from "fs/promises";
2
+ import gitDiff from "git-diff";
2
3
  import path from "path";
3
4
  import {
4
5
  AppliedMigration,
@@ -26,7 +27,7 @@ Options:
26
27
  --path <path> The path to the migrations directory
27
28
  --ssl true/false Whether to use SSL for the connection (default: false)
28
29
  --napply Number of up migrations to apply (default: all)
29
- --nundo Number of down migrations to apply (default: 1)
30
+ --nundo Number of undo migrations to apply (default: 1)
30
31
 
31
32
  Example:
32
33
  npx stepwise-migrations migrate \\
@@ -89,7 +90,15 @@ export const readMigrationFiles = async (
89
90
  file.script !== appliedMigration.script
90
91
  ) {
91
92
  errors.push(
92
- `Versioned migration ${appliedMigration.filename} has been altered. Cannot migrate in current state.`
93
+ `Versioned migration ${
94
+ appliedMigration.filename
95
+ } has been altered. Cannot migrate in current state. \n\n${gitDiff(
96
+ appliedMigration.script,
97
+ file.script,
98
+ {
99
+ color: true,
100
+ }
101
+ )}\n\n`
93
102
  );
94
103
  }
95
104
  }
@@ -2,8 +2,8 @@ import assert from "node:assert";
2
2
  import fs from "node:fs";
3
3
  import { beforeEach, describe, it } from "node:test";
4
4
  import { assertIncludesAll, assertIncludesExcludesAll, execute } from "./utils";
5
- const connection = "postgresql://postgres:postgres@127.0.0.1:5432/stepwise-db";
6
- const schema = "stepwise";
5
+ const connection = "postgresql://postgres:postgres@127.0.0.1:5432/mydb";
6
+ const schema = "testschema";
7
7
 
8
8
  const paths = {
9
9
  valid: "./test/migrations-valid",
@@ -2,3 +2,5 @@ create table first (
2
2
  id serial primary key,
3
3
  name text not null
4
4
  );
5
+
6
+ ALTER TABLE first ADD COLUMN age int;