mcpField
P
platform-salesforce-connect-adapter-generate

platform-salesforce-connect-adapter-generate

github.com/forcedotcom開発1.1k346 回インストール1 日前に更新
リポジトリ

platform-salesforce-connect-adapter-generate について

Salesforce Connect 向けのカスタム Apex アダプターの作成とデプロイを案内する開発スキルです。API 情報を確認してから、2つの Apex クラスとメタデータを生成し、設定手順を示します。

主な機能

  1. 01Connection と Provider の Apex クラス生成
  2. 02REST 応答を外部オブジェクトのスキーマに対応
  3. 03読み取り専用・読み書きアダプターに対応
  4. 04sf CLI によるクラスのデプロイ
  5. 05手動設定と検証の案内

活用シーン

  1. 01REST API データを Salesforce レコードとして公開
  2. 02認証あり・なしのカスタムアダプター構築
  3. 03ページネーションを使う外部データアクセスの設定

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/forcedotcom/sf-skills --skill platform-salesforce-connect-adapter-generate

インストール後、Claude Code で/platform-salesforce-connect-adapter-generateを入力して読み込まれたか確認します。

同梱ファイルreferences/official-examples.mdreferences/scenarios.md

詳細

Salesforce Connect — Custom Apex Adapter

ユーザーが、2 つの Apex クラス、メタデータのデプロイ、登録を含む、完全な Salesforce Connect カスタム Apex アダプターを構築できるよう案内します。ユーザーの API の仕様を推測してはいけません。生成を始める前に質問してください。

対象範囲

対象: DataSource.Connection と DataSource.Provider の Apex クラスの生成、Named Credential メタデータ、sf CLI によるデプロイ、あらゆる REST API のセットアップ登録に関する手順ごとのガイダンス。

対象外: 標準アダプター(OData、Snowflake、GraphQL)の設定(それぞれに独自の手順があります)。External Data Source メタデータファイルの生成(sf CLI ではデプロイできないため、Setup で手動登録する必要があります)。Salesforce Connect フレームワーク外で外部 API を呼び出す Apex の作成(platform-apex-generate または integration-connectivity-generate スキルを使用してください)。

開始前

2 つの点を確認してください。どちらかが不明な場合は、先に質問してください。

1. これは本当に Salesforce Connect のユースケースですか?

ユーザーがしたいこと…適切なツール
外部データをコピーせずにリアルタイムでクエリする — 読み取り専用または読み書き可能で、Salesforce レコードとして表示されるこのスキル
データを Salesforce に定期的にコピーまたは同期するplatform-data-manage スキル
OData、GraphQL、DynamoDB、Athena、または Cross-Org に接続する標準アダプターのセットアップ — Apex は不要で、手順も異なります
Salesforce のネイティブ Snowflake アダプター(Snowflake プロトコルに直接接続)経由で Snowflake に接続する組み込みの Snowflake アダプター — Apex は不要です
REST または HTTP API 経由で Snowflake(または任意のデータベース)のデータにアクセスするこのスキル — Snowflake REST エンドポイント → カスタム Apex アダプター
Apex または Flow のロジックから外部 API を呼び出すplatform-apex-generate スキルまたは integration-connectivity-generate
Salesforce データを外部システムに公開するintegration-connectivity-generate
リアルタイムでプッシュされたデータを受信する、または外部イベントをサブスクライブするSalesforce Connect ではありません — Connect はプル専用です。代わりに Platform Events または Change Data Capture を使用してください
分析または一括処理のためにデータを同期またはコピーするData Cloud または ETL — Connect はゼロコピーの仮想化専用です

標準アダプターが利用できる場合は、そのことをユーザーに伝えてください。標準アダプターで対応できるのにカスタムアダプターを作成するのは、不要な作業です。

2. Salesforce Connect ライセンスを持っていますか?

カスタムアダプターには Salesforce Connect ライセンスが必要です(External Data Source ごとに 1 ライセンス)。ライセンスがない場合、External Data Source メニューに Apex オプションは表示されません。ユーザーがライセンスを持っていない場合は、先にそのことを伝えてください。


デフォルトの組織コンテキスト(ローカルで実行する場合)

ユーザーが組織エイリアスを指定しない場合は、demo-org を使用します。 ユーザーが SFDX プロジェクトのパスを指定しない場合は、~/salesforce-connect-apex-skill/sfconnect-demo/ を使用します。 これらはローカルテスト用のデフォルト値です。ユーザーが独自の値を指定した場合は、必ずそちらを優先してください。


