@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
@@ -0,0 +1,84 @@
1
+ import { mkdir, readdir, writeFile } from 'node:fs/promises';
2
+ import { isMigrationName, nextSequence, pad4 } from "./create-sequence.js";
3
+ import { applyOneDown, applyOneUp, discoverMigrations } from "./datasource-migrate.js";
4
+ import { defaultDialectFactory } from "./infrastructure/default-factory.js";
5
+ import { fillTemplate, loadMessage, loadScaffold } from "./infrastructure/message-templates.js";
6
+ const invalidNameTpl = await loadMessage('errors/invalid-name');
7
+ export class Migrater {
8
+ dialect;
9
+ constructor(dialect) {
10
+ this.dialect = dialect;
11
+ }
12
+ get name() {
13
+ return this.dialect.name;
14
+ }
15
+ async setup({ connection, migrationsPath }) {
16
+ await this.dialect.prepareSetup(connection);
17
+ const client = await this.dialect.createClient(connection);
18
+ try {
19
+ await client.exec(this.dialect.migratesDdl);
20
+ await client.exec(this.dialect.migrateLogsDdl);
21
+ await mkdir(migrationsPath, { recursive: true });
22
+ }
23
+ finally {
24
+ await client.close();
25
+ }
26
+ }
27
+ async up({ connection, migrationsPath, one = false }) {
28
+ const client = await this.dialect.createClient(connection);
29
+ try {
30
+ const migrations = await discoverMigrations({
31
+ migratePath: migrationsPath,
32
+ dialect: this.dialect.name,
33
+ });
34
+ const applied = [];
35
+ for (;;) {
36
+ const result = await applyOneUp({ client, migrations });
37
+ if (!result.applied || result.name == null)
38
+ break;
39
+ applied.push(result.name);
40
+ if (one)
41
+ break;
42
+ }
43
+ return applied;
44
+ }
45
+ finally {
46
+ await client.close();
47
+ }
48
+ }
49
+ async down({ connection, migrationsPath }) {
50
+ const client = await this.dialect.createClient(connection);
51
+ try {
52
+ const migrations = await discoverMigrations({
53
+ migratePath: migrationsPath,
54
+ dialect: this.dialect.name,
55
+ });
56
+ const result = await applyOneDown({ client, migrations });
57
+ return result.rolledBack ? result.name : null;
58
+ }
59
+ finally {
60
+ await client.close();
61
+ }
62
+ }
63
+ async create({ name, migrationsPath }) {
64
+ if (!isMigrationName(name)) {
65
+ throw new Error(fillTemplate(invalidNameTpl, { name }));
66
+ }
67
+ await mkdir(migrationsPath, { recursive: true });
68
+ let entries = [];
69
+ try {
70
+ entries = await readdir(migrationsPath);
71
+ }
72
+ catch (err) {
73
+ if (!(err instanceof Error && 'code' in err && err.code === 'ENOENT'))
74
+ throw err;
75
+ }
76
+ const seq = pad4(nextSequence(entries));
77
+ const upName = `${seq}_${name}_up.sql`;
78
+ const downName = `${seq}_${name}_down.sql`;
79
+ await writeFile(`${migrationsPath}/${upName}`, await loadScaffold('up', { name }));
80
+ await writeFile(`${migrationsPath}/${downName}`, await loadScaffold('down', { name }));
81
+ return { upName, downName };
82
+ }
83
+ }
84
+ export const getMigrater = (provider) => new Migrater(defaultDialectFactory.get(provider));
@@ -0,0 +1,21 @@
1
+ export type MigrationRowValue = string | number | bigint | boolean | Date | null;
2
+ export type MigrationRow = Record<string, MigrationRowValue>;
3
+ export type MigrationSqlParam = string | number | bigint | boolean | Date | null;
4
+ /** The subset of a better-sqlite3 Database that `insertLogStarted` reaches through `_raw` when a caller injects a synchronous handle. */
5
+ export interface SqliteRawDatabase {
6
+ prepare(source: string): {
7
+ run(...params: MigrationSqlParam[]): {
8
+ lastInsertRowid: number | bigint;
9
+ };
10
+ };
11
+ }
12
+ /** Provider-agnostic migration client used by IMigrater.up, IMigrater.down, and IMigrater.setup. */
13
+ export interface MigrationClient {
14
+ dialect: import('./sql.ts').SqlDialect;
15
+ exec(sql: string): Promise<void>;
16
+ query(sql: string, params?: MigrationSqlParam[]): Promise<MigrationRow[]>;
17
+ run(sql: string, params?: MigrationSqlParam[]): Promise<void>;
18
+ transaction<T>(fn: () => Promise<T>): Promise<T>;
19
+ close(): Promise<void>;
20
+ _raw?: SqliteRawDatabase;
21
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export declare const pathExists: (p: string) => Promise<boolean>;
@@ -0,0 +1,10 @@
1
+ import { access } from 'node:fs/promises';
2
+ export const pathExists = async (p) => {
3
+ try {
4
+ await access(p);
5
+ return true;
6
+ }
7
+ catch {
8
+ return false;
9
+ }
10
+ };
package/dist/sql.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ export type SqlDialect = 'sqlite' | 'mysql' | 'postgres' | 'sqlserver' | 'oracle';
2
+ export declare const normalizeDialect: (raw: string | null | undefined) => SqlDialect | null;
3
+ export { pathExists } from './path-exists.ts';
package/dist/sql.js ADDED
@@ -0,0 +1,15 @@
1
+ import { cliSpec } from "./cli-spec.js";
2
+ const stripKey = (raw) => raw.toLowerCase().replace(/[\s_\-]/g, '');
3
+ export const normalizeDialect = (raw) => {
4
+ if (!raw)
5
+ return null;
6
+ const key = stripKey(raw);
7
+ if (cliSpec.providers.includes(key))
8
+ return key;
9
+ for (const [alias, canonical] of Object.entries(cliSpec.provider_aliases ?? {})) {
10
+ if (stripKey(alias) === key)
11
+ return canonical;
12
+ }
13
+ return null;
14
+ };
15
+ export { pathExists } from "./path-exists.js";
@@ -0,0 +1,16 @@
1
+ {{usage}}
2
+
3
+ Creates a new <NNNN>_<name>_up.sql + <NNNN>_<name>_down.sql pair scaffolded
4
+ with TODO placeholders. NNNN is one greater than the highest 1-4-digit
5
+ sequence prefix already present in the migrations directory (starts at 0001).
6
+ Legacy timestamp-prefixed filenames are ignored for numbering.
7
+
8
+ --provider Database dialect. Required.
9
+ --name snake_case slug for the new migration. Required. Must
10
+ match /^[a-z][a-z0-9_]*$/.
11
+ --migrations-path Migrations directory (default: ./sql/<dialect>/migrations).
12
+ Created with mkdir -p if it does not exist.
13
+
14
+ Examples:
15
+ {{command}} --provider sqlite --name add_users
16
+ {{command}} --provider postgres --name backfill_email_lower --migrations-path ./db/changes/postgres
@@ -0,0 +1,42 @@
1
+ {{usage}}
2
+
3
+ Rolls back the MOST RECENTLY applied migration (one step). DESTRUCTIVE: prints a
4
+ random 4-letter uppercase token on stderr and refuses to proceed unless the
5
+ operator types it back on stdin (or passes --confirm <TOKEN> matching it).
6
+
7
+ --provider Database dialect. Required.
8
+ --connection Connection string. Required (or set the per-dialect env var below).
9
+ --migrations-path Full path to the migrations directory.
10
+ --migrations-root Root prefix; the script then looks at <migrations-root>/<dialect>/migrations.
11
+ Defaults to 'sql'. Ignored when --migrations-path is also set.
12
+ --confirm Skip the interactive prompt. The TOKEN must match the value
13
+ printed on stderr at runtime — there is no fixed bypass value.
14
+
15
+ Examples:
16
+ # sqlite — bare path or sqlite:// URL.
17
+ {{command}} --provider sqlite --connection ./app.sqlite
18
+ {{command}} --provider sqlite --connection sqlite:///absolute/path/app.sqlite
19
+
20
+ # postgres — URL or keyword form.
21
+ {{command}} --provider postgres --connection postgresql://user:pass@host:5432/dbname
22
+
23
+ # mysql — URL form.
24
+ {{command}} --provider mysql --connection mysql://user:pass@host:3306/dbname
25
+
26
+ # sqlserver / oracle — pass a driver-native connection string.
27
+ {{command}} --provider sqlserver --connection "Server=host;Database=dbname;User Id=user;Password=pass;"
28
+ {{command}} --provider oracle --connection "user/pass@host:1521/service"
29
+
30
+ # env-var fallback when --connection is omitted:
31
+ SQLITE_PATH=./app.sqlite {{command}} --provider sqlite
32
+ DATABASE_URL=postgresql://... {{command}} --provider postgres
33
+
34
+ # custom migrations layout (default looks under sql/<dialect>/migrations):
35
+ {{command}} --provider sqlite --connection ./app.sqlite --migrations-path ./db/changes/sqlite
36
+
37
+ Per-dialect env vars consulted when --connection is omitted:
38
+ sqlite SQLITE_PATH, DB_PATH
39
+ postgres PG_CONNECTION_STRING, DATABASE_URL
40
+ mysql MYSQL_URL, DATABASE_URL
41
+ sqlserver MSSQL_URL, DATABASE_URL
42
+ oracle ORACLE_CONNECT_STRING, DATABASE_URL
@@ -0,0 +1,13 @@
1
+ {{usage}}
2
+
3
+ Selects the dialects this tree will compile and install. Repeat --dialect
4
+ once per provider. Re-running replaces the previous set. --all restores
5
+ every dialect. Does not take --connection.
6
+
7
+ --dialect Dialect to enable. Repeat for each dialect. Aliases from this file apply.
8
+ --all Enable every dialect. Restores the committed full-provider set.
9
+
10
+ Examples:
11
+ {{command}} --dialect sqlite --dialect postgres
12
+ {{command}} --dialect oracle
13
+ {{command}} --all
@@ -0,0 +1,41 @@
1
+ {{usage}}
2
+
3
+ Creates the bookkeeping tables (migrates, migrate_logs) for the chosen dialect
4
+ and the migrations directory (mkdir -p). Idempotent — re-running against an
5
+ already-setup database is a no-op. For sqlite, also mkdir -p of the parent
6
+ directory of --connection so a fresh-tree path like ./.test/foo.sqlite works.
7
+
8
+ --provider Database dialect. Required.
9
+ --connection Connection string. Required (or set the per-dialect env var below).
10
+ --migrations-path Migrations directory (default: ./sql/<dialect>/migrations).
11
+ --and-up After setup, immediately invoke migrate-up so the chain is applied in one step.
12
+
13
+ Examples:
14
+ # sqlite — bare path or sqlite:// URL; both create a file on disk.
15
+ {{command}} --provider sqlite --connection ./app.sqlite
16
+ {{command}} --provider sqlite --connection sqlite:///absolute/path/app.sqlite
17
+
18
+ # postgres — URL or keyword form.
19
+ {{command}} --provider postgres --connection postgresql://user:pass@host:5432/dbname
20
+
21
+ # mysql — URL form.
22
+ {{command}} --provider mysql --connection mysql://user:pass@host:3306/dbname
23
+
24
+ # sqlserver / oracle — pass a driver-native connection string.
25
+ {{command}} --provider sqlserver --connection "Server=host;Database=dbname;User Id=user;Password=pass;"
26
+ {{command}} --provider oracle --connection "user/pass@host:1521/service"
27
+
28
+ # env-var fallback when --connection is omitted:
29
+ SQLITE_PATH=./app.sqlite {{command}} --provider sqlite
30
+ DATABASE_URL=postgresql://... {{command}} --provider postgres
31
+ DATABASE_URL=mysql://... {{command}} --provider mysql
32
+
33
+ # explicit in-memory sqlite:
34
+ {{command}} --provider sqlite --connection :memory:
35
+
36
+ Per-dialect env vars consulted when --connection is omitted:
37
+ sqlite SQLITE_PATH, DB_PATH
38
+ postgres PG_CONNECTION_STRING, DATABASE_URL
39
+ mysql MYSQL_URL, DATABASE_URL
40
+ sqlserver MSSQL_URL, DATABASE_URL
41
+ oracle ORACLE_CONNECT_STRING, DATABASE_URL
@@ -0,0 +1,43 @@
1
+ {{usage}}
2
+
3
+ Applies ALL pending migrations in sequence, each in its own transaction.
4
+
5
+ --provider Database dialect. Required.
6
+ --connection Connection string. Required (or set the per-dialect env var below).
7
+ --migrations-path Full path to the migrations directory (e.g. sql/sqlite/migrations).
8
+ --migrations-root Root prefix; the script then looks at <migrations-root>/<dialect>/migrations.
9
+ Defaults to 'sql'. Ignored when --migrations-path is also set.
10
+ --one Apply only the next pending migration, then exit. Default is to apply all pending migrations.
11
+
12
+ Examples:
13
+ # sqlite — bare path or sqlite:// URL; both create a file on disk.
14
+ {{command}} --provider sqlite --connection ./app.sqlite
15
+ {{command}} --provider sqlite --connection sqlite:///absolute/path/app.sqlite
16
+
17
+ # postgres — URL or keyword form.
18
+ {{command}} --provider postgres --connection postgresql://user:pass@host:5432/dbname
19
+
20
+ # mysql — URL form.
21
+ {{command}} --provider mysql --connection mysql://user:pass@host:3306/dbname
22
+
23
+ # sqlserver / oracle — pass a driver-native connection string.
24
+ {{command}} --provider sqlserver --connection "Server=host;Database=dbname;User Id=user;Password=pass;"
25
+ {{command}} --provider oracle --connection "user/pass@host:1521/service"
26
+
27
+ # env-var fallback when --connection is omitted:
28
+ SQLITE_PATH=./app.sqlite {{command}} --provider sqlite
29
+ DATABASE_URL=postgresql://... {{command}} --provider postgres
30
+
31
+ # custom migrations layout (default looks under sql/<dialect>/migrations):
32
+ {{command}} --provider sqlite --connection ./app.sqlite --migrations-path ./db/changes/sqlite
33
+ {{command}} --provider sqlite --connection ./app.sqlite --migrations-root ./db/changes
34
+
35
+ # one-shot: apply the next pending migration only, then exit.
36
+ {{command}} --provider sqlite --connection ./app.sqlite --one
37
+
38
+ Per-dialect env vars consulted when --connection is omitted:
39
+ sqlite SQLITE_PATH, DB_PATH
40
+ postgres PG_CONNECTION_STRING, DATABASE_URL
41
+ mysql MYSQL_URL, DATABASE_URL
42
+ sqlserver MSSQL_URL, DATABASE_URL
43
+ oracle ORACLE_CONNECT_STRING, DATABASE_URL
@@ -0,0 +1 @@
1
+ {{name}}: stored {{stored}}..., current {{current}}...
@@ -0,0 +1,11 @@
1
+ Migration checksum drift detected — the migration file changed AFTER it was applied:
2
+ {{lines}}
3
+
4
+ The DB and source disagree about the schema you're running. Either the codegen
5
+ regenerated an already-applied migration in place (the canonical bug — emit a NEW
6
+ migration file instead), or the migrate state was hand-edited.
7
+
8
+ Recovery options:
9
+ 1. Emit a new migration that brings the DB up to the current schema, then deploy.
10
+ 2. For showcase/dev DBs with no real data: wipe the DB file and let migrate:up re-run from scratch.
11
+ 3. If you've verified the DB matches the new file: MIGRATE_ALLOW_CHECKSUM_DRIFT=1 npm run migrate:up
@@ -0,0 +1 @@
1
+ --confirm value ({{supplied}}) does not match the token printed above ({{token}}). Aborting.
@@ -0,0 +1 @@
1
+ Type {{token}} to confirm rollback:
@@ -0,0 +1 @@
1
+ failed to read confirmation from stdin — aborting.
@@ -0,0 +1 @@
1
+ Confirmation token did not match — aborting.
@@ -0,0 +1 @@
1
+ migrate-down requires interactive confirmation when stdin is not a TTY — pass --confirm {{token}} (this exact token, printed above) to proceed.
@@ -0,0 +1,3 @@
1
+
2
+ ⚠ DESTRUCTIVE: this rolls back the most recently applied migration on {{dialect}}.
3
+ Confirmation token: {{token}}
@@ -0,0 +1 @@
1
+ --name must be snake_case: lowercase letter then [a-z0-9_] (got "{{name}}")
@@ -0,0 +1 @@
1
+ migrate-path is not a directory: {{path}}
@@ -0,0 +1 @@
1
+ missing --connection — pass --connection <url> (e.g. ./app.sqlite for sqlite) or set one of: {{envVars}}. Run with --help for examples.
@@ -0,0 +1 @@
1
+ missing --name — pass --name <snake_case_slug>.
@@ -0,0 +1 @@
1
+ missing --name
@@ -0,0 +1 @@
1
+ missing --provider — pass --provider <{{providers}}>. Run with --help for examples.
@@ -0,0 +1 @@
1
+ missing --provider
@@ -0,0 +1 @@
1
+ missing value for {{flag}}
@@ -0,0 +1 @@
1
+ Cannot roll back "{{name}}": no <stem>_down.sql sibling found
@@ -0,0 +1 @@
1
+ Cannot roll back "{{name}}": no rollback_*.sql sibling found
@@ -0,0 +1 @@
1
+ Most recently applied migration is not present under --migrate-path
@@ -0,0 +1 @@
1
+ sqlite file: {{path}} does not exist — run 'migrate-setup --provider sqlite --connection {{path}}' to create it
@@ -0,0 +1 @@
1
+ unknown arg: {{arg}}
@@ -0,0 +1 @@
1
+ unsupported provider: {{provider}}
@@ -0,0 +1,9 @@
1
+ Setup complete: migrates and migrate_logs ready ({{dialect}}).
2
+ Migrations directory: {{migrationsPath}}
3
+
4
+ Next steps:
5
+ # create a new migration
6
+ {{createExample}}
7
+
8
+ # apply pending migrations
9
+ {{upExample}}
@@ -0,0 +1 @@
1
+ Applied: {{name}}
@@ -0,0 +1 @@
1
+ Created: {{file}}
@@ -0,0 +1 @@
1
+ No more pending migrations.
@@ -0,0 +1 @@
1
+ No pending migrations.
@@ -0,0 +1 @@
1
+ No applied migrations to roll back.
@@ -0,0 +1 @@
1
+ Rolled back: {{name}}
@@ -0,0 +1 @@
1
+ -- TODO: write the down migration for "{{name}}"
@@ -0,0 +1 @@
1
+ -- TODO: write the up migration for "{{name}}"
@@ -0,0 +1,11 @@
1
+ CREATE TABLE IF NOT EXISTS `migrate_logs` (
2
+ `id` BIGINT AUTO_INCREMENT PRIMARY KEY,
3
+ `migrate_name` VARCHAR(255) NOT NULL,
4
+ `direction` VARCHAR(8) NOT NULL,
5
+ `status` VARCHAR(16) NOT NULL,
6
+ `finished_at` TIMESTAMP NULL,
7
+ `duration_ms` INT,
8
+ `error_message` TEXT,
9
+ `created` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
10
+ `updated` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
11
+ );
@@ -0,0 +1,7 @@
1
+ CREATE TABLE IF NOT EXISTS `migrates` (
2
+ `id` BIGINT AUTO_INCREMENT PRIMARY KEY,
3
+ `name` VARCHAR(255) NOT NULL UNIQUE,
4
+ `checksum` VARCHAR(64),
5
+ `created` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
6
+ `updated` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
7
+ );
@@ -0,0 +1,14 @@
1
+ BEGIN
2
+ EXECUTE IMMEDIATE 'CREATE TABLE "migrate_logs" (
3
+ "id" NUMBER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
4
+ "migrate_name" VARCHAR2(255) NOT NULL,
5
+ "direction" VARCHAR2(8) NOT NULL,
6
+ "status" VARCHAR2(16) NOT NULL,
7
+ "finished_at" TIMESTAMP,
8
+ "duration_ms" NUMBER(10),
9
+ "error_message" CLOB,
10
+ "created" TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
11
+ "updated" TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL
12
+ )';
13
+ EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF;
14
+ END;
@@ -0,0 +1,10 @@
1
+ BEGIN
2
+ EXECUTE IMMEDIATE 'CREATE TABLE "migrates" (
3
+ "id" NUMBER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
4
+ "name" VARCHAR2(255) NOT NULL UNIQUE,
5
+ "checksum" VARCHAR2(64),
6
+ "created" TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
7
+ "updated" TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL
8
+ )';
9
+ EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF;
10
+ END;
@@ -0,0 +1,11 @@
1
+ CREATE TABLE IF NOT EXISTS "migrate_logs" (
2
+ "id" BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
3
+ "migrate_name" VARCHAR(255) NOT NULL,
4
+ "direction" VARCHAR(8) NOT NULL,
5
+ "status" VARCHAR(16) NOT NULL,
6
+ "finished_at" TIMESTAMPTZ,
7
+ "duration_ms" INTEGER,
8
+ "error_message" TEXT,
9
+ "created" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
10
+ "updated" TIMESTAMPTZ NOT NULL DEFAULT NOW()
11
+ );
@@ -0,0 +1,7 @@
1
+ CREATE TABLE IF NOT EXISTS "migrates" (
2
+ "id" BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
3
+ "name" VARCHAR(255) NOT NULL UNIQUE,
4
+ "checksum" VARCHAR(64),
5
+ "created" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
6
+ "updated" TIMESTAMPTZ NOT NULL DEFAULT NOW()
7
+ );
@@ -0,0 +1,11 @@
1
+ CREATE TABLE IF NOT EXISTS "migrate_logs" (
2
+ "id" INTEGER PRIMARY KEY AUTOINCREMENT,
3
+ "migrate_name" VARCHAR(255) NOT NULL,
4
+ "direction" VARCHAR(8) NOT NULL,
5
+ "status" VARCHAR(16) NOT NULL,
6
+ "finished_at" DATETIME,
7
+ "duration_ms" INTEGER,
8
+ "error_message" TEXT,
9
+ "created" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
10
+ "updated" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
11
+ );
@@ -0,0 +1,7 @@
1
+ CREATE TABLE IF NOT EXISTS "migrates" (
2
+ "id" INTEGER PRIMARY KEY AUTOINCREMENT,
3
+ "name" VARCHAR(255) NOT NULL UNIQUE,
4
+ "checksum" VARCHAR(64),
5
+ "created" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
6
+ "updated" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
7
+ );
@@ -0,0 +1,12 @@
1
+ IF OBJECT_ID('dbo.migrate_logs', 'U') IS NULL
2
+ CREATE TABLE [migrate_logs] (
3
+ [id] BIGINT IDENTITY(1,1) PRIMARY KEY,
4
+ [migrate_name] NVARCHAR(255) NOT NULL,
5
+ [direction] NVARCHAR(8) NOT NULL,
6
+ [status] NVARCHAR(16) NOT NULL,
7
+ [finished_at] DATETIME2,
8
+ [duration_ms] INT,
9
+ [error_message] NVARCHAR(MAX),
10
+ [created] DATETIME2 NOT NULL DEFAULT SYSUTCDATETIME(),
11
+ [updated] DATETIME2 NOT NULL DEFAULT SYSUTCDATETIME()
12
+ );
@@ -0,0 +1,8 @@
1
+ IF OBJECT_ID('dbo.migrates', 'U') IS NULL
2
+ CREATE TABLE [migrates] (
3
+ [id] BIGINT IDENTITY(1,1) PRIMARY KEY,
4
+ [name] NVARCHAR(255) NOT NULL UNIQUE,
5
+ [checksum] NVARCHAR(64),
6
+ [created] DATETIME2 NOT NULL DEFAULT SYSUTCDATETIME(),
7
+ [updated] DATETIME2 NOT NULL DEFAULT SYSUTCDATETIME()
8
+ );
package/package.json CHANGED
@@ -1,6 +1,80 @@
1
1
  {
2
2
  "name": "@deterministic-code/migraters",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.0.1",
4
+ "description": "TypeScript migrate executables for deterministic-code.",
5
+ "type": "module",
6
+ "exports": {
7
+ ".": {
8
+ "types": "./dist/index.d.ts",
9
+ "import": "./dist/index.js"
10
+ },
11
+ "./package.json": "./package.json"
12
+ },
13
+ "bin": {
14
+ "migrate-up": "./dist/bin/migrate-up.js",
15
+ "migrate-down": "./dist/bin/migrate-down.js",
16
+ "migrate-setup": "./dist/bin/migrate-setup.js",
17
+ "migrate-create": "./dist/bin/migrate-create.js",
18
+ "migrate-init": "./dist/bin/migrate-init.js"
19
+ },
20
+ "files": [
21
+ "dist",
22
+ "src",
23
+ "cli.yaml",
24
+ "bundle.yaml",
25
+ "tsconfig.build.json"
26
+ ],
27
+ "scripts": {
28
+ "build": "rm -rf dist && tsc -p tsconfig.build.json && cp -R ../shared/templates dist/templates",
29
+ "prepare": "npm run build",
30
+ "typecheck": "tsc -p tsconfig.build.json --noEmit",
31
+ "test": "vitest run --coverage",
32
+ "test:proof": "vitest run --config vitest.proof.config.ts",
33
+ "test:coverage": "vitest run --coverage",
34
+ "generate:help": "node --experimental-strip-types src/generate-help.ts",
35
+ "format": "prettier --write ."
36
+ },
37
+ "dependencies": {
38
+ "yaml": "^2.9.0"
39
+ },
40
+ "peerDependencies": {
41
+ "better-sqlite3": "^12.10.0",
42
+ "mssql": "^12.5.0",
43
+ "mysql2": "^3.22.2",
44
+ "oracledb": "^6.10.0",
45
+ "pg": "^8.13.0"
46
+ },
47
+ "peerDependenciesMeta": {
48
+ "better-sqlite3": {
49
+ "optional": true
50
+ },
51
+ "mssql": {
52
+ "optional": true
53
+ },
54
+ "mysql2": {
55
+ "optional": true
56
+ },
57
+ "oracledb": {
58
+ "optional": true
59
+ },
60
+ "pg": {
61
+ "optional": true
62
+ }
63
+ },
64
+ "devDependencies": {
65
+ "@types/better-sqlite3": "^7.6.11",
66
+ "better-sqlite3": "^12.10.0",
67
+ "@types/mssql": "^12.3.0",
68
+ "@types/node": "^22.10.0",
69
+ "@types/oracledb": "^6.10.3",
70
+ "@types/pg": "^8.11.10",
71
+ "@vitest/coverage-v8": "^3.2.4",
72
+ "mssql": "^12.5.0",
73
+ "mysql2": "^3.22.2",
74
+ "oracledb": "^6.10.0",
75
+ "pg": "^8.13.0",
76
+ "prettier": "^3.9.6",
77
+ "typescript": "^5.8.0",
78
+ "vitest": "^3.2.4"
79
+ }
80
+ }