mcpField
B
building-nango-functions-remotely

building-nango-functions-remotely

github.com/nangohq开发3125 次安装10 周前更新
代码仓库

关于 building-nango-functions-remotely

此技能指导开发者在无需检出 Nango 项目的情况下,构建和修改 Nango action 与 sync。它强调同步检查点、删除策略以及通过 Nango API 编译、试运行和部署。

主要功能

  1. 01远程编译、试运行与部署函数
  2. 02构建 Nango action 和 sync
  3. 03设计检查点与删除策略
  4. 04遵循输入、架构与运行时约束

适用场景

  1. 01为 Nango 集成实现一次性 action
  2. 02设计可恢复的分页或增量 sync
  3. 03通过 API 验证并部署单文件函数

安装

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

$npx skills add https://github.com/nangohq/skills --skill building-nango-functions-remotely

安装后在 Claude Code 中输入/building-nango-functions-remotely确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
actions.md
api.md
syncs.md

详细介绍

远程构建 Nango 函数

无需检出 Nango 项目,即可通过向 Nango 的 /functions/compile、/functions/dryruns 和 /functions/deployments API 发送单文件 TypeScript 函数,构建 Nango 操作和同步。

实施范围

  • 构建或修改 Nango 函数实现
  • 使用 createAction() 在 Nango 中构建操作
  • 使用 createSync() 在 Nango 中构建同步
  • 使用当前工作流技能处理编译、dryrun、测试和部署机制

同步策略门槛(编写代码前必须完成)

如果任务是同步,请在编写代码前阅读 references/syncs.md,并先说明以下其中一种方案:

  • 检查点方案:
    • 更改源(updated_at、modified_since、更改记录端点、游标、页面令牌、偏移量/页码、since_id 或 webhook)
    • 检查点架构
    • 检查点如何更改提供商请求或恢复状态
    • 请求仍会遍历完整数据集,还是仅返回有更改的行
    • 删除策略
  • 全量刷新阻碍:
    • 文档或示例载荷中明确指出的提供商限制
    • 检查点为何无法奏效

无效的同步实现:

  • 因为更简单而采用全量刷新
  • 使用 saveCheckpoint() 却不使用 getCheckpoint()
  • 读取或保存检查点,却不在请求参数或分页状态中使用它
  • 在新同步中使用 syncType: 'incremental' 或 nango.lastSyncDate
  • 全量刷新没有 checkpoint 架构,或未在每页之后保存检查点——如果执行超出运行时限,运行就会从第 1 页重新开始
  • 仅在还有更多页面时才调用 saveCheckpoint()(例如 if (nextCursor) { await nango.saveCheckpoint(...) })。每个成功的页面都必须调用 saveCheckpoint(),包括最后一页;否则,单页同步会在没有检查点行的情况下到达 clearCheckpoint() 并失败,报错 checkpoint_conflict。
  • 在 clearCheckpoint() 之前调用 trackDeletesEnd(),或完全没有先调用 clearCheckpoint()
  • 对仅返回更改数据的检查点(modified_after、updated_after、更改记录端点)使用 trackDeletesStart() / trackDeletesEnd()。这些请求会省略未更改的行,因此 trackDeletesEnd() 会错误地删除这些行。
  • 在已包含显式删除记录事件的增量同步中使用 trackDeletesStart() / trackDeletesEnd()

选择方案

操作:

  • 一次性、由用户触发,并使用 createAction() 构建的请求
  • 编写代码前阅读 references/actions.md

同步:

  • 定期运行或由 webhook 驱动的缓存更新,使用 createSync() 构建
  • 先完成同步策略门槛
  • 编写代码前阅读 references/syncs.md

必需输入(缺少时询问用户)

始终需要:

  • 集成 ID(提供商名称)
  • 脚本/函数名称(kebab-case)
  • API 参考 URL 或示例响应
  • 如果当前工作流将验证或 dryrun 函数,则需要连接 ID

操作专属:

  • 用例摘要
  • 输入参数
  • 输出字段
  • 如果需要,提供 Metadata JSON
  • 如果当前工作流将验证或 dryrun 操作,则提供测试输入 JSON(无输入操作使用 {})

同步专属:

  • 模型名称(单数、PascalCase)
  • 频率(每小时、每 5 分钟等)
  • 检查点架构(时间戳、游标、页面令牌、偏移量/页码、since_id 或组合值)
  • 检查点如何更改提供商请求或恢复状态
  • 删除策略(删除记录端点/webhook,或说明为何必须全量刷新)
  • 如果提议全量刷新,需提供文档/示例响应中阻碍使用检查点的确切提供商限制
  • 如果需要,提供 Metadata JSON(team_id、workspace_id)

如果缺少任何必需的外部值,请先检查仓库和提供商文档,然后提出有针对性的问题。对于同步,只要提供商支持,就选择检查点和删除策略。如果找不到可行的检查点策略,请在编写全量刷新前明确说明原因。

