@mikro-orm/migrations 7.1.0-dev.25 → 7.1.0-dev.27
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/MigrationRunner.d.ts +3 -0
- package/MigrationRunner.js +34 -2
- package/MigrationStorage.d.ts +3 -0
- package/MigrationStorage.js +33 -8
- package/Migrator.d.ts +3 -1
- package/Migrator.js +30 -12
- package/package.json +3 -3
package/MigrationRunner.d.ts
CHANGED
|
@@ -9,7 +9,10 @@ export declare class MigrationRunner {
|
|
|
9
9
|
protected readonly config: Configuration;
|
|
10
10
|
constructor(driver: AbstractSqlDriver, options: MigrationsOptions, config: Configuration);
|
|
11
11
|
run(migration: Migration, method: 'up' | 'down'): Promise<void>;
|
|
12
|
+
private resetSessionSchema;
|
|
12
13
|
setMasterMigration(trx: Transaction): void;
|
|
13
14
|
unsetMasterMigration(): void;
|
|
15
|
+
setRunSchema(schema?: string): void;
|
|
16
|
+
unsetRunSchema(): void;
|
|
14
17
|
private getQueries;
|
|
15
18
|
}
|
package/MigrationRunner.js
CHANGED
|
@@ -7,6 +7,7 @@ export class MigrationRunner {
|
|
|
7
7
|
#connection;
|
|
8
8
|
#helper;
|
|
9
9
|
#masterTransaction;
|
|
10
|
+
#runSchema;
|
|
10
11
|
constructor(driver, options, config) {
|
|
11
12
|
this.driver = driver;
|
|
12
13
|
this.options = options;
|
|
@@ -17,28 +18,59 @@ export class MigrationRunner {
|
|
|
17
18
|
async run(migration, method) {
|
|
18
19
|
migration.reset();
|
|
19
20
|
if (!this.options.transactional || !migration.isTransactional()) {
|
|
21
|
+
// Without a pinned transaction the set/reset statements may land on different pooled
|
|
22
|
+
// connections than the DDL, so refuse rather than silently running in the default schema.
|
|
23
|
+
if (this.#runSchema) {
|
|
24
|
+
throw new Error('Runtime schema (migrations.schema / migrator.up({ schema })) is only supported with transactional migrations');
|
|
25
|
+
}
|
|
20
26
|
const queries = await this.getQueries(migration, method);
|
|
21
27
|
await Utils.runSerial(queries, sql => this.driver.execute(sql));
|
|
22
28
|
}
|
|
23
29
|
else {
|
|
24
30
|
await this.#connection.transactional(async (tx) => {
|
|
25
31
|
migration.setTransactionContext(tx);
|
|
26
|
-
|
|
27
|
-
|
|
32
|
+
try {
|
|
33
|
+
const queries = await this.getQueries(migration, method);
|
|
34
|
+
await Utils.runSerial(queries, sql => this.driver.execute(sql, undefined, 'all', tx));
|
|
35
|
+
}
|
|
36
|
+
finally {
|
|
37
|
+
await this.resetSessionSchema(tx);
|
|
38
|
+
}
|
|
28
39
|
}, { ctx: this.#masterTransaction });
|
|
29
40
|
}
|
|
30
41
|
}
|
|
42
|
+
async resetSessionSchema(ctx) {
|
|
43
|
+
if (!this.#runSchema) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
const sql = this.#helper.getResetSchemaSQL(this.config.get('dbName'));
|
|
47
|
+
/* v8 ignore next 3 */
|
|
48
|
+
if (!sql) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
// best-effort — surfacing a reset failure would mask the real migration error
|
|
52
|
+
await this.driver.execute(sql, undefined, 'all', ctx).catch(() => void 0);
|
|
53
|
+
}
|
|
31
54
|
setMasterMigration(trx) {
|
|
32
55
|
this.#masterTransaction = trx;
|
|
33
56
|
}
|
|
34
57
|
unsetMasterMigration() {
|
|
35
58
|
this.#masterTransaction = undefined;
|
|
36
59
|
}
|
|
60
|
+
setRunSchema(schema) {
|
|
61
|
+
this.#runSchema = this.#helper.resolveMigrationSchema(schema);
|
|
62
|
+
}
|
|
63
|
+
unsetRunSchema() {
|
|
64
|
+
this.#runSchema = undefined;
|
|
65
|
+
}
|
|
37
66
|
async getQueries(migration, method) {
|
|
38
67
|
await migration[method]();
|
|
39
68
|
const charset = this.config.get('charset');
|
|
40
69
|
let queries = migration.getQueries();
|
|
41
70
|
queries.unshift(...this.#helper.getSchemaBeginning(charset, this.options.disableForeignKeys).split('\n'));
|
|
71
|
+
if (this.#runSchema) {
|
|
72
|
+
queries.unshift(this.#helper.getSetSchemaSQL(this.#runSchema));
|
|
73
|
+
}
|
|
42
74
|
queries.push(...this.#helper.getSchemaEnd(this.options.disableForeignKeys).split('\n'));
|
|
43
75
|
queries = queries.filter(sql => typeof sql !== 'string' || sql.trim().length > 0);
|
|
44
76
|
return queries;
|
package/MigrationStorage.d.ts
CHANGED
|
@@ -18,6 +18,8 @@ export declare class MigrationStorage {
|
|
|
18
18
|
ensureTable(): Promise<void>;
|
|
19
19
|
setMasterMigration(trx: Transaction): void;
|
|
20
20
|
unsetMasterMigration(): void;
|
|
21
|
+
setRunSchema(schema?: string): void;
|
|
22
|
+
unsetRunSchema(): void;
|
|
21
23
|
/**
|
|
22
24
|
* @internal
|
|
23
25
|
*/
|
|
@@ -30,4 +32,5 @@ export declare class MigrationStorage {
|
|
|
30
32
|
schemaName: string;
|
|
31
33
|
entity: EntitySchema;
|
|
32
34
|
};
|
|
35
|
+
private resolveTableName;
|
|
33
36
|
}
|
package/MigrationStorage.js
CHANGED
|
@@ -7,7 +7,9 @@ export class MigrationStorage {
|
|
|
7
7
|
#connection;
|
|
8
8
|
#helper;
|
|
9
9
|
#masterTransaction;
|
|
10
|
+
#runSchema;
|
|
10
11
|
#platform;
|
|
12
|
+
#ensuredSchemas = new Set();
|
|
11
13
|
constructor(driver, options) {
|
|
12
14
|
this.driver = driver;
|
|
13
15
|
this.options = options;
|
|
@@ -20,17 +22,20 @@ export class MigrationStorage {
|
|
|
20
22
|
return migrations.map(({ name }) => this.getMigrationName(name));
|
|
21
23
|
}
|
|
22
24
|
async logMigration(params) {
|
|
25
|
+
await this.ensureTable();
|
|
23
26
|
const { entity } = this.getTableName();
|
|
24
27
|
const name = this.getMigrationName(params.name);
|
|
25
28
|
await this.driver.nativeInsert(entity, { name }, { ctx: this.#masterTransaction });
|
|
26
29
|
}
|
|
27
30
|
async unlogMigration(params) {
|
|
31
|
+
await this.ensureTable();
|
|
28
32
|
const { entity } = this.getTableName();
|
|
29
33
|
const withoutExt = this.getMigrationName(params.name);
|
|
30
34
|
const names = [withoutExt, withoutExt + '.js', withoutExt + '.ts'];
|
|
31
35
|
await this.driver.nativeDelete(entity, { name: { $in: [params.name, ...names] } }, { ctx: this.#masterTransaction });
|
|
32
36
|
}
|
|
33
37
|
async getExecutedMigrations() {
|
|
38
|
+
await this.ensureTable();
|
|
34
39
|
const { entity, schemaName } = this.getTableName();
|
|
35
40
|
const res = await this.driver
|
|
36
41
|
.createQueryBuilder(entity, this.#masterTransaction)
|
|
@@ -45,15 +50,20 @@ export class MigrationStorage {
|
|
|
45
50
|
});
|
|
46
51
|
}
|
|
47
52
|
async ensureTable() {
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
|
|
53
|
+
const { tableName, schemaName } = this.resolveTableName();
|
|
54
|
+
// `\x00` can't appear in SQL identifiers — unambiguous pair encoding
|
|
55
|
+
const cacheKey = `${schemaName ?? ''}\x00${tableName}`;
|
|
56
|
+
if (this.#ensuredSchemas.has(cacheKey)) {
|
|
51
57
|
return;
|
|
52
58
|
}
|
|
53
|
-
|
|
59
|
+
if (await this.#helper.tableExists(this.#connection, tableName, schemaName, this.#masterTransaction)) {
|
|
60
|
+
this.#ensuredSchemas.add(cacheKey);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
const schemas = await this.#helper.getNamespaces(this.#connection, this.#masterTransaction);
|
|
54
64
|
if (schemaName && !schemas.includes(schemaName)) {
|
|
55
65
|
const sql = this.#helper.getCreateNamespaceSQL(schemaName);
|
|
56
|
-
await this.#connection.execute(sql);
|
|
66
|
+
await this.#connection.execute(sql, [], 'run', this.#masterTransaction);
|
|
57
67
|
}
|
|
58
68
|
const table = new DatabaseTable(this.#platform, tableName, schemaName);
|
|
59
69
|
table.addColumn({
|
|
@@ -78,6 +88,7 @@ export class MigrationStorage {
|
|
|
78
88
|
});
|
|
79
89
|
const sql = this.#helper.createTable(table);
|
|
80
90
|
await this.#connection.execute(sql.join(';\n'), [], 'run', this.#masterTransaction);
|
|
91
|
+
this.#ensuredSchemas.add(cacheKey);
|
|
81
92
|
}
|
|
82
93
|
setMasterMigration(trx) {
|
|
83
94
|
this.#masterTransaction = trx;
|
|
@@ -85,6 +96,12 @@ export class MigrationStorage {
|
|
|
85
96
|
unsetMasterMigration() {
|
|
86
97
|
this.#masterTransaction = undefined;
|
|
87
98
|
}
|
|
99
|
+
setRunSchema(schema) {
|
|
100
|
+
this.#runSchema = this.#helper.resolveMigrationSchema(schema);
|
|
101
|
+
}
|
|
102
|
+
unsetRunSchema() {
|
|
103
|
+
this.#runSchema = undefined;
|
|
104
|
+
}
|
|
88
105
|
/**
|
|
89
106
|
* @internal
|
|
90
107
|
*/
|
|
@@ -95,9 +112,7 @@ export class MigrationStorage {
|
|
|
95
112
|
* @internal
|
|
96
113
|
*/
|
|
97
114
|
getTableName() {
|
|
98
|
-
const
|
|
99
|
-
const tableName = parts.length > 1 ? parts[1] : parts[0];
|
|
100
|
-
const schemaName = parts.length > 1 ? parts[0] : this.driver.config.get('schema', this.driver.getPlatform().getDefaultSchemaName());
|
|
115
|
+
const { tableName, schemaName } = this.resolveTableName();
|
|
101
116
|
const entity = defineEntity({
|
|
102
117
|
name: 'Migration',
|
|
103
118
|
tableName,
|
|
@@ -111,4 +126,14 @@ export class MigrationStorage {
|
|
|
111
126
|
entity.meta.sync();
|
|
112
127
|
return { tableName, schemaName, entity };
|
|
113
128
|
}
|
|
129
|
+
resolveTableName() {
|
|
130
|
+
const parts = this.options.tableName.split('.');
|
|
131
|
+
const tableName = parts.length > 1 ? parts[1] : parts[0];
|
|
132
|
+
const schemaName = this.#runSchema ??
|
|
133
|
+
this.options.schema ??
|
|
134
|
+
(parts.length > 1
|
|
135
|
+
? parts[0]
|
|
136
|
+
: this.driver.config.get('schema', this.driver.getPlatform().getDefaultSchemaName()));
|
|
137
|
+
return { tableName, schemaName };
|
|
138
|
+
}
|
|
114
139
|
}
|
package/Migrator.d.ts
CHANGED
|
@@ -17,7 +17,9 @@ export declare class Migrator extends AbstractMigrator<AbstractSqlDriver> {
|
|
|
17
17
|
* @inheritDoc
|
|
18
18
|
*/
|
|
19
19
|
create(path?: string, blank?: boolean, initial?: boolean, name?: string): Promise<MigrationResult>;
|
|
20
|
-
getPending(
|
|
20
|
+
getPending(options?: {
|
|
21
|
+
schema?: string;
|
|
22
|
+
}): Promise<MigrationInfo[]>;
|
|
21
23
|
private hasSnapshot;
|
|
22
24
|
checkSchema(): Promise<boolean>;
|
|
23
25
|
/**
|
package/Migrator.js
CHANGED
|
@@ -51,7 +51,14 @@ export class Migrator extends AbstractMigrator {
|
|
|
51
51
|
if (created) {
|
|
52
52
|
this.initServices();
|
|
53
53
|
}
|
|
54
|
-
|
|
54
|
+
// Defer tracking-table creation when wildcard-schema fan-out is enabled — pre-creating
|
|
55
|
+
// here would land in the default schema and leave a stray `mikro_orm_migrations` after
|
|
56
|
+
// `migrator.up({ schema })` against a virgin DB. For the standard flow, eager creation
|
|
57
|
+
// keeps the per-call query log clean (no `tableExists`/`getNamespaces`/`create` probe
|
|
58
|
+
// on first storage access).
|
|
59
|
+
if (!this.options.includeWildcardSchema) {
|
|
60
|
+
await this.storage.ensureTable();
|
|
61
|
+
}
|
|
55
62
|
}
|
|
56
63
|
/**
|
|
57
64
|
* @inheritDoc
|
|
@@ -74,23 +81,30 @@ export class Migrator extends AbstractMigrator {
|
|
|
74
81
|
diff,
|
|
75
82
|
};
|
|
76
83
|
}
|
|
77
|
-
async getPending() {
|
|
84
|
+
async getPending(options) {
|
|
78
85
|
if (!(await this.hasSnapshot())) {
|
|
79
|
-
return super.getPending();
|
|
86
|
+
return super.getPending(options);
|
|
80
87
|
}
|
|
81
88
|
await this.initPaths();
|
|
82
89
|
const all = await this.discoverMigrations();
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
// from `storage.executed()` propagate so real bugs are not swallowed
|
|
90
|
+
const schema = options?.schema ?? this.options.schema;
|
|
91
|
+
this.storage.setRunSchema?.(schema);
|
|
86
92
|
try {
|
|
87
|
-
|
|
93
|
+
// probe the DB via `ensureTable` — if it fails, the DB is unreachable and
|
|
94
|
+
// we treat every discovered migration as pending; otherwise let errors
|
|
95
|
+
// from `storage.executed()` propagate so real bugs are not swallowed
|
|
96
|
+
try {
|
|
97
|
+
await this.storage.ensureTable();
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
return all.map(m => ({ name: m.name, path: m.path }));
|
|
101
|
+
}
|
|
102
|
+
const executed = new Set(await this.storage.executed());
|
|
103
|
+
return all.filter(m => !executed.has(m.name)).map(m => ({ name: m.name, path: m.path }));
|
|
88
104
|
}
|
|
89
|
-
|
|
90
|
-
|
|
105
|
+
finally {
|
|
106
|
+
this.storage.unsetRunSchema?.();
|
|
91
107
|
}
|
|
92
|
-
const executed = new Set(await this.storage.executed());
|
|
93
|
-
return all.filter(m => !executed.has(m.name)).map(m => ({ name: m.name, path: m.path }));
|
|
94
108
|
}
|
|
95
109
|
async hasSnapshot() {
|
|
96
110
|
if (!this.options.snapshot) {
|
|
@@ -274,7 +288,10 @@ export class Migrator extends AbstractMigrator {
|
|
|
274
288
|
down.push('select 1');
|
|
275
289
|
}
|
|
276
290
|
else if (initial) {
|
|
277
|
-
const dump = await this.#schemaGenerator.getCreateSchemaSQL({
|
|
291
|
+
const dump = await this.#schemaGenerator.getCreateSchemaSQL({
|
|
292
|
+
wrap: false,
|
|
293
|
+
includeWildcardSchema: this.options.includeWildcardSchema,
|
|
294
|
+
});
|
|
278
295
|
up.push(...splitStatements(dump));
|
|
279
296
|
}
|
|
280
297
|
else {
|
|
@@ -283,6 +300,7 @@ export class Migrator extends AbstractMigrator {
|
|
|
283
300
|
safe: this.options.safe,
|
|
284
301
|
dropTables: this.options.dropTables,
|
|
285
302
|
fromSchema: await this.getSchemaFromSnapshot(),
|
|
303
|
+
includeWildcardSchema: this.options.includeWildcardSchema,
|
|
286
304
|
});
|
|
287
305
|
up.push(...splitStatements(diff.up));
|
|
288
306
|
down.push(...splitStatements(diff.down));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mikro-orm/migrations",
|
|
3
|
-
"version": "7.1.0-dev.
|
|
3
|
+
"version": "7.1.0-dev.27",
|
|
4
4
|
"description": "TypeScript ORM for Node.js based on Data Mapper, Unit of Work and Identity Map patterns. Supports MongoDB, MySQL, PostgreSQL and SQLite databases as well as usage with vanilla JavaScript.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"data-mapper",
|
|
@@ -47,13 +47,13 @@
|
|
|
47
47
|
"copy": "node ../../scripts/copy.mjs"
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@mikro-orm/sql": "7.1.0-dev.
|
|
50
|
+
"@mikro-orm/sql": "7.1.0-dev.27"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
53
|
"@mikro-orm/core": "^7.0.13"
|
|
54
54
|
},
|
|
55
55
|
"peerDependencies": {
|
|
56
|
-
"@mikro-orm/core": "7.1.0-dev.
|
|
56
|
+
"@mikro-orm/core": "7.1.0-dev.27"
|
|
57
57
|
},
|
|
58
58
|
"engines": {
|
|
59
59
|
"node": ">= 22.17.0"
|