Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/nest/src/decorators/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './transform.decorator'
141 changes: 141 additions & 0 deletions packages/nest/src/decorators/transform.decorator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
import { HttpException, HttpStatus } from '@nestjs/common'
import { Transform } from 'class-transformer'

export function TransformToBoolean(): PropertyDecorator {
return Transform(({ value }) => {
switch (typeof value) {
case 'string':
return value === 'true' || value === '1'
? true
: value === 'false' || value === '0'
? false
: value
case 'number':
return Boolean(value)
default:
return value
}
})
}

export function TransformToNumber(): PropertyDecorator {
return Transform(({ value }) => Number(value))
}

export function TransformToNumberArray(): PropertyDecorator {
return Transform(({ value }) => {
switch (typeof value) {
case 'string':
return value.split(',').map(i => Number(i.trim()))
case 'object':
return Array.isArray(value) ? value.map(i => Number(i)) : value
default:
return value
}
})
}

export function TransformToStringArray(): PropertyDecorator {
return Transform(({ value }) => {
switch (typeof value) {
case 'string':
return value.split(',')
case 'object':
return Array.isArray(value) ? value.map(i => String(i)) : value
default:
return value
}
})
}

export function TransformToStringAndNumberArray(): PropertyDecorator {
return Transform(({ value }) => {
switch (typeof value) {
case 'string':
return value.split(',').map((i) => {
const num = Number(i.trim())
return Number.isNaN(num) ? i.trim() : num
})
case 'object':
return Array.isArray(value)
? value.map((i) => {
const num = Number(i)
return Number.isNaN(num) ? i : num
})
: value
default:
return value
}
})
}

/**
* 自动转化开启使用
*/
export function Trim(): PropertyDecorator {
return Transform(p => p.value?.trim())
}

/**
* 用于转换boolean类型的值
*/
export function DtoTransformToBoolean(): PropertyDecorator {
return Transform(p =>
p.obj[p.key] === 'true'
? true
: p.obj[p.key] === 'false'
? false
: undefined,
)
}

/**
* Get请求
* 用于前端传递的字符串参数解码
*/
export function DtoDecodeURI(): PropertyDecorator {
return Transform((p) => {
// 对解密失败的字段,抛错
try {
return p.value != null ? decodeURI(p.value) : p.value
}
catch {
throw new HttpException('参数格式异常', HttpStatus.BAD_REQUEST)
}
})
}

/**
* 设置默认值(当值为null时生效)
*/
export function DefaultValue(value?: unknown): PropertyDecorator {
return Transform(target => target.value ?? value)
}

/**
* 手机号、API key等数据脱敏
*/
export function StrDesensitize(): PropertyDecorator {
return Transform(({ value }) => {
if (typeof value !== 'string') {
return value
}

const length = value.length

if (length === 0) {
return ''
}
else if (length <= 2) {
return '*'.repeat(length)
}
else if (length === 3 || length === 4) {
return `${value[0]}${'*'.repeat(length - 2)}${value[length - 1]}`
}
else {
const start = value.slice(0, 2)
const end = value.slice(-2)
return `${start}${'*'.repeat(length - 4)}${end}`
}
})
}
5 changes: 5 additions & 0 deletions packages/nest/src/dtos/base.vo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export class BaseVo<T> {
constructor(obj: T) {
Object.assign(this, obj)
}
}
3 changes: 3 additions & 0 deletions packages/nest/src/dtos/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './base.vo'
export * from './pagination.dto'
export * from './pagination.vo'
26 changes: 26 additions & 0 deletions packages/nest/src/dtos/pagination.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { Exclude, Expose, Transform } from 'class-transformer'
import { IsOptional, IsPositive } from 'class-validator'

/**
* 默认分页参数
*/
@Exclude()
export class PaginationDto {
/**
* 页号 默认1
*/
@Expose()
@IsOptional()
@Transform(({ value }) => Number(value) ?? 1)
@IsPositive()
pageNum!: number

/**
* 单页大小,默认10
*/
@Expose()
@IsOptional()
@Transform(({ value }) => Number(value) ?? 10)
@IsPositive()
pageSize!: number
}
32 changes: 32 additions & 0 deletions packages/nest/src/dtos/pagination.vo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { Exclude, Expose } from 'class-transformer'
import { BaseVo } from './base.vo'

/**
* 分页
*/
@Exclude()
export class PaginationVo<T> extends BaseVo<PaginationVo<T>> {
/**
* 总数
*/
@Expose()
total!: number

/**
* 分页数据
*/
@Expose()
data!: T[]

/**
* 页码
*/
@Expose()
pageNum!: number

/**
* 每页数量
*/
@Expose()
pageSize!: number
}
2 changes: 2 additions & 0 deletions packages/nest/src/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
export * from './app.module'
export * from './decorators'
export * from './dtos'
Loading