尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Webiny Webhooks Admin UI 实现指南:基于三层架构与 WebinySdk 构建完整管理界面

Webiny Webhooks Admin UI 实现指南:基于三层架构与 WebinySdk 构建完整管理界面 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 开源仓库中的 Webhooks Admin UI 实施计划 为骨架结合仓库内已落地实现的源码packages/webhooks/src/admin/、packages/sdk/src/WebhooksSdk.ts、packages/feature/src/admin/展开。读者将掌握如何在 Webiny 中按照 Gateway → UseCase → Presenter 三层模式组织一个完整的管理端功能Webhook 列表、创建/编辑表单、投递日志与权限配置并理解其背后的 DI依赖注入、MobX 响应式状态与 React 视图如何协同工作。一、方案总览目标、架构与技术栈该实施计划的目标是在 Webiny 管理端Admin UI中构建 Webhooks 管理界面覆盖四类核心能力列表List分页展示 Webhook支持搜索、排序、筛选、多选、删除、手动触发Trigger表单Form创建与编辑 Webhook名称、slug、endpointUrl、描述、启用状态、订阅事件并展示只读的签名密钥Signing Secret投递日志Delivery Log以抽屉/独立页面查看每个 Webhook 的历史投递记录支持重发Resend与查看投递详情payload、headers、response权限Permissions通过 Webiny 管理端权限体系控制 read/create/edit/delete 能力。架构采用 Webiny 管理端标准的三层模式Gateway网关封装对WebinySdksdk.webhooks.*的调用统一处理Result的成败分支UseCase用例业务逻辑入口委托给 Gateway薄封装层Presenter表现者持有 MobX 响应式状态向 React 视图暴露vmViewModel与actions列表视图复用共享的ListPresenterIDataSource表单视图使用FormModel。所有依赖注入均通过createAbstraction/createFeature完成即webiny/feature/admin提供的 DI 抽象与 Feature 注册机制。技术栈为 TypeScript MobX React核心依赖包括webiny/feature/admin、webiny/sdk、webiny/admin-ui、webiny/app-admin。文件统一放置在packages/webhooks/src/admin/目录下下文简称admin/这与仓库实际结构一致——源码树 中features/、presentation/、shared/、WebhookRoutes.tsx、Webhooks.tsx、routes.ts、permissions.ts均已按此布局落地。二、贯穿全局的编码约定Conventions计划对所有 Feature 提出了统一约束理解这些约定有助于直接阅读仓库代码导入规范每个具名导入独占一行createAbstraction与createFeature均来自webiny/feature/adminWebinySdk从webiny/app-admin/features/webinySdk/abstractions.js导入Webhook、WebhookDelivery、WebhookEvent等类型直接从webiny/sdk导入无需自定义 DTO。文件规范一个文件只放一个类文件底部通过export const X Abstraction.createImplementation(...)导出实现使用命名空间模式export namespace Foo { export type Interface IFoo; }把抽象与其接口类型组织在一起。作用域ScopeGateway 使用单例作用域.inSingletonScope()UseCase 使用默认的 transient 作用域。Feature 约束每个createFeature必须提供resolve函数。注释与导出单行注释用//多行用/* */注释以句号结尾禁止默认导出。三、Task 1Foundation——共享类型、路由与权限底座Foundation 层没有外部依赖为后续所有任务提供地基共 8 个文件admin/shared/types.ts admin/routes.ts admin/features/permissions/abstractions.ts admin/features/permissions/feature.ts admin/features/permissions/index.ts admin/presentation/security/usePermissions.ts admin/presentation/security/HasPermission.tsx3.1 共享类型直接从 SDK 复用杜绝自定义 DTOshared/types.ts的核心思想是管理端与 API 层共用webiny/sdk的类型契约避免在管理端重复定义数据结构。其导出集合包括实体类型Webhook、WebhookDelivery、WebhookEvent、列表参数与结果类型ListWebhooksParams/Result、ListWebhookDeliveriesParams/Result以及写操作参数类型CreateWebhookParams、UpdateWebhookParams。这些类型在仓库中确实由 SDK 提供WebhooksSdk.ts 定义了WebhooksSdk类其方法签名正是这些类型参数的载体例如async listWebhooks(params?: ListWebhooksParams) : PromiseResultListWebhooksResult, HttpError | ApiError | NetworkError | ValidationError async createWebhook(params: CreateWebhookParams) : PromiseResultWebhook, ... async triggerWebhook(params: TriggerWebhookParams) : PromiseResultWebhookDelivery, ...所有方法统一返回ResultT, E联合类型这也是后续 Gateway 中result.isFail()分支判断的契约来源。3.2 路由定义基于webiny/app-admin的 Routeroutes.ts使用webiny/app-admin导出的Route声明两条核心路由export const Routes { List: new Route({ name: Webhooks/List, path: /webhooks }), Form: new Route({ name: Webhooks/Form, path: /webhooks/:id, params: zod ({ id: zod.string() }) }) };其中/webhooks/:id使用 zod 校验路径参数id创建新 Webhook 时以特殊值new作为id传入表单 Presenter 通过id new判断isNew。仓库中实际落地版本在此基础上扩展出了Deliveries/webhooks/deliveries与Settings/webhooks/settings两条路由见 routes.ts说明投递日志在最终实现中从抽屉演进为了独立页面。3.3 权限体系Schema → Abstraction → Feature → Hook/组件权限底座由四块拼成全部围绕一个权限 Schema 展开。仓库中该 Schema 位于 admin/permissions.tsexport const WEBHOOK_PERMISSIONS_SCHEMA createPermissionSchema({ prefix: webhooks, fullAccess: true, entities: [ { id: webhook, permission: webhooks.webhook, scopes: [full], actions: [{ name: rwd }] } ] });abstractions.ts用createPermissionsAbstraction(WEBHOOK_PERMISSIONS_SCHEMA)创建WebhookPermissions抽象单例并以命名空间导出Interface Permissionstypeof WEBHOOK_PERMISSIONS_SCHEMAfeature.ts用createPermissionsFeature(WEBHOOK_PERMISSIONS_SCHEMA, WebhookPermissions)把 Schema 与抽象注册进 DI 容器usePermissions.ts用createUsePermissions(WebhookPermissions)生成usePermissionsHookHasPermission.tsx用createHasPermission(WebhookPermissions, WEBHOOK_PERMISSIONS_SCHEMA)生成权限守卫组件接受entitywebhook属性用于包裹路由与菜单。对应文件已落地于 packages/webhooks/src/admin/presentation/security/。后续 Presenter 中通过permissions.canRead(webhook)、permissions.canCreate(webhook)、permissions.canEdit(webhook)、permissions.canDelete(webhook)读取能力位视图层据此渲染/隐藏按钮。四、Task 2Webhook CRUD Features——五连 Feature 的标准范式Task 2 定义五个无头headlessFeaturelistWebhooks、getWebhook、createWebhook、updateWebhook、deleteWebhook。每个 Feature 遵循完全相同的五文件范式{abstractions, XxxGateway, XxxUseCase, feature, index}.ts五个 Feature 之间互不依赖可并行开发共 5 × 5 25 个文件。4.1 abstractions抽象即契约以listWebhooks为例抽象文件定义三层契约网关入参/出参ListWebhooksGatewayParamswhere?: { enabled?: boolean }、limit?: number、after?: string与ListWebhooksGatewayResultdata: Webhook[]meta: { cursor, hasMoreItems, totalCount }后者即游标分页元数据网关抽象IListWebhooksGatewaycreateAbstractionIListWebhooksGateway(ListWebhooksGateway)用例抽象IListWebhooksUseCasecreateAbstractionIListWebhooksUseCase(ListWebhooksUseCase)。每个抽象都用export namespace X { export type Interface IX; }绑定接口类型实现类以X.Interface作为类型标注。4.2 GatewaySDK 调用的唯一出口Gateway 是三层中唯一直接接触WebinySdk的地方负责把 SDK 的Result风格返回值翻译成管理端友好的错误抛出class ListWebhooksGatewayImpl implements GatewayAbstraction.Interface { constructor(private readonly sdk: WebinySdk.Interface) {} async execute(params: ListWebhooksGatewayParams): PromiseListWebhooksGatewayResult { const result await this.sdk.webhooks.listWebhooks({ where: params.where, limit: params.limit, after: params.after }); if (result.isFail()) { throw new Error(result.error.message); } return { data: result.value.data, meta: result.value.meta }; } } export const ListWebhooksGateway GatewayAbstraction.createImplementation({ implementation: ListWebhooksGatewayImpl, dependencies: [WebinySdk] });关键点构造函数以private readonly sdk: WebinySdk.Interface注入 SDK 抽象通过createImplementation的dependencies: [WebinySdk]声明依赖result.isFail()失败分支统一抛Error成功分支才解包result.value——这一模式在getWebhook、createWebhook、updateWebhook、deleteWebhook返回Promiseboolean中完全一致。4.3 UseCase委托网关的薄封装UseCase 不直接访问 SDK而是注入 Gateway 抽象并把执行委托给它class ListWebhooksUseCaseImpl implements UseCaseAbstraction.Interface { constructor(private readonly gateway: ListWebhooksGateway.Interface) {} async execute(params: ListWebhooksGatewayParams): PromiseListWebhooksGatewayResult { return this.gateway.execute(params); } } export const ListWebhooksUseCase UseCaseAbstraction.createImplementation({ implementation: ListWebhooksUseCaseImpl, dependencies: [ListWebhooksGateway] });createWebhook的入参结构定义了 Webhook 的完整字段集合name、endpointUrl、events: string[]为必填slug、description、enabled为可选updateWebhook则全部字段可选name?、slug?、endpointUrl?、description?、enabled?、events?更新网关以{ id, ...input }透传给 SDK。4.4 featureDI 容器注册与解析Feature 文件负责把抽象与实现注册进容器并声明resolve输出export const ListWebhooksFeature createFeature({ name: Webhooks/ListWebhooks, register(container) { container.register(ListWebhooksUseCase); container.register(ListWebhooksGateway).inSingletonScope(); }, resolve(container) { return { useCase: container.resolve(UseCaseAbstraction) }; } });注意这里的作用域约定UseCase 用默认transient作用域每次解析创建新实例Gateway 显式.inSingletonScope()。index.ts统一导出XxxUseCase抽象与XxxFeature供上层引用。4.5 仓库落地形态对照仓库 packages/webhooks/src/admin/features/ 中不仅完整实现了计划中的五个 CRUD Feature还额外演进出了getWebhookSettings、updateWebhookSettings两个设置类 Feature印证了这套五文件范式的可复制性。另外仓库中ListWebhooks目录多了一个ListWebhooksRepository.ts说明后续迭代中加入了 Repository 层但这属于实现演进不影响本文介绍的标准范式。五、Task 3Delivery Event Features——投递与事件能力Task 3 再增加四个无头 FeaturelistWebhookDeliveries、resendWebhookDelivery、triggerWebhook、listAvailableEvents同样彼此无依赖、可并行开发。这些能力支撑列表页的手动触发和表单页/日志页的投递记录。listWebhookDeliveries入参为{ webhookId: string; limit?: number; after?: string }返回与列表同构的data: WebhookDelivery[] 游标meta。网关调用sdk.webhooks.listWebhookDeliveries({ webhookId, limit, after })。注意入参比列表多一个必填的webhookId用于按 Webhook 过滤投递记录。resendWebhookDeliveryexecute(id: string): Promiseboolean网关调用sdk.webhooks.resendWebhookDelivery({ id })用于日志页对失败投递执行重发。triggerWebhookexecute(id: string, payload: Recordstring, unknown): PromiseWebhookDelivery网关调用sdk.webhooks.triggerWebhook({ id, payload })。它返回一次新的WebhookDelivery——因为手动触发本身就是一次真实投递会立即产生一条可查看的记录。列表页 Presenter 中以triggerWebhook(id, { test: true })方式调用随后刷新列表。listAvailableEventsexecute(): PromiseWebhookEvent[]网关调用sdk.webhooks.listAvailableWebhookEvents()无参数。表单页用它渲染可订阅事件的选项列表新建与编辑时都会加载。六、Task 4WebhookList 表现层——复用共享 ListPresenter列表表现层依赖 Task 1-3由 6 个文件组成admin/presentation/WebhookList/{abstractions, WebhookListDataSource, WebhookListPresenter, feature, index}.ts admin/presentation/WebhookList/components/WebhookListView.tsx6.1 视图模型与动作契约IWebhookListViewModel将共享列表的状态IListViewModelWebhook与权限位canRead、canCreate、canEdit、canDelete打包成单一vmIWebhookListActions在共享列表动作search、sort、filter、selection、loadMore、refresh之上追加两个领域动作export interface IWebhookListActions extends IListActions { deleteWebhook(id: string): Promisevoid; triggerWebhook(id: string): Promisevoid; }6.2 IDataSource列表数据源契约WebhookListDataSource实现IDataSourceWebhook是连接共享ListPresenter与ListWebhooksUseCase的适配器。它内部持有三份响应式状态_rows、_meta{ cursor, hasMoreItems, totalCount }、_loading构造时通过makeAutoObservable配置——listWebhooksUseCase标记为false不观察依赖rows标记为computed。两个关键方法query(params)首次/刷新加载把params.filters映射为where、params.limit映射为limit、params.cursor映射为after调用 UseCase 后runInAction中整体替换_rows与_metaloadMore(params)仅在hasMoreItems !loading时继续以this._meta.cursor ?? undefined作为after并在runInAction中以[...this._rows, ...result.data]追加而非替换。这套模式把游标分页细节完全收纳在数据源内部共享ListPresenter无需关心具体数据来自哪里。6.3 Presenter组合共享 ListPresenter 与领域动作WebhookListPresenterImpl构造函数注入五个依赖ListPresenter.InterfaceWebhook、ListWebhooksUseCase、DeleteWebhookUseCase、TriggerWebhookUseCase、WebhookPermissions。vm为computed实时组合listPresenter.vm与权限位。init()是装配点创建WebhookListDataSource实例并配置共享列表的初始排序与分页this.listPresenter.init({ dataSource, initialSort: { field: createdOn, direction: DESC }, limit: 20 });actions采用显式委托search/sort/filter/selection/loadMore/refresh 全部转发给listPresenter.actions而领域动作则在 UseCase 执行后触发刷新deleteWebhook: async (id: string) { await this.deleteWebhookUseCase.execute(id); await this.listPresenter.actions.refresh(); }, triggerWebhook: async (id: string) { await this.triggerWebhookUseCase.execute(id, { test: true }); await this.listPresenter.actions.refresh(); }6.4 视图作用域容器 observer 组件WebhookListView是列表页入口组件体现了按视图隔离依赖的作用域容器模式用useMemo基于根容器createChildContainer()创建子容器在子容器中register五个 FeatureListWebhooksFeature、DeleteWebhookFeature、TriggerWebhookFeature、WebhookPermissionsFeature、WebhookListPresenterFeature再用DiContainerProvider包裹内部组件。内部组件通过useFeature(WebhookListPresenterFeature)拿到 Presenter在useEffect中调用presenter.init()。视图骨架的关键结构最终 UI 细节以浏览器可见后打磨为准顶栏Heading level{5}显示标题Webhooks右侧在vm.permissions.canCreate为真时渲染Create Webhook按钮点击navigate(Routes.Form, { id: new })跳转新建主体预留DataTable挂载点计划中的列为name、endpointUrl、enabled、createdOn行操作包含 Edit、Trigger、Delete。仓库中的落地实现见 WebhookListView.tsx且组件拆分更细CreateWebhookButton、WebhookDeliveriesButton、WebhookListContent还新增了投递日志入口按钮。七、Task 5WebhookForm 表现层——FormModel 生命周期管理表单表现层依赖 Task 1-3由 5 个文件组成admin/presentation/WebhookForm/{abstractions, WebhookFormPresenter, feature, index}.ts admin/presentation/WebhookForm/components/WebhookFormView.tsx7.1 视图模型IWebhookFormViewModel比列表更丰富覆盖表单的完整状态export interface IWebhookFormViewModel { loading: boolean; saving: boolean; isNew: boolean; webhook: Webhook | null; showDeliveries: boolean; availableEvents: WebhookEvent[]; permissions: { canEdit: boolean; canDelete: boolean; }; }IWebhookFormActions提供save()、deleteWebhook()、openDeliveries()、closeDeliveries()四个动作init(id: string)负责初始化。7.2 Presenter并行加载与新建/编辑分流WebhookFormPresenterImpl构造函数注入 7 个依赖FormModelFactory.Interface、GetWebhookUseCase、CreateWebhookUseCase、UpdateWebhookUseCase、DeleteWebhookUseCase、ListAvailableEventsUseCase、WebhookPermissions。init(id)是生命周期核心处理两条路径async init(id: string): Promisevoid { this._loading true; this._isNew id new; this._webhookId id new ? null : id; const eventsPromise this.listAvailableEventsUseCase.execute(); if (!this._isNew) { const [webhook, events] await Promise.all([ this.getWebhookUseCase.execute(id), eventsPromise ]); runInAction(() { this._webhook webhook; this._availableEvents events; this._loading false; }); } else { const events await eventsPromise; runInAction(() { this._availableEvents events; this._loading false; }); } }要点通过id new区分新建/编辑这依赖路由层传入的特殊值可订阅事件列表无论新建还是编辑都会加载且编辑场景下与 Webhook 详情用Promise.all并行拉取缩短等待时间所有状态变更包在runInAction中保证 MobX 事务一致性。actions.save()当前是骨架置_saving true后真正的 FormModel 提交与 create/update 分流需要在验证FormModelFactory运行时 API 后接入init()与save()deleteWebhook()仅在非新建且有_webhookId时执行删除。7.3 视图与仓库落地WebhookFormView与列表页同构子容器注册GetWebhookFeature、CreateWebhookFeature、UpdateWebhookFeature、DeleteWebhookFeature、ListAvailableEventsFeature、WebhookPermissionsFeature、WebhookFormPresenterFeature内部组件在useEffect中presenter.init(id)其中id来自useRouter().paramsloading时渲染OverlayLoader。顶栏逻辑新建时标题为Create Webhook编辑时显示vm.webhook?.name非新建场景显示Deliveries按钮actions.openDeliveries()vm.permissions.canEdit为真时显示 Save 按钮disabled{vm.saving}文案随saving在Saving...与Save间切换。表单字段预留为name、slug、endpointUrl、description、enabled、events已有 Webhook 的签名密钥Signing Secret以只读方式展示——仓库中已落地为独立的 SigningSecret.tsx 组件。八、Task 6WebhookDeliveries 表现层——投递日志投递日志表现层依赖 Task 1 与 Task 3计划以抽屉Drawer形式呈现由 6 个文件组成admin/presentation/WebhookDeliveries/{abstractions, WebhookDeliveriesDataSource, WebhookDeliveriesPresenter, feature, index}.ts admin/presentation/WebhookDeliveries/components/WebhookDeliveriesDrawer.tsx8.1 契约IWebhookDeliveriesViewModel由两部分组成共享列表状态IListViewModelWebhookDelivery与当前选中的投递详情selectedDelivery: WebhookDelivery | null。IWebhookDeliveriesActions在共享动作之外增加resend(id)与selectDelivery(delivery | null)。8.2 数据源与 PresenterWebhookDeliveriesDataSource与列表数据源结构几乎一致区别在于构造函数多注入一个webhookIdquery/loadMore始终以该webhookId调用ListWebhookDeliveriesUseCase——数据源按 Webhook 隔离投递记录。WebhookDeliveriesPresenterImpl注入三个依赖ListPresenter.InterfaceWebhookDelivery、ListWebhookDeliveriesUseCase、ResendWebhookDeliveryUseCase。init(webhookId)同样装配共享列表this.listPresenter.init({ dataSource: new WebhookDeliveriesDataSource(this.listDeliveriesUseCase, webhookId), initialSort: { field: createdOn, direction: DESC }, limit: 20 });resend(id)执行重发 UseCase 后刷新列表selectDelivery(delivery)直接写入_selectedDeliveryMobX 自动观察。8.3 抽屉组件WebhookDeliveriesDrawer接收{ webhookId, open, onClose }三个 props仅在open时presenter.init(webhookId)useEffect依赖[presenter, webhookId, open]。子容器只注册三个 FeatureListWebhookDeliveriesFeature、ResendWebhookDeliveryFeature、WebhookDeliveriesPresenterFeature。抽屉内容预留投递列表每行eventType、status、createdOn、responseStatus带状态徽标与重发按钮和选中投递详情payload、headers、response。实现演进说明仓库最终把投递日志从抽屉升级为独立路由页面 WebhookDeliveriesPage并拆出DeliveryAccordionRow、DeliveryFilters、DeliveryDetailContent、DeliveryBottomInfoBar、statusVariant等组件同时在 routes.ts 增加了Webhooks/Deliveries路由/webhooks/deliveries可选参数webhookId。这印证了先以结构骨架打通数据流再在浏览器中打磨 UI的计划策略。九、Task 7Extension 装配——把一切接进 AdminTask 7 依赖全部前置任务负责顶层装配共 3 个文件admin/Extension.tsx admin/WebhookRoutes.tsx src/exports/admin/webhooks.ts9.1 WebhookRoutes路由 菜单 权限守卫WebhookRoutes使用AdminConfig声明路由与菜单并用HasPermission整体守卫export const WebhookRoutes () { const { getLink } useRouter(); return ( AdminConfig HasPermission entitywebhook Route route{Routes.List} element{ AdminLayout titleWebhooksWebhookListView //AdminLayout } / Route route{Routes.Form} element{ AdminLayout titleWebhooksWebhookFormView //AdminLayout } / Menu namewebhooks aftersettings element{ Menu.Link textWebhooks to{getLink(Routes.List)} / } / /HasPermission /AdminConfig ); };要点两条路由都包在AdminLayout titleWebhooks中获得统一的管理端布局菜单项namewebhooks、aftersettings控制菜单位置整个区块被HasPermission entitywebhook包裹无权限用户看不到路由入口与菜单。9.2 ExtensionFeature 总注册Extension组件把所有 Feature 一次性注册进根容器分为三层export const Extension () { return ( {/* Headless features. */} RegisterFeature feature{ListWebhooksFeature} / RegisterFeature feature{GetWebhookFeature} / RegisterFeature feature{CreateWebhookFeature} / RegisterFeature feature{UpdateWebhookFeature} / RegisterFeature feature{DeleteWebhookFeature} / RegisterFeature feature{ListWebhookDeliveriesFeature} / RegisterFeature feature{TriggerWebhookFeature} / RegisterFeature feature{ResendWebhookDeliveryFeature} / RegisterFeature feature{ListAvailableEventsFeature} / RegisterFeature feature{WebhookPermissionsFeature} / {/* Presentation features. */} RegisterFeature feature{WebhookListPresenterFeature} / RegisterFeature feature{WebhookFormPresenterFeature} / RegisterFeature feature{WebhookDeliveriesPresenterFeature} / {/* Routes menu. */} WebhookRoutes / {/* Security permissions UI. */} AdminConfig Security.Permissions namewebhooks titleWebhooks descriptionManage webhook permissions. schema{WEBHOOK_PERMISSIONS_SCHEMA} / /AdminConfig / ); };Security.Permissions把权限 Schema 注册进管理端安全设置界面运维人员即可在 UI 中配置 Webhooks 权限。仓库落地文件为 Webhooks.tsx对外导出名称为Webhooks见 index.ts。9.3 导出与提交流程src/exports/admin/webhooks.ts只做一件事export { Extension } from ../../admin/Extension.js;。随后执行计划规定的提交流程git add . yarn /dev/null 21 node scripts/generateTsConfigsInPackages.js yarn adio yarn format /dev/null 21 yarn lint yarn webiny sync-dependencies git add .这些命令对应仓库根目录的脚本体系scripts/generateTsConfigsInPackages.js为各包生成 tsconfigyarn adiowebiny.config 提供的 lint 命令检查代码规范yarn webiny sync-dependencies同步依赖版本。十、计划中的明确边界与后续事项Notes实施计划末尾对已知边界做了诚实标注这对任何 Agent 或开发者执行计划都至关重要UI 组件是结构骨架DataTable列定义、FormModel字段渲染、Drawer内容都将在功能接线完成、浏览器可见后再细化。Presenters 与数据流是完整的——这意味着数据正确性的验证可以先行视觉层可后置迭代。仓库实现印证了这一节奏骨架已演进出WebhookDeliveriesPage、DeliveryFilters、SigningSecret等完整组件。FormModel 集成待运行时验证WebhookFormPresenter中的buildForm()需要在确认FormModelFactory运行时 API 后接入init()与actions.save()字段定义以 specdocs/superpowers/specs/2026-05-16-webhooks-admin-ui-design.md为准。Features 层不做单元测试网关与用例是薄委托层gateway → SDK、usecase → gateway测试它们等于测试框架本身。Presenter 测试留待后续阶段补充。十一、结语从计划到落地的一手参照本文所述三层范式在仓库中并非纸面设计——packages/webhooks/src/admin/下 13 个 Feature、3 个表现层 Presenter、完整的安全与路由装配均已落地且在此过程中演进出了 Settings 类 Feature、独立投递日志页与更细的组件拆分。阅读本指南时可对照以下文件深化理解实现骨架packages/webhooks/src/admin/SDK 契约WebhooksSdk.ts 与 sdk/src/methods/webhooks/权限 Schemaadmin/permissions.ts路由定义admin/routes.tsDI 基础设施packages/feature/src/admin/对希望在 Webiny 中新增一个管理端模块的团队而言这份计划的五文件 Feature 范式 共享 ListPresenter/FormModel 作用域容器 权限 Schema组合本身就是一套可复制的最小可行方法论先以 Gateway/UseCase 打通数据再用 Presenter 承载状态最后让 React 视图保持纯粹——这正是 Webiny 管理端架构在源码层面的真实写照。赞分享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点击查看免费下载相关推荐为什么你的团队需要mention-bot5个提升协作效率的理由为什么你的团队需要mention bot5个提升协作效率的理由 在大型GitHub项目中团队成员往往难以追踪所有代码变更和拉取请求导致重要PR长时间无人审开发工具nanoMODBUS架构深度解析企业级工业通信的轻量化解决方案nanoMODBUS架构深度解析企业级工业通信的轻量化解决方案 在工业物联网和边缘计算快速发展的今天资源受限的嵌入式系统面临着工业通信协议集成的严峻挑战。传CMS后端前端Keystone 6 自定义 Admin UI 页面基于 /admin/pages 目录构建自定义管理页面的完整实战指南Keystone 6 自定义 Admin UI 页面基于 /admin/pages 目录构建自定义管理页面的完整实战指南 导读 Keystone 6 的 Ad后端上一篇gojsonpointer 详解go-openapi/jsonpointer 的 JSON Pointer 实现及其在 OpenShift 测试套件中的应用下一篇gallery扩展开发如何为数字展馆添加新的交互功能与特效创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表