生成前に入力情報を収集する

以下の情報なしにコードを生成してはいけません。不足しているものがあれば質問してください。

入力重要な理由
API 名とその機能クラス名を決定し、フィールドマッピングのコンテキストを設定します
ベース URLNamed Credential のエンドポイントになります
認証タイプNamed Credential の設定と getAuthenticationMode() を決定します
主な GET エンドポイントとサンプルレスポンスExternal Object のスキーマ(フィールド名、型、ネスト構造)を定義します
書き込みサポートが必要かupsertRows() と deleteRows() を実装するかどうかを決定します
組織の種類(DE、スクラッチ、Sandbox).cls-meta.xml の apiVersion を設定します

ユーザーが OpenAPI 仕様を提供した場合は、以下を抽出してください。

  • 配列を返すすべての GET エンドポイント → それぞれが DataSource.Table になります
  • レスポンスオブジェクトのプロパティ → DataSource.Column エントリになります
  • id/uuid/主キー → ExternalId にマッピングします
  • プロパティの型 → 下記のフィールド型マッピング表を使用します

作成するもの

すべてのカスタム Salesforce Connect アダプターは、正確に 2 つの Apex クラスで構成されます。

DataSource.Connection

外部 API との通信を処理します。正確なシグネチャは次のとおりです。

override global DataSource.TableResult query(DataSource.QueryContext context)
override global List<DataSource.TableResult> search(DataSource.SearchContext context)

// Write support — only if API supports it:
global override List<DataSource.UpsertResult> upsertRows(DataSource.UpsertContext context)
global override List<DataSource.DeleteResult> deleteRows(DataSource.DeleteContext context)

重要な違い:query() は常に1 つのテーブルを対象にします(QueryContext には TableSelection が 1 つだけあります)。search() は複数のテーブルを同時に対象にできます(SearchContext には複数の TableSelection インスタンスがあります)。それぞれをループで処理し、テーブルごとに結果を返してください。

DataSource.Provider

アダプターの機能とスキーマを Salesforce に宣言します。必須メソッドは次のとおりです。

  • getAuthenticationMode() — パブリック API の場合は ANONYMOUS、認証が必要な API の場合は NAMED_PRINCIPAL または PER_USER を返します
  • getCapabilities() — QUERY、SEARCH を宣言します。書き込みを実装する場合に限り、ROW_CREATE、ROW_UPDATE、ROW_DELETE を追加します
  • getConnection(ConnectionParams params) — new YourConnection(params) を返します
  • sync() — Setup でユーザーが「Validate and Sync」をクリックしたときに呼び出されます。外部オブジェクトのスキーマと列を定義する List<DataSource.Table> を返します

Provider クラスは Salesforce Setup の External Data Source タイプのドロップダウンに Custom-[ClassName] として表示されます。

重要: Connection クラスを編集するたびに、変更がなくても Provider クラスも再保存する必要があります。そうしないと、アダプターが Type ピックリストから消え、既存の External Object タブが機能しなくなります。


フィールド型のマッピング

外部 API の型使用する型
string / textDataSource.DataType.TEXT_TYPE
number / integer / decimalDataSource.DataType.NUMBER_TYPE
booleanDataSource.DataType.BOOLEAN_TYPE
date (ISO 8601)DataSource.DataType.DATE_TYPE
datetime / timestampDataSource.DataType.DATETIME_TYPE
URLDataSource.DataType.URL_TYPE
emailDataSource.DataType.EMAIL_TYPE
phoneDataSource.DataType.PHONE_TYPE
enum / picklistTEXT_TYPE — enum 値を文字列としてマッピングします
ネストされたオブジェクト / JSON blobスカラー項目にフラット化するか、TEXT_TYPE にして query() で解析します
array件数フィールド(NUMBER_TYPE)を導出するか、最初の要素のフィールドにフラット化します
255 文字を超える string長テキストエリア — 切り詰めないでください。Salesforce が自動的にマッピングします

すべての DataSource.Table に次の列を含める必要があります。

DataSource.Column.text('ExternalId', 255)  // unique key from external system — REQUIRED
DataSource.Column.text('Name', 255)        // display label shown in Salesforce UI — REQUIRED
DataSource.Column.url('DisplayUrl')        // link to the record in the external system — recommended

