@mikro-orm/migrations 7.0.4 → 7.0.5-dev.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/JSMigrationGenerator.d.ts +7 -10
- package/JSMigrationGenerator.js +20 -20
- package/Migration.d.ts +23 -29
- package/Migration.js +46 -46
- package/MigrationGenerator.d.ts +23 -35
- package/MigrationGenerator.js +33 -33
- package/MigrationRunner.d.ts +9 -9
- package/MigrationRunner.js +41 -43
- package/MigrationStorage.d.ts +27 -23
- package/MigrationStorage.js +108 -113
- package/Migrator.d.ts +32 -42
- package/Migrator.js +238 -237
- package/README.md +1 -1
- package/TSMigrationGenerator.d.ts +7 -10
- package/TSMigrationGenerator.js +16 -16
- package/package.json +3 -3
package/Migrator.js
CHANGED
|
@@ -1,264 +1,265 @@
|
|
|
1
|
-
import { t, Type, UnknownType } from '@mikro-orm/core';
|
|
1
|
+
import { t, Type, UnknownType, } from '@mikro-orm/core';
|
|
2
2
|
import { AbstractMigrator } from '@mikro-orm/core/migrations';
|
|
3
|
-
import { DatabaseSchema, DatabaseTable } from '@mikro-orm/sql';
|
|
3
|
+
import { DatabaseSchema, DatabaseTable, } from '@mikro-orm/sql';
|
|
4
4
|
import { MigrationRunner } from './MigrationRunner.js';
|
|
5
5
|
import { MigrationStorage } from './MigrationStorage.js';
|
|
6
6
|
import { TSMigrationGenerator } from './TSMigrationGenerator.js';
|
|
7
7
|
import { JSMigrationGenerator } from './JSMigrationGenerator.js';
|
|
8
8
|
/** Manages SQL database migrations: creation, execution, and rollback of schema changes. */
|
|
9
9
|
export class Migrator extends AbstractMigrator {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
}
|
|
16
|
-
static register(orm) {
|
|
17
|
-
orm.config.registerExtension('@mikro-orm/migrator', () => new Migrator(orm.em));
|
|
18
|
-
}
|
|
19
|
-
createRunner() {
|
|
20
|
-
return new MigrationRunner(this.driver, this.options, this.config);
|
|
21
|
-
}
|
|
22
|
-
createStorage() {
|
|
23
|
-
return new MigrationStorage(this.driver, this.options);
|
|
24
|
-
}
|
|
25
|
-
getDefaultGenerator() {
|
|
26
|
-
if (this.options.emit === 'js' || this.options.emit === 'cjs') {
|
|
27
|
-
return new JSMigrationGenerator(this.driver, this.config.getNamingStrategy(), this.options);
|
|
10
|
+
#schemaGenerator;
|
|
11
|
+
#snapshotPath;
|
|
12
|
+
constructor(em) {
|
|
13
|
+
super(em);
|
|
14
|
+
this.#schemaGenerator = this.config.getExtension('@mikro-orm/schema-generator');
|
|
28
15
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
async getSnapshotPath() {
|
|
32
|
-
if (!this.#snapshotPath) {
|
|
33
|
-
const { fs } = await import('@mikro-orm/core/fs-utils');
|
|
34
|
-
// for snapshots, we always want to use the path based on `emit` option, regardless of whether we run in TS context
|
|
35
|
-
/* v8 ignore next */
|
|
36
|
-
const snapshotPath = this.options.emit === 'ts' && this.options.pathTs ? this.options.pathTs : this.options.path;
|
|
37
|
-
const absoluteSnapshotPath = fs.absolutePath(snapshotPath, this.config.get('baseDir'));
|
|
38
|
-
const dbName = this.config.get('dbName').replace(/\\/g, '/').split('/').pop().replace(/:/g, '');
|
|
39
|
-
const snapshotName = this.options.snapshotName ?? `.snapshot-${dbName}`;
|
|
40
|
-
this.#snapshotPath = fs.normalizePath(absoluteSnapshotPath, `${snapshotName}.json`);
|
|
16
|
+
static register(orm) {
|
|
17
|
+
orm.config.registerExtension('@mikro-orm/migrator', () => new Migrator(orm.em));
|
|
41
18
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
async init() {
|
|
45
|
-
if (this.initialized) {
|
|
46
|
-
return;
|
|
19
|
+
createRunner() {
|
|
20
|
+
return new MigrationRunner(this.driver, this.options, this.config);
|
|
47
21
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
/* v8 ignore next */
|
|
51
|
-
if (created) {
|
|
52
|
-
this.initServices();
|
|
22
|
+
createStorage() {
|
|
23
|
+
return new MigrationStorage(this.driver, this.options);
|
|
53
24
|
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
async create(path, blank = false, initial = false, name) {
|
|
60
|
-
await this.init();
|
|
61
|
-
if (initial) {
|
|
62
|
-
return this.createInitial(path, name, blank);
|
|
63
|
-
}
|
|
64
|
-
const diff = await this.getSchemaDiff(blank, initial);
|
|
65
|
-
if (diff.up.length === 0) {
|
|
66
|
-
return { fileName: '', code: '', diff };
|
|
25
|
+
getDefaultGenerator() {
|
|
26
|
+
if (this.options.emit === 'js' || this.options.emit === 'cjs') {
|
|
27
|
+
return new JSMigrationGenerator(this.driver, this.config.getNamingStrategy(), this.options);
|
|
28
|
+
}
|
|
29
|
+
return new TSMigrationGenerator(this.driver, this.config.getNamingStrategy(), this.options);
|
|
67
30
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
}
|
|
81
|
-
/**
|
|
82
|
-
* @inheritDoc
|
|
83
|
-
*/
|
|
84
|
-
async createInitial(path, name, blank = false) {
|
|
85
|
-
await this.init();
|
|
86
|
-
const schemaExists = await this.validateInitialMigration(blank);
|
|
87
|
-
const diff = await this.getSchemaDiff(blank, true);
|
|
88
|
-
const migration = await this.generator.generate(diff, path, name);
|
|
89
|
-
await this.storeCurrentSchema();
|
|
90
|
-
if (schemaExists && !blank) {
|
|
91
|
-
await this.storage.logMigration({ name: migration[1] });
|
|
31
|
+
async getSnapshotPath() {
|
|
32
|
+
if (!this.#snapshotPath) {
|
|
33
|
+
const { fs } = await import('@mikro-orm/core/fs-utils');
|
|
34
|
+
// for snapshots, we always want to use the path based on `emit` option, regardless of whether we run in TS context
|
|
35
|
+
/* v8 ignore next */
|
|
36
|
+
const snapshotPath = this.options.emit === 'ts' && this.options.pathTs ? this.options.pathTs : this.options.path;
|
|
37
|
+
const absoluteSnapshotPath = fs.absolutePath(snapshotPath, this.config.get('baseDir'));
|
|
38
|
+
const dbName = this.config.get('dbName').replace(/\\/g, '/').split('/').pop().replace(/:/g, '');
|
|
39
|
+
const snapshotName = this.options.snapshotName ?? `.snapshot-${dbName}`;
|
|
40
|
+
this.#snapshotPath = fs.normalizePath(absoluteSnapshotPath, `${snapshotName}.json`);
|
|
41
|
+
}
|
|
42
|
+
return this.#snapshotPath;
|
|
92
43
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
await this.storeCurrentSchema(schema);
|
|
105
|
-
} catch {
|
|
106
|
-
// Silently ignore for read-only filesystems (production).
|
|
107
|
-
}
|
|
44
|
+
async init() {
|
|
45
|
+
if (this.initialized) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
await super.init();
|
|
49
|
+
const created = await this.#schemaGenerator.ensureDatabase();
|
|
50
|
+
/* v8 ignore next */
|
|
51
|
+
if (created) {
|
|
52
|
+
this.initServices();
|
|
53
|
+
}
|
|
54
|
+
await this.storage.ensureTable();
|
|
108
55
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
56
|
+
/**
|
|
57
|
+
* @inheritDoc
|
|
58
|
+
*/
|
|
59
|
+
async create(path, blank = false, initial = false, name) {
|
|
60
|
+
await this.init();
|
|
61
|
+
if (initial) {
|
|
62
|
+
return this.createInitial(path, name, blank);
|
|
63
|
+
}
|
|
64
|
+
const diff = await this.getSchemaDiff(blank, initial);
|
|
65
|
+
if (diff.up.length === 0) {
|
|
66
|
+
return { fileName: '', code: '', diff };
|
|
67
|
+
}
|
|
68
|
+
const migration = await this.generator.generate(diff, path, name);
|
|
69
|
+
await this.storeCurrentSchema();
|
|
70
|
+
return {
|
|
71
|
+
fileName: migration[1],
|
|
72
|
+
code: migration[0],
|
|
73
|
+
diff,
|
|
74
|
+
};
|
|
127
75
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
.filter(meta => meta.tableName && !meta.embeddable && !meta.virtual)
|
|
133
|
-
.forEach(meta => {
|
|
134
|
-
const schema = meta.schema ?? this.config.get('schema', this.em.getPlatform().getDefaultSchemaName());
|
|
135
|
-
expected.add(schema ? `${schema}.${meta.collection}` : meta.collection);
|
|
136
|
-
});
|
|
137
|
-
schema.getTables().forEach(table => {
|
|
138
|
-
const schema = table.schema ?? this.em.getPlatform().getDefaultSchemaName();
|
|
139
|
-
const tableName = schema ? `${schema}.${table.name}` : table.name;
|
|
140
|
-
if (expected.has(tableName)) {
|
|
141
|
-
exists.add(table.schema ? `${table.schema}.${table.name}` : table.name);
|
|
142
|
-
}
|
|
143
|
-
});
|
|
144
|
-
if (expected.size === 0 && !blank) {
|
|
145
|
-
throw new Error('No entities found');
|
|
76
|
+
async checkSchema() {
|
|
77
|
+
await this.init();
|
|
78
|
+
const diff = await this.getSchemaDiff(false, false);
|
|
79
|
+
return diff.up.length > 0;
|
|
146
80
|
}
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
81
|
+
/**
|
|
82
|
+
* @inheritDoc
|
|
83
|
+
*/
|
|
84
|
+
async createInitial(path, name, blank = false) {
|
|
85
|
+
await this.init();
|
|
86
|
+
const schemaExists = await this.validateInitialMigration(blank);
|
|
87
|
+
const diff = await this.getSchemaDiff(blank, true);
|
|
88
|
+
const migration = await this.generator.generate(diff, path, name);
|
|
89
|
+
await this.storeCurrentSchema();
|
|
90
|
+
if (schemaExists && !blank) {
|
|
91
|
+
await this.storage.logMigration({ name: migration[1] });
|
|
92
|
+
}
|
|
93
|
+
return {
|
|
94
|
+
fileName: migration[1],
|
|
95
|
+
code: migration[0],
|
|
96
|
+
diff,
|
|
97
|
+
};
|
|
151
98
|
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
99
|
+
async runMigrations(method, options) {
|
|
100
|
+
const result = await super.runMigrations(method, options);
|
|
101
|
+
if (result.length > 0 && this.options.snapshot) {
|
|
102
|
+
const schema = await DatabaseSchema.create(this.em.getConnection(), this.em.getPlatform(), this.config);
|
|
103
|
+
try {
|
|
104
|
+
await this.storeCurrentSchema(schema);
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
// Silently ignore for read-only filesystems (production).
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return result;
|
|
157
111
|
}
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
if (!fs.pathExists(snapshotPath)) {
|
|
161
|
-
return undefined;
|
|
112
|
+
getStorage() {
|
|
113
|
+
return this.storage;
|
|
162
114
|
}
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
115
|
+
/**
|
|
116
|
+
* Initial migration can be created only if:
|
|
117
|
+
* 1. no previous migrations were generated or executed
|
|
118
|
+
* 2. existing schema do not contain any of the tables defined by metadata
|
|
119
|
+
*
|
|
120
|
+
* If existing schema contains all of the tables already, we return true, based on that we mark the migration as already executed.
|
|
121
|
+
* If only some of the tables are present, exception is thrown.
|
|
122
|
+
*/
|
|
123
|
+
async validateInitialMigration(blank) {
|
|
124
|
+
const executed = await this.getExecuted();
|
|
125
|
+
const pending = await this.getPending();
|
|
126
|
+
if (executed.length > 0 || pending.length > 0) {
|
|
127
|
+
throw new Error('Initial migration cannot be created, as some migrations already exist');
|
|
128
|
+
}
|
|
129
|
+
const schema = await DatabaseSchema.create(this.em.getConnection(), this.em.getPlatform(), this.config);
|
|
130
|
+
const exists = new Set();
|
|
131
|
+
const expected = new Set();
|
|
132
|
+
[...this.em.getMetadata().getAll().values()]
|
|
133
|
+
.filter(meta => meta.tableName && !meta.embeddable && !meta.virtual)
|
|
134
|
+
.forEach(meta => {
|
|
135
|
+
const schema = meta.schema ?? this.config.get('schema', this.em.getPlatform().getDefaultSchemaName());
|
|
136
|
+
expected.add(schema ? `${schema}.${meta.collection}` : meta.collection);
|
|
137
|
+
});
|
|
138
|
+
schema.getTables().forEach(table => {
|
|
139
|
+
const schema = table.schema ?? this.em.getPlatform().getDefaultSchemaName();
|
|
140
|
+
const tableName = schema ? `${schema}.${table.name}` : table.name;
|
|
141
|
+
if (expected.has(tableName)) {
|
|
142
|
+
exists.add(table.schema ? `${table.schema}.${table.name}` : table.name);
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
if (expected.size === 0 && !blank) {
|
|
146
|
+
throw new Error('No entities found');
|
|
147
|
+
}
|
|
148
|
+
if (exists.size > 0 && expected.size !== exists.size) {
|
|
149
|
+
throw new Error(`Some tables already exist in your schema, remove them first to create the initial migration: ${[...exists].join(', ')}`);
|
|
150
|
+
}
|
|
151
|
+
return expected.size === exists.size;
|
|
192
152
|
}
|
|
193
|
-
|
|
194
|
-
|
|
153
|
+
async getSchemaFromSnapshot() {
|
|
154
|
+
if (!this.options.snapshot) {
|
|
155
|
+
return undefined;
|
|
156
|
+
}
|
|
157
|
+
const snapshotPath = await this.getSnapshotPath();
|
|
158
|
+
const { fs } = await import('@mikro-orm/core/fs-utils');
|
|
159
|
+
if (!fs.pathExists(snapshotPath)) {
|
|
160
|
+
return undefined;
|
|
161
|
+
}
|
|
162
|
+
const data = fs.readJSONSync(snapshotPath);
|
|
163
|
+
const schema = new DatabaseSchema(this.driver.getPlatform(), this.config.get('schema'));
|
|
164
|
+
const { tables, namespaces, ...rest } = data;
|
|
165
|
+
const tableInstances = tables.map((tbl) => {
|
|
166
|
+
const table = new DatabaseTable(this.driver.getPlatform(), tbl.name, tbl.schema);
|
|
167
|
+
table.nativeEnums = tbl.nativeEnums ?? {};
|
|
168
|
+
table.comment = tbl.comment;
|
|
169
|
+
if (tbl.indexes) {
|
|
170
|
+
table.setIndexes(tbl.indexes);
|
|
171
|
+
}
|
|
172
|
+
if (tbl.checks) {
|
|
173
|
+
table.setChecks(tbl.checks);
|
|
174
|
+
}
|
|
175
|
+
if (tbl.foreignKeys) {
|
|
176
|
+
table.setForeignKeys(tbl.foreignKeys);
|
|
177
|
+
}
|
|
178
|
+
const cols = tbl.columns;
|
|
179
|
+
Object.keys(cols).forEach(col => {
|
|
180
|
+
const column = { ...cols[col] };
|
|
181
|
+
/* v8 ignore next */
|
|
182
|
+
column.mappedType = Type.getType(t[cols[col].mappedType] ?? UnknownType);
|
|
183
|
+
table.addColumn(column);
|
|
184
|
+
});
|
|
185
|
+
return table;
|
|
186
|
+
});
|
|
187
|
+
schema.setTables(tableInstances);
|
|
188
|
+
schema.setNamespaces(new Set(namespaces));
|
|
189
|
+
if (rest.nativeEnums) {
|
|
190
|
+
schema.setNativeEnums(rest.nativeEnums);
|
|
191
|
+
}
|
|
192
|
+
if (rest.views) {
|
|
193
|
+
schema.setViews(rest.views);
|
|
194
|
+
}
|
|
195
|
+
return schema;
|
|
195
196
|
}
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
197
|
+
async storeCurrentSchema(schema) {
|
|
198
|
+
if (!this.options.snapshot) {
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
const snapshotPath = await this.getSnapshotPath();
|
|
202
|
+
schema ??= this.#schemaGenerator.getTargetSchema();
|
|
203
|
+
const { fs } = await import('@mikro-orm/core/fs-utils');
|
|
204
|
+
await fs.writeFile(snapshotPath, JSON.stringify(schema, null, 2));
|
|
201
205
|
}
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
206
|
+
async getSchemaDiff(blank, initial) {
|
|
207
|
+
const up = [];
|
|
208
|
+
const down = [];
|
|
209
|
+
// Split SQL by statement boundaries (semicolons followed by newline) rather than
|
|
210
|
+
// just newlines, to preserve multiline statements like view definitions.
|
|
211
|
+
// Blank lines (from double newlines) are preserved as empty strings for grouping.
|
|
212
|
+
// Splits inside single-quoted string literals are re-merged (GH #7185).
|
|
213
|
+
const splitStatements = (sql) => {
|
|
214
|
+
const result = [];
|
|
215
|
+
let buf = '';
|
|
216
|
+
for (const chunk of sql.split(/;\n/)) {
|
|
217
|
+
buf += (buf ? ';\n' : '') + chunk;
|
|
218
|
+
// odd number of single quotes means we're inside a string literal
|
|
219
|
+
if (buf.split(`'`).length % 2 === 0) {
|
|
220
|
+
continue;
|
|
221
|
+
}
|
|
222
|
+
// A chunk starting with \n indicates there was a blank line (grouping separator)
|
|
223
|
+
if (buf.startsWith('\n')) {
|
|
224
|
+
result.push('');
|
|
225
|
+
}
|
|
226
|
+
const trimmed = buf.trim();
|
|
227
|
+
if (trimmed) {
|
|
228
|
+
result.push(trimmed.endsWith(';') ? trimmed : trimmed + ';');
|
|
229
|
+
}
|
|
230
|
+
buf = '';
|
|
231
|
+
}
|
|
232
|
+
return result;
|
|
233
|
+
};
|
|
234
|
+
if (blank) {
|
|
235
|
+
up.push('select 1');
|
|
236
|
+
down.push('select 1');
|
|
222
237
|
}
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
238
|
+
else if (initial) {
|
|
239
|
+
const dump = await this.#schemaGenerator.getCreateSchemaSQL({ wrap: false });
|
|
240
|
+
up.push(...splitStatements(dump));
|
|
226
241
|
}
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
242
|
+
else {
|
|
243
|
+
const diff = await this.#schemaGenerator.getUpdateSchemaMigrationSQL({
|
|
244
|
+
wrap: false,
|
|
245
|
+
safe: this.options.safe,
|
|
246
|
+
dropTables: this.options.dropTables,
|
|
247
|
+
fromSchema: await this.getSchemaFromSnapshot(),
|
|
248
|
+
});
|
|
249
|
+
up.push(...splitStatements(diff.up));
|
|
250
|
+
down.push(...splitStatements(diff.down));
|
|
230
251
|
}
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
wrap: false,
|
|
244
|
-
safe: this.options.safe,
|
|
245
|
-
dropTables: this.options.dropTables,
|
|
246
|
-
fromSchema: await this.getSchemaFromSnapshot(),
|
|
247
|
-
});
|
|
248
|
-
up.push(...splitStatements(diff.up));
|
|
249
|
-
down.push(...splitStatements(diff.down));
|
|
252
|
+
const cleanUp = (diff) => {
|
|
253
|
+
for (let i = diff.length - 1; i >= 0; i--) {
|
|
254
|
+
if (diff[i]) {
|
|
255
|
+
break;
|
|
256
|
+
}
|
|
257
|
+
/* v8 ignore next */
|
|
258
|
+
diff.splice(i, 1);
|
|
259
|
+
}
|
|
260
|
+
};
|
|
261
|
+
cleanUp(up);
|
|
262
|
+
cleanUp(down);
|
|
263
|
+
return { up, down };
|
|
250
264
|
}
|
|
251
|
-
const cleanUp = diff => {
|
|
252
|
-
for (let i = diff.length - 1; i >= 0; i--) {
|
|
253
|
-
if (diff[i]) {
|
|
254
|
-
break;
|
|
255
|
-
}
|
|
256
|
-
/* v8 ignore next */
|
|
257
|
-
diff.splice(i, 1);
|
|
258
|
-
}
|
|
259
|
-
};
|
|
260
|
-
cleanUp(up);
|
|
261
|
-
cleanUp(down);
|
|
262
|
-
return { up, down };
|
|
263
|
-
}
|
|
264
265
|
}
|
package/README.md
CHANGED
|
@@ -133,7 +133,7 @@ const author = await em.findOneOrFail(Author, 1, {
|
|
|
133
133
|
populate: ['books'],
|
|
134
134
|
});
|
|
135
135
|
author.name = 'Jon Snow II';
|
|
136
|
-
author.books.getItems().forEach(book =>
|
|
136
|
+
author.books.getItems().forEach(book => book.title += ' (2nd ed.)');
|
|
137
137
|
author.books.add(orm.em.create(Book, { title: 'New Book', author }));
|
|
138
138
|
|
|
139
139
|
// Flush computes change sets and executes them in a single transaction
|
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
import { MigrationGenerator } from './MigrationGenerator.js';
|
|
2
2
|
/** Generates migration files in TypeScript format. */
|
|
3
3
|
export declare class TSMigrationGenerator extends MigrationGenerator {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
down: string[];
|
|
12
|
-
},
|
|
13
|
-
): string;
|
|
4
|
+
/**
|
|
5
|
+
* @inheritDoc
|
|
6
|
+
*/
|
|
7
|
+
generateMigrationFile(className: string, diff: {
|
|
8
|
+
up: string[];
|
|
9
|
+
down: string[];
|
|
10
|
+
}): string;
|
|
14
11
|
}
|
package/TSMigrationGenerator.js
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
import { MigrationGenerator } from './MigrationGenerator.js';
|
|
2
2
|
/** Generates migration files in TypeScript format. */
|
|
3
3
|
export class TSMigrationGenerator extends MigrationGenerator {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
4
|
+
/**
|
|
5
|
+
* @inheritDoc
|
|
6
|
+
*/
|
|
7
|
+
generateMigrationFile(className, diff) {
|
|
8
|
+
let ret = `import { Migration } from '@mikro-orm/migrations';\n\n`;
|
|
9
|
+
ret += `export class ${className} extends Migration {\n\n`;
|
|
10
|
+
ret += ` override up(): void | Promise<void> {\n`;
|
|
11
|
+
diff.up.forEach(sql => (ret += this.createStatement(sql, 4)));
|
|
12
|
+
ret += ` }\n\n`;
|
|
13
|
+
if (diff.down.length > 0) {
|
|
14
|
+
ret += ` override down(): void | Promise<void> {\n`;
|
|
15
|
+
diff.down.forEach(sql => (ret += this.createStatement(sql, 4)));
|
|
16
|
+
ret += ` }\n\n`;
|
|
17
|
+
}
|
|
18
|
+
ret += `}\n`;
|
|
19
|
+
return ret;
|
|
17
20
|
}
|
|
18
|
-
ret += `}\n`;
|
|
19
|
-
return ret;
|
|
20
|
-
}
|
|
21
21
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mikro-orm/migrations",
|
|
3
|
-
"version": "7.0.
|
|
3
|
+
"version": "7.0.5-dev.0",
|
|
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.0.
|
|
50
|
+
"@mikro-orm/sql": "7.0.5-dev.0"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
53
|
"@mikro-orm/core": "^7.0.4"
|
|
54
54
|
},
|
|
55
55
|
"peerDependencies": {
|
|
56
|
-
"@mikro-orm/core": "7.0.
|
|
56
|
+
"@mikro-orm/core": "7.0.5-dev.0"
|
|
57
57
|
},
|
|
58
58
|
"engines": {
|
|
59
59
|
"node": ">= 22.17.0"
|