MidwayJS 企业级基础组件 - 集成公司常用基础服务能力,快速构建后端应用。
@cicctencent/midwayjs-base 是一个基于 MidwayJS 3.x 框架的企业级基础组件,封装了公司内部常用的基础服务能力,包括认证授权、文件存储、API 网关、会话管理等功能,帮助开发者快速搭建稳定可靠的后端服务。
{ ret, msg, data }src/
├── config/ # 配置文件
│ ├── config.default.ts # 默认配置
│ └── env.ts # 环境变量加载
├── filter/ # 异常过滤器
│ ├── default.filter.ts # 默认异常处理
│ └── notfound.filter.ts # 404 处理
├── guard/ # 守卫器
│ ├── api.ts # API Token 验证守卫
│ └── auth.ts # 登录态验证守卫
├── lib/ # 工具库
│ ├── decorator.ts # 自定义装饰器
│ ├── jwt.ts # JWT 工具函数
│ ├── request.ts # 请求工具
│ └── utils.ts # 通用工具函数
├── middleware/ # 中间件
│ ├── apiResultFormatter.ts # API 响应格式化
│ ├── detect.middleware.ts # 客户端检测
│ └── requestInit.ts # 请求初始化
├── service/ # 服务类
│ ├── session.service.ts # 会话服务
│ └── tencent.service.ts # 腾讯云服务
├── types/ # 类型定义
│ ├── base.controller.ts # 控制器基类
│ ├── base.model.service.ts # 模型服务基类
│ ├── base.service.ts # 服务基类
│ └── session.service.interface.ts # 会话服务接口
├── configuration.ts # 组件配置
└── index.ts # 入口文件
npm install @cicctencent/midwayjs-base
在 src/configuration.ts 中引入组件:
import { Configuration } from '@midwayjs/core';
import * as base from '@cicctencent/midwayjs-base';
@Configuration({
imports: [
base // 引入基础组件
],
importConfigs: [
// 你的业务配置
]
})
export class MainConfiguration {
// 配置
}
创建 .env 文件:
# 应用配置
APP_ID=1001
SERVICE_NAME=your-service-name
# API 配置
API_KEY=your-api-key
# SSO 配置
SSO_URL=https://sso.example.com
# 基础服务地址
BASE_SERVER_URL=https://base-service.example.com
# 腾讯云配置
TENCENT_CREDENTIAL_SECRETID=your-secret-id
TENCENT_CREDENTIAL_SECRETKEY=your-secret-key
# 会话配置
SESSION_TIMEOUT=1200000
# 日志配置
LOG_LEVEL=info
REMOTE_LOGGER_URL=https://log.example.com/api/report
继承 BaseService 获取基础能力:
import { Provide } from '@midwayjs/core';
import { BaseService } from '@cicctencent/midwayjs-base';
import { GetUserInfoReq, GetUserInfoRes } from '@fefeding/common/dist/models/user/request';
@Provide()
export class UserService extends BaseService {
/**
* 获取用户信息
* @param userId 用户ID
*/
async getUserInfo(userId: number) {
// 检查是否为管理员
const isManager = await this.checkManager();
// 方式1:使用请求对象(推荐)
const req = new GetUserInfoReq();
req.userId = userId;
const result = await this.requestBaseApi<GetUserInfoRes>(req);
// 方式2:使用 URL 路径
// const result = await this.requestBaseApi('/api/user/getInfo', {
// data: { userId }
// });
return result?.data || null;
}
}
BaseService 提供的能力:
checkManager(account?) - 检查是否为管理员账号requestBaseApi(req, option) - 请求基础服务(返回 data)requestBaseServer(req, option) - 请求基础服务(返回完整响应)继承 ISessionService 实现自定义会话管理:
import { Provide, Scope, ScopeEnum, Config, Inject } from '@midwayjs/core';
import { ISessionService, TencentService } from '@cicctencent/midwayjs-base';
import { Session, GetLoginSessionReq } from '@fefeding/common/dist/models/account/session';
@Provide('session:service')
@Scope(ScopeEnum.Request, { allowDowngrade: true })
export class SessionService extends ISessionService {
@Config('loginOption')
loginOption: any;
@Inject()
tencentService: TencentService;
/**
* 根据Token获取会话信息
* @param id 会话Token
*/
async getLoginSession(id: string): Promise<Session | null> {
const req = new GetLoginSessionReq();
req.id = id;
const res = await this.requestBaseApi(req);
return res?.data || null;
}
/**
* 用户登出
* @param id 会话Token
*/
async logout(id: string): Promise<any> {
this.ctx.currentSession = null;
return { success: true };
}
/**
* 通过临时授权码登录
* @param code 授权码
*/
async loginByCode(code: string): Promise<Session | null> {
const res = await this.requestBaseApi('/api/session/loginByAuthCode', {
data: { code }
});
return res?.data || null;
}
}
import { Controller, Get, Post } from '@midwayjs/core';
import { BaseController } from '@cicctencent/midwayjs-base';
@Controller('/api/user')
export class UserController extends BaseController {
@Get('/info')
async getUserInfo() {
// 获取当前会话信息
const session = this.ctx.currentSession;
return {
userId: session.userId,
account: session.account
};
}
}
import { Controller, Get, Post } from '@midwayjs/core';
import { checkLogin, checkApiToken, checkIP } from '@cicctencent/midwayjs-base';
@Controller('/api')
export class ApiController {
@Get('/public')
async publicApi() {
// 公开接口,无需认证
return { message: 'public' };
}
@Get('/user/info')
@checkLogin() // 需要登录态
async getUserInfo() {
return this.ctx.currentSession;
}
@Post('/admin/action')
@checkLogin()
@checkIP() // 检查IP白名单
async adminAction() {
// 仅允许白名单IP访问
return { success: true };
}
@Post('/internal/sync')
@checkApiToken() // 验证API Token
async syncData() {
// 需要携带有效的 api_token 和 timestamp
return { success: true };
}
}
import { Provide, Inject } from '@midwayjs/core';
import { TencentService } from '@cicctencent/midwayjs-base';
@Provide()
export class FileService {
@Inject()
tencentService: TencentService;
/**
* 上传文件到 COS
* @param filePath 本地文件路径
* @param key COS对象键
*/
async uploadFile(filePath: string, key: string) {
// 上传文件
const result = await this.tencentService.uploadCosFile(key, filePath);
// 获取带签名的访问URL
const url = await this.tencentService.getCosFileUrl(key);
return {
...result,
url
};
}
/**
* 上传数据到 COS
* @param key COS对象键
* @param data 数据内容(字符串、Buffer、ReadStream等)
*/
async uploadData(key: string, data: any) {
return await this.tencentService.uploadCosData(key, data);
}
/**
* 获取文件内容
* @param key COS对象键
*/
async getFile(key: string) {
return await this.tencentService.getFile(key);
}
}
import { jwt } from '@cicctencent/midwayjs-base';
// 生成 JWT Token
const token = jwt.encodeJWT(
{ userId: 123, loginId: 'user001' },
'your-secret-key',
{ expiresIn: '7d' } // 可选:过期时间
);
// 解码 JWT Token
const payload = jwt.decodeJWT(token, 'your-secret-key');
if (payload) {
console.log('用户ID:', payload.userId);
}
import { utils } from '@cicctencent/midwayjs-base';
// 检查URL是否属于指定域名
const isValid = utils.checkUrlHost('https://example.com/path', 'example.com');
// 获取/设置认证Token
const token = utils.getAuthToken(ctx);
utils.setAuthToken(ctx, 'new-token');
// 渲染模板
await utils.getDefaultTemplate(ctx, 'index.html', { title: '首页' });
// config/config.default.ts
export default {
// Cookie 签名密钥
keys: 'your-app-keys',
// Cookie 配置
cookies: {
secret: '', // 空字符串表示关闭加密
},
// 视图配置(Nunjucks)
view: {
defaultViewEngine: 'nunjucks',
rootDir: {
default: path.join(appInfo.webDist, 'view/'),
},
mapping: {
'.html': 'nunjucks',
},
},
// 文件上传配置
upload: {
mode: 'file',
fileSize: '10mb',
whitelist: ['.jpg', '.jpeg', '.png', '.gif', '.webp', '.pdf', '.doc', '.docx', '.xls', '.xlsx', '.ppt', '.pptx'],
},
// 静态文件服务
staticFile: {
dirs: {
default: {
dir: appInfo.webPublic,
},
},
},
// API 配置
apiOption: {
key: 'your-api-key', // API Token 密钥
reg: /^\/([^/]+\/)?api\//i, // API 路径匹配正则
ignore: ['/'], // 忽略路径
},
// IP 白名单
ipOption: {
whiteList: ['127.0.0.1', '::1', '0.0.0.0'],
},
// 基础服务配置
baseService: {
manager: ['admin'], // 管理员账号列表
appId: 1001, // 应用ID
url: 'https://base-service.example.com',
},
// 会话配置
session: {
timeout: 1200000, // 过期时间(毫秒),默认20分钟
secretKey: 'your-session-secret',
},
// 登录态校验配置
auth: {
ignores: [/\/api\/test\//i], // 忽略登录态校验的路径
},
// SSO 配置
sso: {
baseUrl: 'https://sso.example.com',
appId: 1001,
},
// 腾讯云凭证
tencentCredential: {
secretId: 'your-secret-id',
secretKey: 'your-secret-key',
},
// 请求体解析配置
bodyParser: {
formLimit: '30mb',
jsonLimit: '30mb',
},
// 缓存配置
cacheManager: {
clients: {
default: {
store: 'memory',
options: {
max: 10000, // 最大缓存key数量
ttl: 600000, // 过期时间(毫秒)
},
},
},
},
// 日志配置
logger: {
level: 'info',
consoleLevel: 'info',
remoteUrl: '', // 远程日志上报地址
},
};
请求 → RequestInitMiddleware → DetectMiddleware → ApiResultFormatterMiddleware → Guard → Controller
RequestInitMiddleware: 请求初始化
DetectMiddleware: 客户端检测
ApiResultFormatterMiddleware: API 响应格式化
{ ret, msg, data }ApiGuard: API 接口守卫
@checkApiToken() - 验证 API Token@checkIP() - IP 白名单检查AuthGuard: 认证守卫
@checkLogin() - 登录态验证# 安装依赖
npm install
# 构建
npm run build
# 测试
npm test
# 代码检查
npm run lint
npm run lint:fix
# 构建
npm run build
# 发布
npm publish --access public
@midwayjs/core - MidwayJS 核心框架@midwayjs/koa - Koa 适配器@fefeding/common - 公共模型和工具库jsonwebtoken - JWT 处理axios - HTTP 客户端typeorm - ORM 支持dayjs - 日期处理如有问题或建议,请联系开发团队。
MIT License