Browse Source

feat: add entity and swagger

IlhamTahir 1 year ago
parent
commit
346742b157

+ 12 - 4
package.json

@@ -8,9 +8,9 @@
   "scripts": {
     "build": "nest build",
     "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
-    "start": "nest start",
-    "start:dev": "nest start --watch",
-    "start:debug": "nest start --debug --watch",
+    "start": "NODE_ENV=development nest start",
+    "start:dev": "NODE_ENV=development nest start --watch",
+    "start:debug": "NODE_ENV=development nest start --debug --watch",
     "start:prod": "node dist/main",
     "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
     "test": "jest",
@@ -21,10 +21,18 @@
   },
   "dependencies": {
     "@nestjs/common": "^10.0.0",
+    "@nestjs/config": "^3.3.0",
     "@nestjs/core": "^10.0.0",
     "@nestjs/platform-express": "^10.0.0",
+    "@nestjs/swagger": "^8.0.7",
+    "@nestjs/typeorm": "^10.0.2",
+    "class-transformer": "^0.5.1",
+    "class-validator": "^0.14.1",
+    "mysql2": "^3.11.4",
     "reflect-metadata": "^0.2.0",
-    "rxjs": "^7.8.1"
+    "rxjs": "^7.8.1",
+    "snowflake-id": "^1.1.0",
+    "typeorm": "^0.3.20"
   },
   "devDependencies": {
     "@nestjs/cli": "^10.0.0",

File diff suppressed because it is too large
+ 455 - 15
pnpm-lock.yaml


+ 0 - 22
src/app.controller.spec.ts

@@ -1,22 +0,0 @@
-import { Test, TestingModule } from '@nestjs/testing';
-import { AppController } from './app.controller';
-import { AppService } from './app.service';
-
-describe('AppController', () => {
-  let appController: AppController;
-
-  beforeEach(async () => {
-    const app: TestingModule = await Test.createTestingModule({
-      controllers: [AppController],
-      providers: [AppService],
-    }).compile();
-
-    appController = app.get<AppController>(AppController);
-  });
-
-  describe('root', () => {
-    it('should return "Hello World!"', () => {
-      expect(appController.getHello()).toBe('Hello World!');
-    });
-  });
-});

+ 0 - 12
src/app.controller.ts

@@ -1,12 +0,0 @@
-import { Controller, Get } from '@nestjs/common';
-import { AppService } from './app.service';
-
-@Controller()
-export class AppController {
-  constructor(private readonly appService: AppService) {}
-
-  @Get()
-  getHello(): string {
-    return this.appService.getHello();
-  }
-}

+ 4 - 5
src/app.module.ts

@@ -1,10 +1,9 @@
 import { Module } from '@nestjs/common';
-import { AppController } from './app.controller';
-import { AppService } from './app.service';
+import { CoreModule } from './core/core.module';
 
 @Module({
-  imports: [],
-  controllers: [AppController],
-  providers: [AppService],
+  imports: [CoreModule],
+  controllers: [],
+  providers: [],
 })
 export class AppModule {}

+ 0 - 8
src/app.service.ts

@@ -1,8 +0,0 @@
-import { Injectable } from '@nestjs/common';
-
-@Injectable()
-export class AppService {
-  getHello(): string {
-    return 'Hello World!';
-  }
-}

+ 31 - 0
src/core/core.module.ts

@@ -0,0 +1,31 @@
+import { Global, Module } from '@nestjs/common';
+import { TypeOrmModule } from '@nestjs/typeorm';
+import { ConfigModule, ConfigService } from '@nestjs/config';
+
+@Module({
+  imports: [
+    ConfigModule.forRoot({
+      isGlobal: true,
+      envFilePath: [
+        '.env', // 通用配置,最低优先级
+        `.env.${process.env.NODE_ENV}`, // 环境配置,如 .env.development
+        `.env.${process.env.NODE_ENV}.local`, // 本地配置,最高优先级
+      ],
+    }),
+    TypeOrmModule.forRootAsync({
+      useFactory: async (configService: ConfigService) => ({
+        type: 'mysql',
+        host: configService.get<string>('DB_HOST'),
+        port: configService.get<number>('DB_PORT'),
+        username: configService.get<string>('DB_USERNAME'),
+        password: configService.get<string>('DB_PASSWORD'),
+        database: configService.get<string>('DB_NAME'),
+        autoLoadEntities: true,
+        synchronize: process.env.NODE_ENV === 'development',
+      }),
+      inject: [ConfigService],
+    }),
+  ],
+})
+@Global()
+export class CoreModule {}

+ 13 - 0
src/core/entity/base.entity.ts

@@ -0,0 +1,13 @@
+import { CreateDateColumn, PrimaryColumn, UpdateDateColumn } from 'typeorm';
+import { SnowflakeUtil } from '../util/snowflake.util';
+
+export abstract class BaseEntity {
+  @PrimaryColumn()
+  id: string = SnowflakeUtil.generateId();
+
+  @CreateDateColumn()
+  createdTime: Date;
+
+  @UpdateDateColumn()
+  updatedTime: Date;
+}

+ 12 - 0
src/core/entity/traceable.entity.ts

@@ -0,0 +1,12 @@
+import { BaseEntity } from './base.entity';
+import { Entity, ManyToOne } from 'typeorm';
+import { User } from './user.entity';
+
+@Entity()
+export abstract class TraceableEntity extends BaseEntity {
+  @ManyToOne(() => User)
+  createBy: User;
+
+  @ManyToOne(() => User)
+  updateBy: User;
+}

+ 23 - 0
src/core/entity/user.entity.ts

@@ -0,0 +1,23 @@
+import { Column, Entity } from 'typeorm';
+import { BaseEntity } from './base.entity';
+
+@Entity()
+export class User extends BaseEntity {
+  @Column({
+    unique: true,
+  })
+  username: string;
+
+  @Column()
+  encryptedPassword: string;
+
+  @Column({
+    default: false,
+  })
+  locked: boolean;
+
+  @Column({
+    default: true,
+  })
+  enabled: boolean;
+}

+ 19 - 0
src/core/util/snowflake.util.ts

@@ -0,0 +1,19 @@
+import SnowflakeID from 'snowflake-id';
+
+export class SnowflakeUtil {
+  private static instance: SnowflakeID;
+
+  static initialize(workerId: number = 1, datacenterId: number = 1): void {
+    this.instance = new SnowflakeID({
+      workerId, // 机器 ID
+      datacenterId, // 数据中心 ID
+    });
+  }
+
+  static generateId(): string {
+    if (!this.instance) {
+      throw new Error('SnowflakeUtil is not initialized.');
+    }
+    return this.instance.generate().toString();
+  }
+}

+ 21 - 0
src/main.ts

@@ -1,8 +1,29 @@
 import { NestFactory } from '@nestjs/core';
 import { AppModule } from './app.module';
+import { SnowflakeUtil } from './core/util/snowflake.util';
+import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
+import { ValidationPipe } from '@nestjs/common';
 
 async function bootstrap() {
   const app = await NestFactory.create(AppModule);
+  if (['development', 'test'].includes(process.env.NODE_ENV)) {
+    const config = new DocumentBuilder()
+      .setTitle(process.env.APP_TITLE)
+      .setDescription('The api description')
+      .setVersion('1.0')
+      .build();
+    const document = SwaggerModule.createDocument(app, config);
+    SwaggerModule.setup('docs', app, document);
+  }
+  SnowflakeUtil.initialize(
+    parseInt(process.env.WORKER_ID, 10),
+    parseInt(process.env.DATACENTER_ID, 10),
+  );
+  app.useGlobalPipes(
+    new ValidationPipe({
+      transform: true,
+    }),
+  );
   await app.listen(3000);
 }
 bootstrap();

Some files were not shown because too many files changed in this diff