后端认证鉴权密钥管理密码学【免费下载链接】openbaoOpenBao is a software solution to manage, store, and distribute sensitive data including secrets, certificates, and keys.项目地址https://gitcode.com/GitHub_Trending/op/openbao点击查看免费下载导读OpenBao 的前端ui/app基于 Ember 构建随着依赖升级如 ember-basic-dropdown 2.x、FlightIcon 图标体系与代码规范演进手工修改数百个.hbs模板与.js组件不仅低效还极易遗漏或引入格式错误。本文以 ui/scripts/codemods/README.md 为纲领系统讲解 OpenBao UI 目录下的 codemod 工具链如何使用 ember-template-recast 批量改写 Handlebars 模板、如何用 jscodeshift 改造 JavaScript 组件并结合仓库内 7 个现成 transform 的源码逐段剖析其原理。读完本文你将掌握模板与 JS 两类 codemod 的编写范式、执行与回滚流程并能在自己的 Ember 项目中直接复用这些脚本。一、什么是 Codemod从「逐个手改」到「批量改写」Codemodcode modification是一种用代码改代码的重构方式编写一段转换逻辑transform借助解析器把源码解析成 AST抽象语法树遍历、修改节点后再重新生成源码。OpenBao UI 仓库把这类脚本统一放在 ui/scripts/codemods 目录下按处理对象分为两类类别处理对象核心工具典型脚本模板 Codemod.hbsHandlebars 模板ember-template-recastno-quoteless-attributes.js、dropdown-transform.js、icon-transform.js、linkto-with-on-modifier.js、transform-deprecated-args.jsJS Codemod.js组件/模块jscodeshift Babel 解析器inject-service.js配合 jscodeshift-babylon-parser.js两个工具的定位不同ember-template-recast专门处理 Handlebars 模板语法在改写 AST 的同时尽可能保留原模板的空白与格式jscodeshift是 Facebook 出品的通用 JavaScript 重构工具负责类定义、装饰器、导入语句等 JS 层面的结构性改动。二、模板 Codemod 的运行方式与验证流程README 给出的执行方式非常简洁——在 UI 目录下用npx直接调用# 从仓库根目录进入 UI 目录 cd ui # 对 ui 目录下所有 .hbs 文件运行指定 transform npx ember-template-recast **/*.hbs -t ./path/to/transform-file.js其中**/*.hbs是 glob 匹配模式会覆盖ui/app下的所有模板以及ui/lib下各 addonaddon 路径见 ui/package.json 的ember-addon.paths配置包括lib/core、lib/css、lib/kubernetes、lib/open-api-explorer、lib/pki、lib/service-worker-authenticated-download等-t指定要执行的 transform 脚本路径。以 README 中的示例命令为例npx ember-template-recast **/*.hbs -t ./scripts/codemods/no-quoteless-attributes.js运行结束后终端会输出统计信息处理的文件总数files processed以及 changed已修改、unchanged未修改、skipped跳过、errored出错的文件数。这是快速判断本次重构影响面的第一手依据。README 特别强调了两条工程化建议务必人工验证输出validate the output to ensure that the intended transforms have taken place。codemod 只保证语法正确不保证语义符合预期自动改写后应抽查若干模板或跑一遍ui/package.json中的 lint 脚本如lint:hbs、lint:hbs:fix与测试来兜底。出错就回滚重来。如果某些文件转换结果不理想直接用 git 还原改动git checkout ./git restore调整 transform 后再执行。这种改-验-回滚-再改的迭代闭环正是 codemod 工作流相对手工修改的最大优势——失败成本极低。三、逐个拆解 5 个模板 Transform1. no-quoteless-attributes.js为无引号属性补全 Mustache 语法no-quoteless-attributes.js 解决的是 Handlebars 模板中的一个历史遗留写法布尔属性/参数不带引号如data-test-footrue、isVisibletrue这在模板 lint 中属于不推荐写法。脚本将其改写为规范的 mustache 表达式data-test-footrue → >module.exports (env) { const { builders } env.syntax; return { ElementNode({ attributes }) { let i 0; while (i attributes.length) { const { type, chars } attributes[i].value; if (type TextNode chars !attributes[i].quoteType) { attributes[i].value builders.mustache(builders.path(attributes[i].value.chars)); } i; } }, }; };要点解读transform 导出的是一个函数接收env参数由 ember-template-recast 注入从env.syntax.builders取得节点构造器返回对象中声明要监听的 AST 节点类型ElementNode在回调里拿到该节点的attributes数组判断条件type TextNode chars !attributes[i].quoteType属性值是无引号的纯文本quoteType为空且非空字符串才需要转换用builders.mustache(builders.path(chars))把文本值包成{{...}}mustache 节点原地替换attributes[i].value。data-test-*是 OpenBao UI 测试选择器体系ember-test-selectors见 ui/package.json 依赖的一部分这类模板改动能让测试钩子属性在模板 lint 与渲染中表现一致。2. dropdown-transform.js适配 ember-basic-dropdown 2.x 的组件重命名dropdown-transform.js 处理的是一个真实的上游破坏性变更ember-basic-dropdown 2.x 中yield 出来的子组件名称改为大写开头同时 splattributes 机制被引入class需要以 HTML 属性而非命名参数的形式传递。OpenBao UI 中大量使用BasicDropdown与ToolTip组件例如 basic-dropdown 目录下的封装升级时语法变化点很多。脚本的核心逻辑module.exports () { return { ElementNode(node) { if ([BasicDropdown, ToolTip].includes(node.tag)) { node.children.forEach((child) { if (child.type ElementNode child.tag.match(/\.(content|trigger)/gi)) { // 1. 把 .content / .trigger 中的首字母大写 const { tag } child; const char tag.charAt(tag.indexOf(.) 1); child.tag tag.replace(char, char.toUpperCase()); // 2. 处理 class 与 tagName 参数 child.attributes.forEach((attr) { if (attr.name.includes(class)) { if (child.tag.includes(Content)) { attr.name defaultClass; // Content 组件不支持 splattributes } else if (attr.name class) { attr.name class; // Trigger 组件改为原生 class 属性 } } else if (attr.name.includes(tagName)) { attr.name htmlTag; // tagName 更名 htmlTag } }); } }); } }, }; };逐条翻译它的三个改写规则场景改写前改写后原因yield 组件名大小写BasicDropdown.content/BasicDropdown.triggerBasicDropdown.Content/BasicDropdown.Trigger2.x 起 yield 组件名首字母大写Trigger 的 class 传递class...class...Trigger 支持 splattributesclass 走原生属性Content 的 class 传递class...defaultClass...Content 不支持 splattributes需用命名参数tagName 参数tagNameulhtmlTagul2.x 中参数更名为 htmlTag这个 transform 说明了 codemod 的典型价值当上游依赖升级引入命名与传参约定变化时机械性的全局替换最容易遗漏和出错而脚本可以精确地按父节点标签 子节点标签模式锁定目标。3. icon-transform.js迁移到 FlightIcon 图标 APIicon-transform.js 服务于 OpenBao UI 的图标体系升级——从自有的Icon组件迁移到hashicorp/flight-icons依赖见 ui/package.json。它处理的典型语法变化包括sizeClass参数映射为size、尺寸字母值s/m/l/xlm/xl/xxl换算为像素值其中s/m/l是组件默认尺寸16px可整体删除。脚本内有一段非常实用的工程注释ember-template-recast 在删除多行组件中间某个属性时存在格式 bug——删除的属性若不在首位其下一行的属性会被挤到上一行如class{{foo}}可能变成class{{foo}}。因此脚本实现了preserveFormatting辅助函数在删除属性前先把后面所有属性的loc源码位置信息逐个前移一位让 recast 认为它们还待在原处从而保住换行格式const preserveFormatting (attributes, removeIndex) { if (removeIndex 0) { for (let i attributes.length - 1; i removeIndex; i--) { attributes[i].loc attributes[i - 1].loc; } } };尺寸换算逻辑transformSize也很直观若sizeClass或size的值落在hsSizes [s, m, l, xlm, xl, xxl]内s / m / l→ 对应 16px 即组件默认值直接删除该属性删除前先 preserveFormattingxlm / xl / xxl→ 写入24FlightIcon 支持的另一档尺寸若原属性是sizeClass则顺手改名为size。这段源码同时是写 codemod 前必须了解底层工具缺陷的绝佳案例格式保真是模板重构中不可妥协的目标否则一次批量执行可能让整个 UI 的 diff 变得不可审查。4. transform-deprecated-args.js清理内置组件的废弃参数transform-deprecated-args.js 针对 Ember 内置组件Input/Textarea的参数化变更这些组件的id、name、class、placeholder等命名参数应改为 HTML 属性。Input idfoo / → Input idfoo /脚本内置了一个部分清单deprecatedArgs包含id、name、autocomplete、spellcheck、class、placeholder、wrap、rows、readonly、step、min、pattern等注释说明完整清单来自 ember-template-lint 的no-unknown-arguments-for-builtin-components规则。处理对象是Textarea、Input、LinkTo、ToolbarSecretLink、SecretLink五个标签遍历属性时把命中的x去掉前缀。其中有两个值得注意的边界处理disabled的例外LinkTo使用disabled作为命名参数而非属性所以对LinkTo/SecretLink/ToolbarSecretLink后者是前者的包装见 secret-link.js转换方向是反的——把disabled属性改回disableddisabled的豁免当处理LinkTo系组件时disabled不在待移除的deprecatedArgs匹配范围内避免误删。这个脚本提醒我们codemod 的规则往往不是一刀切同一个参数在不同组件里的语义可能完全不同编写时必须显式列出例外。5. linkto-with-on-modifier.js只读扫描定位目标文件linkto-with-on-modifier.js 是一个非破坏性的探测脚本它不修改任何文件只在发现LinkTo元素使用{{on}}修饰符时把对应文件路径打印到终端ElementNode(node) { if (node.tag LinkTo) { if (!fileAlerted) { const usesModifier node.modifiers.find((modifier) modifier.path.original on); if (usesModifier) { console.log(env.filePath); // 只输出文件路径不改动源码 fileAlerted true; // 同一文件只提示一次 } } } }这类审计型 codemod 在大型重构中非常实用先用只读脚本摸清哪些文件受影响、评估工作量再决定是否编写写操作的 transform。fileAlerted标志保证同一文件只打印一次避免日志刷屏。四、JS Codemodinject-service.js 与自定义 Babel 解析器1. 为什么需要自定义解析器jscodeshift-babylon-parser.js 为 jscodeshift 提供定制的 Babel 解析器。OpenBao UI 的 JS 组件大量使用Ember 装饰器语法如service store见 secret-link.js 中的import { service } from ember/service标准的 Babel 解析配置不认识这类语法因此解析器配置中启用了decorators-legacy插件允许装饰器位于 export 语句之前并配套启用了 flow、jsx、optionalChaining、nullishCoalescingOperator 等一整套现代语法插件const parserConfig { sourceType: module, allowImportExportEverywhere: true, allowReturnOutsideFunction: true, startLine: 1, tokens: true, plugins: [ [flow, { all: true }], flowComments, jsx, asyncGenerators, bigInt, classProperties, classPrivateProperties, classPrivateMethods, decorators-legacy, // allows decorator to come before export statement doExpressions, dynamicImport, exportDefaultFrom, exportNamespaceFrom, functionBind, functionSent, importMeta, logicalAssignment, nullishCoalescingOperator, numericSeparator, objectRestSpread, optionalCatchBinding, optionalChaining, [pipelineOperator, { proposal: minimal }], throwExpressions, ], };2. inject-service.js自动注入 Ember Serviceinject-service.js 是仓库中唯一一个 JS 级 transform解决的是组件里用了this.store或任意 service却没有显式注入的问题。它的用法文件头部注释为npx jscodeshift -t ./scripts/codemods/inject-service.js ./app/**/*.js --servicestore--servicestore是必传参数指定要注入的 service 名加-d则为 dry run只输出 diff 不实际写入。脚本逻辑分两大分支分支 AClass 组件class X extends Componentj(source).find(j.ClassBody).filter(filterForService)找出类体过滤出其中出现this.store这种 MemberExpression 的类object: ThisExpression, property: { name: service }再在这些类体中过滤出尚未注入该 service 的没有service store形式的 ClassProperty且该属性带service装饰器对缺失的类用j.classProperty(j.identifier(service service), null)构造注入属性并unshift到类体最前。分支 B.extend({...})经典写法找CallExpression且 callee 是.extend的调用过滤出访问了该 service 的对象表达式同时通过callee.property?.name extend排除掉actions: { ... }这类非 extend 主体内的误命中对缺失的构造store: service()对象属性并unshift到 properties 首位注意这里使用了recastOptionsquote: single、trailingComma: true、wrapColumn: 110等来控制重写后的格式。兜底逻辑补 import。只要任一分支发生了注入didInjectService为 true就检查文件是否已从ember/service导入inject没有则生成import { inject as service } from ember/service;插入到文件最后一个 import 声明之后const injectionImport j.importDeclaration( [j.importSpecifier(j.identifier(inject), j.identifier(service))], j.literal(ember/service) ); const imports j(source).find(j.ImportDeclaration); source imports.at(imports.length - 1).insertAfter(injectionImport).toSource(recastOptions);inject as service的别名导入正是 Ember 中service装饰器的来源import { inject as service } from ember/service定义了service配合service store完成属性注入。这个 transform 完整覆盖了检测用法 → 注入声明 → 补充 import三个环节是理解 jscodeshift 工作流的最佳范本。五、实战工作流从识别到批量迁移综合 README 与各 transform 源码OpenBao UI 的 codemod 工作流可归纳为以下四步探测只读先运行 linkto-with-on-modifier.js 这类只读脚本列出所有命中目标的文件评估影响面试运行dry run对 JS transform 加-d参数先看 diff对模板 transform 可先限定到子目录如npx ember-template-recast ./templates -t ./scripts/codemods/icon-transform.js此用法见 icon-transform.js 头注释小范围验证正式执行在ui目录下运行npx ember-template-recast **/*.hbs -t ./transform.js核对终端输出的 changed / unchanged / skipped / errored 统计校验与回滚抽查改动文件、运行npm run lint:hbs/npm run lint:js脚本见 ui/package.json发现异常就用 git 还原README 明确建议 revert the changes via git, tweak the codemod and run again修正 transform 后重跑。值得强调的是上述脚本全部位于仓库 ui/scripts/codemods无需额外安装全局依赖——npx ember-template-recast会按需拉取工具transform 文件本身只是普通 Node 模块。编写自己的模板 transform 时只需照抄no-quoteless-attributes.js的骨架module.exports (env) ({ ElementNode(node) { ... } })结合env.syntax.builders即可在 OpenBao UI 及任何 Ember 项目中直接落地。六、写在最后codemod 在大型 UI 工程中的定位从 README 的简短说明延伸开来看这 7 个脚本构成了 OpenBao UI 依赖升级与规范演进的可审计基础设施它们把散落在数百个模板与组件中的机械性改动收敛为可重复执行、可 diff 审查、可一键回滚的确定性程序。无论是ember-basic-dropdown的组件重命名、FlightIcon的尺寸迁移还是Input/Textarea的参数规范化背后都是先写脚本、再跑全量、最后 lint 兜底的统一方法论。理解这些脚本的写法不仅能帮你高效维护 OpenBao UI也能为其他 Ember 项目的批量重构提供一套可直接借鉴的模板。赞分享后端认证鉴权密钥管理密码学【免费下载链接】openbaoOpenBao is a software solution to manage, store, and distribute sensitive data including secrets, certificates, and keys.项目地址https://gitcode.com/GitHub_Trending/op/openbao点击查看免费下载相关推荐jscodeshift 实战指南用 Codemod 自动化重构 JavaScript 与 TypeScript 代码jscodeshift 实战指南用 Codemod 自动化重构 JavaScript 与 TypeScript 代码 jscodeshift 是一个专门用于在开发工具CLIPlane 的 jscodeshift 自动化重构指南Codemod 包 API 参考与实战解析Plane 的 jscodeshift 自动化重构指南Codemod 包 API 参考与实战解析 Plane 仓库内置了 packages/codemods项目管理后端前端研发协作需求管理3步搞定百万行代码重构jscodeshift实战指南3步搞定百万行代码重构jscodeshift实战指南 你还在手动修改数千个文件中的重复代码当项目规模达到百万行级别一个简单的API变更可能需要数天工时。j开发工具CLI上一篇字符串哈希冲突解决终极指南如何在codeforces-go中高效避免哈希碰撞下一篇FlexiViT模型迁移学习教程基于flexivit_small.1200ep_in1k快速构建自定义图像分类器创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
