@tsnx/mikro-orm 1.1.0 → 1.2.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.
@@ -0,0 +1,9 @@
1
+ import { Type } from '@mikro-orm/core';
2
+ import type { IValueConverter } from '@tsnx/data';
3
+ export type ValueConverterTypeConstructor<TModel, TProvider = string> = new () => Type<TModel, TProvider>;
4
+ /**
5
+ * Creates a MikroORM custom Type class from a TSNX IValueConverter,
6
+ * enabling transparent mapping between domain Value Objects and database primitives.
7
+ */
8
+ export declare function createValueConverterType<TModel, TProvider = string>(typeName: string, converter: IValueConverter<TModel, TProvider>, columnType?: string): ValueConverterTypeConstructor<TModel, TProvider>;
9
+ //# sourceMappingURL=value-converter-type.d.ts.map
@@ -0,0 +1,25 @@
1
+ import { Type } from '@mikro-orm/core';
2
+ /**
3
+ * Creates a MikroORM custom Type class from a TSNX IValueConverter,
4
+ * enabling transparent mapping between domain Value Objects and database primitives.
5
+ */
6
+ export function createValueConverterType(typeName, converter, columnType = 'text') {
7
+ class ConvertedType extends Type {
8
+ convertToDatabaseValue(value) {
9
+ if (value === null || value === undefined)
10
+ return value;
11
+ return converter.convertToDatabase(value);
12
+ }
13
+ convertToJSValue(value) {
14
+ if (value === null || value === undefined)
15
+ return value;
16
+ return converter.convertToModel(value);
17
+ }
18
+ getColumnType() {
19
+ return columnType;
20
+ }
21
+ }
22
+ Object.defineProperty(ConvertedType, 'name', { value: typeName });
23
+ return ConvertedType;
24
+ }
25
+ //# sourceMappingURL=value-converter-type.js.map
@@ -1,5 +1,5 @@
1
1
  import type { IServiceCollection, Constructor, InjectionToken } from '@tsnx/hosting-abstractions';
2
- import { type EntityConstructor } from '@tsnx/data';
2
+ import { type EntityConstructor, type IDbCommandInterceptor } from '@tsnx/data';
3
3
  import { MikroDbContext } from '../context/mikro-db-context.js';
4
4
  import { type MikroOrmSource } from '../lifetime/mikro-lifetime-service.js';
5
5
  import { MikroDbSet } from '../repository/mikro-repository.js';
@@ -9,6 +9,7 @@ export interface AddMikroOrmOptions<TContext extends MikroDbContext = MikroDbCon
9
9
  ensureCreated?: boolean;
10
10
  enableLogging?: boolean;
11
11
  enableSensitiveDataLogging?: boolean;
12
+ interceptors?: IDbCommandInterceptor[];
12
13
  connectionString?: string;
13
14
  }
