【问题标题】:Nx-NestJS-TypeOrm: SyntaxError: Unexpected token {Nx-NestJS-TypeOrm: SyntaxError: Unexpected token {
【发布时间】:2020-03-13 02:57:34
【问题描述】:

经过几个小时的挖掘,我需要你的帮助!

上下文

我目前正在使用堆栈创建(早期阶段)一个应用程序:Nx(monorepo) + NestJS + TypeOrm

这是我的 ormconfig 文件:

    "type": "postgres",
    "host": "localhost",
    "port": 5432,
    "username": "***",
    "password": "****",
    "database": "****",
    "synchronize": false,
    "logging":false,
    "entities": ["apps/api/src/app/**/**.entity.ts"],
    "migrations":["apps/api/src/migration/**.ts"],
    "cli":{        
        "migrationsDir":["apps/api/src/migration"],
        "entitiesDir":["apps/api/src/app/**/**.entity.ts"]
    }
  }

这是我的迁移文件:

import {MigrationInterface, QueryRunner, Table} from "typeorm";

export class users1573343025001 implements MigrationInterface {
    public async up (queryRunner: QueryRunner): Promise<any> {
        await queryRunner.createTable(new Table({
          name: 'users',
          columns: [
            { name: 'id', type: 'bigint', isPrimary: true,
 isGenerated: true, generationStrategy: 'increment', unsigned: true },
            { name: 'username', type: 'varchar', isNullable: false },
            { name: 'password', type: 'varchar', isNullable: true },
          ]
        }))
      }

      public async down (queryRunner: QueryRunner): Promise<any> {
        await queryRunner.dropTable('users')
      }

}

问题

当我运行命令 ng serve api 来运行我的后端时,我遇到了这个问题:

SyntaxError: Unexpected token {...

错误来自我的迁移文件:apps\api\src\migration\1573343025001-users.ts:1

什么让我烦恼

如果我使用 typeorm 命令运行迁移,typeorm 可以毫无问题地运行它。 迁移 users1573343025001 已成功执行! 所以我不明白为什么迁移文件在迁移期间但在运行期间对我的应用程序看起来是正确的。

我已经尝试过的

  • 围绕这个主题的很多答案是:将迁移目录更改为 dist/migration。但我只是想为应用提供服务,而不是构建它。
  • 使用 typeorm 命令重新创建文件
  • 验证我的 package.json 是否有行:"typeorm": "ts-node -r tsconfig-paths/register ./node_modules/typeorm/cli.js", 在 typescript 中执行
  • npm install(谁知道?)
  • 删除迁移并运行命令ng serve api,应用启动时没有任何错误迹象

我可能错过了这些对我来说是新的技术的基本内容。 希望这一切都足够清楚,让您了解情况。

谢谢,

塞伯

【问题讨论】:

    标签: typescript migration nestjs typeorm unexpected-token


    【解决方案1】:

    很可能 OP 已经找到了解决方案。这是为遇到此问题的其他人准备的。

    查看https://github.com/nestjs/typeorm/issues/150#issuecomment-510716686 和下一条评论,了解问题的解决方案。

    您无法在转译过程后加载.ts 文件。要么根据环境改变传递给实体的路径,要么将实体直接放到这个数组中。

    我不想在每次创建新实体时都更新实体数组,所以我选择更新文件 glob 模式。

    解决方案的核心:

    /* replaced original two lines */
          // entities: ['**/*.entity{.ts,.js}'],
          // migrations: ['src/migration/*.ts'],
    
    /* with these two lines */
          entities: [path.join(__dirname, '../**/*.entity{.ts,.js}')],
          migrations: [path.join(__dirname, '../migration/*{.ts,.js')],
    

    现在npm run start:devnpm run start:debug 不会抛出错误。

    这是完整的 configuration.tsapp.module.ts

    // src/config/configuration.ts
    
    import { TypeOrmModuleOptions } from '@nestjs/typeorm';
    import path = require('path');
    
    export default () => {
      const customConfigService = new CustomConfigService(
        process.env,
      ).ensureValues([
        'DATABASE_HOST',
        'DATABASE_PORT',
        'DATABASE_USER',
        'DATABASE_PASSWORD',
        'DATABASE_NAME',
      ]);
      return {
        port: parseInt(process.env.PORT, 10) || 4000,
        database: {
          host: process.env.DATABASE_HOST,
          port: parseInt(process.env.DATABASE_PORT, 10) || 5432,
        },
        typeOrmModuleOptions: customConfigService.getTypeOrmConfig(),
      };
    };
    
    // see https://medium.com/@gausmann.simon/nestjs-typeorm-and-postgresql-full-example-development-and-project-setup-working-with-database-c1a2b1b11b8f
    class CustomConfigService {
      constructor(private env: { [k: string]: string | undefined }) {}
    
      private getValue(key: string, throwOnMissing = true): string {
        const value = this.env[key];
        if ((value === null || value === undefined) && throwOnMissing) {
          throw new Error(`config error - missing env.${key}`);
        }
        return value;
      }
    
      public ensureValues(keys: string[]) {
        keys.forEach(k => this.getValue(k, true));
        return this;
      }
    
      public getPort() {
        return this.getValue('PORT', true);
      }
    
      public isProduction() {
        const mode = this.getValue('NODE_ENV', false);
        return mode === 'production';
      }
    
      public getTypeOrmConfig(): TypeOrmModuleOptions {
        return {
          type: 'postgres',
    
          host: this.getValue('DATABASE_HOST'),
          port: parseInt(this.getValue('DATABASE_PORT')),
          username: this.getValue('DATABASE_USER'),
          password: this.getValue('DATABASE_PASSWORD'),
          database: this.getValue('DATABASE_NAME'),
    
          /* replaced original two lines */
          // entities: ['**/*.entity{.ts,.js}'],
          // migrations: ['src/migration/*.ts'],
    
          /* with these two lines */
          entities: [path.join(__dirname, '../**/*.entity{.ts,.js}')],
          migrations: [path.join(__dirname, '../migration/*{.ts,.js')],
    
          migrationsTableName: 'migration',
    
          cli: {
            migrationsDir: 'src/migration',
          },
    
          ssl: this.isProduction(),
        };
      }
    }
    
    // src/app.module.ts
    
    // lib imports
    import { Module } from '@nestjs/common';
    import { ConfigModule, ConfigService } from '@nestjs/config';
    import { TypeOrmModule, TypeOrmModuleOptions } from '@nestjs/typeorm';
    
    // local imports
    import { AppController } from './app.controller';
    import { AppService } from './app.service';
    import { ItemsModule } from './items/items.module';
    import configuration from './config/configuration';
    
    const envFilePath =
      process.env.NODE_ENV === 'production'
        ? 'envs/.production.env'
        : 'envs/.development.env';
    @Module({
      imports: [
        ConfigModule.forRoot({
          isGlobal: true,
          envFilePath,
          load: [configuration],
        }),
        // see https://stackoverflow.com/questions/53426486/best-practice-to-use-config-service-in-nestjs-module
        // see https://github.com/nestjs/nest/issues/530#issuecomment-415690676
        TypeOrmModule.forRootAsync({
          imports: [ConfigModule],
          useFactory: async (configService: ConfigService) => {
            const typeOrmModuleOptions = configService.get<TypeOrmModuleOptions>(
              'typeOrmModuleOptions',
            );
            console.log(`typeOrmModuleOptions= `, typeOrmModuleOptions);
            return typeOrmModuleOptions;
          },
          inject: [ConfigService],
        }),
        ItemsModule,
      ],
      controllers: [AppController],
      providers: [AppService],
    })
    export class AppModule {}
    

    【讨论】:

    • 这是否可以在 monorepo 中工作,因为 Nx 将使用 webpack 生成单个 main.js 文件,那时部署 dist 时 glob 模式将无法正常工作?
    • 同样的问题!由于 webpack 编译成单个 js 文件,它无法找到实体和迁移。有什么解决办法吗?
    猜你喜欢
    • 2021-04-24
    • 2019-11-08
    • 2012-05-17
    • 2019-02-10
    • 2019-11-10
    • 2014-07-08
    • 2013-11-15
    • 2020-09-26
    • 2011-03-09
    相关资源
    最近更新 更多