Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
…4799) ### `onMetadata` hook Sometimes you might want to alter some behavior of the ORM on metadata level. You can use the `onMetadata` hook to modify the metadata. Let's say you want to use your entities with different drivers, and you want to use some driver specific feature. Using the `onMetadata` hook, you can modify the metadata dynamically to fit the drivers requirements. The hook will be executed before the internal process of filling defaults, so you can think of it as modifying the property options in your entity definitions, they will be respected e.g. when inferring the column type. > The hook can be async, but it will be awaited only if you use the async `MikroORM.init()` method, not with the `MikroORM.initSync()`. ```ts import { EntityMetadata, MikroORM, Platform } from '@mikro-orm/sqlite'; const orm = await MikroORM.init({ // ... discovery: { onMetadata(meta: EntityMetadata, platform: Platform) { // sqlite driver does not support schemas delete meta.schema; }, }, }); ``` Alternatively, you can also use the `afterDiscovered` hook, which is fired after the discovery process ends. You can access all the metadata there, and add or remove them as you wish. ```ts import { EntityMetadata, MikroORM, Platform } from '@mikro-orm/sqlite'; const orm = await MikroORM.init({ // ... discovery: { afterDiscovered(storage: MetadataStorage) { // ignore FooBar entity in schema generator storage.reset('FooBar'); }, }, }); ```
- Loading branch information
Showing
7 changed files
with
190 additions
and
24 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
16 changes: 16 additions & 0 deletions
16
tests/features/multiple-schemas/__snapshots__/discovery-hooks.test.ts.snap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
// Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
||
exports[`discovery hooks 1`] = ` | ||
"pragma foreign_keys = off; | ||
create table \`person_2\` (\`id\` integer not null primary key autoincrement, \`name\` text not null, \`version\` integer not null default 1); | ||
create table \`phone_2\` (\`id\` integer not null primary key autoincrement, \`number\` text not null, \`version\` integer not null default 1); | ||
create table \`person_phone\` (\`person_id\` integer not null, \`phone_id\` integer not null, constraint \`person_phone_person_id_foreign\` foreign key(\`person_id\`) references \`person_2\`(\`id\`) on delete cascade on update cascade, constraint \`person_phone_phone_id_foreign\` foreign key(\`phone_id\`) references \`phone_2\`(\`id\`) on delete cascade on update cascade, primary key (\`person_id\`, \`phone_id\`)); | ||
create index \`person_phone_person_id_index\` on \`person_phone\` (\`person_id\`); | ||
create index \`person_phone_phone_id_index\` on \`person_phone\` (\`phone_id\`); | ||
pragma foreign_keys = on; | ||
" | ||
`; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
import { Collection, Entity, ManyToMany, MetadataStorage, PrimaryKey, Property, ReferenceKind } from '@mikro-orm/core'; | ||
import { MikroORM } from '@mikro-orm/better-sqlite'; | ||
|
||
@Entity({ schema: 'staff', tableName: 'person' }) | ||
class Person { | ||
|
||
@PrimaryKey({ nullable: true }) | ||
id?: number; | ||
|
||
@Property() | ||
name!: string; | ||
|
||
@ManyToMany({ entity: () => 'Phone', owner: true, pivotTable: 'tic.person_phone', joinColumn: 'person_id', inverseJoinColumn: 'phone_id' }) | ||
phones = new Collection<Phone>(this); | ||
|
||
} | ||
|
||
@Entity({ schema: 'tic', tableName: 'phone' }) | ||
class Phone { | ||
|
||
@PrimaryKey({ nullable: true }) | ||
id?: number; | ||
|
||
@Property() | ||
number!: string; | ||
|
||
@ManyToMany({ entity: () => 'Person', mappedBy: (e: Person) => e.phones }) | ||
people: Collection<Person> = new Collection<Person>(this); | ||
|
||
} | ||
|
||
@Entity() | ||
class FooBar { | ||
|
||
@PrimaryKey({ nullable: true }) | ||
id?: number; | ||
|
||
} | ||
|
||
let orm: MikroORM; | ||
|
||
beforeAll(async () => { | ||
orm = await MikroORM.init({ | ||
entities: [Person, Phone, FooBar], | ||
dbName: ':memory:', | ||
discovery: { | ||
onMetadata(meta) { | ||
// sqlite driver does not support schemas | ||
delete meta.schema; | ||
|
||
meta.tableName += '_2'; | ||
|
||
for (const prop of meta.relations) { | ||
if (prop.kind === ReferenceKind.MANY_TO_MANY && prop.owner && prop.pivotTable.includes('.')) { | ||
prop.pivotTable = prop.pivotTable.split('.')[1]; | ||
} | ||
} | ||
|
||
meta.addProperty({ name: 'version', version: true, type: 'integer' }); | ||
}, | ||
afterDiscovered(storage: MetadataStorage) { | ||
storage.reset('FooBar'); | ||
}, | ||
}, | ||
}); | ||
await orm.schema.createSchema(); | ||
}); | ||
|
||
afterAll(async () => { | ||
await orm.close(true); | ||
}); | ||
|
||
test('discovery hooks', async () => { | ||
await expect(orm.schema.getCreateSchemaSQL()).resolves.toMatchSnapshot(); | ||
|
||
const person = new Person(); | ||
person.name = 'John Wick'; | ||
const phone = new Phone(); | ||
phone.number = '666555444'; | ||
person.phones.add(phone); | ||
await orm.em.persistAndFlush(person); | ||
|
||
orm.em.clear(); | ||
const [personLoaded] = await orm.em.find(Person, {}, { populate: ['phones'] }); | ||
personLoaded.phones.remove(personLoaded.phones[0]); | ||
await orm.em.flush(); | ||
}); |