新闻详情

新闻详情

首页 / 资讯中心 / 详情

Webiny api-headless-cms 内容条目数据工厂(Entry Data Factories)DI 重构:内联逻辑与工厂注入实战指南

发布时间:2026/9/28 2:20:07来源:尧图网络
Webiny api-headless-cms 内容条目数据工厂(Entry Data Factories)DI 重构:内联逻辑与工厂注入实战指南
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点击查看免费下载本文基于仓库内实施计划 2026-05-13-entry-data-factories-inline-logic.md 与配套设计文档 2026-05-13-entry-data-factories-inline-logic-design.md 展开。它面向需要理解 Webiny 新版features/目录架构、webiny/feature/api依赖注入机制或想在自己的模块中落地逻辑内联 工厂 token 注入重构模式的开发者。读完本文你将掌握六个内容条目数据工厂Create / Update / CreateRevisionFrom / Publish / Unpublish / Republish如何把crud/下的旧函数逻辑吸收进各自Impl类、三个共享工具文件如何上移到features/父级、六个 UseCase 如何通过 DI 容器注入工厂 token 并裁剪不再需要的 Context 依赖以及整条重构的验证与提交链路。一、重构背景与目标消灭crud/contentEntry/entryDataFactories/在 Webiny 的packages/api-headless-cms包中内容条目Content Entry的数据装配逻辑一度散落在crud/contentEntry/entryDataFactories/目录下——那里存放着一批函数式实现如createEntryData()、createUpdateEntryData()以及它们私有的辅助函数。与此同时新版架构在features/contentEntry/entryDataFactories/下已经建立了面向 DI 的工厂实现每个工厂由一个Impl类 一个createImplementation注册组成。两类实现并存导致逻辑重复、消费方六个 UseCase 与ValidateEntryUseCase仍然直接 import 旧的crud/路径形成技术债。本次重构的核心目标是见 计划文档内联逻辑把crud/contentEntry/entryDataFactories/中每个旧函数的完整函数体吸收进对应工厂Impl类的create()方法或由其调用的私有方法旧函数原有的context、getIdentity、getTenant、accessControl等入参不再作为函数参数传递而是改从this.xxxContext读取共享文件上移三个被多个工厂复用的共享文件statuses.ts、system.ts、mapAndCleanUpdatedInputData.ts以内容不变、仅改路径的方式迁移到features/contentEntry/entryDataFactories/父级UseCase 接线六个 UseCaseCreate / Update / CreateEntryRevisionFrom / Publish / Unpublish / Republish停止直接调用旧函数改为在构造函数中注入对应工厂 token同时裁剪那些仅仅为了喂给旧函数才引入的 Context 依赖IdentityContext、TenantContext、CmsContext删除死代码所有消费者迁移完成后整目录删除packages/api-headless-cms/src/crud/contentEntry/entryDataFactories/。技术栈上重构完全基于 Webiny 自研的webiny/feature/apicreateImplementation、createAbstraction、createFeature与 DI 容器。二、目标文件全景Create / Rewrite / Modify / Delete 四类清单计划文档给出了非常明确的文件操作清单按动作分为四类Create新建3 个共享文件内容为旧文件的同构拷贝packages/api-headless-cms/src/features/contentEntry/entryDataFactories/statuses.tspackages/api-headless-cms/src/features/contentEntry/entryDataFactories/system.tspackages/api-headless-cms/src/features/contentEntry/entryDataFactories/mapAndCleanUpdatedInputData.tsRewrite重写内联逻辑、去掉旧的 crud import6 个工厂实现文件.../entryDataFactories/CreateEntryDataFactory/CreateEntryDataFactory.ts.../entryDataFactories/UpdateEntryDataFactory/UpdateEntryDataFactory.ts.../entryDataFactories/CreateEntryRevisionFromDataFactory/CreateEntryRevisionFromDataFactory.ts.../entryDataFactories/CreatePublishEntryDataFactory/CreatePublishEntryDataFactory.ts.../entryDataFactories/CreateUnpublishEntryDataFactory/CreateUnpublishEntryDataFactory.ts.../entryDataFactories/CreateRepublishEntryDataFactory/CreateRepublishEntryDataFactory.tsRewrite重写接线工厂 token、裁剪不再需要的 Context 依赖6 个 UseCase 文件packages/api-headless-cms/src/features/contentEntry/CreateEntry/CreateEntryUseCase.ts.../UpdateEntry/UpdateEntryUseCase.ts.../CreateEntryRevisionFrom/CreateEntryRevisionFromUseCase.ts.../PublishEntry/PublishEntryUseCase.ts.../UnpublishEntry/UnpublishEntryUseCase.ts.../RepublishEntry/RepublishEntryUseCase.tsModify仅改 import 路径不改逻辑1 个文件packages/api-headless-cms/src/features/contentEntry/ValidateEntry/ValidateEntryUseCase.tsDelete整目录 10 个文件packages/api-headless-cms/src/crud/contentEntry/entryDataFactories/值得注意的是crud/contentEntry/目录并未被整体废弃——重构只删除entryDataFactories/子目录。计划实施后对照当前仓库该目录仍保留着entryDataValidation.ts、referenceFieldsMapping.ts、references/buildPaths.ts、validateEntries.ts与searchableFields.ts等被工厂继续引用的底层工具见 crud/contentEntry 目录。三、第一步创建三个共享工具文件Task 1计划文档要求先在features/层创建三个内容与旧文件完全一致的共享文件。它们分别是3.1statuses.ts状态常量的单一出口// packages/api-headless-cms/src/features/contentEntry/entryDataFactories/statuses.ts import { CONTENT_ENTRY_STATUS } from ~/types/index.js; export const STATUS_DRAFT CONTENT_ENTRY_STATUS.DRAFT; export const STATUS_PUBLISHED CONTENT_ENTRY_STATUS.PUBLISHED; export const STATUS_UNPUBLISHED CONTENT_ENTRY_STATUS.UNPUBLISHED;它把条目生命周期中的三种状态草稿 / 已发布 / 已取消发布统一收敛为三个可直接引用的常量消费方是 Create、CreateRevisionFrom、Publish、Unpublish 四个工厂。3.2system.ts系统字段的合并逻辑// packages/api-headless-cms/src/features/contentEntry/entryDataFactories/system.ts import type { CmsEntry, ICmsEntrySystem } from ~/types/index.js; interface IInputWithPossibleSystem { system: PartialICmsEntrySystem; } interface IParams { input: PartialIInputWithPossibleSystem; original?: CmsEntry | null; } export const getSystem ({ input, original }: IParams): ICmsEntrySystem | undefined { if (!input.system) { return original?.system; } return { ...original?.system, ...input.system }; };getSystem()的语义是若新输入没有携带system字段则沿用原条目original的 system若携带了则用输入的system浅合并覆盖原条目的system。这一逻辑在 Create无 original、Update 与 CreateRevisionFrom有 original三类场景中行为统一因此被抽为共享模块。3.3mapAndCleanUpdatedInputData.ts按模型字段白名单清洗更新输入// packages/api-headless-cms/src/features/contentEntry/entryDataFactories/mapAndCleanUpdatedInputData.ts import WebinyError from webiny/error; import type { CmsEntryValues, CmsModel } from ~/types/index.js; export const mapAndCleanUpdatedInputData TValues extends CmsEntryValues CmsEntryValues( model: CmsModel, input?: PartialTValues ) { if (!input) { return {}; } return model.fields.reducePartialTValues((acc, field) { if (!field.fieldId) { throw new WebinyError(Field does not have an fieldId., MISSING_FIELD_ID, { field }); } const key field.fieldId as keyof TValues; const value input[key]; if (value undefined) { return acc; } acc[key] value; return acc; }, {}); };这个函数解决的是部分更新场景的核心问题更新请求通常只携带需要修改的字段。它遍历model.fields以每个字段的fieldId为 key只保留输入中存在非undefined的值若模型字段缺少fieldId则抛出WebinyErrorcode 为MISSING_FIELD_ID。按设计文档的依赖矩阵它被 Update、CreateRevisionFrom 两个工厂以及ValidateEntryUseCase共用因此被放在父级而不是任何单个工厂目录内。四、核心改造一六个工厂实现的内联Task 2–7设计文档用一张表精确列出了每个工厂实现文件需要内联的私有辅助函数工厂实现文件需要内联的私有辅助函数CreateEntryDataFactory.tsconvertDefaultValue、getDefaultValue、cleanInputValues、createEntryIdUpdateEntryDataFactory.tscreateEntryMeta、transformEntryStatusCreateEntryRevisionFromDataFactory.tsincreaseEntryIdVersionCreatePublishEntryDataFactory.ts无CreateUnpublishEntryDataFactory.ts无CreateRepublishEntryDataFactory.ts无内联的原则是旧函数体直接成为create()方法体原函数签名中的context/getIdentity/getTenant/accessControl参数不再由调用方传入而是由Impl类构造器注入的 Context 提供仅被单一函数使用的辅助函数以模块作用域module-scope函数的形式留在各自文件内。4.1CreateEntryDataFactoryImpl最重的工厂从 计划文档 Task 2 的完整代码可以看到当前仓库 CreateEntryDataFactory.ts 已按此落地这个工厂的构造器注入四个依赖public constructor( private readonly cmsContext: CmsContext.Interface, private readonly identityContext: IdentityContext.Interface, private readonly tenantContext: TenantContext.Interface, private readonly accessControl: AccessControl.Interface ) {}其create()方法完整复刻了旧createEntryData()的处理流水线值得逐段拆解第一步清洗输入并填充默认值。cleanInputValues()遍历model.fields对每个fieldId输入有值则保留输入缺失则以getDefaultValue(field)兜底。getDefaultValue()的取值优先级是——先看field.settings.defaultValue若定义再看predefinedValues预定义值非列表字段取第一个selected true的值列表字段field.list为真取所有被选中的值组成数组。convertDefaultValue()则负责把默认值按字段类型转换boolean字段Boolean(value)、number字段Number(value)其他类型原样返回。第二步数据校验与引用映射。清洗后的initialValues先交给validateModelEntryDataOrThrow({ context, model, values, skipValidators })实现见 entryDataValidation.ts随后经referenceFieldsMapping({ context, model, values, validateEntries: true })实现见 referenceFieldsMapping.ts做引用字段的值映射——创建场景必须validateEntries: true。第三步生成条目 ID 与版本。createEntryId(rawInput)内部逻辑默认entryId mdbid()若调用方显式传入input.id则用正则/^([a-zA-Z0-9])([a-zA-Z0-9-])([a-zA-Z0-9])$/校验仅允许字母数字与连字符且不能以-开头或结尾不合法抛INVALID_ID随后固定version 1并用createIdentifier({ id: entryId, version })合成形如{entryId}#0001的复合id。第四步状态、权限与锁定。默认状态为STATUS_DRAFT当输入状态为STATUS_PUBLISHED时先经accessControl.canAccessEntry({ model, pw: p })校验发布权限为STATUS_UNPUBLISHED时经pw: u校验取消发布权限不通过抛NotAuthorizedError见 errors.ts。locked status ! STATUS_DRAFT——非草稿即锁定。第五步时间戳与身份字段回填。通过getDate(raw, fallback)date.ts与getIdentity(raw, fallback)identity.ts组合用户显式传入的值优先否则用currentDateTime/ 当前身份兜底仅在状态为STATUS_PUBLISHED时填充firstPublishedOn/By、lastPublishedOn/By以及revisionFirst/LastPublishedOn/By四组发布元字段。第六步组装CmsEntry对象。关键字段包括tenant取tenantContext.getTenant().id一整套 entry 级createdOn、savedOn、modifiedOn、deletedOn、restoredOn及对应By与 revision 级revisionCreatedOn等时间/身份字段location.folderId的优先级rawInput.location?.folderId→rawInput.wbyAco_location?.folderId→ROOT_FOLDER常量兜底system由getSystem({ input: rawInput })生成新建无 originallive字段已发布时置{ version }否则为null固定revisionDescription: 。第七步对已生成的 entry 做二次权限校验。若状态非草稿还需以entry为对象再走一次canAccessEntry保证创建前后权限一致。最终返回{ entry, input: { ...rawInput, values: structuredClone(values) } }——注意返回的input中values是引用映射后的深拷贝供后续事件发布使用。文件末尾以createImplementation完成 DI 注册export const CreateEntryDataFactory createImplementation({ abstraction: FactoryAbstraction, implementation: CreateEntryDataFactoryImpl, dependencies: [CmsContext, IdentityContext, TenantContext, AccessControl] });4.2UpdateEntryDataFactoryImpl基于原条目做增量合并与创建不同更新必须持有originalEntry因此create()签名变为create(model, rawInput, originalEntry, options?, metaInput?)构造器只注入CmsContext、IdentityContext、TenantContext三个依赖不涉及发布权限故无需AccessControl。其核心差异点增量清洗mapAndCleanUpdatedInputData(model, rawInput?.values)只保留输入中的字段随后与原值合并mergedValues { ...originalEntry.values, ...cleanedValues }引用映射不校验referenceFieldsMapping传validateEntries: falsemeta 合并createEntryMeta(metaInput, originalEntry.meta)用lodash/merge合并后再经removeNullValuesremoveUndefinedValues来自webiny/utils剔除空值状态归一transformEntryStatus()只在[draft, published, unpublished]白名单内接受原状态其余一律归一为draft时间字段revisionCreatedOn、firstPublishedOn等沿用原值fallback 取originalEntry.xxxsavedOn/modifiedOn及对应By刷新为当前时间/身份目录更新仅当rawInput.wbyAco_location?.folderId存在时才覆盖entry.locationlive直接沿用originalEntry.live。4.3CreateEntryRevisionFromDataFactoryImpl版本递增的核心该工厂create()接收sourceId、model、rawInput、originalEntry、latestStorageEntry、options六个参数是六个工厂中签名最复杂的一个构造器注入CmsContext、IdentityContext、TenantContext、AccessControl四个依赖。其关键点取值initialValues { ...originalEntry.values, ...mapAndCleanUpdatedInputData(model, rawInput.values) }即原版本值 输入增量版本号递增increaseEntryIdVersion(id)用parseIdentifier(id)解析{entryId, version}版本无则抛WRONG_ID否则version 1后重新createIdentifier合成新id。递增的基准是latestStorageEntry.id ?? sourceId——取最新存储版本而非当前版本防止并发下版本号回退发布元字段的继承策略revisionFirstPublishedOn/By等 revision 级字段默认以null起步仅当新状态为STATUS_PUBLISHED时刷新为当前时间/身份而 entry 级firstPublishedOn/By默认继承latestStorageEntry的值lastPublishedOn/By在发布时更新为当前值其余权限检查pw: p/pw: u与locked计算逻辑与创建工厂一致live沿用originalEntry.live。4.4 三个轻量工厂Publish / Unpublish / Republish这三个工厂是状态转换型不涉及模型字段清洗实现明显更短CreatePublishEntryDataFactory构造器仅注入CmsContextIdentityContext。先对originalEntry.values做一次校验validateModelEntryDataOrThrow然后生成一条status: STATUS_PUBLISHED、locked: true的新条目entry 级createdOn/By继承latestEntry保持首次创建信息firstPublishedOn/By取latestEntry的既有值或当前值兜底lastPublishedOn/By、savedOn/By、modifiedOn/By与全部revision*刷新为当前live: { version: originalEntry.version }指向被发布的那一版。CreateUnpublishEntryDataFactory最轻量构造器只注入IdentityContext。create(originalEntry)生成status: STATUS_UNPUBLISHED的条目仅刷新savedOn/modifiedOn/savedBy/modifiedBy及对应revisionSavedOn/ModifiedOn/By并置live: null——取消发布即从线上摘除。CreateRepublishEntryDataFactory构造器注入CmsContextIdentityContext。create(model, originalEntry)对原值重新跑一次referenceFieldsMappingvalidateEntries: false产出status: STATUS_PUBLISHED的条目firstPublishedOn/By沿用原值保留首次发布时间否则以当前兜底lastPublishedOn/By刷新为当前live: { version: originalEntry.version }。这三个工厂的注册 token 分别是CreatePublishEntryDataFactory、CreateUnpublishEntryDataFactory、CreateRepublishEntryDataFactory对应的dependencies数组也分别收敛为[CmsContext, IdentityContext]、[IdentityContext]、[CmsContext, IdentityContext]——依赖面越轻越是内联重构的直接收益。五、核心改造二六个 UseCase 注入工厂 tokenTask 8–13这是重构的消费侧改造。改造前的 UseCase 直接调用crud/下导出的函数并为此在构造函数里背上了CmsContext、IdentityContext、TenantContext等 Context 依赖改造后它们只依赖各工厂的Interfacetoken。当前仓库中的 CreateEntryUseCase.ts 已按计划落地可以对照验证。5.1CreateEntryUseCaseImplpublic constructor( private eventPublisher: EventPublisher.Interface, private repository: CreateEntryRepository.Interface, private accessControl: AccessControl.Interface, private createEntryDataFactory: CreateEntryDataFactory.Interface ) {}execute()的执行流变为四段先canAccessEntry({ model, rwd: w })做模型级写权限检查失败返回EntryNotAuthorizedError.fromModel(model)再调this.createEntryDataFactory.create(model, rawInput, options)拿到{ entry, input }随后用entry做条目级写权限二次检查通过后发布EntryBeforeCreateEvent→repository.execute(model, entry)落库 → 发布EntryAfterCreateEvent。异常处理中专门识别error.code VALIDATION_FAILED并转换为EntryValidationError。最后同样以createImplementation注册dependencies为[EventPublisher, CreateEntryRepository, AccessControl, CreateEntryDataFactory]。5.2UpdateEntryUseCaseImpl注入EventPublisher、UpdateEntryRepository、AccessControl、GetRevisionByIdUseCase、UpdateEntryDataFactory五个依赖。执行流模型级写权限 →getRevisionByIdUseCase.execute(model, id)取原条目 →若originalEntry.locked直接返回EntryLockedError锁定条目不可更新→updateEntryDataFactory.create(model, rawInput, originalEntry, options, metaInput)→ 条目级权限复查 →EntryBeforeUpdateEvent→ 仓库落库 →EntryAfterUpdateEvent。5.3CreateEntryRevisionFromUseCaseImpl注入CreateEntryRevisionFromRepository、AccessControl、GetRevisionByIdUseCase、GetLatestRevisionByEntryIdUseCase、EventPublisher、CreateEntryRevisionFromDataFactory。执行流parseIdentifier(sourceId)抽出entryId→ 取指定 revisionoriginalEntry→ 取该 entry 的最新 revisionlatestStorageEntry→ 调工厂create(sourceId, model, rawInput, originalEntry, latestStorageEntry, options)→ 权限复查 → 发布EntryRevisionBeforeCreateEvent→ 落库 →EntryRevisionAfterCreateEvent落库失败或异常时发布EntryRevisionCreateErrorEvent并返回失败。5.4PublishEntryUseCaseImpl注入PublishEntryRepository、AccessControl、GetRevisionByIdUseCase、GetLatestRevisionByEntryIdUseCase、EventPublisher、CreatePublishEntryDataFactory。执行流canAccessEntry({ model, pw: p })→ 取 revision找不到返回EntryNotFoundError→ 条目级发布权限复查 → 取最新 revision → 调工厂create(model, originalEntry, latestEntry)→EntryBeforePublishEvent→ 落库 →EntryAfterPublishEvent失败发EntryPublishErrorEvent。5.5UnpublishEntryUseCaseImpl注入EventPublisher、UnpublishEntryRepository、AccessControl、GetPublishedRevisionByEntryIdUseCase、CreateUnpublishEntryDataFactory。两个值得注意的业务规则通过GetPublishedRevisionByEntryIdUseCase取已发布的 revision且要求originalEntry.id id即目标 revision 本身就是线上版本否则返回EntryValidationError(Entry is not published!)随后调createUnpublishEntryDataFactory.create(originalEntry)发布EntryBeforeUnpublishEvent/EntryAfterUnpublishEvent失败发EntryUnpublishErrorEvent。5.6RepublishEntryUseCaseImpl注入RepublishEntryRepository、AccessControl、GetRevisionByIdUseCase、EventPublisher、CreateRepublishEntryDataFactory。权限检查同时要求rwd: w与pw: p取 revision 后调createRepublishEntryDataFactory.create(model, originalEntry)走EntryBeforeRepublishEvent/ 落库 /EntryAfterRepublishEvent失败发EntryRepublishErrorEvent。5.7 裁剪收益总结对比六份 UseCase 的前后实现重构的最大收益是依赖面的收敛原先为喂给旧函数而注入的CmsContext、IdentityContext、TenantContext等粗粒度 Context 从 UseCase 构造函数中全部消失取而代之的是细粒度的工厂Interfacetoken。UseCase 的职责因此变得更纯粹——编排权限、事件与仓储不再关心条目的数据装配细节。六、仅改 import 的ValidateEntryUseCaseTask 14第六节之外的第七个消费者ValidateEntryUseCase不需要注入任何工厂 token——它只用到mapAndCleanUpdatedInputData这一个共享函数。因此改造仅一行 import 路径替换- import { mapAndCleanUpdatedInputData } from ~/crud/contentEntry/entryDataFactories/index.js; import { mapAndCleanUpdatedInputData } from ~/features/contentEntry/entryDataFactories/mapAndCleanUpdatedInputData.js;这一任务单独列出恰好印证了共享文件必须放在features/contentEntry/entryDataFactories/父级的理由它同时被工厂实现与独立 UseCase 消费放在单个工厂目录内会造成跨目录引用。七、删除旧目录与收尾验证Task 15–167.1 删除死代码所有消费者迁移完成后旧目录成为纯死代码rm -rf packages/api-headless-cms/src/crud/contentEntry/entryDataFactories从当前仓库状态看crud/contentEntry/下已不再存在entryDataFactories/子目录只有 entryDataValidation.ts、referenceFieldsMapping.ts、references/与searchableFields.ts等仍被引用的底层模块——这验证了整条重构链路的闭环。7.2 类型检查与提交计划文档给出了标准的收尾序列# 1. 包级类型检查 yarn check -p webiny/api-headless-cms 21 | tail -30 # 2. 提交前完整校验任何一步修改了文件都要从 git add . 重新跑 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 . # 3. 提交 git commit -m refactor(api-headless-cms): inline entry data factory logic, wire use cases to inject factories其中yarn check -p利用 Webiny 的 monorepo 工具链做单包类型检查generateTsConfigsInPackages.jsscripts为各包重新生成 tsconfigyarn adio、yarn format、yarn lint、yarn webiny sync-dependencies分别承担自动修复/格式化/静态检查/依赖同步。若有步骤改动文件需回到git add .重跑保证提交内容完整一致。八、底层机制webiny/feature/api的三角色协作要真正理解这次重构需要看清它依赖的三个基础 API位于 packages/feature/src/apicreateAbstraction——定义 token。以CreateEntryDataFactory为例abstractions.tscreateAbstractionICreateEntryDataFactory(Cms/Entry/CreateEntryDataFactory)生成一个带命名空间的 token同时用 TypeScript namespace 导出Interface/Response等类型别名供消费方引用CreateEntryDataFactory.InterfacecreateImplementation——把Impl类绑定到 token并通过dependencies: [CmsContext, IdentityContext, ...]声明构造器的依赖顺序由 DI 容器完成装配createFeature——把实现注册进容器的生命周期。每个工厂目录下都有配套的feature.ts例如 CreateEntryDataFactory/feature.ts内部container.register(CreateEntryDataFactory).inSingletonScope()六个工厂的 feature 再由 EntryDataFactoriesFeature.ts 统一聚合注册对外只暴露一个EntryDataFactoriesFeature入口。正是因为abstractions.tstoken 与接口、feature.ts注册、index.tsre-export三者在本次重构中保持不变计划才能把改动精确收敛到实现文件 UseCase两层——这也是整个重构风险可控的结构性前提。九、重构要点速查共享文件放父级statuses.ts、system.ts、mapAndCleanUpdatedInputData.ts位于features/contentEntry/entryDataFactories/根被多个工厂及ValidateEntryUseCase复用内容与旧crud/版本完全一致仅路径变化辅助函数模块化仅被单个工厂使用的私有辅助函数以模块作用域函数内联到该工厂文件convertDefaultValue、cleanInputValues、createEntryId、increaseEntryIdVersion、transformEntryStatus等Context 收敛六个 UseCase 裁掉了只为传递旧函数而注入的CmsContext/IdentityContext/TenantContext统一改为注入工厂 token六个工厂的依赖面也各不相同[CmsContext, IdentityContext, TenantContext, AccessControl]→ 轻至[IdentityContext]接口零改动所有abstractions.ts、feature.ts、index.ts在本次重构中不变改动面被严格限制在实现与消费两侧删除与验证全部消费者迁移完成后整目录删除crud/contentEntry/entryDataFactories/并以yarn check -p webiny/api-headless-cms、yarn lint等命令完成类型与质量验证。如果你想在 Webiny 仓库中亲手验证这套改造的落地效果可以直接对照上述文件路径查看当前实现六个工厂的实现文件、EntryDataFactoriesFeature.ts的聚合注册、以及CreateEntryUseCase.ts等六个 UseCase 的createImplementation依赖数组——它们共同构成了逻辑内联 工厂 token 注入这一 DI 重构模式的完整样板。赞分享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 CMS 内容条目模块重构实践从 ApolloClient 到 DI MobX Presenter 架构Webiny CMS 内容条目模块重构实践从 ApolloClient 到 DI MobX Presenter 架构 导读 本文基于仓库 ai conteCMS后端前端Webiny Website Builder 页面特性 DI 容器化重构指南从 new 工厂到 webiny/feature/admin 依赖注入架构Webiny Website Builder 页面特性 DI 容器化重构指南从 new 工厂到 webiny/feature/admin 依赖注入架构 导读CMS后端前端CMS 内容条目模块 DI 重构指南以 FormModel 与 WebinySdk 驱动的 Headless CMS 条目列表/表单重实现CMS 内容条目模块 DI 重构指南以 FormModel 与 WebinySdk 驱动的 Headless CMS 条目列表/表单重实现 本文是 WebinCMS后端前端上一篇Omni-Notes安全功能解析密码保护和隐私设置的完整指南下一篇探索Twitter Lite轻量级Twitter API客户端库创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