ExternalId がないことは、アダプターのデプロイは成功してもレコードが表示されない最も一般的な原因です。 DisplayUrl を設定すると、リストビューにクリック可能なリンクアイコンが表示されます。外部レコードの URL を設定してください。


シナリオ

シナリオは 4 つあります:(1)パブリックな読み取り専用、(2)API キー/OAuth による認証、(3)upsert/delete による読み書き、(4)ページネーション対応 API。それぞれのコードパターン全体は references/scenarios.md にあります。

シナリオごとの主な違い:

シナリオ認証モード追加機能Named Credential
パブリックな読み取り専用ANONYMOUSQUERY、SEARCHメタデータとしてデプロイ
認証ありNAMED_PRINCIPAL または PER_USERQUERY、SEARCHSetup で手動作成 — 認証情報をメタデータとしてデプロイしないでください
読み書きANONYMOUS または認証ありROW_CREATE、ROW_UPDATE、ROW_DELETE を追加上記に従う
ページネーション対応任意任意context.tableSelection.numberOfRows を使用します(null の場合はデフォルトで 500)。queryMore は自動実行されません

アダプターの動作確認方法

オプション 1 — sf CLI 経由の SOQL(最速、UI 不要)
sf data query \
  --query "SELECT ExternalId, Name__c FROM [YourObject]__x LIMIT 5" \
  --target-org [org-alias]

行が返されれば、アダプターは動作しています。0 行の場合は、以下のトラブルシューティング手順を確認してください。

オプション 2 — Visualforce ページ(デモに最適、どの組織でも動作)

[Object]__x をクエリして行を apex:pageBlockTable に表示する Visualforce ページと Apex コントローラーをデプロイします。[orgUrl]/apex/[PageName] で開きます。タブの要件、デプロイ状況、フィルターの問題を回避できるため、テストにはリストビューよりも信頼性があります。標準テンプレートは references/scenarios.md を参照してください。

オプション 3 — リストビュー(標準 UI ですが、追加の手順が必要です)

リストビューにレコードを表示するには、次の 4 つすべてを満たす必要があります。

  1. 外部オブジェクトのデプロイ状況が デプロイ済み である(オブジェクトマネージャー → 編集)
  2. 外部オブジェクトのタブが存在する(設定 → タブ → カスタムオブジェクトタブ → 新規)
  3. リストビューのフィルターが すべて に設定されている(「最近参照した項目」ではない)
  4. 外部 API の URL に対するリモートサイト設定が存在する
トラブルシューティング:エラーなしでレコードが 0 件
症状原因修正方法
SOQL の結果が 0 件リモートサイト設定がない設定 → リモートサイト設定 → 新規
SOQL の結果が 0 件名前付き認証情報が見つからない設定 → 名前付き認証情報 → callout: の名前が完全に一致することを確認
SOQL の結果が 0 件組織のプロキシが外部 URL をブロックしているループバックパターンを使用するか、外部 DE 組織に切り替える
リストビューに 0 件表示されるデプロイ状況が「開発中」になっているオブジェクトマネージャー → [Object]__x → 編集 → デプロイ済み
リストビューに 0 件表示されるフィルターが「最近参照した項目」になっているフィルターを「すべて」に変更
アプリケーションランチャーに何も表示されないタブが作成されていない設定 → タブ → カスタムオブジェクトタブ → 新規

エージェントがデプロイするものと、開発者が手動で行うこと

エージェントがデプロイするもの(sf project deploy start コマンド 1 つ)
ファイル備考
classes/[API]DataSourceConnection.cls + メタデータ常に
classes/[API]DataSourceProvider.cls + メタデータ常に
namedCredentials/[API].namedCredential-meta.xml公開 API のみ — 認証情報が必要な API ではスキップ

externalDataSources/[API].externalDataSource-meta.xml は生成しないでください。 Apex クラスをデプロイした後、設定で外部データソースを手動登録する必要があります。sf project deploy start コマンドでは、カスタム Apex 外部データソースをデプロイできません。sf CLI は「メタデータ型を推測できません」というエラーを返します。デプロイ後に設定 → 外部データソース → 新規に移動するよう、ユーザーに案内してください。

正しい NamedCredential XML 形式(<name> 要素なし — API 名はファイル名から取得されます):

<?xml version="1.0" encoding="UTF-8"?>
<NamedCredential xmlns="http://soap.sforce.com/2006/04/metadata">
    <label>My API</label>
    <endpoint>https://api.example.com</endpoint>
    <allowMergeFieldsInBody>false</allowMergeFieldsInBody>
    <allowMergeFieldsInHeader>false</allowMergeFieldsInHeader>
    <generateAuthorizationHeader>false</generateAuthorizationHeader>
    <principalType>Anonymous</principalType>
    <protocol>NoAuthentication</protocol>
