В настоящее время я работаю над полностью машинописным проектом вместе с Bun + Elysia. Я перенес свое приложение из предыдущего проекта NestJs, в котором прекрасно работал MikroORM. Теперь, когда мое приложение запущено через bun, мигратор не работает:
bunx --bun mikro-orm
со следующей ошибкой:
354 | /* istanbul ignore next */
355 | if ('type' in this.options) {
356 | throw new Error('The `type` option has been removed in v6, please fill in the `driver` option instead or use `defineConfig` helper (to define your ORM config) or `MikroORM` class (to call the `init` method) exported from the driver package (e.g. `import { defineConfig } from \'@mikro-orm/mysql\'; export default defineConfig({ ... })`).');
357 | }
358 | if (!this.options.driver) {
359 | throw new Error('No driver specified, please fill in the `driver` option or use `defineConfig` helper (to define your ORM config) or `MikroORM` class (to call the `init` method) exported from the driver package (e.g. `import { defineConfig } from \'@mikro-orm/mysql\'; export defineConfig({ ... })`).');
^
error: No driver specified, please fill in the `driver` option or use `defineConfig` helper (to define your ORM config) or `MikroORM` class (to call the `init` method) exported from the driver package (e.g. `import { defineConfig } from '@mikro-orm/mysql'; export defineConfig({ ... })`).
at validateOptions (C:\Users\X\Projects\smm_est\server\node_modules\@mikro-orm\cli\node_modules\@mikro-orm\core\utils\Configuration.js:359:19)
at new Configuration (C:\Users\X\Projects\smm_est\server\node_modules\@mikro-orm\cli\node_modules\@mikro-orm\core\utils\Configuration.js:140:13)
at C:\Users\X\Projects\smm_est\server\node_modules\@mikro-orm\cli\node_modules\@mikro-orm\core\utils\ConfigurationLoader.js:38:24
error: script "orm" exited with code 1
Но я правильно указал все в файле src/orm.ts вот так:
// orm.ts
import { Migrator } from '@mikro-orm/migrations'
import { SeedManager } from '@mikro-orm/seeder'
import { MikroORM, ReflectMetadataProvider, SqliteDriver, defineConfig } from '@mikro-orm/sqlite'
import { User } from '#user/user.entity'
import { Role } from '#role/role.entity'
import { Ability } from '#role/ability.entity'
import { Link } from '#link/link.entity'
export const config = defineConfig({
debug: true,
dbName: 'smm.db',
driver: SqliteDriver,
entities: [
Role,
Ability,
User,
Link
],
extensions: [Migrator, SeedManager],
migrations: {
path: './src/data/migrations',
transactional: true,
emit: 'ts',
snapshot: true
},
seeder: {
path: './src/**/',
glob: '!(*.d)(*.seeder).{js,ts}',
emit: 'ts',
defaultSeeder: 'DatabaseSeeder'
},
metadataProvider: ReflectMetadataProvider
})
export const orm = MikroORM.initSync(config)
export default orm
Я запускаю orm с помощью этой команды:
"orm": "bunx --bun mikro-orm"
Это файл package.json. Обратите внимание, что я не хочу компилировать и создавать файлы js:
"name": "smm_server",
"version": "0.0.1",
"module": "src/index.ts",
"type": "module",
"scripts": {
"dev": "bun run --watch src/index.ts",
"inspect": "bun --inspect src/index.ts",
"format": "biome format .",
"lint": "biome lint .",
"check": "biome check --apply .",
"test": "bun test",
"typecheck": "tsc --noEmit --project tsconfig.json",
"orm": "bunx --bun mikro-orm"
},
"dependencies": {
"@elysiajs/cors": "1.0.2",
"@elysiajs/eden": "1.0.14",
"@elysiajs/jwt": "^1.0.2",
"@elysiajs/static": "1.0.3",
"@elysiajs/swagger": "1.0.5",
"@faker-js/faker": "^8.4.1",
"@mikro-orm/core": "^6.2.9",
"@mikro-orm/migrations": "^6.2.9",
"@mikro-orm/mysql": "^6.2.9",
"@mikro-orm/reflection": "^6.2.9",
"@mikro-orm/seeder": "^6.2.9",
"@mikro-orm/sqlite": "^6.2.9",
"@types/uuid": "^9.0.8",
"elysia": "1.0.22",
"elysia-autoroutes": "0.5.0",
"pino": "9.1.0",
"reflect-metadata": "^0.2.2",
"sqlite3": "^5.1.7",
"uuid": "^9.0.1"
},
"devDependencies": {
"@biomejs/biome": "1.7.3",
"@mikro-orm/cli": "^6.2.9",
"bun-types": "1.1.10",
"tslib": "2.6.2",
"typescript": "5.4.5"
},
"mikro-orm": {
"alwaysAllowTs": true,
"configPaths": [
"./src/data/orm.ts"
]
},
"trustedDependencies": [
"sqlite3"
]
}
Также файл tsconfig.json:
{
"compilerOptions": {
// Enable latest features
"lib": ["ES2022"],
"target": "ES2022",
"module": "Node16",
"moduleDetection": "force",
"jsx": "react-jsx",
"allowJs": true,
// Bundler mode
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"verbatimModuleSyntax": true,
"noEmit": true,
// Best practices
"strict": true,
"skipLibCheck": true,
"noFallthroughCasesInSwitch": true,
"types": ["bun-types"],
// Some stricter flags
"noUnusedLocals": true,
"noUnusedParameters": true,
"noPropertyAccessFromIndexSignature": true,
"forceConsistentCasingInFileNames": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"baseUrl": ".",
"paths": {
"#auth/*": ["./src/auth/*"],
"#data/*": ["./src/data/*"],
"#health/*": ["./src/health/*"],
"#link/*": ["./src/link/*"],
"#page/*": ["./src/page/*"],
"#role/*": ["./src/role/*"],
"#user/*": ["./src/user/*"],
"#logger": ["./src/logger.ts"]
}
},
"include": ["**/*.ts", "**/*.tsx"],
"exclude": ["node_modules"],
}
Я также добавляю сюда два таких объекта:
import { Link } from '#link/link.entity'
import { Role, RoleStandard } from '#role/role.entity'
import { BeforeCreate, BeforeUpdate, Collection, Entity, ManyToOne, OneToMany, PrimaryKey, Property } from '@mikro-orm/core'
import { v4 } from 'uuid'
const SALT_ROUNDS = 10
@Entity({
tableName: 'users'
})
export class User {
@PrimaryKey({
name: 'uuid',
type: 'text',
autoincrement: false,
nullable: false,
unique: true,
comment: 'User\'s ID',
})
public uuid?: string = v4()
@Property({
name: 'username',
type: 'varchar',
length: 32,
unique: true,
nullable: false,
comment: 'User\'s username'
})
public username?: string
@Property({
name: 'email',
type: 'varchar',
length: 64,
unique: true,
nullable: false,
comment: 'User\'s email'
})
public email?: string
@Property({
name: 'display_name',
type: 'varchar',
length: 32,
nullable: true,
comment: 'User\'s display name'
})
public display_name?: string | null
@Property({
name: 'password',
type: 'varchar',
length: 64,
nullable: false,
comment: 'User\'s password'
})
public password?: string
@Property({
name: 'coins',
type: 'integer',
unsigned: true,
nullable: false,
default: 0,
comment: 'User\'s coins'
})
public coins?: number
@Property({
name: 'created_at',
type: 'datetime',
nullable: false,
comment: 'User\'s creation date and time'
})
public createdAt?: Date = new Date()
/**
* Updated at
*/
@Property({
name: 'updated_at',
type: 'datetime',
nullable: false,
onUpdate: () => new Date(),
comment: 'User\'s update date and time'
})
public updatedAt?: Date = new Date()
@ManyToOne({
entity: () => Role,
nullable: false,
deleteRule: 'set null',
})
public role?: Role
@OneToMany({
entity: () => Link,
mappedBy: link => link.user,
orphanRemoval: false
})
public links? = new Collection<Link>(this)
@BeforeCreate()
@BeforeUpdate()
async hashPassword() {
if (this.password) {
this.password = await Bun.password.hash(this.password, {
algorithm: 'bcrypt',
cost: SALT_ROUNDS
})
}
}
@BeforeCreate()
async setDefaultRole() {
if (!this.role) {
this.role = RoleStandard
}
}
}
И role.entity.ts:
import { User } from '#user/user.entity'
import { Collection, Entity, OneToMany, PrimaryKey, Property } from '@mikro-orm/core'
import { Ability } from '#role/ability.entity'
@Entity({
tableName: 'roles'
})
export class Role {
constructor(id?: number, name?: string) {
this.id = id
this.name = name
}
@PrimaryKey({
name: 'id',
type: 'integer',
autoincrement: false,
comment: 'Role\'s ID',
})
public id?: number
@Property({
name: 'name',
type: 'varchar',
length: 16,
unique: true,
nullable: false,
comment: 'Role\'s name'
})
public name?: string
@OneToMany({
entity: () => Ability,
mappedBy: permission => permission.role,
orphanRemoval: false
})
public abilities? = new Collection<Ability>(this)
@OneToMany({
entity: () => User,
mappedBy: user => user.role,
orphanRemoval: false
})
public users? = new Collection<User>(this)
}
export const RoleAdmin: Role = { id: 1, name: 'Admin' }
export const RolePremium: Role = { id: 2, name: 'Premium' }
export const RoleStandard: Role = { id: 3, name: 'Standard' }
export const RoleBanned: Role = { id: 4, name: 'Banned' }
Серьезно, у меня нет подсказок. Когда я использую команду orm без MikroORM.init() (просто defineConfig()), она жалуется, что все объекты абстрактны. Итак, в файле orm.ts вместо экспорта orm, если я экспортирую config, будет выведено:
172 | static noEntityDiscovered() {
173 | return new MetadataError('No entities were discovered');
174 | }
175 | static onlyAbstractEntitiesDiscovered() {
176 | return new MetadataError('Only abstract entities were discovered, maybe you forgot to use @Entity() decorator?');
177 | }
^
MetadataError: Only abstract entities were discovered, maybe you forgot to use @Entity() decorator?
at onlyAbstractEntitiesDiscovered (C:\Users\X\Projects\smm_est\server\node_modules\@mikro-orm\cli\node_modules\@mikro-orm\core\errors.js:177:11)
at validateDiscovered (C:\Users\X\Projects\smm_est\server\node_modules\@mikro-orm\cli\node_modules\@mikro-orm\core\metadata\MetadataValidator.js:117:66)
at findEntities (C:\Users\X\Projects\smm_est\server\node_modules\@mikro-orm\cli\node_modules\@mikro-orm\core\metadata\MetadataDiscovery.js:193:17)
at C:\Users\X\Projects\smm_est\server\node_modules\@mikro-orm\cli\node_modules\@mikro-orm\core\metadata\MetadataDiscovery.js:63:14
at discover (C:\Users\X\Projects\smm_est\server\node_modules\@mikro-orm\cli\node_modules\@mikro-orm\core\metadata\MetadataDiscovery.js:59:25)
at C:\Users\X\Projects\smm_est\server\node_modules\@mikro-orm\cli\node_modules\@mikro-orm\core\MikroORM.js:172:33
at discoverEntities (C:\Users\X\Projects\smm_est\server\node_modules\@mikro-orm\cli\node_modules\@mikro-orm\core\MikroORM.js:172:33)
at C:\Users\X\Projects\smm_est\server\node_modules\@mikro-orm\cli\node_modules\@mikro-orm\core\MikroORM.js:80:13
at processTicksAndRejections (native:1:1)
error: script "orm" exited with code 1
В последнее время эта штука действует мне на нервы. Я думал о переходе на Drizzle, но с Mikro у меня появилась возможность позже легко переключиться на MySql.






Я думаю, ваша проблема не в использовании экспорта по умолчанию для конфигурации ORM. Не смешивайте свою конфигурацию с другими вещами, особенно с кодом с такими побочными эффектами, как у вас, это плохая идея. Конфиг выложите отдельно, желательно в mikro-orm.config.ts файл в корне (и не забудьте использовать экспорт по умолчанию), тогда всё должно работать.
Попробовал еще раз, все равно ошибка :(
С Bun он тоже отлично работает, ваша проблема не в местонахождении файла конфигурации, а в том, что (и как) экспортирует файл. Как упоминалось в обсуждении GH (в следующий раз, пожалуйста, не открывайте один и тот же отчет в нескольких местах, из-за этого вы не привлечете больше внимания, на самом деле вы только создадите еще больше беспорядка:]), вам необходимо (по умолчанию) экспортировать конфигурация ORM, а не экземпляр ORM.
Ты прав, мне очень жаль. Я обновлю это после того, как проблема будет обнаружена.
Спасибо. Перемещение конфигурации orm в
mikro-orm.config.tsв корневую папку решило проблему. Это по-прежнему похоже на ошибку: использованиеconfigPathsвpackage.jsonраньше нормально работало в среде NestJs.