@mikro-orm/core 7.0.0-dev.76 → 7.0.0-dev.78

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.
Files changed (61) hide show
  1. package/EntityManager.js +4 -4
  2. package/MikroORM.d.ts +29 -2
  3. package/MikroORM.js +69 -14
  4. package/cache/FileCacheAdapter.d.ts +1 -1
  5. package/cache/FileCacheAdapter.js +6 -4
  6. package/cache/GeneratedCacheAdapter.d.ts +0 -1
  7. package/cache/GeneratedCacheAdapter.js +0 -2
  8. package/cache/index.d.ts +0 -1
  9. package/cache/index.js +0 -1
  10. package/drivers/DatabaseDriver.js +4 -4
  11. package/entity/Collection.js +2 -2
  12. package/entity/EntityAssigner.js +2 -2
  13. package/entity/EntityFactory.js +1 -1
  14. package/entity/EntityLoader.js +4 -4
  15. package/entity/Reference.js +1 -1
  16. package/entity/WrappedEntity.d.ts +2 -2
  17. package/entity/utils.js +1 -1
  18. package/entity/validators.js +1 -1
  19. package/hydration/Hydrator.js +1 -2
  20. package/hydration/ObjectHydrator.js +1 -1
  21. package/metadata/MetadataDiscovery.d.ts +0 -2
  22. package/metadata/MetadataDiscovery.js +7 -45
  23. package/metadata/MetadataProvider.d.ts +9 -0
  24. package/metadata/MetadataProvider.js +29 -2
  25. package/metadata/discover-entities.js +2 -1
  26. package/naming-strategy/AbstractNamingStrategy.js +1 -1
  27. package/not-supported.d.ts +1 -0
  28. package/not-supported.js +2 -1
  29. package/package.json +5 -1
  30. package/platforms/ExceptionConverter.js +1 -1
  31. package/platforms/Platform.js +8 -17
  32. package/serialization/EntitySerializer.js +3 -3
  33. package/serialization/SerializationContext.js +2 -2
  34. package/types/ArrayType.js +1 -1
  35. package/types/BigIntType.js +1 -1
  36. package/types/DecimalType.js +2 -2
  37. package/types/DoubleType.js +1 -1
  38. package/types/TinyIntType.js +1 -1
  39. package/types/Uint8ArrayType.js +1 -1
  40. package/typings.js +3 -3
  41. package/unit-of-work/UnitOfWork.js +1 -1
  42. package/utils/AbstractSchemaGenerator.js +1 -1
  43. package/utils/Configuration.d.ts +4 -24
  44. package/utils/Configuration.js +13 -50
  45. package/utils/ConfigurationLoader.d.ts +1 -13
  46. package/utils/ConfigurationLoader.js +1 -149
  47. package/utils/Cursor.js +1 -1
  48. package/utils/DataloaderUtils.js +2 -2
  49. package/utils/EntityComparator.js +4 -4
  50. package/utils/QueryHelper.js +1 -1
  51. package/utils/RawQueryFragment.js +1 -1
  52. package/utils/Utils.d.ts +0 -16
  53. package/utils/Utils.js +9 -89
  54. package/utils/clone.js +1 -1
  55. package/utils/env-vars.d.ts +3 -0
  56. package/utils/env-vars.js +87 -0
  57. package/utils/fs-utils.d.ts +12 -0
  58. package/utils/fs-utils.js +96 -0
  59. package/utils/index.d.ts +1 -1
  60. package/utils/index.js +1 -1
  61. package/utils/upsert-utils.js +3 -3
package/EntityManager.js CHANGED
@@ -239,7 +239,7 @@ export class EntityManager {
239
239
  if (options.populateWhere === PopulateHint.ALL) {
240
240
  return { where: {}, populateWhere: options.populateWhere };
241
241
  }
242
- /* v8 ignore next 3 */
242
+ /* v8 ignore next */
243
243
  if (options.populateWhere === PopulateHint.INFER) {
244
244
  return { where, populateWhere: options.populateWhere };
245
245
  }
@@ -977,7 +977,7 @@ export class EntityManager {
977
977
  });
978
978
  return this.comparator.matching(entityName, cond, tmp);
979
979
  });
980
- /* v8 ignore next 3 */
980
+ /* v8 ignore next */
981
981
  if (!row) {
982
982
  throw new Error(`Cannot find matching entity for condition ${JSON.stringify(cond)}`);
983
983
  }
