refactor: 使用 lodash-es 重写 shared 工具函数并升级 cuid
- shared 包工具函数改用 lodash-es 实现 (deepClone, isEmpty, capitalize 等) - Prisma User.id 默认值从 cuid() 改为 cuid(2) 以使用更安全的 cuid2 - 更新 CLAUDE.md 文档,补充 @CurrentUser 装饰器和 lodash 使用约定 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -23,6 +23,7 @@ pnpm format:check # 检查格式
|
||||
# 测试
|
||||
pnpm test
|
||||
cd apps/api && pnpm test:watch # 单个测试文件监听
|
||||
cd apps/api && pnpm test:cov # 测试覆盖率报告
|
||||
|
||||
# 数据库
|
||||
pnpm db:generate # 生成 Prisma Client
|
||||
@@ -48,7 +49,7 @@ NestJS 采用模块化架构:
|
||||
- **AuthModule** - JWT 认证(注册、登录、token 验证)
|
||||
- **UserModule** - 用户 CRUD
|
||||
|
||||
认证流程:使用 `@Public()` 装饰器标记公开接口,其他接口需要 JWT Bearer Token。
|
||||
认证流程:使用 `@Public()` 装饰器标记公开接口,其他接口需要 JWT Bearer Token。使用 `@CurrentUser()` 装饰器获取当前登录用户信息。
|
||||
|
||||
### 共享包使用
|
||||
|
||||
@@ -57,6 +58,8 @@ import type { User, ApiResponse } from '@seclusion/shared';
|
||||
import { formatDate, generateId } from '@seclusion/shared';
|
||||
```
|
||||
|
||||
**注意**: `packages/shared` 中的工具函数应优先使用 lodash 实现。
|
||||
|
||||
## Key Files
|
||||
|
||||
- `apps/api/prisma/schema.prisma` - 数据库模型定义
|
||||
|
||||
@@ -8,7 +8,7 @@ datasource db {
|
||||
}
|
||||
|
||||
model User {
|
||||
id String @id @default(cuid())
|
||||
id String @id @default(cuid(2))
|
||||
email String @unique
|
||||
password String
|
||||
name String?
|
||||
|
||||
@@ -28,7 +28,11 @@
|
||||
"clean": "rm -rf dist",
|
||||
"lint": "eslint src --ext .ts,.tsx"
|
||||
},
|
||||
"dependencies": {
|
||||
"lodash-es": "^4.17.21"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
"@seclusion/eslint-config": "workspace:*",
|
||||
"@seclusion/typescript-config": "workspace:*",
|
||||
"tsup": "^8.3.5",
|
||||
|
||||
@@ -1,3 +1,12 @@
|
||||
import {
|
||||
cloneDeep,
|
||||
isEmpty as _isEmpty,
|
||||
capitalize as _capitalize,
|
||||
kebabCase,
|
||||
camelCase,
|
||||
sampleSize,
|
||||
} from 'lodash-es';
|
||||
|
||||
// 日期格式化
|
||||
export function formatDate(date: Date | string, format = 'YYYY-MM-DD'): string {
|
||||
const d = typeof date === 'string' ? new Date(date) : date;
|
||||
@@ -25,28 +34,18 @@ export function delay(ms: number): Promise<void> {
|
||||
// 生成随机 ID
|
||||
export function generateId(length = 12): string {
|
||||
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
||||
let result = '';
|
||||
for (let i = 0; i < length; i++) {
|
||||
result += chars.charAt(Math.floor(Math.random() * chars.length));
|
||||
}
|
||||
return result;
|
||||
return sampleSize(chars.split(''), length).join('');
|
||||
}
|
||||
|
||||
// 深拷贝
|
||||
export function deepClone<T>(obj: T): T {
|
||||
if (obj === null || typeof obj !== 'object') {
|
||||
return obj;
|
||||
}
|
||||
return JSON.parse(JSON.stringify(obj));
|
||||
return cloneDeep(obj);
|
||||
}
|
||||
|
||||
// 判断是否为空对象
|
||||
// 判断是否为空
|
||||
export function isEmpty(obj: unknown): boolean {
|
||||
if (obj === null || obj === undefined) return true;
|
||||
if (typeof obj === 'string') return obj.trim().length === 0;
|
||||
if (Array.isArray(obj)) return obj.length === 0;
|
||||
if (typeof obj === 'object') return Object.keys(obj).length === 0;
|
||||
return false;
|
||||
return _isEmpty(obj);
|
||||
}
|
||||
|
||||
// 安全解析 JSON
|
||||
@@ -60,16 +59,15 @@ export function safeJsonParse<T>(json: string, fallback: T): T {
|
||||
|
||||
// 首字母大写
|
||||
export function capitalize(str: string): string {
|
||||
if (!str) return '';
|
||||
return str.charAt(0).toUpperCase() + str.slice(1);
|
||||
return _capitalize(str);
|
||||
}
|
||||
|
||||
// 驼峰转短横线
|
||||
export function camelToKebab(str: string): string {
|
||||
return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
|
||||
return kebabCase(str);
|
||||
}
|
||||
|
||||
// 短横线转驼峰
|
||||
export function kebabToCamel(str: string): string {
|
||||
return str.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
|
||||
return camelCase(str);
|
||||
}
|
||||
|
||||
24
pnpm-lock.yaml
generated
24
pnpm-lock.yaml
generated
@@ -187,6 +187,10 @@ importers:
|
||||
version: 8.57.1
|
||||
|
||||
packages/shared:
|
||||
dependencies:
|
||||
lodash-es:
|
||||
specifier: ^4.17.21
|
||||
version: 4.17.22
|
||||
devDependencies:
|
||||
'@seclusion/eslint-config':
|
||||
specifier: workspace:*
|
||||
@@ -194,6 +198,9 @@ importers:
|
||||
'@seclusion/typescript-config':
|
||||
specifier: workspace:*
|
||||
version: link:../typescript-config
|
||||
'@types/lodash-es':
|
||||
specifier: ^4.17.12
|
||||
version: 4.17.12
|
||||
tsup:
|
||||
specifier: ^8.3.5
|
||||
version: 8.5.1(jiti@2.6.1)(postcss@8.4.31)(typescript@5.9.3)
|
||||
@@ -1295,6 +1302,12 @@ packages:
|
||||
'@types/jsonwebtoken@9.0.5':
|
||||
resolution: {integrity: sha512-VRLSGzik+Unrup6BsouBeHsf4d1hOEgYWTm/7Nmw1sXoN1+tRly/Gy/po3yeahnP4jfnQWWAhQAqcNfH7ngOkA==}
|
||||
|
||||
'@types/lodash-es@4.17.12':
|
||||
resolution: {integrity: sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==}
|
||||
|
||||
'@types/lodash@4.17.21':
|
||||
resolution: {integrity: sha512-FOvQ0YPD5NOfPgMzJihoT+Za5pdkDJWcbpuj1DjaKZIr/gxodQjY/uWEFlTNqW2ugXHUiL8lRQgw63dzKHZdeQ==}
|
||||
|
||||
'@types/ms@2.1.0':
|
||||
resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==}
|
||||
|
||||
@@ -3181,6 +3194,9 @@ packages:
|
||||
resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
lodash-es@4.17.22:
|
||||
resolution: {integrity: sha512-XEawp1t0gxSi9x01glktRZ5HDy0HXqrM0x5pXQM98EaI0NxO6jVM7omDOxsuEo5UIASAnm2bRp1Jt/e0a2XU8Q==}
|
||||
|
||||
lodash.includes@4.3.0:
|
||||
resolution: {integrity: sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==}
|
||||
|
||||
@@ -5648,6 +5664,12 @@ snapshots:
|
||||
dependencies:
|
||||
'@types/node': 22.19.3
|
||||
|
||||
'@types/lodash-es@4.17.12':
|
||||
dependencies:
|
||||
'@types/lodash': 4.17.21
|
||||
|
||||
'@types/lodash@4.17.21': {}
|
||||
|
||||
'@types/ms@2.1.0': {}
|
||||
|
||||
'@types/node@22.19.3':
|
||||
@@ -8054,6 +8076,8 @@ snapshots:
|
||||
dependencies:
|
||||
p-locate: 5.0.0
|
||||
|
||||
lodash-es@4.17.22: {}
|
||||
|
||||
lodash.includes@4.3.0: {}
|
||||
|
||||
lodash.isboolean@3.0.3: {}
|
||||
|
||||
Reference in New Issue
Block a user