</NamedCredential>

デプロイコマンド:

sf project deploy start \
  --source-dir force-app/main/default/ \
  --target-org [org-alias]
開発者が手動で行うこと(常に必要 — 対応するメタデータがありません)

検証と同期では、外部 API を呼び出してスキーマを検出し、外部オブジェクト定義を作成します。これはスクリプト化できません。

Setup → External Data Sources → [your data source] → Validate and Sync
Check the box next to each External Object → Sync
App Launcher → search [External Object name] → confirm records appear

必ず最後に次のように記載してください:「デプロイが完了しました。あと 1 つだけ手順があります。Salesforce の設定で外部データソースを開き、[検証と同期]をクリックしてください。」


エラー処理のルール

query() から例外を捕捉されないまま伝播させないでください。Salesforce はコンテキストを示さず、ユーザーに汎用エラーを表示します。

状況対処方法
HTTP 401throw new DataSource.OAuthTokenExpiredException()
HTTP 429/レート制限空の行を返し、System.debug() でログに記録
HTTP 500 またはネットワークエラー空の行を返し、再スローしない
応答内のフィールドが nullrecord.get('field') != null ? (String) record.get('field') : ''
フラット化できないネストされた JSONクエリ全体を失敗させず、TEXT_TYPE フィールドとして生の JSON 文字列を返す

ガバナー制限

  • トランザクションあたり最大 100 回の HTTP コールアウト — query() の呼び出しごとに 1 つのトランザクションです
  • ヒープ制限は 6 MB(同期)— 巨大なペイロードをデシリアライズせず、サーバー側のページネーションを使用してください
  • CPU 制限は 10 秒 — 大きな応答配列に対するネストされたループは避けてください

前提となる設定 — 必ずこの順序で行ってください

1. Apex クラスを先にデプロイする

Salesforce Connect: Custom (Developed with Apex) タイプは、少なくとも 1 つの DataSource.Provider サブクラスが組織にデプロイされた後にのみ、外部データソースのタイプのドロップダウンに表示されます。

これは権限の問題ではありません。依存関係によるものです。Salesforce は実行時に利用可能な Provider クラスを検出します。Provider がデプロイされていなければ、ドロップダウンに選択肢は表示されません。

常に次の正しい手順で進めてください。

  1. まず Apex クラスをデプロイします(sf project deploy start)
  2. 次に「設定」→「外部データソース」→「新規」へ移動すると、カスタム Apex タイプが表示されます

ユーザーが「ドロップダウンにカスタム Apex の選択肢が表示されない」と言った場合は、まずクラスをデプロイしてから、設定に戻るよう案内してください。

2. テスト前にリモートサイトの設定を追加する

外部 API のベース URL はホワイトリストに登録する必要があります。登録しないと、コールアウトはエラーも例外も表示せずに失敗します。query() は空の行を返します。メタデータとしてデプロイするか、「設定」→「リモートサイトの設定」→「新規」で追加してください。

3. Validate and Sync の後に、Deployment Status を Deployed に設定する

Validate and Sync の後、Salesforce はステータスが "In Development" の外部オブジェクトを作成します。この設定を変更するまで、リストビューと SOQL ではレコードが 0 件返されます。エラーは表示されず、これもまたサイレントな失敗です。

Setup → Object Manager → [YourObject]__x → Edit
  Deployment Status → Deployed → Save

Validate and Sync が完了したら、必ずこの手順をユーザーに伝えてください。

4. 外部オブジェクトをアプリケーションランチャーに表示するタブを作成する

タブがないと、外部オブジェクトは UI に表示されません。次の場所で作成してください。

Setup → Tabs → Custom Object Tabs → New → select [YourObject]__x → Save
こちらも必要です
  • Salesforce Connect ライセンス — ライセンスがない場合、OData を含むすべての Connect アダプタータイプが非表示になります。ドロップダウンに OData と Cross-Org が表示される場合は、ライセンスはすでに有効です。

アンチパターン

