关于 cordova-plugin-migrator
面向将现有 Cordova 插件迁移到 Capacitor 的团队的编排技能。它分析源代码并生成结构化 YAML 交接计划,经用户确认后调用 capacitor-plugin-generator 生成插件,再整理迁移文档。
主要功能
- 01分析 Cordova 源码和依赖
- 02生成结构化 YAML 迁移计划
- 03生成前设置用户确认环节
- 04委托 capacitor-plugin-generator
- 05汇总 MIGRATION.md 文档
- 06检查钩子和平台差异
适用场景
- 01承诺迁移前评估工作量和阻碍
- 02为 Cordova 插件准备生成器计划
- 03审查钩子及原生依赖的可移植性
- 04比较 Cordova 与 Capacitor API
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ ionic-team/ capacitor-skills --skill cordova-plugin-migrator安装后在 Claude Code 中输入/cordova-plugin-migrator确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/api-mappings.mdcomplexity-assessment.mddependency-migration.mdexample-analysis.mdhooks-migration.mdmigration-patterns.mdoutput-modes.mdpost-migration-cleanup.mdunsupported-patterns.mdusing-plugin-generator.md详细介绍
Cordova 插件迁移器
端到端协调器,只需调用一次技能,即可接收 Cordova 插件源代码树,并生成候选 Capacitor 插件及整合后的 MIGRATION.md。它会先分析 Cordova 插件,生成符合 capacitor-plugin-generator/references/input-contract.md 的结构化 YAML 计划,等待用户确认,然后以结构化模式将该计划交给 capacitor-plugin-generator 技能。此技能不会重新实现生成器已有的功能;脚手架搭建和原生代码生成由生成器负责。
何时使用此技能
✅ 在以下情况下使用此技能:
- 将现有 Cordova 插件迁移到 Capacitor。
- 在做出决定前评估迁移的复杂度、工作量和阻碍因素。
- 为
capacitor-plugin-generator生成结构化交接 YAML。 - 将官方 Cordova API 与现有或计划中的 Capacitor API 进行比较。
- 审查 Cordova 插件的钩子、原生依赖项或
<config-file>修改,评估其可移植性。
❌ 请勿在以下情况下使用此技能:
- 生成 Capacitor 插件脚手架或实现;请将计划交给
capacitor-plugin-generator。 - 在没有 Cordova 源代码的情况下设计全新插件。
- 迁移整个 Cordova 应用。此技能的范围仅限插件。
- 调试已迁移插件的运行时问题。
- 发布或发行生成的 Capacitor 插件。
前置条件
| 要求 | 用途 |
|---|---|
| Cordova 插件源代码(本地克隆或可访问的仓库) | 读取 plugin.xml、原生源代码和 JS 桥接代码。 |
| Node.js LTS 和 npm | 检查依赖项,并运行钩子引用的脚本。 |
capacitor-plugin-generator 技能 | 接收此技能生成的 YAML 计划。 |
capacitor-plugin-generator/references/input-contract.md | 规定交接 YAML 的权威格式。 |
| 对官方 Capacitor 等效实现(如有)的读取权限 | 移植已有 Capacitor 实现的插件时,复用其线格式名称和类型。 |
| Xcode 和 Android Studio(可选) | 确认检测到的原生依赖项所需的 SDK 是否可用。 |
Agent 行为
- 作为编排器运行。阶段 1–10 分析 Cordova 源码并生成 YAML 计划;阶段 11 通过 Skill 工具调用
capacitor-plugin-generator,以结构化模式传入计划;阶段 12 整合文档。不要通过此技能输出原生 Capacitor 代码。该生成器负责此项工作。 - 生成 YAML 前,先阅读
capacitor-plugin-generator/references/input-contract.md。生成器的契约具有权威性;不要臆造字段或重命名现有字段。 - 首先从
plugin.xml确定插件身份:id、name、version、声明的平台、声明的框架、hooks 和 config-file 目标。 - 在断言平台支持情况前,检查所有原生依赖声明。应反映
plugin.xml的实际内容,而非 README 中的说法。 - 根据
references/hooks-migration.md中的规则,将每个<hook>分类为 Tier 1(Capacitor hooks)、Tier 2(npm 脚本/手动步骤)或 Tier 3(阻断项)。一个 Tier 3 hook 就足以阻止移交给生成器。 - 如果存在官方 Capacitor 等效实现(
@capacitor/<name>或 Capawesome/社区移植版本),请阅读其definitions.ts和原生源码。原样复用其中的 wire-format 字符串、枚举值、方法名和事件名。不要臆造“看起来相似”的平行 API。 - 检测混合插件。如果
package.json已声明scripts.capacitor:*hooks,则该插件已部分支持 Capacitor。将现有 hooks 记录为 Tier 1“已转换”,并询问用户是要复用、重写还是合并。不要悄悄丢弃它们。 - 如果某个 JS 方法在 Cordova 端接收的参数是字符串化 JSON 数据块(原生处理程序中出现
JSON.parse/Gson.fromJson/JSONObject(args.getString(0))),必须将其映射为api.types中强类型的 TypeScript 接口,而不是string参数。根据原生解析位置记录接口结构。 - 如果 Cordova 原生源码使用运行时权限 API(
cordova.requestPermission、requestPermissions(...)、AVCaptureDevice.requestAccess、PHPhotoLibrary.requestAuthorization、CLLocationManager代理、CNContactStore.requestAccess等),请在 YAML 中添加checkPermissions()和requestPermissions()方法,即使 Cordova JS 接口未公开这些方法也一样。Capacitor 的惯例是显式权限方法,而且官方等效实现(如有)几乎总会公开这些方法。 - 如果 Cordova 原生源码通过辅助类(
ExifHelper、MimeTypeHelper、ImageMetadata等)提取元数据,并将其纳入响应负载,则应在相应的api.types接口中记录这些字段,即使 Cordova JS 文档未说明它们也一样。应阅读原生代码,而非 README。 - 镜像官方 Capacitor 等效实现时,请核对该官方实现的原生 LOC 与 Cordova 源码的原生 LOC。如果官方实现的 LOC 超过后者的 3 倍,请在
migration.notes中添加一条说明,提醒审阅者:直接移植会遗漏官方实现涵盖的行为(例如,用于精确控制振动时长的 iOSCHHapticEngine,或用于冲击/通知效果的 AndroidVibrationEffect模式)。生成器的 SDK 适配器规则不一定能发现这一点。 - 添加设置说明时,请区分三个下游目标:
- 插件自身的打包配置。 Gradle
implementation '...'行、CocoaPodss.dependency '...'行、自定义 Maven 仓库 URL、s.weak_framework、s.vendored_frameworks、AndroidManifest<uses-permission>/<meta-data>/<queries>条目,以及@CapacitorPlugin(permissions = [...])声明,都应放在插件自身的android/build.gradle、.podspec、android/src/main/AndroidManifest.xml或注解中。Gradle 清单合并和 CocoaPods 会将这些配置传递给使用方,因此无需宿主应用步骤,也无需在MIGRATION.md中添加条目。 - 宿主应用的构建配置。 不能放在插件包中、必须由使用方应用配置的项目:Info.plist 隐私说明(
NSCameraUsageDescription、NSLocationWhenInUseUsageDescription等)、iOS 功能和授权(Apple Pay 商家 ID、aps-environment、com.apple.security.application-groups),以及其他必须在宿主应用中而非插件中完成的清单修改。记录在migration.notes中,并在MIGRATION.md中按平台提供可直接复制粘贴的代码片段。 - 使用方的运行时配置/代码。 Apple Developer 端的凭据配置、由宿主应用提供的 JSON 配置值(商家编号、API 密钥),以及使用方 JS 调用点的迁移(回调 → Promise、位置参数 → 命名参数)。由于这些输入属于使用方自己的数据,没有工具可以自动完成这些工作。
在
migration.notes中,将每条plugin.xml指令归入这三类之一。切勿编写要求使用者为插件应打包的依赖添加implementation '...'的MIGRATION.md步骤。有关依赖项的具体表格,请参阅references/dependency-migration.md中的“所有权模型”。
- 插件自身的打包配置。 Gradle
- 当 Cordova 插件使用
<preference name="VAR" default="...">,并在<config-file target="*-Info.plist">条目中包含安装时占位值(Apple Pay 商户配置、OAuth 客户端 ID、分析密钥等)时,请检测这一情况,并在migration.warnings中建议采用运行时配置 JSON 文件模式:由混合capacitor:sync:after脚本使用PluginConfig.json,在构建时将文件复制到原生项目中。Cordova 插件可能已经提供了此脚本(请在hooks/capacitor*.js中查找);如果有,请重复使用。否则,请提供一个单屏模板。此模式可完全避免将使用方的值写入静态 plist / manifest 条目。 - 检测
plugin.xml中的 SPM 标记:<platform name="ios" package="swift">和<pod ... nospm="true">表明 Cordova 插件已附带同级的Package.swift。如果存在:(a) 读取该Package.swift,并将其依赖项填入 YAML 的dependencies.ios.spm;(b) 将所有未带nospm="true"的 pod 移至dependencies.ios.cocoapods;(c) 在migration.notes中添加说明:生成的 Capacitor 插件必须同时附带Package.swift和.podspec(Capacitor 8 同时支持两者,且 SPM 是新插件的默认方式)。架构请参阅references/dependency-migration.md中的 "Swift Package Manager (SPM)"。 - 默认输出模式为 Mode B(并列目录)。仅当用户明确要求且源文件位于可写工作副本中时,才切换到 Mode A(在原位置操作并使用
.cordova-archive/)。 - 如果阻塞项、Tier 3 钩子、无法解决的专有 SDK 或缺失的源文件会迫使你猜测,请暂停并要求用户输入。不要输出掩盖缺失信息的 YAML 计划。
- 区分可解决的警告(有文档记录的手动步骤)和阻塞项(无法自动迁移)。两者都要写入计划;只有阻塞项会阻止移交。
- 在 Cordova 插件目录中检入的随附二进制文件(例如
src/ios/frameworks/Foo.xcframework)本身不是阻塞项。保留该二进制文件,并在migration.source_files.ios(或.android)下记录其路径。只有当该二进制文件需要用户不具备的运行时凭据,或不满足 AndroidX / 64 位 / 模拟器要求时,才将其视为阻塞项。 - 报告实际检查过的内容。标记阻塞项或不受支持的模式时,请注明文件路径和行号。
- 在宣布 Phase 9 前,对照 iOS 和 Android 的检查结果。如果某个平台提供了另一平台没有的方法,请在
migration.warnings中指出不匹配,以便生成器选择策略(两端都实现、有条件地公开,或删除)。不要悄然生成只有一个平台能够实现的契约。 - 默认响应形式是架构和计划,而不是代码。除非用户明确要求“展示代码”或“深入分析”,否则不要包含完整的迁移前后代码块。
migration.cordova_to_capacitor_map中逐方法的一行映射不算“代码”,它们属于计划的一部分。 - 对
migration.cordova_to_capacitor_map中的每个值,以及其他包含 JS 语法((、)、{、}、:、[、])的 YAML 字符串,都加上引号。未加引号的 JS 表达式(如Foo.bar({ x: 1 }))是无法解析的 YAML,生成器会在加载计划时拒绝它。 - 只有在 Phase 10 的用户检查点获批后,才能调用生成器。如果用户拒绝、暂停或仍有未解决的阻塞项,就停止。绝不要使用
migration.blockers非空或migration.hooks.tier_3非空的 YAML 调用生成器。 - 当
odc_target: true时,Phase 11 分为两个按顺序执行的子阶段(11a 和 11b)。Phase 11a 调用build-actions-generator;Phase 11b 调用capacitor-plugin-generator。完整流程请参阅references/using-plugin-generator.md中的 "ODC Path"。构建操作写入 Capacitor 插件文件夹。对于由构建操作完全覆盖的钩子和迁移说明,必须从传给生成器的 YAML(Phase 11b)中排除,以免生成器为构建操作已处理的配置级工作重复生成 Capacitor 钩子脚本。
流程
阶段 1:确定任务和输出模式
确认用户有一个要迁移的 Cordova 插件。如果用户想从头开始创建全新的 Capacitor 插件,且没有 Cordova 源代码可供转换,请在此处停止,并直接引导用户使用 capacitor-plugin-generator;此技能无法提供帮助。
否则,选择输出模式:
- 模式 B(默认,旁置),生成器在 Cordova 仓库的同级目录中搭建新的 Capacitor 插件。绝不触碰 Cordova 仓库。
- 模式 A(选择加入,原位),生成器在临时
目录中搭建插件。阶段 11 成功后,阶段 12 会将生成器的
输出移至 Cordova 仓库根目录,并将原始 Cordova
源代码移至
.cordova-archive/。保留原始仓库的 npm 包名称和 git 历史记录。需要用户明确选择加入,并确保 git 工作副本干净且可写。
请参阅 references/output-modes.md,了解目录布局、预检和
确切的迁移顺序。
**ODC 确认:**检查用户是否在请求中的任何位置提到了 ODC 或 OutSystems
Developer Cloud。如果提到了,设置 odc_target: true 并继续。如果没有,请询问:"这个 Capacitor 插件是否会供 ODC
(OutSystems Developer Cloud)应用使用?如果会,我们会在 Capacitor 插件旁生成构建操作,以便在 MABS 中处理原生配置。"
将回答记录为 odc_target: true/false,以供阶段 11 使用。
阶段 2:读取 plugin.xml
典型的 Cordova 插件目录结构:
my-plugin/
├── plugin.xml # Plugin manifest and configuration
├── package.json # NPM metadata (and any capacitor:* scripts)
├── www/ # JavaScript bridge
├── src/
│ ├── ios/ # CDVPlugin subclasses (.h/.m/.swift)
│ └── android/ # CordovaPlugin subclasses (.java/.kt)
└── hooks/ # Optional lifecycle scripts
打开 plugin.xml。提取:插件 ID、名称、版本、声明的平台
(<platform name="...">)、<source-file>/<header-file> 映射、
<framework> 条目、<podspec> 块、<config-file> 目标、
<edit-config> 目标、<hook> 声明、<dependency> 条目、
<preference> 标签,以及 <js-module> 暴露方式(clobbers / merges /
runs)。记录每个潜在阻塞项的文件路径和行号。
阶段 3:分析原生依赖
按照 references/dependency-migration.md 操作。针对每个 <framework> 和
<podspec> pod,判定其属于:直接迁移、版本更新、替代库或阻塞项。针对每个 Android Gradle 坐标,检查其使用的是 AndroidX 还是 Support
Library,以及是否符合 Capacitor 的最低 compile SDK 要求。记录迁移后所需的手动安装步骤。
阶段 4:分析钩子
按照 references/hooks-migration.md 中的三级规则操作:
- 第 1 级,可转换为 Capacitor 插件 npm 钩子
(
capacitor:{sync,copy,update}:{before,after}、capacitor:{android,ios}:add:{before,after})。 - 第 2 级,可转换为 npm 生命周期脚本(
postinstall、preuninstall)或记录为手动步骤。 - 第 3 级,交互式提示、修改 plugin.xml/config.xml、Cordova CLI 内部功能,或任何没有 Capacitor 对应项的内容。
阅读每个引用的脚本。不要仅根据文件名进行分类。
阶段 5:分析 JavaScript 桥接
按照 references/api-mappings.md 操作。根据 www/*.js 列出每个公共方法、
其位置参数结构、使用成功/错误回调还是返回 Promise,以及 exec() 是否与
cordova.exec() 操作名称配对。将每个方法映射为 Capacitor 的
methodName(options): Promise<R> 签名。
阶段 6:分析 iOS 实现
按照 references/api-mappings.md 操作。根据 src/ios/*.{h,m,swift},识别
CDVPlugin 子类、每个与 JS 操作对应的方法、从 command.arguments
中提取参数的方式、响应构造(CDVPluginResult)、权限流程,以及使用的任何系统框架或 SDK 适配器。指出需要将 Objective-C 现代化为 Swift 的位置。
阶段 7:分析 Android 实现
按照 references/api-mappings.md 操作。根据 src/android/**/*.{java,kt},识别
CordovaPlugin 子类、execute() 路由器、操作字符串、参数提取方式(args.getString(i))、响应路径(CallbackContext.success/error)、权限流程,以及任何 Activity Result 模式。指出需要将 Java 现代化为 Kotlin 的位置。
阶段 8:评估复杂度
应用 references/complexity-assessment.md。根据方法数量、
代码行数、依赖规模、钩子层级组合、语言现代化程度、阻碍项数量以及
Capacitor 等效复用情况为插件评分。输出以下其中一项:simple、moderate、
complex、blocked。blocked 表示用户必须先解决问题,才能交接给
生成器。
阶段 9:生成迁移 YAML
应用 references/using-plugin-generator.md。依据生成器的
references/input-contract.md 构建 YAML,包含基础区块(plugin、
platforms、api、permissions、dependencies)以及可选的
migration: 区块(source、complexity、output_mode、blockers、
warnings、language_modernization、source_files、hooks、
cordova_to_capacitor_map)。若存在官方 Capacitor 等效项,则将线级格式字符串
固定为其对应值。
阶段 10:用户确认点
在 YAML 旁附上简短的人类可读摘要:复杂度、阻碍项、警告、手动设置、 建议的输出模式,以及所参照的任何 Capacitor 等效项。如果存在阻碍项或 Tier 3 钩子,则停止并等待确认。
阶段 11:调用下游技能
下游调用路径取决于阶段 1 中是否确认了 ODC。
非 ODC 路径:应用 references/using-plugin-generator.md。通过 Skill 工具以结构化模式调用
capacitor-plugin-generator,并传入阶段 9 的 YAML。生成器会运行自己的操作流程;
本技能不会重新检查 Cordova 源代码。对于 Complex 插件,使用增量模式
(每次处理一个平台,并在每个平台后等待用户确认)。如果生成器拒绝 YAML,则返回阶段 9 并修正;
切勿手动编辑生成器的输出。
**ODC 路径:**按照
references/using-plugin-generator.md“ODC Path”中的两个子阶段顺序执行:
- 阶段 11a — 使用阶段 9 的 YAML 和 Cordova 插件路径调用
build-actions-generator; 等待其生成build-actions/。记录其覆盖了哪些钩子/元素。 - 阶段 11b — 从
migration.hooks.tier_1中移除已由构建操作覆盖的项目 (或将其标记为status: handled_by_build_actions);添加一条migration.notes记录说明这一点。然后使用带注释的 YAML 调用capacitor-plugin-generator(根据复杂度选择标准模式或增量模式)。
阶段 12:迁移后清理
应用 references/post-migration-cleanup.md。生成器生成可用脚手架后,将中间备注
整合到插件根目录中的单个 MIGRATION.md 文件中,根据所选输出模式归档或移除
原始 Cordova 源代码,并更新 README,说明面向使用者的破坏性变更
(回调 → Promise、位置参数 → 命名参数、手动原生设置)。
根据 Agent Behavior 规则,交叉检查每条 migration.notes 和
migration.warnings 条目是否已归类(插件打包 / 宿主应用构建配置 /
使用者运行时配置)。MIGRATION.md 只应列出归入类别 2 或 3 的项目。
插件打包项目对使用者透明,不应纳入迁移记录。
最佳实践
应当做
- ✅ 首先阅读
plugin.xml,并以实际 XML、源文件路径或钩子脚本内容为依据支持每项结论。对阻碍项标注行号。 - ✅ 将生成器的输入契约视为权威依据。根据
capacitor-plugin-generator/references/input-contract.md构建 YAML。 - ✅ 如果存在官方 Capacitor 等效项,则复用其线级格式字符串。枚举大小写、事件名称和方法名称必须完全一致。
- ✅ 阅读钩子引用的脚本来对钩子分类,不要仅凭文件名判断。
- ✅ 默认使用模式 B(并行放置)。只有在用户明确选择加入且有可写工作副本时,才切换到模式 A。
- ✅ 如果存在阻碍项或 Tier 3 钩子,则在阶段 10 的确认点停止。
- ✅ 同时记录阻碍项和警告;只有阻碍项会阻止交接。
- ✅ 记录迁移后使用者需要执行的手动原生设置步骤(Info.plist 键、AndroidManifest 条目、Podfile / Gradle 添加项)。
不要
- ❌ 不要通过此技能生成原生 Capacitor 代码(Swift、Kotlin、Java、TypeScript)。代码生成由生成器负责。
- ❌ 不要臆造 YAML 字段,也不要重命名生成器已定义的字段。
- ❌ 如果存在官方的 Capacitor 等效项,不要根据便于理解的名称重新推导线缆格式字符串。请查看其
definitions.ts。 - ❌ 不要在未打开引用脚本的情况下,将钩子归类为 Tier 1/2。
- ❌ 不要输出一份 YAML 计划,其中将
complexity: simple列为简单,却隐瞒了专有 AAR 或交互式设置钩子。 - ❌ 不要在此处添加特定于 Capacitor 版本的说明;生成器技能负责生成器端的规则(名称一致性、Java 文件名、
notifyListeners可见性等)。请引用,不要重复。 - ❌ 不要静默调用生成器。阶段 10 是用户必须确认的检查点,不得跳过。
- ❌ 存在未解决的阻塞项或 Tier 3 钩子时,不要调用生成器。
- ❌ 不要通过此技能提交、推送或发布生成器输出。
错误处理
| 症状 | 修复方法 |
|---|---|
缺少 plugin.xml 或文件格式错误 | 停止。请用户提供规范的插件源文件。不要根据 README 中的宣传文案推断契约。 |
plugin.xml 引用的源文件在磁盘上不存在 | 停止。按路径报告缺失文件。缺少这些文件,计划就不完整;不要继续到 Phase 9。 |
| Hook 引用的脚本无法打开或经过混淆 | 归类为 Tier 3,并将脚本路径添加到 migration.blockers。不要根据 Hook 类型猜测。 |
插件为需要用户不具备的运行时凭据的私有/专有 AAR 或 .framework 声明了 <framework> | 记录为阻碍项。注明需要联系供应商。不要悄悄换成公开替代项。 |
插件在仓库中携带二进制文件(例如 src/ios/frameworks/Foo.xcframework、src/android/libs/Foo.aar),且该文件公开分发 | 不属于阻碍项。保留该二进制文件,并在 migration.source_files.{ios,android} 下记录其路径。生成器会将其复制到 Capacitor 插件的 ios/ 或 android/libs/ 目录。 |
| 插件从自定义 Maven 仓库(Azure DevOps、JFrog 等)拉取 Android 依赖项 | 在 migration.dependencies.android.maven_repos 下记录 URL。无需身份验证即可访问时,作为警告而非阻碍项。需要身份验证但未提供凭据时,作为阻碍项。 |
插件使用 Support Library(android.support.*)坐标 | 除非用户确认接受 Jetifier,否则记录为阻碍项。Capacitor 需要 AndroidX。 |
Cordova 插件有官方 Capacitor 等效插件(@capacitor/<name>) | 阅读该等效插件的 definitions.ts 和原生源代码。在 YAML 中固定方法名称、枚举值、事件名称和错误代码。将该等效插件的包作为 migration.notes 提供给审核者。 |
插件同时声明了 <hook> 条目和 package.json 中的 scripts.capacitor:* 条目(混合插件) | Capacitor 脚本已经存在。将其记录为 Tier 1“已转换”Hook。询问用户是要复用、重写,还是与新迁移的 Cordova Hook 合并。 |
插件通过 <config-file> 修改 AndroidManifest.xml,添加 <uses-permission>、<meta-data>、<queries> 或 <provider> | 放入插件自己的 android/src/main/AndroidManifest.xml,Gradle 清单合并器会自动将其合并到宿主应用。无需执行宿主应用步骤。在 migration.notes 下记录,以便生成器输出。 |
插件通过 <config-file> 修改 Info.plist,添加 Apple 要求的隐私说明字符串(NSCameraUsageDescription、NSLocationWhenInUseUsageDescription、NSMicrophoneUsageDescription 等) | 宿主应用的 Info.plist,Apple App Store 要求这些内容位于宿主应用的 plist 中,而非插件的 plist 中。在 migration.notes 下记录,并在 MIGRATION.md 中提供可复制粘贴的代码片段。 |
插件通过 $VAR 安装时占位符,使用 <config-file> 修改 Info.plist,添加面向使用者的特定值(Apple Pay 商户 ID、OAuth 客户端 ID、分析密钥) | 强烈推荐使用运行时配置 JSON 文件模式:由混合 capacitor:sync:after 脚本读取 <Plugin>Configuration.json。如果 Cordova 插件中已有脚本,则复用;否则提供一屏即可完成的模板。这样可以将面向使用者的特定值完全排除在 plist 之外。 |
插件通过 <config-file> 修改 entitlements plist(*-Debug.plist、*-Release.plist、*-Entitlements.plist),以添加 com.apple.developer.in-app-payments、aps-environment、com.apple.security.application-groups 等功能所需配置 | 宿主应用功能 + entitlement。 在 migration.notes 下记录;在 MIGRATION.md 中说明使用者必须启用的确切 Xcode 功能(Apple Pay、推送通知、App Groups 等)和 entitlement 值。 |
插件为 iOS 声明了带有 weak="true" 的 <framework> | 插件自己的 podspec。 在 dependencies.ios.system_frameworks 中记录,并添加一条 migration.notes,以便生成器输出 s.weak_framework 而非 s.framework。无需执行宿主应用步骤。 |
插件使用 <edit-config> 和 mode="merge",向宿主 <application> 元素添加 android:requestLegacyExternalStorage 或类似属性 | 宿主应用的 AndroidManifest(如果该属性适用于宿主应用);否则使用插件自己的 AndroidManifest。在 migration.notes 中记录确切属性和父元素,以便 MIGRATION.md 包含可复制粘贴的代码片段。 |
插件使用 <js-module runs="true"> | 添加到 migration.warnings。建议在 Web 层使用显式的 initialize() 方法或在构造函数中初始化。 |
插件有多个 <js-module> 条目,且含有多个 <clobbers> 目标(例如常量模块 + 主模块) | 合并为单个 registerPlugin() 注册。在 definitions.ts 中将常量与插件接口一起导出。Capacitor 没有对应的多重 clobber 机制。 |
插件通过 <source-file target-dir="res/..."> 包含 Android 资源文件 | 在 migration.source_files.android 下记录,并注明目标 res/ 子路径。生成器会将其复制到 android/src/main/res/<subpath>/。常见于 FileProvider 路径和主题。 |
插件使用 <preference name="..." default="..."> 和安装时变量替换(plugin.xml 中的 ${VAR}),并在 <config-file target="*-Info.plist"> 或 AndroidManifest.xml 中引用 | 优先采用运行时配置 JSON 文件模式(使用者将值填入 <Plugin>Configuration.json,由混合 capacitor:sync:after 脚本读取)。如果 Cordova 插件中已有脚本,则复用。备选方案:在 capacitor.config.json 中使用 plugins.<PluginJSName> 下的运行时配置。 |
插件使用 <preference name="ANDROIDX_CORE_VERSION" default="1.18.0">(或类似的仅构建时版本固定项),并在插件自己的 build.gradle 中引用 | 插件自己的 build.gradle,在生成的 Gradle 文件中按字面值固定版本。无需执行宿主应用步骤,也无需运行时配置。使用者不会看到此配置。 |
插件的原生处理程序解析字符串化的 JSON 数据块(Gson.fromJson、JSONObject(args.getString(0))) | 将解析后的结构映射到强类型的 api.types 接口,绝不能使用 string。从原生解析位置(Kotlin data class 或 Swift struct)提取结构定义。 |
一个 JS 方法根据 typeof param 分派到多个 cordova.exec() 操作名称(例如 vibrate(num) 与 vibrate([...])) | 拆分为多个类型化的 Capacitor 方法,例如 vibrate({ duration })、vibrateWithPattern({ pattern, repeat })、cancelVibration()。在 migration.cordova_to_capacitor_map 中记录拆分,并将其添加到 migration.warnings,作为面向使用者的破坏性变更。 |
| 生成器因“bad indentation”或“mapping entry”解析错误而拒绝 YAML | 某个 cordova_to_capacitor_map 条目包含未加引号的 JS 语法((、{、: 等)。为每个 cordova: 和 capacitor: 值都加引号,使其成为 YAML 字符串。必须重新输出计划;生成器无法按原样加载。 |
| Cordova 原生源代码请求运行时权限,但 Cordova JS 接口没有权限方法 | 将 checkPermissions()(Promise<PermissionStatus>)和 requestPermissions(options?)(Promise<PermissionStatus>)添加到 api.methods,并将 PermissionStatus 接口添加到 api.types。否则,迁移后的插件将违反 Capacitor 惯例,使用者也会期待这些方法。 |
Cordova 原生源代码有用于提取元数据的辅助类(ExifHelper、MimeTypeHelper 等),但 Cordova JS 文档没有列出相应字段 | 阅读构造原生响应的位置。将元数据字段(通常为 exif?: any、mimeType?、size?)添加到结果类型中。Cordova JS 文档经常低估原生端实际返回的内容。 |
| 官方 Capacitor 等效插件的原生源代码行数超过 Cordova 源代码的 3 倍 | 添加 migration.notes 条目,提醒审核者,照搬移植会导致未实现平台特定行为(例如,以 AudioServicesPlaySystemSound 替代 iOS CHHapticEngine,或以单次振动替代 Android 基于模式的触觉反馈)。建议评估是否将使用者转向官方包。 |
Cordova 插件的 plugin.xml 含有 <platform name="ios" package="swift"> 或任何 <pod ... nospm="true"> | 插件已在 CocoaPods 之外提供 SPM 支持。将其 Package.swift 依赖项移至 dependencies.ios.spm;仅将没有 nospm="true" 的 pod 移至 dependencies.ios.cocoapods。Capacitor 移植版必须同时提供 Package.swift 和 .podspec。 |
插件声明了对另一个 Cordova 插件的 <dependency> | 单独解决该依赖项。如果其没有 Capacitor 等效插件或迁移计划,则将其视为当前插件的阻碍项。 |
| 插件的 iOS 源代码仅使用 Objective-C | 记录 migration.language_modernization.ios: { from: objective_c, to: swift }。注明使用者可能仍需要桥接头文件。 |
| 插件的 Android 源代码仅使用 Java | 记录 migration.language_modernization.android: { from: java, to: kotlin }。用户提出要求时,生成器仍会生成 Java,但默认建议使用 Kotlin。 |
| 生成器拒绝 YAML | 重新阅读 capacitor-plugin-generator/references/input-contract.md。在此技能中修复 YAML,而不是修改生成器。不要绕过契约。 |
| 生成器提示缺少线格式字符串 | 重新阅读官方 Capacitor 等效插件的 definitions.ts。逐字更新 api.types 值。不要根据易读名称进行“翻译”。 |
| 用户请求 Mode A,但工作副本不受版本控制或为只读 | 拒绝 Mode A。建议使用 Mode B。没有 VCS 时,从错误的原地移动中恢复需要手动操作。 |
| 插件宣传了源代码并未实现的功能 | 以源代码为准。在 migration.warnings 下记录宣传但未实现的功能。不要为了符合文档而虚构 API 方法。 |
| Hook 根据文件名被归类为 Tier 1,但实际上需要交互 | 阅读脚本源代码,而不只是 <hook> 的 name 属性。任何通过 stdin 提示、打开 TTY 或调用 read / prompt 的内容都属于 Tier 3。 |
| 依赖项被标记为“直接迁移”,但对应 pod / Gradle 产物已弃用 | 在标记为直接迁移前,核实最新发布日期以及 Swift / AndroidX 兼容性。超过 3 年未更新的内容应改为“替换”或“阻碍项”。 |
| 插件复杂度被评估为“简单”,但其公共 API 方法有 15 个以上 | 始终统计公共 API 方法。公共方法超过 10 个的插件至少属于中等复杂度,无论其他信号如何。 |
| 分析时漏掉了阻碍项 | 始终扫描 plugin.xml 中的 <config-file>、<edit-config>、<js-module runs="true">、<hook> 和 <dependency>;这些都是必须检查的潜在阻碍项。如果 YAML 看起来过于整齐,进入 Phase 9 前要重新扫描。 |
| 生成器在 Phase 11 重新读取 Cordova 源代码 | YAML 计划不完整。根据 capacitor-plugin-generator/references/input-contract.md 重新验证;将 JS API 签名、原生方法映射、权限、依赖项和阻碍项一并写入计划,以免生成器需要查看 Cordova 目录树。 |
| 用户在检查点因不接受某个阻碍项而停止 | 在 MIGRATION.md 中记录该阻碍项并停止。不要调用生成器。记录拒绝原因,以便下次尝试时处理。 |
| 复杂插件在单次调用中超出生成器的上下文容量 | 使用增量模式:按平台分别调用生成器(web → iOS → Android → final),并在每个平台之间设置用户检查点,而不是一次性处理整个插件。参见 references/using-plugin-generator.md。 |
| Mode A 移动操作与 Cordova 仓库中的文件冲突(顶层名称冲突) | 停止整个流程。与用户手动解决(重命名、删除或移动冲突文件),或者回退到 Mode B,针对同级目录重新运行 Phase 11。 |
相关技能
capacitor-plugin-generator(必需的下游依赖): 第 11 阶段会通过 Skill 工具以结构化模式调用此技能, 并使用第 9 阶段生成的 YAML 计划。生成器的references/input-contract.md是交接内容格式的权威规范。 此技能遵循并引用该规范,但不会重复生成器侧的任何 规则。build-actions-generator(可选的下游依赖,仅用于 ODC 路径): 当odc_target: true时,第 11a 阶段会调用此技能。它会为 Capacitor 插件的build-actions/目录 生成buildAction.json,涵盖配置级原生设置(manifest、plist、Gradle 依赖、 entitlements),因此生成器无需为这些项目生成对应的 Capacitor hook。
参考资料
references/output-modes.md:模式 A(原地迁移并使用.cordova-archive/)与模式 B(并排放置)的目录布局和git mv模式。references/unsupported-patterns.md:<config-file>、<edit-config>、<hook>、<js-module runs>、偏好设置、权限及各模式的阻塞阈值。references/dependency-migration.md:CocoaPods、SPM、系统框架、Gradle 坐标、AAR/JAR、自定义 Maven 仓库及各依赖的阻塞阈值。references/hooks-migration.md:三级 hook 分类(第 1 级 Capacitor hook、第 2 级 npm 脚本、第 3 级阻塞项)及脚本分析工作流。references/api-mappings.md:JavaScript 桥接、iOS(CDVPlugin→CAPPlugin)、Android(CordovaPlugin→Plugin)以及从 plugin.xml 到 package.json 的转换。references/migration-patterns.md:回调 → Promise、权限处理、多平台配置,以及跨平台一致的错误处理。references/complexity-assessment.md:simple/moderate/complex/blocked评分标准,以及会导致插件在不同类别间变动的输入。references/using-plugin-generator.md:根据capacitor-plugin-generator/references/input-contract.md构建 YAML、migration:可选块,以及第 11 阶段的调用模式(标准模式与增量模式)。references/post-migration-cleanup.md:将中间笔记整合到MIGRATION.md、模式 A 的迁移流程、归档 Cordova 源码、更新 README,以及面向使用者的破坏性变更检查清单。references/example-analysis.md:完整的端到端示例,包括读取 plugin.xml、依赖分析、hook 分类、YAML 输出和生成器交接。