mcpField
M
migrating-to-zero-yaml

migrating-to-zero-yaml

github.com/nangohq开发387 次安装3 天前更新
代码仓库

关于 migrating-to-zero-yaml

面向 Nango 项目的迁移技能,指导将基于 nango.yaml 的配置机械迁移到 Zero YAML,并优先保持现有行为。流程涵盖脚手架、脚本改写和验证。

主要功能

  1. 01盘点 YAML 配置与关联脚本
  2. 02生成 Zod 模型和项目脚手架
  3. 03将同步、操作和事件处理器改写为函数
  4. 04生成入口导入并修正类型导入
  5. 05编译、dryrun 与测试验证

适用场景

  1. 01将旧 Nango 项目迁移到 Zero YAML
  2. 02保持脚本路径和业务逻辑不变地迁移
  3. 03迁移后检查编译及 dryrun 结果

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/nangohq/skills --skill migrating-to-zero-yaml

安装后在 Claude Code 中输入/migrating-to-zero-yaml确认已加载。

详细介绍

迁移到 Zero YAML

此技能使用由大模型驱动的机械式迁移取代旧版命令行迁移工具。尽可能贴近现有 YAML 项目的行为,然后进行验证并停止。除非用户要求,否则不要借此进行更广泛的清理。

关键规则

  • 不要让用户运行 nango migrate-to-zero-yaml。
  • 在代码中手动执行迁移。
  • 优先保留现有行为。
  • 除非用户要求或编译迫使你修改,否则不要顺带迁移 lastSyncDate、syncType、trackDeletes 或验证模式。
  • 如果仓库已经是 Zero YAML,则停止迁移,改用常规的 Zero YAML 重构工作流,不要强行迁移。

前提条件

  1. 确认当前位于 Nango 项目根目录,且 nango.yaml 存在。
  2. 在进行破坏性编辑前,确保有回滚途径(git 分支/提交或外部备份)。
  3. 阅读 nango.yaml 并盘点:
    • integrations
    • syncs
    • actions
    • on-event handlers
    • models
  4. 检查这些 YAML 条目所指向的现有 TypeScript 文件。
  5. 保持迁移过程机械化。避免重新设计 API、重命名脚本或更改业务逻辑。

目标最终状态

迁移后的项目应包含:

  • package.json
  • tsconfig.json
  • 根目录下的 models.ts
  • 根目录下的 index.ts
  • 导出 createSync()、createAction() 或 createOnEvent() 的 integration 文件
  • 从 nango 导入 Nango 运行时类型的辅助文件
  • 最终迁移状态中不包含 nango.yaml

迁移工作流

  1. 阅读 nango.yaml 并建立迁移清单。
  2. 创建或更新 Zero YAML 脚手架:
    • package.json
    • tsconfig.json
  3. 根据 YAML 模型生成 models.ts。
  4. 将每个 sync 文件改写为 createSync(...)。
  5. 将每个 action 文件改写为 createAction(...)。
  6. 将每个生命周期处理程序改写为 createOnEvent(...)。
  7. 生成 index.ts,为每个已迁移的脚本添加副作用导入。
  8. 修复辅助文件的导入和小型 TypeScript 错误。
  9. 编译并验证。
  10. 仅在替代项目已就绪,且文件之外仍有回滚途径后,才移除 nango.yaml。

脚手架规则

package.json

如果项目没有 package 文件,请创建一个。如果已有文件,请保留现有字段并添加 Zero YAML 必需项:

  • type: "module"
  • engines.node: ">=20.0"
  • scripts:
    • compile: "nango compile"
    • dev: "nango dev"
  • devDependencies.nango
  • devDependencies.zod

优先保留仓库现有的包管理器和 workspace 字段。

tsconfig.json

使用标准的 Zero YAML TypeScript 配置结构:

{
  "$schema": "https://json.schemastore.org/tsconfig",
  "include": ["index.ts", "**/*.ts"],
  "exclude": ["node_modules", "dist", "build", ".nango"],
  "compilerOptions": {
    "module": "node16",
    "target": "esnext",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "moduleResolution": "node16",
    "exactOptionalPropertyTypes": true,
    "noImplicitOverride": true,
    "noImplicitReturns": true,
    "noPropertyAccessFromIndexSignature": true,
    "noUncheckedIndexedAccess": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "sourceMap": true,
    "noEmit": true
  }
}

生成 models.ts

创建根目录下的 models.ts 文件,将 YAML 模型定义转换为 Zod 模式和导出的推断类型。

使用此模式:

import * as z from 'zod';

export const Ticket = z.object({
    id: z.string(),
    title: z.string()
});

export type Ticket = z.infer<typeof Ticket>;

export const models = {
    Ticket
};

转换规则:

  • string -> z.string()
  • number -> z.number()
  • boolean -> z.boolean()
  • Date -> z.date()
  • any -> z.any();如果需要更安全的回退方案,也可以使用 z.unknown()
  • 可选字段 -> .optional()
  • 数组 -> z.array(...)
  • 嵌套对象 -> 嵌套的 z.object(...)
  • 联合类型 -> z.union([...])
  • 模型引用 -> 复用被引用的模式
  • 动态对象字段 -> z.record(...) 或 .catchall(...)

实用规则:如果旧 YAML 模型难以精确表达,可使用最宽泛且安全、同时仍能让项目编译的模式,以保持迁移进度。只有在需要时才进一步收紧。

按依赖顺序定义模型。如果遇到循环引用,请使用 z.lazy(() => ModelName)。

重写同步

