关于 migrating-to-zero-yaml
面向 Nango 项目的迁移技能,指导将基于 nango.yaml 的配置机械迁移到 Zero YAML,并优先保持现有行为。流程涵盖脚手架、脚本改写和验证。
主要功能
- 01盘点 YAML 配置与关联脚本
- 02生成 Zod 模型和项目脚手架
- 03将同步、操作和事件处理器改写为函数
- 04生成入口导入并修正类型导入
- 05编译、dryrun 与测试验证
适用场景
- 01将旧 Nango 项目迁移到 Zero YAML
- 02保持脚本路径和业务逻辑不变地迁移
- 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 重构工作流,不要强行迁移。
前提条件
- 确认当前位于 Nango 项目根目录,且
nango.yaml存在。 - 在进行破坏性编辑前,确保有回滚途径(git 分支/提交或外部备份)。
- 阅读
nango.yaml并盘点:- integrations
- syncs
- actions
- on-event handlers
- models
- 检查这些 YAML 条目所指向的现有 TypeScript 文件。
- 保持迁移过程机械化。避免重新设计 API、重命名脚本或更改业务逻辑。
目标最终状态
迁移后的项目应包含:
package.jsontsconfig.json- 根目录下的
models.ts - 根目录下的
index.ts - 导出
createSync()、createAction()或createOnEvent()的 integration 文件 - 从
nango导入 Nango 运行时类型的辅助文件 - 最终迁移状态中不包含
nango.yaml
迁移工作流
- 阅读
nango.yaml并建立迁移清单。 - 创建或更新 Zero YAML 脚手架:
package.jsontsconfig.json
- 根据 YAML 模型生成
models.ts。 - 将每个 sync 文件改写为
createSync(...)。 - 将每个 action 文件改写为
createAction(...)。 - 将每个生命周期处理程序改写为
createOnEvent(...)。 - 生成
index.ts,为每个已迁移的脚本添加副作用导入。 - 修复辅助文件的导入和小型 TypeScript 错误。
- 编译并验证。
- 仅在替代项目已就绪,且文件之外仍有回滚途径后,才移除
nango.yaml。
脚手架规则
package.json
如果项目没有 package 文件,请创建一个。如果已有文件,请保留现有字段并添加 Zero YAML 必需项:
type: "module"engines.node: ">=20.0"- scripts:
compile: "nango compile"dev: "nango dev"
devDependencies.nangodevDependencies.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->descriptionversion->version(缺失时默认为0.0.1)runs->frequencyauto_start->autoStartsync_type->syncTypetrack_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->descriptionversion->version(默认为0.0.1)- YAML
endpoint-> 从createAction(...)中省略;Zero YAML 的endpoint字段已弃用 input->inputoutput->outputscopes->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
如果迁移后的同步/操作此时仍需要进行真正的行为重构,请停止,并将其作为单独任务处理。
实用文档
- Zero YAML 迁移文档:https://www.nango.dev/docs/implementation-guides/platform/migrations/migrate-to-zero-yaml
- 测试:https://www.nango.dev/docs/implementation-guides/platform/functions/testing
- Functions SDK:https://www.nango.dev/docs/reference/functions
- Checkpoints 迁移:https://www.nango.dev/docs/implementation-guides/platform/migrations/migrate-to-checkpoints
- 删除检测:https://www.nango.dev/docs/implementation-guides/use-cases/syncs/deletion-detection