commerce-app-api-mesh について
commerce-app-api-mesh は、Adobe API Mesh を介して Commerce GraphQL API とランタイムアクションを組み合わせるスキルです。データソースの設定、委譲リゾルバーによる型の拡張、デプロイと検証を開発者向けに案内します。
主な機能
- 01GraphQL と OpenAPI のデータソース設定
- 02ランタイムアクションのメッシュソース化
- 03リゾルバーによる Commerce 型の拡張
- 04メッシュ変更のデプロイと検証
- 05認証・ネスト・ブラウザーリクエストの確認
活用シーン
- 01Commerce 型にランタイムアクションのフィールドを追加
- 02認証済み Commerce データへのアプリ接続
- 03デプロイ済みメッシュへのブラウザーアクセスを検証
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ adobe/ skills --skill commerce-app-api-meshインストール後、Claude Code で/commerce-app-api-meshを入力して読み込まれたか確認します。
詳細
コマースアプリの前段に API Mesh を構築する
Commerce 独自の GraphQL API と、このアプリのランタイムアクションを 1 つのメッシュスキーマに統合します。このスキルでは、ランタイムアクションをメッシュソースとして公開する方法と、そのソースへの委譲で解決されるフィールドを既存の Commerce 型に追加する方法の 2 つを扱います。
このスキルでは、API Mesh の一般的な知識(mesh.json の構造、ハンドラーの種類、変換、フック、シークレット、CORS、汎用の宣言型/プログラム型リゾルバー)があることを前提とします。これらに馴染みがない場合は、構文を推測するのではなく、まず Adobe の資料から確認してください。詳しくは参考資料を参照してください。これらの資料では、additionalResolvers(targetTypeName/sourceTypeName/requiredSelectionSet/sourceSelectionSet)を使って既存の Commerce 型を拡張する方法や、aio-commerce-sdk のランタイムアクションをメッシュソースとしてラップする方法は扱っていません。以下で説明するのはその方法です。
前提条件
aio plugins install @adobe/aio-cli-plugin-api-meshがインストールされていること。- ランタイムアクションをソースとして公開する場合は、ビルドおよびデプロイが完了しており、実際に到達可能な HTTPS エンドポイントがあること。未デプロイのアクションを指すソースは、原因が分かりにくい形で失敗します。
- このワークスペースに既存のメッシュがあるか確認してください:
aio api-mesh:get。「No mesh found」と表示された場合はcreateを実行します。それ以外の場合は既存のmesh.jsonを編集してupdateを実行します。
ステップ 1 — イントロスペクションでスキーマの形状を確認する
additionalTypeDefs または additionalResolvers を記述する前に、拡張する Commerce(またはその他の)GraphQL ソースをイントロスペクションしてください。記憶や似た慣例から型名やフィールド名を推測しないでください。わずかな名前の違いでも、メッシュは正常にビルドされる一方でリゾルバーが実行されない原因になります。
curl -s -X POST "<graphql-endpoint>" -H "Content-Type: application/json" \
-d '{"query":"{ __type(name: \"<TargetType>\") { fields { name } } }"}'
ステップ 2 — ソースのひな形を作成する
{
"name": "Commerce",
"handler": {
"graphql": {
"endpoint": "<commerce-graphql-endpoint>",
"operationHeaders": { "Authorization": "{context.headers.authorization}" }
}
}
}
顧客、カート、またはセッションのスコープを持つフィールドがスキーマにあるソースには、デフォルトで operationHeaders を含めてください。API Mesh は呼び出し元の Authorization ヘッダーを自動では転送しません。これを省略すると、認証が必要なクエリはすべてバックエンド固有の汎用的な「not authorized」エラーで失敗し、無効なトークンの場合と区別できなくなります。
ランタイムアクションをラップするには、エンドポイントのみを記述した小さな静的 OpenAPI ドキュメントを作成し、相対パスで参照してください。
{
"name": "<SourceName>",
"handler": { "openapi": { "source": "./mesh/<source>.json" } }
}
OpenAPI ドキュメント自体にも、上記のポインターだけでなく、メッシュがそこから Query フィールドを生成できるだけの構造が必要です。単一エンドポイントのランタイムアクションに対する最小限の例を示します。
{
"openapi": "3.0.0",
"info": { "title": "<SourceName>", "version": "1.0.0" },
"servers": [{ "url": "<runtime-action-base-url>" }],
"paths": {
"/<action-path>": {
"get": {
"operationId": "<sourceField>",
"parameters": [
{
"name": "<arg>",
"in": "query",
"required": true,
"schema": { "type": "string" }
}
],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": { "<resultField>": { "type": "string" } }
}
}
}
}
}
}
}
}
}
operationId は Query フィールド名になります。ステップ 3 のリゾルバーにある sourceFieldName と完全に一致させる必要があります。一致しない場合、リゾルバーは正常にビルドされますが実行されません。
宣言するレスポンススキーマは、アクションが実際に返す内容と一致させてください。メッシュは宣言に従ってデータを解析するものであり、データの形状を変更するものではありません。
ステップ 3 — 型を拡張してリゾルバーを接続する
"additionalTypeDefs": "extend type <TargetType> { <newField>: String }",
"additionalResolvers": [
{
"targetTypeName": "<TargetType>",
"targetFieldName": "<newField>",
"sourceName": "<SourceName>",
"sourceTypeName": "Query",
"sourceFieldName": "<sourceField>",
"requiredSelectionSet": "{ <keyField> }",
"sourceArgs": { "<arg>": "{root.<keyField>}" },
"sourceSelectionSet": "{ <resultField> }",
"result": "<resultField>"
}
]
オブジェクトを返すソースフィールドからスカラーを抽出するときは、必ず sourceSelectionSet と result を組み合わせてください。result だけを使ってはいけません。result のみを使う経路では、GraphQL パーサーを介さずに選択セットを手作業で構築するため、対象フィールドがリスト内(例:親の items[].<newField>)で解決される場合に、特に "No type was found for field node ... __typename" というエラーが発生します。この不具合がある場合でも、同じソースフィールドをルートクエリから直接呼び出せば成功するため、そのテストだけではリゾルバーが機能している証明として不十分です。
ステップ 4 — デプロイと検証
ブラウザベースのアプリがこのメッシュを呼び出すことがすでに分かっている場合は、最初のデプロイ前に responseConfig.CORS をどうするか決めてください。以下のブラウザー検証段階は、CORS 設定の漏れを検出するためのものですが、事前に決めておけば、デプロイをやり直す必要がありません。
セッション中に最初の aio api-mesh:* を呼び出すと、ブラウザーでのインタラクティブなログインが開始されます(Waiting for browser login...)。ブラウザーにアクセスできないエージェント自身では完了できません。表示されたログイン URI を人間に渡して、完了を待ってください。
aio api-mesh:create mesh.json -c # first time
aio api-mesh:update mesh.json -c # subsequent edits
-c/--autoConfirmAction は、インタラクティブな Are you sure you want to update the mesh: <id>? プロンプトを省略します。このプロンプトは、ほかの人やシステムがすでに依存している可能性のあるメッシュを変更する前の唯一のチェックポイントです。-c は、自分で作成したワークスペーススコープのメッシュ(たとえば、CI 内や使い捨ての開発ワークスペース内)に限って使用してください。既存のメッシュ、共有メッシュ、またはデプロイ済みのメッシュを更新する場合は、-c を省略して人間にプロンプトを確認してもらうか、少なくともコマンドの実行前に差分について人間の明示的な承認を得てください。通常の CLI 呼び出しではなく、ほかの本番インフラ変更と同様に扱ってください。
プロビジョニングは非同期です。完了したと決めつけず、ポーリングしてください。
until aio api-mesh:status 2>&1 | grep -qi success; do sleep 20; done
2 段階で検証します。まずソースのルートフィールドを直接確認し、次に実際のネストされた形状と認証を使ってフィールドを確認してください(フラットなルートフィールドの呼び出しではなく、実際の呼び出し元の認証情報を使ったリストのネストされたクエリ)。第 1 段階に合格しても、第 2 段階が機能する証明にはなりません。上記のバグは第 1 段階では確認できません。
利用するアプリがサーバー間の通信だけでなく、ブラウザーからこのメッシュを直接呼び出す場合は、第 3 段階として、そのアプリの実際のオリジンから実リクエストを送信してください。上記の 2 段階で確認できるのは、サーバー側から到達できることだけです。そのオリジンに対する responseConfig.CORS エントリーがないメッシュでも、両方の段階に合格しながら、追加したフィールドだけでなく、ブラウザーからのすべての呼び出しが失敗します(以下の api-mesh-starter-kit リファレンスの CORS セクションを参照してください)。
よくある問題
- 有効なトークンを使用しているのに、認証が必要なクエリで
"not authorized"が表示される — ソースのgraphqlハンドラーにoperationHeadersがありません。トークンではなく、mesh.jsonを確認してください。 - ネストされたフィールド/リスト内フィールドで
"No type was found for field node ... __typename"が表示されるが、ソースのルートでは問題なく動作する — リゾルバーでsourceSelectionSetを使わずにresultを使用しています。追加してください。
品質基準
aio api-mesh:statusが成功を報告し、新しいフィールドがソースのルートフィールドだけでなく、実際のネストされた形状と認証を使って正しく解決されること。- ブラウザベースのアプリがこのメッシュを呼び出す場合、そのアプリから実リクエストを完了できること。
aio api-mesh:statusとcurlの確認だけでは不十分です。
連携
- ソースがまだランタイムアクションとして存在しない — まず
commerce-app-storage、commerce-app-webhooks、またはcommerce-app-eventingを呼び出して、スキャフォールドを作成してデプロイしてください。
リファレンス
- API Mesh プロンプトガイド — エージェントにメッシュ設定を作成させるための Adobe 独自のガイダンス。一般的なワークフローと期待事項を説明しています。
- api-mesh-starter-kit llm.txt —
mesh.jsonの構造、3 種類すべてのハンドラー、変換、フック、シークレット、コンテキスト状態、CORS、CLI コマンド一式を網羅したリファレンスナレッジベース