FullStack Nestjs Core
npm install @lark-apaas/fullstack-nestjs-coreFullStack NestJS Core 是一个为 NestJS 全栈应用提供核心功能的工具包,包括平台集成、CSRF 保护、用户上下文管理和开发工具等。
- 平台模块: 一站式集成 Config、Logger、Database、Auth 等核心功能
- HTTP 客户端: 自动集成 @nestjs/axios,提供 HTTP 请求能力,自动打印请求日志
- CSRF 保护: 提供完整的 CSRF Token 生成和验证机制
- 用户上下文: 自动从请求头中提取并注入用户上下文信息
- 视图上下文: 将用户信息和 CSRF Token 注入到模板渲染上下文
- 开发工具: 自动生成 Swagger 文档、OpenAPI JSON 和 TypeScript 客户端 SDK
- 应用配置: 一键配置 Logger、Cookie Parser、全局前缀等
``bash`
npm install @lark-apaas/fullstack-nestjs-core
或使用 yarn:
`bash`
yarn add @lark-apaas/fullstack-nestjs-core
- Node.js >= 18.0.0
- NestJS >= 10.4.20
最简单的方式是使用 PlatformModule,它会自动集成所有核心功能:
`typescript
import { Module } from '@nestjs/common';
import { PlatformModule } from '@lark-apaas/fullstack-nestjs-core';
@Module({
imports: [
PlatformModule.forRoot({
enableCsrf: true, // 是否启用 CSRF 保护,默认 true
csrfRoutes: '/api/', // CSRF 保护的路由,默认 '/api/'
alwaysNeedLogin: true, // 是否所有路由都需要登录,默认 true
}),
],
})
export class AppModule {}
`
PlatformModule 自动集成:
- ✅ ConfigModule (环境变量配置)
- ✅ LoggerModule (日志系统)
- ✅ HttpModule (HTTP 客户端,自动打印请求日志)
- ✅ DataPaasModule (数据库连接)
- ✅ AuthNPaasModule (认证系统)
- ✅ UserContextMiddleware (用户上下文)
- ✅ CsrfTokenMiddleware + CsrfMiddleware (CSRF 保护)
- ✅ ViewContextMiddleware (视图上下文)
- ✅ ValidationPipe (全局验证管道)
在 main.ts 中使用 configureApp 快速配置应用:
`typescript
import { NestFactory } from '@nestjs/core';
import { NestExpressApplication } from '@nestjs/platform-express';
import { configureApp } from '@lark-apaas/fullstack-nestjs-core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create
// 一键配置:Logger、CookieParser、GlobalPrefix、DevTools
await configureApp(app);
await app.listen(3000);
}
bootstrap();
`
configureApp 会自动:CLIENT_BASE_PATH
- ✅ 注册 AppLogger
- ✅ 注册 cookie-parser 中间件
- ✅ 根据 环境变量设置全局前缀DevToolsV2Module
- ✅ 在非生产环境自动挂载
如果需要更细粒度的控制,可以单独使用各个模块:
`typescript
import { Module, NestModule, MiddlewareConsumer } from '@nestjs/common';
import {
CsrfTokenMiddleware,
CsrfMiddleware,
UserContextMiddleware,
ViewContextMiddleware,
} from '@lark-apaas/fullstack-nestjs-core';
@Module({})
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
// 用户上下文中间件
consumer
.apply(UserContextMiddleware)
.forRoutes('*');
// CSRF Token 生成(用于视图渲染)
consumer
.apply(CsrfTokenMiddleware)
.exclude('/api/(.*)')
.forRoutes('*');
// 视图上下文注入
consumer
.apply(ViewContextMiddleware)
.exclude('/api/(.*)')
.forRoutes('*');
// CSRF 验证(用于 API 保护)
consumer
.apply(CsrfMiddleware)
.forRoutes('/api/*');
}
}
`
全局平台模块,集成了所有核心功能。
#### 配置选项
| 选项 | 类型 | 默认值 | 描述 |
|------|------|--------|------|
| enableCsrf | boolean | true | 是否启用 CSRF 保护 |'/api/*'
| csrfRoutes | string \| string[] | | CSRF 保护应用的路由 |true
| alwaysNeedLogin | boolean | | 是否所有路由都需要登录 |
#### 使用示例
`typescript`
@Module({
imports: [
PlatformModule.forRoot({
enableCsrf: true,
csrfRoutes: ['/api/', '/admin/'],
alwaysNeedLogin: false,
}),
],
})
export class AppModule {}
使用 @hey-api/openapi-ts 生成高质量的 TypeScript 客户端 SDK。
新特性:
- ✅ 使用最新的 @hey-api/openapi-ts 生成器baseURL
- ✅ 自动注入 配置到生成的客户端// @ts-nocheck
- ✅ 自动给所有生成的文件添加 注释
#### 配置选项
| 选项 | 类型 | 默认值 | 描述 |
|------|------|--------|------|
| basePath | string | '/' | API 基础路径 |'/api/docs'
| docsPath | string | | Swagger UI 的挂载路径 |'./client/src/api/gen/openapi.json'
| openapiOut | string | | OpenAPI JSON 输出路径 |false
| needSetupServer | boolean | | 是否挂载 Swagger UI 服务器 |true
| needGenerateClientSdk | boolean | | 是否生成客户端 SDK |'./client/src/api/gen'
| clientSdkOut | string | | 客户端 SDK 输出目录 |
| swaggerOptions | object | - | Swagger 文档配置 |
#### 使用示例
`typescript
import { NestFactory } from '@nestjs/core';
import { DevToolsV2Module } from '@lark-apaas/fullstack-nestjs-core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
// 在开发环境挂载开发工具
if (process.env.NODE_ENV !== 'production') {
await DevToolsV2Module.mount(app, {
basePath: '/app',
docsPath: '/api_docs',
needSetupServer: true,
needGenerateClientSdk: true,
swaggerOptions: {
title: 'My API',
version: '1.0.0',
},
});
}
await app.listen(3000);
}
bootstrap();
`
#### 生成的文件
``
client/src/api/gen/
├── openapi.json # OpenAPI 规范文件
├── client.config.ts # 客户端配置(自动生成 baseURL)
├── types.gen.ts # TypeScript 类型定义
├── sdk.gen.ts # SDK 函数
└── client/
└── client.gen.ts # Axios 客户端
所有生成的 .ts 文件都会自动添加 // @ts-nocheck 注释,避免类型检查错误。
使用 openapi-typescript-codegen 生成客户端 SDK(不推荐,建议迁移到 DevToolsV2Module)。
`typescript
import { DevToolsModule } from '@lark-apaas/fullstack-nestjs-core';
await DevToolsModule.mount(app, {
docsPath: 'api-docs',
openapiOut: './openapi.json',
needSetupServer: true,
needGenerateClientSdk: true,
clientSdkOut: './src/sdk',
});
`
PlatformModule 自动集成了 @nestjs/axios,提供开箱即用的 HTTP 请求能力。
- ✅ 自动集成: 导入 PlatformModule 后即可直接使用,无需额外配置
- ✅ 自动日志: 所有 HTTP 请求和响应自动打印到日志系统
- ✅ 标准 API: 完全遵循 @nestjs/axios 的标准用法
- ✅ 默认配置: 自动设置 5 秒超时和最多 5 次重定向
`typescript
import { Injectable } from '@nestjs/common';
import { HttpService } from '@nestjs/axios';
import { firstValueFrom } from 'rxjs';
interface User {
id: string;
name: string;
email: string;
}
@Injectable()
export class UserService {
constructor(private readonly httpService: HttpService) {}
async getUserById(id: string): Promise
const { data } = await firstValueFrom(
this.httpService.get)
);
return data;
}
async createUser(userData: Partial
const { data } = await firstValueFrom(
this.httpService.post
);
return data;
}
async updateUser(id: string, userData: Partial
const { data } = await firstValueFrom(
this.httpService.put, userData)
);
return data;
}
async deleteUser(id: string): Promise
await firstValueFrom(
this.httpService.delete(https://api.example.com/users/${id})`
);
}
}
`typescripthttps://api.example.com/users/${id}
async getUserWithHeaders(id: string) {
const { data } = await firstValueFrom(
this.httpService.get(, {`
headers: {
'Authorization': 'Bearer token',
'X-Custom-Header': 'value',
},
params: {
include: 'profile',
},
timeout: 10000, // 10秒超时
})
);
return data;
}
所有 HTTP 请求会自动打印到日志系统:
`
[HttpService] HTTP Request {
method: 'GET',
url: 'https://api.example.com/users/123',
headers: { ... },
params: { include: 'profile' },
data: undefined
}
[HttpService] HTTP Response {
method: 'GET',
url: 'https://api.example.com/users/123',
status: 200,
statusText: 'OK',
data: { id: '123', name: 'John', email: 'john@example.com' }
}
`
错误请求也会自动记录:
``
[HttpService] HTTP Response Error {
method: 'GET',
url: 'https://api.example.com/users/999',
status: 404,
statusText: 'Not Found',
data: { message: 'User not found' },
message: 'Request failed with status code 404'
}
#### 直接访问 Axios 实例
`typescript
constructor(private readonly httpService: HttpService) {
// 访问底层的 axios 实例
const axiosInstance = this.httpService.axiosRef;
// 添加自定义拦截器
axiosInstance.interceptors.request.use((config) => {
config.headers['X-Custom'] = 'my-value';
return config;
});
}
`
#### 使用 RxJS 操作符
`typescript
import { map, catchError } from 'rxjs/operators';
import { of } from 'rxjs';
async getUsers() {
return this.httpService.get
map(response => response.data),
catchError(error => {
console.error('Error fetching users:', error);
return of([]);
})
);
}
`
PlatformModule 注册 HttpModule 时使用以下默认配置:
`typescript`
HttpModule.register({
timeout: 5000, // 5 秒超时
maxRedirects: 5, // 最多 5 次重定向
})
1. 记得使用 firstValueFrom: @nestjs/axios 返回的是 Observable,需要转换为 Promise
2. 记得解构 data: 响应数据在 response.data 中httpService.get
3. 类型安全: 使用泛型指定响应数据类型
生成 CSRF Token 并设置到 Cookie 中,用于视图渲染场景。
#### 配置选项
| 选项 | 类型 | 默认值 | 描述 |
|------|------|--------|------|
| cookieKey | string | 'suda-csrf-token' | Cookie 中存储 Token 的键名 |2592000000
| cookieMaxAge | number | (30天) | Cookie 过期时间(毫秒) |'/'
| cookiePath | string | | Cookie 路径 |
#### 使用示例
`typescript
CsrfTokenMiddleware.configure({
cookieKey: 'my-csrf-token',
cookieMaxAge: 86400000, // 1天
});
consumer
.apply(CsrfTokenMiddleware)
.exclude('/api/(.*)')
.forRoutes('*');
`
验证请求中的 CSRF Token,用于保护 API 接口。
#### 配置选项
| 选项 | 类型 | 默认值 | 描述 |
|------|------|--------|------|
| headerKey | string | 'x-suda-csrf-token' | 请求头中 Token 的键名 |'suda-csrf-token'
| cookieKey | string | | Cookie 中 Token 的键名 |
#### 使用示例
`typescript
CsrfMiddleware.configure({
headerKey: 'x-my-csrf-token',
cookieKey: 'my-csrf-token',
});
consumer
.apply(CsrfMiddleware)
.forRoutes('/api/*');
`
注意: 确保 CsrfTokenMiddleware 和 CsrfMiddleware 的 cookieKey 配置一致。
从请求头中提取用户上下文信息并注入到 req.userContext。
#### 注入的上下文
`typescript`
req.userContext = {
userId: string | undefined; // 用户 ID(来自 x-user-id 请求头)
tenantId: string | undefined; // 租户 ID(来自 x-tenant-id 请求头)
appId: string; // 应用 ID(来自 x-app-id 请求头)
}
#### 使用示例
`typescript`
@Controller()
export class AppController {
@Get('profile')
getProfile(@Req() req: Request) {
const { userId, tenantId, appId } = req.userContext;
return { userId, tenantId, appId };
}
}
将用户上下文和 CSRF Token 注入到 res.locals,用于模板渲染。
#### 注入的变量
`typescript`
res.locals = {
csrfToken: string; // CSRF Token
userId: string; // 用户 ID
tenantId: string; // 租户 ID
appId: string; // 应用 ID
}
#### 使用示例
`typescript`
// 在模板引擎中可以直接使用这些变量
// EJS 示例:User ID: <%= userId %>
本包完全使用 TypeScript 编写,并提供完整的类型定义。
`typescript``
declare global {
namespace Express {
interface Request {
csrfToken?: string;
userContext: {
userId?: string;
tenantId?: string;
appId: string;
};
}
}
}
| 变量名 | 描述 | 默认值 |
|--------|------|--------|
| CLIENT_BASE_PATH | 应用的全局路径前缀 | - |
| NODE_ENV | 运行环境 | - |
MIT
- plugin
- nestjs
- server
- typescript
- fullstack