From d4bd928e18faf3e02082ca1422528628fa1dc900 Mon Sep 17 00:00:00 2001 From: bqy_fe <1743369777@qq.com> Date: Fri, 4 Nov 2022 10:28:10 +0800 Subject: [PATCH] Release/1.9.1 (#19) --- .env | 3 - .github/workflows/build-dev.yml | 28 +++++ .github/workflows/build-latest.yml | 28 +++++ docker-compose.dev.yaml | 69 ----------- docker-compose.yaml | 6 +- package.json | 2 +- src/app.controller.ts | 9 +- src/app.dto.ts | 5 + src/app.service.ts | 109 ++++++++++++++++++ src/entities/apiData.entity.ts | 15 ++- src/entities/apiGroup.entity.ts | 10 +- src/entities/apiTestHistory.entity.ts | 10 +- src/entities/environment.entity.ts | 10 +- src/entities/mock.entity.ts | 10 +- src/entities/project.entity.ts | 34 +++++- src/entities/shared.entity.ts | 10 +- src/entities/user.entity.ts | 4 + .../1667469358917-update-table_1_9_1.ts | 38 ++++++ src/modules/auth/auth.service.ts | 4 + .../workspace/apiData/apiData.service.ts | 11 +- .../workspace/apiGroup/apiGroup.service.ts | 8 +- .../apiTestHistory/apiTestHistory.service.ts | 8 +- .../environment/environment.service.ts | 8 +- src/modules/workspace/mock/mock.service.ts | 7 +- .../workspace/shared/shared.service.ts | 8 +- src/modules/workspace/workspace.controller.ts | 2 +- src/utils/index.ts | 4 +- 27 files changed, 363 insertions(+), 97 deletions(-) create mode 100644 .github/workflows/build-dev.yml create mode 100644 .github/workflows/build-latest.yml delete mode 100644 docker-compose.dev.yaml create mode 100644 src/app.dto.ts create mode 100644 src/migrations/1667469358917-update-table_1_9_1.ts diff --git a/.env b/.env index d8c4f25..68cc99e 100644 --- a/.env +++ b/.env @@ -18,6 +18,3 @@ SWAGGER_VERSION=1.0 SWAGGER_TITLE=Eoapi-remote-server API文档 SWAGGER_DESC=Eoapi remote server API document。 -# eoapi-test-server -TEST_SERVER_PORT=4201 -EOAPI_WEBSOCKET_POST=4202 \ No newline at end of file diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml new file mode 100644 index 0000000..666791e --- /dev/null +++ b/.github/workflows/build-dev.yml @@ -0,0 +1,28 @@ +name: Build Dev Image + +on: + push: + branches: + - 'release/1.9.1' + +jobs: + docker: + runs-on: ubuntu-latest + steps: + - name: Set up QEMU + uses: docker/setup-qemu-action@v2 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + - name: Login to DockerHub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Build and push + id: docker_build + uses: docker/build-push-action@v3 + with: + push: true + tags: eolinker/eoapi-remote-server:1.9.1 + - name: Image digest + run: echo ${{ steps.docker_build.outputs.digest }} diff --git a/.github/workflows/build-latest.yml b/.github/workflows/build-latest.yml new file mode 100644 index 0000000..c3063fb --- /dev/null +++ b/.github/workflows/build-latest.yml @@ -0,0 +1,28 @@ +name: Build Latest Image + +on: + push: + branches: + - 'main' + +jobs: + docker: + runs-on: ubuntu-latest + steps: + - name: Set up QEMU + uses: docker/setup-qemu-action@v2 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + - name: Login to DockerHub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Build and push + id: docker_build + uses: docker/build-push-action@v3 + with: + push: true + tags: eolinker/eoapi-remote-server:latest + - name: Image digest + run: echo ${{ steps.docker_build.outputs.digest }} diff --git a/docker-compose.dev.yaml b/docker-compose.dev.yaml deleted file mode 100644 index 77a230f..0000000 --- a/docker-compose.dev.yaml +++ /dev/null @@ -1,69 +0,0 @@ -version: '3' - -services: - eoapi-remote-server-test: - # build: 从当前路径构建镜像 - # build: . - image: eolinker/eoapi-remote-server:1.9.0 - container_name: eoapi-remote-server-test - deploy: - restart_policy: - condition: on-failure - max_attempts: 10 - environment: - # 服务配置 - EOAPI_SERVER_PORT: 3001 - EOAPI_API_PREFIX: /api - MYSQL_HOST: host.docker.internal # 数据库地址 - TZ: Asia/Shanghai - # 数据库配置 - MYSQL_PORT: 33066 # 数据库端口号 - MYSQL_USERNAME: root - MYSQL_DATABASE: eoapi-test - MYSQL_PASSWORD: 123456a. - MYSQL_ROOT_PASSWORD: 123456a. - # swagger配置 - SWAGGER_PATH: swagger-docs - SWAGGER_ENABLE: 'true' - SWAGGER_VERSION: 1.0 - SWAGGER_TITLE: Eoapi-remote-server API文档 - SWAGGER_DESC: Eoapi remote server API document。 - extra_hosts: - - 'host.docker.internal:host-gateway' - ports: - - '3001:3001' - networks: - - eoapi_net - - eoapi: - image: eolinker/eoapi:1.9.0-dev - container_name: eoapi-dev - deploy: - restart_policy: - condition: on-failure - max_attempts: 3 - extra_hosts: - - 'host.docker.internal:host-gateway' - ports: - - '3002:80' - networks: - - eoapi_net - - eoapi-test-server: - image: eolinker/eoapi-test-server:1.9.0-dev - container_name: eoapi-test-server-dev - deploy: - restart_policy: - condition: on-failure - max_attempts: 3 - extra_hosts: - - 'host.docker.internal:host-gateway' - ports: - - '42011:4201' - - '42022:4202' - networks: - - eoapi_net - -networks: - eoapi_net: - name: eoapi_net diff --git a/docker-compose.yaml b/docker-compose.yaml index d822df9..baac0e9 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -3,7 +3,7 @@ version: '3' services: eoapi-remote-server: # build: 从当前路径构建镜像 - # build: . + build: . image: eolinker/eoapi-remote-server:latest container_name: eoapi-remote-server deploy: @@ -15,7 +15,7 @@ services: extra_hosts: - 'host.docker.internal:host-gateway' ports: - - 3000:3000 + - '${EOAPI_SERVER_PORT}:3000' # 当前服务启动之前先要把depends_on指定的服务启动起来才行 depends_on: - mysql @@ -33,7 +33,7 @@ services: env_file: - .env ports: - - 33066:3306 + - '${MYSQL_PORT}:3306' volumes: - ./sample/mysql/:/var/lib/mysql/ # ./sample/mysql/路径可以替换成自己的路径 networks: diff --git a/package.json b/package.json index 4181c0a..0873897 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "eoapi-remote-server", - "version": "1.9.0", + "version": "1.9.1", "description": "Storage api data in remote server", "author": "eoapi", "private": true, diff --git a/src/app.controller.ts b/src/app.controller.ts index d3ce1e0..8e3ec34 100644 --- a/src/app.controller.ts +++ b/src/app.controller.ts @@ -1,7 +1,8 @@ -import { Controller, Get } from '@nestjs/common'; +import { Body, Controller, Get, Post } from '@nestjs/common'; import { version } from '../package.json'; import { AppService } from './app.service'; import { Public } from '@/common/decorators/public.decorator'; +import { MockMatchDto } from '@/app.dto'; @Controller() export class AppController { @@ -18,4 +19,10 @@ export class AppController { status() { return version; } + + @Post('mock/match') + @Public() + mockMatch(@Body() body: MockMatchDto) { + return this.appService.mockMatch(body); + } } diff --git a/src/app.dto.ts b/src/app.dto.ts new file mode 100644 index 0000000..d93be3c --- /dev/null +++ b/src/app.dto.ts @@ -0,0 +1,5 @@ +export class MockMatchDto { + req: any; + projectID: number; + mockID: number; +} diff --git a/src/app.service.ts b/src/app.service.ts index bf3f556..d9eec46 100644 --- a/src/app.service.ts +++ b/src/app.service.ts @@ -1,8 +1,117 @@ import { Injectable } from '@nestjs/common'; +import { MockMatchDto } from '@/app.dto'; +import { ApiData } from '@/entities/apiData.entity'; +import { ApiDataService } from '@/modules/workspace/apiData/apiData.service'; +import { MockService } from '@/modules/workspace/mock/mock.service'; +import { tree2obj } from '@/utils'; @Injectable() export class AppService { + constructor( + private apiDataService: ApiDataService, + private mockService: MockService, + ) {} + getHello(): string { return 'Eoapi,Hello World!'; } + + async mockMatch(body: MockMatchDto) { + const { projectID, mockID, req } = body; + if (!Number.isNaN(Number(mockID))) { + try { + const mock = await this.mockService.findOne({ + where: { uuid: Number(mockID) }, + }); + if (mock === null) { + return { + statusCode: 404, + response: { + message: `mockID为${mockID}的mock不存在`, + }, + }; + } + const apiData = await this.apiDataService.findOne({ + where: { uuid: Number(mock.apiDataID) }, + }); + if (apiData === null) { + return { statusCode: 404 }; + } + if (mock?.createWay === 'system') { + return this.matchApiData(apiData, req); + } else { + const result = await this.matchApiData(apiData, req); + if (result.statusCode === 404) { + return result; + } + mock.response ??= this.generateResponse(apiData.responseBody); + } + return mock; + } catch (error) { + return { + response: { + message: error, + }, + }; + } + // Whether the matching request mode is enabled + } else { + const response = await this.batchMatchApiData(projectID, req); + return response; + } + } + + /** + * generate response data + * + * @returns + */ + generateResponse(responseBody: ApiData['responseBody']) { + return tree2obj([].concat(responseBody), { + key: 'name', + valueKey: 'description', + }); + } + /** + * match apiData by method and url + * + * @param projectID + * @param req + * @returns + */ + async matchApiData(apiData: ApiData, req?) { + const { restParams, queryParams, method } = apiData; + const { pathname } = new URL(req.url, 'http://localhost:3040'); + let uri = apiData.uri.trim(); + let isQueryMatch = true; + if (Array.isArray(restParams) && restParams.length > 0) { + const restMap = restParams.reduce( + (p, c) => ((p[c.name] = c.example), p), + {}, + ); + uri = uri.replace(/\{(.+?)\}/g, (match, p) => restMap[p] ?? match); + } + if (Array.isArray(queryParams) && queryParams.length > 0) { + const query = req.query; + isQueryMatch = queryParams.every((n) => n.example === query[n.name]); + } + const uriReg = new RegExp(`^/?${uri}/?$`); + const isMatch = + method === req.method && uriReg.test(pathname) && isQueryMatch; + return isMatch + ? { response: this.generateResponse(apiData.responseBody) } + : { statusCode: 404 }; + } + + async batchMatchApiData(projectID = 1, req) { + const apiDatas = await this.apiDataService.findAll({ projectID }); + let result; + for (const api of apiDatas) { + result = await this.matchApiData(api, req); + if (result?.statusCode !== 404) { + return result; + } + } + return result; + } } diff --git a/src/entities/apiData.entity.ts b/src/entities/apiData.entity.ts index 3f9c5b3..ee026a7 100644 --- a/src/entities/apiData.entity.ts +++ b/src/entities/apiData.entity.ts @@ -1,5 +1,8 @@ -import { Column, Entity, Generated } from 'typeorm'; +import { Column, Entity, Generated, ManyToOne, OneToMany } from 'typeorm'; +import { Exclude } from 'class-transformer'; import { Base } from './base.entity'; +import { Project } from './project.entity'; +import { Mock } from './mock.entity'; @Entity({ name: 'api_data' }) export class ApiData extends Base { @@ -54,4 +57,14 @@ export class ApiData extends Base { @Column({ default: 0 }) weight: number; + + @Exclude() + @ManyToOne(() => Project, (project) => project.apiData, { + onDelete: 'CASCADE', + }) + project: Project; + + @Exclude() + @OneToMany(() => Mock, (mock) => mock.apiData) + mock: Mock[]; } diff --git a/src/entities/apiGroup.entity.ts b/src/entities/apiGroup.entity.ts index 6987665..6bab2de 100644 --- a/src/entities/apiGroup.entity.ts +++ b/src/entities/apiGroup.entity.ts @@ -1,4 +1,6 @@ -import { Column, Entity } from 'typeorm'; +import { Column, Entity, ManyToOne } from 'typeorm'; +import { Exclude } from 'class-transformer'; +import { Project } from './project.entity'; import { Base } from './base.entity'; @Entity({ name: 'api_group' }) @@ -11,4 +13,10 @@ export class ApiGroup extends Base { @Column({ default: 0 }) weight: number; + + @Exclude() + @ManyToOne(() => Project, (project) => project.apiGroup, { + onDelete: 'CASCADE', + }) + project: Project; } diff --git a/src/entities/apiTestHistory.entity.ts b/src/entities/apiTestHistory.entity.ts index 02bbc86..b1d6ad7 100644 --- a/src/entities/apiTestHistory.entity.ts +++ b/src/entities/apiTestHistory.entity.ts @@ -1,4 +1,6 @@ -import { Column, Entity } from 'typeorm'; +import { Exclude } from 'class-transformer'; +import { Column, Entity, ManyToOne } from 'typeorm'; +import { Project } from './project.entity'; import { OperatorBase } from './base.entity'; @Entity({ name: 'api_test_history' }) @@ -17,4 +19,10 @@ export class ApiTestHistory extends OperatorBase { @Column({ type: 'json' }) response: string; + + @Exclude() + @ManyToOne(() => Project, (project) => project.apiTestHistory, { + onDelete: 'CASCADE', + }) + project: Project; } diff --git a/src/entities/environment.entity.ts b/src/entities/environment.entity.ts index 1c30919..8aa23bf 100644 --- a/src/entities/environment.entity.ts +++ b/src/entities/environment.entity.ts @@ -1,4 +1,6 @@ -import { Column, Entity } from 'typeorm'; +import { Exclude } from 'class-transformer'; +import { Column, Entity, ManyToOne } from 'typeorm'; +import { Project } from './project.entity'; import { Base } from './base.entity'; @Entity({ name: 'environment' }) @@ -11,4 +13,10 @@ export class Environment extends Base { @Column({ type: 'json', nullable: true }) parameters: string; + + @Exclude() + @ManyToOne(() => Project, (project) => project.environment, { + onDelete: 'CASCADE', + }) + project: Project; } diff --git a/src/entities/mock.entity.ts b/src/entities/mock.entity.ts index 361ad19..405fa6a 100644 --- a/src/entities/mock.entity.ts +++ b/src/entities/mock.entity.ts @@ -1,4 +1,6 @@ -import { Column, Entity } from 'typeorm'; +import { Exclude } from 'class-transformer'; +import { Column, Entity, ManyToOne } from 'typeorm'; +import { ApiData } from './apiData.entity'; import { Base } from './base.entity'; @Entity({ name: 'mock' }) @@ -14,4 +16,10 @@ export class Mock extends Base { @Column() createWay: string; + + @Exclude() + @ManyToOne(() => ApiData, (apiData) => apiData.mock, { + onDelete: 'CASCADE', + }) + apiData: ApiData; } diff --git a/src/entities/project.entity.ts b/src/entities/project.entity.ts index 0873d65..f00fa63 100644 --- a/src/entities/project.entity.ts +++ b/src/entities/project.entity.ts @@ -1,14 +1,19 @@ import { ApiHideProperty, ApiProperty } from '@nestjs/swagger'; import { Exclude } from 'class-transformer'; -import { Entity, JoinTable, ManyToMany, ManyToOne } from 'typeorm'; +import { Entity, JoinTable, ManyToMany, ManyToOne, OneToMany } from 'typeorm'; import { Base } from './base.entity'; import { WorkspaceEntity } from './workspace.entity'; import { UserEntity } from './user.entity'; +import { ApiData } from './apiData.entity'; +import { ApiGroup } from './apiGroup.entity'; +import { Environment } from './environment.entity'; +import { ApiTestHistory } from './apiTestHistory.entity'; +import { SharedEntity } from './shared.entity'; @Entity({ name: 'project' }) export class Project extends Base { @ApiProperty({ description: '项目所属空间' }) - @ManyToOne(() => WorkspaceEntity, (user) => user.projects, { + @ManyToOne(() => WorkspaceEntity, (workspace) => workspace.projects, { onDelete: 'CASCADE', }) workspace: WorkspaceEntity; @@ -18,4 +23,29 @@ export class Project extends Base { @ManyToMany(() => UserEntity, (user) => user.projects) @JoinTable() users: UserEntity[]; + + @ApiProperty({ description: '当前项目下的 apiData' }) + @Exclude() + @OneToMany(() => ApiData, (apiData) => apiData.project) + apiData: ApiData[]; + + @ApiProperty({ description: '当前项目下的 apiGroup' }) + @Exclude() + @OneToMany(() => ApiGroup, (apiGroup) => apiGroup.project) + apiGroup: ApiGroup[]; + + @ApiProperty({ description: '当前项目下的 apiTestHistory' }) + @Exclude() + @OneToMany(() => ApiTestHistory, (apiTestHistory) => apiTestHistory.project) + apiTestHistory: ApiGroup[]; + + @ApiProperty({ description: '当前项目下的 environment' }) + @Exclude() + @OneToMany(() => Environment, (environment) => environment.project) + environment: Environment[]; + + @ApiProperty({ description: '当前项目下的 shared' }) + @Exclude() + @OneToMany(() => SharedEntity, (shared) => shared.project) + shared: SharedEntity[]; } diff --git a/src/entities/shared.entity.ts b/src/entities/shared.entity.ts index 9ea0f05..e965e50 100644 --- a/src/entities/shared.entity.ts +++ b/src/entities/shared.entity.ts @@ -1,4 +1,6 @@ -import { Column, Entity, Generated } from 'typeorm'; +import { Exclude } from 'class-transformer'; +import { Column, Entity, Generated, ManyToOne } from 'typeorm'; +import { Project } from './project.entity'; import { FictitiousBase } from './base.entity'; @Entity({ name: 'shared' }) @@ -9,4 +11,10 @@ export class SharedEntity extends FictitiousBase { @Column() projectID: number; + + @Exclude() + @ManyToOne(() => Project, (project) => project.shared, { + onDelete: 'CASCADE', + }) + project: Project; } diff --git a/src/entities/user.entity.ts b/src/entities/user.entity.ts index 0d18185..2954350 100644 --- a/src/entities/user.entity.ts +++ b/src/entities/user.entity.ts @@ -43,6 +43,10 @@ export class UserEntity extends TimestampBase { @ApiProperty({ example: 'url', description: '用户头像' }) avatar: string; + @Column({ type: 'timestamp', nullable: true }) + @ApiProperty({ description: '最后登录时间' }) + lastLoginTime: Date; + @ApiHideProperty() @Exclude() @ManyToMany(() => WorkspaceEntity, (workspace) => workspace.users) diff --git a/src/migrations/1667469358917-update-table_1_9_1.ts b/src/migrations/1667469358917-update-table_1_9_1.ts new file mode 100644 index 0000000..21ee4ed --- /dev/null +++ b/src/migrations/1667469358917-update-table_1_9_1.ts @@ -0,0 +1,38 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class updateTable1911667469358917 implements MigrationInterface { + name = 'updateTable1911667469358917' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE \`user\` ADD \`lastLoginTime\` timestamp NULL`); + await queryRunner.query(`ALTER TABLE \`api_group\` ADD \`projectUuid\` int NULL`); + await queryRunner.query(`ALTER TABLE \`environment\` ADD \`projectUuid\` int NULL`); + await queryRunner.query(`ALTER TABLE \`api_test_history\` ADD \`projectUuid\` int NULL`); + await queryRunner.query(`ALTER TABLE \`shared\` ADD \`projectUuid\` int NULL`); + await queryRunner.query(`ALTER TABLE \`mock\` ADD \`apiDataUuid\` int NULL`); + await queryRunner.query(`ALTER TABLE \`api_data\` ADD \`projectUuid\` int NULL`); + await queryRunner.query(`ALTER TABLE \`api_group\` ADD CONSTRAINT \`FK_4c9f998ae6bc89ef7a5ad3d9d3c\` FOREIGN KEY (\`projectUuid\`) REFERENCES \`project\`(\`uuid\`) ON DELETE CASCADE ON UPDATE NO ACTION`); + await queryRunner.query(`ALTER TABLE \`environment\` ADD CONSTRAINT \`FK_eb347c0e0647044122bf5a837ad\` FOREIGN KEY (\`projectUuid\`) REFERENCES \`project\`(\`uuid\`) ON DELETE CASCADE ON UPDATE NO ACTION`); + await queryRunner.query(`ALTER TABLE \`api_test_history\` ADD CONSTRAINT \`FK_c5c21e17151420d32a003983f15\` FOREIGN KEY (\`projectUuid\`) REFERENCES \`project\`(\`uuid\`) ON DELETE CASCADE ON UPDATE NO ACTION`); + await queryRunner.query(`ALTER TABLE \`shared\` ADD CONSTRAINT \`FK_5261cf174dbbaf80ded486b90a5\` FOREIGN KEY (\`projectUuid\`) REFERENCES \`project\`(\`uuid\`) ON DELETE CASCADE ON UPDATE NO ACTION`); + await queryRunner.query(`ALTER TABLE \`mock\` ADD CONSTRAINT \`FK_369b5e31d6e3ac04039542b92e5\` FOREIGN KEY (\`apiDataUuid\`) REFERENCES \`api_data\`(\`uuid\`) ON DELETE CASCADE ON UPDATE NO ACTION`); + await queryRunner.query(`ALTER TABLE \`api_data\` ADD CONSTRAINT \`FK_2e2745ab4ece582a653c8092901\` FOREIGN KEY (\`projectUuid\`) REFERENCES \`project\`(\`uuid\`) ON DELETE CASCADE ON UPDATE NO ACTION`); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE \`api_data\` DROP FOREIGN KEY \`FK_2e2745ab4ece582a653c8092901\``); + await queryRunner.query(`ALTER TABLE \`mock\` DROP FOREIGN KEY \`FK_369b5e31d6e3ac04039542b92e5\``); + await queryRunner.query(`ALTER TABLE \`shared\` DROP FOREIGN KEY \`FK_5261cf174dbbaf80ded486b90a5\``); + await queryRunner.query(`ALTER TABLE \`api_test_history\` DROP FOREIGN KEY \`FK_c5c21e17151420d32a003983f15\``); + await queryRunner.query(`ALTER TABLE \`environment\` DROP FOREIGN KEY \`FK_eb347c0e0647044122bf5a837ad\``); + await queryRunner.query(`ALTER TABLE \`api_group\` DROP FOREIGN KEY \`FK_4c9f998ae6bc89ef7a5ad3d9d3c\``); + await queryRunner.query(`ALTER TABLE \`api_data\` DROP COLUMN \`projectUuid\``); + await queryRunner.query(`ALTER TABLE \`mock\` DROP COLUMN \`apiDataUuid\``); + await queryRunner.query(`ALTER TABLE \`shared\` DROP COLUMN \`projectUuid\``); + await queryRunner.query(`ALTER TABLE \`api_test_history\` DROP COLUMN \`projectUuid\``); + await queryRunner.query(`ALTER TABLE \`environment\` DROP COLUMN \`projectUuid\``); + await queryRunner.query(`ALTER TABLE \`api_group\` DROP COLUMN \`projectUuid\``); + await queryRunner.query(`ALTER TABLE \`user\` DROP COLUMN \`lastLoginTime\``); + } + +} diff --git a/src/modules/auth/auth.service.ts b/src/modules/auth/auth.service.ts index 03a9214..714d394 100644 --- a/src/modules/auth/auth.service.ts +++ b/src/modules/auth/auth.service.ts @@ -119,6 +119,10 @@ export class AuthService implements OnModuleInit { }) .save(); + userEntity.lastLoginTime = new Date(); + + this.userService.updateUser(userEntity); + return result; } } diff --git a/src/modules/workspace/apiData/apiData.service.ts b/src/modules/workspace/apiData/apiData.service.ts index 4969954..4ba289e 100644 --- a/src/modules/workspace/apiData/apiData.service.ts +++ b/src/modules/workspace/apiData/apiData.service.ts @@ -6,20 +6,23 @@ import { CreateDto } from './dto/create.dto'; import { UpdateDto } from './dto/update.dto'; import { QueryDto } from './dto/query.dto'; import { ApiData } from '@/entities/apiData.entity'; -import { Mock } from '@/entities/mock.entity'; +import { Project } from '@/entities/project.entity'; @Injectable() export class ApiDataService { constructor( @InjectRepository(ApiData) private readonly repository: Repository, - @InjectRepository(Mock) - private readonly mockRepository: Repository, + @InjectRepository(Project) + private readonly projectRepository: Repository, private readonly mockService: MockService, ) {} async create(createDto: CreateDto) { - const apiData = await this.repository.save(createDto); + const project = await this.projectRepository.findOneBy({ + uuid: createDto.projectID, + }); + const apiData = await this.repository.save({ ...createDto, project }); await this.mockService.create( this.mockService.createSystemMockDTO(apiData), 'system', diff --git a/src/modules/workspace/apiGroup/apiGroup.service.ts b/src/modules/workspace/apiGroup/apiGroup.service.ts index a2ba629..cc849b0 100644 --- a/src/modules/workspace/apiGroup/apiGroup.service.ts +++ b/src/modules/workspace/apiGroup/apiGroup.service.ts @@ -6,17 +6,23 @@ import { UpdateDto } from './dto/update.dto'; import { QueryDto } from './dto/query.dto'; import { ApiGroup } from '@/entities/apiGroup.entity'; import { ApiDataService } from '@/modules/workspace/apiData/apiData.service'; +import { Project } from '@/entities/project.entity'; @Injectable() export class ApiGroupService { constructor( @InjectRepository(ApiGroup) private readonly repository: Repository, + @InjectRepository(Project) + private readonly projectRepository: Repository, private apiDataService: ApiDataService, ) {} async create(createDto: CreateDto) { - return await this.repository.save(createDto); + const project = await this.projectRepository.findOneBy({ + uuid: createDto.projectID, + }); + return await this.repository.save({ ...createDto, project }); } async batchCreate(createDto: Array) { diff --git a/src/modules/workspace/apiTestHistory/apiTestHistory.service.ts b/src/modules/workspace/apiTestHistory/apiTestHistory.service.ts index 1f3d968..b641b71 100644 --- a/src/modules/workspace/apiTestHistory/apiTestHistory.service.ts +++ b/src/modules/workspace/apiTestHistory/apiTestHistory.service.ts @@ -5,18 +5,24 @@ import { CreateDto } from './dto/create.dto'; import { UpdateDto } from './dto/update.dto'; import { QueryDto } from './dto/query.dto'; import { ApiTestHistory } from '@/entities/apiTestHistory.entity'; +import { Project } from '@/entities/project.entity'; @Injectable() export class ApiTestHistoryService { constructor( @InjectRepository(ApiTestHistory) private readonly repository: Repository, + @InjectRepository(Project) + private readonly projectRepository: Repository, ) {} async create(createDto: CreateDto) { + const project = await this.projectRepository.findOneBy({ + uuid: createDto.projectID, + }); createDto.general ??= '{}'; createDto.apiDataID ??= -1; - return await this.repository.save(createDto); + return await this.repository.save({ ...createDto, project }); } async batchCreate(createDto: Array) { diff --git a/src/modules/workspace/environment/environment.service.ts b/src/modules/workspace/environment/environment.service.ts index e1a9059..e41a322 100644 --- a/src/modules/workspace/environment/environment.service.ts +++ b/src/modules/workspace/environment/environment.service.ts @@ -5,16 +5,22 @@ import { CreateDto } from './dto/create.dto'; import { UpdateDto } from './dto/update.dto'; import { QueryDto } from './dto/query.dto'; import { Environment } from '@/entities/environment.entity'; +import { Project } from '@/entities/project.entity'; @Injectable() export class EnvironmentService { constructor( @InjectRepository(Environment) private readonly repository: Repository, + @InjectRepository(Project) + private readonly projectRepository: Repository, ) {} async create(createDto: CreateDto) { - return await this.repository.save(createDto); + const project = await this.projectRepository.findOneBy({ + uuid: createDto.projectID, + }); + return await this.repository.save({ ...createDto, project }); } async batchCreate(createDto: Array) { diff --git a/src/modules/workspace/mock/mock.service.ts b/src/modules/workspace/mock/mock.service.ts index 9e196aa..0911530 100644 --- a/src/modules/workspace/mock/mock.service.ts +++ b/src/modules/workspace/mock/mock.service.ts @@ -17,6 +17,8 @@ export class MockService { constructor( @InjectRepository(Mock) private readonly repository: Repository, + @InjectRepository(ApiData) + private readonly apiDataRepository: Repository, private moduleRef: ModuleRef, ) {} @@ -25,8 +27,11 @@ export class MockService { } async create(createDto: CreateDto, createWay: CreateWay = 'custom') { + const apiData = await this.apiDataRepository.findOneBy({ + uuid: createDto.apiDataID, + }); createDto.createWay = createWay; - return await this.repository.save(createDto); + return await this.repository.save({ ...createDto, apiData }); } async batchCreate(createDto: Array) { diff --git a/src/modules/workspace/shared/shared.service.ts b/src/modules/workspace/shared/shared.service.ts index f7ed1e6..ea4e162 100644 --- a/src/modules/workspace/shared/shared.service.ts +++ b/src/modules/workspace/shared/shared.service.ts @@ -2,17 +2,23 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { FindOptionsWhere, Repository } from 'typeorm'; import { SharedEntity } from '@/entities/shared.entity'; +import { Project } from '@/entities/project.entity'; @Injectable() export class SharedService { constructor( @InjectRepository(SharedEntity) private readonly sharedEntityRepository: Repository, + @InjectRepository(Project) + private readonly projectRepository: Repository, ) {} async createShared(projectID: number) { + const project = await this.projectRepository.findOneBy({ + uuid: projectID, + }); const shared = await this.findOneBy({ projectID }); - return shared ?? this.sharedEntityRepository.save({ projectID }); + return shared ?? this.sharedEntityRepository.save({ projectID, project }); } async deleteShared(uniqueID: string, projectID: number) { diff --git a/src/modules/workspace/workspace.controller.ts b/src/modules/workspace/workspace.controller.ts index 0993c46..836c1d4 100644 --- a/src/modules/workspace/workspace.controller.ts +++ b/src/modules/workspace/workspace.controller.ts @@ -60,7 +60,7 @@ export class WorkspaceController { sampleApiData.map((item) => { Reflect.deleteProperty(item, 'uuid'); Reflect.deleteProperty(item, 'uniqueID'); - return { ...item, projectID: project.uuid }; + return { ...item, projectID: project.uuid, project }; }), ); return workspace; diff --git a/src/utils/index.ts b/src/utils/index.ts index 2066558..96c18d1 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -35,8 +35,9 @@ export const tree2obj = ( curr = typeof curr === 'string' ? JSON.parse(curr) : curr; prev[curr[key]] = curr[valueKey] || fieldTypeMap.get(curr.type); if (Array.isArray(curr[childKey]) && curr[childKey].length > 0) { - console.log(`prev: ${prev} == curr: ${curr} == key: ${key}`); tree2obj(curr[childKey], opts, (prev[curr[key]] = {})); + } else if (curr?.example) { + prev[curr[key]] = curr?.example; } } catch (error) { console.log('error==>', `prev: ${prev} == curr: ${curr} == key: ${key}`); @@ -44,7 +45,6 @@ export const tree2obj = ( return prev; }, initObj); }; - /** * check dev env * @returns boolean true is dev