对于每个 YAML 同步,在可能的情况下保留现有文件路径,并将当前默认导出的函数包装在 createSync(...) 中。

按如下方式将 YAML 配置映射到 Zero YAML 配置:

  • description -> description
  • version -> version(缺失时默认为 0.0.1)
  • runs -> frequency
  • auto_start -> autoStart
  • sync_type -> syncType
  • track_deletes -> trackDeletes
  • YAML endpoints -> 从 createSync(...) 中省略;Zero YAML 的 endpoints 字段已弃用
  • scopes -> scopes
  • webhook 订阅 -> webhookSubscriptions
  • YAML input 模型 -> metadata
  • YAML output 模型 -> models
  • 现有默认导出函数体 -> exec

如果同步没有 YAML 输入模型,则将 metadata 默认设为 z.object({}),以保持迁移一致性。

如果文件导出了 onWebhookPayloadReceived,请将该函数移入 createSync(...) 配置并命名为 onWebhook。

使用以下结构:

import { createSync } from 'nango';
import * as z from 'zod';
import { Metadata, Ticket } from '../../models.js';

const sync = createSync({
    description: 'Sync tickets',
    version: '0.0.1',
    frequency: 'every hour',
    autoStart: true,
    syncType: 'full',
    trackDeletes: false,
    metadata: Metadata,
    models: { Ticket },
    exec: async (nango) => {
        // keep existing logic
    }
});

export type NangoSyncLocal = Parameters<typeof sync['exec']>[0];
export default sync;

重写操作

对于每个 YAML 操作,将现有默认导出的函数包装在 createAction(...) 中。

按如下方式映射 YAML 配置:

  • description -> description
  • version -> version(默认为 0.0.1)
  • YAML endpoint -> 从 createAction(...) 中省略;Zero YAML 的 endpoint 字段已弃用
  • input -> input
  • output -> output
  • scopes -> scopes
  • 现有默认导出函数体 -> exec

如果操作没有输入或输出架构,请使用 z.void()。

使用以下结构:

import { createAction } from 'nango';
import * as z from 'zod';
import { CreateTicketInput, CreateTicketOutput } from '../../models.js';

const action = createAction({
    description: 'Create ticket',
    version: '0.0.1',
    input: CreateTicketInput,
    output: CreateTicketOutput,
    exec: async (nango, input) => {
        // keep existing logic
    }
});

export type NangoActionLocal = Parameters<typeof action['exec']>[0];
export default action;

重写事件处理程序

对于每个 YAML 生命周期处理程序,将现有默认导出包装在 createOnEvent(...) 中。

按如下方式映射:

  • 事件名称 -> event
  • description -> 如果已有描述则保留;否则使用 <event> event handler
  • 现有默认导出函数体 -> exec

使用以下结构:

import { createOnEvent } from 'nango';

export default createOnEvent({
    event: 'post-connection-creation',
    description: 'post-connection-creation event handler',
    exec: async (nango) => {
        // keep existing logic
    }
});

导入与类型修正

旧迁移工具还会清理导入。请手动执行相同的操作。

  • 从旧的 models 导入中移除 NangoSync、NangoAction、ProxyConfiguration 和 ActionError。
  • 改为从 nango 导入运行时类型。
  • 保留指向 ../../models.js 或正确相对路径的生成模型导入。
  • 在 index.ts 中使用带 .js 的副作用导入。

重要的机械性修正:

  • 包装文件后,将本地 NangoSync 参数注解替换为 NangoSyncLocal。
  • 包装文件后,将本地 NangoAction 参数注解替换为 NangoActionLocal。
  • 移除以下项目的类型参数:
    • nango.batchSave<T>(...)
    • nango.batchUpdate<T>(...)
    • nango.batchDelete<T>(...)
    • nango.getMetadata<T>()

这些泛型参数在旧格式中通常可以通过编译,但迁移后会显得冗余或不必要。

生成 index.ts

创建根目录下的 index.ts,为每个已迁移脚本添加副作用导入。包含 .js 扩展名。

示例:

import './github/syncs/fetch-issues.js';
import './github/actions/create-issue.js';
import './github/on-events/post-connection-creation.js';

此处不要使用命名导入或默认导入。

清理辅助文件

搜索仓库其余部分,查找已迁移集成入口点之外的 TypeScript 辅助文件。

如果这些文件从旧模型文件导入 Nango 运行时类型,请将这些导入改为从 nango 导入;仅当模型导入用于实际模型架构或类型时,才保留模型导入。

不要重写辅助文件中无关的业务逻辑。

优先保持迁移一致性

手动迁移的行为应与旧 CLI 迁移工具一致:

  • 保留脚本名称
  • 在可能的情况下保留文件位置
  • 保留函数体
  • 保留 syncType
  • 保留 trackDeletes
  • 如果已有 nango.lastSyncDate 用法,则保留

仅当用户明确要求时,才进行第二轮现代化改造。

验证循环

完成机械迁移后:

  • 运行 nango compile
  • 修复明显的 TypeScript/导入/架构问题
  • 运行 nango dryrun <script-name> <connection-id> --validate -e dev --no-interactive --auto-confirm
  • 对于操作,添加 --input '{...}' 或 --input '{}'
  • 如果验证通过,运行 nango dryrun <script-name> <connection-id> --save -e dev --no-interactive --auto-confirm
  • 运行 nango generate:tests && npm test
  • 切勿手动编辑生成的 *.test.json

如果迁移后的同步/操作此时仍需要进行真正的行为重构,请停止,并将其作为单独任务处理。

实用文档

评论

支持 Markdown