Nuxt 3 nitro + mikro-orm
max5432112345 opened this issue · 5 comments
Environment
- Operating System:
Linux
- Node Version:
v16.15.1
- Nuxt Version:
3.0.0-rc.4
- Package Manager:
npm@8.12.2
- Builder:
vite
- User Config:
-
- Runtime Modules:
-
- Build Modules:
-
Reproduction
import { RequestContext } from '@mikro-orm/core'
import { DI } from '../data-source'
export default defineEventHandler(async (event) => {
console.log(next)
RequestContext.create(DI.orm.em, next) // no next function
})
OR
import { RequestContext } from '@mikro-orm/core'
import { DI } from '../data-source'
export default (req, res, next) => {
console.log(next)
RequestContext.create(DI.orm.em, next) // has next but not work, such error was with fastify https://github.com/fastify/fastify/issues/3570
}
DI file
import 'reflect-metadata'
import {
// EntityManager,
// EntityRepository,
MikroORM
} from '@mikro-orm/core'
import { Author } from './entities'
export const DI = {} as {
orm: MikroORM,
// em: EntityManager,
// authorRepository: EntityRepository<Author>
}
(async () => {
DI.orm = await MikroORM.init({
type: 'mariadb',
entities: [Author],
dbName: 'nuxt',
password: '123456',
user: 'admin',
debug: true
})
})()
Describe the bug
No next function. In legacy exist but no effect like with old version of fastify here
nestjs/nest#8837
nodejs/node#41285
[nitro] [dev] [unhandledRejection] ValidationError: Using global EntityManager instance methods for context specific actions is disallowed. If you need to work with the global instance's identity map, use allowGlobalContext
configuration option or fork()
instead.
Additional context
No response
Logs
No response
some file can be taken from https://github.com/max5432112345/nuxt-mikro
need useNext() helper???
+1 Stuck at this too
@max5432112345 here a approach that works for me, but is defenitly not the end-solution:
Create a server middleware with following content which initialize the database connection if no one exists:
import { RequestContext } from '@mikro-orm/core'
import { useClient } from '../datasources/tenant/client'
export default defineEventHandler(async (event) => {
const client = await useClient();
// TODO:: https://github.com/nuxt/framework/issues/5603
RequestContext.create(client.orm.em, () => { })
event.context.tenantClient = client;
})
A client file:
import type { MySqlDriver } from '@mikro-orm/mysql';
import { MikroORM, EntityRepository, EntityManager } from "@mikro-orm/core";
import { Author, Book, BookTag, Publisher, BaseEntity } from "./entities";
import { SqlHighlighter } from "@mikro-orm/sql-highlighter";
export type Client = {
orm: MikroORM,
em: EntityManager,
authorRepository: EntityRepository<Author>
};
let client: Client;
export const useClient = async () => {
if (!client) {
// TODO:: CLI config will be used automatically
const orm = await MikroORM.init<MySqlDriver>({
dbName: "mikro-orm",
type: "mysql",
host: process.env.MYSQL_HOST || "127.0.0.1",
port: Number(process.env.MYSQL_PORT) || 3306,
user: process.env.MYSQL_USERNAME || "root",
password: process.env.MYSQL_PASSWORD || "root",
// as we are using class references here, we don't need to specify `entitiesTs` option
entities: [Author, Book, BookTag, Publisher, BaseEntity],
highlighter: new SqlHighlighter(),
discovery: { disableDynamicFileAccess: true },
debug: true, // todo:: env
});
const em = orm.em.fork();
const authorRepository = em.getRepository(Author);
client = {
orm, em, authorRepository
};
}
return client;
}
Now you can use in your /api/foo.ts api endpoint the client (orm) as following:
import { QueryOrder } from "@mikro-orm/core";
import { Client } from "../datasources/tenant/client";
export default defineEventHandler(async (event) => {
const { tenantClient } = event.context as { tenantClient: Client };
const authors = await tenantClient.authorRepository.findAll({
populate: ['books'],
orderBy: { name: QueryOrder.DESC },
limit: 20,
});
return {
statusCode: 200,
body: JSON.stringify(authors),
};
});
Hope it helps you a bit