14
15
  /**
@@ -29,6 +29,7 @@ export function addMikroOrm(services, source, optionsOrContext) {
29
29
  ensureCreated: optionsOrContext.ensureCreated,
30
30
  enableLogging: optionsOrContext.enableLogging,
31
31
  enableSensitiveDataLogging: optionsOrContext.enableSensitiveDataLogging,
32
+ interceptors: optionsOrContext.interceptors,
32
33
  connectionString: optionsOrContext.connectionString,
33
34
  };
34
35
  }
package/dist/index.d.ts CHANGED
@@ -4,6 +4,7 @@ export * from './context/mikro-db-context-factory.js';
4
4
  export * from './context/mikro-database-facade.js';
5
5
  export * from './context/mikro-transaction.js';
6
6
  export * from './repository/mikro-repository.js';
7
+ export * from './converters/value-converter-type.js';
7
8
  export * from './lifetime/mikro-lifetime-service.js';
8
9
  export * from './extensions/service-collection-extensions.js';
9
10
  //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -7,6 +7,8 @@ export * from './context/mikro-database-facade.js';
7
7
  export * from './context/mikro-transaction.js';
8
8
  // Repositories
9
9
  export * from './repository/mikro-repository.js';
10
+ // Converters (ValueConverter)
11
+ export * from './converters/value-converter-type.js';
10
12
  // Host Service & Types
11
13
  export * from './lifetime/mikro-lifetime-service.js';
12
14
  // DI Extensions
@@ -35,21 +35,45 @@ export class MikroHostService {
35
35
  }
36
36
  else {
37
37
  const config = { ...this.source };
38
- if (this.options?.enableSensitiveDataLogging) {
39
- config.debug = true;
38
+ this._orm = await MikroORM.init(config);
39
+ }
40
+ }
41
+ // 2. Attach query interceptors & debug logging via ORM logger
42
+ if (this.options?.interceptors?.length) {
43
+ const interceptors = this.options.interceptors;
44
+ const logger = this._orm.config.getLogger();
45
+ if (typeof logger.setDebugMode === 'function') {
46
+ logger.setDebugMode(true);
47
+ }
48
+ const originalWriter = typeof logger.writer === 'function' ? logger.writer : null;
49
+ logger.writer = (message) => {
50
+ const context = { command: message, startTime: Date.now() };
51
+ for (const interceptor of interceptors) {
52
+ interceptor.afterExecute?.(context);
40
53
  }
41
- else if (this.options?.enableLogging !== undefined) {
42
- config.debug = Boolean(this.options.enableLogging);
54
+ if (this.options?.enableLogging && originalWriter) {
55
+ originalWriter(message);
43
56
  }
44
- this._orm = await MikroORM.init(config);
57
+ };
58
+ }
59
+ else if (this.options?.enableSensitiveDataLogging) {
60
+ const logger = this._orm.config.getLogger();
61
+ if (typeof logger.setDebugMode === 'function') {
62
+ logger.setDebugMode(true);
63
+ }
64
+ }
65
+ else if (this.options?.enableLogging !== undefined) {
66
+ const logger = this._orm.config.getLogger();
67
+ if (typeof logger.setDebugMode === 'function') {
68
+ logger.setDebugMode(Boolean(this.options.enableLogging));
45
69
  }
46
70
  }
47
- // 2. Verify / ensure connection
71
+ // 3. Verify / ensure connection
48
72
  const isConnected = await this._orm.isConnected();
49
73
  if (!isConnected) {
50
74
  await this._orm.connect();
51
75
  }
52
- // 3. Auto-migration or schema creation if configured
76
+ // 4. Auto-migration or schema creation if configured
53
77
  if (this.options?.autoMigrate && this._orm.migrator) {
54
78
  await this._orm.migrator.up();
55
79
  }
@@ -13,6 +13,14 @@ export declare class MikroDbSet<TEntity extends object, TId = unknown> implement
13
13
  addMany(entities: TEntity[]): void;
14
14
  remove(entity: TEntity): void;
15
15
  removeMany(entities: TEntity[]): void;
16
+ /**
17
+ * Executes a bulk update directly in the database without loading entities into memory.
18
+ */
19
+ executeUpdate(filter: FilterQuery<TEntity>, data: Partial<TEntity> | Record<string, any>): Promise<number>;
20
+ /**
21
+ * Executes a bulk delete directly in the database without loading entities into memory.
22
+ */
23
+ executeDelete(filter: FilterQuery<TEntity>): Promise<number>;
16
24
  private mapOptions;
17
25
  }
18
26
  //# sourceMappingURL=mikro-repository.d.ts.map
@@ -35,6 +35,18 @@ export class MikroDbSet {
35
35
  this.em.remove(entity);
36
36
  }
37
37
  }
38
+ /**
39
+ * Executes a bulk update directly in the database without loading entities into memory.
40
+ */
41
+ async executeUpdate(filter, data) {
42
+ return await this.em.nativeUpdate(this.entityType, (filter ?? {}), data);
43
+ }
44
+ /**
45
+ * Executes a bulk delete directly in the database without loading entities into memory.
46
+ */
47
+ async executeDelete(filter) {
48
+ return await this.em.nativeDelete(this.entityType, (filter ?? {}));
49
+ }
38
50
  mapOptions(options) {
39
51
  if (!options)
40
52
  return undefined;
@@ -51,6 +63,8 @@ export class MikroDbSet {
51
63
  mapped.fields = options.fields;
52
64
  if (options.asNoTracking)
53
65
  mapped.disableIdentityMap = true;
66
+ if (options.cache !== undefined)
67
+ mapped.cache = options.cache;
54
68
  return mapped;
55
69
  }
56
70
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tsnx/mikro-orm",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "MikroORM provider adapter for TSNX Data - Scoped EntityManager, MikroDbContext, and Hosted Service integration",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -27,7 +27,7 @@
27
27
  "access": "public"
28
28
  },
29
29
  "dependencies": {
30
- "@tsnx/data": "1.1.0",
30
+ "@tsnx/data": "1.2.0",
31
31
  "@tsnx/hosting-abstractions": "^1.1.0"
32
32
  },
33
33
  "peerDependencies": {