diff --git a/package.json b/package.json index 638b9ea..a8254a4 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,8 @@ "test:cov": "jest --coverage", "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.json", - "orm": "typeorm-ts-node-esm -d ./src/database/datasource/index.ts" + "orm": "typeorm-ts-node-esm -d ./src/database/datasource/index.ts", + "g": "plop --plopfile scripts/template/index.js" }, "prettier": { "printWidth": 120, diff --git a/scripts/template/index.js b/scripts/template/index.js index a4ee539..fb41f58 100644 --- a/scripts/template/index.js +++ b/scripts/template/index.js @@ -10,12 +10,23 @@ module.exports = function main(/** @type { import('plop').NodePlopAPI } */ plop) return filename.charAt(0).toUpperCase() + filename.slice(1); }); + plop.setHelper('lowcaseName', (name) => { + const filename = plop.getHelper('fileName')(name); + return filename.charAt(0).toLowerCase() + filename.slice(1); + }); + plop.setGenerator('module', { prompts: [ { name: 'name', message: '请输入模块名称', type: 'input', + validate: (input) => { + if (/^(\w+\/)*(\w+)$/.test(input)) { + return true; + } + return '请输入 / 格式, 且不包含中文的名称'; + }, }, { name: 'cnName', @@ -28,7 +39,7 @@ module.exports = function main(/** @type { import('plop').NodePlopAPI } */ plop) type: 'addMany', destination: join(process.cwd(), 'src/{{name}}'), base: 'module', - templateFiles: 'module/**/*.ts', + templateFiles: 'module/**/*.hbs', }, ], }); diff --git a/scripts/template/module/dto/create-{{fileName name}}.dto.ts.hbs b/scripts/template/module/dto/create-{{fileName name}}.dto.ts.hbs index 14fb0a3..654168d 100644 --- a/scripts/template/module/dto/create-{{fileName name}}.dto.ts.hbs +++ b/scripts/template/module/dto/create-{{fileName name}}.dto.ts.hbs @@ -1,37 +1,10 @@ -import { Role } from '@/modules/role/entities/role.entity'; -import { IsInt, IsOptional, IsString } from 'class-validator'; +import { IsString } from 'class-validator'; -export class CreateUserDto { +export class Create{{upcaseName name}}Dto { /** - * 登录账号 - * @example 'juetan' + * 字段描述(Swagger用途) + * @example 'demo' */ @IsString() - username: string; - /** - * 用户密码 - * @example 'password' - */ - @IsString() - password: string; - /** - * 用户昵称 - * @example '绝弹' - */ - @IsString() - nickname: string; - /** - * 用户头像 - * @example './assets/222421415123.png ' - */ - @IsOptional() - @IsString() - avatar: string; - /** - * 用户角色 - * @example [1, 2, 3] - */ - @IsOptional() - @IsInt({ each: true }) - roles: Role[]; + demo: string; } diff --git a/scripts/template/module/dto/find-{{fileName name}}.dto.ts.hbs b/scripts/template/module/dto/find-{{fileName name}}.dto.ts.hbs index f879eb3..c736847 100644 --- a/scripts/template/module/dto/find-{{fileName name}}.dto.ts.hbs +++ b/scripts/template/module/dto/find-{{fileName name}}.dto.ts.hbs @@ -2,12 +2,12 @@ import { PaginationDto } from '@/common/response'; import { IntersectionType } from '@nestjs/swagger'; import { IsOptional, IsString } from 'class-validator'; -export class FindUserDto extends IntersectionType(PaginationDto) { +export class Find{{upcaseName name}}Dto extends IntersectionType(PaginationDto) { /** - * 用户昵称 - * @example '绝弹' + * 字段描述(Swagger用途) + * @example '示例值' */ @IsOptional() @IsString() - nickname?: string; + demo?: string; } diff --git a/scripts/template/module/dto/update-{{fileName name}}.dto.ts.hbs b/scripts/template/module/dto/update-{{fileName name}}.dto.ts.hbs index 9a4ef92..cb1c76d 100644 --- a/scripts/template/module/dto/update-{{fileName name}}.dto.ts.hbs +++ b/scripts/template/module/dto/update-{{fileName name}}.dto.ts.hbs @@ -1,4 +1,4 @@ import { PartialType } from '@nestjs/swagger'; -import { CreateUserDto } from './create-{{fileName name}}.dto'; +import { Create{{upcaseName name}}Dto } from './create-{{fileName name}}.dto'; -export class UpdateUserDto extends PartialType(CreateUserDto) {} +export class Update{{upcaseName name}}Dto extends PartialType(Create{{upcaseName name}}Dto) {} diff --git a/scripts/template/module/entities/{{fileName name}}.entity.ts.hbs b/scripts/template/module/entities/{{fileName name}}.entity.ts.hbs index bcb9fa7..af40cf1 100644 --- a/scripts/template/module/entities/{{fileName name}}.entity.ts.hbs +++ b/scripts/template/module/entities/{{fileName name}}.entity.ts.hbs @@ -1,71 +1,12 @@ -import { ApiHideProperty } from '@nestjs/swagger'; -import { Exclude } from 'class-transformer'; import { BaseEntity } from '@/database'; -import { Post } from '@/modules/post'; -import { Role } from '@/modules/role'; -import { Column, Entity, JoinTable, ManyToMany, RelationId } from 'typeorm'; +import { Column, Entity } from 'typeorm'; @Entity({ orderBy: { id: 'DESC' } }) -export class User extends BaseEntity { +export class {{upcaseName name}} extends BaseEntity { /** - * 登录账号 - * @example 'juetan' + * 字段描述(Swagger用途) + * @example '示例值' */ - @Column({ length: 48 }) - username: string; - - /** - * 用户昵称 - * @example '绝弹' - */ - @Column({ length: 48 }) - nickname: string; - - /** - * 用户介绍 - * @example '这个人很懒, 什么也没有留下!' - */ - @Column({ default: '这个人很懒, 什么也没有留下!' }) - description: string; - - /** - * 用户头像(URL) - * @example './assets/222421415123.png ' - */ - @Column({ nullable: true }) - avatar: string; - - /** - * 用户密码 - * @example 'password' - */ - @Exclude() - @Column({ length: 64 }) - password: string; - - /** - * 用户邮箱 - * @example 'example@mail.com' - */ - @Column({ length: 64, nullable: true }) - email: string; - - /** - * 用户文章 - */ - @ApiHideProperty() - @ManyToMany(() => Post, (post) => post.author) - @JoinTable() - posts: Post[]; - - /** - * 用户角色 - */ - @ApiHideProperty() - @ManyToMany(() => Role, (role) => role.user) - @JoinTable() - roles: Role[]; - - @RelationId('roles') - roleIds: number[]; + @Column() + demo: string; } diff --git a/scripts/template/module/index.ts.hbs b/scripts/template/module/index.ts.hbs index eb0b703..91e9440 100644 --- a/scripts/template/module/index.ts.hbs +++ b/scripts/template/module/index.ts.hbs @@ -1,5 +1,3 @@ -export * from './dto/create-{{fileName name}}.dto'; -export * from './dto/update-{{fileName name}}.dto'; export * from './entities/{{fileName name}}.entity'; export * from './{{fileName name}}.controller'; export * from './{{fileName name}}.module'; diff --git a/scripts/template/module/{{fileName name}}.controller.ts.hbs b/scripts/template/module/{{fileName name}}.controller.ts.hbs index 44a2158..66cd3d3 100644 --- a/scripts/template/module/{{fileName name}}.controller.ts.hbs +++ b/scripts/template/module/{{fileName name}}.controller.ts.hbs @@ -2,49 +2,42 @@ import { BaseController } from '@/common/base'; import { Respond, RespondType } from '@/common/response'; import { Body, Controller, Delete, Get, Param, Patch, Post, Query, Version } from '@nestjs/common'; import { ApiOkResponse, ApiOperation, ApiTags } from '@nestjs/swagger'; -import { CreateUserDto } from './dto/create-{{fileName name}}.dto'; -import { FindUserDto } from './dto/find-{{fileName name}}.dto'; -import { UpdateUserDto } from './dto/update-{{fileName name}}.dto'; -import { User } from './entities/{{fileName name}}.entity'; -import { UserService } from './{{fileName name}}.service'; +import { Create{{upcaseName name}}Dto } from './dto/create-{{fileName name}}.dto'; +import { Find{{upcaseName name}}Dto } from './dto/find-{{fileName name}}.dto'; +import { Update{{upcaseName name}}Dto } from './dto/update-{{fileName name}}.dto'; +import { {{upcaseName name}} } from './entities/{{fileName name}}.entity'; +import { {{upcaseName name}}Service } from './{{fileName name}}.service'; @ApiTags('{{fileName name}}') -@Controller('users') -export class UserController extends BaseController { - constructor(private userService: UserService) { +@Controller('{{lowcaseName name}}s') +export class {{upcaseName name}}Controller extends BaseController { + constructor(private {{lowcaseName name}}Service: {{upcaseName name}}Service) { super(); } @Post() - @ApiOperation({ description: '创建{{fileName cnName}}', operationId: 'addUser' }) - create(@Body() createUserDto: CreateUserDto) { - return this.userService.create(createUserDto); + @ApiOperation({ description: '创建{{cnName}}', operationId: 'add{{upcaseName name}}' }) + create(@Body() create{{upcaseName name}}Dto: Create{{upcaseName name}}Dto) { + return this.{{lowcaseName name}}Service.create(create{{upcaseName name}}Dto); } @Get() @Respond(RespondType.PAGINATION) - @ApiOkResponse({ isArray: true, type: User }) - @ApiOperation({ description: '批量查询{{fileName cnName}}', operationId: 'getUsers' }) - async findMany(@Query() query: FindUserDto) { - return this.userService.findMany(query); - } - - @Get(':id') - @Version('2') - @ApiOperation({ deprecated: true, description: '查询{{fileName cnName}}', operationId: 'getUserv2' }) - findOne(@Param('id') id: number) { - return this.userService.findOne(+id); + @ApiOkResponse({ isArray: true, type: {{upcaseName name}} }) + @ApiOperation({ description: '批量查询{{cnName}}', operationId: 'get{{upcaseName name}}s' }) + async findMany(@Query() query: Find{{upcaseName name}}Dto) { + return this.{{lowcaseName name}}Service.findMany(query); } @Patch(':id') - @ApiOperation({ description: '更新{{fileName cnName}}', operationId: 'updateUser' }) - update(@Param('id') id: number, @Body() updateUserDto: UpdateUserDto) { - return this.userService.update(+id, updateUserDto); + @ApiOperation({ description: '更新{{cnName}}', operationId: 'update{{upcaseName name}}' }) + update(@Param('id') id: number, @Body() update{{upcaseName name}}Dto: Update{{upcaseName name}}Dto) { + return this.{{lowcaseName name}}Service.update(+id, update{{upcaseName name}}Dto); } @Delete(':id') - @ApiOperation({ description: '删除{{fileName cnName}}', operationId: 'deleteUser' }) + @ApiOperation({ description: '删除{{cnName}}', operationId: 'delete{{upcaseName name}}' }) remove(@Param('id') id: number) { - return this.userService.remove(+id); + return this.{{lowcaseName name}}Service.remove(+id); } } diff --git a/scripts/template/module/{{fileName name}}.module.ts.hbs b/scripts/template/module/{{fileName name}}.module.ts.hbs index 0845f02..c984c9c 100644 --- a/scripts/template/module/{{fileName name}}.module.ts.hbs +++ b/scripts/template/module/{{fileName name}}.module.ts.hbs @@ -1,13 +1,13 @@ import { Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; -import { User } from './entities/{{fileName name}}.entity'; -import { UserController } from './{{fileName name}}.controller'; -import { UserService } from './{{fileName name}}.service'; +import { {{upcaseName name}} } from './entities/{{fileName name}}.entity'; +import { {{upcaseName name}}Controller } from './{{fileName name}}.controller'; +import { {{upcaseName name}}Service } from './{{fileName name}}.service'; @Module({ - imports: [TypeOrmModule.forFeature([User])], - controllers: [UserController], - providers: [UserService], - exports: [UserService], + imports: [TypeOrmModule.forFeature([{{upcaseName name}}])], + controllers: [{{upcaseName name}}Controller], + providers: [{{upcaseName name}}Service], + exports: [{{upcaseName name}}Service], }) -export class UserModule {} +export class {{upcaseName name}}Module {} diff --git a/scripts/template/module/{{fileName name}}.service.ts.hbs b/scripts/template/module/{{fileName name}}.service.ts.hbs index 4f77fd0..c6ec2d9 100644 --- a/scripts/template/module/{{fileName name}}.service.ts.hbs +++ b/scripts/template/module/{{fileName name}}.service.ts.hbs @@ -2,58 +2,54 @@ import { BaseService } from '@/common/base'; import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Like, Repository } from 'typeorm'; -import { CreateUserDto } from './dto/create-{{fileName name}}.dto'; -import { FindUserDto } from './dto/find-{{fileName name}}.dto'; -import { UpdateUserDto } from './dto/update-{{fileName name}}.dto'; -import { User } from './entities/{{fileName name}}.entity'; +import { Create{{upcaseName name}}Dto } from './dto/create-{{fileName name}}.dto'; +import { Find{{upcaseName name}}Dto } from './dto/find-{{fileName name}}.dto'; +import { Update{{upcaseName name}}Dto } from './dto/update-{{fileName name}}.dto'; +import { {{upcaseName name}} } from './entities/{{fileName name}}.entity'; @Injectable() -export class UserService extends BaseService { - constructor(@InjectRepository(User) private userRepository: Repository) { +export class {{upcaseName name}}Service extends BaseService { + constructor(@InjectRepository({{upcaseName name}}) private {{lowcaseName name}}Repository: Repository<{{upcaseName name}}>) { super(); } /** - * 创建用户 + * 新增{{cnName}} */ - async create(createUserDto: CreateUserDto) { - const user = this.userRepository.create(createUserDto); - if (createUserDto.roles) { - user.roles = createUserDto.roles.map((id) => ({ id })) as any; - } - await this.userRepository.save(user); - return user.id; + async create(create{{upcaseName name}}Dto: Create{{upcaseName name}}Dto) { + const {{lowcaseName name}} = this.{{lowcaseName name}}Repository.create(create{{upcaseName name}}Dto); + await this.{{lowcaseName name}}Repository.save({{lowcaseName name}}); + return {{lowcaseName name}}.id; } /** - * 查找所有用户 + * 条件/分页查询 */ - async findMany(findUserdto: FindUserDto) { - const { nickname: _nickname, page, size } = findUserdto; - const nickname = _nickname && Like(`%${_nickname}%`); + async findMany(find{{upcaseName name}}dto: Find{{upcaseName name}}Dto) { + const { page, size } = find{{upcaseName name}}dto; const { skip, take } = this.formatPagination(page, size, true); - return this.userRepository.findAndCount({ skip, take, where: { nickname } }); + return this.{{lowcaseName name}}Repository.findAndCount({ skip, take }); } /** - * 根据id查找用户 + * 根据ID查询 */ - findOne(idOrOptions: number | Partial) { + findOne(idOrOptions: number | Partial<{{upcaseName name}}>) { const where = typeof idOrOptions === 'number' ? { id: idOrOptions } : (idOrOptions as any); - return this.userRepository.findOne({ where }); + return this.{{lowcaseName name}}Repository.findOne({ where }); } /** - * 根据用户id + * 根据ID更新 */ - update(id: number, updateUserDto: UpdateUserDto) { - return this.userRepository.update(id, updateUserDto); + update(id: number, update{{upcaseName name}}Dto: Update{{upcaseName name}}Dto) { + return this.{{lowcaseName name}}Repository.update(id, update{{upcaseName name}}Dto); } /** - * 根据id删除用户 + * 根据ID删除(软删除) */ remove(id: number) { - return this.userRepository.softDelete(id); + return this.{{lowcaseName name}}Repository.softDelete(id); } }