Skip to main content

Release 4.0.0-beta.2

· 2 minute read
Harry Chen
Maintainer of Midway

这是全新的 Midway 4.0 的第二个 beta 版本。

在这个版本中,我们带来了一些重要的新功能和改进,主要包括 MCP 组件的全面支持以及 mock 组件的测试体验优化。

🚀 主要新增功能

MCP (Model Context Protocol) 支持

我们正式加入了对 MCP 的完整支持。MCP 是由 Anthropic 开发的开放标准协议,用于将 AI 模型与外部数据源和工具安全连接。

Midway 现在提供了:

  • 完整的 MCP 服务器框架封装
  • 支持多种传输方式:stdio、stream-http、sse
  • 基于装饰器的开发体验
  • 与现有 HTTP 框架(Express、Koa、Egg.js)的无缝集成

使用 Midway 可以快速创建 MCP 服务,为 AI 应用程序提供标准化的数据访问和工具调用接口。

import { Tool, IMcpTool } from '@midwayjs/mcp';
import { z } from 'zod';

@Tool('databaes-tool', {
description: 'A tool to query user information from the database',
inputSchema: {
name: z.string().describe('name to query'),
}
})
export class DatabaseTool implements IMcpTool {
async execute(args: { name: string }) {
// 模拟数据库查询
return {
content: [{
type: 'text',
text: [{ id: 1, name: args.name }]
}],
}
}
}

更多关于 MCP 的详细使用方法和配置选项,请参考 MCP 组件文档

Mock 组件测试改进

针对开发者测试体验的优化,我们为 mock 组件的 createApp 方法增加了完整的生命周期支持:

  • 新增 onReadyonStoponConfigLoadonServerReadyonHealthCheck 等生命周期钩子

这些改进让测试代码能够更准确地反映真实运行环境的行为,提升测试的可靠性。

const app = await createApp(join(__dirname, 'fixtures', 'base-app'), {
onReady: async () => {
console.log('应用准备就绪');
},
onStop: async () => {
console.log('应用停止');
}
});

Release 4.0.0-beta.1

· 4 minute read
Harry Chen
Maintainer of Midway

这是全新的 Midway 4.0 的变化,这是一个非常重大的版本。

  • 全局变化
    • 框架支持从 Node.js >=20 开始
    • 默认开启 asyncLocalStorage
  • 编程范式
    • 不再以黑盒方式提供框架启动时的目录文件扫描自动绑定能力,改为显式声明,每个组件都可以有自己的绑定和加载方式
    • 组件包查找规范变化,现在会查找 index.tsconfiguration.ts,以及 package.json 中 main 定义的路径
    • 统一规范函数式的导出路径,为组件包下的 functional 路径,如 @midwayjs/core/functional
  • 【core】
    • 通用能力
      • 由于使用率较低且影响依赖注入容器逻辑,移除了流程控制 Pipeline 相关的能力
      • 移除之前版本中框架启动时的目录文件扫描自动绑定能力,现在需要显式增加一个 file detector,可以自由配置其需要扫描和忽略的目录或者文件
      • 移除了会和 validate 的转换产生歧义的请求参数自动 DTO 转换功能,现在自动转换仅在 validate 或者 validation 组件开启时生效
      • onReady 等生命周期现在增加了超时机制,默认 30s
    • 函数式编程
      • 提供与 @Configuration 同样功能的 defineConfiguration 方法
      • 提供内置的 hooks 方法,如 useContext, useLogger, useInject, useConfig, useApp, useMainApp
      • 提供了函数式方法的导出规范,新开发的 hooks 放在 functional 目录中,使用子模块方式导出
    • 装饰器部分
      • 为了更好的管理元数据,重构了 DecoratorManager,增加新的 MetadataManager,增加了更加方便的聚合和拷贝元数据的能力
      • 明确各种装饰器继承的情况,默认情况下,类装饰器和参数装饰器不继承,属性装饰器和方法装饰器继承
      • 使用 @MainApp() 代替 @App() 空参数
      • 使用 @Config(ALL) 替换为更为明确的 @AllConfig() 装饰器
      • 移除 @Configuration 中的 conflictCheckdetectorOptions, 这些配置将移动到 detector
      • DecoratorManager 中的 listPrelaodModules 调整为 listPreStartModulesavePreloadModule 调整为 savePreStartModule ,使其语义更加明确
    • 依赖注入
      • 移除了 container.getcontainer.getAsync 的一部分无用的参数
      • 优化了循环依赖时展示的依赖链路信息以及 definition 未找到时的输出信息
      • 单例对象现在和 registerObject 的对象存储的位置一致了
      • 增加了一个动态依赖注入容器,用于在开发期动态替换实例,支持 HMR 功能
    • 框架机制
      • BaseFramework 移除了令人疑惑的 container 相关 hook 方法,现在都统一使用 applicationInitialize
      • 移除框架的 MidwayFrameworkType,以及对应的 getFrameworkType() 方法
      • 移除了特定框架下令人疑惑的 contextLoggerApplyLoggercontextLoggerFormat 配置,现在如果要配置框架特定的 logger,使用 setFrameworkLoggerName 方法
      • ServiceFactoryDataSourceManager 现在启动可以通过 initClients 的参数 concurrent 支持并发,由组件自行控制是否支持
      • DataSourceManager 原有的 cacheInstancevalidateConnection 选项废弃
      • MidwayConfigServce 在获取配置时可以增加默认值
      • 增加服务发现基础功能,增加了 consulredisetcd 的实现
  • 【decorator】移除,API 都移动到 @midwayjs/core,不再单独提供 4.x 版本
  • 【async-hooks-context-manager】现在默认开启 async_local_storage,代码合并至 core 模块中
  • 【axios】移除了废弃的 axios 导出
  • 【socketio】移除了内置的 socket.io-redis
  • 【validate】
    • 由于固化了 Joi 作为验证器,不再更新
    • 移除 @Rule 作为类装饰器的功能
    • 移除属性 @Rule 参数传递类本身的功能
  • 【validation】新增组件,替代原有 validate 组件
    • 支持多种验证器,如 Joi, zod, class-validator,提供内置的 i18n 支持
    • 可自定义扩展验证器
  • 【mock】
    • 由于移除了框架启动的扫描能力,如果有大量历史测试不方便修改,可以使用提供的 createLegacyAppcreateLegacyLightAppcreateLegacyFunctionApp ,对应之前的 createAppcreateLightApp, createFunctionApp
    • 移除了 createAppcreateLightApp, createFunctionApp 方法的最后一个参数,现在额外指定组件可以写到 options.imports
  • 【sequelize】
    • 移除老版本配置的兼容代码,以及历史装饰器导出,如 @BaseTable
    • 移除默认启动时数据源连接校验 validateConnection,如有需求,可以在配置中单独开启
  • 【tags】移除,不再提供 4.x 版本
  • 【processAgent】移除,不再提供 4.x 版本
  • 【event-emitter] 新增组件,提供事件触发和监听能力支持

