npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@lark-apaas/fullstack-nestjs-core

v1.1.31

Published

FullStack Nestjs Core

Downloads

4,651

Readme

@lark-apaas/fullstack-nestjs-core

FullStack NestJS Core 是一个为 NestJS 全栈应用提供核心功能的工具包,包括平台集成、CSRF 保护、用户上下文管理和开发工具等。

特性

  • 平台模块: 一站式集成 Config、Logger、Database、Auth 等核心功能
  • HTTP 客户端: 自动集成 @nestjs/axios,提供 HTTP 请求能力,自动打印请求日志
  • CSRF 保护: 提供完整的 CSRF Token 生成和验证机制
  • 用户上下文: 自动从请求头中提取并注入用户上下文信息
  • 视图上下文: 将用户信息和 CSRF Token 注入到模板渲染上下文
  • 旧路径兼容: 灰度迁移期间自动将旧路径 302 重定向到新路径,实现平滑过渡
  • 开发工具: 自动生成 Swagger 文档、OpenAPI JSON 和 TypeScript 客户端 SDK
  • 应用配置: 一键配置 Logger、Cookie Parser、全局前缀等

安装

npm install @lark-apaas/fullstack-nestjs-core

或使用 yarn:

yarn add @lark-apaas/fullstack-nestjs-core

环境要求

  • Node.js >= 18.0.0
  • NestJS >= 10.4.20

快速开始

方案 1: 使用 PlatformModule(推荐)

最简单的方式是使用 PlatformModule,它会自动集成所有核心功能:

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 (用户上下文)
  • ✅ LegacyPathRedirectMiddleware (旧路径兼容重定向)
  • ✅ CsrfTokenMiddleware + CsrfMiddleware (CSRF 保护)
  • ✅ ViewContextMiddleware (视图上下文)
  • ✅ ValidationPipe (全局验证管道)

方案 2: 使用 configureApp 辅助函数

main.ts 中使用 configureApp 快速配置应用:

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<NestExpressApplication>(AppModule);

  // 一键配置:Logger、CookieParser、GlobalPrefix、DevTools
  await configureApp(app);

  await app.listen(3000);
}
bootstrap();

configureApp 会自动:

  • ✅ 注册 AppLogger
  • ✅ 注册 cookie-parser 中间件
  • ✅ 根据 CLIENT_BASE_PATH 环境变量设置全局前缀
  • ✅ 在非生产环境自动挂载 DevToolsV2Module

方案 3: 手动配置各个模块