智能体评测卷·终章|判卷的终局:评测即治理(全系列收官) 2026/9/28 5:03:03

智能体评测卷·终章|判卷的终局:评测即治理(全系列收官)

智能体评测卷终章|判卷的终局:评测即治理(全系列收官) 专栏:Valhalla‑Matrix 智能体评测卷(第9期 终章) 作者:Valhalla Matrix 治理实验室 原创声明:本文为原创技术博…

阅读更多 →
Spring 4核心功能:Java配置取代XML 2026/9/28 5:03:03

Spring 4核心功能:Java配置取代XML

一 1 介绍它是项目里面的一个子部分, 在 3.0 版本开始的时候, 从一个独立的项目合并到中去了, 并且在 4 之后变成了核心功能。它提供了一套用纯 Java 语言来配置 IoC 容器的方法, 这种方法有助于让人不去使用那种传统的 XML配置文件的方式。这么做的好处主要可以从下面这几个方…

阅读更多 →
共享内存实战:性能提升百倍的秘密 2026/9/28 5:03:03

共享内存实战:性能提升百倍的秘密

在最近的这段时间里, 我发布了一个宏大的愿望, 这个愿望的意图是想去构建一套专门用于对企业金融展开研究的框架。后来我把相关的进度情况拉出来查看以后, 才发现该框架的版本已经更新到了三点八这一阶段, 于是我就在这个过程中发现了在三八点八的这个新版本里面新出现的一个模…