不可妥协的规则

共享平台约束
  • Nango 函数使用 createAction() / createSync()。
  • 不能添加任意软件包。仅当所选工作流支持时,才使用相对导入;内置模块包括 zod、crypto/node:crypto 和 url/node:url。
  • 在函数代码之外,使用 Nango HTTP API 查询连接、获取凭据和调用代理。不要臆造 CLI 令牌或连接命令。
  • 在每个服务提供商调用上方添加 API 文档链接注释。
  • Action 输出不得超过 2MB。
  • 文件上传和下载无法通过 action 实现(沙盒运行时:没有 fs、没有 axios,输出上限为 2MB)。请改用 {integration}/proxy/ 中的代理脚本,并使用 @nangohq/node——参见 references/actions.md。
  • HTTP 重试默认值为 0;请有意设置 retries。通常最多设为 3;对于 sync 的服务提供商调用,除非文档证明更高值安全且必要,否则实际上禁止设置超过 3。除非 API 支持幂等性,否则避免对非幂等写入进行重试。
  • 不要设置已弃用的函数定义路由字段:action 的 endpoint 和 sync 的 endpoints。通过 SDK/API 按 action 名称触发 action,并通过 records API 获取 sync 记录。
Sync 规则
  • Sync 记录需要稳定的字符串 id。
  • 新建 sync 时应定义 checkpoint 架构,先调用 nango.getCheckpoint(),并在每个页面或批次处理后调用 nango.saveCheckpoint()。
  • 只有在 checkpoint 会改变请求或恢复状态(since、updated_after、cursor、page_token、offset、page、since_id 等)时,它才有效。不使用 checkpoint 却保存 checkpoint,不算增量同步。
  • 新建 sync 不得使用 syncType: 'incremental' 或 nango.lastSyncDate。
  • 默认使用 nango.paginate(...) + nango.batchSave(...)。当 cursor、link 或 offset 分页适用时,避免手动编写 while (true) 循环。
  • 服务提供商返回删除记录、墓碑记录或删除 webhook 时,优先使用 batchDelete()。
  • 只有在服务提供商无法返回变更、删除或恢复状态,或者数据集很小时,才使用全量刷新。
  • 使用全量刷新时,请引用文档或负载中的具体服务提供商限制。“这样更简单”并不足以作为理由。
  • 全量刷新 sync 也需要定义 checkpoint 架构(涵盖页面/游标/偏移量),以记录分页进度,而不仅仅是增量 sync 需要定义。Nango sync 在有时间限制的执行窗口内运行;如果全量刷新没有 checkpoint,那么每次运行超出执行窗口时都会从第 1 页重新开始,浪费计算资源重复获取相同的前几页,并且永远无法到达其余页面。
  • deleteRecordsFromPreviousExecutions() 已弃用。全量刷新时,每次执行都要调用 trackDeletesStart()(安全且幂等——不会覆盖已打开窗口的开始位置),然后在每页处理后调用 saveCheckpoint(),最后一页处理完后调用 clearCheckpoint(),并且仅在 clearCheckpoint() 之后调用 trackDeletesEnd()。
  • 全量刷新中,每次成功处理页面后都要调用 saveCheckpoint(),包括最后一页,并且必须在调用 clearCheckpoint() 之前执行。绝不要以“还有更多页面”为条件来决定是否保存。如果某条独立执行路径完全没有创建 checkpoint(例如没有处理任何页面),则不要在该路径调用 clearCheckpoint();这会在运行时抛出 checkpoint_conflict。此例外不能代替保存终止页面的 checkpoint。
  • 绝不要将 trackDeletesStart() / trackDeletesEnd() 与仅包含变更数据的 checkpoint(modified_after、updated_after、仅返回变更记录的端点等)结合使用。它们会省略未变更的行,因此 trackDeletesEnd() 会将这些行删除。
  • 使用 checkpoint 的全量刷新仍然是全量刷新。仅在完成并清除 checkpoint 的那次运行中调用 trackDeletesEnd()。
  • 如果 sync 需要元数据(例如 team_id、workspace_id、guild_id),请设置 autoStart: false。调用方设置元数据前,sync 无法运行,因此自动启动会导致失败。
约定
  • 字段大小写应与外部 API 保持一致。透传字段保留提供方的大小写;非透传字段采用该 API 的主流大小写风格。
  • 优先使用明确的字段名称。
  • 为 ID、时间戳、枚举值和 URL 添加 .describe() 示例。
  • 避免使用 any;使用内联映射类型。
  • 列表操作应提供 cursor 和一个符合该 API 主流大小写风格的下一游标字段(next_cursor、nextCursor 等)。
  • 仅在需要自定义验证或日志记录时使用 nango.zodValidateInput();否则依靠 Schema 和所选的验证工作流。
