@mikro-orm/migrations 7.0.15 → 7.0.16-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/Migrator.js CHANGED
@@ -1,311 +1,303 @@
1
- import { Utils, t, Type, UnknownType } from '@mikro-orm/core';
1
+ import { Utils, 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
- #schemaGenerator;
11
- #snapshotPath;
12
- constructor(em) {
13
- super(em);
14
- this.#schemaGenerator = this.config.getExtension('@mikro-orm/schema-generator');
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
- return new TSMigrationGenerator(this.driver, this.config.getNamingStrategy(), this.options);
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
- return this.#snapshotPath;
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
- await super.init();
49
- const created = await this.#schemaGenerator.ensureDatabase();
50
- /* v8 ignore next */
51
- if (created) {
52
- this.initServices();
22
+ createStorage() {
23
+ return new MigrationStorage(this.driver, this.options);
53
24
  }
54
- await this.storage.ensureTable();
55
- }
56
- /**
57
- * @inheritDoc
58
- */
59
- async create(path, blank = false, initial = false, name) {
60
- const offline = !initial && (await this.hasSnapshot());
61
- await (offline ? this.initPaths() : this.init());
62
- if (initial) {
63
- return this.createInitial(path, name, blank);
64
- }
65
- const diff = await this.getSchemaDiff(blank, initial);
66
- if (diff.up.length === 0) {
67
- return { fileName: '', code: '', diff };
68
- }
69
- const migration = await this.generator.generate(diff, path, name);
70
- await this.storeCurrentSchema();
71
- return {
72
- fileName: migration[1],
73
- code: migration[0],
74
- diff,
75
- };
76
- }
77
- async getPending() {
78
- if (!(await this.hasSnapshot())) {
79
- return super.getPending();
80
- }
81
- await this.initPaths();
82
- const all = await this.discoverMigrations();
83
- // probe the DB via `ensureTable` — if it fails, the DB is unreachable and
84
- // we treat every discovered migration as pending; otherwise let errors
85
- // from `storage.executed()` propagate so real bugs are not swallowed
86
- try {
87
- await this.storage.ensureTable();
88
- } catch {
89
- return all.map(m => ({ name: m.name, path: m.path }));
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);
90
30
  }
91
- const executed = new Set(await this.storage.executed());
92
- return all.filter(m => !executed.has(m.name)).map(m => ({ name: m.name, path: m.path }));
93
- }
94
- async hasSnapshot() {
95
- if (!this.options.snapshot) {
96
- return false;
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;
97
43
  }
98
- const { fs } = await import('@mikro-orm/core/fs-utils');
99
- return fs.pathExists(await this.getSnapshotPath());
100
- }
101
- async checkSchema() {
102
- const snapshot = await this.getSchemaFromSnapshot();
103
- if (!snapshot) {
104
- await this.init();
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();
105
55
  }
106
- const diff = await this.#schemaGenerator.getUpdateSchemaMigrationSQL({
107
- wrap: false,
108
- safe: this.options.safe,
109
- dropTables: this.options.dropTables,
110
- fromSchema: snapshot,
111
- });
112
- return diff.up.trim().length > 0;
113
- }
114
- /**
115
- * @inheritDoc
116
- */
117
- async createInitial(path, name, blank = false) {
118
- await this.init();
119
- const schemaExists = await this.validateInitialMigration(blank);
120
- const diff = await this.getSchemaDiff(blank, true);
121
- const migration = await this.generator.generate(diff, path, name);
122
- await this.storeCurrentSchema();
123
- if (schemaExists && !blank) {
124
- await this.storage.logMigration({ name: migration[1] });
56
+ /**
57
+ * @inheritDoc
58
+ */
59
+ async create(path, blank = false, initial = false, name) {
60
+ const offline = !initial && (await this.hasSnapshot());
61
+ await (offline ? this.initPaths() : this.init());
62
+ if (initial) {
63
+ return this.createInitial(path, name, blank);
64
+ }
65
+ const diff = await this.getSchemaDiff(blank, initial);
66
+ if (diff.up.length === 0) {
67
+ return { fileName: '', code: '', diff };
68
+ }
69
+ const migration = await this.generator.generate(diff, path, name);
70
+ await this.storeCurrentSchema();
71
+ return {
72
+ fileName: migration[1],
73
+ code: migration[0],
74
+ diff,
75
+ };
125
76
  }
126
- return {
127
- fileName: migration[1],
128
- code: migration[0],
129
- diff,
130
- };
131
- }
132
- async runMigrations(method, options) {
133
- const result = await super.runMigrations(method, options);
134
- if (result.length > 0 && this.options.snapshot) {
135
- const ctx = Utils.isObject(options) ? options.transaction : undefined;
136
- const schema = await DatabaseSchema.create(
137
- this.em.getConnection(),
138
- this.em.getPlatform(),
139
- this.config,
140
- undefined,
141
- undefined,
142
- undefined,
143
- undefined,
144
- undefined,
145
- ctx,
146
- );
147
- try {
148
- await this.storeCurrentSchema(schema);
149
- } catch {
150
- // Silently ignore for read-only filesystems (production).
151
- }
77
+ async getPending() {
78
+ if (!(await this.hasSnapshot())) {
79
+ return super.getPending();
80
+ }
81
+ await this.initPaths();
82
+ const all = await this.discoverMigrations();
83
+ // probe the DB via `ensureTable` — if it fails, the DB is unreachable and
84
+ // we treat every discovered migration as pending; otherwise let errors
85
+ // from `storage.executed()` propagate so real bugs are not swallowed
86
+ try {
87
+ await this.storage.ensureTable();
88
+ }
89
+ catch {
90
+ return all.map(m => ({ name: m.name, path: m.path }));
91
+ }
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 }));
152
94
  }
