nango-function-builder について
デプロイ可能な Nango の TypeScript アクションと sync を作成・検証するスキルです。プロジェクト構成の確認や sync のチェックポイントと削除戦略の明示を求め、デプロイ前の dryrun とテストを定めています。
主な機能
- 01Nango アクションと sync の作成
- 02sync のチェックポイントと削除戦略の策定
- 03TypeScript プロジェクト構成と登録の確認
- 04Nango dryrun による関数の検証
- 05デプロイ前のテスト生成と実行
活用シーン
- 01プロバイダー API 呼び出し用アクションの作成
- 02定期実行または webhook 駆動の sync 構築
- 03Zero YAML TypeScript プロジェクト内の関数変更
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ nangohq/ skills --skill nango-function-builderインストール後、Claude Code で/nango-function-builderを入力して読み込まれたか確認します。
同梱ファイルreferences/actions.mdreferences/syncs.md
詳細
Nango 関数ビルダー
再現性のあるパターンと検証手順を使って、デプロイ可能な Nango 関数(アクションと同期)を構築します。
使用する場合
- ユーザーが Nango 関数の構築または変更を希望している場合
- ユーザーが Nango でアクションを構築したい場合
- ユーザーが Nango で同期を構築したい場合
同期戦略ゲート(コードを書く前に必須)
タスクが同期の場合は、コードを書く前に references/syncs.md を読み、まず次のいずれかの方針を示します。
- チェックポイント計画:
- 変更ソース(
updated_at、modified_since、変更レコード用エンドポイント、カーソル、ページトークン、オフセット/ページ、since_id、または Webhook) - チェックポイントのスキーマ
- チェックポイントによってプロバイダーへのリクエストまたは再開状態がどのように変わるか
- リクエストが引き続きデータセット全体を走査するのか、変更された行のみを返すのか
- 削除戦略
- 変更ソース(
- 全件更新が必要な理由:
- ドキュメントまたはサンプルペイロードに記載された、プロバイダー側の具体的な制約
- チェックポイントが機能しない理由
無効な同期の実装:
- より簡単だからという理由で全件更新する
getCheckpoint()を使わずにsaveCheckpoint()を使う- チェックポイントを読み取る、または保存するものの、リクエストパラメーターやページネーション状態に利用しない
- 新しい同期で
syncType: 'incremental'またはnango.lastSyncDateを使う - 変更のみを対象とするチェックポイント(
modified_after、updated_after、変更レコード用エンドポイント)を使いながらtrackDeletesStart()/trackDeletesEnd()を使う。これらのリクエストでは変更されていない行が省かれるため、trackDeletesEnd()はそれらを誤って削除します。 - 削除レコードの明示的なイベントがすでにあるインクリメンタル同期で
trackDeletesStart()/trackDeletesEnd()を使う
パスを選択する
アクション:
- ユーザーが実行する単発のリクエストで、
createAction()を使って構築します - コードを書く前に
references/actions.mdを読みます
同期:
createSync()を使って構築する、スケジュール実行または Webhook 駆動のキャッシュ更新です- まず同期戦略ゲートを完了します
- コードを書く前に
references/syncs.mdを読みます
ワークフロー(推奨)
- アクションと同期のどちらに該当するか判断します。
- 対応するリファレンスファイル
references/actions.mdまたはreferences/syncs.mdを読みます。 - 同期の場合は、プロバイダーのドキュメントまたはペイロードを確認してチェックポイントと削除の方法を調べ、エンドポイントが全データを返すのか変更された行のみを返すのかを判断し、同期戦略ゲートを完了します。
- 必要な入力と外部値を収集します。接続の検索、認証情報、または検出には Nango HTTP API を使います。
- Zero YAML TypeScript プロジェクト(
no nango.yaml)であり、Nango のルート(.nango/が存在する場所)にいることを確認します。 {integrationId}/actions/または{integrationId}/syncs/の下に関数を作成または更新し、ここに記載されているスキーマと大文字・小文字の規則を適用してから、index.tsに登録します。nango dryrun ... --validate -e dev --no-interactive --auto-confirmで検証します。- 検証に合格できない場合は、そこで止め、不足している外部状態または入力を報告します。
- 検証に合格したら、
nango dryrun ... --save、続けてnango generate:tests、最後にnpm testを実行します。 - 要求された場合に限り、
nango deploy devでデプロイします。
必須の入力情報(不足している場合はユーザーに確認)
常に必要:
- Integration ID(プロバイダー名)
- Connection ID(dryrun 用)
- スクリプト名(kebab-case)
- API リファレンスの URL またはサンプルレスポンス
アクション固有:
- ユースケースの概要
- 入力パラメーター
- 出力フィールド
- 必要な場合は Metadata JSON
- dryrun
--inputおよびモック用のテスト入力 JSON(必須。入力のないアクションには{}を使用)
同期固有:
- モデル名(単数形、PascalCase)
- 頻度(1 時間ごと、5 分ごとなど)
- チェックポイントのスキーマ(timestamp、cursor、page token、offset/page、
since_id、または複合形式) - チェックポイントによってプロバイダーへのリクエストまたは再開状態がどう変化するか
- 削除戦略(削除済みレコードのエンドポイント/webhook、または全件更新が必要な理由)
- 全件更新を提案する場合、チェックポイントを妨げるドキュメント/サンプルレスポンス上のプロバイダーの具体的な制約
- 必要な場合は Metadata JSON(team_id、workspace_id)
必須の外部情報が不足している場合は、リポジトリとプロバイダーのドキュメントを確認したうえで、対象を絞った質問をしてください。同期では、プロバイダーが対応している場合は必ずチェックポイントと削除戦略を選択してください。実行可能なチェックポイント戦略が見つからない場合は、全件更新のコードを書く前に、その理由を具体的に説明してください。
前提条件(コードを書く前に実施)
TypeScript プロジェクトであることを確認する(nango.yaml がないこと)
このスキルが対応するのは、createAction()/createSync() を使用する TypeScript プロジェクトのみです。
ls nango.yaml 2>/dev/null && echo "YAML PROJECT DETECTED" || echo "OK - No nango.yaml"
YAML PROJECT DETECTED と表示された場合:
- 直ちに作業を中止します。
- まず TypeScript 形式にアップグレードするようユーザーに伝えます。
- YAML と TypeScript を混在させないでください。
参考:https://nango.dev/docs/implementation-guides/platform/migrations/migrate-to-zero-yaml
Nango プロジェクトのルートを確認する
Nango のルートを確認するまで、ファイルを作成しないでください。
ls -la .nango/ 2>/dev/null && pwd && echo "IN NANGO PROJECT ROOT" || echo "NOT in Nango root"
NOT in Nango root と表示された場合:
- .nango/ を含むディレクトリに移動します。
- 確認を再実行します。
- 回避策として絶対パスを使用しないでください。
すべてのファイルパスは Nango のルートからの相対パスにしてください。すでに Nango のルートにいる状態で余分なプレフィックスを付けてファイルを作成すると、ビルドを壊すネストしたディレクトリが作成されます。
プロジェクト構成と命名規則
./
|-- .nango/
|-- index.ts
|-- hubspot/
| |-- actions/
| | `-- create-contact.ts
| `-- syncs/
| `-- fetch-contacts.ts
`-- slack/
`-- actions/
`-- post-message.ts
- プロバイダーディレクトリ:小文字(hubspot、slack)
- アクションファイル:kebab-case(create-contact.ts)
- 同期ファイル:kebab-case(多くのチームでは
fetch-プレフィックスを使用しますが、任意です) - 1 ファイルにつき関数は 1 つ(アクションまたは同期)
- すべてのアクションと同期を index.ts にインポートする必要があります
index.ts にスクリプトを登録する(必須)
副作用インポートのみを使用してください(default/named import は使用しないでください)。.js 拡張子を含めてください。
// index.ts
import './github/actions/get-top-contributor.js';
import './github/syncs/fetch-issues.js';
登録が正しくない場合の症状:ファイルはコンパイルされるものの、No entry points found in index.ts... と表示されるか、関数が一度も表示されません。
必ず守るルール
プラットフォーム共通の制約
- Zero YAML の TypeScript プロジェクトでは、
nango.yamlではなくcreateAction()/createSync()を使用します。 - すべてのアクション/同期を、副作用インポート(
import './<path>.js')でindex.tsに登録します。 - 任意のパッケージは追加できません。相対インポートを使用してください。組み込みのパッケージには
zod、crypto/node:crypto、url/node:urlがあります。 - 関数コードの外部で接続の検索、認証情報の取得、プロキシ呼び出しを行う場合は、Nango HTTP API を使用してください。CLI のトークン/接続コマンドをでっち上げないでください。
- プロバイダーを呼び出す箇所の上に、API ドキュメントへのリンクをコメントとして追加してください。
- アクションの出力は 2MB を超えてはいけません。
- HTTP の再試行回数の既定値は
0です。特に書き込み処理では、retriesを意図的に設定してください。
同期ルール
- 同期レコードには、安定した文字列の
idが必要です。 - 新しい同期では
checkpointスキーマを定義し、最初にnango.getCheckpoint()を呼び出し、各ページまたはバッチの処理後にnango.saveCheckpoint()を呼び出してください。 - チェックポイントが有効なのは、リクエストまたは再開状態(
since、updated_after、cursor、page_token、offset、page、since_idなど)が変わる場合に限られます。利用せずに保存するだけでは、増分同期になりません。 - 新しい同期では
syncType: 'incremental'やnango.lastSyncDateを使用しないでください。 - デフォルトでは
nango.paginate(...)とnango.batchSave(...)を使用してください。cursor、link、またはoffsetによるページネーションが適している場合、手動のwhile (true)ループは避けてください。 - プロバイダーが削除、削除済みレコードを示すトゥームストーン、または削除 Webhook を返す場合は、
batchDelete()を優先してください。 - プロバイダーが変更、削除、または再開状態を返せない場合、あるいはデータセットがごく小さい場合に限り、フルリフレッシュを使用してください。
- フルリフレッシュを行う場合は、ドキュメントまたはペイロードに記載されたプロバイダーの具体的な制限を引用してください。「そのほうが簡単だから」では不十分です。
deleteRecordsFromPreviousExecutions()は非推奨です。フルリフレッシュでは、取得・保存の前にtrackDeletesStart()を呼び出し、フル取得・保存が正常に完了した後にのみtrackDeletesEnd()を呼び出してください。trackDeletesStart()/trackDeletesEnd()を、変更分のみを対象とするチェックポイント(modified_after、updated_after、変更レコード用エンドポイントなど)と組み合わせて使用しないでください。これらは変更のない行を除外するため、trackDeletesEnd()によって削除されてしまいます。- チェックポイントを使ったフルリフレッシュも、フルリフレッシュです。フルウィンドウを完了した実行でのみ
trackDeletesEnd()を呼び出してください。
規約
- フィールドの大文字・小文字の形式は外部 API に合わせてください。パススルーフィールドはプロバイダーの形式を維持し、パススルーではないフィールドには、その API で多数派の形式を使用してください。
- 明示的なフィールド名を優先してください。
- ID、タイムスタンプ、列挙型、URL には
.describe()の例を追加してください。 anyは避け、インラインのマッピング型を使用してください。- 静的な Nango エンドポイントパスを優先してください(公開するエンドポイントで
:id/{id}を避けてください)。ID は入力/パラメーターで渡してください。 - リストアクションでは
cursorと、その API で多数派の形式に従った次のカーソル用フィールド(next_cursor、nextCursorなど)を公開してください。 - カスタムの検証やログ記録が必要な場合にのみ
nango.zodValidateInput()を使用し、それ以外の場合はスキーマとnango dryrun --validateに任せてください。
スキーマの意味
- 必須ではない入力は、デフォルトで
.optional()にしてください。 .nullable()は、通常は更新時のクリアなど、nullに意味がある場合にのみ使用してください。呼び出し元がフィールドを省略することもある場合は、.optional()も追加してください。- プロバイダーの生スキーマはプロバイダーに合わせてください。省略されたフィールドには
.optional()、明示的なnullには.nullable()を使用し、.nullish()はプロバイダーが実際に両方を使う場合にのみ使用してください。 - 最終的なアクション出力と正規化された同期モデルでは、
.optional()を優先し、nullに意味がある場合を除いて、上流のnullは省略に正規化してください。 - 生成スキーマでは、必須ではない入力と正規化された出力にデフォルトで
.optional()を使用してください。上流の契約で正当化される場合にのみ、許容範囲を広げてください。 z.union([z.null(), T])やz.union([T, z.null()])よりも.nullable()を優先してください。- 出力スキーマで許可されている場合にのみ
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 との一貫性を保つことが目的です。
Dryrun、モック、テスト(必須)
必須の手順(省略しないでください):
nango dryrun ... --validate -e dev --no-interactive --auto-confirmが成功するまで実行します。- アクション:必ず
--input '{...}'を渡します(入力が不要なアクションでは--input '{}'を使用します)。 - 同期:再開した実行をシミュレートする必要がある場合は、
--checkpoint '{...}'を使用します。 - 検証を成功させられない場合は、停止して、不足している外部状態または必要な入力を説明します。
- 検証が成功したら、
nango dryrun ... --save -e dev --no-interactive --auto-confirmを実行して<script-name>.test.jsonを生成します。 nango generate:testsを実行し、その後npm testを実行します。
厳守事項:
<script-name>.test.jsonは生成された出力として扱います。作成、編集、名前の変更、移動は行わないでください(記録されたhashフィールドも変更しないでください)。- モックが誤っている、または古くなっている場合は、コードを修正し、
--saveで再記録します。 *.test.jsonにエラーペイロードをハードコードしないでください。404/401/429/タイムアウトのケースには、vi.spyOn(...)を使った Vitest テストを使用します。- 接続 ID は2番目の位置引数です。
--connection-idは使用しないでください。 - スクリプト名が複数のインテグレーションで重複する場合は、
--integration-id <integration-id>を使用します。 - 新しい増分同期では
--checkpointを優先します。--lastSyncDateはレガシーパターンです。 nangoが PATH にない場合は、npx nango ...を使用します。- CLI のアップグレード確認プロンプトが自動化を妨げる場合があります。必要に応じて
NANGO_CLI_UPGRADE_MODE=ignoreを設定してください。
参考:https://nango.dev/docs/implementation-guides/platform/functions/testing
参考資料
- アクションのパターン、CRUD の例、メタデータの使用方法、ActionError の例:
references/actions.md - 同期のパターン、具体的なチェックポイントの例、削除方法、全件更新へのフォールバック:
references/syncs.md
Nango の便利なドキュメント(クイックリンク)
- 関数ランタイム SDK リファレンス:https://nango.dev/docs/reference/functions
- アクションの実装:https://nango.dev/docs/implementation-guides/use-cases/actions/implement-an-action
- 同期の実装:https://nango.dev/docs/implementation-guides/use-cases/syncs/implement-a-sync
- チェックポイント:https://nango.dev/docs/implementation-guides/use-cases/syncs/checkpoints
- 削除の検出(全件と増分):https://nango.dev/docs/implementation-guides/use-cases/syncs/deletion-detection
- インテグレーションのテスト(dryrun、--save、Vitest):https://nango.dev/docs/implementation-guides/platform/functions/testing
- Nango HTTP API リファレンス:https://nango.dev/docs/reference/api
デプロイ(任意)
Nango アカウントの環境に関数をデプロイします:
nango deploy dev
# Deploy only one function
nango deploy --action <action-name> dev
nango deploy --sync <sync-name> dev
参考:https://nango.dev/docs/implementation-guides/use-cases/actions/implement-an-action
API ドキュメントが表示されない場合
ウェブ取得で不完全なドキュメントが返される場合(JS によるレンダリング):
- ユーザーにサンプルレスポンスを依頼します
- リポジトリ内の既存のアクション/同期をパターンとして使用します
--validateを付けて dryrun を成功するまで実行し、その後--saveを付けて dryrun を実行してから、nango generate:testsを実行します
最終チェックリスト
アクション:
- Nango のルートを確認済み
- アクションのパターンには
references/actions.mdを使用した - スキーマと型が明確で、欠損値のルールがプロバイダーと正規化後のコントラクトに一致している
- 必要に応じて、
createAction()にエンドポイント、入力、出力、スコープが含まれている - フィールドにはパススルーの大文字・小文字表記、または API で多数派の表記を使用している
- プロバイダー呼び出しに API ドキュメントへのリンクコメントがあり、再試行が意図的に設定されている
- 想定されるエラーには
nango.ActionErrorを使用している - index.ts に登録済み
-
--validate -e dev --no-interactive --auto-confirm --input '{...}'でドライランが成功する -
--validateの後にnango dryrun ... --saveで<action-name>.test.jsonを生成した -
nango generate:testsを実行し、npm testが成功する
同期:
- Nango のルートを確認済み
- 同期のパターンには
references/syncs.mdを使用した - モデルのマップが定義され、ID が安定した文字列であり、
nullが重要な場合を除き、正規化モデルでは.optional()を優先している - まず増分同期を選択し、ドキュメントまたはペイロードを根拠にフルリフレッシュが明確に正当化される場合を除き、チェックポイントのスキーマを用意した
-
nango.getCheckpoint()を冒頭で読み取り、各ページまたはバッチの後にnango.saveCheckpoint()を実行する - チェックポイントのデータがプロバイダーへのリクエストまたは再開状態(
since、updated_after、cursor、page_token、offset、page、since_idなど)に反映される - 変更分のみを対象とするチェックポイント同期(
modified_after、updated_after、変更レコードのエンドポイント)では、trackDeletesStart()/trackDeletesEnd()を使用しない - チェックポイントを使用しなかった場合、その実行可能なチェックポイント戦略が存在しない理由を説明している
- プロバイダーの生スキーマで省略と
nullを正しくモデル化し、フィールドにはパススルーの大文字・小文字表記、または API で多数派の表記を使用している - API が Nango のページネーターに真に適合しない場合を除き、
nango.paginate()を使用している - 削除戦略が同期の種類に一致している:増分同期では、プロバイダーが明示的な削除を返す場合にのみ
batchDelete()を使用する。それ以外の場合、フルリフレッシュへのフォールバックでは、フェッチ/保存の前にtrackDeletesStart()を実行し、フェッチと保存の両方が成功した後にのみtrackDeletesEnd()を実行する - 必要に応じてメタデータを処理している
- index.ts に登録済み
-
--validate -e dev --no-interactive --auto-confirmでドライランが成功する -
--validateの後にnango dryrun ... --saveで<sync-name>.test.jsonを生成した -
nango generate:testsを実行し、npm testが成功する