building-nango-functions-locally
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseBuild Nango Functions Locally
本地构建Nango Functions
Build deployable Nango actions and syncs in a checked-out Nango project with the local CLI validation and test workflow.
在已检出的Nango项目中,通过本地CLI验证和测试工作流构建可部署的Nango action和sync。
When to use
适用场景
- User wants to build or modify a Nango function
- User wants to build an action in Nango
- User wants to build a sync in Nango
- 用户需要构建或修改Nango函数
- 用户需要在Nango中构建action
- 用户需要在Nango中构建sync
Sync Strategy Gate (required before writing code)
同步策略门槛(编写代码前必须完成)
If the task is a sync, read before writing code and state one of these paths first:
references/syncs.md- Checkpoint plan:
- change source (,
updated_at, changed-records endpoint, cursor, page token, offset/page,modified_since, or webhook)since_id - checkpoint schema
- how the checkpoint changes the provider request or resume state
- whether the request still walks the full dataset or returns changed rows only
- delete strategy
- change source (
- Full refresh blocker:
- exact provider limitation from the docs or sample payloads
- why checkpoints cannot work here
Invalid sync implementations:
- full refresh because it is simpler
- without
saveCheckpoint()getCheckpoint() - reading or saving a checkpoint without using it in request params or pagination state
- using or
syncType: 'incremental'in a new syncnango.lastSyncDate - using /
trackDeletesStart()with a changed-only checkpoint (trackDeletesEnd(),modified_after, changed-records endpoint). Those requests omit unchanged rows, soupdated_afterwill falsely delete them.trackDeletesEnd() - using /
trackDeletesStart()in an incremental sync that already has explicit deleted-record eventstrackDeletesEnd()
如果当前任务是开发sync,请先阅读,并优先明确以下两种路径之一:
references/syncs.md- 检查点方案:
- 变更源(、
updated_at、变更记录端点、cursor、page token、offset/page、modified_since或webhook)since_id - 检查点schema
- 检查点如何修改provider请求或恢复状态
- 请求是遍历全量数据集还是仅返回变更行
- 删除策略
- 变更源(
- 全量刷新阻塞说明:
- 来自文档或示例payload的明确provider限制
- 检查点无法生效的原因
无效的sync实现:
- 仅因为更简单就使用全量刷新
- 只调用但不调用
saveCheckpoint()getCheckpoint() - 读取或保存检查点,但未在请求参数或分页状态中使用
- 新sync中使用或
syncType: 'incremental'nango.lastSyncDate - 配合仅返回变更的检查点(、
modified_after、变更记录端点)使用updated_after/trackDeletesStart():这类请求会忽略未变更的行,导致trackDeletesEnd()误删这些数据trackDeletesEnd() - 在已经有显式删除记录事件的增量sync中使用/
trackDeletesStart()trackDeletesEnd()
Choose the Path
选择开发路径
Action:
- One-time request, user-triggered, built with
createAction() - Read before writing code
references/actions.md
Sync:
- Scheduled or webhook-driven cache updates built with
createSync() - Complete the Sync Strategy Gate first
- Read before writing code
references/syncs.md
Action:
- 单次请求、用户触发,使用构建
createAction() - 编写代码前请阅读
references/actions.md
Sync:
- 定时或webhook驱动的缓存更新,使用构建
createSync() - 优先完成同步策略门槛校验
- 编写代码前请阅读
references/syncs.md
Required Inputs (Ask User if Missing)
所需输入(缺失时请询问用户)
Always:
- Integration ID (provider name)
- Connection ID (for validation or dryrun)
- Script/function name (kebab-case)
- API reference URL or sample response
Action-specific:
- Use case summary
- Input parameters
- Output fields
- Metadata JSON if required
- Test input JSON for validation/dryrun (required; use for no-input actions)
{}
Sync-specific:
- Model name (singular, PascalCase)
- Frequency (every hour, every 5 minutes, etc.)
- Checkpoint schema (timestamp, cursor, page token, offset/page, , or composite)
since_id - How the checkpoint changes the provider request or resume state
- Delete strategy (deleted-record endpoint/webhook, or why full refresh is required)
- If proposing a full refresh, the exact provider limitation that blocks checkpoints from the docs/sample response
- Metadata JSON if required (team_id, workspace_id)
If any required external values are missing, ask a targeted question after checking the repo and provider docs. For syncs, choose a checkpoint plus deletion strategy whenever the provider supports one. If you cannot find a viable checkpoint strategy, state exactly why before writing a full refresh.
通用要求:
- 集成ID(provider名称)
- 连接ID(用于验证或dryrun)
- 脚本/函数名称(kebab-case格式)
- API参考文档链接或示例响应
Action专属要求:
- 使用场景摘要
- 输入参数
- 输出字段
- 所需的Metadata JSON
- 用于验证/dryrun的测试输入JSON(必填,无输入的action使用)
{}
Sync专属要求:
- 模型名称(单数,PascalCase格式)
- 运行频率(每小时、每5分钟等)
- 检查点schema(timestamp、cursor、page token、offset/page、或复合类型)
since_id - 检查点如何修改provider请求或恢复状态
- 删除策略(删除记录端点/webhook,或需要全量刷新的原因)
- 如果计划使用全量刷新,需提供来自文档/示例响应的、明确阻塞检查点使用的provider限制
- 所需的Metadata JSON(team_id、workspace_id等)
如果缺少任何必填的外部值,请先检查仓库和provider文档,再针对性询问用户。对于sync,只要provider支持,就优先选择检查点加删除策略。如果找不到可行的检查点策略,在编写全量刷新逻辑前请明确说明原因。
Non-Negotiable Rules
不可违反的规则
Shared platform constraints
共享平台约束
- Nango functions use /
createAction().createSync() - You cannot add arbitrary packages. Use relative imports only when the chosen workflow supports them; built-ins include ,
zod/crypto, andnode:crypto/url.node:url - Use the Nango HTTP API for connection lookup, credentials, and proxy calls outside function code. Do not invent CLI token or connection commands.
- Add an API doc link comment above each provider call.
- Action outputs cannot exceed 2MB.
- HTTP retries default to ; set
0deliberately, especially for writes.retries
- Nango函数必须使用/
createAction()createSync() - 不能随意添加依赖包。仅在所选工作流支持时使用相对导入;内置依赖包括、
zod/crypto、node:crypto/urlnode:url - 函数代码外的连接查询、凭证获取、代理调用需使用Nango HTTP API,不要自行创建CLI token或连接命令
- 每个provider调用上方都要添加API文档链接注释
- Action输出不能超过2MB
- HTTP重试默认值为,请显式设置
0值,写操作尤其需要注意retries
Sync rules
Sync规则
- Sync records need a stable string .
id - New syncs should define a schema, call
checkpointfirst, andnango.getCheckpoint()after each page or batch.nango.saveCheckpoint() - A checkpoint is valid only if it changes the request or resume state (,
since,updated_after,cursor,page_token,offset,page, etc.). Saving one without using it is not incremental sync.since_id - New syncs must not use or
syncType: 'incremental'.nango.lastSyncDate - Default to +
nango.paginate(...). Avoid manualnango.batchSave(...)loops whenwhile (true),cursor, orlinkpagination fits.offset - Prefer when the provider returns deletions, tombstones, or delete webhooks.
batchDelete() - Use full refresh only if the provider cannot return changes, deletions, or resume state, or if the dataset is tiny.
- For full refresh, cite the exact provider limitation from docs or payloads. "It is easier" is not enough.
- is deprecated. For full refresh, call
deleteRecordsFromPreviousExecutions()before fetch/save andtrackDeletesStart()only after a successful full fetch/save.trackDeletesEnd() - Never combine /
trackDeletesStart()with changed-only checkpoints (trackDeletesEnd(),modified_after, changed-records endpoints, etc.). They omit unchanged rows, soupdated_afterwould delete them.trackDeletesEnd() - Checkpointed full refreshes are still full refreshes. Call only in the run that finishes the full window.
trackDeletesEnd()
- Sync记录需要有稳定的字符串类型
id - 新sync需要定义schema,首先调用
checkpoint,每处理完一页或一批数据后调用nango.getCheckpoint()nango.saveCheckpoint() - 只有当检查点会修改请求或恢复状态(、
since、updated_after、cursor、page_token、offset、page等)时才有效,只保存不使用不属于增量同步since_id - 新sync禁止使用或
syncType: 'incremental'nango.lastSyncDate - 优先使用+
nango.paginate(...),如果nango.batchSave(...)、cursor或link分页适配,避免手动编写offset循环while (true) - 当provider返回删除记录、逻辑删除标记或删除webhook时,优先使用
batchDelete() - 仅当provider无法返回变更、删除数据或恢复状态,或数据集极小时才使用全量刷新
- 使用全量刷新时,需要引用来自文档或payload的明确provider限制,「更简单」不能作为理由
- 已废弃。全量刷新场景下,在拉取/保存数据前调用
deleteRecordsFromPreviousExecutions(),仅在全量拉取/保存成功后调用trackDeletesStart()trackDeletesEnd() - 禁止配合仅返回变更的检查点(、
modified_after、变更记录端点等)使用updated_after/trackDeletesStart():这类请求会忽略未变更的行,导致trackDeletesEnd()误删这些数据trackDeletesEnd() - 带检查点的全量刷新仍然属于全量刷新,仅在完成全量窗口的运行中调用
trackDeletesEnd()
Conventions
开发规范
- Match field casing to the external API. Passthrough fields keep provider casing; non-passthrough fields should use the majority casing of that API.
- Prefer explicit field names.
- Add examples for IDs, timestamps, enums, and URLs.
.describe() - Avoid ; use inline mapping types.
any - Prefer static Nango endpoint paths (avoid /
:idin the exposed endpoint); pass IDs in input or params.{id} - List actions should expose plus a next-cursor field in the majority casing of that API (
cursor,next_cursor, etc.).nextCursor - Use only when you need custom validation or logging; otherwise rely on schemas plus the chosen validation workflow.
nango.zodValidateInput()
- 字段大小写要与外部API保持一致:透传字段保留provider的大小写;非透传字段使用对应API的主流大小写规范
- 优先使用含义明确的字段名
- 为ID、时间戳、枚举、URL添加示例
.describe() - 避免使用,使用内联映射类型
any - 优先使用静态Nango端点路径(暴露的端点中避免使用/
:id),通过输入或参数传递ID{id} - 列表类action需要暴露以及对应API主流大小写格式的下一页游标字段(
cursor、next_cursor等)nextCursor - 仅当需要自定义验证或日志时使用,其他情况下依赖schema和所选验证工作流
nango.zodValidateInput()
Schema Semantics
Schema语义规范
- Default non-required inputs to .
.optional() - Use only when
.nullable()has meaning, usually clear-on-update; addnullwhen callers may omit the field too..optional() - Raw provider schemas should match the provider: for omitted fields,
.optional()for explicit.nullable(),nullonly when the provider truly does both..nullish() - Final action outputs and normalized sync models should prefer and normalize upstream
.optional()to omission unlessnullmatters.null - Default generated schemas to for non-required inputs and normalized outputs; widen only when the upstream contract justifies it.
.optional() - Prefer over
.nullable()orz.union([z.null(), T]).z.union([T, z.null()]) - Return only when the output schema allows it.
null - strips unknown keys by default. For provider pass-through use
z.object(),z.object({}).passthrough(), orz.record(z.unknown())with minimal refinements.z.unknown()
- 非必填输入默认添加
.optional() - 仅当有明确含义时(通常是更新时清空字段)使用
null;如果调用方可能省略该字段,同时添加.nullable().optional() - 原始provider schema要与provider行为匹配:省略的字段用,显式返回
.optional()的字段用null,仅当provider确实会同时返回两种情况时使用.nullable().nullish() - 最终的action输出和标准化的sync模型优先使用,将上游
.optional()标准化为省略该字段,除非null有明确业务含义null - 生成的schema默认对非必填输入和标准化输出使用,仅当上游契约有明确要求时放宽限制
.optional() - 优先使用而非
.nullable()或z.union([z.null(), T])z.union([T, z.null()]) - 仅当输出schema允许时才返回
null - 默认会移除未知键,provider透传场景下使用
z.object()、z.object({}).passthrough()或带最小化校验的z.record(z.unknown())z.unknown()
Field Naming and Casing Rules
字段命名与大小写规则
- Use explicit suffixes in the API's majority casing: IDs (,
user_id), names (userId,channel_name), emails (channelName,user_email), URLs (userEmail,callback_url), and timestamps (callbackUrl,created_at).createdAt
Mapping example (API expects a different parameter name):
typescript
const InputSchema = z.object({
userId: z.string()
});
const config: ProxyConfiguration = {
endpoint: 'users.info',
params: {
user: input.userId
},
retries: 3
};If the API is snake_case, use instead. The goal is API consistency.
user_id- 使用对应API主流大小写格式的明确后缀:ID(、
user_id)、名称(userId、channel_name)、邮箱(channelName、user_email)、URL(userEmail、callback_url)、时间戳(callbackUrl、created_at)createdAt
映射示例(API期望的参数名与输入字段名不同):
typescript
const InputSchema = z.object({
userId: z.string()
});
const config: ProxyConfiguration = {
endpoint: 'users.info',
params: {
user: input.userId
},
retries: 3
};如果API使用snake_case,则替换为,目标是保持API一致性。
user_idReferences
参考资料
- Action patterns, CRUD examples, metadata usage, and ActionError examples:
references/actions.md - Sync patterns, concrete checkpoint examples, delete strategies, and full refresh fallback:
references/syncs.md
- Action模式、CRUD示例、Metadata用法、ActionError示例:
references/actions.md - Sync模式、具体检查点示例、删除策略、全量刷新 fallback:
references/syncs.md
Useful Nango docs (quick links)
实用Nango文档(快速链接)
- Functions runtime SDK reference: https://nango.dev/docs/reference/functions
- Implement an action: https://nango.dev/docs/implementation-guides/use-cases/actions/implement-an-action
- Implement a sync: https://nango.dev/docs/implementation-guides/use-cases/syncs/implement-a-sync
- Checkpoints: https://nango.dev/docs/implementation-guides/use-cases/syncs/checkpoints
- Deletion detection (full vs incremental): https://nango.dev/docs/implementation-guides/use-cases/syncs/deletion-detection
- Testing integrations (dryrun, , Vitest): https://nango.dev/docs/implementation-guides/platform/functions/testing
--save - Nango HTTP API reference: https://nango.dev/docs/reference/api
- 函数运行时SDK参考:https://nango.dev/docs/reference/functions
- 实现action:https://nango.dev/docs/implementation-guides/use-cases/actions/implement-an-action
- 实现sync:https://nango.dev/docs/implementation-guides/use-cases/syncs/implement-a-sync
- 检查点:https://nango.dev/docs/implementation-guides/use-cases/syncs/checkpoints
- 删除检测(全量 vs 增量):https://nango.dev/docs/implementation-guides/use-cases/syncs/deletion-detection
- 测试集成(dryrun、、Vitest):https://nango.dev/docs/implementation-guides/platform/functions/testing
--save - Nango HTTP API参考:https://nango.dev/docs/reference/api
When API Docs Do Not Render
API文档无法正常渲染时的处理
If web fetching returns incomplete docs (JS-rendered):
- Ask the user for a sample response
- Use existing Nango actions or syncs in the workspace as a pattern when they exist
- Use the skill-specific validation or dryrun workflow until it passes
如果网页抓取返回的文档不完整(JS渲染的内容):
- 请用户提供示例响应
- 如果工作区已有可用的Nango action或sync,可以参考其模式
- 使用对应技能的验证或dryrun工作流直到通过
Workflow (required)
工作流(必须执行)
- Decide whether this is an action or a sync.
- Read the matching reference file: or
references/actions.md.references/syncs.md - For syncs, inspect provider docs or payloads for checkpoints and deletes, decide whether the endpoint returns full data or changed rows, and complete the Sync Strategy Gate.
- Gather required inputs and external values. For connection lookup, credentials, or discovery, use the Nango HTTP API.
- Confirm this is a Zero YAML TypeScript project () and that you are in the Nango root (
no nango.yamlexists)..nango/ - Create or update the function under or
{integrationId}/actions/, apply the shared schema and casing rules, then register it in{integrationId}/syncs/.index.ts - Validate with .
nango dryrun ... --validate -e dev --no-interactive --auto-confirm - If validation cannot pass, stop and report the missing external state or inputs.
- After validation passes, run , then
nango dryrun ... --save, thennango generate:tests.npm test - Deploy with only when requested.
nango deploy dev
- 确定开发类型是action还是sync
- 阅读对应的参考文档:或
references/actions.mdreferences/syncs.md - 对于sync,查阅provider文档或payload确认检查点和删除逻辑,确定端点返回全量数据还是变更行,完成同步策略门槛校验
- 收集所需输入和外部值,连接查询、凭证获取或发现逻辑使用Nango HTTP API
- 确认当前是Zero YAML TypeScript项目(无),且处于Nango根目录(存在
nango.yaml文件夹).nango/ - 在或
{integrationId}/actions/下创建或更新函数,遵循共享schema和大小写规则,然后在{integrationId}/syncs/中注册index.ts - 使用进行验证
nango dryrun ... --validate -e dev --no-interactive --auto-confirm - 如果验证无法通过,停止并上报缺失的外部状态或输入
- 验证通过后,运行,然后运行
nango dryrun ... --save,再运行nango generate:testsnpm test - 仅当用户要求时,使用部署
nango deploy dev
Preconditions (Do Before Writing Code)
前置条件(编写代码前完成)
Confirm TypeScript Project (No nango.yaml
)
nango.yaml确认是TypeScript项目(无nango.yaml
)
nango.yamlThis skill only supports TypeScript projects using / .
createAction()createSync()bash
ls nango.yaml 2>/dev/null && echo "YAML PROJECT DETECTED" || echo "OK - No nango.yaml"If you see :
YAML PROJECT DETECTED- Stop immediately.
- Tell the user to upgrade to the TypeScript format first.
- Do not attempt to mix YAML and TypeScript.
本技能仅支持使用 / 的TypeScript项目
createAction()createSync()bash
ls nango.yaml 2>/dev/null && echo "YAML PROJECT DETECTED" || echo "OK - No nango.yaml"如果输出:
YAML PROJECT DETECTED- 立即停止操作
- 告知用户需要先升级到TypeScript格式
- 不要尝试混合使用YAML和TypeScript
Verify Nango Project Root
验证Nango项目根目录
Do not create files until you confirm the Nango root:
bash
ls -la .nango/ 2>/dev/null && pwd && echo "IN NANGO PROJECT ROOT" || echo "NOT in Nango root"If you see :
NOT in Nango root- into the directory that contains
cd.nango/ - Re-run the check
- Do not use absolute paths as a workaround
All file paths must be relative to the Nango root. Creating files with extra prefixes while already in the Nango root will create nested directories that break the build.
确认处于Nango根目录前不要创建文件:
bash
ls -la .nango/ 2>/dev/null && pwd && echo "IN NANGO PROJECT ROOT" || echo "NOT in Nango root"如果输出:
NOT in Nango root- 到包含
cd的目录.nango/ - 重新执行校验
- 不要使用绝对路径作为变通方案
所有文件路径必须是相对于Nango根目录的相对路径。如果已经在Nango根目录下却添加额外路径前缀,会创建嵌套目录导致构建失败。
Project Structure and Naming
项目结构与命名规范
text
./
|-- .nango/
|-- index.ts
|-- hubspot/
| |-- actions/
| | `-- create-contact.ts
| `-- syncs/
| `-- fetch-contacts.ts
`-- slack/
`-- actions/
`-- post-message.ts- Provider directories: lowercase (,
hubspot)slack - Action files: kebab-case ()
create-contact.ts - Sync files: kebab-case (many teams use a prefix, but it is optional)
fetch- - One function per file
- All actions and syncs must be imported in
index.ts
text
./
|-- .nango/
|-- index.ts
|-- hubspot/
| |-- actions/
| | `-- create-contact.ts
| `-- syncs/
| `-- fetch-contacts.ts
`-- slack/
`-- actions/
`-- post-message.ts- Provider目录:全小写(、
hubspot)slack - Action文件:kebab-case格式()
create-contact.ts - Sync文件:kebab-case格式(很多团队会使用前缀,非强制)
fetch- - 每个文件仅包含一个函数
- 所有action和sync都必须在中导入
index.ts
Register scripts in index.ts
(required)
index.ts在index.ts
中注册脚本(必填)
index.tsUse side-effect imports only. Include the extension.
.jstypescript
// index.ts
import './github/actions/get-top-contributor.js';
import './github/syncs/fetch-issues.js';Symptom of incorrect registration: the file compiles but you see or the function never appears.
No entry points found in index.ts...仅使用副作用导入,包含后缀
.jstypescript
// index.ts
import './github/actions/get-top-contributor.js';
import './github/syncs/fetch-issues.js';注册错误的表现:文件编译成功,但提示或函数始终不显示
No entry points found in index.ts...Dryrun, Mocks, and Tests (required)
Dryrun、Mock与测试(必须执行)
Required loop:
- Run until it passes.
nango dryrun ... --validate -e dev --no-interactive --auto-confirm - Actions: always pass (use
--input '{...}'for no-input actions).--input '{}' - Syncs: use when you need to simulate a resumed run.
--checkpoint '{...}' - If validation cannot pass, stop and state the missing external state or inputs required.
- After validation passes, run to generate
nango dryrun ... --save -e dev --no-interactive --auto-confirm.<script-name>.test.json - Run , then
nango generate:tests.npm test
Hard rules:
- Treat as generated output. Never create, edit, rename, or move it.
<script-name>.test.json - If mocks are wrong or stale, fix the code and re-record with .
--save - Do not hard-code error payloads in ; use a Vitest test with
*.test.jsonfor 404, 401, 429, or timeout cases.vi.spyOn(...) - Connection ID is the second positional argument; do not use .
--connection-id - Use when script names overlap across integrations.
--integration-id <integration-id> - Prefer for new incremental syncs;
--checkpointis a legacy pattern.--lastSyncDate - If is not on
nango, usePATH.npx nango ... - CLI upgrade prompts can block automation; set if needed.
NANGO_CLI_UPGRADE_MODE=ignore
必填循环流程:
- 运行直到通过
nango dryrun ... --validate -e dev --no-interactive --auto-confirm - Action:必须传入(无输入的action使用
--input '{...}')--input '{}' - Sync:需要模拟恢复运行时使用
--checkpoint '{...}' - 如果验证无法通过,停止并说明所需的缺失外部状态或输入
- 验证通过后,运行生成
nango dryrun ... --save -e dev --no-interactive --auto-confirm<script-name>.test.json - 运行,然后运行
nango generate:testsnpm test
硬性规则:
- 将视为生成产物,永远不要手动创建、编辑、重命名或移动
<script-name>.test.json - 如果mock错误或过时,修复代码后使用重新录制
--save - 不要在中硬编码错误payload,404、401、429或超时场景使用带
*.test.json的Vitest测试vi.spyOn(...) - 连接ID是第二个位置参数,不要使用
--connection-id - 不同集成的脚本名称重复时使用
--integration-id <integration-id> - 新增量sync优先使用,
--checkpoint是旧模式--lastSyncDate - 如果不在
nango中,使用PATHnpx nango ... - CLI升级提示会阻塞自动化流程,必要时设置
NANGO_CLI_UPGRADE_MODE=ignore
Deploy (Optional)
部署(可选)
Deploy functions to an environment in your Nango account:
bash
nango deploy dev将函数部署到Nango账号的指定环境:
bash
nango deploy devDeploy only one function
仅部署单个函数
nango deploy --action <action-name> dev
nango deploy --sync <sync-name> dev
Reference: https://nango.dev/docs/implementation-guides/use-cases/actions/implement-an-actionnango deploy --action <action-name> dev
nango deploy --sync <sync-name> dev
参考:https://nango.dev/docs/implementation-guides/use-cases/actions/implement-an-actionFinal Checklists
最终检查清单
Action:
- Nango root verified
- was used for the action pattern
references/actions.md - Schemas and types are clear, and missing-value rules match the provider versus normalized contract
- includes endpoint, input, output, and scopes when required
createAction() - Fields use passthrough casing or the API's majority casing
- Provider call includes an API doc link comment and intentional retries
- is used for expected failures
nango.ActionError - Registered in
index.ts - Dryrun succeeds with
--validate -e dev --no-interactive --auto-confirm --input '{...}' - was generated by
<action-name>.test.jsonafternango dryrun ... --save--validate - ran and
nango generate:testspassesnpm test
Sync:
- Nango root verified
- was used for the sync pattern
references/syncs.md - Models map is defined, ids are stable strings, and normalized models prefer unless
.optional()mattersnull - Incremental was chosen first, with a checkpoint schema unless full refresh is explicitly justified from docs or payloads
- is read at the start and
nango.getCheckpoint()runs after each page or batchnango.saveCheckpoint() - Checkpoint data changes the provider request or resume state (,
since,updated_after,cursor,page_token,offset,page, etc.)since_id - Changed-only checkpoint syncs (,
modified_after, changed-records endpoint) do not useupdated_after/trackDeletesStart()trackDeletesEnd() - If checkpoints were not used, the response explains exactly why no viable checkpoint strategy exists
- Raw provider schemas model omitted versus correctly, and fields use passthrough casing or the API's majority casing
null - is used unless the API truly cannot fit Nango's paginator
nango.paginate() - Deletion strategy matches the sync type: for incremental only when the provider returns explicit deletions; otherwise full-refresh fallback uses
batchDelete()before fetch/save andtrackDeletesStart()only after a successful full fetch plus savetrackDeletesEnd() - Metadata handled if required
- Registered in
index.ts - Dryrun succeeds with
--validate -e dev --no-interactive --auto-confirm - was generated by
<sync-name>.test.jsonafternango dryrun ... --save--validate - ran and
nango generate:testspassesnpm test
Action:
- 已验证Nango根目录
- 已参考实现action模式
references/actions.md - Schema和类型定义清晰,缺失值规则符合provider与标准化契约的要求
- 包含端点、输入、输出,以及所需的权限范围
createAction() - 字段使用透传大小写或API的主流大小写规范
- Provider调用包含API文档链接注释和显式设置的重试次数
- 预期失败场景使用处理
nango.ActionError - 已在中注册
index.ts - 执行成功
nango dryrun ... --validate -e dev --no-interactive --auto-confirm --input '{...}' - 是验证通过后通过
<action-name>.test.json生成的nango dryrun ... --save - 已运行且
nango generate:tests通过npm test
Sync:
- 已验证Nango根目录
- 已参考实现sync模式
references/syncs.md - 已定义模型映射,id是稳定的字符串,标准化模型优先使用除非
.optional()有明确含义null - 优先选择增量同步,带有检查点schema,除非文档或payload明确证明只能使用全量刷新
- 运行开始时调用,每处理完一页或一批数据后调用
nango.getCheckpoint()nango.saveCheckpoint() - 检查点数据会修改provider请求或恢复状态(、
since、updated_after、cursor、page_token、offset、page等)since_id - 仅返回变更的检查点sync(、
modified_after、变更记录端点)未使用updated_after/trackDeletesStart()trackDeletesEnd() - 如果未使用检查点,已明确说明不存在可行检查点策略的原因
- 原始provider schema正确区分字段省略和,字段使用透传大小写或API的主流大小写规范
null - 除非API确实无法适配Nango的分页器,否则使用
nango.paginate() - 删除策略与sync类型匹配:增量同步仅当provider返回显式删除记录时使用;否则全量刷新 fallback 在拉取/保存前调用
batchDelete(),仅在全量拉取+保存成功后调用trackDeletesStart()trackDeletesEnd() - 已按要求处理Metadata
- 已在中注册
index.ts - 执行成功
nango dryrun ... --validate -e dev --no-interactive --auto-confirm - 是验证通过后通过
<sync-name>.test.json生成的nango dryrun ... --save - 已运行且
nango generate:tests通过npm test