Невозможно запустить миграцию Mikro-ORM на булочке

В настоящее время я работаю над полностью машинописным проектом вместе с 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.

Зод: сила проверки и преобразования данных
Зод: сила проверки и преобразования данных
Сегодня я хочу познакомить вас с библиотекой Zod и раскрыть некоторые ее особенности, например, возможности валидации и трансформации данных, а также...
Как заставить Remix работать с Mantine и Cloudflare Pages/Workers
Как заставить Remix работать с Mantine и Cloudflare Pages/Workers
Мне нравится библиотека Mantine Component , но заставить ее работать без проблем с Remix бывает непросто.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
TypeScript против JavaScript
TypeScript против JavaScript
TypeScript vs JavaScript - в чем различия и какой из них выбрать?
Синхронизация localStorage в масштабах всего приложения с помощью пользовательского реактивного хука useLocalStorage
Синхронизация localStorage в масштабах всего приложения с помощью пользовательского реактивного хука useLocalStorage
Не все нужно хранить на стороне сервера. Иногда все, что вам нужно, это постоянное хранилище на стороне клиента для хранения уникальных для клиента...
Что такое ленивая загрузка в Angular и как ее применять
Что такое ленивая загрузка в Angular и как ее применять
Ленивая загрузка - это техника, используемая в Angular для повышения производительности приложения путем загрузки модулей только тогда, когда они...
0
0
115
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я думаю, ваша проблема не в использовании экспорта по умолчанию для конфигурации ORM. Не смешивайте свою конфигурацию с другими вещами, особенно с кодом с такими побочными эффектами, как у вас, это плохая идея. Конфиг выложите отдельно, желательно в mikro-orm.config.ts файл в корне (и не забудьте использовать экспорт по умолчанию), тогда всё должно работать.

Спасибо. Перемещение конфигурации orm в mikro-orm.config.ts в корневую папку решило проблему. Это по-прежнему похоже на ошибку: использование configPaths в package.json раньше нормально работало в среде NestJs.

Reza Hajianpour 08.06.2024 14:02

Попробовал еще раз, все равно ошибка :(

Reza Hajianpour 08.06.2024 14:18

С Bun он тоже отлично работает, ваша проблема не в местонахождении файла конфигурации, а в том, что (и как) экспортирует файл. Как упоминалось в обсуждении GH (в следующий раз, пожалуйста, не открывайте один и тот же отчет в нескольких местах, из-за этого вы не привлечете больше внимания, на самом деле вы только создадите еще больше беспорядка:]), вам необходимо (по умолчанию) экспортировать конфигурация ORM, а не экземпляр ORM.

Martin Adámek 08.06.2024 14:43

Ты прав, мне очень жаль. Я обновлю это после того, как проблема будет обнаружена.

Reza Hajianpour 09.06.2024 01:31

Другие вопросы по теме