Agent-almanac use-graphql-api
git clone https://github.com/pjt222/agent-almanac
T=$(mktemp -d) && git clone --depth=1 https://github.com/pjt222/agent-almanac "$T" && mkdir -p ~/.claude/skills && cp -r "$T/i18n/de/skills/use-graphql-api" ~/.claude/skills/pjt222-agent-almanac-use-graphql-api-6378de && rm -rf "$T"
i18n/de/skills/use-graphql-api/SKILL.mdGraphQL-API verwenden
GraphQL-APIs abfragen und Mutations durchführen, sowohl über die Kommandozeile als auch in TypeScript-Anwendungen.
Wann verwenden
- Integration einer GraphQL-API in eine Anwendung
- Migration einer bestehenden REST-Integration auf GraphQL
- Debugging von GraphQL-Operationen und Schema-Problemen
- Erkunden einer unbekannten GraphQL-API über Introspection
Eingaben
- Erforderlich: GraphQL-Endpunkt-URL (z. B.
)https://api.example.com/graphql - Optional: Authentifizierungs-Token oder API-Key
- Optional: Spezifische Query- oder Mutation-Operationen
- Optional: TypeScript-Client-Library-Präferenz (fetch, urql, Apollo)
Vorgehensweise
Schritt 1: API über Introspection erkunden
Das Schema der GraphQL-API entdecken, ohne Dokumentation.
# Einfache Introspection-Query mit curl curl -s -X POST https://api.example.com/graphql \ -H "Content-Type: application/json" \ -d '{"query": "{ __schema { types { name kind } } }"}' \ | jq '.data.__schema.types[] | select(.kind == "OBJECT") | .name' # Mit Authentifizierung curl -s -X POST https://api.example.com/graphql \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_TOKEN" \ -d '{"query": "{ __schema { queryType { fields { name description } } } }"}' \ | jq '.data.__schema.queryType.fields[]'
Für eine vollständigere Schema-Erkundung:
# Vollständige Introspection-Query speichern cat > /tmp/introspection.json << 'EOF' { "query": "{ __schema { types { name kind fields { name type { name kind ofType { name kind } } } } } }" } EOF curl -s -X POST https://api.example.com/graphql \ -H "Content-Type: application/json" \ -d @/tmp/introspection.json | jq '.' > /tmp/schema.json
Erwartet: Schema-Typen und verfügbare Query-Felder werden aufgelistet.
Bei Fehler: Wenn Introspection disabled ist (häufig in Produktions-APIs), die offizielle Dokumentation konsultieren oder den API-Anbieter für ein Schema-Dokument kontaktieren.
Schritt 2: Queries mit curl testen
Queries manuell testen, bevor Code geschrieben wird.
# Einfache Query curl -s -X POST https://api.example.com/graphql \ -H "Content-Type: application/json" \ -d '{ "query": "query GetUser($id: ID!) { user(id: $id) { id name email } }", "variables": {"id": "123"} }' | jq '.' # Query mit verschachtelten Feldern curl -s -X POST https://api.example.com/graphql \ -H "Content-Type: application/json" \ -d '{ "query": "{ users(first: 10) { edges { node { id name posts { title } } } pageInfo { hasNextPage endCursor } } }" }' | jq '.data.users.edges[].node'
Erwartet: JSON-Antwort mit
data-Schlüssel, der die angeforderten Felder enthält. Keine errors-Schlüssel.
Bei Fehler: Wenn
errors erscheint, den Meldungstext prüfen. Häufige Ursachen: falsche Feldnamen (Schema-Introspection auf korrekte Namen prüfen), fehlende erforderliche Variablen, Berechtigungsfehler.
Schritt 3: TypeScript-GraphQL-Client einrichten
Eine typisierte GraphQL-Client-Integration in TypeScript einrichten.
# Option 1: Nativer Fetch (kein Client erforderlich) # Keine Installation nötig # Option 2: graphql-request (leichtgewichtig) npm install graphql-request graphql # Option 3: urql (React-fokussiert) npm install urql graphql # Option 4: Apollo Client (vollständig) npm install @apollo/client graphql
Typisierter Client mit
graphql-request:
// src/lib/graphql-client.ts import { GraphQLClient, gql } from 'graphql-request' const endpoint = process.env.NEXT_PUBLIC_GRAPHQL_URL! export const client = new GraphQLClient(endpoint, { headers: { authorization: `Bearer ${process.env.API_TOKEN}`, }, }) // Typen definieren interface User { id: string name: string email: string } interface GetUserQuery { user: User } interface GetUserVariables { id: string } // Typisierte Query-Funktion const GET_USER = gql` query GetUser($id: ID!) { user(id: $id) { id name email } } ` export async function getUser(id: string): Promise<User> { const data = await client.request<GetUserQuery, GetUserVariables>( GET_USER, { id } ) return data.user }
Erwartet: Client initialisiert ohne Fehler.
getUser()-Funktion gibt typisierte User-Daten zurück.
Bei Fehler: Wenn TypeScript Typfehler meldet, sicherstellen, dass GraphQL-Response-Typen mit den tatsächlichen Schema-Feldern übereinstimmen.
Schritt 4: Mutations implementieren
Daten-schreibende Operationen implementieren.
// src/lib/mutations.ts import { client, gql } from './graphql-client' interface CreatePostInput { title: string content: string authorId: string } interface Post { id: string title: string content: string createdAt: string } interface CreatePostMutation { createPost: Post } const CREATE_POST = gql` mutation CreatePost($input: CreatePostInput!) { createPost(input: $input) { id title content createdAt } } ` export async function createPost(input: CreatePostInput): Promise<Post> { const data = await client.request<CreatePostMutation>(CREATE_POST, { input, }) return data.createPost }
# Mutation mit curl testen curl -s -X POST https://api.example.com/graphql \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_TOKEN" \ -d '{ "query": "mutation CreatePost($input: CreatePostInput!) { createPost(input: $input) { id title } }", "variables": {"input": {"title": "Test Post", "content": "Hello", "authorId": "123"}} }' | jq '.'
Erwartet: Mutation gibt das erstellte Objekt mit ID zurück.
Bei Fehler: Wenn Mutation schlägt mit "Not authorized" fehl, sicherstellen, dass das Auth-Token korrekt formatiert ist (Bearer-Präfix, gültiger Token).
Schritt 5: Fehlerbehandlung implementieren
Robuste Fehlerbehandlung für GraphQL-Antworten.
// src/lib/graphql-client.ts (erweitert) import { ClientError } from 'graphql-request' export interface GraphQLError { message: string locations?: Array<{ line: number; column: number }> path?: string[] extensions?: Record<string, unknown> } export class GraphQLRequestError extends Error { constructor( message: string, public readonly errors: GraphQLError[], public readonly status: number ) { super(message) this.name = 'GraphQLRequestError' } } export async function safeRequest<T>( query: string, variables?: Record<string, unknown> ): Promise<T> { try { return await client.request<T>(query, variables) } catch (error) { if (error instanceof ClientError) { const graphqlErrors = error.response.errors ?? [] throw new GraphQLRequestError( graphqlErrors[0]?.message ?? 'GraphQL request failed', graphqlErrors, error.response.status ) } throw error } }
Erwartet:
safeRequest() gibt typisierte Daten zurück oder wirft GraphQLRequestError mit strukturierten Fehlerinformationen.
Bei Fehler: Wenn Fehler-Typen nicht übereinstimmen, GraphQL-Error-Response-Struktur durch Logging von
error.response aus ClientError überprüfen.
Schritt 6: In Next.js-API-Route integrieren
GraphQL-Queries in Next.js Server-Komponenten oder API-Routen verwenden.
// src/app/users/[id]/page.tsx (Server Component) import { getUser } from '@/lib/graphql-client' interface Props { params: { id: string } } export default async function UserPage({ params }: Props) { const user = await getUser(params.id) return ( <div> <h1>{user.name}</h1> <p>{user.email}</p> </div> ) } // src/app/api/posts/route.ts (API Route) import { NextRequest, NextResponse } from 'next/server' import { createPost } from '@/lib/mutations' export async function POST(request: NextRequest) { const body = await request.json() const post = await createPost({ title: body.title, content: body.content, authorId: body.authorId, }) return NextResponse.json(post) }
Erwartet: Server-Komponente rendert User-Daten. API-Route erstellt Post und gibt JSON zurück.
Bei Fehler: Wenn Daten nicht auf der Client-Seite erscheinen, sicherstellen, dass die Komponente als Server-Komponente deklariert ist (keine
'use client'-Direktive) und die GraphQL-Antwort korrekt gemappt wird.
Validierung
- Schema-Introspection gibt verfügbare Typen und Felder zurück
- Test-Query über curl gibt erwartete Daten zurück
- TypeScript-Client kompiliert ohne Fehler
- Mutations erstellen/aktualisieren Daten erfolgreich
- Fehlerbehandlung fängt GraphQL-Fehler und gibt strukturierte Informationen zurück
- Next.js-Integration rendert GraphQL-Daten korrekt
Haeufige Stolperfallen
- GraphQL vs REST-Fehlerstatuscodes: GraphQL gibt immer HTTP 200 zurück — Fehler stehen in
-Array im Response-Body, nicht im HTTP-Status.errors - N+1-Query-Problem: Das Abrufen von einer Liste und dann für jedes Element einer Unterabfrage führt zu N+1 Datenbankabfragen.
oder Batching auf API-Seite verwenden.DataLoader - Introspection in Produktion deaktiviert: Viele APIs deaktivieren Introspection aus Sicherheitsgründen. Lokale Entwicklung oder Staging-Endpunkte zum Erkunden verwenden.
- Cursor-basierte Pagination: GraphQL-APIs verwenden oft Cursor-Pagination (
/edges
/node
) statt Offset-Pagination.pageInfo
korrekt für die nächste Seite weitergeben.endCursor - Variablen-Typen müssen übereinstimmen: GraphQL ist stark typisiert.
vs"123"
(String vs Int) führt zu Validierungsfehlern.123 - Auth-Token-Aktualisierung: Wenn Tokens ablaufen, Client-Instanz neu initialisieren oder Header-Funktion anstelle eines statischen Strings verwenden.
Verwandte Skills
— Next.js-App für GraphQL-Integration vorbereitenscaffold-nextjs-app
— GraphQL-integrierte App deployendeploy-to-vercel