Release 3.20.0

· 3 minute read
Harry Chen
Maintainer of Midway

升级请参考 如何更新 Midway 中描述,请不要单独升级某个组件包。

本次 3.20 版本,主要引入了全新的 BullMQ 组件,作为 Bull 组件的升级替代,提供了更好的性能和更多的功能。

下面是更为细节的描述。

BullMQ 组件

从 v3.20 开始,我们引入了全新的 BullMQ 组件,作为 Bull 组件的下一代实现。BullMQ 提供了更好的性能和更丰富的功能,包括:

  • 更好的类型支持
  • 更强大的任务流(Flow Producer)功能
  • 更完善的事件系统
  • 更灵活的任务处理机制

基础使用示例:

// 定义任务处理器
@Processor('test')
export class TestProcessor implements IProcessor {
async execute(data: any) {
// 处理任务逻辑
console.log('processing job:', data);
}
}

// 执行任务
const testQueue = this.bullmqFramework.getQueue('test');
await testQueue?.runJob({
name: 'harry'
});

任务流示例:

// 创建任务流
const flowProducer = bullmqFramework.createFlowProducer({}, 'test-flow');

await flowProducer.add({
name: 'flow-test',
queueName: 'flow-queue-1',
data: { value: 1 },
children: [
{
name: 'child-job',
queueName: 'flow-queue-2',
data: { value: 2 }
}
]
});

更多的内容,请参考 BullMQ 组件文档

Bull 组件迁移提示

从 v3.20 开始,我们推荐使用 BullMQ 组件替代原有的 Bull 组件。虽然 Bull 组件仍然可用,但我们建议在新项目中使用 BullMQ,并逐步将现有项目迁移到 BullMQ。

主要的变化包括:

  1. 配置方式的调整
// Bull
export default {
bull: {
defaultQueueOptions: {
redis: {
port: 6379,
host: '127.0.0.1',
},
}
},
}

// BullMQ
export default {
bullmq: {
defaultConnection: {
port: 6379,
host: '127.0.0.1',
},
},
}
  1. Worker 和事件处理
// BullMQ 新增了独立的 Worker 和 QueueEvents
const worker = bullmqFramework.createWorker(
'queueName',
async (job) => {
// 处理任务
}
);

const queueEvents = queue.createQueueEvents();
queueEvents.on('completed', ({ jobId }) => {
console.log(`Job ${jobId} completed!`);
});
  1. 任务流支持