@@ -1000,7 +1000,7 @@ export class EntityManager {
1000
1000
  }, {});
1001
1001
  return this.comparator.matching(entityName, cond, pk);
1002
1002
  });
1003
- /* v8 ignore next 3 */
1003
+ /* v8 ignore next */
1004
1004
  if (!row) {
1005
1005
  throw new Error(`Cannot find matching entity for condition ${JSON.stringify(cond)}`);
1006
1006
  }
@@ -1674,7 +1674,7 @@ export class EntityManager {
1674
1674
  }
1675
1675
  if (typeof options.populate !== 'boolean') {
1676
1676
  options.populate = Utils.asArray(options.populate).map(field => {
1677
- /* v8 ignore next 3 */
1677
+ /* v8 ignore next */
1678
1678
  if (typeof field === 'boolean' || field === PopulatePath.ALL) {
1679
1679
  return [{ field: meta.primaryKeys[0], strategy: options.strategy, all: !!field }]; //
1680
1680
  }
package/MikroORM.d.ts CHANGED
@@ -4,8 +4,35 @@ import { MetadataStorage } from './metadata/MetadataStorage.js';
4
4
  import { Configuration, type Options } from './utils/Configuration.js';
5
5
  import type { EntityManager } from './EntityManager.js';
6
6
  import type { AnyEntity, Constructor, EntityClass, EntityMetadata, EntityName, IEntityGenerator, IMigrator, ISeedManager } from './typings.js';
7
+ /** @internal */
8
+ export declare function lookupExtensions(options: Options): Promise<void>;
7
9
  /**
8
- * Helper class for bootstrapping the MikroORM.
10
+ * The main class used to configure and bootstrap the ORM.
11
+ *
12
+ * @example
13
+ * ```ts
14
+ * // import from driver package
15
+ * import { MikroORM, defineEntity, p } from '@mikro-orm/sqlite';
16
+ *
17
+ * const User = defineEntity({
18
+ * name: 'User',
19
+ * properties: {
20
+ * id: p.integer().primary(),
21
+ * name: p.string(),
22
+ * },
23
+ * });
24
+ *
25
+ * const orm = new MikroORM({
26
+ * entities: [User],
27
+ * dbName: 'my.db',
28
+ * });
29
+ * await orm.schema.update();
30
+ *
31
+ * const em = orm.em.fork();
32
+ * const u1 = em.create(User, { name: 'John' });
33
+ * const u2 = em.create(User, { name: 'Ben' });
34
+ * await em.flush();
35
+ * ```
9
36
  */
10
37
  export declare class MikroORM<Driver extends IDatabaseDriver = IDatabaseDriver, EM extends Driver[typeof EntityManagerType] & EntityManager<Driver> = Driver[typeof EntityManagerType] & EntityManager<Driver>, Entities extends (string | EntityClass<AnyEntity> | EntitySchema)[] = (string | EntityClass<AnyEntity> | EntitySchema)[]> {
11
38
  /** The global EntityManager instance. If you are using `RequestContext` helper, it will automatically pick the request specific context under the hood */
@@ -42,7 +69,7 @@ export declare class MikroORM<Driver extends IDatabaseDriver = IDatabaseDriver,
42
69
  */
43
70
  isConnected(): Promise<boolean>;
44
71
  /**
45
- * Checks whether the database connection is active, returns .
72
+ * Checks whether the database connection is active, returns the reason if not.
46
73
  */
47
74
  checkConnection(): Promise<{
48
75
  ok: true;
package/MikroORM.js CHANGED
@@ -1,11 +1,69 @@
1
1
  import { MetadataDiscovery } from './metadata/MetadataDiscovery.js';
2
2
  import { MetadataStorage } from './metadata/MetadataStorage.js';
3
3
  import { Configuration } from './utils/Configuration.js';
4
- import { ConfigurationLoader } from './utils/ConfigurationLoader.js';
4
+ import { loadEnvironmentVars } from './utils/env-vars.js';
5
5
  import { Utils } from './utils/Utils.js';
6
6
  import { colors } from './logging/colors.js';
7
+ async function registerExtension(name, mod, extensions) {
8
+ /* v8 ignore next */
9
+ const resolved = await mod.catch(() => null);
10
+ const module = resolved?.[name];
11
+ /* v8 ignore else */
12
+ if (module) {
13
+ extensions.push(module);
14
+ }
15
+ }
16
+ /** @internal */
17
+ export async function lookupExtensions(options) {
18
+ const extensions = options.extensions ?? [];
19
+ const exists = (name) => extensions.some(ext => ext.name === name);
20
+ if (!exists('SeedManager')) {
21
+ await registerExtension('SeedManager', import('@mikro-orm/seeder' + ''), extensions);
22
+ }
23
+ if (!exists('Migrator')) {
24
+ await registerExtension('Migrator', import('@mikro-orm/migrations' + ''), extensions);
25
+ }
26
+ /* v8 ignore if */
27
+ if (!exists('Migrator')) {
28
+ await registerExtension('Migrator', import('@mikro-orm/migrations-mongodb' + ''), extensions);
29
+ }
30
+ if (!exists('EntityGenerator')) {
31
+ await registerExtension('EntityGenerator', import('@mikro-orm/entity-generator' + ''), extensions);
32
+ }
33
+ options.extensions = extensions;
34
+ const metadataCacheEnabled = options.metadataCache?.enabled || options.metadataProvider?.useCache?.();
35
+ if (metadataCacheEnabled) {
36
+ options.metadataCache ??= {};
37
+ options.metadataCache.adapter ??= await import('@mikro-orm/core/fs-utils').then(m => m.FileCacheAdapter);
38
+ }
39
+ }
7
40
  /**
8
- * Helper class for bootstrapping the MikroORM.
41
+ * The main class used to configure and bootstrap the ORM.
42
+ *
43
+ * @example
44
+ * ```ts
45
+ * // import from driver package
46
+ * import { MikroORM, defineEntity, p } from '@mikro-orm/sqlite';
47
+ *
48
+ * const User = defineEntity({
49
+ * name: 'User',
50
+ * properties: {
51
+ * id: p.integer().primary(),
52
+ * name: p.string(),
53
+ * },
54
+ * });
55
+ *
56
+ * const orm = new MikroORM({
57
+ * entities: [User],
58
+ * dbName: 'my.db',
59
+ * });
60
+ * await orm.schema.update();
61
+ *
62
+ * const em = orm.em.fork();
63
+ * const u1 = em.create(User, { name: 'John' });
64
+ * const u2 = em.create(User, { name: 'Ben' });
65
+ * await em.flush();
66
+ * ```
9
67
  */
10
68
  export class MikroORM {
11
69
  /** The global EntityManager instance. If you are using `RequestContext` helper, it will automatically pick the request specific context under the hood */
@@ -20,12 +78,14 @@ export class MikroORM {
20
78
  * If you omit the `options` parameter, your CLI config will be used.
21
79
  */
22
80
  static async init(options) {
23
- /* v8 ignore next 3 */
81
+ /* v8 ignore next */
24
82
  if (!options) {
25
83
  throw new Error(`options parameter is required`);
26
84
  }
85
+ options = { ...options };
27
86
  options.discovery ??= {};
28
87
  options.discovery.skipSyncDiscovery ??= true;
88
+ await lookupExtensions(options);
29
89
  const orm = new this(options);
30
90
  const preferTs = orm.config.get('preferTs', Utils.detectTypeScriptSupport());
31
91
  orm.metadata = await orm.discovery.discover(preferTs);
@@ -39,14 +99,13 @@ export class MikroORM {
39
99
  * - no support for folder based discovery
40
100
  */
41
101
  constructor(options) {
42
- const env = ConfigurationLoader.loadEnvironmentVars();
43
- const coreVersion = ConfigurationLoader.checkPackageVersion();
102
+ const env = loadEnvironmentVars();
44
103
  options = Utils.merge(options, env);
45
104
  this.config = new Configuration(options);
46
105
  const discovery = this.config.get('discovery');
47
106
  this.driver = this.config.getDriver();
48
107
  this.logger = this.config.getLogger();
49
- this.logger.log('info', `MikroORM version: ${colors.green(coreVersion)}`);
108
+ this.logger.log('info', `MikroORM version: ${colors.green(Utils.getORMVersion())}`);
50
109
  this.discovery = new MetadataDiscovery(new MetadataStorage(), this.driver.getPlatform(), this.config);
51
110
  this.driver.getPlatform().init(this);
52
111
  for (const extension of this.config.get('extensions')) {
@@ -68,7 +127,7 @@ export class MikroORM {
68
127
  * Reconnects, possibly to a different database.
69
128
  */
70
129
  async reconnect(options = {}) {
71
- /* v8 ignore next 3 */
130
+ /* v8 ignore next */
72
131
  for (const key of Utils.keys(options)) {
73
132
  this.config.set(key, options[key]);
74
133
  }
@@ -81,7 +140,7 @@ export class MikroORM {
81
140
  return this.driver.getConnection().isConnected();
82
141
  }
83
142
  /**
84
- * Checks whether the database connection is active, returns .
143
+ * Checks whether the database connection is active, returns the reason if not.
85
144
  */
86
145
  async checkConnection() {
87
146
  return this.driver.getConnection().checkConnection();
@@ -91,12 +150,8 @@ export class MikroORM {
91
150
  */
92
151
  async close(force = false) {
93
152
  await this.driver.close(force);
94
- if (this.config.getMetadataCacheAdapter()?.close) {
95
- await this.config.getMetadataCacheAdapter().close();
96
- }
97
- if (this.config.getResultCacheAdapter()?.close) {
98
- await this.config.getResultCacheAdapter().close();
99
- }
153
+ await this.config.getMetadataCacheAdapter().close?.();
154
+ await this.config.getResultCacheAdapter().close?.();
100
155
  }
101
156
  /**
102
157
  * Gets the `MetadataStorage` (without parameters) or `EntityMetadata` instance when provided with the `entityName` parameter.
@@ -8,7 +8,7 @@ export declare class FileCacheAdapter implements SyncCacheAdapter {
8
8
  constructor(options: {
9
9
  cacheDir: string;
10
10
  combined?: boolean | string;
11
- }, baseDir: string, pretty?: boolean);
11
+ } | undefined, baseDir: string, pretty?: boolean);
12
12
  /**
13
13
  * @inheritDoc
14
14
  */
@@ -1,4 +1,5 @@
1
1
  import { existsSync, readFileSync, writeFileSync, unlinkSync } from 'node:fs';
2
+ import { fs } from '../utils/fs-utils.js';
2
3
  import { Utils } from '../utils/Utils.js';
3
4
  export class FileCacheAdapter {
4
5
  options;
@@ -6,10 +7,11 @@ export class FileCacheAdapter {
6
7
  pretty;
7
8
  VERSION = Utils.getORMVersion();
8
9
  cache = {};
9
- constructor(options, baseDir, pretty = false) {
10
+ constructor(options = {}, baseDir, pretty = false) {
10
11
  this.options = options;
11
12
  this.baseDir = baseDir;
12
13
  this.pretty = pretty;
14
+ this.options.cacheDir ??= process.cwd() + '/temp';
13
15
  }
14
16
  /**
15
17
  * @inheritDoc
@@ -19,7 +21,7 @@ export class FileCacheAdapter {
19
21
  if (!existsSync(path)) {
20
22
  return null;
21
23
  }
22
- const payload = Utils.readJSONSync(path);
24
+ const payload = fs.readJSONSync(path);
23
25
  const hash = this.getHash(payload.origin);
24
26
  if (!hash || payload.hash !== hash) {
25
27
  return null;
@@ -50,7 +52,7 @@ export class FileCacheAdapter {
50
52
  */
51
53
  clear() {
52
54
  const path = this.path('*');
53
- const files = Utils.glob(path);
55
+ const files = fs.glob(path);
54
56
  files.forEach(file => unlinkSync(file));
55
57
  this.cache = {};
56
58
  }
@@ -67,7 +69,7 @@ export class FileCacheAdapter {
67
69
  return path;
68
70
  }
69
71
  path(name) {
70
- Utils.ensureDir(this.options.cacheDir);
72
+ fs.ensureDir(this.options.cacheDir);
71
73
  return `${this.options.cacheDir}/${name}.json`;
72
74
  }
73
75
  getHash(origin) {
@@ -1,7 +1,6 @@
1
1
  import type { CacheAdapter } from './CacheAdapter.js';
2
2
  import type { Dictionary } from '../typings.js';
3
3
  export declare class GeneratedCacheAdapter implements CacheAdapter {
4
- private readonly options;
5
4
  private readonly data;
6
5
  constructor(options: {
7
6
  data: Dictionary;
@@ -1,8 +1,6 @@
1
1
  export class GeneratedCacheAdapter {
2
- options;
3
2
  data = new Map();
4
3
  constructor(options) {
5
- this.options = options;
6
4
  this.data = new Map(Object.entries(options.data));
7
5
  }
8
6
  /**
package/cache/index.d.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  export * from './CacheAdapter.js';
2
2
  export * from './NullCacheAdapter.js';
3
- export * from './FileCacheAdapter.js';
4
3
  export * from './MemoryCacheAdapter.js';
5
4
  export * from './GeneratedCacheAdapter.js';
package/cache/index.js CHANGED
@@ -1,5 +1,4 @@
1
1
  export * from './CacheAdapter.js';
2
2
  export * from './NullCacheAdapter.js';
3
- export * from './FileCacheAdapter.js';
4
3
  export * from './MemoryCacheAdapter.js';
5
4
  export * from './GeneratedCacheAdapter.js';
@@ -31,11 +31,11 @@ export class DatabaseDriver {
31
31
  const EntityManagerClass = this.config.get('entityManager', EntityManager);
32
32
  return new EntityManagerClass(this.config, this, this.metadata, useContext);
33
33
  }
34
- /* v8 ignore next 3 */
34
+ /* v8 ignore next */
35
35
  async findVirtual(entityName, where, options) {
36
36
  throw new Error(`Virtual entities are not supported by ${this.constructor.name} driver.`);
37
37
  }
38
- /* v8 ignore next 3 */
38
+ /* v8 ignore next */
39
39
  async countVirtual(entityName, where, options) {
40
40
  throw new Error(`Counting virtual entities is not supported by ${this.constructor.name} driver.`);
41
41
  }
@@ -53,7 +53,7 @@ export class DatabaseDriver {
53
53
  }
54
54
  continue;
55
55
  }
56
- /* v8 ignore next 3 */
56
+ /* v8 ignore next */
57
57
  const pk = coll.property.targetMeta.primaryKeys[0];
58
58
  const data = { [coll.property.name]: coll.getIdentifiers(pk) };
59
59
  await this.nativeUpdate(coll.owner.constructor.name, helper(coll.owner).getPrimaryKey(), data, options);
@@ -253,7 +253,7 @@ export class DatabaseDriver {
253
253
  return data;
254
254
  }
255
255
  inlineEmbeddables(meta, data, where) {
256
- /* v8 ignore next 3 */
256
+ /* v8 ignore next */
257
257
  if (data == null) {
258
258
  return;
259
259
  }
@@ -18,7 +18,7 @@ export class Collection {
18
18
  _populated;
19
19
  constructor(owner, items, initialized = true) {
20
20
  this.owner = owner;
21
- /* v8 ignore next 5 */
21
+ /* v8 ignore next */
22
22
  if (items) {
23
23
  let i = 0;
24
24
  this.items = new Set(items);
@@ -619,7 +619,7 @@ export class Collection {
619
619
  get property() {
620
620
  if (!this._property) {
621
621
  const meta = wrap(this.owner, true).__meta;
622
- /* v8 ignore next 3 */
622
+ /* v8 ignore next */
623
623
  if (!meta) {
624
624
  throw MetadataError.fromUnknownEntity(this.owner.constructor.name, 'Collection.property getter, maybe you just forgot to initialize the ORM?');
625
625
  }
@@ -120,7 +120,7 @@ export class EntityAssigner {
120
120
  }
121
121
  const meta2 = helper(ref).__meta;
122
122
  const prop2 = meta2.properties[prop.inversedBy || prop.mappedBy];
123
- /* v8 ignore next 7 */
123
+ /* v8 ignore next */
124
124
  if (prop2 && !ref[prop2.name]) {
125
125
  if (Reference.isReference(ref)) {
126
126
  ref.unwrap()[prop2.name] = Reference.wrapReference(entity, prop2);
@@ -173,7 +173,7 @@ export class EntityAssigner {
173
173
  }
174
174
  return this.createCollectionItem(item, em, prop, invalid, options);
175
175
  }
176
- /* v8 ignore next 3 */
176
+ /* v8 ignore next */
177
177
  if (options.updateNestedEntities && !options.updateByPrimaryKey && collection[idx] && helper(collection[idx])?.isInitialized()) {
178
178
  return EntityAssigner.assign(collection[idx], item, options);
179
179
  }
@@ -323,7 +323,7 @@ export class EntityFactory {
323
323
  return Reference.wrapReference(target, prop);
324
324
  }
325
325
  if (prop?.kind === ReferenceKind.EMBEDDED && value) {
326
- /* v8 ignore next 3 */
326
+ /* v8 ignore next */
327
327
  if (Utils.isEntity(value)) {
328
328
  return value;
329
329
  }
@@ -41,7 +41,7 @@ export class EntityLoader {
41
41
  }
42
42
  populate = this.normalizePopulate(entityName, populate, options.strategy, options.lookup);
43
43
  const invalid = populate.find(({ field }) => !this.em.canPopulate(entityName, field));
44
- /* v8 ignore next 3 */
44
+ /* v8 ignore next */
45
45
  if (options.validate && invalid) {
46
46
  throw ValidationError.invalidPropertyName(entityName, invalid.field);
47
47
  }
@@ -463,7 +463,7 @@ export class EntityLoader {
463
463
  const parts = f.toString().split('.');
464
464
  const propName = parts.shift();
465
465
  const childPropName = parts.join('.');
466
- /* v8 ignore next 3 */
466
+ /* v8 ignore next */
467
467
  if (propName === prop.name) {
468
468
  ret.push(childPropName);
469
469
  }
@@ -514,7 +514,7 @@ export class EntityLoader {
514
514
  return wrapped.__loadedProperties.has(field);
515
515
  }
516
516
  const [f, ...r] = field.split('.');
517
- /* v8 ignore next 3 */
517
+ /* v8 ignore next */
518
518
  if (!wrapped.__loadedProperties.has(f) || !wrapped.__meta.properties[f]?.targetMeta) {
519
519
  return false;
520
520
  }
@@ -547,7 +547,7 @@ export class EntityLoader {
547
547
  .map(e => Reference.unwrapReference(e[field]));
548
548
  }
549
549
  filterByReferences(entities, field, refresh) {
550
- /* v8 ignore next 3 */
550
+ /* v8 ignore next */
551
551
  if (refresh) {
552
552
  return entities;
553
553
  }
@@ -213,8 +213,8 @@ export class ScalarReference {
213
213
  isInitialized() {
214
214
  return this.initialized;
215
215
  }
216
- /* v8 ignore next 4 */
217
216
  /** @ignore */
217
+ /* v8 ignore next */
218
218
  [inspect.custom]() {
219
219
  return this.initialized ? `Ref<${inspect(this.value)}>` : `Ref<?>`;
220
220
  }
@@ -59,8 +59,8 @@ export declare class WrappedEntity<Entity extends object> {
59
59
  setPrimaryKey(id: Primary<Entity> | null): void;
60
60
  getSerializedPrimaryKey(): string;
61
61
  get __meta(): EntityMetadata<Entity>;
62
- get __platform(): import("../index.js").Platform;
63
- get __config(): import("../index.js").Configuration<import("../drivers/IDatabaseDriver.js").IDatabaseDriver<import("../index.js").Connection>, EntityManager<import("../drivers/IDatabaseDriver.js").IDatabaseDriver<import("../index.js").Connection>>>;
62
+ get __platform(): import("@mikro-orm/knex").Platform;
63
+ get __config(): import("@mikro-orm/knex").Configuration<import("../drivers/IDatabaseDriver.js").IDatabaseDriver<import("@mikro-orm/knex").Connection>, EntityManager<import("../drivers/IDatabaseDriver.js").IDatabaseDriver<import("@mikro-orm/knex").Connection>>>;
64
64
  get __primaryKeys(): Primary<Entity>[];
65
65
  /** @ignore */
66
66
  [inspect.custom](): string;
package/entity/utils.js CHANGED
@@ -21,7 +21,7 @@ export function expandDotPaths(meta, populate, normalized = false) {
21
21
  if (typeof field === 'string') {
22
22
  return { field };
23
23
  }
24
- /* v8 ignore next 3 */
24
+ /* v8 ignore next */
25
25
  return typeof field === 'boolean' || field.field === PopulatePath.ALL
26
26
  ? { all: !!field, field: meta.primaryKeys[0] }
27
27
  : field;
@@ -11,7 +11,7 @@ export function validateProperty(prop, givenValue, entity) {
11
11
  const propName = prop.embedded ? prop.name.replace(/~/g, '.') : prop.name;
12
12
  const givenType = Utils.getObjectType(givenValue);
13
13
  if (prop.enum && prop.items) {
14
- /* v8 ignore next 3 */
14
+ /* v8 ignore next */
15
15
  if (!prop.items.some(it => it === givenValue)) {
16
16
  throw ValidationError.fromWrongPropertyType(entity, propName, expectedType, givenType, givenValue);
17
17
  }
@@ -1,4 +1,4 @@
1
- /* v8 ignore start */
1
+ /* v8 ignore next */
2
2
  export class Hydrator {
3
3
  metadata;
4
4
  platform;
@@ -45,4 +45,3 @@ export class Hydrator {
45
45
  entity[prop.name] = data[prop.name];
46
46
  }
47
47
  }
48
- /* v8 ignore stop */
@@ -51,7 +51,7 @@ export class ObjectHydrator extends Hydrator {
51
51
  context.set('Reference', Reference);
52
52
  const registerCustomType = (prop, convertorKey, method, context) => {
53
53
  context.set(`${method}_${convertorKey}`, (val) => {
54
- /* v8 ignore next 3 */
54
+ /* v8 ignore next */
55
55
  if (RawQueryFragment.isKnownFragment(val)) {
56
56
  return val;
57
57
  }
@@ -9,7 +9,6 @@ export declare class MetadataDiscovery {
9
9
  private readonly config;
10
10
  private readonly namingStrategy;
11
11
  private readonly metadataProvider;
12
- private readonly cache;
13
12
  private readonly logger;
14
13
  private readonly schemaHelper;
15
14
  private readonly validator;
@@ -29,7 +28,6 @@ export declare class MetadataDiscovery {
29
28
  private getSchema;
30
29
  private getRootEntity;
31
30
  private discoverEntity;
32
- private saveToCache;
33
31
  private initNullability;
34
32
  private applyNamingStrategy;
35
33
  private initOwnColumns;
@@ -1,4 +1,3 @@
1
- import { extname } from 'node:path';
2
1
  import { EntityMetadata, } from '../typings.js';
3
2
  import { Utils } from '../utils/Utils.js';
4
3
  import { MetadataValidator } from './MetadataValidator.js';
@@ -15,7 +14,6 @@ export class MetadataDiscovery {
15
14
  config;
16
15
  namingStrategy;
17
16
  metadataProvider;
18
- cache;
19
17
  logger;
20
18
  schemaHelper;
21
19
  validator = new MetadataValidator();
@@ -26,7 +24,6 @@ export class MetadataDiscovery {
26
24
  this.config = config;
27
25
  this.namingStrategy = this.config.getNamingStrategy();
28
26
  this.metadataProvider = this.config.getMetadataProvider();
29
- this.cache = this.config.getMetadataCacheAdapter();
30
27
  this.logger = this.config.getLogger();
31
28
  this.schemaHelper = this.platform.getSchemaHelper();
32
29
  }
@@ -145,11 +142,7 @@ export class MetadataDiscovery {
145
142
  discovered.push(...this.processEntity(meta));
146
143
  }
147
144
  discovered.forEach(meta => meta.sync(true));
148
- const combinedCachePath = this.cache.combine?.();
149
- // override the path in the options, so we can log it from the CLI in `cache:generate` command
150
- if (combinedCachePath) {
151
- this.config.get('metadataCache').combined = combinedCachePath;
152
- }
145
+ this.metadataProvider.combineCache();
153
146
  return discovered.map(meta => {
154
147
  meta = this.metadata.get(meta.className);
155
148
  meta.sync(true);
@@ -224,7 +217,7 @@ export class MetadataDiscovery {
224
217
  if (typeof parent === 'function' && parent.name && !this.metadata.has(parent.name)) {
225
218
  this.discoverReferences([parent], false);
226
219
  }
227
- /* v8 ignore next 3 */
220
+ /* v8 ignore next */
228
221
  if (!meta.class) {
229
222
  continue;
230
223
  }
@@ -287,11 +280,9 @@ export class MetadataDiscovery {
287
280
  this.logger.log('discovery', `- processing entity ${colors.cyan(meta.className)}${colors.grey(path ? ` (${path})` : '')}`);
288
281
  const root = this.getRootEntity(meta);
289
282
  schema.meta.path = Utils.relativePath(meta.path, this.config.get('baseDir'));
290
- const cache = this.metadataProvider.useCache() && meta.path && this.cache.get(meta.className + extname(meta.path));
283
+ const cache = this.metadataProvider.getCachedMetadata(meta, root);
291
284
  if (cache) {
292
285
  this.logger.log('discovery', `- using cached metadata for entity ${colors.cyan(meta.className)}`);
293
- this.metadataProvider.loadFromCache(meta, cache);
294
- meta.root = root;
295
286
  this.discovered.push(meta);
296
287
  return;
297
288
  }
@@ -305,39 +296,10 @@ export class MetadataDiscovery {
305
296
  const entityName = root.discriminatorColumn ? root.name : meta.name;
306
297
  meta.collection = this.namingStrategy.classToTableName(entityName);
307
298
  }
308
- delete meta.root; // to allow caching (as root can contain cycles)
309
- this.saveToCache(meta);
299
+ this.metadataProvider.saveToCache(meta);
310
300
  meta.root = root;
311
301
  this.discovered.push(meta);
312
302
  }
313
- saveToCache(meta) {
314
- if (!this.metadataProvider.useCache()) {
315
- return;
316
- }
317
- const copy = Utils.copy(meta, false);
318
- for (const prop of copy.props) {
319
- if (Type.isMappedType(prop.type)) {
320
- Reflect.deleteProperty(prop, 'type');
321
- Reflect.deleteProperty(prop, 'customType');
322
- }
323
- if (prop.default) {
324
- const raw = RawQueryFragment.getKnownFragment(prop.default);
325
- if (raw) {
326
- prop.defaultRaw ??= this.platform.formatQuery(raw.sql, raw.params);
327
- Reflect.deleteProperty(prop, 'default');
328
- }
329
- }
330
- Reflect.deleteProperty(prop, 'targetMeta');
331
- }
332
- [
333
- 'prototype', 'props', 'referencingProperties', 'propertyOrder', 'relations',
334
- 'concurrencyCheckKeys', 'checks',
335
- ].forEach(key => delete copy[key]);
336
- // base entity without properties might not have path, but nothing to cache there
337
- if (meta.path) {
338
- this.cache.set(meta.className + extname(meta.path), copy, meta.path);
339
- }
340
- }
341
303
  initNullability(prop) {
342
304
  if (prop.kind === ReferenceKind.ONE_TO_ONE) {
343
305
  return Utils.defaultValue(prop, 'nullable', prop.optional || !prop.owner);
@@ -375,7 +337,7 @@ export class MetadataDiscovery {
375
337
  if (prop.joinColumns.length !== prop.columnTypes.length) {
376
338
  prop.columnTypes = prop.joinColumns.flatMap(field => {
377
339
  const matched = meta.props.find(p => p.fieldNames?.includes(field));
378
- /* v8 ignore next 3 */
340
+ /* v8 ignore next */
379
341
  if (!matched) {
380
342
  throw MetadataError.fromWrongForeignKey(meta, prop, 'columnTypes');
381
343
  }
@@ -538,7 +500,7 @@ export class MetadataDiscovery {
538
500
  }
539
501
  else if (fks.length >= 2) {
540
502
  [first, second] = fks;
541
- /* v8 ignore next 3 */
503
+ /* v8 ignore next */
542
504
  }
543
505
  else {
544
506
  return [];
@@ -1016,7 +978,7 @@ export class MetadataDiscovery {
1016
978
  if (typeof prop.defaultRaw !== 'undefined') {
1017
979
  return prop.defaultRaw;
1018
980
  }
1019
- /* v8 ignore next 3 */
981
+ /* v8 ignore next */
1020
982
  if (prop.default != null) {
1021
983
  return '' + this.platform.quoteVersionValue(prop.default, prop);
1022
984
  }
@@ -1,13 +1,22 @@
1
1
  import type { EntityMetadata } from '../typings.js';
2
2
  import type { Logger } from '../logging/Logger.js';
3
+ import type { SyncCacheAdapter } from '../cache/CacheAdapter.js';
4
+ import type { Platform } from '../platforms/Platform.js';
3
5
  export interface IConfiguration {
4
6
  get(key: string, defaultValue?: any): any;
5
7
  getLogger(): Logger;
8
+ getMetadataCacheAdapter(): SyncCacheAdapter;
9
+ getPlatform(): Platform;
6
10
  }
7
11
  export declare class MetadataProvider {
8
12
  protected readonly config: IConfiguration;
9
13
  constructor(config: IConfiguration);
10
14
  loadEntityMetadata(meta: EntityMetadata): void;
11
15
  loadFromCache(meta: EntityMetadata, cache: EntityMetadata): void;
16
+ static useCache(): boolean;
12
17
  useCache(): boolean;
18
+ saveToCache(meta: EntityMetadata): void;
19
+ getCachedMetadata<T>(meta: Pick<EntityMetadata<T>, 'className' | 'path' | 'root'>, root: EntityMetadata<T>): EntityMetadata<T> | undefined;
20
+ combineCache(): void;
21
+ getCacheKey(meta: Pick<EntityMetadata, 'className' | 'path'>): string;
13
22
  }