@danceroutine/tango-migrations 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/CollectingBuilder-C6qnwyrb.js +28 -0
- package/dist/CollectingBuilder-C6qnwyrb.js.map +1 -0
- package/dist/CompilerStrategy-Cv1woBmO.js +55 -0
- package/dist/CompilerStrategy-Cv1woBmO.js.map +1 -0
- package/dist/InternalColumnType-_YAz7RqI.js +17 -0
- package/dist/InternalColumnType-_YAz7RqI.js.map +1 -0
- package/dist/InternalOperationKind-BPVoOQwD.js +20 -0
- package/dist/InternalOperationKind-BPVoOQwD.js.map +1 -0
- package/dist/IntrospectorStrategy-BM1Eizfc.js +38 -0
- package/dist/IntrospectorStrategy-BM1Eizfc.js.map +1 -0
- package/dist/Migration-D9J6ZbLP.js +25 -0
- package/dist/Migration-D9J6ZbLP.js.map +1 -0
- package/dist/MigrationGenerator-Z39LTKmC.js +199 -0
- package/dist/MigrationGenerator-Z39LTKmC.js.map +1 -0
- package/dist/MigrationRunner-CCFuPUlr.js +144 -0
- package/dist/MigrationRunner-CCFuPUlr.js.map +1 -0
- package/dist/SqliteCompilerFactory-DwMwO7xY.js +303 -0
- package/dist/SqliteCompilerFactory-DwMwO7xY.js.map +1 -0
- package/dist/SqliteIntrospector-BRdNt6KG.js +121 -0
- package/dist/SqliteIntrospector-BRdNt6KG.js.map +1 -0
- package/dist/builder/contracts/Builder.d.ts +11 -0
- package/dist/builder/contracts/ColumnSpec.d.ts +19 -0
- package/dist/builder/contracts/ColumnType.d.ts +2 -0
- package/dist/builder/contracts/DeleteReferentialAction.d.ts +2 -0
- package/dist/builder/contracts/UpdateReferentialAction.d.ts +2 -0
- package/dist/builder/contracts/index.d.ts +8 -0
- package/dist/builder/index.d.ts +10 -0
- package/dist/builder/index.js +6 -0
- package/dist/builder/ops/OpBuilder.d.ts +88 -0
- package/dist/builder/ops/OpBuilder.js +173 -0
- package/dist/builder/ops/index.d.ts +4 -0
- package/dist/builder/runtime/CollectingBuilder.d.ts +21 -0
- package/dist/builder/runtime/index.d.ts +4 -0
- package/dist/builder-Dtk8oP_Y.js +236 -0
- package/dist/builder-Dtk8oP_Y.js.map +1 -0
- package/dist/chunk-BkvOhyD0.js +12 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +178 -0
- package/dist/cli.js.map +1 -0
- package/dist/compilers/contracts/CompilerFactory.d.ts +4 -0
- package/dist/compilers/contracts/SQL.d.ts +4 -0
- package/dist/compilers/contracts/SQLCompiler.d.ts +5 -0
- package/dist/compilers/contracts/index.d.ts +6 -0
- package/dist/compilers/dialects/PostgresCompiler.d.ts +17 -0
- package/dist/compilers/dialects/SqliteCompiler.d.ts +10 -0
- package/dist/compilers/dialects/index.d.ts +5 -0
- package/dist/compilers/factories/PostgresCompilerFactory.d.ts +8 -0
- package/dist/compilers/factories/SqliteCompilerFactory.d.ts +8 -0
- package/dist/compilers/factories/index.d.ts +5 -0
- package/dist/compilers/index.d.ts +10 -0
- package/dist/compilers/index.js +6 -0
- package/dist/compilers-D8DJuTnQ.js +38 -0
- package/dist/compilers-D8DJuTnQ.js.map +1 -0
- package/dist/diff/diffSchema.d.ts +33 -0
- package/dist/diff/index.d.ts +4 -0
- package/dist/diff/index.js +8 -0
- package/dist/diff-Cs0TPEGR.js +10 -0
- package/dist/diff-Cs0TPEGR.js.map +1 -0
- package/dist/diffSchema-KgGHP-s3.js +86 -0
- package/dist/diffSchema-KgGHP-s3.js.map +1 -0
- package/dist/domain/Dialect.d.ts +2 -0
- package/dist/domain/Migration.d.ts +12 -0
- package/dist/domain/MigrationMode.d.ts +2 -0
- package/dist/domain/MigrationOperation.d.ts +76 -0
- package/dist/domain/MigrationOperation.js +1 -0
- package/dist/domain/index.d.ts +7 -0
- package/dist/domain/index.js +4 -0
- package/dist/domain/internal/InternalColumnType.d.ts +10 -0
- package/dist/domain/internal/InternalDialect.d.ts +4 -0
- package/dist/domain/internal/InternalMigrationMode.d.ts +4 -0
- package/dist/domain/internal/InternalOperationKind.d.ts +13 -0
- package/dist/domain/internal/InternalReferentialAction.d.ts +6 -0
- package/dist/domain-BXVlG0C0.js +10 -0
- package/dist/domain-BXVlG0C0.js.map +1 -0
- package/dist/generator/MigrationGenerator.d.ts +35 -0
- package/dist/generator/index.d.ts +4 -0
- package/dist/generator/index.js +5 -0
- package/dist/generator-3yC60b1u.js +10 -0
- package/dist/generator-3yC60b1u.js.map +1 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.js +21 -0
- package/dist/introspect/DatabaseIntrospector.d.ts +9 -0
- package/dist/introspect/PostgresIntrospector.d.ts +42 -0
- package/dist/introspect/SqliteIntrospector.d.ts +40 -0
- package/dist/introspect/index.d.ts +6 -0
- package/dist/introspect/index.js +4 -0
- package/dist/introspect-ks-QSodq.js +13 -0
- package/dist/introspect-ks-QSodq.js.map +1 -0
- package/dist/runner/MigrationRunner.d.ts +73 -0
- package/dist/runner/index.d.ts +4 -0
- package/dist/runner/index.js +10 -0
- package/dist/runner-BOs-tItW.js +10 -0
- package/dist/runner-BOs-tItW.js.map +1 -0
- package/dist/strategies/CompilerStrategy.d.ts +20 -0
- package/dist/strategies/IntrospectorStrategy.d.ts +19 -0
- package/dist/strategies/index.d.ts +5 -0
- package/dist/strategies/index.js +9 -0
- package/dist/strategies-BvHwf4as.js +16 -0
- package/dist/strategies-BvHwf4as.js.map +1 -0
- package/package.json +101 -0
package/dist/cli.js
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import "./CollectingBuilder-C6qnwyrb.js";
|
|
3
|
+
import "./Migration-D9J6ZbLP.js";
|
|
4
|
+
import "./InternalOperationKind-BPVoOQwD.js";
|
|
5
|
+
import "./InternalColumnType-_YAz7RqI.js";
|
|
6
|
+
import "./SqliteCompilerFactory-DwMwO7xY.js";
|
|
7
|
+
import "./CompilerStrategy-Cv1woBmO.js";
|
|
8
|
+
import { MigrationRunner } from "./MigrationRunner-CCFuPUlr.js";
|
|
9
|
+
import { MigrationGenerator } from "./MigrationGenerator-Z39LTKmC.js";
|
|
10
|
+
import "./builder-Dtk8oP_Y.js";
|
|
11
|
+
import { diffSchema } from "./diffSchema-KgGHP-s3.js";
|
|
12
|
+
import "./SqliteIntrospector-BRdNt6KG.js";
|
|
13
|
+
import { createDefaultIntrospectorStrategy } from "./IntrospectorStrategy-BM1Eizfc.js";
|
|
14
|
+
import yargs from "yargs";
|
|
15
|
+
import { hideBin } from "yargs/helpers";
|
|
16
|
+
import { resolve } from "node:path";
|
|
17
|
+
|
|
18
|
+
//#region src/cli.ts
|
|
19
|
+
async function loadModels(modelsPath) {
|
|
20
|
+
const absolutePath = resolve(process.cwd(), modelsPath);
|
|
21
|
+
const mod = await import(absolutePath);
|
|
22
|
+
const models = [];
|
|
23
|
+
for (const value of Object.values(mod)) if (value && typeof value === "object" && "metadata" in value) {
|
|
24
|
+
const model = value;
|
|
25
|
+
models.push(model.metadata);
|
|
26
|
+
}
|
|
27
|
+
if (models.length === 0) throw new Error(`No models found in '${modelsPath}'. ` + `Ensure the module exports Model() definitions.`);
|
|
28
|
+
return models;
|
|
29
|
+
}
|
|
30
|
+
async function connectAndIntrospect(dbUrl, dialect) {
|
|
31
|
+
if (dialect !== "postgres") throw new Error(`Introspection for '${dialect}' is not yet supported. Omit --db to generate from scratch.`);
|
|
32
|
+
const pg = await import("pg");
|
|
33
|
+
const client = new pg.default.Client({ connectionString: dbUrl });
|
|
34
|
+
await client.connect();
|
|
35
|
+
const dbClient = {
|
|
36
|
+
async query(sql) {
|
|
37
|
+
const result = await client.query(sql);
|
|
38
|
+
return { rows: result.rows };
|
|
39
|
+
},
|
|
40
|
+
async close() {
|
|
41
|
+
await client.end();
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
try {
|
|
45
|
+
const strategy = createDefaultIntrospectorStrategy();
|
|
46
|
+
return await strategy.introspect("postgres", dbClient);
|
|
47
|
+
} finally {
|
|
48
|
+
await dbClient.close();
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
yargs(hideBin(process.argv)).command("migrate", "Apply pending migrations to the database", (yargsBuilder) => yargsBuilder.option("dir", {
|
|
52
|
+
type: "string",
|
|
53
|
+
default: "migrations",
|
|
54
|
+
describe: "Migrations directory"
|
|
55
|
+
}).option("db", {
|
|
56
|
+
type: "string",
|
|
57
|
+
demandOption: true,
|
|
58
|
+
describe: "Database connection URL"
|
|
59
|
+
}).option("dialect", {
|
|
60
|
+
type: "string",
|
|
61
|
+
choices: ["postgres", "sqlite"],
|
|
62
|
+
default: "postgres",
|
|
63
|
+
describe: "Database dialect"
|
|
64
|
+
}).option("to", {
|
|
65
|
+
type: "string",
|
|
66
|
+
describe: "Target migration ID (apply up to this migration)"
|
|
67
|
+
}), async (argv) => {
|
|
68
|
+
const pg = await import("pg");
|
|
69
|
+
const client = new pg.default.Client({ connectionString: argv.db });
|
|
70
|
+
await client.connect();
|
|
71
|
+
const dbClient = {
|
|
72
|
+
async query(sql, params) {
|
|
73
|
+
const result = await client.query(sql, params);
|
|
74
|
+
return { rows: result.rows };
|
|
75
|
+
},
|
|
76
|
+
async close() {
|
|
77
|
+
await client.end();
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
const runner = new MigrationRunner(dbClient, argv.dialect, argv.dir);
|
|
81
|
+
await runner.apply(argv.to);
|
|
82
|
+
await dbClient.close();
|
|
83
|
+
console.log("Migrations applied successfully");
|
|
84
|
+
}).command("make:migrations", "Generate migration file by comparing models to database", (yargsBuilder) => yargsBuilder.option("dir", {
|
|
85
|
+
type: "string",
|
|
86
|
+
default: "migrations",
|
|
87
|
+
describe: "Migrations directory"
|
|
88
|
+
}).option("name", {
|
|
89
|
+
type: "string",
|
|
90
|
+
demandOption: true,
|
|
91
|
+
describe: "Migration name (e.g. \"create_users\")"
|
|
92
|
+
}).option("models", {
|
|
93
|
+
type: "string",
|
|
94
|
+
demandOption: true,
|
|
95
|
+
describe: "Path to module exporting Model definitions (e.g. \"./src/models.ts\")"
|
|
96
|
+
}).option("db", {
|
|
97
|
+
type: "string",
|
|
98
|
+
describe: "Database connection URL for introspection (omit for initial migration)"
|
|
99
|
+
}).option("dialect", {
|
|
100
|
+
type: "string",
|
|
101
|
+
choices: ["postgres", "sqlite"],
|
|
102
|
+
default: "postgres",
|
|
103
|
+
describe: "Database dialect"
|
|
104
|
+
}), async (argv) => {
|
|
105
|
+
const models = await loadModels(argv.models);
|
|
106
|
+
console.log(`Found ${models.length} model(s): ${models.map((m) => m.table).join(", ")}`);
|
|
107
|
+
let dbState;
|
|
108
|
+
if (argv.db) {
|
|
109
|
+
console.log("Introspecting database...");
|
|
110
|
+
dbState = await connectAndIntrospect(argv.db, argv.dialect);
|
|
111
|
+
} else dbState = { tables: {} };
|
|
112
|
+
const operations = diffSchema(dbState, models);
|
|
113
|
+
if (operations.length === 0) {
|
|
114
|
+
console.log("No changes detected — models and database are in sync");
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
const generator = new MigrationGenerator();
|
|
118
|
+
const filepath = await generator.generate({
|
|
119
|
+
name: argv.name,
|
|
120
|
+
operations,
|
|
121
|
+
directory: argv.dir
|
|
122
|
+
});
|
|
123
|
+
console.log(`Generated migration: ${filepath}`);
|
|
124
|
+
console.log(` ${operations.length} operation(s)`);
|
|
125
|
+
}).command("plan", "Print migration SQL without applying", (yargsBuilder) => yargsBuilder.option("dir", {
|
|
126
|
+
type: "string",
|
|
127
|
+
default: "migrations",
|
|
128
|
+
describe: "Migrations directory"
|
|
129
|
+
}).option("dialect", {
|
|
130
|
+
type: "string",
|
|
131
|
+
choices: ["postgres", "sqlite"],
|
|
132
|
+
default: "postgres",
|
|
133
|
+
describe: "Database dialect"
|
|
134
|
+
}), async (argv) => {
|
|
135
|
+
const runner = new MigrationRunner({
|
|
136
|
+
query: async () => ({ rows: [] }),
|
|
137
|
+
close: async () => {}
|
|
138
|
+
}, argv.dialect, argv.dir);
|
|
139
|
+
const output = await runner.plan();
|
|
140
|
+
console.log(output);
|
|
141
|
+
}).command("status", "Show applied/pending status of all migrations", (yargsBuilder) => yargsBuilder.option("dir", {
|
|
142
|
+
type: "string",
|
|
143
|
+
default: "migrations",
|
|
144
|
+
describe: "Migrations directory"
|
|
145
|
+
}).option("db", {
|
|
146
|
+
type: "string",
|
|
147
|
+
demandOption: true,
|
|
148
|
+
describe: "Database connection URL"
|
|
149
|
+
}).option("dialect", {
|
|
150
|
+
type: "string",
|
|
151
|
+
choices: ["postgres", "sqlite"],
|
|
152
|
+
default: "postgres",
|
|
153
|
+
describe: "Database dialect"
|
|
154
|
+
}), async (argv) => {
|
|
155
|
+
const pg = await import("pg");
|
|
156
|
+
const client = new pg.default.Client({ connectionString: argv.db });
|
|
157
|
+
await client.connect();
|
|
158
|
+
const dbClient = {
|
|
159
|
+
async query(sql, params) {
|
|
160
|
+
const result = await client.query(sql, params);
|
|
161
|
+
return { rows: result.rows };
|
|
162
|
+
},
|
|
163
|
+
async close() {
|
|
164
|
+
await client.end();
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
const runner = new MigrationRunner(dbClient, argv.dialect, argv.dir);
|
|
168
|
+
const statuses = await runner.status();
|
|
169
|
+
if (statuses.length === 0) console.log("No migrations found");
|
|
170
|
+
else statuses.forEach((s) => {
|
|
171
|
+
const marker = s.applied ? "[x]" : "[ ]";
|
|
172
|
+
console.log(` ${marker} ${s.id}`);
|
|
173
|
+
});
|
|
174
|
+
await dbClient.close();
|
|
175
|
+
}).demandCommand(1, "You must specify a command").strict().help().alias("help", "h").alias("version", "v").parse();
|
|
176
|
+
|
|
177
|
+
//#endregion
|
|
178
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","names":["modelsPath: string","models: ModelMetadataLike[]","dbUrl: string","dialect: string","sql: string","params?: readonly unknown[]","dbState: DbSchema"],"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport yargs from 'yargs';\nimport { hideBin } from 'yargs/helpers';\nimport { resolve } from 'node:path';\nimport { MigrationRunner } from './runner/MigrationRunner';\nimport { MigrationGenerator } from './generator/MigrationGenerator';\nimport { diffSchema } from './diff/diffSchema';\nimport type { DbSchema } from './introspect/PostgresIntrospector';\nimport type { Dialect } from './domain/Dialect';\nimport type { ColumnType } from './builder/contracts/ColumnType';\nimport type { DeleteReferentialAction } from './builder/contracts/DeleteReferentialAction';\nimport type { UpdateReferentialAction } from './builder/contracts/UpdateReferentialAction';\nimport { createDefaultIntrospectorStrategy } from './strategies/IntrospectorStrategy';\n\ntype ModelMetadataLike = {\n table: string;\n fields: Array<{\n name: string;\n type: ColumnType;\n notNull?: boolean;\n default?: string | { now: true } | null;\n primaryKey?: boolean;\n unique?: boolean;\n references?: {\n table: string;\n column: string;\n onDelete?: DeleteReferentialAction;\n onUpdate?: UpdateReferentialAction;\n };\n }>;\n indexes?: Array<{ name: string; on: string[]; unique?: boolean }>;\n};\n\nasync function loadModels(modelsPath: string): Promise<ModelMetadataLike[]> {\n const absolutePath = resolve(process.cwd(), modelsPath);\n const mod = await import(absolutePath);\n\n const models: ModelMetadataLike[] = [];\n\n for (const value of Object.values(mod)) {\n if (value && typeof value === 'object' && 'metadata' in value) {\n const model = value as { metadata: ModelMetadataLike };\n models.push(model.metadata);\n }\n }\n\n if (models.length === 0) {\n throw new Error(`No models found in '${modelsPath}'. ` + `Ensure the module exports Model() definitions.`);\n }\n\n return models;\n}\n\nasync function connectAndIntrospect(dbUrl: string, dialect: string): Promise<DbSchema> {\n if (dialect !== 'postgres') {\n throw new Error(`Introspection for '${dialect}' is not yet supported. Omit --db to generate from scratch.`);\n }\n\n const pg = await import('pg');\n const client = new pg.default.Client({ connectionString: dbUrl });\n await client.connect();\n\n const dbClient = {\n async query<T = unknown>(sql: string): Promise<{ rows: T[] }> {\n const result = await client.query(sql);\n return { rows: result.rows as T[] };\n },\n async close() {\n await client.end();\n },\n };\n\n try {\n const strategy = createDefaultIntrospectorStrategy();\n return await strategy.introspect('postgres' as Dialect, dbClient);\n } finally {\n await dbClient.close();\n }\n}\n\nyargs(hideBin(process.argv))\n .command(\n 'migrate',\n 'Apply pending migrations to the database',\n (yargsBuilder) =>\n yargsBuilder\n .option('dir', {\n type: 'string',\n default: 'migrations',\n describe: 'Migrations directory',\n })\n .option('db', {\n type: 'string',\n demandOption: true,\n describe: 'Database connection URL',\n })\n .option('dialect', {\n type: 'string',\n choices: ['postgres', 'sqlite'] as const,\n default: 'postgres' as const,\n describe: 'Database dialect',\n })\n .option('to', {\n type: 'string',\n describe: 'Target migration ID (apply up to this migration)',\n }),\n async (argv) => {\n const pg = await import('pg');\n const client = new pg.default.Client({ connectionString: argv.db });\n await client.connect();\n\n const dbClient = {\n async query<T = unknown>(sql: string, params?: readonly unknown[]): Promise<{ rows: T[] }> {\n const result = await client.query(sql, params as unknown[] | undefined);\n return { rows: result.rows as T[] };\n },\n async close() {\n await client.end();\n },\n };\n\n const runner = new MigrationRunner(dbClient, argv.dialect as Dialect, argv.dir);\n await runner.apply(argv.to);\n\n await dbClient.close();\n console.log('Migrations applied successfully');\n }\n )\n .command(\n 'make:migrations',\n 'Generate migration file by comparing models to database',\n (yargsBuilder) =>\n yargsBuilder\n .option('dir', {\n type: 'string',\n default: 'migrations',\n describe: 'Migrations directory',\n })\n .option('name', {\n type: 'string',\n demandOption: true,\n describe: 'Migration name (e.g. \"create_users\")',\n })\n .option('models', {\n type: 'string',\n demandOption: true,\n describe: 'Path to module exporting Model definitions (e.g. \"./src/models.ts\")',\n })\n .option('db', {\n type: 'string',\n describe: 'Database connection URL for introspection (omit for initial migration)',\n })\n .option('dialect', {\n type: 'string',\n choices: ['postgres', 'sqlite'] as const,\n default: 'postgres' as const,\n describe: 'Database dialect',\n }),\n async (argv) => {\n const models = await loadModels(argv.models);\n console.log(`Found ${models.length} model(s): ${models.map((m) => m.table).join(', ')}`);\n\n let dbState: DbSchema;\n if (argv.db) {\n console.log('Introspecting database...');\n dbState = await connectAndIntrospect(argv.db, argv.dialect);\n } else {\n dbState = { tables: {} };\n }\n\n const operations = diffSchema(dbState, models);\n\n if (operations.length === 0) {\n console.log('No changes detected — models and database are in sync');\n return;\n }\n\n const generator = new MigrationGenerator();\n const filepath = await generator.generate({\n name: argv.name,\n operations,\n directory: argv.dir,\n });\n\n console.log(`Generated migration: ${filepath}`);\n console.log(` ${operations.length} operation(s)`);\n }\n )\n .command(\n 'plan',\n 'Print migration SQL without applying',\n (yargsBuilder) =>\n yargsBuilder\n .option('dir', {\n type: 'string',\n default: 'migrations',\n describe: 'Migrations directory',\n })\n .option('dialect', {\n type: 'string',\n choices: ['postgres', 'sqlite'] as const,\n default: 'postgres' as const,\n describe: 'Database dialect',\n }),\n async (argv) => {\n const runner = new MigrationRunner(\n { query: async () => ({ rows: [] }), close: async () => {} },\n argv.dialect as Dialect,\n argv.dir\n );\n const output = await runner.plan();\n console.log(output);\n }\n )\n .command(\n 'status',\n 'Show applied/pending status of all migrations',\n (yargsBuilder) =>\n yargsBuilder\n .option('dir', {\n type: 'string',\n default: 'migrations',\n describe: 'Migrations directory',\n })\n .option('db', {\n type: 'string',\n demandOption: true,\n describe: 'Database connection URL',\n })\n .option('dialect', {\n type: 'string',\n choices: ['postgres', 'sqlite'] as const,\n default: 'postgres' as const,\n describe: 'Database dialect',\n }),\n async (argv) => {\n const pg = await import('pg');\n const client = new pg.default.Client({ connectionString: argv.db });\n await client.connect();\n\n const dbClient = {\n async query<T = unknown>(sql: string, params?: readonly unknown[]): Promise<{ rows: T[] }> {\n const result = await client.query(sql, params as unknown[] | undefined);\n return { rows: result.rows as T[] };\n },\n async close() {\n await client.end();\n },\n };\n\n const runner = new MigrationRunner(dbClient, argv.dialect as Dialect, argv.dir);\n const statuses = await runner.status();\n\n if (statuses.length === 0) {\n console.log('No migrations found');\n } else {\n statuses.forEach((s) => {\n const marker = s.applied ? '[x]' : '[ ]';\n console.log(` ${marker} ${s.id}`);\n });\n }\n\n await dbClient.close();\n }\n )\n .demandCommand(1, 'You must specify a command')\n .strict()\n .help()\n .alias('help', 'h')\n .alias('version', 'v')\n .parse();\n"],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { MigrationOperation } from '../../domain/MigrationOperation';
|
|
2
|
+
import type { SQL } from '../contracts/SQL';
|
|
3
|
+
import type { SQLCompiler } from '../contracts/SQLCompiler';
|
|
4
|
+
export declare class PostgresCompiler implements SQLCompiler {
|
|
5
|
+
static readonly BRAND: "tango.migrations.postgres_compiler";
|
|
6
|
+
readonly __tangoBrand: typeof PostgresCompiler.BRAND;
|
|
7
|
+
static isPostgresCompiler(value: unknown): value is PostgresCompiler;
|
|
8
|
+
compile(op: MigrationOperation): SQL[];
|
|
9
|
+
/**
|
|
10
|
+
* Compile a DEFAULT value change into ALTER TABLE statements.
|
|
11
|
+
* Extracted to flatten the nested conditional logic.
|
|
12
|
+
*/
|
|
13
|
+
private compileDefaultChange;
|
|
14
|
+
private id;
|
|
15
|
+
private colDDL;
|
|
16
|
+
private typeToSQL;
|
|
17
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { MigrationOperation } from '../../domain/MigrationOperation';
|
|
2
|
+
import type { SQL } from '../contracts/SQL';
|
|
3
|
+
import type { SQLCompiler } from '../contracts/SQLCompiler';
|
|
4
|
+
export declare class SqliteCompiler implements SQLCompiler {
|
|
5
|
+
static readonly BRAND: "tango.migrations.sqlite_compiler";
|
|
6
|
+
readonly __tangoBrand: typeof SqliteCompiler.BRAND;
|
|
7
|
+
static isSqliteCompiler(value: unknown): value is SqliteCompiler;
|
|
8
|
+
compile(op: MigrationOperation): SQL[];
|
|
9
|
+
private colDDL;
|
|
10
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { CompilerFactory } from '../contracts/CompilerFactory';
|
|
2
|
+
import type { SQLCompiler } from '../contracts/SQLCompiler';
|
|
3
|
+
export declare class PostgresCompilerFactory implements CompilerFactory {
|
|
4
|
+
static readonly BRAND: "tango.migrations.postgres_compiler_factory";
|
|
5
|
+
readonly __tangoBrand: typeof PostgresCompilerFactory.BRAND;
|
|
6
|
+
static isPostgresCompilerFactory(value: unknown): value is PostgresCompilerFactory;
|
|
7
|
+
create(): SQLCompiler;
|
|
8
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { CompilerFactory } from '../contracts/CompilerFactory';
|
|
2
|
+
import type { SQLCompiler } from '../contracts/SQLCompiler';
|
|
3
|
+
export declare class SqliteCompilerFactory implements CompilerFactory {
|
|
4
|
+
static readonly BRAND: "tango.migrations.sqlite_compiler_factory";
|
|
5
|
+
readonly __tangoBrand: typeof SqliteCompilerFactory.BRAND;
|
|
6
|
+
static isSqliteCompilerFactory(value: unknown): value is SqliteCompilerFactory;
|
|
7
|
+
create(): SQLCompiler;
|
|
8
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Domain boundary barrel: exposes namespaced exports for Django-style drill-down
|
|
3
|
+
* imports and curated flat exports for TS-native ergonomics.
|
|
4
|
+
*/
|
|
5
|
+
export * as contracts from './contracts/index';
|
|
6
|
+
export * as dialects from './dialects/index';
|
|
7
|
+
export * as factories from './factories/index';
|
|
8
|
+
export type { SQL, SQLCompiler, CompilerFactory } from './contracts/index';
|
|
9
|
+
export { PostgresCompiler, SqliteCompiler } from './dialects/index';
|
|
10
|
+
export * from './factories/index';
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import "../InternalOperationKind-BPVoOQwD.js";
|
|
2
|
+
import "../InternalColumnType-_YAz7RqI.js";
|
|
3
|
+
import { PostgresCompiler, PostgresCompilerFactory, SqliteCompiler, SqliteCompilerFactory } from "../SqliteCompilerFactory-DwMwO7xY.js";
|
|
4
|
+
import { contracts_exports$1 as contracts_exports, dialects_exports, factories_exports } from "../compilers-D8DJuTnQ.js";
|
|
5
|
+
|
|
6
|
+
export { PostgresCompiler, PostgresCompilerFactory, SqliteCompiler, SqliteCompilerFactory, contracts_exports as contracts, dialects_exports as dialects, factories_exports as factories };
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { __export } from "./chunk-BkvOhyD0.js";
|
|
2
|
+
import { PostgresCompiler, PostgresCompilerFactory, SqliteCompiler, SqliteCompilerFactory } from "./SqliteCompilerFactory-DwMwO7xY.js";
|
|
3
|
+
|
|
4
|
+
//#region src/compilers/contracts/index.ts
|
|
5
|
+
var contracts_exports = {};
|
|
6
|
+
|
|
7
|
+
//#endregion
|
|
8
|
+
//#region src/compilers/dialects/index.ts
|
|
9
|
+
var dialects_exports = {};
|
|
10
|
+
__export(dialects_exports, {
|
|
11
|
+
PostgresCompiler: () => PostgresCompiler,
|
|
12
|
+
SqliteCompiler: () => SqliteCompiler
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
//#endregion
|
|
16
|
+
//#region src/compilers/factories/index.ts
|
|
17
|
+
var factories_exports = {};
|
|
18
|
+
__export(factories_exports, {
|
|
19
|
+
PostgresCompilerFactory: () => PostgresCompilerFactory,
|
|
20
|
+
SqliteCompilerFactory: () => SqliteCompilerFactory
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
//#endregion
|
|
24
|
+
//#region src/compilers/index.ts
|
|
25
|
+
var compilers_exports = {};
|
|
26
|
+
__export(compilers_exports, {
|
|
27
|
+
PostgresCompiler: () => PostgresCompiler,
|
|
28
|
+
PostgresCompilerFactory: () => PostgresCompilerFactory,
|
|
29
|
+
SqliteCompiler: () => SqliteCompiler,
|
|
30
|
+
SqliteCompilerFactory: () => SqliteCompilerFactory,
|
|
31
|
+
contracts: () => contracts_exports,
|
|
32
|
+
dialects: () => dialects_exports,
|
|
33
|
+
factories: () => factories_exports
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
//#endregion
|
|
37
|
+
export { compilers_exports, contracts_exports as contracts_exports$1, dialects_exports, factories_exports };
|
|
38
|
+
//# sourceMappingURL=compilers-D8DJuTnQ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compilers-D8DJuTnQ.js","names":[],"sources":["../src/compilers/contracts/index.ts","../src/compilers/dialects/index.ts","../src/compilers/factories/index.ts","../src/compilers/index.ts"],"sourcesContent":["/**\n * Domain boundary barrel: centralizes this subdomain's public contract.\n */\n\nexport type { SQL } from './SQL';\nexport type { SQLCompiler } from './SQLCompiler';\nexport type { CompilerFactory } from './CompilerFactory';\n","/**\n * Domain boundary barrel: centralizes this subdomain's public contract.\n */\n\nexport { PostgresCompiler } from './PostgresCompiler';\nexport { SqliteCompiler } from './SqliteCompiler';\n","/**\n * Domain boundary barrel: centralizes this subdomain's public contract.\n */\n\nexport { PostgresCompilerFactory } from './PostgresCompilerFactory';\nexport { SqliteCompilerFactory } from './SqliteCompilerFactory';\n","/**\n * Domain boundary barrel: exposes namespaced exports for Django-style drill-down\n * imports and curated flat exports for TS-native ergonomics.\n */\n\nexport * as contracts from './contracts/index';\nexport * as dialects from './dialects/index';\nexport * as factories from './factories/index';\n\nexport type { SQL, SQLCompiler, CompilerFactory } from './contracts/index';\nexport { PostgresCompiler, SqliteCompiler } from './dialects/index';\nexport * from './factories/index';\n"],"mappings":""}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { DbSchema } from '../introspect/PostgresIntrospector';
|
|
2
|
+
import type { MigrationOperation } from '../domain/MigrationOperation';
|
|
3
|
+
import type { ColumnType } from '../builder/contracts/ColumnType';
|
|
4
|
+
import type { DeleteReferentialAction } from '../builder/contracts/DeleteReferentialAction';
|
|
5
|
+
import type { UpdateReferentialAction } from '../builder/contracts/UpdateReferentialAction';
|
|
6
|
+
type ModelField = {
|
|
7
|
+
name: string;
|
|
8
|
+
type: ColumnType;
|
|
9
|
+
notNull?: boolean;
|
|
10
|
+
default?: string | {
|
|
11
|
+
now: true;
|
|
12
|
+
} | null;
|
|
13
|
+
primaryKey?: boolean;
|
|
14
|
+
unique?: boolean;
|
|
15
|
+
references?: {
|
|
16
|
+
table: string;
|
|
17
|
+
column: string;
|
|
18
|
+
onDelete?: DeleteReferentialAction;
|
|
19
|
+
onUpdate?: UpdateReferentialAction;
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
type ModelIndex = {
|
|
23
|
+
name: string;
|
|
24
|
+
on: string[];
|
|
25
|
+
unique?: boolean;
|
|
26
|
+
};
|
|
27
|
+
type ModelMetadataLike = {
|
|
28
|
+
table: string;
|
|
29
|
+
fields: ModelField[];
|
|
30
|
+
indexes?: ModelIndex[];
|
|
31
|
+
};
|
|
32
|
+
export declare function diffSchema(db: DbSchema, models: ModelMetadataLike[]): MigrationOperation[];
|
|
33
|
+
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import "../CollectingBuilder-C6qnwyrb.js";
|
|
2
|
+
import "../InternalOperationKind-BPVoOQwD.js";
|
|
3
|
+
import "../InternalColumnType-_YAz7RqI.js";
|
|
4
|
+
import "../builder-Dtk8oP_Y.js";
|
|
5
|
+
import { diffSchema } from "../diffSchema-KgGHP-s3.js";
|
|
6
|
+
import "../diff-Cs0TPEGR.js";
|
|
7
|
+
|
|
8
|
+
export { diffSchema };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { __export } from "./chunk-BkvOhyD0.js";
|
|
2
|
+
import { diffSchema } from "./diffSchema-KgGHP-s3.js";
|
|
3
|
+
|
|
4
|
+
//#region src/diff/index.ts
|
|
5
|
+
var diff_exports = {};
|
|
6
|
+
__export(diff_exports, { diffSchema: () => diffSchema });
|
|
7
|
+
|
|
8
|
+
//#endregion
|
|
9
|
+
export { diff_exports };
|
|
10
|
+
//# sourceMappingURL=diff-Cs0TPEGR.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff-Cs0TPEGR.js","names":[],"sources":["../src/diff/index.ts"],"sourcesContent":["/**\n * Domain boundary barrel: centralizes this subdomain's public contract.\n */\n\nexport { diffSchema } from './diffSchema';\n"],"mappings":""}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { OpBuilder, applyFieldType } from "./builder-Dtk8oP_Y.js";
|
|
2
|
+
|
|
3
|
+
//#region src/diff/diffSchema.ts
|
|
4
|
+
function diffSchema(db, models) {
|
|
5
|
+
const ops = [];
|
|
6
|
+
const modelTables = new Set(models.map((model) => model.table));
|
|
7
|
+
const internalTables = new Set(["_tango_migrations"]);
|
|
8
|
+
models.forEach((model) => {
|
|
9
|
+
const dbTable = db.tables[model.table];
|
|
10
|
+
if (!dbTable) {
|
|
11
|
+
ops.push(OpBuilder.table(model.table).create((cols) => {
|
|
12
|
+
model.fields.forEach((field) => {
|
|
13
|
+
cols.add(field.name, (builder) => {
|
|
14
|
+
builder = applyFieldType(builder, field.type);
|
|
15
|
+
if (field.notNull) builder = builder.notNull();
|
|
16
|
+
if (field.default === null) builder = builder.default(null);
|
|
17
|
+
else if (field.default && typeof field.default === "object" && "now" in field.default) builder = builder.defaultNow();
|
|
18
|
+
else if (typeof field.default === "string") builder = builder.default(field.default);
|
|
19
|
+
if (field.primaryKey) builder = builder.primaryKey();
|
|
20
|
+
if (field.unique) builder = builder.unique();
|
|
21
|
+
if (field.references) builder = builder.references(field.references.table, field.references.column, {
|
|
22
|
+
onDelete: field.references.onDelete,
|
|
23
|
+
onUpdate: field.references.onUpdate
|
|
24
|
+
});
|
|
25
|
+
return builder;
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
}));
|
|
29
|
+
(model.indexes ?? []).forEach((index) => {
|
|
30
|
+
ops.push(OpBuilder.index.create({
|
|
31
|
+
name: index.name,
|
|
32
|
+
table: model.table,
|
|
33
|
+
on: index.on,
|
|
34
|
+
unique: !!index.unique
|
|
35
|
+
}));
|
|
36
|
+
});
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
const modelFieldNames = new Set(model.fields.map((field) => field.name));
|
|
40
|
+
const dbFieldNames = new Set(Object.keys(dbTable.columns));
|
|
41
|
+
model.fields.forEach((field) => {
|
|
42
|
+
if (!dbFieldNames.has(field.name)) ops.push(OpBuilder.table(model.table).addColumn(field.name, (builder) => {
|
|
43
|
+
builder = applyFieldType(builder, field.type);
|
|
44
|
+
if (field.notNull) builder = builder.notNull();
|
|
45
|
+
if (field.default === null) builder = builder.default(null);
|
|
46
|
+
else if (field.default && typeof field.default === "object" && "now" in field.default) builder = builder.defaultNow();
|
|
47
|
+
else if (typeof field.default === "string") builder = builder.default(field.default);
|
|
48
|
+
if (field.primaryKey) builder = builder.primaryKey();
|
|
49
|
+
if (field.unique) builder = builder.unique();
|
|
50
|
+
if (field.references) builder = builder.references(field.references.table, field.references.column, {
|
|
51
|
+
onDelete: field.references.onDelete,
|
|
52
|
+
onUpdate: field.references.onUpdate
|
|
53
|
+
});
|
|
54
|
+
return builder;
|
|
55
|
+
}));
|
|
56
|
+
});
|
|
57
|
+
dbFieldNames.forEach((dbColumnName) => {
|
|
58
|
+
if (!modelFieldNames.has(dbColumnName)) ops.push(OpBuilder.table(model.table).dropColumn(dbColumnName));
|
|
59
|
+
});
|
|
60
|
+
const modelIndexes = new Map((model.indexes ?? []).map((index) => [index.name, index]));
|
|
61
|
+
const dbIndexNames = new Set(Object.keys(dbTable.indexes));
|
|
62
|
+
modelIndexes.forEach((index, indexName) => {
|
|
63
|
+
if (!dbIndexNames.has(indexName)) ops.push(OpBuilder.index.create({
|
|
64
|
+
name: index.name,
|
|
65
|
+
table: model.table,
|
|
66
|
+
on: index.on,
|
|
67
|
+
unique: !!index.unique
|
|
68
|
+
}));
|
|
69
|
+
});
|
|
70
|
+
dbIndexNames.forEach((dbIndexName) => {
|
|
71
|
+
if (!modelIndexes.has(dbIndexName)) ops.push(OpBuilder.index.drop({
|
|
72
|
+
name: dbIndexName,
|
|
73
|
+
table: model.table
|
|
74
|
+
}));
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
Object.keys(db.tables).forEach((dbTableName) => {
|
|
78
|
+
if (internalTables.has(dbTableName)) return;
|
|
79
|
+
if (!modelTables.has(dbTableName)) ops.push(OpBuilder.table(dbTableName).drop());
|
|
80
|
+
});
|
|
81
|
+
return ops;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
//#endregion
|
|
85
|
+
export { diffSchema };
|
|
86
|
+
//# sourceMappingURL=diffSchema-KgGHP-s3.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diffSchema-KgGHP-s3.js","names":["db: DbSchema","models: ModelMetadataLike[]","ops: MigrationOperation[]"],"sources":["../src/diff/diffSchema.ts"],"sourcesContent":["import type { DbSchema } from '../introspect/PostgresIntrospector';\nimport type { MigrationOperation } from '../domain/MigrationOperation';\nimport type { ColumnType } from '../builder/contracts/ColumnType';\nimport type { DeleteReferentialAction } from '../builder/contracts/DeleteReferentialAction';\nimport type { UpdateReferentialAction } from '../builder/contracts/UpdateReferentialAction';\nimport { op, applyFieldType } from '../builder/index';\n\ntype ModelField = {\n name: string;\n type: ColumnType;\n notNull?: boolean;\n default?: string | { now: true } | null;\n primaryKey?: boolean;\n unique?: boolean;\n references?: {\n table: string;\n column: string;\n onDelete?: DeleteReferentialAction;\n onUpdate?: UpdateReferentialAction;\n };\n};\n\ntype ModelIndex = {\n name: string;\n on: string[];\n unique?: boolean;\n};\n\ntype ModelMetadataLike = {\n table: string;\n fields: ModelField[];\n indexes?: ModelIndex[];\n};\n\nexport function diffSchema(db: DbSchema, models: ModelMetadataLike[]): MigrationOperation[] {\n const ops: MigrationOperation[] = [];\n const modelTables = new Set(models.map((model) => model.table));\n const internalTables = new Set(['_tango_migrations']);\n\n models.forEach((model) => {\n const dbTable = db.tables[model.table];\n\n if (!dbTable) {\n ops.push(\n op.table(model.table).create((cols) => {\n model.fields.forEach((field) => {\n cols.add(field.name, (builder) => {\n builder = applyFieldType(builder, field.type);\n\n if (field.notNull) {\n builder = builder.notNull();\n }\n\n if (field.default === null) {\n builder = builder.default(null);\n } else if (field.default && typeof field.default === 'object' && 'now' in field.default) {\n builder = builder.defaultNow();\n } else if (typeof field.default === 'string') {\n builder = builder.default(field.default);\n }\n\n if (field.primaryKey) {\n builder = builder.primaryKey();\n }\n\n if (field.unique) {\n builder = builder.unique();\n }\n\n if (field.references) {\n builder = builder.references(field.references.table, field.references.column, {\n onDelete: field.references.onDelete,\n onUpdate: field.references.onUpdate,\n });\n }\n\n return builder;\n });\n });\n })\n );\n\n (model.indexes ?? []).forEach((index) => {\n ops.push(\n op.index.create({\n name: index.name,\n table: model.table,\n on: index.on,\n unique: !!index.unique,\n })\n );\n });\n return;\n }\n\n const modelFieldNames = new Set(model.fields.map((field) => field.name));\n const dbFieldNames = new Set(Object.keys(dbTable.columns));\n\n model.fields.forEach((field) => {\n if (!dbFieldNames.has(field.name)) {\n ops.push(\n op.table(model.table).addColumn(field.name, (builder) => {\n builder = applyFieldType(builder, field.type);\n\n if (field.notNull) {\n builder = builder.notNull();\n }\n if (field.default === null) {\n builder = builder.default(null);\n } else if (field.default && typeof field.default === 'object' && 'now' in field.default) {\n builder = builder.defaultNow();\n } else if (typeof field.default === 'string') {\n builder = builder.default(field.default);\n }\n if (field.primaryKey) {\n builder = builder.primaryKey();\n }\n if (field.unique) {\n builder = builder.unique();\n }\n if (field.references) {\n builder = builder.references(field.references.table, field.references.column, {\n onDelete: field.references.onDelete,\n onUpdate: field.references.onUpdate,\n });\n }\n\n return builder;\n })\n );\n }\n });\n\n dbFieldNames.forEach((dbColumnName) => {\n if (!modelFieldNames.has(dbColumnName)) {\n ops.push(op.table(model.table).dropColumn(dbColumnName));\n }\n });\n\n const modelIndexes = new Map((model.indexes ?? []).map((index) => [index.name, index] as const));\n const dbIndexNames = new Set(Object.keys(dbTable.indexes));\n\n modelIndexes.forEach((index, indexName) => {\n if (!dbIndexNames.has(indexName)) {\n ops.push(\n op.index.create({\n name: index.name,\n table: model.table,\n on: index.on,\n unique: !!index.unique,\n })\n );\n }\n });\n\n dbIndexNames.forEach((dbIndexName) => {\n if (!modelIndexes.has(dbIndexName)) {\n ops.push(\n op.index.drop({\n name: dbIndexName,\n table: model.table,\n })\n );\n }\n });\n });\n\n Object.keys(db.tables).forEach((dbTableName) => {\n if (internalTables.has(dbTableName)) {\n return;\n }\n if (!modelTables.has(dbTableName)) {\n ops.push(op.table(dbTableName).drop());\n }\n });\n\n return ops;\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Builder } from '../builder/contracts/Builder';
|
|
2
|
+
import type { MigrationMode } from './MigrationMode';
|
|
3
|
+
export declare abstract class Migration {
|
|
4
|
+
static readonly BRAND: "tango.migration";
|
|
5
|
+
readonly __tangoBrand: typeof Migration.BRAND;
|
|
6
|
+
abstract id: string;
|
|
7
|
+
mode?: MigrationMode;
|
|
8
|
+
abstract up(m: Builder): void | Promise<void>;
|
|
9
|
+
abstract down(m: Builder): void | Promise<void>;
|
|
10
|
+
static isMigration(value: unknown): value is Migration;
|
|
11
|
+
static isMigrationConstructor(value: unknown): value is new () => Migration;
|
|
12
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import type { InternalOperationKind } from './internal/InternalOperationKind';
|
|
2
|
+
import type { ColumnSpec } from '../builder/contracts/ColumnSpec';
|
|
3
|
+
export type TableCreate = {
|
|
4
|
+
kind: InternalOperationKind.TABLE_CREATE;
|
|
5
|
+
table: string;
|
|
6
|
+
columns: ColumnSpec[];
|
|
7
|
+
};
|
|
8
|
+
export type TableDrop = {
|
|
9
|
+
kind: InternalOperationKind.TABLE_DROP;
|
|
10
|
+
table: string;
|
|
11
|
+
cascade?: boolean;
|
|
12
|
+
};
|
|
13
|
+
export type ColumnAdd = {
|
|
14
|
+
kind: InternalOperationKind.COLUMN_ADD;
|
|
15
|
+
table: string;
|
|
16
|
+
column: ColumnSpec;
|
|
17
|
+
};
|
|
18
|
+
export type ColumnDrop = {
|
|
19
|
+
kind: InternalOperationKind.COLUMN_DROP;
|
|
20
|
+
table: string;
|
|
21
|
+
column: string;
|
|
22
|
+
};
|
|
23
|
+
export type ColumnAlter = {
|
|
24
|
+
kind: InternalOperationKind.COLUMN_ALTER;
|
|
25
|
+
table: string;
|
|
26
|
+
column: string;
|
|
27
|
+
to: Partial<ColumnSpec>;
|
|
28
|
+
};
|
|
29
|
+
export type ColumnRename = {
|
|
30
|
+
kind: InternalOperationKind.COLUMN_RENAME;
|
|
31
|
+
table: string;
|
|
32
|
+
from: string;
|
|
33
|
+
to: string;
|
|
34
|
+
};
|
|
35
|
+
export type IndexCreate = {
|
|
36
|
+
kind: InternalOperationKind.INDEX_CREATE;
|
|
37
|
+
table: string;
|
|
38
|
+
name: string;
|
|
39
|
+
on: string[];
|
|
40
|
+
unique?: boolean;
|
|
41
|
+
where?: string;
|
|
42
|
+
concurrently?: boolean;
|
|
43
|
+
};
|
|
44
|
+
export type IndexDrop = {
|
|
45
|
+
kind: InternalOperationKind.INDEX_DROP;
|
|
46
|
+
table: string;
|
|
47
|
+
name: string;
|
|
48
|
+
concurrently?: boolean;
|
|
49
|
+
};
|
|
50
|
+
export type ForeignKeyCreate = {
|
|
51
|
+
kind: InternalOperationKind.FK_CREATE;
|
|
52
|
+
table: string;
|
|
53
|
+
name?: string;
|
|
54
|
+
columns: string[];
|
|
55
|
+
refTable: string;
|
|
56
|
+
refColumns: string[];
|
|
57
|
+
onDelete?: string;
|
|
58
|
+
onUpdate?: string;
|
|
59
|
+
notValid?: boolean;
|
|
60
|
+
};
|
|
61
|
+
export type ForeignKeyValidate = {
|
|
62
|
+
kind: InternalOperationKind.FK_VALIDATE;
|
|
63
|
+
table: string;
|
|
64
|
+
name: string;
|
|
65
|
+
};
|
|
66
|
+
export type ForeignKeyDrop = {
|
|
67
|
+
kind: InternalOperationKind.FK_DROP;
|
|
68
|
+
table: string;
|
|
69
|
+
name: string;
|
|
70
|
+
};
|
|
71
|
+
export type CustomMigrationOperation<TName extends string = string, TArgs extends object = Record<string, unknown>> = {
|
|
72
|
+
kind: 'custom';
|
|
73
|
+
name: TName;
|
|
74
|
+
args: TArgs;
|
|
75
|
+
};
|
|
76
|
+
export type MigrationOperation = TableCreate | TableDrop | ColumnAdd | ColumnDrop | ColumnAlter | ColumnRename | IndexCreate | IndexDrop | ForeignKeyCreate | ForeignKeyValidate | ForeignKeyDrop | CustomMigrationOperation;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|