ARTICLE DETAIL

资讯详情

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

Swagger Editor 中 ApiDOM 语言 Worker 的定制指南:配置 ApiDOM Context、动态/静态扩展与数据传递

Swagger Editor 中 ApiDOM 语言 Worker 的定制指南:配置 ApiDOM Context、动态/静态扩展与数据传递 API设计前端开发工具【免费下载链接】swagger-editorSwagger Editor项目地址https://gitcode.com/gh_mirrors/sw/swagger-editor点击查看免费下载导读editor-monaco-language-apidom是 Swagger Editor 基于 Monaco Editor 构建的语言服务插件它为编辑器内置了apidom语言在 Web Worker 中运行 ApiDOM Language Server为 OpenAPI 2 / OpenAPI 3.x 等规范提供校验Diagnostics、补全Completion、悬停Hover、文档链接、符号、定义跳转、语义高亮与反引用Dereference等能力。本文以官方文档 docs/customization/plug-points/editor-monaco-language-apidom.md 为骨架结合插件源码系统讲解三个实战主题如何通过apiDOMContext配置 Worker 的语言服务能力如何通过**动态运行时import()与静态打包器构建自定义入口**两种方式扩展apidom.worker以及如何借助createData向 Worker 传递任意结构化数据。读完本文你将能独立为 Swagger Editor 的 ApiDOM 语言服务定制校验、补全与日志行为并为 Worker 注入带鉴权的数据拉取等自定义能力。背景插件如何把 ApiDOM 语言服务搬进 Web Worker在 Swagger Editor 中Monaco 编辑器的语言能力由editor-monaco插件与editor-monaco-language-apidom插件共同提供。后者在 src/presets/monaco/index.js 中被MonacoPreset默认装载并在 src/App.tsx 中注册为EditorMonacoLanguageApiDOM。插件的工作链路大致如下插件工厂EditorMonacoLanguageApiDOMPlugin见 src/plugins/editor-monaco-language-apidom/index.js接收createData、useApiDOMSyntaxHighlighting等选项并在afterLoad阶段注册apidom语言见 after-load.jsapidom-mode.js中的setupMode创建WorkerManager并通过MonacoEnvironment.getWorker(ApiDOMWorker, languageId)获取 Worker见 WorkerManager.jsWorker 端由 apidom.worker.js 承载它基于monaco-editor的initialize约定初始化内部实例化ApiDOMWorker后者再调用swagger-api/apidom-ls的getLanguageService完成各类语言操作见 ApiDOMWorker.js。理解了这条链路就很容易明白想要定制语言服务行为本质上就是定制 Worker 的创建过程与上下文Context——这正是本文要解决的三个问题。一、配置 Worker 能力ApiDOM Context 配置对象1.1 默认配置长什么样apidom.worker通过一个ApiDOM Context 配置对象来接收语言服务的配置。文档给出的默认配置如下{ validatorProviders: [], completionProviders: [], performanceLogs: false, logLevel: apidomLS.LogLevel.WARN, completionContext: { maxNumberOfItems: 100, enableLSPFilter: false, }, }对照源码 src/plugins/editor-monaco-language-apidom/language/ApiDOMWorker.js该对象实际由ApiDOMWorker.defaultApiDOMContext静态属性定义且比文档展示的默认值更完整还包含两组对实际行为有影响的额外配置配置项默认值说明validatorProviders[]自定义校验器提供者列表用于扩展校验能力completionProviders[]自定义补全提供者列表用于扩展补全能力performanceLogsfalse是否输出性能日志logLevelapidomLS.LogLevel.WARN语言服务日志级别如ERROR/WARN等completionContext.maxNumberOfItems100单次补全返回的最大条目数completionContext.enableLSPFilterfalse是否启用 LSP 的“严格”单词过滤默认关闭使用 Monaco 模糊匹配validationContext.referenceValidationContinueOnErrortrue引用校验出错时是否继续校验validationContext.referenceValidationModeapidomLS.ReferenceValidationMode.APIDOM_INDIRECT_EXTERNAL引用校验模式间接外部引用referenceOptions.resolve.resolverOpts.cacheTTL60 * 1000外部引用解析结果缓存时长60 秒也就是说只要没有显式覆盖Worker 会以“WARN 级日志、单次最多 100 条补全、Monaco 模糊匹配、引用解析结果缓存 60 秒”的默认策略运行。这些默认值也印证了“配置对象会被深度合并”的设计初衷使用者只需覆盖关心的字段其余沿用默认。1.2 通过apiDOMContext覆盖默认配置要覆盖默认配置只需把apiDOMContext作为createData选项传给EditorMonacoLanguageApiDOM插件EditorMonacoLanguageApiDOM({ createData: { apiDOMContext: { completionContext: { enableLSPFilter: true, // 启用“严格”单词过滤替代默认的 Monaco 模糊匹配 }, }, }, });例如这里开启enableLSPFilter: true后补全候选词将按 LSP 的严格词过滤规则匹配而不是 Monaco 默认的模糊匹配——适合对补全精确度要求更高的场景。合并机制传入的 ApiDOM Context 配置对象会与默认对象通过 npm 的deep-extend包做深度合并而非浅层替换。源码中的证据在 ApiDOMWorker.jscreateLanguageService() { return apidomLS.getLanguageService( deepExtend({}, this.constructor.defaultApiDOMContext, this._createData.apiDOMContext) ); }deepExtend({}, 默认配置, 传入配置)意味着嵌套对象如completionContext、validationContext、referenceOptions是逐层合并的你只写completionContext.enableLSPFilter: true时maxNumberOfItems: 100依然保留。这也是官方推荐“只覆盖需要改的字段”的原因。注意 apidom.worker.js 中为兼容deep-extend对 CJS 全局Buffer的引用在 Worker 启动时做了globalThis.Buffer的 polyfill这也提醒我们该配置对象最终是在 Worker 线程中被消费的。1.3 配置对象的传递路径从源码可以梳理出apiDOMContext到达语言服务的完整调用链这对排查“配置为何不生效”很有帮助插件入口EditorMonacoLanguageApiDOMPlugin({ createData: { apiDOMContext } })afterLoadafter-load.js 把整个createData交给lazyMonacoContribution语言注册monaco.contribution.js 在onDidCreateEditor中把customApiDOMWorkerPath重命名为内部字段customWorkerPath并把apiDOMContext与其余data一并组装成 Worker 选项Worker 拉取WorkerManager.js 把{ ...data, languageId, apiDOMContext, customWorkerPath }通过worker.postMessage(createData)发给 Worker实例化ApiDOMWorker.js 构造函数把createData存入this._createData再由createLanguageService()深度合并后交给apidom-ls。二、扩展 Worker 能力动态扩展与静态扩展editor-monaco-language-apidom自带apidom.worker它基于 ApiDOM 能力实现。文档明确给出两种扩展方式动态扩展运行时与静态扩展构建期。两者修改的都是“Worker 类”区别在于何时、以何种方式替换默认的ApiDOMWorker。2.1 动态扩展运行时import()注入动态扩展发生在运行时官方建议只用于简单场景。第一步是把customApiDOMWorkerPath选项传给插件EditorMonacoLanguageApiDOM({ createData: { customApiDOMWorkerPath: https://example.com/index.js, }, });customApiDOMWorkerPath是扩展模块的 URL绝对或相对路径apidom.worker会在运行时通过动态import()加载它。加载进来的模块必须导出一个名为customApiDOMWorkerFactory的函数export const customApiDOMWorkerFactory (ApiDOMWorkerClass, toolbelt) { return ApiDOMWorkerClass; };该函数接收两个参数ApiDOMWorkerClass—— 当前 Worker 类默认是ApiDOMWorker若多次扩展则是前一次扩展的结果实现编辑器的语言能力toolbelt—— 一个包含各种库导出的工具对象方便你直接使用 ApiDOM 相关库。toolbelt里到底有什么从源码 ApiDOMWorker.js 可以看到makeCreate构造的toolbelt包含const toolbelt { apidomLS, // swagger-api/apidom-ls语言服务主库 apidomNSOpenAPI2, // OpenAPI 2.0 命名空间 apidomNSOpenAPI30, // OpenAPI 3.0 命名空间 vscodeLanguageServerTextDocument, // 文本文档抽象TextDocument deepExtend, // 深度合并工具 };下面是一个官方示例把语言服务的日志级别从默认的WARN提升到ERRORexport const customApiDOMWorkerFactory (ApiDOMWorkerClass, toolbelt) { const { apidomLS } toolbelt; class ApiDOMWorkerLogLevelErrorClass extends ApiDOMWorkerClass { static apiDOMContext { ...ApiDOMWorkerClass.apiDOMContext, logLevel: apidomLS.LogLevel.ERROR, }; } return ApiDOMWorkerLogLevelErrorClass; };这里用类继承的方式扩展新类通过static apiDOMContext覆盖父类的默认上下文从而只改日志级别、保留其他行为。传统 Worker 兼容非模块classicWorker 的使用者仍可使用globalThis.customApiDOMWorkerFactory赋值模式——当扩展模块没有命名导出时它作为兜底方案被支持。源码中的对应实现见 ApiDOMWorker.jsconst factory mod.customApiDOMWorkerFactory ?? globalThis.customApiDOMWorkerFactory; if (typeof factory ! function) { throw new TypeError(The module at ${path} does not export customApiDOMWorkerFactory); }动态扩展的底层机制从源码结构看customApiDOMWorkerPath在 monaco.contribution.js 被改名为customWorkerPath传给 WorkermakeCreate 在实例化前遍历createData.customWorkerPath支持传数组、依次应用多个扩展对每个路径执行import(path)取出工厂函数并调用factory(ApiDOMWorkerClass, toolbelt)得到新类非法条目会被console.warn跳过最终返回的是一个Proxy 包装的异步实例ApiDOMWorker.js所有方法调用都会先等待instancePromise完成再转发到真实实例上从而保证“扩展模块加载完成前调用不会丢失”。2.2 静态扩展用打包器构建自定义 Worker 入口静态扩展需要借助打包器Vite、webpack 等构建一个自定义的 Worker 入口文件。先在项目中新建一个 worker 入口比如my-custom-apidom.worker.jsimport { initialize, makeCreate, ApiDOMWorker } from swagger-editor/apidom.worker; class ApiDOMWorkerExtended extends ApiDOMWorker { // 扩展实现 } const create makeCreate(ApiDOMWorkerExtended); initialize((ctx, createData) create(ctx, createData)); export { initialize, create, makeCreate, ApiDOMWorkerExtended as ApiDOMWorker };这段代码做的事从swagger-editor/apidom.worker导入官方 Worker 的三个核心导出源码见 apidom.worker.js它本身也导出initialize、create、makeCreate、ApiDOMWorker定义ApiDOMWorkerExtended继承ApiDOMWorker写入扩展逻辑用makeCreate(ApiDOMWorkerExtended)生成实例工厂再交给initialize注册为 Worker 的启动回调——这正好对应makeCreate在 ApiDOMWorker.js 中的“先套扩展、再实例化”逻辑。随后把打包器指向这个文件作为apidom.worker的入口并配置MonacoEnvironment.getWorker让它服务于构建产物。文档给出的 webpack 示例entry: { app: ./index.js, apidom.worker: ./my-custom-apidom.worker.js, editor.worker: swagger-editor/editor.worker, }这样构建后apidom.worker将使用你的自定义类同时editor.worker仍使用 Monaco 内置 Worker。若用 Vite可以参考仓库自带的 vite/configs/worker-configs.esm.js其中apidomWorkerConfig以 src/plugins/editor-monaco-language-apidom/language/apidom.worker.js 为入口以formats: [es]、codeSplitting: false构建自包含的单文件 ESM Worker输出到dist/esm/apidom.worker.js——这就是“静态扩展”在仓库内部的标准做法。2.3 两种方式怎么选维度动态扩展静态扩展时机运行时import()加载构建期打包进 Worker 产物依赖打包器否URL 加载是Vite/webpack 等适用场景简单、低耦合的调整如改日志级别复杂、需要新依赖或较大逻辑的扩展扩展模块位置任意 URL需可被动态 import随构建产物分发官方建议仅用于简单用例复杂用例的推荐方式三、向 Web Worker 传递数据createData与_createData扩展 Worker 能力时经常需要向 Worker 传递额外数据。这些数据可以是任意兼容结构化克隆算法Structured Clone Algorithm的数据——包括普通对象、数组、字符串乃至ArrayBuffer等它们会随postMessage被安全复制进 Worker 线程。官方给出的场景是让apidom.worker按需从带鉴权的 REST 端点拉取数据。核心思路是把鉴权令牌作为createData传入插件扩展类通过this._createData读取。3.1 动态扩展中的数据传递插件配置EditorMonacoLanguageApiDOM({ createData: { authToken: c32d8b45-92fe-44f6-8b61-42c2107dfe87, customApiDOMWorkerPath: https://example.com/index.js, }, });扩展模块https://example.com/index.jsexport const customApiDOMWorkerFactory (ApiDOMWorkerClass, toolbelt) { const { apidomLS } toolbelt; class ApiDOMWorkerLogLevelErrorClass extends ApiDOMWorkerClass { static apiDOMContext { ...ApiDOMWorkerClass.apiDOMContext, logLevel: apidomLS.LogLevel.ERROR, }; async loadData() { // createData 作为插件选项传入后在 Worker 中通过 this._createData 读取 const { authToken } this._createData; return await fetch(https://example.com/data?authToken${authToken}); } } return ApiDOMWorkerLogLevelErrorClass; };注意示例同时演示了“传数据 改配置”的组合authToken进入_createDataapiDOMContext覆盖日志级别。3.2 静态扩展中的数据传递静态扩展中只要你继承了ApiDOMWorker类就自动拥有_createData公开属性import { initialize, makeCreate, ApiDOMWorker } from swagger-editor/apidom.worker; class ApiDOMWorkerExtended extends ApiDOMWorker { async loadData() { // createData 作为插件选项传入后在 Worker 中通过 this._createData 读取 const { authToken } this._createData; return await fetch(https://example.com/data?authToken${authToken}); } } const create makeCreate(ApiDOMWorkerExtended); initialize((ctx, createData) create(ctx, createData)); export { initialize, create, makeCreate, ApiDOMWorkerExtended as ApiDOMWorker };数据是如何到达_createData的从源码看链路非常清晰EditorMonacoLanguageApiDOM({ createData })中的createData在 after-load.js 被解构为{ createData {}, useApiDOMSyntaxHighlighting false }monaco.contribution.js 把apiDOMContext、customWorkerPath之外的其余字段作为data传递const { customApiDOMWorkerPath: customWorkerPath, apiDOMContext, ...data } createData;WorkerManager.js 组装createData { ...data, languageId, apiDOMContext, customWorkerPath }并postMessageApiDOMWorker.js 构造函数执行this._createData createData。于是authToken这类自定义字段便与apiDOMContext、languageId一起进入 Worker且在getJsonPointerPosition、doComplete、doValidation等所有语言服务方法见 ApiDOMWorker.js中都能间接使用。四、小结与源码索引总结一下三个核心结论配置apiDOMContext与默认上下文经deep-extend深度合并后注入语言服务只需覆盖关心的字段完整默认值含validationContext、referenceOptions.cacheTTL等见 ApiDOMWorker.js。扩展动态扩展靠customApiDOMWorkerPath 导出customApiDOMWorkerFactory运行时import()支持数组与globalThis兜底静态扩展靠打包器构建自定义入口makeCreateinitialize仓库的 Vite 构建示例见 vite/configs/worker-configs.esm.js。传数据任何符合结构化克隆算法的数据都能放进createData经postMessage到达 Worker 后统一暴露为this._createData。想要继续深入可以按以下路径阅读仓库源码插件入口src/plugins/editor-monaco-language-apidom/index.jsEditorMonacoLanguageApiDOM工厂Worker 启动src/plugins/editor-monaco-language-apidom/language/apidom.worker.jsWorker 核心类与扩展机制src/plugins/editor-monaco-language-apidom/language/ApiDOMWorker.jsdefaultApiDOMContext、makeCreate、toolbelt、Proxy 异步实例Worker 生命周期管理src/plugins/editor-monaco-language-apidom/language/WorkerManager.js空闲 2 分钟自动销毁、postMessage(createData)语言注册与 Provider 装配src/plugins/editor-monaco-language-apidom/language/monaco.contribution.js 与 src/plugins/editor-monaco-language-apidom/language/apidom-mode.js打包配置vite/configs/worker-configs.esm.js配合文档 docs/customization/plug-points/editor-monaco-language-apidom.md 与同目录 docs/customization/plug-points/README.md即可系统掌握 Swagger Editor 中 ApiDOM 语言服务的全部定制点。赞分享API设计前端开发工具【免费下载链接】swagger-editorSwagger Editor项目地址https://gitcode.com/gh_mirrors/sw/swagger-editor点击查看免费下载相关推荐突破静态限制ComfyUI-Impact-Pack动态API参数传递的创新实践突破静态限制ComfyUI Impact Pack动态API参数传递的创新实践 引言参数传递的痛点与解决方案 在现代AI工作流Workflow开发中尤AI 应用计算机视觉图像处理Atlas数据库加密静态数据与传输中数据安全配置Atlas数据库加密静态数据与传输中数据安全配置 在现代数据库管理中数据安全已成为核心需求。Atlas作为一款现代化的数据库模式管理工具提供了多种配置选项数据库开发工具数据工程Amazon Bedrock Workshop数据加密实践传输中与静态数据保护配置Amazon Bedrock Workshop数据加密实践传输中与静态数据保护配置 数据加密概述 在Amazon Bedrock Workshop中数据安全示例工程上一篇open-saas 企业级微服务架构深度解析从单体到模块化的演进之路下一篇gh_mirrors/tac/tachyon内存计算加速Spark作业性能提升3倍实践创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表