【问题标题】:EntityMetadataNotFound: No metadata for "User" was foundEntityMetadataNotFound:找不到“用户”的元数据
【发布时间】:2021-08-03 20:51:21
【问题描述】:

PS.:我已经阅读了很多类似的主题,但没有一个可以解决我的问题,已经尝试为 ormconfig.js 和其他东西更改实体上的正则表达式模式。

好吧,几天前我能够成功执行这个 ExpressJS 应用程序,没有出现任何错误。但是现在,它才刚刚开始抛出EntityMetadataNotFound: No metadata for "User" was found.

这是项目的存储库:https://github.com/joaocasarin/gittin

如您所见,我的 entitiesmigrations 分别指向 dist/entities/*.jsdist/database/migrations/*.js,因为我读过 TypeORM 在打字稿中无法使用它们(使用 ts-node-dev要运行应用程序,如果实体在 .ts 中,我会收到错误消息,说我不能在纯 javascript 文件上使用来自 ES6+ 的导入和东西。如果我使用 .ts 文件运行迁移,则找不到运行迁移.)。此外,您会看到我的实体、存储库、服务和控制器都是正确的(我看不到它们有任何问题),但是当我尝试与数据库进行交互时仍然出现该错误。

失眠请求正文: /POST http://localhost:3000/api/users

{
    "name": "123",
    "password": "123",
    "email": "docker@123.com",
    "admin": true
}

回复:

{
  "error": {
    "name": "EntityMetadataNotFound",
    "message": "No metadata for \"User\" was found."
  }
}

终端错误:

EntityMetadataNotFound: No metadata for "User" was found.
    at new EntityMetadataNotFoundError (C:\Users\joaov\Documents\gittin\src\error\EntityMetadataNotFoundError.ts:10:9)
    at Connection.getMetadata (C:\Users\joaov\Documents\gittin\src\connection\Connection.ts:337:19)
    at EntityManager.getCustomRepository (C:\Users\joaov\Documents\gittin\src\entity-manager\EntityManager.ts:976:86)
    at Connection.getCustomRepository (C:\Users\joaov\Documents\gittin\src\connection\Connection.ts:372:29)
    at Object.getCustomRepository (C:\Users\joaov\Documents\gittin\src\index.ts:298:55)
    at CreateUserService.<anonymous> (C:\Users\joaov\Documents\gittin\src\services\CreateUserService.ts:14:37)
    at step (C:\Users\joaov\Documents\gittin\src\services\CreateUserService.ts:33:23)
    at Object.next (C:\Users\joaov\Documents\gittin\src\services\CreateUserService.ts:14:53)
    at C:\Users\joaov\Documents\gittin\src\services\CreateUserService.ts:8:71
    at new Promise (<anonymous>)

为了方便起见,这些是我认为的相关文件。请告诉我是否还有其他相关文件:

package.json:

{
  "name": "gittin",
  "version": "1.0.0",
  "main": "./dist/index.js",
  "repository": "https://github.com/joaocasarin/gittin.git",
  "author": "Joao Casarin <joaovitorcasarin@hotmail.com>",
  "license": "MIT",
  "scripts": {
    "db": "docker-compose -f ./docker-compose.db.yml up --build -d",
    "docker:dev": "docker-compose -f ./docker-compose.dev.yml up --build -d",
    "docker:prod": "docker-compose -f ./docker-compose.yml up --build -d",
    "docker:clear": "docker-compose down -v --rmi local",
    "docker:stop": "docker-compose down",
    "dev": "ts-node-dev ./src/index.ts",
    "test": "jest",
    "migration:run": "ts-node-dev ./node_modules/typeorm/cli.js migration:run",
    "migration:create": "ts-node-dev ./node_modules/typeorm/cli.js migration:create",
    "entity:create": "ts-node-dev ./node_modules/typeorm/cli.js entity:create",
    "build": "tsc",
    "start": "node ."
  },
  "dependencies": {
    "axios": "^0.21.1",
    "bcryptjs": "^2.4.3",
    "class-transformer": "^0.4.0",
    "cors": "^2.8.5",
    "dotenv": "^10.0.0",
    "express": "^4.17.1",
    "express-async-errors": "^3.1.1",
    "jsonwebtoken": "^8.5.1",
    "pg": "^8.6.0",
    "reflect-metadata": "^0.1.13",
    "typeorm": "^0.2.34",
    "uuid": "^8.3.2"
  },
  "devDependencies": {
    "@types/babel__core": "^7.1.15",
    "@types/bcryptjs": "^2.4.2",
    "@types/cors": "^2.8.10",
    "@types/express": "^4.17.12",
    "@types/jest": "^26.0.23",
    "@types/jsonwebtoken": "^8.5.4",
    "@types/node": "^15.12.4",
    "@types/supertest": "^2.0.11",
    "@types/uuid": "^8.3.1",
    "jest": "^27.0.5",
    "supertest": "^6.1.3",
    "ts-jest": "^27.0.3",
    "ts-node-dev": "^1.1.6",
    "typescript": "^4.3.4"
  }
}

ormconfig.js:

module.exports = {
    "type": "postgres",
    "ssl": process.env.NODE_ENV === 'production'
           && process.env.DATABASE_URL !== 'postgres://postgres:docker@localhost:5432/gittin'
           && process.env.DATABASE_URL !== 'postgres://postgres:docker@db:5432/gittin' ? { rejectUnauthorized: false } : false,

    "url": process.env.DATABASE_URL,
    
    "entities": ["dist/entities/*.js"], // typeorm loads entities from this directory
    "migrations": ["dist/database/migrations/*.js"], // typeorm loads migrations from the directory

    "dropSchema": process.env.NODE_ENV === 'test' ? true : false,
    "migrationsRun": process.env.NODE_ENV !== 'production' ? true : false,

    "cli": {
        "migrationsDir": "src/database/migrations", // typeorm creates migrations in this directory
        "entitiesDir": "src/entities" // typeorm creates entities in this directory
    }
}

src/entities/User.ts:

import { Entity, PrimaryColumn, Column, CreateDateColumn, UpdateDateColumn } from "typeorm";
import { Exclude } from "class-transformer";
import { v4 as uuid } from "uuid";

@Entity("users")
class User {

    @PrimaryColumn()
    readonly id: string;

    @Column()
    name: string;

    @Column()
    email: string;

    @Column()
    admin: boolean;

    @Exclude()
    @Column()
    password: string;

    @CreateDateColumn()
    created_at: Date;

    @UpdateDateColumn()
    updated_at: Date;

    constructor() {
        if (!this.id) {
            this.id = uuid();
        }
    }
}

export { User };

src/repositories/UserRepositories.ts:

import { EntityRepository, Repository } from "typeorm";
import { User } from "../entities/User";

@EntityRepository(User)
class UsersRepositories extends Repository<User> {}

export { UsersRepositories };

src/services/CreateUserService.ts:

import { getCustomRepository } from "typeorm";
import { UsersRepositories } from "../repositories/UsersRepositories";
import { hash } from "bcryptjs";

interface IUserRequest {
    name: string;
    email: string;
    admin?: boolean;
    password: string;
}

class CreateUserService {
    async execute({ name, email, admin = false, password }: IUserRequest) {
            const usersRepository = getCustomRepository(UsersRepositories);

            if(!email) {
                throw new Error('Incorrect e-mail.');
            }

            const userAlreadyExists = await usersRepository.findOne({ email });

            if(userAlreadyExists) {
                throw new Error('User already exists.');
            }

            const passwordHash = await hash(password, 8);

            const user = usersRepository.create({ name, email, admin, password: passwordHash });

            await usersRepository.save(user);

            return user;
    }
}

export { CreateUserService };

src/controllers/CreateUserController.ts:

import { Request, Response } from "express";
import { CreateUserService } from "../services/CreateUserService";

class CreateUserController {
    async handle(request: Request, response: Response) {
        try {
            const { name, email, admin, password } = request.body;

            const createUserService = new CreateUserService();

            const user = await createUserService.execute({ name, email, admin, password });

            return response.send(user);
        } catch (error) {
            return response.send({ error });
        }
    }
}

export { CreateUserController };

src/routes/index.ts:

import { Router, Request, Response, NextFunction } from "express";
import { CreateUserController } from "../controllers/CreateUserController";

const router = Router();

const createUserController = new CreateUserController();
router.post('/users', createUserController.handle);

export default router;

【问题讨论】:

    标签: javascript node.js typescript typeorm


    【解决方案1】:

    首先,你的 git repo 对发现问题很有帮助。您只需要更新您的ormconfig.js 文件,如下所示:

    module.exports = {
        ...
        "entities": ["src/entities/*{.js,.ts}"], // typeorm loads entities from this directory
        ...
        }
    }
    

    我只测试了npm run dev,它使用ts-node-dev 来执行你的文件。

    当它被编译并在生产环境中运行时,您可能需要更改它。

    【讨论】:

    • 嗨@Eranga Heshan,感谢您的回答。正如我所说,我也尝试过这种修改,我确实把entities 和你的一样,但是没有用。现在我又试了一次,它成功了,所以我决定做这样的事情:"entities": ["**/entities/*.{js,ts}"]。它应该使实体在生产和开发中都可见,我对迁移做了同样的事情,现在一切正常,但我不知道为什么,因为昨天没有进行完全相同的修改。
    猜你喜欢
    • 2020-06-25
    • 2020-11-02
    • 2019-01-04
    • 2018-05-09
    • 1970-01-01
    • 1970-01-01
    • 2022-10-06
    • 2022-10-20
    • 2022-08-18
    相关资源
    最近更新 更多