
CMS后端前端【免费下载链接】webiny-jsOpen-source, self-hosted CMS platform on AWS serverless (Lambda, DynamoDB, S3). TypeScript framework with multi-tenancy, lifecycle hooks, GraphQL API, and AI-assisted development via MCP server. Built for developers at large organizations.项目地址https://gitcode.com/gh_mirrors/we/webiny-js点击查看免费下载Webiny 的开源代码规范文档 routes-delegate-to-use-cases.md 确立了一条清晰的分层原则HttpRoute是传输层而非功能代码它的职责仅限于解析请求、调用一个 use case、并把结果映射为状态码认证、编排、调用其他服务等业务逻辑必须收敛到 use case 及其抽象之后以便脱离 HTTP 请求被解析、装饰与测试。本文以该规范为骨架结合仓库中event-handler-core的路由实现与ai-powerups的真实用例说明这条规则背后的架构动机与落地方式读完你可以直接按此模式写出可复用、可测试、可装饰的 Webiny HTTP 路由。核心原则Route 是传输层不是功能层规范的第一句话定义了路由的边界AnHttpRouteis transport, not feature code。一个合格的 Webiny 路由类只做三件事解析请求——从request中取出参数并做最基础的格式校验调用一个 use case——把解析结果交给抽象出来的用例接口映射结果——把 use case 的返回值或错误翻译成 HTTP 状态码与响应体。业务逻辑——身份校验、跨服务编排、事件发布、仓库访问——一律不属于路由。它必须住进一个 use case并且是behind its own abstraction处在自己的抽象之后即路由只依赖用例的Interface而不是具体实现类。这样做的好处是规范原文点名的三件事可以被解析resolved抽象与实现的绑定关系由依赖容器管理路由构造时注入的是接口具体实现何时替换、如何组合由 DI 决定可以被装饰decorated装饰器可以包住用例接口在真正执行前后注入审计、限流、重试等横切逻辑可以在没有 HTTP 请求的情况下被测试tested用例不感知IHttpRequest单测直接构造参数调用execute()即可。仓库中这套抽象就定义在 packages/event-handler-core/src/features/http/abstractions.ts路由处理逻辑实现HttpRouteHandler.Interface即IHttpRoute其handle(request, response)接收IHttpRequest与可链式调用的IHttpResponseBuilder路由定义实现HttpRouteDefinition.Interfacename/method/path/handler四个纯数据字段。定义与处理分离的设计使得路由的匹配阶段零依赖、零开销具体见下文。好示例薄路由 厚用例规范给出的好示例是CreateThingRouteImpl它把整条链路拆成了两层// Good class CreateThingRouteImpl implements HttpRoute.Interface { public readonly method POST; public readonly path /things; public constructor(private readonly createThing: CreateThingUseCase.Interface) {} public async handle(request: IHttpRequest): PromiseIHttpResponse { const params parseBody(request.body); if (!params) { return json(400, { error: Invalid body. }); } return json(200, await this.createThing.execute(params)); } }逐行拆解这条规范示例method与path是路由定义不是行为。HttpRouter匹配请求时只读这两个字段以及name连用例都不需要被构建见 HttpRouter.ts 中的match()构造参数注入的是CreateThingUseCase.Interface。这就是behind its own abstraction的字面实现——路由与具体实现零耦合parseBody是唯一被允许存在的业务前处理且它的产物只是传输格式请求体到领域输入params的转换失败直接映射为 400成功路径只有一行json(200, await this.createThing.execute(params))用例负责返回领域结果路由负责把它翻译成 HTTP 语义。值得注意的是示例中路由类把method/path声明为实例字段。Webiny 实际项目中通常更进一步将定义拆成独立类并挂到HttpRouteDefinition抽象上见下文AdminAssistant的真实实现这样路由匹配阶段连处理类都不实例化——这正是 HttpRouter.ts 注释 中强调的优化动机曾经为了读一个path就要解析整个依赖图静态资源请求也会白白构建 GraphQL 引擎、上下文 schema 与 AI provider。坏示例业务逻辑泄漏进路由的代价规范给出的坏示例把整个特性塞进了handle()// Bad — the feature lives in the route, so nothing else can reuse or test it class CreateThingRouteImpl implements HttpRoute.Interface { public async handle(request: IHttpRequest): PromiseIHttpResponse { const identity this.identityContext.getIdentity(); if (identity.isAnonymous()) { return json(401, { error: Authentication required. }); } const validated validate(request.body); const created await this.repository.create(validated); await this.eventPublisher.publish(new ThingCreatedEvent(created)); return json(200, created); } }这段代码集中暴露了四类反模式每一条都能在仓库中找到对应的正解坏示例中的操作问题正确归属identityContext.getIdentity() 匿名判定身份/授权是横切关注点每个入口都要重复用例内部见AdminAssistantUseCase.prepare()的NotAuthorizedError抛出或装饰器validate(request.body)校验逻辑无法脱离 HTTP 复用用例入口或领域层校验器this.repository.create(validated)直接触碰仓库绕过了用例的编排与事务边界用例内部遵循 use cases go through repositorieseventPublisher.publish(...)事件发布是副作用路由无法独立测试用例内部随业务步骤一同编排更重要的是注释点出的本质特性住在路由里其他入口就无法复用也无法测试。同一份创建 Thing的流程如果还要被后台任务、GraphQL resolver、定时器或另一个内部入口调用就必须把逻辑从路由里抠出来重新包一层——而如果一开始就放在用例里所有入口共享同一抽象即可。此外HttpRoute的handle()直接依赖identityContext、repository、eventPublisher三个具体依赖意味着测试必须构造真实的 HTTP 请求与全套基础设施拆成用例后单测只需要new CreateThingUseCase(fakeRepository)一把梭。为什么抽象之后如此重要解析、装饰、测试三件事规范要求用例behind its own abstraction仓库中的机制让这三件事成为可操作的事实1. 可解析resolved。Webiny 的用例通过createAbstraction/createImplementation声明抽象与实现的绑定携带依赖元数据。以 packages/ai-powerups/src/api/features/AdminAssistant/abstractions.ts 为例用例抽象AdminAssistantUseCase只暴露一个stream()方法其实现类在 AdminAssistantUseCase.ts 中通过createImplementation登记六个依赖Ai、AiSdkTools、全部AiSdkToolDefinition{ multiple: true }、IdentityContext、AdminAssistantConfig、ResolveAiCapabilityUseCase。路由只 import 抽象容器负责装配具体实现。2. 可装饰decorated。装饰器的钩子点在于抽象本身createAbstraction允许为同一抽象注册多个实现/装饰器HttpRouter在构建匹配路由时调用resolveImplementation该调用会应用为HttpRouteHandler注册的装饰器HttpRouter.ts 的注释明确说明 applies decorators registered forHttpRouteHandler, so a route stays decoratable。用例层同理——AdminAssistant的 Wb 翻译功能就有WbTranslatePageDecorator以装饰器形式包裹用例抽象。3. 可测试tested without an HTTP request。路由与用例分离后测试有两个层次用例单测直接构造领域参数完全不需要IHttpRequest路由测试则通过测试专用的 HTTP 事件处理器。仓库的 packages/event-handler-core/src/features/testing/HttpRouterHandler.ts 提供了TestHttpEventHandler实现它把ctx.event交给router.route()把RouteNotFoundError映射为 404、带code的结构化错误映射为 500 并保留code/data字段供断言其余兜底 500。也就是说你可以构造一个普通对象形式的请求直接await router.route(...)无需启动任何 HTTP 服务器。仓库中的真实范例AdminAssistantStreamRoute 与 AdminAssistantUseCaseai-powerups包的 Admin AssistantAI 管理助手是这条规范的完整落地样本两个文件对照阅读即可看清边界路由侧——AdminAssistantStreamRoute.ts 把定义与处理拆成两个类class AdminAssistantStreamRouteImpl implements HttpRouteHandler.Interface { public constructor(private readonly assistant: AdminAssistantUseCase.Interface) {} public async handle( request: IHttpRequest, response: IHttpResponseBuilder ): PromiseIHttpResponseBuilder { const parsed parseChatBody(request.body); if (!parsed) { return response.status(400).json({ error: BAD_REQUEST_MESSAGE }); } const events this.assistant.stream(parsed); const frames toSseFrames(events); return response.sse(frames); } } export const AdminAssistantStreamRoute HttpRouteHandler.createImplementation({ implementation: AdminAssistantStreamRouteImpl, dependencies: [AdminAssistantUseCase] }); class AdminAssistantStreamRouteDefinitionImpl implements HttpRouteDefinition.Interface { readonly name admin-assistant-stream; readonly method POST; readonly path /stream/ai/admin-assistant; readonly handler AdminAssistantStreamRoute; }对照规范逐条验证路由只做请求体解析parseChatBody失败映射 400、调用用例的stream()、把异步事件帧映射为 SSE 响应——没有任何身份判断、没有调用任何 AI SDK、没有触碰任何仓库。连注释都贯彻了这一哲学what events exist, and what they carry, belongs to the feature, so the mapping lives here——SSE 帧的线格式来自event-handler-core而事件本身属于特性因此帧映射这一小段传输适配逻辑才被允许留在路由里。文件注释还解释了为何额外开一条流式路由而非给缓冲路由加开关两种响应的契约JSON 对象 vs 事件流本质不同客户端按 URL 选择同时缓冲路由保留给无法读流的调用方。用例侧——AdminAssistantUseCase.ts 承载了全部业务逻辑这正是规范要求的auth checks, orchestration, calls to other services身份校验prepare()第一步if (this.identityContext.getIdentity().isAnonymous()) throw new NotAuthorizedError()能力解析resolveCapability.execute(ADMIN_ASSISTANT_CAPABILITY)决定模型与连接失败时抛出携带去 Settings → AI Power-Ups → Model roles 选择模型信息的错误跨服务编排调用aiSdkTools.getToolSet()、按readOnlyHint过滤只读工具、通过toolApproval回调把写操作暂停为人工审批工具调用与事件产出stream()是一个 async generator把 AI SDK 的流式 part 翻译成text/tool-call/tool-result/tool-error/approval/error/done事件——路由只负责把这些事件帧化。用例的注释还记录了一个典型教训必须用responseMessages累计历史而非response.messages仅最后一步否则审批恢复时approvalId对不上、模型只会重复提出改动——这类业务细节天然属于用例层路由永远不需要关心。边界判断清单写 Route 前先过一遍综合规范文档与仓库实现可以提炼出下面这张自查清单用于判断一段代码是否应该放进路由这段代码是否只与传输有关解析请求体、映射状态码、选择响应类型它是否只调用一个用例接口且以构造注入而非静态引用的方式获得身份/权限校验是否出现在路由里——是则移到用例如AdminAssistantUseCase.prepare()或装饰器是否直接 new 仓库、发布事件、调用第三方 SDK——是则这些都应发生在用例内部业务逻辑离开 HTTP 后是否仍可被另一个入口GraphQL resolver、后台任务、定时器复用用例能否在完全不构造IHttpRequest的情况下被单元测试如果答案有任何一项不满足规范的建议是把逻辑下沉到用例抽象之后路由保持薄。这样做的收益在 Webiny 的架构里是被源码实证的——HttpRouter.ts 通过定义与处理分离 惰性构建匹配路由避免了每次请求解析全部依赖图而薄路由 用例抽象的组合恰恰是让这套惰性机制成为可能的先决条件匹配只需纯数据处理才需要依赖图。反过来说把业务塞进路由既破坏了可测试性也让每一次请求都背上整棵依赖图。小结routes-delegate-to-use-cases.md用一页篇幅定义了一条可执行的架构纪律路由只做翻译用例只做业务抽象隔开两者。在 Webiny 中这条纪律由HttpRouteHandler/HttpRouteDefinition/ 用例createAbstraction三件套从机制上支撑——定义与处理分离让匹配零成本接口注入让用例可解析可装饰测试用事件处理器让路由与用例都能脱离 HTTP 独立验证。照着 AdminAssistantStreamRoute.ts 与 AdminAssistantUseCase.ts 这对样本写新特性就是对该规范最直接的实践。赞分享CMS后端前端【免费下载链接】webiny-jsOpen-source, self-hosted CMS platform on AWS serverless (Lambda, DynamoDB, S3). TypeScript framework with multi-tenancy, lifecycle hooks, GraphQL API, and AI-assisted development via MCP server. Built for developers at large organizations.项目地址https://gitcode.com/gh_mirrors/we/webiny-js点击查看免费下载相关推荐2025年Android Developer Roadmap完全指南业务逻辑封装与实战应用2025年Android Developer Roadmap完全指南业务逻辑封装与实战应用 Android Developer Roadmap是一份全面的学习移动开发教程低代码业务逻辑JeecgBoot Online代码编辑器低代码业务逻辑JeecgBoot Online代码编辑器 你是否还在为企业级应用开发中的复杂业务逻辑编写而烦恼是否希望有一种工具能让你无需深入编程细节就能快低代码后端前端AI 应用大模型RAG工作流自动化如何快速掌握yidaRule动态规则引擎的终极实践指南如何快速掌握yidaRule动态规则引擎的终极实践指南 yidaRule益达规则仓库是一款颠覆传统业务逻辑的动态规则引擎帮助开发者轻松管理和应用各类规则创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考