Website-Suche

typescript - Nx-NestJS-TypeOrm: Syntaxfehler: Unerwartetes Zeichen {


Nach stundenlangem Graben brauche ich deine Hilfe!

Der Kontext

Ich erstelle derzeit (frühe Phase) eine Anwendung mit dem Stack: Nx (Monorepo) + NestJS + TypeOrm

Hier ist meine ormconfig-Datei:

    "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"]
    }
  }

Hier ist meine Migrationsdatei:

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')
      }

}

Das Problem

Wenn ich den Befehl ng serve api ausführe, um mein Backend zu starten, stoße ich auf dieses Problem:

Syntaxfehler: Unerwartetes Token {...

Der Fehler stammt aus meiner Migrationsdatei: apps\api\src\migration\1573343025001-users.ts:1

Was mich stört

Wenn ich meine Migration mit dem TypeORM-Befehl ausführe, kann TypeORM sie ohne Probleme ausführen. Migration users1573343025001 wurde erfolgreich ausgeführt! Deshalb verstehe ich nicht, warum die Migrationsdatei für meine App während der Migration korrekt aussieht, aber während der Ausführung nicht.

Was ich bereits versucht habe

  • Viele Antworten zu diesem Thema sind: Ändere das Migrationsverzeichnis zu dist/migration. Aber ich versuche nur, die App zu starten, nicht sie zu bauen.
  • Erstellen Sie die Datei mit dem TypeORM-Befehl neu
  • Überprüfen Sie, ob meine package.json die Zeile enthält: "typeorm": "ts-node -r tsconfig-paths/register ./node_modules/typeorm/cli.js",, um in TypeScript auszuführen
  • npm installieren (Wer weiß?)
  • Löschen Sie die Migration und führen Sie den Befehl ng serve api aus, die App startete ohne Anzeichen eines Fehlers

Ich übersehe wahrscheinlich eine grundlegende Sache bei diesen Technologien, die mir neu sind. Ich hoffe, all dies ist klar genug, damit Sie die Situation verstehen können.

Danke,

Séb

Antwort #1

Wahrscheinlich hat der OP eine Lösung gefunden. Dies ist für andere, die auf dieses Problem gestoßen sind.

Sieh dir https://github.com/nestjs/typeorm/issues/150#issuecomment-510716686 und den nächsten Kommentar für eine Lösung des Problems an.

Nach dem Transpilationsprozess können Sie keine .ts-Dateien laden. Ändern Sie entweder den Pfad, der an die Entitäten übergeben wird, basierend auf der Umgebung, oder fügen Sie die Entitäten direkt in dieses Array ein.

Ich wollte das Entities-Array nicht jedes Mal aktualisieren müssen, wenn eine neue Entität erstellt wird, also habe ich mich entschieden, das Dateiglob-Muster zu aktualisieren.

Das Wesentliche der Lösung:

/* 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')],

Jetzt wirft npm run start:dev oder npm run start:debug keine Fehler mehr.

Hier ist die vollständige configuration.ts und app.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 {}

Verwandte Artikel