如果需要更细粒度的控制,可以单独使用各个模块:

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/*');
  }
}

核心模块

PlatformModule

全局平台模块,集成了所有核心功能。

配置选项

| 选项 | 类型 | 默认值 | 描述 | |------|------|--------|------| | enableCsrf | boolean | true | 是否启用 CSRF 保护 | | csrfRoutes | string | string[] | '/api/*' | CSRF 保护应用的路由 | | alwaysNeedLogin | boolean | true | 是否所有路由都需要登录 |

使用示例

@Module({
  imports: [
    PlatformModule.forRoot({
      enableCsrf: true,
      csrfRoutes: ['/api/*', '/admin/*'],
      alwaysNeedLogin: false,
    }),
  ],
})
export class AppModule {}

DevToolsV2Module(推荐)

使用 @hey-api/openapi-ts 生成高质量的 TypeScript 客户端 SDK。

新特性:

  • ✅ 使用最新的 @hey-api/openapi-ts 生成器
  • ✅ 自动注入 baseURL 配置到生成的客户端
  • ✅ 自动给所有生成的文件添加 // @ts-nocheck 注释

配置选项

| 选项 | 类型 | 默认值 | 描述 | |------|------|--------|------| | basePath | string | '/' | API 基础路径 | | docsPath | string | '/api/docs' | Swagger UI 的挂载路径 | | openapiOut | string | './client/src/api/gen/openapi.json' | OpenAPI JSON 输出路径 | | needSetupServer | boolean | false | 是否挂载 Swagger UI 服务器 | | needGenerateClientSdk | boolean | true | 是否生成客户端 SDK | | clientSdkOut | string | './client/src/api/gen' | 客户端 SDK 输出目录 | | swaggerOptions | object | - | Swagger 文档配置 |

使用示例

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 注释,避免类型检查错误。

DevToolsModule(旧版)

使用 openapi-typescript-codegen 生成客户端 SDK(不推荐,建议迁移到 DevToolsV2Module)。

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',
});

HTTP 客户端

PlatformModule 自动集成了 @nestjs/axios,提供开箱即用的 HTTP 请求能力。

特性

  • 自动集成: 导入 PlatformModule 后即可直接使用,无需额外配置
  • 自动日志: 所有 HTTP 请求和响应自动打印到日志系统
  • 标准 API: 完全遵循 @nestjs/axios 的标准用法
  • 默认配置: 自动设置 5 秒超时和最多 5 次重定向

基础使用

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<User> {
    const { data } = await firstValueFrom(
      this.httpService.get<User>(`https://api.example.com/users/${id}`)
    );
    return data;
  }

  async createUser(userData: Partial<User>): Promise<User> {
    const { data } = await firstValueFrom(
      this.httpService.post<User>('https://api.example.com/users', userData)
    );
    return data;
  }

  async updateUser(id: string, userData: Partial<User>): Promise<User> {
    const { data } = await firstValueFrom(
      this.httpService.put<User>(`https://api.example.com/users/${id}`, userData)
    );
    return data;
  }

  async deleteUser(id: string): Promise<void> {
    await firstValueFrom(
      this.httpService.delete(`https://api.example.com/users/${id}`)
    );
  }
}

带配置的请求

async getUserWithHeaders(id: string) {
  const { data } = await firstValueFrom(
    this.httpService.get(`https://api.example.com/users/${id}`, {
      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: '[email protected]' }
}

错误请求也会自动记录:

[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 实例

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 操作符

import { map, catchError } from 'rxjs/operators';
import { of } from 'rxjs';

async getUsers() {
  return this.httpService.get<User[]>('https://api.example.com/users').pipe(
    map(response => response.data),
    catchError(error => {
      console.error('Error fetching users:', error);
      return of([]);
    })
  );
}

默认配置

PlatformModule 注册 HttpModule 时使用以下默认配置:

HttpModule.register({
  timeout: 5000,      // 5 秒超时
  maxRedirects: 5,    // 最多 5 次重定向
})

注意事项

  1. 记得使用 firstValueFrom: @nestjs/axios 返回的是 Observable,需要转换为 Promise
  2. 记得解构 data: 响应数据在 response.data
  3. 类型安全: 使用泛型指定响应数据类型 httpService.get<User>(...)

中间件

LegacyPathRedirectMiddleware

CLIENT_BASE_PATH 灰度切换到新路径格式(/app/:appId)后,将旧路径的页面请求 302 重定向到新路径,实现平滑过渡。已内置于 PlatformModule,无需手动注册。

重定向规则

| 环境 (req.userContext.env) | 旧路径前缀 | 重定向目标 | |---|---|---| | preview | /af/p/:appId/... | CLIENT_BASE_PATH/... | | runtime | /spark/faas/:appId/... | CLIENT_BASE_PATH/... |

触发条件

  • CLIENT_BASE_PATH/app/:appId 格式开头(新路径格式)
  • 请求路径匹配对应环境的旧前缀
  • 请求路径不以 /api 开头(仅拦截页面请求)

示例

CLIENT_BASE_PATH = /app/cli_abc123

# 预览态旧链接访问
GET /af/p/cli_abc123/pages/home?tab=1
→ 302 /app/cli_abc123/pages/home?tab=1

# 运行态旧链接访问
GET /spark/faas/cli_abc123/pages/home
→ 302 /app/cli_abc123/pages/home

注意事项

  • 中间件依赖 UserContextMiddleware 已填充 req.userContext,注册顺序不可颠倒
  • 旧路径格式(CLIENT_BASE_PATH 不是 /app/:appId)下该中间件是空操作,没有额外开销
  • 路径后缀和 query string 完整保留

CsrfTokenMiddleware

生成 CSRF Token 并设置到 Cookie 中,用于视图渲染场景。

配置选项

| 选项 | 类型 | 默认值 | 描述 | |------|------|--------|------| | cookieKey | string | 'suda-csrf-token' | Cookie 中存储 Token 的键名 | | cookieMaxAge | number | 2592000000 (30天) | Cookie 过期时间(毫秒) | | cookiePath | string | '/' | Cookie 路径 |

使用示例

CsrfTokenMiddleware.configure({
  cookieKey: 'my-csrf-token',
  cookieMaxAge: 86400000, // 1天
});

consumer
  .apply(CsrfTokenMiddleware)
  .exclude('/api/(.*)')
  .forRoutes('*');

CsrfMiddleware

验证请求中的 CSRF Token,用于保护 API 接口。

配置选项

| 选项 | 类型 | 默认值 | 描述 | |------|------|--------|------| | headerKey | string | 'x-suda-csrf-token' | 请求头中 Token 的键名 | | cookieKey | string | 'suda-csrf-token' | Cookie 中 Token 的键名 |

使用示例

CsrfMiddleware.configure({
  headerKey: 'x-my-csrf-token',
  cookieKey: 'my-csrf-token',
});

consumer
  .apply(CsrfMiddleware)
  .forRoutes('/api/*');

注意: 确保 CsrfTokenMiddlewareCsrfMiddlewarecookieKey 配置一致。

UserContextMiddleware

从请求头中提取用户上下文信息并注入到 req.userContext

注入的上下文

req.userContext = {
  userId: string | undefined;    // 用户 ID(来自 x-user-id 请求头)
  tenantId: string | undefined;  // 租户 ID(来自 x-tenant-id 请求头)
  appId: string;                 // 应用 ID(来自 x-app-id 请求头)
}

使用示例

@Controller()
export class AppController {
  @Get('profile')
  getProfile(@Req() req: Request) {
    const { userId, tenantId, appId } = req.userContext;
    return { userId, tenantId, appId };
  }
}

ViewContextMiddleware

将用户上下文和 CSRF Token 注入到 res.locals,用于模板渲染。

注入的变量

res.locals = {
  csrfToken: string;   // CSRF Token
  userId: string;      // 用户 ID
  tenantId: string;    // 租户 ID
  appId: string;       // 应用 ID
}

使用示例

// 在模板引擎中可以直接使用这些变量
// EJS 示例:
<input type="hidden" name="_csrf" value="<%= csrfToken %>">
<div>User ID: <%= userId %></div>

TypeScript 支持

本包完全使用 TypeScript 编写,并提供完整的类型定义。

扩展 Express Request 类型

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