Schema 语义
  • 非必填输入默认使用 .optional()。
  • 仅在 null 有意义时使用 .nullable(),通常用于清除更新;如果调用方也可以省略该字段,则同时添加 .optional()。
  • 原始提供方 Schema 应与提供方保持一致:省略字段时使用 .optional(),显式为 null 时使用 .nullable(),仅当提供方确实同时采用这两种方式时才使用 .nullish()。
  • 最终操作输出和规范化同步模型应优先使用 .optional();除非 null 有意义,否则应将上游的 null 规范化为省略。
  • 生成的 Schema 默认应将非必填输入和规范化输出设为 .optional();只有上游契约有充分依据时才放宽限制。
  • 优先使用 .nullable(),而不是 z.union([z.null(), T]) 或 z.union([T, z.null()])。
  • 仅当输出 Schema 允许时才返回 null。
  • z.object() 默认会剔除未知键。对于提供方透传,请使用 z.object({}).passthrough()、z.record(z.unknown()),或仅进行最少细化的 z.unknown()。
字段命名和大小写规则
  • 使用符合 API 主流大小写风格的明确后缀:ID(user_id、userId)、名称(channel_name、channelName)、电子邮件(user_email、userEmail)、URL(callback_url、callbackUrl)和时间戳(created_at、createdAt)。

映射示例(API 要求使用不同的参数名称):

const InputSchema = z.object({
    userId: z.string()
});

const config: ProxyConfiguration = {
    endpoint: 'users.info',
    params: {
        user: input.userId
    },
    retries: 3
};

如果 API 使用 snake_case,请改用 user_id。目标是保持与 API 的一致性。

参考资料

  • 操作模式、CRUD 示例、元数据用法和 ActionError 示例:references/actions.md
  • 同步模式、具体检查点示例、删除策略和完整刷新回退方案:references/syncs.md

实用的 Nango 文档(快速链接)

API 文档无法正常显示时

如果网页抓取返回的文档不完整(由 JavaScript 渲染):

  • 向用户索取一个示例响应
  • 如果工作区中已有 Nango 操作或同步,请参照其模式
  • 使用该技能专用的验证或 dryrun 工作流,直到通过为止

前置条件(编写代码前完成)

  • 无需检出 Nango 项目。
  • 按以下顺序解析 NANGO_SERVER_URL:环境变量、.env 文件,然后回退到 https://api.nango.dev。
  • 调用函数端点前解析 NANGO_SECRET_KEY。
  • 使用与该密钥绑定的环境。
  • 确认密钥具有所需的作用域:编译需要 environment:functions:compile,dryrun 和轮询需要 environment:functions:dryrun,部署需要 environment:deploy。
  • 除非有直接证据表明远程端点接受多文件负载,否则将函数放在一个独立的 TypeScript 文件中。
  • 不要在当前项目/目录中创建或修改任何文件。如果需要创建文件,请使用临时文件夹。

工作流(必需)

  1. 判断这是一个操作还是同步。
  2. 阅读对应的参考文件:references/actions.md 或 references/syncs.md。
  3. 对于同步,检查提供方文档或载荷中的检查点和删除信息,判断端点返回的是完整数据还是变更行,并完成 Sync Strategy Gate。
  4. 收集必需的输入和外部值,包括目标环境的 NANGO_SECRET_KEY,以及 dryrun 所需的任何元数据。
  5. 依次从环境变量、.env 文件和 https://api.nango.dev 获取 NANGO_SERVER_URL,确定主机地址。
  6. 使用 createAction() 或 createSync(),将函数编写或更新为一个独立的 TypeScript 文件。
  7. 使用 POST {host}/functions/compile 进行编译,直到编译通过。
  8. 使用 POST {host}/functions/dryruns 启动 dryrun,并提供目标集成、连接、函数类型、代码,以及所需的任何 input、metadata 或 checkpoint。
  9. 轮询 GET {host}/functions/dryruns/{id},直到 dryrun 状态变为 success 或 failed。
  10. 如果编译或 dryrun 无法通过,则停止并报告缺少的外部状态、输入或 API 契约不匹配问题。
  11. 仅在收到请求时,使用 POST {host}/functions/deployments 启动部署。
  12. 轮询 GET {host}/functions/deployments/{id},直到部署状态变为 success 或 failed。

远程 API 工作流(必需)

进行远程调用前,请先阅读 references/api.md。

必需顺序:

  1. 首先使用 POST /functions/compile 进行编译。
  2. 其次使用 POST /functions/dryruns 启动 dryrun。
  3. 使用 GET /functions/dryruns/{id} 轮询 dryrun 状态,直到进入终态。
  4. 仅在收到请求时,使用 POST /functions/deployments 启动部署。
  5. 使用 GET /functions/deployments/{id} 轮询部署状态,直到进入终态。

