@deterministic-code/migraters 0.0.0-stage → 0.0.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 (162) hide show
  1. package/bundle.yaml +262 -0
  2. package/dist/abstractions/migrater.d.ts +28 -0
  3. package/dist/abstractions/migrater.js +1 -0
  4. package/dist/abstractions/sql-dialect-base.d.ts +16 -0
  5. package/dist/abstractions/sql-dialect-base.js +19 -0
  6. package/dist/abstractions/sql-dialect-factory.d.ts +8 -0
  7. package/dist/abstractions/sql-dialect-factory.js +22 -0
  8. package/dist/abstractions/sql-dialect.d.ts +16 -0
  9. package/dist/abstractions/sql-dialect.js +1 -0
  10. package/dist/bin/migrate-create.d.ts +2 -0
  11. package/dist/bin/migrate-create.js +71 -0
  12. package/dist/bin/migrate-down.d.ts +2 -0
  13. package/dist/bin/migrate-down.js +135 -0
  14. package/dist/bin/migrate-init.d.ts +2 -0
  15. package/dist/bin/migrate-init.js +77 -0
  16. package/dist/bin/migrate-setup.d.ts +2 -0
  17. package/dist/bin/migrate-setup.js +87 -0
  18. package/dist/bin/migrate-up.d.ts +2 -0
  19. package/dist/bin/migrate-up.js +97 -0
  20. package/dist/cli-contract.d.ts +6 -0
  21. package/dist/cli-contract.js +19 -0
  22. package/dist/cli-spec.d.ts +24 -0
  23. package/dist/cli-spec.js +33 -0
  24. package/dist/cli.d.ts +9 -0
  25. package/dist/cli.js +41 -0
  26. package/dist/create-sequence.d.ts +4 -0
  27. package/dist/create-sequence.js +16 -0
  28. package/dist/datasource-migrate.d.ts +31 -0
  29. package/dist/datasource-migrate.js +206 -0
  30. package/dist/dialects/mysql-dialect.d.ts +12 -0
  31. package/dist/dialects/mysql-dialect.js +56 -0
  32. package/dist/dialects/oracle-dialect.d.ts +18 -0
  33. package/dist/dialects/oracle-dialect.js +76 -0
  34. package/dist/dialects/postgres-dialect.d.ts +11 -0
  35. package/dist/dialects/postgres-dialect.js +58 -0
  36. package/dist/dialects/sqlite-dialect.d.ts +13 -0
  37. package/dist/dialects/sqlite-dialect.js +96 -0
  38. package/dist/dialects/sqlserver-dialect.d.ts +12 -0
  39. package/dist/dialects/sqlserver-dialect.js +73 -0
  40. package/dist/help.d.ts +2 -0
  41. package/dist/help.js +10 -0
  42. package/dist/index.d.ts +7 -0
  43. package/dist/index.js +6 -0
  44. package/dist/infrastructure/connection-resolver.d.ts +7 -0
  45. package/dist/infrastructure/connection-resolver.js +19 -0
  46. package/dist/infrastructure/default-factory.d.ts +4 -0
  47. package/dist/infrastructure/default-factory.js +15 -0
  48. package/dist/infrastructure/interop-default.d.ts +3 -0
  49. package/dist/infrastructure/interop-default.js +1 -0
  50. package/dist/infrastructure/message-templates.d.ts +3 -0
  51. package/dist/infrastructure/message-templates.js +18 -0
  52. package/dist/infrastructure/split-on-go.d.ts +2 -0
  53. package/dist/infrastructure/split-on-go.js +20 -0
  54. package/dist/infrastructure/sql-templates.d.ts +2 -0
  55. package/dist/infrastructure/sql-templates.js +4 -0
  56. package/dist/infrastructure/templates-root.d.ts +2 -0
  57. package/dist/infrastructure/templates-root.js +11 -0
  58. package/dist/init-select.d.ts +12 -0
  59. package/dist/init-select.js +52 -0
  60. package/dist/migrater.d.ts +12 -0
  61. package/dist/migrater.js +84 -0
  62. package/dist/migration-client.d.ts +21 -0
  63. package/dist/migration-client.js +1 -0
  64. package/dist/path-exists.d.ts +1 -0
  65. package/dist/path-exists.js +10 -0
  66. package/dist/sql.d.ts +3 -0
  67. package/dist/sql.js +15 -0
  68. package/dist/templates/help/create.txt +16 -0
  69. package/dist/templates/help/down.txt +42 -0
  70. package/dist/templates/help/init.txt +13 -0
  71. package/dist/templates/help/setup.txt +41 -0
  72. package/dist/templates/help/up.txt +43 -0
  73. package/dist/templates/messages/checksum-drift-line.txt +1 -0
  74. package/dist/templates/messages/checksum-drift.txt +11 -0
  75. package/dist/templates/messages/down/confirm-mismatch.txt +1 -0
  76. package/dist/templates/messages/down/confirm-prompt.txt +1 -0
  77. package/dist/templates/messages/down/confirm-stdin-failed.txt +1 -0
  78. package/dist/templates/messages/down/confirm-token-mismatch.txt +1 -0
  79. package/dist/templates/messages/down/confirm-tty-required.txt +1 -0
  80. package/dist/templates/messages/down/destructive-header.txt +3 -0
  81. package/dist/templates/messages/errors/invalid-name.txt +1 -0
  82. package/dist/templates/messages/errors/migrate-path-not-dir.txt +1 -0
  83. package/dist/templates/messages/errors/missing-connection.txt +1 -0
  84. package/dist/templates/messages/errors/missing-name-hint.txt +1 -0
  85. package/dist/templates/messages/errors/missing-name.txt +1 -0
  86. package/dist/templates/messages/errors/missing-provider-hint.txt +1 -0
  87. package/dist/templates/messages/errors/missing-provider.txt +1 -0
  88. package/dist/templates/messages/errors/missing-value-for-flag.txt +1 -0
  89. package/dist/templates/messages/errors/rollback-no-down-sibling.txt +1 -0
  90. package/dist/templates/messages/errors/rollback-no-rollback-sibling.txt +1 -0
  91. package/dist/templates/messages/errors/rollback-not-in-path.txt +1 -0
  92. package/dist/templates/messages/errors/sqlite-prerequisite.txt +1 -0
  93. package/dist/templates/messages/errors/unknown-arg.txt +1 -0
  94. package/dist/templates/messages/errors/unsupported-provider.txt +1 -0
  95. package/dist/templates/messages/setup-complete.txt +9 -0
  96. package/dist/templates/messages/status/applied.txt +1 -0
  97. package/dist/templates/messages/status/created.txt +1 -0
  98. package/dist/templates/messages/status/no-more-pending.txt +1 -0
  99. package/dist/templates/messages/status/no-pending.txt +1 -0
  100. package/dist/templates/messages/status/no-rollback.txt +1 -0
  101. package/dist/templates/messages/status/rolled-back.txt +1 -0
  102. package/dist/templates/scaffold/down.sql +1 -0
  103. package/dist/templates/scaffold/up.sql +1 -0
  104. package/dist/templates/sql/mysql/migrate_logs.sql +11 -0
  105. package/dist/templates/sql/mysql/migrates.sql +7 -0
  106. package/dist/templates/sql/oracle/migrate_logs.sql +14 -0
  107. package/dist/templates/sql/oracle/migrates.sql +10 -0
  108. package/dist/templates/sql/postgres/migrate_logs.sql +11 -0
  109. package/dist/templates/sql/postgres/migrates.sql +7 -0
  110. package/dist/templates/sql/sqlite/migrate_logs.sql +11 -0
  111. package/dist/templates/sql/sqlite/migrates.sql +7 -0
  112. package/dist/templates/sql/sqlserver/migrate_logs.sql +12 -0
  113. package/dist/templates/sql/sqlserver/migrates.sql +8 -0
  114. package/package.json +78 -4
  115. package/src/abstractions/migrater.ts +13 -0
  116. package/src/abstractions/sql-dialect-base.ts +36 -0
  117. package/src/abstractions/sql-dialect-factory.ts +29 -0
  118. package/src/abstractions/sql-dialect.ts +17 -0
  119. package/src/bin/migrate-create.ts +80 -0
  120. package/src/bin/migrate-down.ts +163 -0
  121. package/src/bin/migrate-init.ts +88 -0
  122. package/src/bin/migrate-setup.ts +98 -0
  123. package/src/bin/migrate-up.ts +111 -0
  124. package/src/cli-contract.ts +25 -0
  125. package/src/cli-spec.ts +64 -0
  126. package/src/cli.ts +52 -0
  127. package/src/create-sequence.ts +17 -0
  128. package/src/datasource-migrate.ts +314 -0
  129. package/src/dialects/mysql-dialect.test.ts +93 -0
  130. package/src/dialects/mysql-dialect.ts +67 -0
  131. package/src/dialects/oracle-dialect.test.ts +118 -0
  132. package/src/dialects/oracle-dialect.ts +91 -0
  133. package/src/dialects/postgres-dialect.test.ts +80 -0
  134. package/src/dialects/postgres-dialect.ts +65 -0
  135. package/src/dialects/sqlite-dialect.rollback.test.ts +30 -0
  136. package/src/dialects/sqlite-dialect.test.ts +77 -0
  137. package/src/dialects/sqlite-dialect.ts +96 -0
  138. package/src/dialects/sqlserver-dialect.test.ts +99 -0
  139. package/src/dialects/sqlserver-dialect.ts +87 -0
  140. package/src/generate-help.test.ts +33 -0
  141. package/src/generate-help.ts +173 -0
  142. package/src/help.test.ts +48 -0
  143. package/src/help.ts +12 -0
  144. package/src/index.ts +23 -0
  145. package/src/infrastructure/connection-resolver.ts +18 -0
  146. package/src/infrastructure/default-factory.test.ts +18 -0
  147. package/src/infrastructure/default-factory.ts +17 -0
  148. package/src/infrastructure/interop-default.test.ts +9 -0
  149. package/src/infrastructure/interop-default.ts +2 -0
  150. package/src/infrastructure/message-templates.ts +30 -0
  151. package/src/infrastructure/split-on-go.ts +19 -0
  152. package/src/infrastructure/sql-templates.ts +10 -0
  153. package/src/infrastructure/templates-root.ts +13 -0
  154. package/src/init-select.test.ts +26 -0
  155. package/src/init-select.ts +73 -0
  156. package/src/migrater.ts +92 -0
  157. package/src/migration-client.ts +21 -0
  158. package/src/path-exists.ts +10 -0
  159. package/src/setup-sql.test.ts +16 -0
  160. package/src/sql.ts +17 -0
  161. package/tsconfig.build.json +19 -0
  162. package/README.md +0 -3