153
- return result;
154
- }
155
- getStorage() {
156
- return this.storage;
157
- }
158
- /**
159
- * Initial migration can be created only if:
160
- * 1. no previous migrations were generated or executed
161
- * 2. existing schema do not contain any of the tables defined by metadata
162
- *
163
- * If existing schema contains all of the tables already, we return true, based on that we mark the migration as already executed.
164
- * If only some of the tables are present, exception is thrown.
165
- */
166
- async validateInitialMigration(blank) {
167
- const executed = await this.getExecuted();
168
- const pending = await this.getPending();
169
- if (executed.length > 0 || pending.length > 0) {
170
- throw new Error('Initial migration cannot be created, as some migrations already exist');
95
+ async hasSnapshot() {
96
+ if (!this.options.snapshot) {
97
+ return false;
98
+ }
99
+ const { fs } = await import('@mikro-orm/core/fs-utils');
100
+ return fs.pathExists(await this.getSnapshotPath());
171
101
  }
172
- const schema = await DatabaseSchema.create(this.em.getConnection(), this.em.getPlatform(), this.config);
173
- const exists = new Set();
174
- const expected = new Set();
175
- [...this.em.getMetadata().getAll().values()]
176
- .filter(meta => meta.tableName && !meta.embeddable && !meta.virtual)
177
- .forEach(meta => {
178
- const schema = meta.schema ?? this.config.get('schema', this.em.getPlatform().getDefaultSchemaName());
179
- expected.add(schema ? `${schema}.${meta.collection}` : meta.collection);
180
- });
181
- schema.getTables().forEach(table => {
182
- const schema = table.schema ?? this.em.getPlatform().getDefaultSchemaName();
183
- const tableName = schema ? `${schema}.${table.name}` : table.name;
184
- if (expected.has(tableName)) {
185
- exists.add(table.schema ? `${table.schema}.${table.name}` : table.name);
186
- }
187
- });
188
- if (expected.size === 0 && !blank) {
189
- throw new Error('No entities found');
102
+ async checkSchema() {
103
+ const snapshot = await this.getSchemaFromSnapshot();
104
+ if (!snapshot) {
105
+ await this.init();
106
+ }
107
+ const diff = await this.#schemaGenerator.getUpdateSchemaMigrationSQL({
108
+ wrap: false,
109
+ safe: this.options.safe,
110
+ dropTables: this.options.dropTables,
111
+ fromSchema: snapshot,
112
+ });
113
+ return diff.up.trim().length > 0;
190
114
  }
191
- if (exists.size > 0 && expected.size !== exists.size) {
192
- throw new Error(
193
- `Some tables already exist in your schema, remove them first to create the initial migration: ${[...exists].join(', ')}`,
194
- );
115
+ /**
116
+ * @inheritDoc
117
+ */
118
+ async createInitial(path, name, blank = false) {
119
+ await this.init();
120
+ const schemaExists = await this.validateInitialMigration(blank);
121
+ const diff = await this.getSchemaDiff(blank, true);
122
+ const migration = await this.generator.generate(diff, path, name);
123
+ await this.storeCurrentSchema();
124
+ if (schemaExists && !blank) {
125
+ await this.storage.logMigration({ name: migration[1] });
126
+ }
127
+ return {
128
+ fileName: migration[1],
129
+ code: migration[0],
130
+ diff,
131
+ };
195
132
  }
196
- return expected.size === exists.size;
197
- }
198
- async getSchemaFromSnapshot() {
199
- if (!this.options.snapshot) {
200
- return undefined;
133
+ async runMigrations(method, options) {
134
+ const result = await super.runMigrations(method, options);
135
+ if (result.length > 0 && this.options.snapshot) {
136
+ const ctx = Utils.isObject(options) ? options.transaction : undefined;
137
+ const schema = await DatabaseSchema.create(this.em.getConnection(), this.em.getPlatform(), this.config, undefined, undefined, undefined, undefined, undefined, ctx);
138
+ try {
139
+ await this.storeCurrentSchema(schema);
140
+ }
141
+ catch {
142
+ // Silently ignore for read-only filesystems (production).
143
+ }
144
+ }
145
+ return result;
201
146
  }
202
- const snapshotPath = await this.getSnapshotPath();
203
- const { fs } = await import('@mikro-orm/core/fs-utils');
204
- if (!fs.pathExists(snapshotPath)) {
205
- return undefined;
147
+ getStorage() {
148
+ return this.storage;
206
149
  }
207
- const data = fs.readJSONSync(snapshotPath);
208
- const schema = new DatabaseSchema(this.driver.getPlatform(), this.config.get('schema'));
209
- const { tables, namespaces, ...rest } = data;
210
- // share schema-level native enums by reference; fall back to per-table copy on older snapshots
211
- const sharedNativeEnums = rest.nativeEnums ?? {};
212
- const hasSharedNativeEnums = Object.keys(sharedNativeEnums).length > 0;
213
- const tableInstances = tables.map(tbl => {
214
- const table = new DatabaseTable(this.driver.getPlatform(), tbl.name, tbl.schema);
215
- table.nativeEnums = hasSharedNativeEnums ? sharedNativeEnums : (tbl.nativeEnums ?? {});
216
- table.comment = tbl.comment;
217
- if (tbl.indexes) {
218
- table.setIndexes(tbl.indexes);
219
- }
220
- if (tbl.checks) {
221
- table.setChecks(tbl.checks);
222
- }
223
- if (tbl.foreignKeys) {
224
- table.setForeignKeys(tbl.foreignKeys);
225
- }
226
- const cols = tbl.columns;
227
- Object.keys(cols).forEach(col => {
228
- const column = { ...cols[col] };
229
- /* v8 ignore next */
230
- column.mappedType = Type.getType(t[cols[col].mappedType] ?? UnknownType);
231
- table.addColumn(column);
232
- });
233
- return table;
234
- });
235
- schema.setTables(tableInstances);
236
- schema.setNamespaces(new Set(namespaces));
237
- if (rest.nativeEnums) {
238
- schema.setNativeEnums(rest.nativeEnums);
150
+ /**
151
+ * Initial migration can be created only if:
152
+ * 1. no previous migrations were generated or executed
153
+ * 2. existing schema do not contain any of the tables defined by metadata
154
+ *
155
+ * If existing schema contains all of the tables already, we return true, based on that we mark the migration as already executed.
156
+ * If only some of the tables are present, exception is thrown.
157
+ */
158
+ async validateInitialMigration(blank) {
159
+ const executed = await this.getExecuted();
160
+ const pending = await this.getPending();
161
+ if (executed.length > 0 || pending.length > 0) {
162
+ throw new Error('Initial migration cannot be created, as some migrations already exist');
163
+ }
164
+ const schema = await DatabaseSchema.create(this.em.getConnection(), this.em.getPlatform(), this.config);
165
+ const exists = new Set();
166
+ const expected = new Set();
167
+ [...this.em.getMetadata().getAll().values()]
168
+ .filter(meta => meta.tableName && !meta.embeddable && !meta.virtual)
169
+ .forEach(meta => {
170
+ const schema = meta.schema ?? this.config.get('schema', this.em.getPlatform().getDefaultSchemaName());
171
+ expected.add(schema ? `${schema}.${meta.collection}` : meta.collection);
172
+ });
173
+ schema.getTables().forEach(table => {
174
+ const schema = table.schema ?? this.em.getPlatform().getDefaultSchemaName();
175
+ const tableName = schema ? `${schema}.${table.name}` : table.name;
176
+ if (expected.has(tableName)) {
177
+ exists.add(table.schema ? `${table.schema}.${table.name}` : table.name);
178
+ }
179
+ });
180
+ if (expected.size === 0 && !blank) {
181
+ throw new Error('No entities found');
182
+ }
183
+ if (exists.size > 0 && expected.size !== exists.size) {
184
+ throw new Error(`Some tables already exist in your schema, remove them first to create the initial migration: ${[...exists].join(', ')}`);
185
+ }
186
+ return expected.size === exists.size;
239
187
  }
240
- if (rest.views) {
241
- schema.setViews(rest.views);
188
+ async getSchemaFromSnapshot() {
189
+ if (!this.options.snapshot) {
190
+ return undefined;
191
+ }
192
+ const snapshotPath = await this.getSnapshotPath();
193
+ const { fs } = await import('@mikro-orm/core/fs-utils');
194
+ if (!fs.pathExists(snapshotPath)) {
195
+ return undefined;
196
+ }
197
+ const data = fs.readJSONSync(snapshotPath);
198
+ const schema = new DatabaseSchema(this.driver.getPlatform(), this.config.get('schema'));
199
+ const { tables, namespaces, ...rest } = data;
200
+ // share schema-level native enums by reference; fall back to per-table copy on older snapshots
201
+ const sharedNativeEnums = rest.nativeEnums ?? {};
202
+ const hasSharedNativeEnums = Object.keys(sharedNativeEnums).length > 0;
203
+ const tableInstances = tables.map((tbl) => {
204
+ const table = new DatabaseTable(this.driver.getPlatform(), tbl.name, tbl.schema);
205
+ table.nativeEnums = hasSharedNativeEnums ? sharedNativeEnums : (tbl.nativeEnums ?? {});
206
+ table.comment = tbl.comment;
207
+ if (tbl.indexes) {
208
+ table.setIndexes(tbl.indexes);
209
+ }
210
+ if (tbl.checks) {
211
+ table.setChecks(tbl.checks);
212
+ }
213
+ if (tbl.foreignKeys) {
214
+ table.setForeignKeys(tbl.foreignKeys);
215
+ }
216
+ const cols = tbl.columns;
217
+ Object.keys(cols).forEach(col => {
218
+ const column = { ...cols[col] };
219
+ /* v8 ignore next */
220
+ column.mappedType = Type.getType(t[cols[col].mappedType] ?? UnknownType);
221
+ table.addColumn(column);
222
+ });
223
+ return table;
224
+ });
225
+ schema.setTables(tableInstances);
226
+ schema.setNamespaces(new Set(namespaces));
227
+ if (rest.nativeEnums) {
228
+ schema.setNativeEnums(rest.nativeEnums);
229
+ }
230
+ if (rest.views) {
231
+ schema.setViews(rest.views);
232
+ }
233
+ return schema;
242
234
  }
243
- return schema;
244
- }
245
- async storeCurrentSchema(schema) {
246
- if (!this.options.snapshot) {
247
- return;
235
+ async storeCurrentSchema(schema) {
236
+ if (!this.options.snapshot) {
237
+ return;
238
+ }
239
+ const snapshotPath = await this.getSnapshotPath();
240
+ schema ??= this.#schemaGenerator.getTargetSchema();
241
+ const { fs } = await import('@mikro-orm/core/fs-utils');
242
+ await fs.writeFile(snapshotPath, JSON.stringify(schema, null, 2));
248
243
  }
249
- const snapshotPath = await this.getSnapshotPath();
250
- schema ??= this.#schemaGenerator.getTargetSchema();
251
- const { fs } = await import('@mikro-orm/core/fs-utils');
252
- await fs.writeFile(snapshotPath, JSON.stringify(schema, null, 2));
253
- }
254
- async getSchemaDiff(blank, initial) {
255
- const up = [];
256
- const down = [];
257
- // Split SQL by statement boundaries (semicolons followed by newline) rather than
258
- // just newlines, to preserve multiline statements like view definitions.
259
- // Blank lines (from double newlines) are preserved as empty strings for grouping.
260
- // Splits inside single-quoted string literals are re-merged (GH #7185).
261
- const splitStatements = sql => {
262
- const result = [];
263
- let buf = '';
264
- for (const chunk of sql.split(/;\n/)) {
265
- buf += (buf ? ';\n' : '') + chunk;
266
- // odd number of single quotes means we're inside a string literal
267
- if (buf.split(`'`).length % 2 === 0) {
268
- continue;
244
+ async getSchemaDiff(blank, initial) {
245
+ const up = [];
246
+ const down = [];
247
+ // Split SQL by statement boundaries (semicolons followed by newline) rather than
248
+ // just newlines, to preserve multiline statements like view definitions.
249
+ // Blank lines (from double newlines) are preserved as empty strings for grouping.
250
+ // Splits inside single-quoted string literals are re-merged (GH #7185).
251
+ const splitStatements = (sql) => {
252
+ const result = [];
253
+ let buf = '';
254
+ for (const chunk of sql.split(/;\n/)) {
255
+ buf += (buf ? ';\n' : '') + chunk;
256
+ // odd number of single quotes means we're inside a string literal
257
+ if (buf.split(`'`).length % 2 === 0) {
258
+ continue;
259
+ }
260
+ // A chunk starting with \n indicates there was a blank line (grouping separator)
261
+ if (buf.startsWith('\n')) {
262
+ result.push('');
263
+ }
264
+ const trimmed = buf.trim();
265
+ if (trimmed) {
266
+ result.push(trimmed.endsWith(';') ? trimmed : trimmed + ';');
267
+ }
268
+ buf = '';
269
+ }
270
+ return result;
271
+ };
272
+ if (blank) {
273
+ up.push('select 1');
274
+ down.push('select 1');
269
275
  }
270
- // A chunk starting with \n indicates there was a blank line (grouping separator)
271
- if (buf.startsWith('\n')) {
272
- result.push('');
276
+ else if (initial) {
277
+ const dump = await this.#schemaGenerator.getCreateSchemaSQL({ wrap: false });
278
+ up.push(...splitStatements(dump));
273
279
  }
274
- const trimmed = buf.trim();
275
- if (trimmed) {
276
- result.push(trimmed.endsWith(';') ? trimmed : trimmed + ';');
280
+ else {
281
+ const diff = await this.#schemaGenerator.getUpdateSchemaMigrationSQL({
282
+ wrap: false,
283
+ safe: this.options.safe,
284
+ dropTables: this.options.dropTables,
285
+ fromSchema: await this.getSchemaFromSnapshot(),
286
+ });
287
+ up.push(...splitStatements(diff.up));
288
+ down.push(...splitStatements(diff.down));
277
289
  }
278
- buf = '';
279
- }
280
- return result;
281
- };
282
- if (blank) {
283
- up.push('select 1');
284
- down.push('select 1');
285
- } else if (initial) {
286
- const dump = await this.#schemaGenerator.getCreateSchemaSQL({ wrap: false });
287
- up.push(...splitStatements(dump));
288
- } else {
289
- const diff = await this.#schemaGenerator.getUpdateSchemaMigrationSQL({
290
- wrap: false,
291
- safe: this.options.safe,
292
- dropTables: this.options.dropTables,
293
- fromSchema: await this.getSchemaFromSnapshot(),
294
- });
295
- up.push(...splitStatements(diff.up));
296
- down.push(...splitStatements(diff.down));
290
+ const cleanUp = (diff) => {
291
+ for (let i = diff.length - 1; i >= 0; i--) {
292
+ if (diff[i]) {
293
+ break;
294
+ }
295
+ /* v8 ignore next */
296
+ diff.splice(i, 1);
297
+ }
298
+ };
299
+ cleanUp(up);
300
+ cleanUp(down);
301
+ return { up, down };
297
302
  }
298
- const cleanUp = diff => {
299
- for (let i = diff.length - 1; i >= 0; i--) {
300
- if (diff[i]) {
301
- break;
302
- }
303
- /* v8 ignore next */
304
- diff.splice(i, 1);
305
- }
306
- };
307
- cleanUp(up);
308
- cleanUp(down);
309
- return { up, down };
310
- }
311
303
  }
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 => (book.title += ' (2nd ed.)'));
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
- * @inheritDoc
6
- */
7
- generateMigrationFile(
8
- className: string,
9
- diff: {
10
- up: string[];
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
  }