规则:

  • 这些端点均为相对路径。始终根据选定的 NANGO_SERVER_URL 解析它们。
  • 发送 Authorization: Bearer <NANGO_SECRET_KEY> 和 Content-Type: application/json。
  • API 密钥所需的权限范围为:编译需要 environment:functions:compile,创建 dryrun 和查询状态需要 environment:functions:dryrun,创建部署和查询状态需要 environment:deploy。
  • 除非 API 文档或现有调用方证明支持,否则不要发送查询参数。
  • 根据服务器返回的验证错误修正载荷。如果 API 拒绝请求,不要臆造未记录的字段。
  • 编译请求仅发送 { "code": "..." }。
  • Dryrun 请求发送 integration_id、function_type、code 和 connection_id。
  • 部署请求发送 type: "function"、integration_id、function_name、function_type 和 code。仅在明确需要时添加 version 或 allow_destructive。
  • 对于操作,仅在需要时于 dryrun 中包含 input 和 metadata。
  • 对于同步,仅在需要模拟恢复运行时,于 dryrun 中包含 metadata 和 checkpoint。新的同步设计中不要加入 last_sync_date。
  • Dryrun 为异步操作。POST /functions/dryruns 会返回一个 id;轮询 GET /functions/dryruns/{id},获取 status、output、result 或 error。不要调用 /functions/dryruns/{id}/result;该端点仅供沙箱内部使用。
  • 部署为异步操作。POST /functions/deployments 会返回一个 id;轮询 GET /functions/deployments/{id},获取 status、deployed、deployed_functions、output 或 error。不要调用 /functions/deployments/{id}/result;该端点仅供沙箱内部使用。
  • 将 waiting 和 running 视为非终态;仅在状态变为 success 或 failed 时停止轮询。
  • 远程 dryrun 不支持 CLI 的 --validate 或 --save;它会在运行前编译,并通过状态端点返回执行结果,但不会记录本地模拟数据。

最终检查清单

操作:

  • 使用了 references/actions.md 中的操作模式
  • Schema 和类型清晰,且函数在一个文件中保持自包含
  • 在需要时,createAction() 包含输入、输出和 scopes;省略已弃用的 endpoint
  • 字段采用透传大小写格式,或遵循 API 中占多数的大小写格式
  • Provider 调用包含 API 文档链接注释和有意设置的重试
  • 对预期失败使用 nango.ActionError
  • 主机地址通过 NANGO_SERVER_URL、.env 或 https://api.nango.dev 确定
  • 使用 POST /functions/compile 编译成功
  • 使用 POST /functions/dryruns 启动 Dryrun
  • 通过 GET /functions/dryruns/{id} 查询,Dryrun 状态达到 success,且输出符合预期
  • 在有要求时,使用 POST /functions/deployments 启动部署
  • 在有要求时,通过 GET /functions/deployments/{id} 查询,部署状态达到 success

同步:

  • 使用了 references/syncs.md 中的同步模式
  • 已定义 Models 映射,ID 为稳定的字符串;除非 null 有意义,否则规范化模型优先使用 .optional()
  • 优先选择增量同步;除非文档或数据载荷明确证明有必要进行全量刷新,否则应提供检查点 Schema
  • 在开始时读取 nango.getCheckpoint(),并在每页或每批处理后运行 nango.saveCheckpoint()
  • 检查点数据会改变 Provider 请求或恢复状态(since、updated_after、cursor、page_token、offset、page、since_id 等)
  • 仅同步变更数据的检查点同步(modified_after、updated_after、变更记录端点)不使用 trackDeletesStart() / trackDeletesEnd()
  • 如果未使用检查点,响应会准确说明为何不存在可行的检查点策略
  • 全量刷新同步具有 checkpoint Schema,会从中恢复分页,并在每页后调用 saveCheckpoint(),以免执行窗口超时后从第 1 页重新开始
  • 仅在调用 clearCheckpoint() 后,全量刷新中的 trackDeletesEnd() 才会运行,且只在完成最后一页的那次运行中执行
  • Provider API 调用使用 retries: 3;没有任何同步重试值超过 3,除非有记录在案的例外
  • 除非远程 API 证明支持多文件,否则函数应在一个文件中保持自包含
  • 主机地址通过 NANGO_SERVER_URL、.env 或 https://api.nango.dev 确定
  • 使用 POST /functions/compile 编译成功
  • 使用 POST /functions/dryruns 启动 Dryrun
  • 通过 GET /functions/dryruns/{id} 查询,Dryrun 状态达到 success,并返回符合预期的变更集
  • 在有要求时,使用 POST /functions/deployments 启动部署
  • 在有要求时,通过 GET /functions/deployments/{id} 查询,部署状态达到 success

评论

支持 Markdown