// BullMQ 支持创建任务依赖关系
const flowProducer = bullmqFramework.createFlowProducer();
await flowProducer.add({
name: 'flow-test',
queueName: 'flow-queue-1',
children: [/* 子任务 */]
});
  1. 队列操作的增强
// BullMQ 提供了更多队列操作方法
const queue = bullmqFramework.createQueue('test');
await queue.runJob(data); // 执行任务
await queue.createQueueEvents(); // 创建事件监听
await queue.createQueueEventsProducer(); // 创建事件生产者

其他更新

  • typeorm 组件现在可以指定自定义的 DataSource 了,以支持一些自定义数据源的场景
  • 更新了一些依赖库以提高安全性和稳定性

更多的更新内容和详细信息,请参考我们的 ChangeLog

Release 3.19.0

· 2 minute read
Harry Chen
Maintainer of Midway

升级请参考 如何更新 Midway 中描述,请不要单独升级某个组件包。

本次 3.19 版本,主要引入了 Kafka 组件的重构,以及一些性能优化和 bug 修复。

下面是更为细节的描述。

Kafka 组件重构

从 v3.19 开始,Kafka 组件进行了重构,配置和使用方法与之前有较大差异。虽然原有的使用方式仍然兼容,但文档不再保留。新的 Kafka 组件提供了更灵活的配置和更强大的功能。

// src/config/config.default.ts
export default {
kafka: {
consumer: {
sub1: {
connectionOptions: {
clientId: 'my-app',
brokers: ['localhost:9092'],
},
consumerOptions: {
groupId: 'groupId-test-1',
},
subscribeOptions: {
topics: ['topic-test-1'],
}
},
},
producer: {
clients: {
pub1: {
connectionOptions: {
clientId: 'my-app',
brokers: ['localhost:9092'],
},
producerOptions: {
// ...
}
}
}
}
}
}

更多的内容,请参考 Kafka 组件文档

Mock 功能分组

3.19.0 开始,Midway 的 mock 功能支持通过分组来管理不同的 mock 数据。你可以在创建 mock 时指定一个分组名称,这样可以在需要时单独恢复或清理某个分组的 mock 数据。

import { mockContext, restoreMocks } from '@midwayjs/mock';

it('should test mock with groups', async () => {
const app = await createApp();

// 创建普通对象的 mock
const a = {};
mockProperty(a, 'getUser', async () => {
return 'midway';
}, 'group1');

// 创建上下文的 mock
mockContext(app, 'user', 'midway', 'group1');
mockContext(app, 'role', 'admin', 'group2');

// 恢复单个分组
restoreMocks('group1');

// 恢复所有分组
restoreAllMocks();
});

通过分组,你可以更灵活地管理和控制 mock 数据,特别是在复杂的测试场景中。

新增了一个启动性能分析的命令

在开发环境下,新增了一个 perf-init 命令,用于在启动时初始化性能分析,需要配合最新的 mwtsc 一同使用。

{
"scripts": {
"dev": "cross-env NODE_ENV=local mwtsc --watch --run @midwayjs/mock/app.js --perf-init"
}
}

其他更新

  • 更新了一些依赖库以提高安全性和稳定性。

更多的更新内容和详细信息,请参考我们的 ChangeLog

Release 3.18.0

· 2 minute read
Harry Chen
Maintainer of Midway

升级请参考 如何更新 Midway 中描述,请不要单独升级某个组件包。

本次 3.18 版本,主要修复了新的 busboy 组件的一些遗留问题,以及新增了一种上传模式。

下面是更为细节的描述。

异步迭代器上传模式

为了支持单次多个文件的流式上传,新版本使用了异步迭代器模型转换了上传流,这个新的模式用于替代原有的流式模式。

// src/config/config.default.ts
export default {
// ...
busboy: {
mode: 'asyncIterator',
},
}

装饰器的入参也已经变成了异步迭代器。

import { Controller, Post, Files, Fields } from '@midwayjs/core';
import { UploadStreamFileInfo, UploadStreamFieldInfo } from '@midwayjs/busboy';

@Controller('/')
export class HomeController {

@Post('/upload', /*...*/)
async upload(
@Files() fileIterator: AsyncGenerator<UploadStreamFileInfo>,
@Fields() fieldIterator: AsyncGenerator<UploadStreamFieldInfo>
) {
// ...
}
}

我们可以通过循环迭代器获取到每个上传的文件。

for await (const file of fileIterator) {
const { filename, data } = file;
// ...
}

进而可以方便的做后续处理。

更多的内容,请参考 细节文档

此外还有更多的变化

  • 流式上传时的 fieldName 字段现在恢复了
  • httpClient 现在默认的配置不再会被单次请求覆盖
  • 数据源的优先级 NPE 报错现在已经修复了
  • 业务中的 https 配置现在在 dev 的输出提示中也变得正常了

以及一大批依赖进行了更新,可以参考我们的 ChangeLog