ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Strapi OpenAPI 生成器处理器扩展机制:Pre-Processor 与 Post-Processor 的实现与注册详解

Strapi OpenAPI 生成器处理器扩展机制:Pre-Processor 与 Post-Processor 的实现与注册详解 Strapi OpenAPI 生成器处理器扩展机制Pre-Processor 与 Post-Processor 的实现与注册详解【免费下载链接】strapi Strapi is the leading open-source headless CMS. It’s 100% JavaScript/TypeScript, fully customizable, and developer-first.项目地址: https://gitcode.com/GitHub_Trending/st/strapi本文围绕 Strapi 核心包strapi/openapi的生成生命周期讲解如何在文档组装前后挂载 pre-processor 与 post-processor。读完你可以掌握两类处理器的接口契约、注册工厂PreProcessorFactory/PostProcessorsFactory的接线位置以及现有实现ComponentsWriter如何把 Zod 内容 API 注册表写成components.schemas从而为 OpenAPI 文档生成管线贡献自己的横切处理逻辑。生成器执行顺序处理器在整个生命周期中的位置OpenAPI 生成器按固定顺序执行三类组件这一顺序在 OpenAPIGenerator.generate 中以链式调用的形式实现this // Init timers ._bootstrap(context) // Run registered pre-processors ._preProcess(context) // Run registered section assemblers ._assemble(context) // Run registered post-processors ._postProcess(context) // Clean up and set necessary properties ._finalize(context);即Pre-processors预处理—— 在文档组装前准备DocumentContextAssemblers组装器—— 构建 OpenAPI 文档的各个部分Post-processors后处理—— 在组装完成后对文档做最终处理。三类组件都以for...of循环按注册顺序逐个执行见 _preProcess 与 _postProcess每一步都带有debug(running pre-processor: %s...)之类的调试日志开启 debug 模式时可以看到每个处理器类的执行轨迹。两类处理器接收的都是完整的DocumentContext。从 类型定义 看DocumentContextData就是PartialOpenAPIV3_1.Document因此context.output.data是一份可增量修改的 OpenAPI 3.1 文档骨架。DocumentContext本身由 context/types.ts 中的泛型ContextT定义包含五个字段字段类型说明routesCore.Route[]经路由收集器筛选后的 Strapi 路由列表strapiCore.StrapiStrapi 应用实例可访问 schema 注册表等运行时能力timerTimer生成计时器用于统计耗时registriesContextRegistries由RegistriesFactory创建的一组注册表包括存放抽取组件 schema 的extractedComponentSchemasoutput{ data, stats }data为正在构建的文档stats.time记录startTime / endTime / elapsedTime处理器实例在 src/exports.ts 导出的generate()入口中统一装配const config { preProcessors: new PreProcessorFactory().createAll(), assemblers: new DocumentAssemblerFactory().createAll(), postProcessors: new PostProcessorsFactory().createAll(), };生成的config连同strapi实例、RouteCollector和DocumentContextFactory一起注入OpenAPIGenerator构造函数。因此新增处理器只需修改对应工厂的createAll()返回值无需触碰生成器本体。添加一个 Post-Processor当前代码库中唯一内置的后处理器是ComponentsWriter它在组装结束后从strapi.contentAPISchemaRegistry一个 Zod 注册表写出components.schemas而在路由转换阶段通过嵌套 Zod.meta({ id })收割到的 schema则通过context.registries.extractedComponentSchemas一并合并保证文档中的$ref都能解析到真实定义。1. 创建处理器类PostProcessor 接口 只有一个方法import type { DocumentContext } from ../types; import type { PostProcessor } from ./types; export class ExamplePostProcessor implements PostProcessor { postProcess(context: DocumentContext): void { // mutate context.output.data } }接口签名为postProcess(context: DocumentContext): void约定处理器直接就地修改context.output.data即文档对象本身而不是返回新文档。2. 在 PostProcessorsFactory 中注册在 post-processor/factory.ts 中追加实例即可。当前实现为export class PostProcessorsFactory { createAll(): PostProcessor[] { return [new ComponentsWriter()]; } }注册新的处理器后形如import { ComponentsWriter } from ./component-writer; import { ExamplePostProcessor } from ./example; export class PostProcessorsFactory { createAll(): PostProcessor[] { return [new ComponentsWriter(), new ExamplePostProcessor()]; } }数组顺序即执行顺序后处理器按注册先后依次运行因此依赖前一个处理器产出的处理器要排在后面。深入实现ComponentsWriter 做了什么ComponentsWriter.postProcess 的完整流程可作为编写后处理器的参照样板从context.strapi.contentAPISchemaRegistry.entries()读取内容 API 的 Zod schema逐个以{ id }元数据加入一个本地z.registry调用z.toJSONSchema(registry, { ...OPENAPI_SCHEMA_CONVERSION_OPTIONS, uri: toComponentsPath })把 Zod 定义转换为 OpenAPI schemauri选项toComponentsPath决定$ref的目标路径用liftZodSharedDefinitions(converted)提升 Zod 转换产生的共享定义将结果与output.data.components中已有内容做浅合并同时把context.registries.extractedComponentSchemas路由转换阶段收割的嵌套.meta({ id })schema放在前面展开再叠加注册表转换出的 schema确保引用与定义一致。值得注意的是它对空输出的防御isPlainObject(schemas) ? schemas : {}保证注册表为空时不会写出undefined。Pre-Processor 的工作方式Pre-processor 与 post-processor 完全对称接口定义在 pre-processor/types.tsexport interface PreProcessor { preProcess(context: DocumentContext): void; }注册方式相同在 PreProcessorFactory 的createAll()中返回实例。当前该工厂返回空数组return [];说明仓库中尚无内置的 pre-processor——这是一个明确的扩展位点适合放置“在组装开始前清理/注入上下文、预热注册表、标注路由元数据”一类的工作。选型原则优先用 Assembler处理器只用于横切逻辑:::tip 官方贡献指南的建议构建文档的各个 section 应优先使用 assemblerprocessor 只用于必须在完整组装通过前后执行的横切cross-cutting工作。:::从 assemblers/types.ts 可以看到assembler 家族按粒度分层Assembler.Document拿到DocumentContextAssembler.Path/PathItem/Operation分别拿到更窄的上下文。文档级 section如info、servers、security的构建都落在Assembler.Document层而操作级细节operationId、参数、响应、tag由更细的上下文组装器负责。只有当你的逻辑依赖整份文档的终态典型如ComponentsWriter需要等所有$ref都写入后才汇总 schema或者需要在组装前改变上下文时才应使用 pre/post-processor。小结与关键文件索引生成管线与执行顺序generator.ts_preProcess → _assemble → _postProcess工厂接线位置exports.tsPreProcessorFactory/PostProcessorsFactory在此实例化Post-processor 接口与工厂types.ts、factory.ts现成后处理器实现component-writer.tsPre-processor 接口与工厂types.ts、factory.ts当前为空注册表DocumentContext结构types.ts、context/types.tsAssembler 分层接口选型对比assemblers/types.ts本文档来源05-processors.md需要说明的前提strapi/openapi的generate()入口在源码注释中标记为experimental上述处理器机制基于当前仓库快照的实际代码接口签名如postProcess(context): void的 void 返回值约定可能随后续版本演进。【免费下载链接】strapi Strapi is the leading open-source headless CMS. It’s 100% JavaScript/TypeScript, fully customizable, and developer-first.项目地址: https://gitcode.com/GitHub_Trending/st/strapi创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表