しないこと理由すること
API の仕様を把握せずにコードを生成するフィールドタイプの誤り、ExternalId のマッピングミス、アダプターの不具合につながりますまず API 名、ベース URL、認証タイプ、サンプルレスポンスを確認します
ExternalDataSource をメタデータとしてデプロイするデプロイ可能なメタデータタイプではないため、sf CLI でエラーになりますApex クラスをデプロイした後、設定で外部データソースを手動で登録します
upsertRow() または deleteRow()(単数形)を使用するこれらのメソッドは存在せず、コンパイルエラーになりますupsertRows() と deleteRows()(複数形)を使用します
sync() を Provider だけに実装する一部の API バージョンでは sync() を Connection に実装する必要があり、コンパイラーがエラーを通知しますConnection に sync() を実装し、エラーが出る場合は Provider から削除します
Apex に API URL をハードコードするソースコードから認証情報が漏れ、コールアウトがブロックされます常に callout:NamedCredentialName を使用します
search() から単一の DataSource.TableResult を返すsearch() は List<DataSource.TableResult> を返すため、コンパイルエラーになりますcontext.tableSelections をループして、テーブルごとに 1 つの結果を返します
query() で COUNT の処理を省略するリストビューは COUNT クエリを実行するため、検出しないと誤った結果が返されますcolumnsSelected[0].aggregation == DataSource.QueryAggregation.COUNT を確認します
外部オブジェクトを "In Development" のままにするエラーなしでレコードが 0 件返され、ユーザーには見えませんValidate and Sync の後に、「オブジェクトマネージャー」→ [Object]__x →「編集」→「Deployed」の順に操作します
リモートサイトの設定を省略するコールアウトはエラーなく実行されたように見えますが、空の行を返しますremoteSiteSettings/[API].remoteSite-meta.xml をデプロイするか、設定で手動で追加します

リリース前の確認事項

次の点を確認してください。必要な入力情報(API 名、URL、認証、サンプルレスポンス、書き込みのサポート)を収集済み → コードでは Connection に sync() + query() + search()、Provider に getCapabilities() + getConnection() を実装し、すべてのテーブルに ExternalId と nameColumn を設定し、query() で COUNT を処理し、テスト用のモックデータを用意し、すべてのエンドポイントに callout: プレフィックスを付与済み → 両方の .cls-meta.xml ファイルを生成済み → デプロイコマンドを提示済み → デプロイ後の手順(Named Credential の設定、リモートサイトの設定、外部データソースの登録、Validate and Sync、Deployment Status → Deployed、タブの作成)を伝達済み。


リファレンス例

Salesforce Connect アダプターの公式サンプル(GitHub Issues(完全な DML、選択リスト、テーブル間のリレーション)、Google Drive(OAuth +テスト用モック)、Google Books(ページネーション)、StackOverflow(複数のテーブル)、Loopback(フィルター変換))の注釈付き解説については、references/official-examples.md を参照してください。新しいユーザー向けに生成する前に読んでください。


プロジェクトのセットアップ — 開発者がまだ SFDX プロジェクトを持っていない場合

デプロイする前に、プロジェクト構造が必要です。まだ存在しない場合は、まず生成してください。

sf project generate --name my-adapter --output-dir .
cd my-adapter

これにより、force-app/main/default/classes/ と必要な sfdx-project.json が作成されます。生成されたファイルはすべてこの構造に配置します。開発者に必要なのは、sf CLI がインストールされていることと、sf org login web --alias my-org で組織に認証済みであることだけです。VS Code、Agentforce Vibes、Salesforce IDE は必要ありません。

このスキルは、コンテキストファイルを読み取れるあらゆるコーディングエージェントで動作します。Claude Code、Cursor、Windsurf、GitHub Copilot、または SKILL.md が読み込まれたあらゆるエージェントに対応しています。Salesforce MCP サーバー、Agentforce Vibes、Salesforce 内部ツールは必要ありません。


出力形式

次の順序でファイルを生成し、その後にデプロイコマンドを提示してください。

  1. force-app/main/default/classes/[API]DataSourceConnection.cls
  2. force-app/main/default/classes/[API]DataSourceProvider.cls
  3. force-app/main/default/classes/[API]DataSourceConnection.cls-meta.xml
  4. force-app/main/default/classes/[API]DataSourceProvider.cls-meta.xml
  5. force-app/main/default/namedCredentials/[API].namedCredential-meta.xml — 公開 API のみ

各 Apex クラスの先頭に 1 行のコメントを記載します:// Salesforce Connect custom adapter for [API name] ロジック上の選択が自明でない場合を除き、その他のインラインコメントは記載しないでください。

コメント