Skip to content

Commit 1e44657

Browse files
authored
docs: update MikroORM recipe based on its v6 changes
1 parent f97033f commit 1e44657

File tree

1 file changed

+35
-61
lines changed

1 file changed

+35
-61
lines changed

content/recipes/mikroorm.md

Lines changed: 35 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,44 @@
11
### MikroORM
22

3-
This recipe is here to help users getting started with MikroORM in Nest. MikroORM is the TypeScript ORM for Node.js based on Data Mapper, Unit of Work and Identity Map patterns. It is a great alternative to TypeORM and migration from TypeORM should be fairly easy. The complete documentation on MikroORM can be found [here](https://mikro-orm.io/docs).
3+
This recipe is here to help users get started with MikroORM in Nest. MikroORM is the TypeScript ORM for Node.js based on Data Mapper, Unit of Work and Identity Map patterns. It is a great alternative to TypeORM and migration from TypeORM should be fairly easy. The complete documentation on MikroORM can be found [here](https://mikro-orm.io/docs).
44

5-
> info **info** `@mikro-orm/nestjs` is a third party package and is not managed by the NestJS core team. Please, report any issues found with the library in the [appropriate repository](https://github.com/mikro-orm/nestjs).
5+
> info **info** `@mikro-orm/nestjs` is a third party package and is not managed by the NestJS core team. Please report any issues found with the library in the [appropriate repository](https://github.com/mikro-orm/nestjs).
66
77
#### Installation
88

99
Easiest way to integrate MikroORM to Nest is via [`@mikro-orm/nestjs` module](https://github.com/mikro-orm/nestjs).
1010
Simply install it next to Nest, MikroORM and underlying driver:
1111

1212
```bash
13-
$ npm i @mikro-orm/core @mikro-orm/nestjs @mikro-orm/mysql # for mysql/mariadb
13+
$ npm i @mikro-orm/core @mikro-orm/nestjs @mikro-orm/sqlite
1414
```
1515

1616
MikroORM also supports `postgres`, `sqlite`, and `mongo`. See the [official docs](https://mikro-orm.io/docs/usage-with-sql/) for all drivers.
1717

1818
Once the installation process is completed, we can import the `MikroOrmModule` into the root `AppModule`.
1919

2020
```typescript
21+
import { SqliteDriver } from '@mikro-orm/sqlite';
22+
2123
@Module({
2224
imports: [
2325
MikroOrmModule.forRoot({
2426
entities: ['./dist/entities'],
2527
entitiesTs: ['./src/entities'],
2628
dbName: 'my-db-name.sqlite3',
27-
type: 'sqlite',
29+
driver: SqliteDriver,
2830
}),
2931
],
3032
controllers: [AppController],
3133
providers: [AppService],
3234
})
33-
export class AppModule {}
35+
export class AppModule {
36+
}
3437
```
3538

3639
The `forRoot()` method accepts the same configuration object as `init()` from the MikroORM package. Check [this page](https://mikro-orm.io/docs/configuration) for the complete configuration documentation.
3740

38-
Alternatively we can [configure the CLI](https://mikro-orm.io/docs/installation#setting-up-the-commandline-tool) by creating a configuration file `mikro-orm.config.ts` and then call the `forRoot()` without any arguments. This won't work when you use a build tools that use tree shaking.
41+
Alternatively we can [configure the CLI](https://mikro-orm.io/docs/installation#setting-up-the-commandline-tool) by creating a configuration file `mikro-orm.config.ts` and then call the `forRoot()` without any arguments.
3942

4043
```typescript
4144
@Module({
@@ -47,12 +50,25 @@ Alternatively we can [configure the CLI](https://mikro-orm.io/docs/installation#
4750
export class AppModule {}
4851
```
4952

50-
Afterward, the `EntityManager` will be available to inject across entire project (without importing any module elsewhere).
53+
But this won't work when you use a build tools that use tree shaking, for that it is better to provide the config explicitly:
54+
55+
```typescript
56+
import config from './mikro-orm.config'; // your ORM config
57+
58+
@Module({
59+
imports: [
60+
MikroOrmModule.forRoot(config),
61+
],
62+
...
63+
})
64+
export class AppModule {}
65+
```
66+
67+
Afterward, the `EntityManager` will be available to inject across the entire project (without importing any module elsewhere).
5168

5269
```ts
53-
import { MikroORM } from '@mikro-orm/core';
54-
// Import EntityManager from your driver package or `@mikro-orm/knex`
55-
import { EntityManager } from '@mikro-orm/mysql';
70+
// Import everytyhing from your driver package or `@mikro-orm/knex`
71+
import { EntityManager, MikroORM } from '@mikro-orm/sqlite';
5672

5773
@Injectable()
5874
export class MyService {
@@ -67,7 +83,7 @@ export class MyService {
6783
6884
#### Repositories
6985

70-
MikroORM supports the repository design pattern. For every entity we can create a repository. Read the complete documentation on repositories [here](https://mikro-orm.io/docs/repositories). To define which repositories should be registered in the current scope you can use the `forFeature()` method. For example, in this way:
86+
MikroORM supports the repository design pattern. For every entity, we can create a repository. Read the complete documentation on repositories [here](https://mikro-orm.io/docs/repositories). To define which repositories should be registered in the current scope you can use the `forFeature()` method. For example, in this way:
7187

7288
> info **info** You should **not** register your base entities via `forFeature()`, as there are no
7389
> repositories for those. On the other hand, base entities need to be part of the list in `forRoot()` (or in the ORM config in general).
@@ -106,28 +122,18 @@ export class PhotoService {
106122

107123
#### Using custom repositories
108124

109-
When using custom repositories, we can get around the need for `@InjectRepository()`
110-
decorator by naming our repositories the same way as `getRepositoryToken()` method do:
111-
112-
```ts
113-
export const getRepositoryToken = <T>(entity: EntityName<T>) =>
114-
`${Utils.className(entity)}Repository`;
115-
```
116-
117-
In other words, as long as we name the repository same was as the entity is called,
118-
appending `Repository` suffix, the repository will be registered automatically in
119-
the Nest DI container.
125+
When using custom repositories, we no longer need the `@InjectRepository()`
126+
decorator, as Nest DI resolved based on the class references.
120127

121128
```ts
122129
// `**./author.entity.ts**`
123-
@Entity()
130+
@Entity({ repository: () => AuthorRepository })
124131
export class Author {
125132
// to allow inference in `em.getRepository()`
126133
[EntityRepositoryType]?: AuthorRepository;
127134
}
128135

129136
// `**./author.repository.ts**`
130-
@Repository(Author)
131137
export class AuthorRepository extends EntityRepository<Author> {
132138
// your custom methods...
133139
}
@@ -145,8 +151,6 @@ export class MyService {
145151

146152
#### Load entities automatically
147153

148-
> info **info** `autoLoadEntities` option was added in v4.1.0
149-
150154
Manually adding entities to the entities array of the connection options can be
151155
tedious. In addition, referencing entities from the root module breaks application
152156
domain boundaries and causes leaking implementation details to other parts of the
@@ -207,15 +211,13 @@ export class Book {
207211

208212
#### Request scoped handlers in queues
209213

210-
> info **info** `@UseRequestContext()` decorator was added in v4.1.0
211-
212214
As mentioned in the [docs](https://mikro-orm.io/docs/identity-map), we need a clean state for each request. That is handled automatically thanks to the `RequestContext` helper registered via middleware.
213215

214216
But middlewares are executed only for regular HTTP request handles, what if we need
215217
a request scoped method outside of that? One example of that is queue handlers or
216218
scheduled tasks.
217219

218-
We can use the `@UseRequestContext()` decorator. It requires you to first inject the
220+
We can use the `@CreateRequestContext()` decorator. It requires you to first inject the
219221
`MikroORM` instance to current context, it will be then used to create the context
220222
for you. Under the hood, the decorator will register new request context for your
221223
method and execute it inside the context.
@@ -225,43 +227,14 @@ method and execute it inside the context.
225227
export class MyService {
226228
constructor(private readonly orm: MikroORM) {}
227229

228-
@UseRequestContext()
230+
@CreateRequestContext()
229231
async doSomething() {
230232
// this will be executed in a separate context
231233
}
232234
}
233235
```
234236

235-
#### Using `AsyncLocalStorage` for request context
236-
237-
By default, the `domain` api is used in the `RequestContext` helper. Since `@mikro-orm/[email protected]`,
238-
you can use the new `AsyncLocalStorage` too, if you are on up to date node version:
239-
240-
```typescript
241-
// create new (global) storage instance
242-
const storage = new AsyncLocalStorage<EntityManager>();
243-
244-
@Module({
245-
imports: [
246-
MikroOrmModule.forRoot({
247-
// ...
248-
registerRequestContext: false, // disable automatic middleware
249-
context: () => storage.getStore(), // use our AsyncLocalStorage instance
250-
}),
251-
],
252-
controllers: [AppController],
253-
providers: [AppService],
254-
})
255-
export class AppModule {}
256-
257-
// register the request context middleware
258-
const app = await NestFactory.create(AppModule, { ... });
259-
const orm = app.get(MikroORM);
260-
261-
app.use((req, res, next) => {
262-
storage.run(orm.em.fork(true, true), next);
263-
});
264-
```
237+
> As the name suggests, this decorator always creates new context, as opposed to its alternative `@EnsureRequestContext` that only creates on if it's already not inside another.
265238
266239
#### Testing
267240

@@ -272,7 +245,8 @@ The `@mikro-orm/nestjs` package exposes `getRepositoryToken()` function that ret
272245
providers: [
273246
PhotoService,
274247
{
275-
provide: getRepositoryToken(Photo),
248+
// or when you have a custom repository: `provide: PhotoRepository`
249+
provide: getRepositoryToken(Photo),
276250
useValue: mockedRepository,
277251
},
278252
],

0 commit comments

Comments
 (0)