You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ESbuild+TypeScript环境下TypeORM实体元数据缺失(含ts-node报错)求助

问题描述

更新

直接用ts-node执行实体创建与数据库初始化操作时也会触发该错误,因此推测这不是构建环节的问题,而是TypeScript+TypeORM+ts-node组合的兼容性或配置问题。

项目背景

本Node.js项目采用ESbuild搭配esbuild-plugin-tsc插件构建,配置如下:

import * as esbuild from 'esbuild';

const config = {
    entryPoints: ['server.js'],
    bundle: true,
    outdir,
    platform: 'node',
    packages: 'external',
    external: ['uuid'],
    plugins: [
      esbuildPluginTsc({
        force: true
      }),
   ...], // 其他静态文件配置
  ...options,
}

await esbuild.build(config);

同时tsconfig.json已正确启用装饰器相关配置:

  • "emitDecoratorMetadata": true
  • "experimentalDecorators": true

代码实现

实体定义

import 'reflect-metadata';
import {
  Entity,
  PrimaryGeneratedColumn,
  Column,
} from 'typeorm';

@Entity()
export class Common {
  @PrimaryGeneratedColumn('uuid')
  id: string;

  @Column({ type: 'varchar', nullable: false })
  name: string;
}

DataSource初始化代码

import 'reflect-metadata';
import { Common } from '@entity/common-entity'; // 自定义实体路径别名
import { DataSource } from 'typeorm';

const myDataSource = new DataSource({
  type: 'postgres',
  host: process.env.DB_HOST,
  port: parseInt(process.env.DB_PORT || '5432'),
  username: process.env.DB_USER,
  password: process.env.DB_PASSWORD,
  database: process.env.DB_NAME,
  entities: [Common],
  logging: true,
  synchronize: true,
});

export const init = async () => {
  myDataSource
    .initialize()
    .then(async () => {
      logger.info('Data Source has been initialized!');
    })
    .catch((err) => {
      logger.error(
        'Error during Data Source initialization:\n',
        err.message,
        err.stack
      );
    });

  const commonRepository = myDataSource.getRepository(Common);
  const newCommon = new Common();
  newCommon.name = 'new user';
  await commonRepository.save(newCommon);
  await myDataSource.destroy();
};

构建结果

生成的build/server.js中实体相关代码片段:

...
    Object.defineProperty(exports2, "__esModule", { value: true }); exports2.Common = void 0;
    require("reflect-metadata");
    var typeorm_1 = require("typeorm");
    var Common2 = class Common {
    };
    __decorate([
      (0, typeorm_1.PrimaryGeneratedColumn)("uuid")
    ], Common2.prototype, "id", void 0);
    __decorate([
      (0, typeorm_1.Column)({ type: "varchar", nullable: false })
    ], Common2.prototype, "name", void 0);
    Common2 = __decorate([
      (0, typeorm_1.Entity)()
    ], Common2);
    exports2.Common = Common2;

问题现象

构建过程无异常,实体类已被装饰器包裹,但数据库初始化后抛出错误:

EntityMetadataNotFoundError: No metadata for "Common" was found. at DataSource.getMetadata (/node_modules/typeorm/data-source/DataSource.js:304:19)

实体类确实存在,但TypeORM无法读取其元数据。

求助

已查阅官方文档、相关Issue及其他资料,所有提及的配置均已完成,请问还需进行哪些操作才能让实体生成所需元数据,使项目正常运行?


解决方案

1. 统一reflect-metadata导入方式

TypeORM依赖reflect-metadata存储装饰器元数据,重复导入或局部导入会导致元数据上下文冲突。建议在项目入口文件(如server.js)最顶部全局导入一次:

import 'reflect-metadata';

同时移除实体文件和DataSource文件中的import 'reflect-metadata';语句。

2. 修正异步操作顺序

当前代码中initialize()是异步操作,但后续的getRepository和save未等待初始化完成就执行,导致DataSource还未加载完实体元数据就被调用。修改init函数为完全异步等待:

export const init = async () => {
  try {
    await myDataSource.initialize();
    logger.info('Data Source has been initialized!');

    const commonRepository = myDataSource.getRepository(Common);
    const newCommon = new Common();
    newCommon.name = 'new user';
    await commonRepository.save(newCommon);
  } catch (err) {
    logger.error(
      'Error during Data Source initialization or operation:\n',
      err.message,
      err.stack
    );
  } finally {
    await myDataSource.destroy();
  }
};

3. 确保实体引用一致性

检查路径别名(如@entity)在tsconfig.json和ESbuild配置中的一致性,避免因路径解析问题导致导入的Common类是不同实例。如果使用TypeScript路径别名,需确保ESbuild也配置了对应的别名映射。

4. 改用实体文件路径配置

若直接传入类引用无效,可在DataSource配置中使用实体文件的glob路径,让TypeORM自行加载解析元数据:

const myDataSource = new DataSource({
  // ...其他配置
  entities: ['src/entity/**/*.ts'], // 开发环境
  // 生产环境替换为构建后的路径:['build/entity/**/*.js']
});

5. 检查版本兼容性

  • 确保使用TypeORM 0.3.x最新稳定版本
  • 若用ts-node,添加--esm参数或调整tsconfig.json的module配置(如设为CommonJS)以匹配项目模块系统
  • 确保esbuild-plugin-tsc版本与当前TypeScript版本兼容,避免编译时丢失装饰器元数据

内容的提问来源于stack exchange,提问作者Gadzhiev Islam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 04:45:53