@mikro-orm/core 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/EntityManager.d.ts +584 -885
- package/EntityManager.js +1911 -1939
- package/MikroORM.d.ts +74 -103
- package/MikroORM.js +178 -177
- package/README.md +1 -1
- package/cache/CacheAdapter.d.ts +36 -36
- package/cache/FileCacheAdapter.d.ts +24 -30
- package/cache/FileCacheAdapter.js +78 -80
- package/cache/GeneratedCacheAdapter.d.ts +20 -18
- package/cache/GeneratedCacheAdapter.js +30 -30
- package/cache/MemoryCacheAdapter.d.ts +20 -18
- package/cache/MemoryCacheAdapter.js +36 -35
- package/cache/NullCacheAdapter.d.ts +16 -16
- package/cache/NullCacheAdapter.js +24 -24
- package/connections/Connection.d.ts +84 -95
- package/connections/Connection.js +168 -165
- package/drivers/DatabaseDriver.d.ts +80 -186
- package/drivers/DatabaseDriver.js +443 -450
- package/drivers/IDatabaseDriver.d.ts +305 -444
- package/entity/BaseEntity.d.ts +83 -120
- package/entity/BaseEntity.js +43 -43
- package/entity/Collection.d.ts +181 -215
- package/entity/Collection.js +724 -730
- package/entity/EntityAssigner.d.ts +77 -88
- package/entity/EntityAssigner.js +230 -231
- package/entity/EntityFactory.d.ts +55 -67
- package/entity/EntityFactory.js +413 -454
- package/entity/EntityHelper.d.ts +23 -35
- package/entity/EntityHelper.js +290 -302
- package/entity/EntityIdentifier.d.ts +4 -4
- package/entity/EntityIdentifier.js +10 -10
- package/entity/EntityLoader.d.ts +72 -98
- package/entity/EntityLoader.js +786 -815
- package/entity/EntityRepository.d.ts +201 -316
- package/entity/EntityRepository.js +213 -213
- package/entity/PolymorphicRef.d.ts +5 -5
- package/entity/PolymorphicRef.js +10 -10
- package/entity/Reference.d.ts +83 -127
- package/entity/Reference.js +277 -281
- package/entity/WrappedEntity.d.ts +72 -115
- package/entity/WrappedEntity.js +166 -168
- package/entity/defineEntity.d.ts +659 -1412
- package/entity/defineEntity.js +518 -527
- package/entity/utils.d.ts +3 -13
- package/entity/utils.js +73 -71
- package/entity/validators.js +43 -43
- package/entity/wrap.js +8 -8
- package/enums.d.ts +253 -258
- package/enums.js +252 -251
- package/errors.d.ts +72 -114
- package/errors.js +253 -350
- package/events/EventManager.d.ts +14 -26
- package/events/EventManager.js +77 -79
- package/events/EventSubscriber.d.ts +29 -29
- package/events/TransactionEventBroadcaster.d.ts +8 -15
- package/events/TransactionEventBroadcaster.js +14 -14
- package/exceptions.d.ts +40 -23
- package/exceptions.js +52 -35
- package/hydration/Hydrator.d.ts +17 -42
- package/hydration/Hydrator.js +43 -43
- package/hydration/ObjectHydrator.d.ts +17 -50
- package/hydration/ObjectHydrator.js +418 -483
- package/index.d.ts +2 -118
- package/index.js +1 -10
- package/logging/DefaultLogger.d.ts +32 -34
- package/logging/DefaultLogger.js +86 -86
- package/logging/Logger.d.ts +41 -41
- package/logging/SimpleLogger.d.ts +11 -13
- package/logging/SimpleLogger.js +22 -22
- package/logging/colors.d.ts +6 -6
- package/logging/colors.js +10 -11
- package/logging/inspect.js +7 -7
- package/metadata/EntitySchema.d.ts +130 -214
- package/metadata/EntitySchema.js +412 -411
- package/metadata/MetadataDiscovery.d.ts +115 -115
- package/metadata/MetadataDiscovery.js +1931 -2013
- package/metadata/MetadataProvider.d.ts +26 -29
- package/metadata/MetadataProvider.js +97 -95
- package/metadata/MetadataStorage.d.ts +32 -38
- package/metadata/MetadataStorage.js +118 -118
- package/metadata/MetadataValidator.d.ts +39 -39
- package/metadata/MetadataValidator.js +340 -385
- package/metadata/discover-entities.d.ts +2 -5
- package/metadata/discover-entities.js +37 -35
- package/metadata/types.d.ts +531 -615
- package/naming-strategy/AbstractNamingStrategy.d.ts +39 -54
- package/naming-strategy/AbstractNamingStrategy.js +85 -90
- package/naming-strategy/EntityCaseNamingStrategy.d.ts +6 -6
- package/naming-strategy/EntityCaseNamingStrategy.js +22 -22
- package/naming-strategy/MongoNamingStrategy.d.ts +6 -6
- package/naming-strategy/MongoNamingStrategy.js +18 -18
- package/naming-strategy/NamingStrategy.d.ts +99 -109
- package/naming-strategy/UnderscoreNamingStrategy.d.ts +7 -7
- package/naming-strategy/UnderscoreNamingStrategy.js +21 -21
- package/not-supported.js +4 -7
- package/package.json +1 -1
- package/platforms/ExceptionConverter.d.ts +1 -1
- package/platforms/ExceptionConverter.js +4 -4
- package/platforms/Platform.d.ts +303 -312
- package/platforms/Platform.js +695 -715
- package/serialization/EntitySerializer.d.ts +26 -49
- package/serialization/EntitySerializer.js +218 -224
- package/serialization/EntityTransformer.d.ts +6 -10
- package/serialization/EntityTransformer.js +217 -219
- package/serialization/SerializationContext.d.ts +23 -27
- package/serialization/SerializationContext.js +105 -105
- package/types/ArrayType.d.ts +8 -8
- package/types/ArrayType.js +33 -33
- package/types/BigIntType.d.ts +10 -17
- package/types/BigIntType.js +37 -37
- package/types/BlobType.d.ts +3 -3
- package/types/BlobType.js +13 -13
- package/types/BooleanType.d.ts +4 -4
- package/types/BooleanType.js +12 -12
- package/types/CharacterType.d.ts +2 -2
- package/types/CharacterType.js +6 -6
- package/types/DateTimeType.d.ts +5 -5
- package/types/DateTimeType.js +15 -15
- package/types/DateType.d.ts +5 -5
- package/types/DateType.js +15 -15
- package/types/DecimalType.d.ts +7 -7
- package/types/DecimalType.js +26 -26
- package/types/DoubleType.d.ts +3 -3
- package/types/DoubleType.js +12 -12
- package/types/EnumArrayType.d.ts +5 -5
- package/types/EnumArrayType.js +24 -24
- package/types/EnumType.d.ts +3 -3
- package/types/EnumType.js +11 -11
- package/types/FloatType.d.ts +3 -3
- package/types/FloatType.js +9 -9
- package/types/IntegerType.d.ts +3 -3
- package/types/IntegerType.js +9 -9
- package/types/IntervalType.d.ts +4 -4
- package/types/IntervalType.js +12 -12
- package/types/JsonType.d.ts +8 -8
- package/types/JsonType.js +32 -32
- package/types/MediumIntType.d.ts +1 -1
- package/types/MediumIntType.js +3 -3
- package/types/SmallIntType.d.ts +3 -3
- package/types/SmallIntType.js +9 -9
- package/types/StringType.d.ts +4 -4
- package/types/StringType.js +12 -12
- package/types/TextType.d.ts +3 -3
- package/types/TextType.js +9 -9
- package/types/TimeType.d.ts +5 -5
- package/types/TimeType.js +17 -17
- package/types/TinyIntType.d.ts +3 -3
- package/types/TinyIntType.js +10 -10
- package/types/Type.d.ts +79 -83
- package/types/Type.js +82 -82
- package/types/Uint8ArrayType.d.ts +4 -4
- package/types/Uint8ArrayType.js +21 -21
- package/types/UnknownType.d.ts +4 -4
- package/types/UnknownType.js +12 -12
- package/types/UuidType.d.ts +5 -5
- package/types/UuidType.js +19 -19
- package/types/index.d.ts +49 -75
- package/types/index.js +26 -52
- package/typings.d.ts +746 -1268
- package/typings.js +233 -246
- package/unit-of-work/ChangeSet.d.ts +26 -26
- package/unit-of-work/ChangeSet.js +56 -56
- package/unit-of-work/ChangeSetComputer.d.ts +12 -12
- package/unit-of-work/ChangeSetComputer.js +179 -187
- package/unit-of-work/ChangeSetPersister.d.ts +50 -69
- package/unit-of-work/ChangeSetPersister.js +446 -469
- package/unit-of-work/CommitOrderCalculator.d.ts +40 -40
- package/unit-of-work/CommitOrderCalculator.js +88 -89
- package/unit-of-work/IdentityMap.d.ts +31 -31
- package/unit-of-work/IdentityMap.js +105 -105
- package/unit-of-work/UnitOfWork.d.ts +141 -181
- package/unit-of-work/UnitOfWork.js +1226 -1240
- package/utils/AbstractMigrator.d.ts +92 -112
- package/utils/AbstractMigrator.js +288 -286
- package/utils/AbstractSchemaGenerator.d.ts +34 -43
- package/utils/AbstractSchemaGenerator.js +122 -121
- package/utils/AsyncContext.d.ts +3 -3
- package/utils/AsyncContext.js +35 -34
- package/utils/Configuration.d.ts +808 -852
- package/utils/Configuration.js +344 -359
- package/utils/Cursor.d.ts +22 -40
- package/utils/Cursor.js +127 -135
- package/utils/DataloaderUtils.d.ts +43 -58
- package/utils/DataloaderUtils.js +198 -203
- package/utils/EntityComparator.d.ts +82 -99
- package/utils/EntityComparator.js +744 -836
- package/utils/NullHighlighter.d.ts +1 -1
- package/utils/NullHighlighter.js +3 -3
- package/utils/QueryHelper.d.ts +57 -85
- package/utils/QueryHelper.js +392 -404
- package/utils/RawQueryFragment.d.ts +34 -50
- package/utils/RawQueryFragment.js +121 -122
- package/utils/RequestContext.d.ts +32 -32
- package/utils/RequestContext.js +53 -52
- package/utils/TransactionContext.d.ts +16 -16
- package/utils/TransactionContext.js +27 -27
- package/utils/TransactionManager.d.ts +58 -58
- package/utils/TransactionManager.js +200 -202
- package/utils/Utils.d.ts +145 -204
- package/utils/Utils.js +826 -826
- package/utils/clone.js +114 -105
- package/utils/env-vars.js +88 -90
- package/utils/fs-utils.d.ts +15 -15
- package/utils/fs-utils.js +182 -181
- package/utils/upsert-utils.d.ts +5 -20
- package/utils/upsert-utils.js +116 -114
|
@@ -1,313 +1,315 @@
|
|
|
1
1
|
import { Utils } from './Utils.js';
|
|
2
2
|
export class AbstractMigrator {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}
|
|
21
|
-
/**
|
|
22
|
-
* @inheritDoc
|
|
23
|
-
*/
|
|
24
|
-
on(eventName, listener) {
|
|
25
|
-
if (!this.#listeners.has(eventName)) {
|
|
26
|
-
this.#listeners.set(eventName, new Set());
|
|
3
|
+
em;
|
|
4
|
+
runner;
|
|
5
|
+
storage;
|
|
6
|
+
generator;
|
|
7
|
+
driver;
|
|
8
|
+
config;
|
|
9
|
+
options;
|
|
10
|
+
absolutePath;
|
|
11
|
+
initialized = false;
|
|
12
|
+
#listeners = new Map();
|
|
13
|
+
constructor(em) {
|
|
14
|
+
this.em = em;
|
|
15
|
+
this.driver = this.em.getDriver();
|
|
16
|
+
this.config = this.em.config;
|
|
17
|
+
this.options = this.config.get('migrations');
|
|
18
|
+
this.initServices();
|
|
19
|
+
this.registerDefaultListeners();
|
|
27
20
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* @inheritDoc
|
|
40
|
-
*/
|
|
41
|
-
async getExecuted() {
|
|
42
|
-
await this.init();
|
|
43
|
-
return this.storage.getExecutedMigrations();
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* @inheritDoc
|
|
47
|
-
*/
|
|
48
|
-
async getPending() {
|
|
49
|
-
await this.init();
|
|
50
|
-
const all = await this.discoverMigrations();
|
|
51
|
-
const executed = new Set(await this.storage.executed());
|
|
52
|
-
return all.filter(m => !executed.has(m.name)).map(m => ({ name: m.name, path: m.path }));
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* @inheritDoc
|
|
56
|
-
*/
|
|
57
|
-
async up(options) {
|
|
58
|
-
return this.runMigrations('up', options);
|
|
59
|
-
}
|
|
60
|
-
/**
|
|
61
|
-
* @inheritDoc
|
|
62
|
-
*/
|
|
63
|
-
async down(options) {
|
|
64
|
-
return this.runMigrations('down', options);
|
|
65
|
-
}
|
|
66
|
-
async init() {
|
|
67
|
-
if (this.initialized) {
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
this.initialized = true;
|
|
71
|
-
await this.initPaths();
|
|
72
|
-
}
|
|
73
|
-
async initPaths() {
|
|
74
|
-
if (this.absolutePath || this.options.migrationsList) {
|
|
75
|
-
return;
|
|
76
|
-
}
|
|
77
|
-
const { fs } = await import('@mikro-orm/core/fs-utils');
|
|
78
|
-
this.detectSourceFolder(fs);
|
|
79
|
-
/* v8 ignore next */
|
|
80
|
-
const key = this.config.get('preferTs', Utils.detectTypeScriptSupport()) && this.options.pathTs ? 'pathTs' : 'path';
|
|
81
|
-
this.absolutePath = fs.absolutePath(this.options[key], this.config.get('baseDir'));
|
|
82
|
-
try {
|
|
83
|
-
fs.ensureDir(this.absolutePath);
|
|
84
|
-
} catch {
|
|
85
|
-
// read-only filesystem — read-only operations (e.g. `getPending` with a
|
|
86
|
-
// snapshot) may still succeed; write operations will fail on their own
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
initServices() {
|
|
90
|
-
this.runner = this.createRunner();
|
|
91
|
-
this.storage = this.createStorage();
|
|
92
|
-
if (this.options.generator) {
|
|
93
|
-
this.generator = new this.options.generator(this.driver, this.config.getNamingStrategy(), this.options);
|
|
94
|
-
} else {
|
|
95
|
-
this.generator = this.getDefaultGenerator();
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
resolve(params) {
|
|
99
|
-
const createMigrationHandler = async (method, afterRun) => {
|
|
100
|
-
const { fs } = await import('@mikro-orm/core/fs-utils');
|
|
101
|
-
const migration = await fs.dynamicImport(params.path);
|
|
102
|
-
const MigrationClass = Object.values(migration).find(
|
|
103
|
-
cls => typeof cls === 'function' && typeof cls.constructor === 'function',
|
|
104
|
-
);
|
|
105
|
-
const instance = new MigrationClass(this.driver, this.config);
|
|
106
|
-
await this.runner.run(instance, method, afterRun);
|
|
107
|
-
};
|
|
108
|
-
return {
|
|
109
|
-
name: this.storage.getMigrationName(params.name),
|
|
110
|
-
path: params.path,
|
|
111
|
-
up: afterRun => createMigrationHandler('up', afterRun),
|
|
112
|
-
down: afterRun => createMigrationHandler('down', afterRun),
|
|
113
|
-
};
|
|
114
|
-
}
|
|
115
|
-
initialize(MigrationClass, name) {
|
|
116
|
-
const instance = new MigrationClass(this.driver, this.config);
|
|
117
|
-
return {
|
|
118
|
-
name: this.storage.getMigrationName(name),
|
|
119
|
-
up: afterRun => this.runner.run(instance, 'up', afterRun),
|
|
120
|
-
down: afterRun => this.runner.run(instance, 'down', afterRun),
|
|
121
|
-
};
|
|
122
|
-
}
|
|
123
|
-
/**
|
|
124
|
-
* Checks if `src` folder exists, it so, tries to adjust the migrations and seeders paths automatically to use it.
|
|
125
|
-
* If there is a `dist` or `build` folder, it will be used for the JS variant (`path` option), while the `src` folder will be
|
|
126
|
-
* used for the TS variant (`pathTs` option).
|
|
127
|
-
*
|
|
128
|
-
* If the default folder exists (e.g. `/migrations`), the config will respect that, so this auto-detection should not
|
|
129
|
-
* break existing projects, only help with the new ones.
|
|
130
|
-
*/
|
|
131
|
-
detectSourceFolder(fs) {
|
|
132
|
-
const baseDir = this.config.get('baseDir');
|
|
133
|
-
const defaultPath = './migrations';
|
|
134
|
-
if (!fs.pathExists(baseDir + '/src')) {
|
|
135
|
-
this.options.path ??= defaultPath;
|
|
136
|
-
return;
|
|
21
|
+
/**
|
|
22
|
+
* @inheritDoc
|
|
23
|
+
*/
|
|
24
|
+
on(eventName, listener) {
|
|
25
|
+
if (!this.#listeners.has(eventName)) {
|
|
26
|
+
this.#listeners.set(eventName, new Set());
|
|
27
|
+
}
|
|
28
|
+
this.#listeners.get(eventName).add(listener);
|
|
29
|
+
return this;
|
|
137
30
|
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
// only if the user did not provide any values and if the default path does not exist
|
|
145
|
-
if (!this.options.path && !this.options.pathTs && !exists) {
|
|
146
|
-
this.options.path = `${path}/migrations`;
|
|
147
|
-
this.options.pathTs = './src/migrations';
|
|
31
|
+
/**
|
|
32
|
+
* @inheritDoc
|
|
33
|
+
*/
|
|
34
|
+
off(eventName, listener) {
|
|
35
|
+
this.#listeners.get(eventName)?.delete(listener);
|
|
36
|
+
return this;
|
|
148
37
|
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
this.on('migrated', event => logger.log('migrator', `Applied '${event.name}'`, { enabled: true }));
|
|
156
|
-
this.on('reverting', event => logger.log('migrator', `Processing '${event.name}'`, { enabled: true }));
|
|
157
|
-
this.on('reverted', event => logger.log('migrator', `Reverted '${event.name}'`, { enabled: true }));
|
|
38
|
+
/**
|
|
39
|
+
* @inheritDoc
|
|
40
|
+
*/
|
|
41
|
+
async getExecuted() {
|
|
42
|
+
await this.init();
|
|
43
|
+
return this.storage.getExecutedMigrations();
|
|
158
44
|
}
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
45
|
+
/**
|
|
46
|
+
* @inheritDoc
|
|
47
|
+
*/
|
|
48
|
+
async getPending() {
|
|
49
|
+
await this.init();
|
|
50
|
+
const all = await this.discoverMigrations();
|
|
51
|
+
const executed = new Set(await this.storage.executed());
|
|
52
|
+
return all.filter(m => !executed.has(m.name)).map(m => ({ name: m.name, path: m.path }));
|
|
163
53
|
}
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
return this.initialize(migration, migration.name);
|
|
170
|
-
}
|
|
171
|
-
return this.initialize(migration.class, migration.name);
|
|
172
|
-
});
|
|
54
|
+
/**
|
|
55
|
+
* @inheritDoc
|
|
56
|
+
*/
|
|
57
|
+
async up(options) {
|
|
58
|
+
return this.runMigrations('up', options);
|
|
173
59
|
}
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
name: filePath.replace(/\\/g, '/').split('/').pop(),
|
|
180
|
-
path: filePath,
|
|
181
|
-
}),
|
|
182
|
-
);
|
|
183
|
-
}
|
|
184
|
-
async executeMigrations(method, options = {}) {
|
|
185
|
-
const all = await this.discoverMigrations();
|
|
186
|
-
const executed = await this.storage.executed();
|
|
187
|
-
const executedSet = new Set(executed);
|
|
188
|
-
let toRun;
|
|
189
|
-
if (method === 'up') {
|
|
190
|
-
toRun = this.filterUp(all, executedSet, options);
|
|
191
|
-
} else {
|
|
192
|
-
toRun = this.filterDown(all, executed, options);
|
|
60
|
+
/**
|
|
61
|
+
* @inheritDoc
|
|
62
|
+
*/
|
|
63
|
+
async down(options) {
|
|
64
|
+
return this.runMigrations('down', options);
|
|
193
65
|
}
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
for (const migration of toRun) {
|
|
198
|
-
const event = { name: migration.name, path: migration.path };
|
|
199
|
-
await this.emit(eventBefore, event);
|
|
200
|
-
// log inside the runner's tx (if any) so a logMigration failure rolls the migration back
|
|
201
|
-
await migration[method](async tx => {
|
|
202
|
-
if (method === 'up') {
|
|
203
|
-
await this.storage.logMigration({ name: migration.name }, tx);
|
|
204
|
-
} else {
|
|
205
|
-
await this.storage.unlogMigration({ name: migration.name }, tx);
|
|
66
|
+
async init() {
|
|
67
|
+
if (this.initialized) {
|
|
68
|
+
return;
|
|
206
69
|
}
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
result.push(event);
|
|
70
|
+
this.initialized = true;
|
|
71
|
+
await this.initPaths();
|
|
210
72
|
}
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
73
|
+
async initPaths() {
|
|
74
|
+
if (this.absolutePath || this.options.migrationsList) {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
const { fs } = await import('@mikro-orm/core/fs-utils');
|
|
78
|
+
this.detectSourceFolder(fs);
|
|
79
|
+
/* v8 ignore next */
|
|
80
|
+
const key = this.config.get('preferTs', Utils.detectTypeScriptSupport()) && this.options.pathTs ? 'pathTs' : 'path';
|
|
81
|
+
this.absolutePath = fs.absolutePath(this.options[key], this.config.get('baseDir'));
|
|
82
|
+
try {
|
|
83
|
+
fs.ensureDir(this.absolutePath);
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
// read-only filesystem — read-only operations (e.g. `getPending` with a
|
|
87
|
+
// snapshot) may still succeed; write operations will fail on their own
|
|
88
|
+
}
|
|
218
89
|
}
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
90
|
+
initServices() {
|
|
91
|
+
this.runner = this.createRunner();
|
|
92
|
+
this.storage = this.createStorage();
|
|
93
|
+
if (this.options.generator) {
|
|
94
|
+
this.generator = new this.options.generator(this.driver, this.config.getNamingStrategy(), this.options);
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
this.generator = this.getDefaultGenerator();
|
|
98
|
+
}
|
|
225
99
|
}
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
100
|
+
resolve(params) {
|
|
101
|
+
const createMigrationHandler = async (method, afterRun) => {
|
|
102
|
+
const { fs } = await import('@mikro-orm/core/fs-utils');
|
|
103
|
+
const migration = await fs.dynamicImport(params.path);
|
|
104
|
+
const MigrationClass = Object.values(migration).find(cls => typeof cls === 'function' && typeof cls.constructor === 'function');
|
|
105
|
+
const instance = new MigrationClass(this.driver, this.config);
|
|
106
|
+
await this.runner.run(instance, method, afterRun);
|
|
107
|
+
};
|
|
108
|
+
return {
|
|
109
|
+
name: this.storage.getMigrationName(params.name),
|
|
110
|
+
path: params.path,
|
|
111
|
+
up: afterRun => createMigrationHandler('up', afterRun),
|
|
112
|
+
down: afterRun => createMigrationHandler('down', afterRun),
|
|
113
|
+
};
|
|
232
114
|
}
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
return executedReversed
|
|
241
|
-
.filter(name => set.has(name))
|
|
242
|
-
.map(name => migrationMap.get(name))
|
|
243
|
-
.filter(Boolean);
|
|
115
|
+
initialize(MigrationClass, name) {
|
|
116
|
+
const instance = new MigrationClass(this.driver, this.config);
|
|
117
|
+
return {
|
|
118
|
+
name: this.storage.getMigrationName(name),
|
|
119
|
+
up: afterRun => this.runner.run(instance, 'up', afterRun),
|
|
120
|
+
down: afterRun => this.runner.run(instance, 'down', afterRun),
|
|
121
|
+
};
|
|
244
122
|
}
|
|
245
|
-
|
|
246
|
-
|
|
123
|
+
/**
|
|
124
|
+
* Checks if `src` folder exists, it so, tries to adjust the migrations and seeders paths automatically to use it.
|
|
125
|
+
* If there is a `dist` or `build` folder, it will be used for the JS variant (`path` option), while the `src` folder will be
|
|
126
|
+
* used for the TS variant (`pathTs` option).
|
|
127
|
+
*
|
|
128
|
+
* If the default folder exists (e.g. `/migrations`), the config will respect that, so this auto-detection should not
|
|
129
|
+
* break existing projects, only help with the new ones.
|
|
130
|
+
*/
|
|
131
|
+
detectSourceFolder(fs) {
|
|
132
|
+
const baseDir = this.config.get('baseDir');
|
|
133
|
+
const defaultPath = './migrations';
|
|
134
|
+
if (!fs.pathExists(baseDir + '/src')) {
|
|
135
|
+
this.options.path ??= defaultPath;
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
const exists = fs.pathExists(`${baseDir}/${defaultPath}`);
|
|
139
|
+
const distDir = fs.pathExists(baseDir + '/dist');
|
|
140
|
+
const buildDir = fs.pathExists(baseDir + '/build');
|
|
141
|
+
// if neither `dist` nor `build` exist, we use the `src` folder as it might be a JS project without building, but with `src` folder
|
|
142
|
+
/* v8 ignore next */
|
|
143
|
+
const path = distDir ? './dist' : buildDir ? './build' : './src';
|
|
144
|
+
// only if the user did not provide any values and if the default path does not exist
|
|
145
|
+
if (!this.options.path && !this.options.pathTs && !exists) {
|
|
146
|
+
this.options.path = `${path}/migrations`;
|
|
147
|
+
this.options.pathTs = './src/migrations';
|
|
148
|
+
}
|
|
247
149
|
}
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
return result;
|
|
150
|
+
registerDefaultListeners() {
|
|
151
|
+
/* v8 ignore else */
|
|
152
|
+
if (!this.options.silent) {
|
|
153
|
+
const logger = this.config.getLogger();
|
|
154
|
+
this.on('migrating', event => logger.log('migrator', `Processing '${event.name}'`, { enabled: true }));
|
|
155
|
+
this.on('migrated', event => logger.log('migrator', `Applied '${event.name}'`, { enabled: true }));
|
|
156
|
+
this.on('reverting', event => logger.log('migrator', `Processing '${event.name}'`, { enabled: true }));
|
|
157
|
+
this.on('reverted', event => logger.log('migrator', `Reverted '${event.name}'`, { enabled: true }));
|
|
158
|
+
}
|
|
260
159
|
}
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
160
|
+
async emit(event, data) {
|
|
161
|
+
for (const listener of this.#listeners.get(event) ?? []) {
|
|
162
|
+
await listener(data);
|
|
163
|
+
}
|
|
265
164
|
}
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
165
|
+
async discoverMigrations() {
|
|
166
|
+
if (this.options.migrationsList) {
|
|
167
|
+
return this.options.migrationsList.map(migration => {
|
|
168
|
+
if (typeof migration === 'function') {
|
|
169
|
+
return this.initialize(migration, migration.name);
|
|
170
|
+
}
|
|
171
|
+
return this.initialize(migration.class, migration.name);
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
const { fs } = await import('@mikro-orm/core/fs-utils');
|
|
175
|
+
const pattern = fs.normalizePath(this.absolutePath, this.options.glob);
|
|
176
|
+
const files = fs.glob(pattern).sort();
|
|
177
|
+
return files.map(filePath => this.resolve({
|
|
178
|
+
name: filePath.replace(/\\/g, '/').split('/').pop(),
|
|
179
|
+
path: filePath,
|
|
180
|
+
}));
|
|
275
181
|
}
|
|
276
|
-
|
|
277
|
-
|
|
182
|
+
async executeMigrations(method, options = {}) {
|
|
183
|
+
const all = await this.discoverMigrations();
|
|
184
|
+
const executed = await this.storage.executed();
|
|
185
|
+
const executedSet = new Set(executed);
|
|
186
|
+
let toRun;
|
|
187
|
+
if (method === 'up') {
|
|
188
|
+
toRun = this.filterUp(all, executedSet, options);
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
toRun = this.filterDown(all, executed, options);
|
|
192
|
+
}
|
|
193
|
+
const result = [];
|
|
194
|
+
const eventBefore = method === 'up' ? 'migrating' : 'reverting';
|
|
195
|
+
const eventAfter = method === 'up' ? 'migrated' : 'reverted';
|
|
196
|
+
for (const migration of toRun) {
|
|
197
|
+
const event = { name: migration.name, path: migration.path };
|
|
198
|
+
await this.emit(eventBefore, event);
|
|
199
|
+
// log inside the runner's tx (if any) so a logMigration failure rolls the migration back
|
|
200
|
+
await migration[method](async (tx) => {
|
|
201
|
+
if (method === 'up') {
|
|
202
|
+
await this.storage.logMigration({ name: migration.name }, tx);
|
|
203
|
+
}
|
|
204
|
+
else {
|
|
205
|
+
await this.storage.unlogMigration({ name: migration.name }, tx);
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
await this.emit(eventAfter, event);
|
|
209
|
+
result.push(event);
|
|
210
|
+
}
|
|
211
|
+
return result;
|
|
278
212
|
}
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
213
|
+
filterUp(all, executed, options) {
|
|
214
|
+
let pending = all.filter(m => !executed.has(m.name));
|
|
215
|
+
if (options.migrations) {
|
|
216
|
+
const set = new Set(options.migrations);
|
|
217
|
+
return pending.filter(m => set.has(m.name));
|
|
218
|
+
}
|
|
219
|
+
if (options.from) {
|
|
220
|
+
const idx = all.findIndex(m => m.name === options.from);
|
|
221
|
+
if (idx >= 0) {
|
|
222
|
+
const names = new Set(all.slice(idx + 1).map(m => m.name));
|
|
223
|
+
pending = pending.filter(m => names.has(m.name));
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
if (options.to && typeof options.to === 'string') {
|
|
227
|
+
const idx = all.findIndex(m => m.name === options.to);
|
|
228
|
+
if (idx >= 0) {
|
|
229
|
+
const names = new Set(all.slice(0, idx + 1).map(m => m.name));
|
|
230
|
+
pending = pending.filter(m => names.has(m.name));
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
return pending;
|
|
282
234
|
}
|
|
283
|
-
|
|
284
|
-
|
|
235
|
+
filterDown(all, executed, options) {
|
|
236
|
+
const migrationMap = new Map(all.map(m => [m.name, m]));
|
|
237
|
+
const executedReversed = [...executed].reverse();
|
|
238
|
+
if (options.migrations) {
|
|
239
|
+
const set = new Set(options.migrations);
|
|
240
|
+
return executedReversed
|
|
241
|
+
.filter(name => set.has(name))
|
|
242
|
+
.map(name => migrationMap.get(name))
|
|
243
|
+
.filter(Boolean);
|
|
244
|
+
}
|
|
245
|
+
if (options.to === 0) {
|
|
246
|
+
return executedReversed.map(name => migrationMap.get(name)).filter(Boolean);
|
|
247
|
+
}
|
|
248
|
+
if (options.to) {
|
|
249
|
+
const result = [];
|
|
250
|
+
for (const name of executedReversed) {
|
|
251
|
+
if (name === String(options.to)) {
|
|
252
|
+
break;
|
|
253
|
+
}
|
|
254
|
+
const m = migrationMap.get(name);
|
|
255
|
+
if (m) {
|
|
256
|
+
result.push(m);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
return result;
|
|
260
|
+
}
|
|
261
|
+
// Default: revert last 1
|
|
262
|
+
if (executedReversed.length > 0) {
|
|
263
|
+
const m = migrationMap.get(executedReversed[0]);
|
|
264
|
+
return m ? [m] : [];
|
|
265
|
+
}
|
|
266
|
+
return [];
|
|
285
267
|
}
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
result.to = 0;
|
|
268
|
+
getMigrationFilename(name) {
|
|
269
|
+
name = name.replace(/\.[jt]s$/, '');
|
|
270
|
+
return /^\d{14}$/.exec(name) ? this.options.fileName(name) : name;
|
|
290
271
|
}
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
272
|
+
prefix(options) {
|
|
273
|
+
if (typeof options === 'string' || Array.isArray(options)) {
|
|
274
|
+
return { migrations: Utils.asArray(options).map(name => this.getMigrationFilename(name)) };
|
|
275
|
+
}
|
|
276
|
+
if (!options) {
|
|
277
|
+
return {};
|
|
278
|
+
}
|
|
279
|
+
const result = {};
|
|
280
|
+
if (options.migrations) {
|
|
281
|
+
result.migrations = options.migrations.map(name => this.getMigrationFilename(name));
|
|
282
|
+
}
|
|
283
|
+
if (options.from) {
|
|
284
|
+
result.from = this.getMigrationFilename(String(options.from));
|
|
285
|
+
}
|
|
286
|
+
if (options.to && options.to !== 0) {
|
|
287
|
+
result.to = this.getMigrationFilename(String(options.to));
|
|
288
|
+
}
|
|
289
|
+
else if (options.to === 0) {
|
|
290
|
+
result.to = 0;
|
|
291
|
+
}
|
|
292
|
+
return result;
|
|
297
293
|
}
|
|
298
|
-
|
|
299
|
-
|
|
294
|
+
async runMigrations(method, options) {
|
|
295
|
+
await this.init();
|
|
296
|
+
if (!this.options.transactional || !this.options.allOrNothing) {
|
|
297
|
+
return this.executeMigrations(method, this.prefix(options));
|
|
298
|
+
}
|
|
299
|
+
if (Utils.isObject(options) && options.transaction) {
|
|
300
|
+
return this.runInTransaction(options.transaction, method, options);
|
|
301
|
+
}
|
|
302
|
+
return this.driver.getConnection().transactional(trx => this.runInTransaction(trx, method, options));
|
|
300
303
|
}
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
304
|
+
async runInTransaction(trx, method, options) {
|
|
305
|
+
this.runner.setMasterMigration(trx);
|
|
306
|
+
this.storage.setMasterMigration(trx);
|
|
307
|
+
try {
|
|
308
|
+
return await this.executeMigrations(method, this.prefix(options));
|
|
309
|
+
}
|
|
310
|
+
finally {
|
|
311
|
+
this.runner.unsetMasterMigration();
|
|
312
|
+
this.storage.unsetMasterMigration();
|
|
313
|
+
}
|
|
311
314
|
}
|
|
312
|
-
}
|
|
313
315
|
}
|