阅读更多 →
systemd入门教程:unit、service、target、systemctl详解 2026/9/28 5:02:57

systemd入门教程:unit、service、target、systemctl详解

现在主流 Linux 发行版(Ubuntu 16.04 以后、CentOS 7 以后、Rocky、Debian)的 init 系统基本都是 systemd。开机启动哪些服务、服务崩了怎么重启、看日志去哪看,全靠它。这篇把 systemd 的核心概念 unit、service、target 和主命令 systemctl…

阅读更多 →
用路由侠做网站哪家好?防黑挂马实战指南 2026/9/28 5:02:56

用路由侠做网站哪家好?防黑挂马实战指南

用路由侠做网站哪家好?防黑挂马实战指南 网站被黑挂马,后台进不去,首页全是乱码广告,这种噩梦谁没经历过?别慌,先别急着删库,检查服务器日志和文件改动时间。很多人一上来就问建站公司哪家好,其实核心在于你用的技术栈够不够硬,安全防护做得够不够细…

阅读更多 →
小游戏修完一个问题后:怎样记录还没测过的部分 2026/9/28 5:02:56

小游戏修完一个问题后:怎样记录还没测过的部分

大家好,我是 SiKi老师。修完“暂停后角色不能动”,沿原步骤检查没有再出现,接下来能写“这个包测试通过”吗?我建议先停一下:这条问题的复查结果,与整份试玩包已经检查的范围,是两件事。 本文适…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