@mikro-orm/migrations 7.0.0-rc.1 → 7.0.0-rc.3
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/JSMigrationGenerator.js +2 -2
- package/MigrationGenerator.js +3 -4
- package/MigrationStorage.d.ts +7 -4
- package/MigrationStorage.js +4 -9
- package/Migrator.d.ts +15 -61
- package/Migrator.js +71 -218
- package/TSMigrationGenerator.js +2 -2
- package/package.json +31 -32
- package/tsconfig.build.tsbuildinfo +1 -1
- package/typings.d.ts +1 -1
package/JSMigrationGenerator.js
CHANGED
|
@@ -9,12 +9,12 @@ export class JSMigrationGenerator extends MigrationGenerator {
|
|
|
9
9
|
ret += `const { Migration } = require('@mikro-orm/migrations');\n\n`;
|
|
10
10
|
ret += `class ${className} extends Migration {\n\n`;
|
|
11
11
|
ret += ` async up() {\n`;
|
|
12
|
-
diff.up.forEach(sql => ret += this.createStatement(sql, 4));
|
|
12
|
+
diff.up.forEach(sql => (ret += this.createStatement(sql, 4)));
|
|
13
13
|
ret += ` }\n\n`;
|
|
14
14
|
/* v8 ignore next */
|
|
15
15
|
if (diff.down.length > 0) {
|
|
16
16
|
ret += ` async down() {\n`;
|
|
17
|
-
diff.down.forEach(sql => ret += this.createStatement(sql, 4));
|
|
17
|
+
diff.down.forEach(sql => (ret += this.createStatement(sql, 4)));
|
|
18
18
|
ret += ` }\n\n`;
|
|
19
19
|
}
|
|
20
20
|
ret += `}\n`;
|
package/MigrationGenerator.js
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { fs } from '@mikro-orm/core/fs-utils';
|
|
2
|
-
import { writeFile } from 'node:fs/promises';
|
|
3
1
|
export class MigrationGenerator {
|
|
4
2
|
driver;
|
|
5
3
|
namingStrategy;
|
|
@@ -13,15 +11,16 @@ export class MigrationGenerator {
|
|
|
13
11
|
* @inheritDoc
|
|
14
12
|
*/
|
|
15
13
|
async generate(diff, path, name) {
|
|
14
|
+
const { fs } = await import('@mikro-orm/core/fs-utils');
|
|
16
15
|
/* v8 ignore next */
|
|
17
16
|
const defaultPath = this.options.emit === 'ts' && this.options.pathTs ? this.options.pathTs : this.options.path;
|
|
18
17
|
path = fs.normalizePath(this.driver.config.get('baseDir'), path ?? defaultPath);
|
|
19
18
|
fs.ensureDir(path);
|
|
20
|
-
const timestamp = new Date().toISOString().replace(/[-T:]|\.\d{3}z$/
|
|
19
|
+
const timestamp = new Date().toISOString().replace(/[-T:]|\.\d{3}z$/gi, '');
|
|
21
20
|
const className = this.namingStrategy.classToMigrationName(timestamp, name);
|
|
22
21
|
const fileName = `${this.options.fileName(timestamp, name)}.${this.options.emit}`;
|
|
23
22
|
const ret = await this.generateMigrationFile(className, diff);
|
|
24
|
-
await writeFile(path + '/' + fileName, ret, { flush: true });
|
|
23
|
+
await fs.writeFile(path + '/' + fileName, ret, { flush: true });
|
|
25
24
|
return [ret, fileName];
|
|
26
25
|
}
|
|
27
26
|
/**
|
package/MigrationStorage.d.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { type MigrationsOptions, type Transaction, type EntitySchema } from '@mikro-orm/core';
|
|
2
2
|
import { type AbstractSqlDriver } from '@mikro-orm/sql';
|
|
3
|
-
import type { MigrationParams, UmzugStorage } from 'umzug';
|
|
4
3
|
import type { MigrationRow } from './typings.js';
|
|
5
|
-
export declare class MigrationStorage
|
|
4
|
+
export declare class MigrationStorage {
|
|
6
5
|
protected readonly driver: AbstractSqlDriver;
|
|
7
6
|
protected readonly options: MigrationsOptions;
|
|
8
7
|
private readonly connection;
|
|
@@ -11,8 +10,12 @@ export declare class MigrationStorage implements UmzugStorage {
|
|
|
11
10
|
private readonly platform;
|
|
12
11
|
constructor(driver: AbstractSqlDriver, options: MigrationsOptions);
|
|
13
12
|
executed(): Promise<string[]>;
|
|
14
|
-
logMigration(params:
|
|
15
|
-
|
|
13
|
+
logMigration(params: {
|
|
14
|
+
name: string;
|
|
15
|
+
}): Promise<void>;
|
|
16
|
+
unlogMigration(params: {
|
|
17
|
+
name: string;
|
|
18
|
+
}): Promise<void>;
|
|
16
19
|
getExecutedMigrations(): Promise<MigrationRow[]>;
|
|
17
20
|
ensureTable(): Promise<void>;
|
|
18
21
|
setMasterMigration(trx: Transaction): void;
|
package/MigrationStorage.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { defineEntity, p } from '@mikro-orm/core';
|
|
2
2
|
import { DatabaseTable, } from '@mikro-orm/sql';
|
|
3
|
-
import { parse } from 'node:path';
|
|
4
3
|
export class MigrationStorage {
|
|
5
4
|
driver;
|
|
6
5
|
options;
|
|
@@ -32,12 +31,13 @@ export class MigrationStorage {
|
|
|
32
31
|
}
|
|
33
32
|
async getExecutedMigrations() {
|
|
34
33
|
const { entity, schemaName } = this.getTableName();
|
|
35
|
-
const res = await this.driver
|
|
34
|
+
const res = await this.driver
|
|
35
|
+
.createQueryBuilder(entity, this.masterTransaction)
|
|
36
36
|
.withSchema(schemaName)
|
|
37
37
|
.orderBy({ id: 'asc' })
|
|
38
38
|
.execute('all', false);
|
|
39
39
|
return res.map(row => {
|
|
40
|
-
if (typeof row.executed_at === 'string') {
|
|
40
|
+
if (typeof row.executed_at === 'string' || typeof row.executed_at === 'number') {
|
|
41
41
|
row.executed_at = new Date(row.executed_at);
|
|
42
42
|
}
|
|
43
43
|
return row;
|
|
@@ -88,12 +88,7 @@ export class MigrationStorage {
|
|
|
88
88
|
* @internal
|
|
89
89
|
*/
|
|
90
90
|
getMigrationName(name) {
|
|
91
|
-
|
|
92
|
-
if (['.js', '.ts'].includes(parsedName.ext)) {
|
|
93
|
-
// strip extension
|
|
94
|
-
return parsedName.name;
|
|
95
|
-
}
|
|
96
|
-
return name;
|
|
91
|
+
return name.replace(/\.[jt]s$/, '');
|
|
97
92
|
}
|
|
98
93
|
/**
|
|
99
94
|
* @internal
|
package/Migrator.d.ts
CHANGED
|
@@ -1,32 +1,18 @@
|
|
|
1
|
-
import { type
|
|
2
|
-
import {
|
|
3
|
-
import { DatabaseSchema, type EntityManager } from '@mikro-orm/sql';
|
|
4
|
-
import type { Migration } from './Migration.js';
|
|
1
|
+
import { type IMigrationGenerator, type IMigrationRunner, type IMigratorStorage, type MigrateOptions, type MigrationInfo, type MikroORM } from '@mikro-orm/core';
|
|
2
|
+
import { AbstractMigrator } from '@mikro-orm/core/migrations';
|
|
3
|
+
import { type AbstractSqlDriver, DatabaseSchema, type EntityManager } from '@mikro-orm/sql';
|
|
5
4
|
import { MigrationStorage } from './MigrationStorage.js';
|
|
6
|
-
import type {
|
|
7
|
-
export declare class Migrator
|
|
8
|
-
private readonly em;
|
|
9
|
-
private umzug;
|
|
10
|
-
private runner;
|
|
11
|
-
private storage;
|
|
12
|
-
private generator;
|
|
13
|
-
private readonly driver;
|
|
5
|
+
import type { MigrationResult } from './typings.js';
|
|
6
|
+
export declare class Migrator extends AbstractMigrator<AbstractSqlDriver> {
|
|
14
7
|
private readonly schemaGenerator;
|
|
15
|
-
private
|
|
16
|
-
private readonly options;
|
|
17
|
-
private readonly absolutePath;
|
|
18
|
-
private readonly snapshotPath;
|
|
8
|
+
private snapshotPath?;
|
|
19
9
|
constructor(em: EntityManager);
|
|
20
|
-
/**
|
|
21
|
-
* Checks if `src` folder exists, it so, tries to adjust the migrations and seeders paths automatically to use it.
|
|
22
|
-
* If there is a `dist` or `build` folder, it will be used for the JS variant (`path` option), while the `src` folder will be
|
|
23
|
-
* used for the TS variant (`pathTs` option).
|
|
24
|
-
*
|
|
25
|
-
* If the default folder exists (e.g. `/migrations`), the config will respect that, so this auto-detection should not
|
|
26
|
-
* break existing projects, only help with the new ones.
|
|
27
|
-
*/
|
|
28
|
-
private detectSourceFolder;
|
|
29
10
|
static register(orm: MikroORM): void;
|
|
11
|
+
protected createRunner(): IMigrationRunner;
|
|
12
|
+
protected createStorage(): IMigratorStorage;
|
|
13
|
+
protected getDefaultGenerator(): IMigrationGenerator;
|
|
14
|
+
private getSnapshotPath;
|
|
15
|
+
protected init(): Promise<void>;
|
|
30
16
|
/**
|
|
31
17
|
* @inheritDoc
|
|
32
18
|
*/
|
|
@@ -36,15 +22,8 @@ export declare class Migrator implements IMigrator {
|
|
|
36
22
|
* @inheritDoc
|
|
37
23
|
*/
|
|
38
24
|
createInitial(path?: string, name?: string, blank?: boolean): Promise<MigrationResult>;
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
*/
|
|
42
|
-
on(eventName: MigratorEvent, listener: (event: UmzugMigration) => MaybePromise<void>): this;
|
|
43
|
-
/**
|
|
44
|
-
* @inheritDoc
|
|
45
|
-
*/
|
|
46
|
-
off(eventName: MigratorEvent, listener: (event: UmzugMigration) => MaybePromise<void>): this;
|
|
47
|
-
private createUmzug;
|
|
25
|
+
protected runMigrations(method: 'up' | 'down', options?: string | string[] | MigrateOptions): Promise<MigrationInfo[]>;
|
|
26
|
+
getStorage(): MigrationStorage;
|
|
48
27
|
/**
|
|
49
28
|
* Initial migration can be created only if:
|
|
50
29
|
* 1. no previous migrations were generated or executed
|
|
@@ -54,32 +33,7 @@ export declare class Migrator implements IMigrator {
|
|
|
54
33
|
* If only some of the tables are present, exception is thrown.
|
|
55
34
|
*/
|
|
56
35
|
private validateInitialMigration;
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
*/
|
|
60
|
-
getExecuted(): Promise<MigrationRow[]>;
|
|
61
|
-
private ensureDatabase;
|
|
62
|
-
/**
|
|
63
|
-
* @inheritDoc
|
|
64
|
-
*/
|
|
65
|
-
getPending(): Promise<UmzugMigration[]>;
|
|
66
|
-
/**
|
|
67
|
-
* @inheritDoc
|
|
68
|
-
*/
|
|
69
|
-
up(options?: string | string[] | MigrateOptions): Promise<UmzugMigration[]>;
|
|
70
|
-
/**
|
|
71
|
-
* @inheritDoc
|
|
72
|
-
*/
|
|
73
|
-
down(options?: string | string[] | MigrateOptions): Promise<UmzugMigration[]>;
|
|
74
|
-
getStorage(): MigrationStorage;
|
|
75
|
-
protected resolve(params: MigrationParams<any>): RunnableMigration<any>;
|
|
76
|
-
protected getSchemaFromSnapshot(): DatabaseSchema | undefined;
|
|
77
|
-
protected storeCurrentSchema(): Promise<void>;
|
|
78
|
-
protected initialize(MigrationClass: Constructor<Migration>, name: string): RunnableMigration<any>;
|
|
36
|
+
protected getSchemaFromSnapshot(): Promise<DatabaseSchema | undefined>;
|
|
37
|
+
protected storeCurrentSchema(schema?: DatabaseSchema): Promise<void>;
|
|
79
38
|
private getSchemaDiff;
|
|
80
|
-
private getMigrationFilename;
|
|
81
|
-
private prefix;
|
|
82
|
-
private runMigrations;
|
|
83
|
-
private runInTransaction;
|
|
84
|
-
private ensureMigrationsDirExists;
|
|
85
39
|
}
|
package/Migrator.js
CHANGED
|
@@ -1,82 +1,65 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { existsSync, writeFileSync } from 'node:fs';
|
|
4
|
-
import { t, Type, UnknownType, Utils, } from '@mikro-orm/core';
|
|
5
|
-
import { fs } from '@mikro-orm/core/fs-utils';
|
|
1
|
+
import { t, Type, UnknownType, } from '@mikro-orm/core';
|
|
2
|
+
import { AbstractMigrator } from '@mikro-orm/core/migrations';
|
|
6
3
|
import { DatabaseSchema, DatabaseTable, } from '@mikro-orm/sql';
|
|
7
4
|
import { MigrationRunner } from './MigrationRunner.js';
|
|
8
5
|
import { MigrationStorage } from './MigrationStorage.js';
|
|
9
6
|
import { TSMigrationGenerator } from './TSMigrationGenerator.js';
|
|
10
7
|
import { JSMigrationGenerator } from './JSMigrationGenerator.js';
|
|
11
|
-
export class Migrator {
|
|
12
|
-
em;
|
|
13
|
-
umzug;
|
|
14
|
-
runner;
|
|
15
|
-
storage;
|
|
16
|
-
generator;
|
|
17
|
-
driver;
|
|
8
|
+
export class Migrator extends AbstractMigrator {
|
|
18
9
|
schemaGenerator;
|
|
19
|
-
config;
|
|
20
|
-
options;
|
|
21
|
-
absolutePath;
|
|
22
10
|
snapshotPath;
|
|
23
11
|
constructor(em) {
|
|
24
|
-
|
|
25
|
-
this.driver = this.em.getDriver();
|
|
26
|
-
this.config = this.em.config;
|
|
27
|
-
this.options = this.config.get('migrations');
|
|
12
|
+
super(em);
|
|
28
13
|
this.schemaGenerator = this.config.getExtension('@mikro-orm/schema-generator');
|
|
29
|
-
this.detectSourceFolder();
|
|
30
|
-
/* v8 ignore next */
|
|
31
|
-
const key = (this.config.get('preferTs', Utils.detectTypeScriptSupport()) && this.options.pathTs) ? 'pathTs' : 'path';
|
|
32
|
-
this.absolutePath = fs.absolutePath(this.options[key], this.config.get('baseDir'));
|
|
33
|
-
// for snapshots, we always want to use the path based on `emit` option, regardless of whether we run in TS context
|
|
34
|
-
/* v8 ignore next */
|
|
35
|
-
const snapshotPath = this.options.emit === 'ts' && this.options.pathTs ? this.options.pathTs : this.options.path;
|
|
36
|
-
const absoluteSnapshotPath = fs.absolutePath(snapshotPath, this.config.get('baseDir'));
|
|
37
|
-
const dbName = basename(this.config.get('dbName'));
|
|
38
|
-
const snapshotName = this.options.snapshotName ?? `.snapshot-${dbName}`;
|
|
39
|
-
this.snapshotPath = fs.normalizePath(absoluteSnapshotPath, `${snapshotName}.json`);
|
|
40
|
-
this.createUmzug();
|
|
41
14
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
15
|
+
static register(orm) {
|
|
16
|
+
orm.config.registerExtension('@mikro-orm/migrator', () => new Migrator(orm.em));
|
|
17
|
+
}
|
|
18
|
+
createRunner() {
|
|
19
|
+
return new MigrationRunner(this.driver, this.options, this.config);
|
|
20
|
+
}
|
|
21
|
+
createStorage() {
|
|
22
|
+
return new MigrationStorage(this.driver, this.options);
|
|
23
|
+
}
|
|
24
|
+
getDefaultGenerator() {
|
|
25
|
+
if (this.options.emit === 'js' || this.options.emit === 'cjs') {
|
|
26
|
+
return new JSMigrationGenerator(this.driver, this.config.getNamingStrategy(), this.options);
|
|
27
|
+
}
|
|
28
|
+
return new TSMigrationGenerator(this.driver, this.config.getNamingStrategy(), this.options);
|
|
29
|
+
}
|
|
30
|
+
async getSnapshotPath() {
|
|
31
|
+
if (!this.snapshotPath) {
|
|
32
|
+
const { fs } = await import('@mikro-orm/core/fs-utils');
|
|
33
|
+
// for snapshots, we always want to use the path based on `emit` option, regardless of whether we run in TS context
|
|
34
|
+
/* v8 ignore next */
|
|
35
|
+
const snapshotPath = this.options.emit === 'ts' && this.options.pathTs ? this.options.pathTs : this.options.path;
|
|
36
|
+
const absoluteSnapshotPath = fs.absolutePath(snapshotPath, this.config.get('baseDir'));
|
|
37
|
+
const dbName = this.config.get('dbName').replace(/\\/g, '/').split('/').pop().replace(/:/g, '');
|
|
38
|
+
const snapshotName = this.options.snapshotName ?? `.snapshot-${dbName}`;
|
|
39
|
+
this.snapshotPath = fs.normalizePath(absoluteSnapshotPath, `${snapshotName}.json`);
|
|
40
|
+
}
|
|
41
|
+
return this.snapshotPath;
|
|
42
|
+
}
|
|
43
|
+
async init() {
|
|
44
|
+
if (this.initialized) {
|
|
55
45
|
return;
|
|
56
46
|
}
|
|
57
|
-
|
|
58
|
-
const
|
|
59
|
-
const buildDir = fs.pathExists(baseDir + '/build');
|
|
60
|
-
// if neither `dist` nor `build` exist, we use the `src` folder as it might be a JS project without building, but with `src` folder
|
|
47
|
+
await super.init();
|
|
48
|
+
const created = await this.schemaGenerator.ensureDatabase();
|
|
61
49
|
/* v8 ignore next */
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
if (!this.options.path && !this.options.pathTs && !exists) {
|
|
65
|
-
this.options.path = `${path}/migrations`;
|
|
66
|
-
this.options.pathTs = './src/migrations';
|
|
50
|
+
if (created) {
|
|
51
|
+
this.initServices();
|
|
67
52
|
}
|
|
68
|
-
|
|
69
|
-
static register(orm) {
|
|
70
|
-
orm.config.registerExtension('@mikro-orm/migrator', () => new Migrator(orm.em));
|
|
53
|
+
await this.storage.ensureTable();
|
|
71
54
|
}
|
|
72
55
|
/**
|
|
73
56
|
* @inheritDoc
|
|
74
57
|
*/
|
|
75
58
|
async create(path, blank = false, initial = false, name) {
|
|
59
|
+
await this.init();
|
|
76
60
|
if (initial) {
|
|
77
61
|
return this.createInitial(path, name, blank);
|
|
78
62
|
}
|
|
79
|
-
this.ensureMigrationsDirExists();
|
|
80
63
|
const diff = await this.getSchemaDiff(blank, initial);
|
|
81
64
|
if (diff.up.length === 0) {
|
|
82
65
|
return { fileName: '', code: '', diff };
|
|
@@ -90,7 +73,7 @@ export class Migrator {
|
|
|
90
73
|
};
|
|
91
74
|
}
|
|
92
75
|
async checkSchema() {
|
|
93
|
-
this.
|
|
76
|
+
await this.init();
|
|
94
77
|
const diff = await this.getSchemaDiff(false, false);
|
|
95
78
|
return diff.up.length > 0;
|
|
96
79
|
}
|
|
@@ -98,13 +81,13 @@ export class Migrator {
|
|
|
98
81
|
* @inheritDoc
|
|
99
82
|
*/
|
|
100
83
|
async createInitial(path, name, blank = false) {
|
|
101
|
-
this.
|
|
84
|
+
await this.init();
|
|
102
85
|
const schemaExists = await this.validateInitialMigration(blank);
|
|
103
86
|
const diff = await this.getSchemaDiff(blank, true);
|
|
104
87
|
const migration = await this.generator.generate(diff, path, name);
|
|
105
88
|
await this.storeCurrentSchema();
|
|
106
89
|
if (schemaExists && !blank) {
|
|
107
|
-
await this.storage.logMigration({ name: migration[1]
|
|
90
|
+
await this.storage.logMigration({ name: migration[1] });
|
|
108
91
|
}
|
|
109
92
|
return {
|
|
110
93
|
fileName: migration[1],
|
|
@@ -112,57 +95,21 @@ export class Migrator {
|
|
|
112
95
|
diff,
|
|
113
96
|
};
|
|
114
97
|
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
off(eventName, listener) {
|
|
126
|
-
this.umzug.off(eventName, listener);
|
|
127
|
-
return this;
|
|
128
|
-
}
|
|
129
|
-
createUmzug() {
|
|
130
|
-
this.runner = new MigrationRunner(this.driver, this.options, this.config);
|
|
131
|
-
this.storage = new MigrationStorage(this.driver, this.options);
|
|
132
|
-
let migrations = {
|
|
133
|
-
glob: join(this.absolutePath, this.options.glob).replace(/\\/g, '/'),
|
|
134
|
-
resolve: (params) => this.resolve(params),
|
|
135
|
-
};
|
|
136
|
-
if (this.options.migrationsList) {
|
|
137
|
-
migrations = this.options.migrationsList.map(migration => {
|
|
138
|
-
if (typeof migration === 'function') {
|
|
139
|
-
return this.initialize(migration, migration.name);
|
|
140
|
-
}
|
|
141
|
-
return this.initialize(migration.class, migration.name);
|
|
142
|
-
});
|
|
143
|
-
}
|
|
144
|
-
this.umzug = new Umzug({
|
|
145
|
-
storage: this.storage,
|
|
146
|
-
logger: undefined,
|
|
147
|
-
migrations,
|
|
148
|
-
});
|
|
149
|
-
/* v8 ignore else */
|
|
150
|
-
if (!this.options.silent) {
|
|
151
|
-
const logger = this.config.getLogger();
|
|
152
|
-
this.umzug.on('migrating', event => logger.log('migrator', `Processing '${event.name}'`, { enabled: true }));
|
|
153
|
-
this.umzug.on('migrated', event => logger.log('migrator', `Applied '${event.name}'`, { enabled: true }));
|
|
154
|
-
this.umzug.on('reverting', event => logger.log('migrator', `Processing '${event.name}'`, { enabled: true }));
|
|
155
|
-
this.umzug.on('reverted', event => logger.log('migrator', `Reverted '${event.name}'`, { enabled: true }));
|
|
156
|
-
}
|
|
157
|
-
if (this.options.generator) {
|
|
158
|
-
this.generator = new this.options.generator(this.driver, this.config.getNamingStrategy(), this.options);
|
|
159
|
-
}
|
|
160
|
-
else if (this.options.emit === 'js' || this.options.emit === 'cjs') {
|
|
161
|
-
this.generator = new JSMigrationGenerator(this.driver, this.config.getNamingStrategy(), this.options);
|
|
162
|
-
}
|
|
163
|
-
else {
|
|
164
|
-
this.generator = new TSMigrationGenerator(this.driver, this.config.getNamingStrategy(), this.options);
|
|
98
|
+
async runMigrations(method, options) {
|
|
99
|
+
const result = await super.runMigrations(method, options);
|
|
100
|
+
if (result.length > 0 && this.options.snapshot) {
|
|
101
|
+
const schema = await DatabaseSchema.create(this.em.getConnection(), this.em.getPlatform(), this.config);
|
|
102
|
+
try {
|
|
103
|
+
await this.storeCurrentSchema(schema);
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
// Silently ignore for read-only filesystems (production).
|
|
107
|
+
}
|
|
165
108
|
}
|
|
109
|
+
return result;
|
|
110
|
+
}
|
|
111
|
+
getStorage() {
|
|
112
|
+
return this.storage;
|
|
166
113
|
}
|
|
167
114
|
/**
|
|
168
115
|
* Initial migration can be created only if:
|
|
@@ -202,62 +149,16 @@ export class Migrator {
|
|
|
202
149
|
}
|
|
203
150
|
return expected.size === exists.size;
|
|
204
151
|
}
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
async getExecuted() {
|
|
209
|
-
await this.ensureDatabase();
|
|
210
|
-
return this.storage.getExecutedMigrations();
|
|
211
|
-
}
|
|
212
|
-
async ensureDatabase() {
|
|
213
|
-
this.ensureMigrationsDirExists();
|
|
214
|
-
const created = await this.schemaGenerator.ensureDatabase();
|
|
215
|
-
/* v8 ignore next */
|
|
216
|
-
if (created) {
|
|
217
|
-
this.createUmzug();
|
|
152
|
+
async getSchemaFromSnapshot() {
|
|
153
|
+
if (!this.options.snapshot) {
|
|
154
|
+
return undefined;
|
|
218
155
|
}
|
|
219
|
-
await this.
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
* @inheritDoc
|
|
223
|
-
*/
|
|
224
|
-
async getPending() {
|
|
225
|
-
await this.ensureDatabase();
|
|
226
|
-
return this.umzug.pending();
|
|
227
|
-
}
|
|
228
|
-
/**
|
|
229
|
-
* @inheritDoc
|
|
230
|
-
*/
|
|
231
|
-
async up(options) {
|
|
232
|
-
return this.runMigrations('up', options);
|
|
233
|
-
}
|
|
234
|
-
/**
|
|
235
|
-
* @inheritDoc
|
|
236
|
-
*/
|
|
237
|
-
async down(options) {
|
|
238
|
-
return this.runMigrations('down', options);
|
|
239
|
-
}
|
|
240
|
-
getStorage() {
|
|
241
|
-
return this.storage;
|
|
242
|
-
}
|
|
243
|
-
resolve(params) {
|
|
244
|
-
const createMigrationHandler = async (method) => {
|
|
245
|
-
const migration = await fs.dynamicImport(params.path);
|
|
246
|
-
const MigrationClass = Object.values(migration).find(cls => typeof cls === 'function' && typeof cls.constructor === 'function');
|
|
247
|
-
const instance = new MigrationClass(this.driver, this.config);
|
|
248
|
-
await this.runner.run(instance, method);
|
|
249
|
-
};
|
|
250
|
-
return {
|
|
251
|
-
name: this.storage.getMigrationName(params.name),
|
|
252
|
-
up: () => createMigrationHandler('up'),
|
|
253
|
-
down: () => createMigrationHandler('down'),
|
|
254
|
-
};
|
|
255
|
-
}
|
|
256
|
-
getSchemaFromSnapshot() {
|
|
257
|
-
if (!this.options.snapshot || !existsSync(this.snapshotPath)) {
|
|
156
|
+
const snapshotPath = await this.getSnapshotPath();
|
|
157
|
+
const { fs } = await import('@mikro-orm/core/fs-utils');
|
|
158
|
+
if (!fs.pathExists(snapshotPath)) {
|
|
258
159
|
return undefined;
|
|
259
160
|
}
|
|
260
|
-
const data = fs.readJSONSync(
|
|
161
|
+
const data = fs.readJSONSync(snapshotPath);
|
|
261
162
|
const schema = new DatabaseSchema(this.driver.getPlatform(), this.config.get('schema'));
|
|
262
163
|
const { tables, namespaces, ...rest } = data;
|
|
263
164
|
const tableInstances = tables.map((tbl) => {
|
|
@@ -275,20 +176,14 @@ export class Migrator {
|
|
|
275
176
|
Object.assign(schema, { tables: tableInstances, namespaces: new Set(namespaces), ...rest });
|
|
276
177
|
return schema;
|
|
277
178
|
}
|
|
278
|
-
async storeCurrentSchema() {
|
|
179
|
+
async storeCurrentSchema(schema) {
|
|
279
180
|
if (!this.options.snapshot) {
|
|
280
181
|
return;
|
|
281
182
|
}
|
|
282
|
-
const
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
const instance = new MigrationClass(this.driver, this.config);
|
|
287
|
-
return {
|
|
288
|
-
name: this.storage.getMigrationName(name),
|
|
289
|
-
up: () => this.runner.run(instance, 'up'),
|
|
290
|
-
down: () => this.runner.run(instance, 'down'),
|
|
291
|
-
};
|
|
183
|
+
const snapshotPath = await this.getSnapshotPath();
|
|
184
|
+
schema ??= this.schemaGenerator.getTargetSchema();
|
|
185
|
+
const { fs } = await import('@mikro-orm/core/fs-utils');
|
|
186
|
+
await fs.writeFile(snapshotPath, JSON.stringify(schema, null, 2));
|
|
292
187
|
}
|
|
293
188
|
async getSchemaDiff(blank, initial) {
|
|
294
189
|
const up = [];
|
|
@@ -331,7 +226,7 @@ export class Migrator {
|
|
|
331
226
|
wrap: false,
|
|
332
227
|
safe: this.options.safe,
|
|
333
228
|
dropTables: this.options.dropTables,
|
|
334
|
-
fromSchema: this.getSchemaFromSnapshot(),
|
|
229
|
+
fromSchema: await this.getSchemaFromSnapshot(),
|
|
335
230
|
});
|
|
336
231
|
up.push(...splitStatements(diff.up));
|
|
337
232
|
down.push(...splitStatements(diff.down));
|
|
@@ -341,6 +236,7 @@ export class Migrator {
|
|
|
341
236
|
if (diff[i]) {
|
|
342
237
|
break;
|
|
343
238
|
}
|
|
239
|
+
/* v8 ignore next */
|
|
344
240
|
diff.splice(i, 1);
|
|
345
241
|
}
|
|
346
242
|
};
|
|
@@ -348,47 +244,4 @@ export class Migrator {
|
|
|
348
244
|
cleanUp(down);
|
|
349
245
|
return { up, down };
|
|
350
246
|
}
|
|
351
|
-
getMigrationFilename(name) {
|
|
352
|
-
name = name.replace(/\.[jt]s$/, '');
|
|
353
|
-
return name.match(/^\d{14}$/) ? this.options.fileName(name) : name;
|
|
354
|
-
}
|
|
355
|
-
prefix(options) {
|
|
356
|
-
if (typeof options === 'string' || Array.isArray(options)) {
|
|
357
|
-
return { migrations: Utils.asArray(options).map(name => this.getMigrationFilename(name)) };
|
|
358
|
-
}
|
|
359
|
-
if (!options) {
|
|
360
|
-
return {};
|
|
361
|
-
}
|
|
362
|
-
if (options.migrations) {
|
|
363
|
-
options.migrations = options.migrations.map(name => this.getMigrationFilename(name));
|
|
364
|
-
}
|
|
365
|
-
if (options.transaction) {
|
|
366
|
-
delete options.transaction;
|
|
367
|
-
}
|
|
368
|
-
['from', 'to'].filter(k => options[k]).forEach(k => options[k] = this.getMigrationFilename(options[k]));
|
|
369
|
-
return options;
|
|
370
|
-
}
|
|
371
|
-
async runMigrations(method, options) {
|
|
372
|
-
await this.ensureDatabase();
|
|
373
|
-
if (!this.options.transactional || !this.options.allOrNothing) {
|
|
374
|
-
return this.umzug[method](this.prefix(options));
|
|
375
|
-
}
|
|
376
|
-
if (Utils.isObject(options) && options.transaction) {
|
|
377
|
-
return this.runInTransaction(options.transaction, method, options);
|
|
378
|
-
}
|
|
379
|
-
return this.driver.getConnection().transactional(trx => this.runInTransaction(trx, method, options));
|
|
380
|
-
}
|
|
381
|
-
async runInTransaction(trx, method, options) {
|
|
382
|
-
this.runner.setMasterMigration(trx);
|
|
383
|
-
this.storage.setMasterMigration(trx);
|
|
384
|
-
const ret = await this.umzug[method](this.prefix(options));
|
|
385
|
-
this.runner.unsetMasterMigration();
|
|
386
|
-
this.storage.unsetMasterMigration();
|
|
387
|
-
return ret;
|
|
388
|
-
}
|
|
389
|
-
ensureMigrationsDirExists() {
|
|
390
|
-
if (!this.options.migrationsList) {
|
|
391
|
-
fs.ensureDir(this.absolutePath);
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
247
|
}
|
package/TSMigrationGenerator.js
CHANGED
|
@@ -7,11 +7,11 @@ export class TSMigrationGenerator extends MigrationGenerator {
|
|
|
7
7
|
let ret = `import { Migration } from '@mikro-orm/migrations';\n\n`;
|
|
8
8
|
ret += `export class ${className} extends Migration {\n\n`;
|
|
9
9
|
ret += ` override async up(): Promise<void> {\n`;
|
|
10
|
-
diff.up.forEach(sql => ret += this.createStatement(sql, 4));
|
|
10
|
+
diff.up.forEach(sql => (ret += this.createStatement(sql, 4)));
|
|
11
11
|
ret += ` }\n\n`;
|
|
12
12
|
if (diff.down.length > 0) {
|
|
13
13
|
ret += ` override async down(): Promise<void> {\n`;
|
|
14
|
-
diff.down.forEach(sql => ret += this.createStatement(sql, 4));
|
|
14
|
+
diff.down.forEach(sql => (ret += this.createStatement(sql, 4)));
|
|
15
15
|
ret += ` }\n\n`;
|
|
16
16
|
}
|
|
17
17
|
ret += `}\n`;
|