package/bundle.yaml ADDED
@@ -0,0 +1,262 @@
1
+ # Source of truth for vendoring migrate runners into generated apps.
2
+ # generators-migraters `fetch-bundle` copies these files; `generate` emits
3
+ # Bundled content or Reference install instructions from the same manifest.
4
+
5
+ repository: https://github.com/deterministic-code/migraters
6
+ ref: main
7
+
8
+ languages:
9
+ typescript:
10
+ root: migraters
11
+ common:
12
+ - cli.yaml
13
+ - typescript/cli.yaml
14
+ - typescript/package.json
15
+ - typescript/tsconfig.build.json
16
+ - typescript/src/**/*.ts
17
+ - shared/templates/help/**
18
+ - shared/templates/messages/**
19
+ - shared/templates/scaffold/**
20
+ exclude:
21
+ - typescript/src/**/*.test.ts
22
+ - typescript/src/generate-help.ts
23
+ dialects:
24
+ sqlite:
25
+ files:
26
+ - typescript/src/dialects/sqlite-dialect.ts
27
+ - shared/templates/sql/sqlite/**
28
+ apk: sqlite
29
+ packages:
30
+ - name: better-sqlite3
31
+ version: "^13.0.3"
32
+ installScripts: true
33
+ postgres:
34
+ files:
35
+ - typescript/src/dialects/postgres-dialect.ts
36
+ - shared/templates/sql/postgres/**
37
+ apk: postgresql-client
38
+ packages:
39
+ - name: pg
40
+ version: "^8.13.0"
41
+ mysql:
42
+ files:
43
+ - typescript/src/dialects/mysql-dialect.ts
44
+ - shared/templates/sql/mysql/**
45
+ apk: mysql-client
46
+ packages:
47
+ - name: mysql2
48
+ version: "^3.22.2"
49
+ sqlserver:
50
+ files:
51
+ - typescript/src/dialects/sqlserver-dialect.ts
52
+ - shared/templates/sql/sqlserver/**
53
+ packages:
54
+ - name: mssql
55
+ version: "^12.5.0"
56
+ oracle:
57
+ files:
58
+ - typescript/src/dialects/oracle-dialect.ts
59
+ - shared/templates/sql/oracle/**
60
+ packages:
61
+ - name: oracledb
62
+ version: "^6.10.0"
63
+ commands:
64
+ setup: migrate-setup --provider {{provider}}
65
+ up: migrate-up --provider {{provider}} --migrate-path {{migrationsPath}}
66
+ down: migrate-down --provider {{provider}} --migrate-path {{migrationsPath}}
67
+ create: migrate-create --provider {{provider}}
68
+ build:
69
+ cwd: typescript
70
+ steps:
71
+ - npm install
72
+ - npm run build
73
+ invoke:
74
+ setup:
75
+ reference: migrate-setup --provider "$DIALECT" --connection "$CONN"
76
+ bundled: npm --prefix /app/migraters/typescript exec -- migrate-setup --provider "$DIALECT" --connection "$CONN"
77
+ up:
78
+ reference: migrate-up --provider "$DIALECT" --migrate-path "$MIGRATIONS_DIR" --connection "$CONN"
79
+ bundled: npm --prefix /app/migraters/typescript exec -- migrate-up --provider "$DIALECT" --migrate-path "$MIGRATIONS_DIR" --connection "$CONN"
80
+ reference:
81
+ package: "@deterministic-code/migraters"
82
+ spec: "github:deterministic-code/migraters"
83
+ docker:
84
+ copy:
85
+ reference: |
86
+ COPY {{shared}}sql {{containerSqlRoot}}
87
+ bundled: |
88
+ COPY {{shared}}sql {{containerSqlRoot}}
89
+ COPY {{lane}}migraters ./migraters
90
+ runtime_copy:
91
+ reference: |
92
+ COPY {{shared}}sql {{containerSqlRoot}}
93
+ bundled: |
94
+ COPY {{shared}}sql {{containerSqlRoot}}
95
+ COPY {{lane}}migraters ./migraters
96
+
97
+ rust:
98
+ root: migraters
99
+ common:
100
+ - rust/Cargo.toml
101
+ - rust/rustfmt.toml
102
+ - rust/src/**/*.rs
103
+ - rust/init/**
104
+ - shared/templates/help/**
105
+ - shared/templates/messages/**
106
+ - shared/templates/scaffold/**
107
+ - cli.yaml
108
+ dialects:
109
+ sqlite:
110
+ files:
111
+ - rust/src/dialects/sqlite.rs
112
+ - shared/templates/sql/sqlite/**
113
+ apk: sqlite
114
+ feature: sqlite
115
+ postgres:
116
+ files:
117
+ - rust/src/dialects/postgres.rs
118
+ - shared/templates/sql/postgres/**
119
+ apk: postgresql-client
120
+ feature: postgres
121
+ mysql:
122
+ files:
123
+ - rust/src/dialects/mysql.rs
124
+ - shared/templates/sql/mysql/**
125
+ apk: mysql-client
126
+ feature: mysql
127
+ sqlserver:
128
+ files:
129
+ - rust/src/dialects/sqlserver.rs
130
+ - shared/templates/sql/sqlserver/**
131
+ feature: sqlserver
132
+ oracle:
133
+ files:
134
+ - rust/src/dialects/oracle.rs
135
+ - shared/templates/sql/oracle/**
136
+ feature: oracle
137
+ commands:
138
+ setup: migrate-setup --provider {{provider}}
139
+ up: migrate-up --provider {{provider}} --migrate-path {{migrationsPath}}
140
+ down: migrate-down --provider {{provider}} --migrate-path {{migrationsPath}}
141
+ create: migrate-create --provider {{provider}}
142
+ build:
143
+ cwd: rust
144
+ steps:
145
+ - cargo build --release
146
+ invoke:
147
+ setup:
148
+ reference: migrate-setup --provider "$DIALECT" --connection "$CONN"
149
+ bundled: /app/migraters/rust/target/release/migrate-setup --provider "$DIALECT" --connection "$CONN"
150
+ up:
151
+ reference: migrate-up --provider "$DIALECT" --migrate-path "$MIGRATIONS_DIR" --connection "$CONN"
152
+ bundled: /app/migraters/rust/target/release/migrate-up --provider "$DIALECT" --migrate-path "$MIGRATIONS_DIR" --connection "$CONN"
153
+ reference:
154
+ git: "https://github.com/deterministic-code/migraters"
155
+ path: rust
156
+ docker:
157
+ copy:
158
+ reference: |
159
+ COPY {{shared}}sql ./sql
160
+ bundled: |
161
+ COPY {{shared}}sql ./sql
162
+ COPY {{lane}}migraters ./migraters
163
+ RUN cargo build --release --manifest-path migraters/rust/Cargo.toml
164
+ runtime_copy:
165
+ reference: |
166
+ COPY {{shared}}sql {{containerSqlRoot}}
167
+ bundled: |
168
+ COPY --from=builder /app/migraters/rust/target/release/migrate-setup /app/migraters/rust/target/release/migrate-setup
169
+ COPY --from=builder /app/migraters/rust/target/release/migrate-up /app/migraters/rust/target/release/migrate-up
170
+ COPY --from=builder /app/migraters/rust/target/release/migrate-down /app/migraters/rust/target/release/migrate-down
171
+ COPY --from=builder /app/migraters/rust/target/release/migrate-create /app/migraters/rust/target/release/migrate-create
172
+ COPY {{shared}}sql {{containerSqlRoot}}
173
+
174
+ csharp:
175
+ root: migraters
176
+ common:
177
+ - csharp/**/*.cs
178
+ - csharp/MigrateRunner.csproj
179
+ - csharp/MigrateInit/MigrateInit.csproj
180
+ - csharp/GlobalUsings.cs
181
+ - csharp/.csharpierrc.json
182
+ - csharp/.csharpierignore
183
+ - csharp/dotnet-tools.json
184
+ - cli.yaml
185
+ - shared/templates/help/**
186
+ - shared/templates/messages/**
187
+ - shared/templates/scaffold/**
188
+ exclude:
189
+ - csharp/bin/**
190
+ - csharp/obj/**
191
+ dialects:
192
+ sqlite:
193
+ files:
194
+ - csharp/Dialects/SqliteDialect.cs
195
+ - shared/templates/sql/sqlite/**
196
+ apk: sqlite
197
+ packages:
198
+ - name: Microsoft.Data.Sqlite
199
+ version: "9.0.0"
200
+ postgres:
201
+ files:
202
+ - csharp/Dialects/PostgresDialect.cs
203
+ - shared/templates/sql/postgres/**
204
+ apk: postgresql-client
205
+ packages:
206
+ - name: Npgsql
207
+ version: "9.0.1"
208
+ mysql:
209
+ files:
210
+ - csharp/Dialects/MysqlDialect.cs
211
+ - shared/templates/sql/mysql/**
212
+ apk: mysql-client
213
+ packages:
214
+ - name: MySqlConnector
215
+ version: "2.4.0"
216
+ sqlserver:
217
+ files:
218
+ - csharp/Dialects/SqlServerDialect.cs
219
+ - shared/templates/sql/sqlserver/**
220
+ packages:
221
+ - name: Microsoft.Data.SqlClient
222
+ version: "6.0.1"
223
+ oracle:
224
+ files:
225
+ - csharp/Dialects/OracleDialect.cs
226
+ - shared/templates/sql/oracle/**
227
+ packages:
228
+ - name: Oracle.ManagedDataAccess.Core
229
+ version: "23.7.0"
230
+ commands:
231
+ setup: migrate-setup --provider {{provider}}
232
+ up: migrate-up --provider {{provider}} --migrate-path {{migrationsPath}}
233
+ down: migrate-down --provider {{provider}} --migrate-path {{migrationsPath}}
234
+ create: migrate-create --provider {{provider}}
235
+ build:
236
+ cwd: csharp
237
+ steps:
238
+ - dotnet publish MigrateRunner.csproj -c Release
239
+ invoke:
240
+ setup:
241
+ reference: migrate-setup --provider "$DIALECT" --connection "$CONN"
242
+ bundled: dotnet /app/MigrateRunner/MigrateRunner.dll setup --provider "$DIALECT" --connection "$CONN"
243
+ up:
244
+ reference: migrate-up --provider "$DIALECT" --migrate-path "$MIGRATIONS_DIR" --connection "$CONN"
245
+ bundled: dotnet /app/MigrateRunner/MigrateRunner.dll up --provider "$DIALECT" --migrate-path "$MIGRATIONS_DIR" --connection "$CONN"
246
+ reference:
247
+ git: "https://github.com/deterministic-code/migraters"
248
+ path: csharp
249
+ docker:
250
+ copy:
251
+ reference: |
252
+ COPY {{shared}}sql ./sql
253
+ bundled: |
254
+ COPY {{shared}}sql ./sql
255
+ COPY {{lane}}migraters ./migraters
256
+ RUN dotnet publish migraters/csharp/MigrateRunner.csproj -c Release -o /app/migrate-publish
257
+ runtime_copy:
258
+ reference: |
259
+ COPY {{shared}}sql {{containerSqlRoot}}
260
+ bundled: |
261
+ COPY --from=build /app/migrate-publish ./MigrateRunner
262
+ COPY {{shared}}sql {{containerSqlRoot}}
@@ -0,0 +1,28 @@
1
+ export type SetupArg = {
2
+ connection: string;
3
+ migrationsPath: string;
4
+ };
5
+ export type UpArg = {
6
+ connection: string;
7
+ migrationsPath: string;
8
+ one?: boolean;
9
+ };
10
+ export type DownArg = {
11
+ connection: string;
12
+ migrationsPath: string;
13
+ };
14
+ export type CreateArg = {
15
+ name: string;
16
+ migrationsPath: string;
17
+ };
18
+ export type CreateResponse = {
19
+ upName: string;
20
+ downName: string;
21
+ };
22
+ export interface IMigrater {
23
+ readonly name: string;
24
+ setup(args: SetupArg): Promise<void>;
25
+ up(args: UpArg): Promise<string[]>;
26
+ down(args: DownArg): Promise<string | null>;
27
+ create(args: CreateArg): Promise<CreateResponse>;
28
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,16 @@
1
+ import type { SqlDialect } from '../sql.ts';
2
+ import type { ISqlDialect } from './sql-dialect.ts';
3
+ export declare abstract class SqlDialectBase implements ISqlDialect {
4
+ abstract readonly name: SqlDialect;
5
+ abstract readonly connectionEnvironmentVariables: readonly string[];
6
+ abstract readonly migratesDdl: string;
7
+ abstract readonly migrateLogsDdl: string;
8
+ readonly usesLastInsertRowid: boolean;
9
+ quoteIdent(ident: string): string;
10
+ nowExpr(): string;
11
+ limitClause(n: number): string;
12
+ translatePlaceholders(sql: string): string;
13
+ prerequisiteError(_connection: string): Promise<string | null>;
14
+ prepareSetup(_connection: string): Promise<void>;
15
+ abstract createClient(connection: string): Promise<import('../migration-client.ts').MigrationClient>;
16
+ }
@@ -0,0 +1,19 @@
1
+ export class SqlDialectBase {
2
+ usesLastInsertRowid = false;
3
+ quoteIdent(ident) {
4
+ return `"${ident}"`;
5
+ }
6
+ nowExpr() {
7
+ return 'CURRENT_TIMESTAMP';
8
+ }
9
+ limitClause(n) {
10
+ return `LIMIT ${n}`;
11
+ }
12
+ translatePlaceholders(sql) {
13
+ return sql;
14
+ }
15
+ async prerequisiteError(_connection) {
16
+ return null;
17
+ }
18
+ async prepareSetup(_connection) { }
19
+ }
@@ -0,0 +1,8 @@
1
+ import type { ISqlDialect } from './sql-dialect.ts';
2
+ export declare class SqlDialectFactory {
3
+ private readonly byName;
4
+ constructor(dialects: readonly ISqlDialect[]);
5
+ tryGet(raw: string): ISqlDialect | undefined;
6
+ get(raw: string): ISqlDialect;
7
+ all(): readonly ISqlDialect[];
8
+ }
@@ -0,0 +1,22 @@
1
+ import { normalizeDialect } from "../sql.js";
2
+ const VALID = 'sqlite, mysql, postgres, sqlserver, oracle';
3
+ export class SqlDialectFactory {
4
+ byName;
5
+ constructor(dialects) {
6
+ this.byName = new Map(dialects.map((d) => [d.name, d]));
7
+ }
8
+ tryGet(raw) {
9
+ const key = normalizeDialect(raw);
10
+ return key ? this.byName.get(key) : undefined;
11
+ }
12
+ get(raw) {
13
+ const dialect = this.tryGet(raw);
14
+ if (!dialect) {
15
+ throw new Error(`Unknown SQL dialect "${raw}". Valid: ${VALID}.`);
16
+ }
17
+ return dialect;
18
+ }
19
+ all() {
20
+ return [...this.byName.values()];
21
+ }
22
+ }
@@ -0,0 +1,16 @@
1
+ import type { MigrationClient } from '../migration-client.ts';
2
+ import type { SqlDialect } from '../sql.ts';
3
+ export interface ISqlDialect {
4
+ readonly name: SqlDialect;
5
+ readonly connectionEnvironmentVariables: readonly string[];
6
+ readonly migratesDdl: string;
7
+ readonly migrateLogsDdl: string;
8
+ readonly usesLastInsertRowid: boolean;
9
+ quoteIdent(ident: string): string;
10
+ nowExpr(): string;
11
+ limitClause(n: number): string;
12
+ translatePlaceholders(sql: string): string;
13
+ prerequisiteError(connection: string): Promise<string | null>;
14
+ prepareSetup(connection: string): Promise<void>;
15
+ createClient(connection: string): Promise<MigrationClient>;
16
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,71 @@
1
+ #!/usr/bin/env node
2
+ // Scaffolds a new <NNNN>_<name>_{up,down}.sql pair in the migrations directory. Numbering is max(1-4-digit prefix in dir)+1; legacy timestamp prefixes are ignored.
3
+ import { missingProviderMsg, requireDialect, takeFlag } from "../cli.js";
4
+ import { isMigrationName } from "../create-sequence.js";
5
+ import { fillTemplate, loadMessage } from "../infrastructure/message-templates.js";
6
+ import { loadHelp, Migrater } from "../index.js";
7
+ const [HELP_TEXT, unknownArgTpl, missingNameMsg, invalidNameTpl, createdTpl] = await Promise.all([
8
+ loadHelp('migrate-create'),
9
+ loadMessage('errors/unknown-arg'),
10
+ loadMessage('errors/missing-name'),
11
+ loadMessage('errors/invalid-name'),
12
+ loadMessage('status/created'),
13
+ ]);
14
+ const parseArgs = (argv) => {
15
+ const args = { provider: null, name: null, migrationsPath: null };
16
+ const rest = argv.slice(2);
17
+ for (let i = 0; i < rest.length; i++) {
18
+ const a = rest[i];
19
+ if (a === '-h' || a === '--help') {
20
+ process.stderr.write(HELP_TEXT);
21
+ process.exit(0);
22
+ }
23
+ let taken;
24
+ if ((taken = takeFlag(rest, i, a, '--provider'))) {
25
+ args.provider = taken.value;
26
+ i = taken.next;
27
+ }
28
+ else if ((taken = takeFlag(rest, i, a, '--name'))) {
29
+ args.name = taken.value;
30
+ i = taken.next;
31
+ }
32
+ else if ((taken = takeFlag(rest, i, a, '--migrations-path')) ||
33
+ (taken = takeFlag(rest, i, a, '--migrate-path'))) {
34
+ args.migrationsPath = taken.value;
35
+ i = taken.next;
36
+ }
37
+ else {
38
+ process.stderr.write(fillTemplate(unknownArgTpl, { arg: a }));
39
+ process.exit(2);
40
+ }
41
+ }
42
+ return args;
43
+ };
44
+ const main = async () => {
45
+ const args = parseArgs(process.argv);
46
+ if (!args.provider) {
47
+ process.stderr.write(missingProviderMsg);
48
+ process.exit(2);
49
+ }
50
+ const dialect = requireDialect(args.provider);
51
+ if (!args.name) {
52
+ process.stderr.write(missingNameMsg);
53
+ process.exit(2);
54
+ }
55
+ if (!isMigrationName(args.name)) {
56
+ process.stderr.write(fillTemplate(invalidNameTpl, { name: args.name }));
57
+ process.exit(2);
58
+ }
59
+ const migrationsPath = args.migrationsPath ?? `./sql/${dialect.name}/migrations`;
60
+ const { upName, downName } = await new Migrater(dialect).create({
61
+ name: args.name,
62
+ migrationsPath,
63
+ });
64
+ process.stdout.write(fillTemplate(createdTpl, { file: upName }));
65
+ process.stdout.write(fillTemplate(createdTpl, { file: downName }));
66
+ };
67
+ main().catch((e) => {
68
+ const err = e;
69
+ process.stderr.write(`${err?.stack ?? err?.message ?? String(e)}\n`);
70
+ process.exit(1);
71
+ });
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,135 @@
1
+ #!/usr/bin/env node
2
+ // Rolls back the most recently applied migration (one step). DESTRUCTIVE: prints a random 4-letter uppercase confirmation token and refuses to proceed unless the user types it back on stdin. Pass --confirm <TOKEN> matching the printed token to bypass the interactive prompt (CI / scripted use).
3
+ import { resolve } from 'node:path';
4
+ import { createInterface } from 'node:readline/promises';
5
+ import { missingProviderMsg, requireConnection, requireDialect, takeFlag } from "../cli.js";
6
+ import { fillTemplate, loadMessage } from "../infrastructure/message-templates.js";
7
+ import { loadHelp, Migrater } from "../index.js";
8
+ const [HELP_TEXT, unknownArgTpl, destructiveHeaderTpl, confirmMismatchTpl, confirmTtyRequiredTpl, confirmPromptTpl, confirmTokenMismatchMsg, noRollbackMsg, rolledBackTpl,] = await Promise.all([
9
+ loadHelp('migrate-down'),
10
+ loadMessage('errors/unknown-arg'),
11
+ loadMessage('down/destructive-header'),
12
+ loadMessage('down/confirm-mismatch'),
13
+ loadMessage('down/confirm-tty-required'),
14
+ loadMessage('down/confirm-prompt'),
15
+ loadMessage('down/confirm-token-mismatch'),
16
+ loadMessage('status/no-rollback'),
17
+ loadMessage('status/rolled-back'),
18
+ ]);
19
+ const parseArgs = (argv) => {
20
+ const args = {
21
+ provider: null,
22
+ migratePath: null,
23
+ migrateRoot: null,
24
+ connection: null,
25
+ confirm: null,
26
+ };
27
+ const rest = argv.slice(2);
28
+ for (let i = 0; i < rest.length; i++) {
29
+ const a = rest[i];
30
+ if (a === '-h' || a === '--help') {
31
+ process.stderr.write(HELP_TEXT);
32
+ process.exit(0);
33
+ }
34
+ let taken;
35
+ if ((taken = takeFlag(rest, i, a, '--provider'))) {
36
+ args.provider = taken.value;
37
+ i = taken.next;
38
+ }
39
+ else if ((taken = takeFlag(rest, i, a, '--migrations-path')) ||
40
+ (taken = takeFlag(rest, i, a, '--migrate-path'))) {
41
+ args.migratePath = taken.value;
42
+ i = taken.next;
43
+ }
44
+ else if ((taken = takeFlag(rest, i, a, '--migrations-root')) ||
45
+ (taken = takeFlag(rest, i, a, '--migrate-root'))) {
46
+ args.migrateRoot = taken.value;
47
+ i = taken.next;
48
+ }
49
+ else if ((taken = takeFlag(rest, i, a, '--connection'))) {
50
+ args.connection = taken.value;
51
+ i = taken.next;
52
+ }
53
+ else if ((taken = takeFlag(rest, i, a, '--confirm'))) {
54
+ args.confirm = taken.value;
55
+ i = taken.next;
56
+ }
57
+ else {
58
+ process.stderr.write(fillTemplate(unknownArgTpl, { arg: a }));
59
+ process.exit(2);
60
+ }
61
+ }
62
+ return args;
63
+ };
64
+ const resolveMigratePath = (args, dialect) => {
65
+ if (args.migratePath)
66
+ return args.migratePath;
67
+ const root = args.migrateRoot ?? 'sql';
68
+ return `${root}/${dialect}/migrations`;
69
+ };
70
+ const randomToken = () => {
71
+ const alphabet = 'ABCDEFGHJKLMNPQRSTUVWXYZ';
72
+ const buf = new Uint8Array(4);
73
+ globalThis.crypto.getRandomValues(buf);
74
+ let out = '';
75
+ for (let i = 0; i < 4; i++)
76
+ out += alphabet[buf[i] % alphabet.length];
77
+ return out;
78
+ };
79
+ const promptConfirmation = async (token) => {
80
+ if (!process.stdin.isTTY) {
81
+ process.stderr.write(fillTemplate(confirmTtyRequiredTpl, { token }));
82
+ process.exit(2);
83
+ }
84
+ const rl = createInterface({ input: process.stdin, output: process.stderr });
85
+ try {
86
+ const answer = await rl.question(fillTemplate(confirmPromptTpl, { token }));
87
+ return answer.trim() === token;
88
+ }
89
+ finally {
90
+ rl.close();
91
+ }
92
+ };
93
+ const main = async () => {
94
+ const args = parseArgs(process.argv);
95
+ if (!args.provider) {
96
+ process.stderr.write(missingProviderMsg);
97
+ process.exit(2);
98
+ }
99
+ const dialect = requireDialect(args.provider);
100
+ const connection = requireConnection(dialect, args.connection);
101
+ const missing = await dialect.prerequisiteError(connection);
102
+ if (missing !== null) {
103
+ process.stderr.write(`${missing}\n`);
104
+ process.exit(2);
105
+ }
106
+ const token = randomToken();
107
+ process.stderr.write(fillTemplate(destructiveHeaderTpl, { dialect: dialect.name, token }));
108
+ if (args.confirm !== null) {
109
+ if (args.confirm !== token) {
110
+ process.stderr.write(fillTemplate(confirmMismatchTpl, { supplied: args.confirm, token }));
111
+ process.exit(2);
112
+ }
113
+ }
114
+ else {
115
+ const ok = await promptConfirmation(token);
116
+ if (!ok) {
117
+ process.stderr.write(confirmTokenMismatchMsg);
118
+ process.exit(2);
119
+ }
120
+ }
121
+ const migratePath = resolve(resolveMigratePath(args, dialect.name));
122
+ const name = await new Migrater(dialect).down({
123
+ connection,
124
+ migrationsPath: migratePath,
125
+ });
126
+ if (name == null)
127
+ process.stdout.write(noRollbackMsg);
128
+ else
129
+ process.stdout.write(fillTemplate(rolledBackTpl, { name }));
130
+ };
131
+ main().catch((e) => {
132
+ const err = e;
133
+ process.stderr.write(`${err?.stack ?? err?.message ?? String(e)}\n`);
134
+ process.exit(1);
135
+ });
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,77 @@
1
+ #!/usr/bin/env node
2
+ import { spawnSync } from 'node:child_process';
3
+ import { loadHelp } from "../help.js";
4
+ import { loadSelectedPackages, resolveInitDialects } from "../init-select.js";
5
+ const HELP_TEXT = await loadHelp('migrate-init');
6
+ const takeFlag = (rest, i, arg, flag) => {
7
+ const eq = `${flag}=`;
8
+ if (arg === flag) {
9
+ const value = rest[i + 1];
10
+ if (value === undefined)
11
+ return undefined;
12
+ return { value, next: i + 1 };
13
+ }
14
+ if (arg.startsWith(eq))
15
+ return { value: arg.slice(eq.length), next: i };
16
+ return undefined;
17
+ };
18
+ const parseArgs = (argv) => {
19
+ const dialects = [];
20
+ let all = false;
21
+ const rest = argv.slice(2);
22
+ for (let i = 0; i < rest.length; i++) {
23
+ const a = rest[i];
24
+ if (a === '-h' || a === '--help') {
25
+ process.stderr.write(HELP_TEXT);
26
+ process.exit(0);
27
+ }
28
+ if (a === '--all') {
29
+ all = true;
30
+ continue;
31
+ }
32
+ const taken = takeFlag(rest, i, a, '--dialect');
33
+ if (taken) {
34
+ dialects.push(taken.value);
35
+ i = taken.next;
36
+ continue;
37
+ }
38
+ process.stderr.write(`unknown arg: ${a}\n`);
39
+ process.exit(2);
40
+ }
41
+ return { dialects, all };
42
+ };
43
+ const npmFlags = ['--no-audit', '--no-fund', '--loglevel=error'];
44
+ const npm = (args) => {
45
+ const cmd = process.platform === 'win32' ? 'npm.cmd' : 'npm';
46
+ const result = spawnSync(cmd, args, { stdio: 'inherit', cwd: process.cwd() });
47
+ if (result.status !== 0) {
48
+ process.exit(result.status ?? 1);
49
+ }
50
+ };
51
+ const main = async () => {
52
+ const args = parseArgs(process.argv);
53
+ let names;
54
+ try {
55
+ names = resolveInitDialects(args.dialects, args.all);
56
+ }
57
+ catch (e) {
58
+ const err = e;
59
+ process.stderr.write(`${err.message}\n`);
60
+ process.exit(2);
61
+ }
62
+ const selected = await loadSelectedPackages(names);
63
+ const specs = selected.packages.map((p) => `${p.name}@${p.version}`);
64
+ if (specs.length > 0) {
65
+ npm(['install', ...npmFlags, ...specs]);
66
+ }
67
+ const remove = selected.allDriverPackages.filter((name) => !selected.packages.some((p) => p.name === name));
68
+ if (remove.length > 0) {
69
+ npm(['uninstall', ...npmFlags, ...remove]);
70
+ }
71
+ process.stdout.write(`Enabled dialects: ${selected.names.join(', ')}\n`);
72
+ };
73
+ main().catch((e) => {
74
+ const err = e;
75
+ process.stderr.write(`${err?.stack ?? err?.message ?? String(e)}\n`);
76
+ process.exit(1);
77
+ });
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};