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

资讯详情

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

Vendure CLI codemod 指南:用 `vendure codemod` 自动迁移 Dashboard 扩展代码

Vendure CLI codemod 指南:用 `vendure codemod` 自动迁移 Dashboard 扩展代码 Vendure CLI codemod 指南用vendure codemod自动迁移 Dashboard 扩展代码【免费下载链接】vendureOpen-source headless commerce platform built with TypeScript, NestJS, React, and GraphQL项目地址: https://gitcode.com/GitHub_Trending/ve/vendurevendure codemod是 Vendure CLIvendure/cli提供的自动化代码转换命令用于对 Vendure 项目执行一次性的批量代码改写。在本文场景中它最主要的用途是把基于 Radix UI / 旧版vendure-io/ui编写的 Dashboard 扩展自动迁移到 Base UI 模式vendure/dashboard统一入口。读完本文你将掌握vendure codemod的交互式与非交互式用法、dashboard-base-uitransform 的 5 类具体改写规则以及它在源码层的执行机制与可验证的测试依据。命令定位codemod 在 Vendure CLI 中的角色Vendure CLI 是驱动 Vendure 项目全生命周期的命令行工具二进制名为vendure包含dev、build、start、add、migrate、schema、doctor、codemod八个子命令。其中codemod的命令定义位于 command-declarations.ts描述为 “Run codemods to update your Vendure project code”运行 codemod 更新你的 Vendure 项目代码它接受两个可选位置参数transform要运行的 codemod 名称path要转换的文件或目录路径。与add、migrate、schema一样codemod属于“具备交互提示能力”的命令不带参数运行时会在终端弹出选择器而带显式参数运行时则走非交互路径这在自动化脚本和 Agent 场景中尤为重要详见下文。交互式与非交互式两种模式运行vendure codemod且不传transform参数时命令会进入交互模式终端会显示 Vendure Codemods标题并通过下拉选择器列出所有已注册的 codemod等待用户选择后执行源码见 codemod.ts。但交互模式有一个关键限制交互模式下不支持path参数只能从当前工作目录运行。这是因为clack/prompts的选择器会阻塞等待用户输入——对无人值守的 CI 流水线或 AI Agent 而言这会导致进程挂起。因此Agent 必须显式传入 transform 名称让命令以非交互方式运行。当交互模式检测到非交互环境时例如设置了VENDURE_CLI_NON_INTERACTIVEtrue会调用abortIfNonInteractive(vendure codemod, [vendure codemod dashboard-base-ui])快速失败并打印可参考的示例命令而不是干等终端输入。这一约定同时记录在 vendure-cli SKILL.md 的 “Critical rules for agents” 一节中。基本用法与参数说明vendure codemod transform [directory]两个参数的语义transform要运行的 codemod 名称。若传入的名称不在注册表中命令会报错Unknown codemod: name并列出所有可用的 codemod 后以非零状态码退出codemod.ts。directory可选的要转换的目标目录仅在非交互模式下支持默认是当前工作目录。传入后命令会先做严格校验resolveAndValidatePath见 codemod.ts使用path.resolve解析为绝对路径若路径不存在报错Path does not exist: resolved并退出若路径存在但不是目录报错Path is not a directory: resolved并退出。运行方式按项目 lockfile 选择 CLI 启动器vendure/cli通常是项目的 devDependency因此不应硬编码npx。请根据项目根目录的 lockfile 选择对应的运行器规则见 vendure-cli SKILL.md项目根目录 lockfile包管理器运行命令bun.lock/bun.lockbbunbunx vendure commandpnpm-lock.yamlpnpmpnpm exec vendure commandyarn.lockyarnyarn vendure commandpackage-lock.jsonnpmnpx vendure command未找到npm回退npx vendure command若vendure/cli是全局安装的可直接调用vendure command用vendure --help可列出全部命令。下文示例为便于阅读使用裸vendure前缀实际执行时请按上表补上对应运行器。可用 transforms 一览Transform描述dashboard-base-ui将 Dashboard 扩展从 Radix UI 迁移到 Base UI 模式目前 codemod 注册表中仅有一个 transformcodemod.ts并且是按需动态加载的dashboard-base-ui的run函数内部通过await import(./dashboard-ui/dashboard-ui-migration)懒加载迁移实现避免 CLI 启动时加载昂贵的 TSX 解析依赖。新增 codemod 时只需在CODEMODS注册表中添加一个条目注册表结构为const CODEMODS: Recordstring, { description: string; run: (targetPath?: string) Promisevoid } { dashboard-base-ui: { description: Migrate dashboard extensions from Radix UI to Base UI patterns, run: async (targetPath?: string) { /* ... */ }, }, };若 transform 名称未被识别可运行不带参数的vendure codemod查看交互式列表或直接查看上述注册表获取最新清单。基础示例# 对当前工作目录下的整个项目执行迁移 vendure codemod dashboard-base-ui # 仅对指定插件目录执行迁移非交互模式 vendure codemod dashboard-base-ui ./src/plugins/my-plugin第二条命令会把./src/plugins/my-plugin解析为绝对路径并校验其为存在的目录然后仅对该目录内的 TSX 文件执行迁移。深入dashboard-base-ui五类源码级转换dashboard-base-ui的实际执行入口是dashboardUiMigration函数dashboard-ui-migration.ts。它基于ts-morph构建 TypeScript/TSX 抽象语法树AST进行分析与改写——值得注意的实现细节是它刻意没有复用getTsMorphProject()因为后者会做 Vendure 特有的 monorepo/package.json 探测在外部项目中会失败codemod 只需要加载 TSX 文件因此自行创建Project。迁移会对每个.tsx文件依次执行 5 个 transform其顺序是精心设计的源码注释明确说明了依赖关系asChild → renderas-child-to-render.ts必须先于 import 合并执行确保asChild属性在 import 被重写前已经消失FormField → FormFieldWrapperform-components.ts移除旧表单组件的 import 并引入FormFieldWrapper同样必须先于 import 合并以便第三方的残留表单 import 能被后续步骤捕获Import 合并import-consolidation.ts把radix-ui/*、vendure-io/ui、base-ui/react等 import 统一改写为vendure/dashboard并重写命名空间成员访问点。放在 JSX 转换之后才能看到最终的 import 集合Accordion prop 清理accordion-props.ts独立转换顺序无关Select items 提示/改写select-items-prop.ts只读为主不产生破坏性修改。在遍历源码文件之前迁移会先定位 tsconfigfindTsConfigdashboard-ui-migration.ts优先向上查找tsconfig.dashboard.jsonDashboard 扩展的首选配置其次查找tsconfig.json一直回溯到文件系统根目录若都找不到则抛出明确错误提示“请从包含 tsconfig.json 的目录运行或通过第二个参数传入项目目录路径”。加载项目后它会过滤出目标目录下所有.tsx文件如果 tsconfig 的 include 模式没有覆盖到 Dashboard 扩展文件sourceFiles.length 0则回退用**/*.tsxglob 手动扫描并添加。每次转换完成后命令会打印摘要Found N TSX files (using tsconfig)、每个改动文件的Updated: path (N changes)最后Done! N changes across M files若未发现任何 Radix UI 模式则输出No Radix UI patterns found. Your code is already up to date!。单个文件处理出错只记录警告Error processing path: message并继续不会中断整体迁移。1.asChildprop →renderpropRadix 风格的Button asChildLink.../Link/Button组合子模式在 Base UI 中改为显式的renderprop// 迁移前 Button asChild Link to./new PlusIcon / New /Link /Button // 迁移后 Button render{Link to./new /} PlusIcon / New /Button转换逻辑as-child-to-render.ts会反复扫描源码中的asChild属性每次替换都会使 AST 位置失效因此采用“替换一次、重新扫描”的循环策略并处理多种边界情况asChild出现在自闭合元素上仅删除属性并给出警告asChild的子节点数量不为 1JSX 要求恰好一个子元素跳过并警告子节点是 JSX 表达式或纯文本无法自动转换跳过并警告子元素是普通 JSX 元素时会用原始源码文本提取内部内容保留{value.firstName} {value.lastName}这类内联空白并对内部内容做基于缩进的 dedent保证格式化后缩进正确。2. 旧表单组件 →FormFieldWrappershadcn 风格的FormField FormItem FormLabel FormControl FormMessage嵌套结构被合并为更简洁的FormFieldWrapper单组件// 迁移前 FormField control{form.control} nameslug render{({ field }) ( FormItem FormLabelSlug/FormLabel FormControl Input {...field} / /FormControl FormDescriptionThe URL slug./FormDescription FormMessage / /FormItem )} / // 迁移后 FormFieldWrapper control{form.control} nameslug labelSlug descriptionThe URL slug. render{({ field }) ( Input {...field} / )} /该转换form-components.ts基于 ts-morph AST 解析逐个处理FormField每次修改后重新查询最多迭代 100 次防止死循环对于无法自动转换的模式会回退写入TODO注释提示人工处理。3. Import 合并统一到vendure/dashboard转换的核心目标import-consolidation.ts是让所有 UI 组件 import 统一来自vendure/dashboard识别radix-ui/*、vendure-io/ui*、base-ui/react*三类 import收集其默认/命名 import保留别名删除原声明去重后合并写入import { ... } from vendure/dashboard处理命名空间 import如import * as Dialog from radix-ui/react-dialog通过NAMESPACE_MEMBER_MAP将Dialog.Root → Dialog、Dialog.Trigger → DialogTrigger、Dialog.Content → DialogContent等成员访问改写为扁平组件名并自动补充对应命名 import如Dialog.Root映射为Dialog本身、Dialog.Overlay映射为DialogOverlay遇到未收录的成员则按NamespaceMember命名并输出警告处理第三方包中被vendure/dashboard重新导出的符号源码中的REEXPORTED_SYMBOLS表精确列出了可迁移的符号集合例如react-hook-formuseForm、Controller、useWatch等、tanstack/react-queryuseQuery、useMutation、queryOptions等、tanstack/react-routerLink、useNavigate等、tanstack/react-table、lingui/react的useLingui、lucide-react的LucideIcon类型以及sonner的toast。只把表内符号搬移到vendure/dashboard其余保留在原包避免破坏性的错误重写注释中特别说明lingui/react/macro路径下的Trans、useLingui宏不被迁移Babel 宏无法被 re-exportlucide-react的实际图标组件也不迁移仅LucideIcon类型被 re-export。4. Accordion 过时 prop 清理Base UI 的 Accordion 不再需要 Radix 风格的type与collapsiblepropaccordion-props.ts// 迁移前 Accordion typesingle collapsible classNamew-full // 迁移后 Accordion classNamew-full实现上会查找所有Accordion开闭标签与自闭合标签逆序移除typesingle、typemultiple属性以及collapsible布尔属性逆序处理避免位置偏移并保留其余属性。5. Select 缺失itemsprop 补齐Base UI 的 Select 推荐通过itemsrecord 声明选项select-items-prop.ts。对于静态的SelectItem子节点字符串valueprop 文本内容转换会自动生成 items record// 迁移前 Select value{value} onValueChange{setValue} SelectContent SelectItem valuedraftDraft/SelectItem SelectItem valuepublishedPublished/SelectItem /SelectContent /Select // 迁移后 Select value{value} onValueChange{setValue} items{{ draft: Draft, published: Published }} SelectContent SelectItem valuedraftDraft/SelectItem SelectItem valuepublishedPublished/SelectItem /SelectContent /Select对于动态模式如.map()生成的选项无法静态推断则输出警告提示人工处理。测试与验证可运行的证据链dashboard-base-ui的全部 5 个转换均有 vitest 单元测试覆盖测试文件位于 dashboard-ui-migration.spec.ts。测试采用共享的 ts-morphProjectuseInMemoryFileSystem: true避免重复初始化 TypeScript 编译器和内存源码文件进行断言。例如transformAsChildToRender的用例验证改动计数为 1输出文本包含render{Link to./new /}不再包含asChild子内容PlusIcon /与文本New被保留外层仍然是Button。仓库还附带了一套面向 Agent 的迁移操作手册 radix-to-base-ui-migration它与 codemod 的执行顺序一致扫描asChild用法、旧表单组件、直接radix-ui/*/vendure-io/ui/*/base-ui/react/*import、带type/collapsible的Accordion、缺items的Select然后参考01-asChild-to-render.md、02-form-components.md、03-import-consolidation.md、04-component-api-changes.md四份细则逐项转换最后验证“所有 UI 组件 import 均来自vendure/dashboard、不再残留三类直接 import、第三方 import 仅使用白名单符号”。使用建议与注意事项Agent / CI 场景必须传 transform 名并建议设置VENDURE_CLI_NON_INTERACTIVEtrue让无参数调用快速失败并打印示例而不是阻塞在终端提示符迁移前先提交或备份codemod 是直接改写文件的批量操作通过project.save()落盘虽然单文件出错不会中断整体但建议先在干净的工作区运行git diff审查改动目录参数只在非交互模式生效交互模式请直接在目标项目目录下运行确保能找到 tsconfig迁移依赖tsconfig.dashboard.json或tsconfig.json从目标目录向上回溯查找找不到时会报错并提示传入项目目录路径查看最新 transform 清单运行不带参数的vendure codemod查看交互式列表或查看 codemod.ts 中的CODEMODS注册表。【免费下载链接】vendureOpen-source headless commerce platform built with TypeScript, NestJS, React, and GraphQL项目地址: https://gitcode.com/GitHub_Trending/ve/vendure创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表