feat: 优化生成模板
parent
a8952831ab
commit
ad27bab0c5
|
|
@ -20,7 +20,8 @@
|
||||||
"test:cov": "jest --coverage",
|
"test:cov": "jest --coverage",
|
||||||
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
|
"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",
|
"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": {
|
"prettier": {
|
||||||
"printWidth": 120,
|
"printWidth": 120,
|
||||||
|
|
|
||||||
|
|
@ -10,12 +10,23 @@ module.exports = function main(/** @type { import('plop').NodePlopAPI } */ plop)
|
||||||
return filename.charAt(0).toUpperCase() + filename.slice(1);
|
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', {
|
plop.setGenerator('module', {
|
||||||
prompts: [
|
prompts: [
|
||||||
{
|
{
|
||||||
name: 'name',
|
name: 'name',
|
||||||
message: '请输入模块名称',
|
message: '请输入模块名称',
|
||||||
type: 'input',
|
type: 'input',
|
||||||
|
validate: (input) => {
|
||||||
|
if (/^(\w+\/)*(\w+)$/.test(input)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return '请输入 <moduleName> 或 <dirName>/<moduleName> 格式, 且不包含中文的名称';
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'cnName',
|
name: 'cnName',
|
||||||
|
|
@ -28,7 +39,7 @@ module.exports = function main(/** @type { import('plop').NodePlopAPI } */ plop)
|
||||||
type: 'addMany',
|
type: 'addMany',
|
||||||
destination: join(process.cwd(), 'src/{{name}}'),
|
destination: join(process.cwd(), 'src/{{name}}'),
|
||||||
base: 'module',
|
base: 'module',
|
||||||
templateFiles: 'module/**/*.ts',
|
templateFiles: 'module/**/*.hbs',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,37 +1,10 @@
|
||||||
import { Role } from '@/modules/role/entities/role.entity';
|
import { IsString } from 'class-validator';
|
||||||
import { IsInt, IsOptional, IsString } from 'class-validator';
|
|
||||||
|
|
||||||
export class CreateUserDto {
|
export class Create{{upcaseName name}}Dto {
|
||||||
/**
|
/**
|
||||||
* 登录账号
|
* 字段描述(Swagger用途)
|
||||||
* @example 'juetan'
|
* @example 'demo'
|
||||||
*/
|
*/
|
||||||
@IsString()
|
@IsString()
|
||||||
username: string;
|
demo: 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[];
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,12 @@ import { PaginationDto } from '@/common/response';
|
||||||
import { IntersectionType } from '@nestjs/swagger';
|
import { IntersectionType } from '@nestjs/swagger';
|
||||||
import { IsOptional, IsString } from 'class-validator';
|
import { IsOptional, IsString } from 'class-validator';
|
||||||
|
|
||||||
export class FindUserDto extends IntersectionType(PaginationDto) {
|
export class Find{{upcaseName name}}Dto extends IntersectionType(PaginationDto) {
|
||||||
/**
|
/**
|
||||||
* 用户昵称
|
* 字段描述(Swagger用途)
|
||||||
* @example '绝弹'
|
* @example '示例值'
|
||||||
*/
|
*/
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@IsString()
|
@IsString()
|
||||||
nickname?: string;
|
demo?: string;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { PartialType } from '@nestjs/swagger';
|
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) {}
|
||||||
|
|
|
||||||
|
|
@ -1,71 +1,12 @@
|
||||||
import { ApiHideProperty } from '@nestjs/swagger';
|
|
||||||
import { Exclude } from 'class-transformer';
|
|
||||||
import { BaseEntity } from '@/database';
|
import { BaseEntity } from '@/database';
|
||||||
import { Post } from '@/modules/post';
|
import { Column, Entity } from 'typeorm';
|
||||||
import { Role } from '@/modules/role';
|
|
||||||
import { Column, Entity, JoinTable, ManyToMany, RelationId } from 'typeorm';
|
|
||||||
|
|
||||||
@Entity({ orderBy: { id: 'DESC' } })
|
@Entity({ orderBy: { id: 'DESC' } })
|
||||||
export class User extends BaseEntity {
|
export class {{upcaseName name}} extends BaseEntity {
|
||||||
/**
|
/**
|
||||||
* 登录账号
|
* 字段描述(Swagger用途)
|
||||||
* @example 'juetan'
|
* @example '示例值'
|
||||||
*/
|
*/
|
||||||
@Column({ length: 48 })
|
@Column()
|
||||||
username: string;
|
demo: 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[];
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 './entities/{{fileName name}}.entity';
|
||||||
export * from './{{fileName name}}.controller';
|
export * from './{{fileName name}}.controller';
|
||||||
export * from './{{fileName name}}.module';
|
export * from './{{fileName name}}.module';
|
||||||
|
|
|
||||||
|
|
@ -2,49 +2,42 @@ import { BaseController } from '@/common/base';
|
||||||
import { Respond, RespondType } from '@/common/response';
|
import { Respond, RespondType } from '@/common/response';
|
||||||
import { Body, Controller, Delete, Get, Param, Patch, Post, Query, Version } from '@nestjs/common';
|
import { Body, Controller, Delete, Get, Param, Patch, Post, Query, Version } from '@nestjs/common';
|
||||||
import { ApiOkResponse, ApiOperation, ApiTags } from '@nestjs/swagger';
|
import { ApiOkResponse, ApiOperation, ApiTags } from '@nestjs/swagger';
|
||||||
import { CreateUserDto } from './dto/create-{{fileName name}}.dto';
|
import { Create{{upcaseName name}}Dto } from './dto/create-{{fileName name}}.dto';
|
||||||
import { FindUserDto } from './dto/find-{{fileName name}}.dto';
|
import { Find{{upcaseName name}}Dto } from './dto/find-{{fileName name}}.dto';
|
||||||
import { UpdateUserDto } from './dto/update-{{fileName name}}.dto';
|
import { Update{{upcaseName name}}Dto } from './dto/update-{{fileName name}}.dto';
|
||||||
import { User } from './entities/{{fileName name}}.entity';
|
import { {{upcaseName name}} } from './entities/{{fileName name}}.entity';
|
||||||
import { UserService } from './{{fileName name}}.service';
|
import { {{upcaseName name}}Service } from './{{fileName name}}.service';
|
||||||
|
|
||||||
@ApiTags('{{fileName name}}')
|
@ApiTags('{{fileName name}}')
|
||||||
@Controller('users')
|
@Controller('{{lowcaseName name}}s')
|
||||||
export class UserController extends BaseController {
|
export class {{upcaseName name}}Controller extends BaseController {
|
||||||
constructor(private userService: UserService) {
|
constructor(private {{lowcaseName name}}Service: {{upcaseName name}}Service) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post()
|
@Post()
|
||||||
@ApiOperation({ description: '创建{{fileName cnName}}', operationId: 'addUser' })
|
@ApiOperation({ description: '创建{{cnName}}', operationId: 'add{{upcaseName name}}' })
|
||||||
create(@Body() createUserDto: CreateUserDto) {
|
create(@Body() create{{upcaseName name}}Dto: Create{{upcaseName name}}Dto) {
|
||||||
return this.userService.create(createUserDto);
|
return this.{{lowcaseName name}}Service.create(create{{upcaseName name}}Dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get()
|
@Get()
|
||||||
@Respond(RespondType.PAGINATION)
|
@Respond(RespondType.PAGINATION)
|
||||||
@ApiOkResponse({ isArray: true, type: User })
|
@ApiOkResponse({ isArray: true, type: {{upcaseName name}} })
|
||||||
@ApiOperation({ description: '批量查询{{fileName cnName}}', operationId: 'getUsers' })
|
@ApiOperation({ description: '批量查询{{cnName}}', operationId: 'get{{upcaseName name}}s' })
|
||||||
async findMany(@Query() query: FindUserDto) {
|
async findMany(@Query() query: Find{{upcaseName name}}Dto) {
|
||||||
return this.userService.findMany(query);
|
return this.{{lowcaseName name}}Service.findMany(query);
|
||||||
}
|
|
||||||
|
|
||||||
@Get(':id')
|
|
||||||
@Version('2')
|
|
||||||
@ApiOperation({ deprecated: true, description: '查询{{fileName cnName}}', operationId: 'getUserv2' })
|
|
||||||
findOne(@Param('id') id: number) {
|
|
||||||
return this.userService.findOne(+id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Patch(':id')
|
@Patch(':id')
|
||||||
@ApiOperation({ description: '更新{{fileName cnName}}', operationId: 'updateUser' })
|
@ApiOperation({ description: '更新{{cnName}}', operationId: 'update{{upcaseName name}}' })
|
||||||
update(@Param('id') id: number, @Body() updateUserDto: UpdateUserDto) {
|
update(@Param('id') id: number, @Body() update{{upcaseName name}}Dto: Update{{upcaseName name}}Dto) {
|
||||||
return this.userService.update(+id, updateUserDto);
|
return this.{{lowcaseName name}}Service.update(+id, update{{upcaseName name}}Dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Delete(':id')
|
@Delete(':id')
|
||||||
@ApiOperation({ description: '删除{{fileName cnName}}', operationId: 'deleteUser' })
|
@ApiOperation({ description: '删除{{cnName}}', operationId: 'delete{{upcaseName name}}' })
|
||||||
remove(@Param('id') id: number) {
|
remove(@Param('id') id: number) {
|
||||||
return this.userService.remove(+id);
|
return this.{{lowcaseName name}}Service.remove(+id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
import { User } from './entities/{{fileName name}}.entity';
|
import { {{upcaseName name}} } from './entities/{{fileName name}}.entity';
|
||||||
import { UserController } from './{{fileName name}}.controller';
|
import { {{upcaseName name}}Controller } from './{{fileName name}}.controller';
|
||||||
import { UserService } from './{{fileName name}}.service';
|
import { {{upcaseName name}}Service } from './{{fileName name}}.service';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [TypeOrmModule.forFeature([User])],
|
imports: [TypeOrmModule.forFeature([{{upcaseName name}}])],
|
||||||
controllers: [UserController],
|
controllers: [{{upcaseName name}}Controller],
|
||||||
providers: [UserService],
|
providers: [{{upcaseName name}}Service],
|
||||||
exports: [UserService],
|
exports: [{{upcaseName name}}Service],
|
||||||
})
|
})
|
||||||
export class UserModule {}
|
export class {{upcaseName name}}Module {}
|
||||||
|
|
|
||||||
|
|
@ -2,58 +2,54 @@ import { BaseService } from '@/common/base';
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { InjectRepository } from '@nestjs/typeorm';
|
import { InjectRepository } from '@nestjs/typeorm';
|
||||||
import { Like, Repository } from 'typeorm';
|
import { Like, Repository } from 'typeorm';
|
||||||
import { CreateUserDto } from './dto/create-{{fileName name}}.dto';
|
import { Create{{upcaseName name}}Dto } from './dto/create-{{fileName name}}.dto';
|
||||||
import { FindUserDto } from './dto/find-{{fileName name}}.dto';
|
import { Find{{upcaseName name}}Dto } from './dto/find-{{fileName name}}.dto';
|
||||||
import { UpdateUserDto } from './dto/update-{{fileName name}}.dto';
|
import { Update{{upcaseName name}}Dto } from './dto/update-{{fileName name}}.dto';
|
||||||
import { User } from './entities/{{fileName name}}.entity';
|
import { {{upcaseName name}} } from './entities/{{fileName name}}.entity';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class UserService extends BaseService {
|
export class {{upcaseName name}}Service extends BaseService {
|
||||||
constructor(@InjectRepository(User) private userRepository: Repository<User>) {
|
constructor(@InjectRepository({{upcaseName name}}) private {{lowcaseName name}}Repository: Repository<{{upcaseName name}}>) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建用户
|
* 新增{{cnName}}
|
||||||
*/
|
*/
|
||||||
async create(createUserDto: CreateUserDto) {
|
async create(create{{upcaseName name}}Dto: Create{{upcaseName name}}Dto) {
|
||||||
const user = this.userRepository.create(createUserDto);
|
const {{lowcaseName name}} = this.{{lowcaseName name}}Repository.create(create{{upcaseName name}}Dto);
|
||||||
if (createUserDto.roles) {
|
await this.{{lowcaseName name}}Repository.save({{lowcaseName name}});
|
||||||
user.roles = createUserDto.roles.map((id) => ({ id })) as any;
|
return {{lowcaseName name}}.id;
|
||||||
}
|
|
||||||
await this.userRepository.save(user);
|
|
||||||
return user.id;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查找所有用户
|
* 条件/分页查询
|
||||||
*/
|
*/
|
||||||
async findMany(findUserdto: FindUserDto) {
|
async findMany(find{{upcaseName name}}dto: Find{{upcaseName name}}Dto) {
|
||||||
const { nickname: _nickname, page, size } = findUserdto;
|
const { page, size } = find{{upcaseName name}}dto;
|
||||||
const nickname = _nickname && Like(`%${_nickname}%`);
|
|
||||||
const { skip, take } = this.formatPagination(page, size, true);
|
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<User>) {
|
findOne(idOrOptions: number | Partial<{{upcaseName name}}>) {
|
||||||
const where = typeof idOrOptions === 'number' ? { id: idOrOptions } : (idOrOptions as any);
|
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) {
|
update(id: number, update{{upcaseName name}}Dto: Update{{upcaseName name}}Dto) {
|
||||||
return this.userRepository.update(id, updateUserDto);
|
return this.{{lowcaseName name}}Repository.update(id, update{{upcaseName name}}Dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据id删除用户
|
* 根据ID删除(软删除)
|
||||||
*/
|
*/
|
||||||
remove(id: number) {
|
remove(id: number) {
|
||||||
return this.userRepository.softDelete(id);
|
return this.{{lowcaseName name}}Repository.softDelete(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue