From 74dd87ec608a3a0790af64892c6a0749c138689b Mon Sep 17 00:00:00 2001 From: stevereis <stevereis93@gmail.com> Date: Sat, 26 Mar 2022 16:10:56 +0100 Subject: [PATCH] fix: Typeorm issue with entity name (user) fix: Add migration for production DB --- api/.env.defaults | 7 ------ api/ormconfig.ts | 20 ++++++++++++++++ api/package.json | 5 +++- api/src/config/db.config.ts | 12 ++++++++++ api/src/engine/models/category.model.ts | 4 ++-- api/src/engine/models/dataset.model.ts | 4 ++-- api/src/engine/models/domain.model.ts | 4 ++-- api/src/engine/models/entity.model.ts | 2 +- api/src/engine/models/group.model.ts | 4 ++-- api/src/engine/models/variable.model.ts | 4 ++-- api/src/main.ts | 2 +- api/src/main/app.module.ts | 23 +++++++++++-------- api/src/migrations/1648306965760-initSetup.ts | 15 ++++++++++++ api/src/users/models/user.model.ts | 4 ++-- api/src/users/users.service.ts | 4 ++-- api/tsconfig.build.json | 2 +- 16 files changed, 81 insertions(+), 35 deletions(-) create mode 100644 api/ormconfig.ts create mode 100644 api/src/config/db.config.ts create mode 100644 api/src/migrations/1648306965760-initSetup.ts diff --git a/api/.env.defaults b/api/.env.defaults index ec63f00..eda459d 100644 --- a/api/.env.defaults +++ b/api/.env.defaults @@ -14,10 +14,3 @@ AUTH_JWT_SECRET=SecretForDevPurposeOnly AUTH_JWT_TOKEN_EXPIRES_IN=2d AUTH_COOKIE_SAME_SITE=strict AUTH_COOKIE_SECURE=true - -#DB -DB_HOST=localhost -DB_PORT=5454 -DB_USERNAME=postgres -DB_PASSWORD=pass123 -DB_NAME=postgres diff --git a/api/ormconfig.ts b/api/ormconfig.ts new file mode 100644 index 0000000..27afa05 --- /dev/null +++ b/api/ormconfig.ts @@ -0,0 +1,20 @@ +import { ConfigModule } from '@nestjs/config'; +import dbConfiguration from './src/config/db.config'; + +ConfigModule.forRoot({ + isGlobal: true, + envFilePath: ['.env', '.env.defaults'], + load: [dbConfiguration], +}); + +const config = { + ...dbConfiguration(), + entities: ['dist/**/*.entity.js', 'dist/**/*.model.js'], + migrations: ['dist/migrations/*{.ts,.js}'], + migrationsRun: false, + cli: { + migrationsDir: 'src/migrations', + }, +}; + +export default config; diff --git a/api/package.json b/api/package.json index 142d29f..50b0668 100644 --- a/api/package.json +++ b/api/package.json @@ -20,7 +20,10 @@ "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand", "test:e2e": "jest --config ./test/jest.e2e-config.ts", "test:we2e": "jest --watch --config ./test/jest.e2e-config.ts", - "prepare": "cd .. && husky install api/.husky" + "prepare": "cd .. && husky install api/.husky", + "typeorm": "node --require ts-node/register ./node_modules/typeorm/cli.js", + "typeorm:migration:generate": "npm run typeorm -- migration:generate -n", + "typeorm:migration:run": "npm run typeorm -- migration:run" }, "dependencies": { "@nestjs/apollo": "^10.0.6", diff --git a/api/src/config/db.config.ts b/api/src/config/db.config.ts new file mode 100644 index 0000000..346dbff --- /dev/null +++ b/api/src/config/db.config.ts @@ -0,0 +1,12 @@ +import { registerAs } from '@nestjs/config'; + +export default registerAs('database', () => { + return { + type: 'postgres', + host: process.env.DB_HOST || 'localhost', + port: +process.env.DB_PORT || 5432, + username: process.env.DB_USERNAME || 'postgres', + password: process.env.DB_PASSWORD || 'pass123', + database: process.env.DB_NAME || 'postgres', + }; +}); diff --git a/api/src/engine/models/category.model.ts b/api/src/engine/models/category.model.ts index 921ebfc..2000d8f 100644 --- a/api/src/engine/models/category.model.ts +++ b/api/src/engine/models/category.model.ts @@ -1,5 +1,5 @@ import { ObjectType } from '@nestjs/graphql'; -import { Entity } from './entity.model'; +import { BaseModel } from './entity.model'; @ObjectType() -export class Category extends Entity {} +export class Category extends BaseModel {} diff --git a/api/src/engine/models/dataset.model.ts b/api/src/engine/models/dataset.model.ts index a15340b..74bf78d 100644 --- a/api/src/engine/models/dataset.model.ts +++ b/api/src/engine/models/dataset.model.ts @@ -1,8 +1,8 @@ import { Field, ObjectType } from '@nestjs/graphql'; -import { Entity } from './entity.model'; +import { BaseModel } from './entity.model'; @ObjectType() -export class Dataset extends Entity { +export class Dataset extends BaseModel { @Field({ nullable: true, defaultValue: false }) isLongitudinal?: boolean; } diff --git a/api/src/engine/models/domain.model.ts b/api/src/engine/models/domain.model.ts index 1cfef22..9fe8262 100644 --- a/api/src/engine/models/domain.model.ts +++ b/api/src/engine/models/domain.model.ts @@ -1,11 +1,11 @@ import { Field, ObjectType } from '@nestjs/graphql'; import { Dataset } from './dataset.model'; -import { Entity } from './entity.model'; +import { BaseModel } from './entity.model'; import { Group } from './group.model'; import { Variable } from './variable.model'; @ObjectType() -export class Domain extends Entity { +export class Domain extends BaseModel { @Field({ nullable: true }) description?: string; diff --git a/api/src/engine/models/entity.model.ts b/api/src/engine/models/entity.model.ts index 32183fd..7641f7b 100644 --- a/api/src/engine/models/entity.model.ts +++ b/api/src/engine/models/entity.model.ts @@ -2,7 +2,7 @@ import { Field, InputType, ObjectType } from '@nestjs/graphql'; @InputType() @ObjectType() -export class Entity { +export class BaseModel { @Field() id: string; diff --git a/api/src/engine/models/group.model.ts b/api/src/engine/models/group.model.ts index 6a23f19..11be6a1 100644 --- a/api/src/engine/models/group.model.ts +++ b/api/src/engine/models/group.model.ts @@ -1,8 +1,8 @@ import { Field, ObjectType } from '@nestjs/graphql'; -import { Entity } from './entity.model'; +import { BaseModel } from './entity.model'; @ObjectType() -export class Group extends Entity { +export class Group extends BaseModel { @Field({ nullable: true }) description?: string; diff --git a/api/src/engine/models/variable.model.ts b/api/src/engine/models/variable.model.ts index bd54afe..c48a32b 100644 --- a/api/src/engine/models/variable.model.ts +++ b/api/src/engine/models/variable.model.ts @@ -1,10 +1,10 @@ import { Field, ObjectType } from '@nestjs/graphql'; import { Category } from './category.model'; -import { Entity } from './entity.model'; +import { BaseModel } from './entity.model'; import { Group } from './group.model'; @ObjectType() -export class Variable extends Entity { +export class Variable extends BaseModel { @Field({ nullable: true }) type?: string; diff --git a/api/src/main.ts b/api/src/main.ts index e336333..6e6fe7b 100644 --- a/api/src/main.ts +++ b/api/src/main.ts @@ -19,6 +19,6 @@ async function bootstrap() { app.use(cookieParser()); - await app.listen(process.env.GATEWAY_PORT); + await app.listen(process.env.GATEWAY_PORT || 8081); } bootstrap(); diff --git a/api/src/main/app.module.ts b/api/src/main/app.module.ts index 1555caa..56ef2df 100644 --- a/api/src/main/app.module.ts +++ b/api/src/main/app.module.ts @@ -1,11 +1,12 @@ import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo'; import { Module } from '@nestjs/common'; -import { ConfigModule } from '@nestjs/config'; +import { ConfigModule, ConfigService } from '@nestjs/config'; import { GraphQLModule } from '@nestjs/graphql'; import { TypeOrmModule } from '@nestjs/typeorm'; import { GraphQLError } from 'graphql'; import { join } from 'path'; import { AuthModule } from 'src/auth/auth.module'; +import dbConfig from 'src/config/db.config'; import { EngineModule } from 'src/engine/engine.module'; import { FilesModule } from 'src/files/files.module'; import { UsersModule } from 'src/users/users.module'; @@ -17,6 +18,7 @@ import { AppService } from './app.service'; ConfigModule.forRoot({ isGlobal: true, envFilePath: ['.env', '.env.defaults'], + load: [dbConfig], }), GraphQLModule.forRoot<ApolloDriverConfig>({ driver: ApolloDriver, @@ -44,15 +46,16 @@ import { AppService } from './app.service'; type: process.env.ENGINE_TYPE, baseurl: process.env.ENGINE_BASE_URL, }), - TypeOrmModule.forRoot({ - type: 'postgres', // type of our database - host: process.env.DB_HOST, // database host - port: parseInt(process.env.DB_PORT), // database host - username: process.env.DB_USERNAME, // username - password: process.env.DB_PASSWORD, // user password - database: process.env.DB_NAME, // name of our database, - autoLoadEntities: true, // models will be loaded automatically - synchronize: process.env.NODE_ENV !== 'production', // your entities will be synced with the database(recommended: disable in prod) + TypeOrmModule.forRootAsync({ + inject: [ConfigService], + useFactory: (config: ConfigService) => ({ + ...config.get('database'), + migrations: ['dist/migrations/*{.ts,.js}'], + migrationsRun: process.env.NODE_ENV !== 'dev', + synchronize: process.env.NODE_ENV === 'dev', + loggerLevel: 'debug', + autoLoadEntities: true, + }), }), AuthModule, UsersModule, diff --git a/api/src/migrations/1648306965760-initSetup.ts b/api/src/migrations/1648306965760-initSetup.ts new file mode 100644 index 0000000..ec93742 --- /dev/null +++ b/api/src/migrations/1648306965760-initSetup.ts @@ -0,0 +1,15 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class initSetup1648306965760 implements MigrationInterface { + name = 'initSetup1648306965760'; + + public async up(queryRunner: QueryRunner): Promise<void> { + await queryRunner.query( + `CREATE TABLE "user" ("id" character varying NOT NULL, "agreeNDA" boolean DEFAULT false, CONSTRAINT "PK_cace4a159ff9f2512dd42373760" PRIMARY KEY ("id"))`, + ); + } + + public async down(queryRunner: QueryRunner): Promise<void> { + await queryRunner.query(`DROP TABLE "user"`); + } +} diff --git a/api/src/users/models/user.model.ts b/api/src/users/models/user.model.ts index fc63052..980d7c1 100644 --- a/api/src/users/models/user.model.ts +++ b/api/src/users/models/user.model.ts @@ -1,7 +1,7 @@ import { Field, ObjectType } from '@nestjs/graphql'; import { Entity, PrimaryColumn, Column } from 'typeorm'; -@Entity() +@Entity({ name: 'user' }) @ObjectType() export class User { @PrimaryColumn() @@ -17,7 +17,7 @@ export class User { @Field({ nullable: true }) email?: string; - @Column() + @Column({ nullable: true, default: false }) @Field({ nullable: true }) agreeNDA?: boolean; diff --git a/api/src/users/users.service.ts b/api/src/users/users.service.ts index 273abf6..d74ca14 100644 --- a/api/src/users/users.service.ts +++ b/api/src/users/users.service.ts @@ -33,11 +33,11 @@ export class UsersService { * @returns The updated user. */ async update(id: string, data: UpdateUserInput): Promise<InternalUser> { - const test = { + const updateData = { id, ...data, }; - return await this.userRepository.save(test); + return await this.userRepository.save(updateData); } } diff --git a/api/tsconfig.build.json b/api/tsconfig.build.json index 64f86c6..8580c55 100644 --- a/api/tsconfig.build.json +++ b/api/tsconfig.build.json @@ -1,4 +1,4 @@ { "extends": "./tsconfig.json", - "exclude": ["node_modules", "test", "dist", "**/*spec.ts"] + "exclude": ["node_modules", "test", "dist", "**/*spec.ts", "ormconfig.ts"] } -- GitLab