跳到正文
cccskills
免费在 GitHub 公开

api-graphql-apollo-server

GraphQL API server with Apollo Server — schema, resolvers, context, error handling, data sources, plugins

中文简介正在准备中。当前显示原文说明。

查看安装方法

包含的文件(6)

  • SKILL.md14.4 KB
  • examples/advanced.md13.4 KB
  • examples/core.md13.3 KB
  • examples/data-sources.md10.0 KB
  • metadata.yaml487 B
  • reference.md9.7 KB

SKILL.md(原文)

安装前可以查看交给 AI 代理的指令内容。

GraphQL API with Apollo Server

Quick Guide: Use @apollo/server (v5) for schema-first GraphQL APIs. Define schemas with SDL (typeDefs), implement field population with resolvers, share per-request state via the context function, and handle errors with GraphQLError + extension codes. Use startStandaloneServer for quick setups or integrate with your HTTP framework for production. DataLoader solves the N+1 problem. Plugins hook into the request lifecycle for logging, auth, and performance.


<critical_requirements>

CRITICAL: Before Using This Skill

(You MUST import from @apollo/server -- NOT the deprecated apollo-server or apollo-server-express packages)

(You MUST create new data source and DataLoader instances per request in the context function -- sharing across requests causes data leaks)

(You MUST throw GraphQLError (from graphql) with extension codes for client-facing errors -- generic Error exposes stack traces)

(You MUST use ApolloServerPluginDrainHttpServer when integrating with an HTTP framework -- without it the server doesn't shut down gracefully)

</critical_requirements>


Auto-detection: Apollo Server, @apollo/server, ApolloServer, startStandaloneServer, expressMiddleware, GraphQLError, typeDefs, resolvers, contextValue, DataLoader, RESTDataSource, @apollo/datasource-rest, ApolloServerPlugin, buildSubgraphSchema, @apollo/subgraph, graphql-ws, PubSub, formatError, gql tag

When to use:

  • Building a GraphQL API with schema-first (SDL) design
  • Defining typed resolvers with shared context (auth, data sources)
  • Wrapping REST APIs or databases behind a unified GraphQL layer
  • Implementing real-time features with subscriptions (via graphql-ws)
  • Building federated subgraphs with @apollo/subgraph
  • Adding lifecycle hooks with plugins (logging, auth, tracing)

When NOT to use:

  • Simple REST APIs without nested data relationships (a REST framework is simpler)
  • APIs consumed only by one client you control with no query flexibility needs
  • Performance-critical APIs where schema overhead matters (consider a code-first approach)

Key patterns covered:

  • Server setup with startStandaloneServer and framework middleware integration
  • Resolver structure, arguments (parent, args, contextValue, info), and chains
  • Context function for per-request state (auth tokens, data sources, DataLoaders)
  • Error handling with GraphQLError, built-in codes, and formatError
  • RESTDataSource for wrapping REST APIs with caching and deduplication
  • DataLoader for batching and deduplication (N+1 problem)
  • Custom plugins with server-level and request-level lifecycle hooks
  • Subscriptions with graphql-ws and WebSocket server
  • Federation subgraph setup with @apollo/subgraph

Detailed Resources:


<philosophy>

Philosophy

Apollo Server follows a schema-first approach: define your API contract in SDL, then implement resolvers to populate each field. The schema is the single source of truth for your API shape, documentation, and type system.

Core principles:

  1. Schema as contract -- SDL defines what clients can query before implementation begins
  2. Thin resolvers -- Resolvers orchestrate data fetching but delegate to data sources and services
  3. Per-request context -- Each operation gets fresh data source instances and auth state via the context function
  4. Graceful error handling -- GraphQLError with extension codes communicates errors without leaking internals

Use Apollo Server when:

  • You need a unified API layer over multiple data sources (REST, DB, services)
  • Clients benefit from querying exactly the data they need (mobile, varied frontends)
  • Schema documentation and introspection matter for developer experience
  • You want lifecycle plugins for observability, auth, and caching

Use simpler approaches when:

  • A single REST endpoint suffices for your use case
  • You have no nested data relationships worth expressing in a graph
  • The overhead of schema definition and resolver wiring doesn't justify the flexibility
</philosophy>
<patterns>

Core Patterns

Pattern 1: Server Setup

Two approaches: startStandaloneServer for quick/simple setups, or framework middleware integration for production.

import { ApolloServer } from "@apollo/server";
import { startStandaloneServer } from "@apollo/server/standalone";

const server = new ApolloServer({ typeDefs, resolvers });

const DEFAULT_PORT = 4000;

const { url } = await startStandaloneServer(server, {
  context: async ({ req }) => ({
    token: req.headers.authorization,
  }),
  listen: { port: DEFAULT_PORT },
});

Why good: minimal boilerplate for development, context function provides per-request auth state

For production with an HTTP framework, use expressMiddleware (from @as-integrations/express4 or @as-integrations/express5) with ApolloServerPluginDrainHttpServer for graceful shutdown.

See examples/core.md for both setup patterns with full TypeScript types.


Pattern 2: Resolver Structure and Arguments

Resolvers receive four arguments: parent (return value from parent resolver), args (field arguments), contextValue (shared per-request state), and info (operation metadata).

const resolvers = {
  Query: {
    user: async (_parent, args, contextValue) => {
      return contextValue.dataSources.usersAPI.getUser(args.id);
    },
  },
  User: {
    posts: async (parent, _args, contextValue) => {
      return contextValue.dataSources.postsAPI.getPostsByAuthor(parent.id);
    },
  },
};

Why good: parent chaining enables nested queries without client round-trips, data source access through context keeps resolvers thin

See examples/core.md for full resolver patterns with type safety.


Pattern 3: Context Function

The context function runs for every operation. Use it to create per-request data sources, extract auth, and set up DataLoaders.

interface MyContext {
  token: string | undefined;
  dataSources: {
    usersAPI: UsersAPI;
    postsAPI: PostsAPI;
  };
}

const server = new ApolloServer<MyContext>({ typeDefs, resolvers });

Critical: Create new data source instances per request. Sharing instances across requests causes stale data and leaks between users.

See examples/core.md for complete context setup.


Pattern 4: Error Handling with GraphQLError

Throw GraphQLError (from the graphql package) with extension codes for structured client errors. Use formatError to sanitize errors before sending.

import { GraphQLError } from "graphql";

throw new GraphQLError("User not found", {
  extensions: {
    code: "USER_NOT_FOUND",
    argumentName: "id",
  },
});

Built-in codes (from ApolloServerErrorCode): GRAPHQL_PARSE_FAILED, GRAPHQL_VALIDATION_FAILED, BAD_USER_INPUT, INTERNAL_SERVER_ERROR, BAD_REQUEST, PERSISTED_QUERY_NOT_FOUND.

See examples/core.md for formatError, custom codes, and auth error patterns.


Pattern 5: RESTDataSource

Wrap REST APIs with @apollo/datasource-rest for built-in caching, request deduplication, and HTTP method helpers.

import { RESTDataSource } from "@apollo/datasource-rest";

class MoviesAPI extends RESTDataSource {
  override baseURL = "https://movies-api.example.com/";

  async getMovie(id: string): Promise<Movie> {
    return this.get<Movie>(`movies/${encodeURIComponent(id)}`);
  }
}

Two-layer caching: (1) request deduplication prevents duplicate GET calls within a single operation, (2) HTTP response caching honors cache-control headers.

See examples/data-sources.md for RESTDataSource methods, custom caching, and willSendRequest.


Pattern 6: DataLoader for N+1 Prevention

Use DataLoader to batch and deduplicate database or API calls within a single GraphQL operation.

import DataLoader from "dataloader";

const userLoader = new DataLoader<string, User>(async (ids) => {
  const users = await db.users.findMany({ where: { id: { in: [...ids] } } });
  return ids.map(
    (id) => users.find((u) => u.id === id) ?? new Error(`User ${id} not found`),
  );
});

Critical: Create new DataLoader instances per request (in the context function). DataLoader caches results for the request lifetime -- sharing across requests serves stale data.

See examples/data-sources.md for DataLoader setup, batching patterns, and integration with context.


Pattern 7: Custom Plugins

Plugins hook into server and request lifecycle events. Use them for logging, auth checks, performance tracing, and error reporting.

import type { ApolloServerPlugin } from "@apollo/server";

const loggingPlugin: ApolloServerPlugin<MyContext> = {
  async requestDidStart(requestContext) {
    const start = Date.now();
    return {
      async willSendResponse() {
        const duration = Date.now() - start;
        console.log(`Operation took ${duration}ms`);
      },
    };
  },
};

Key lifecycle events: serverWillStart, requestDidStart, parsingDidStart, validationDidStart, executionDidStart, didEncounterErrors, willSendResponse.

See examples/advanced.md for complete plugin patterns.


Pattern 8: Subscriptions with graphql-ws

Apollo Server does not include a built-in WebSocket transport. Use graphql-ws + ws for real-time subscriptions alongside your HTTP server.

import { WebSocketServer } from "ws";
import { useServer } from "graphql-ws/use/ws";

const wsServer = new WebSocketServer({
  server: httpServer,
  path: "/subscriptions",
});
const serverCleanup = useServer({ schema }, wsServer);

Note: startStandaloneServer does not support subscriptions -- use framework middleware integration instead. The in-memory PubSub from graphql-subscriptions is for development only; use a distributed pub/sub system in production.

See examples/advanced.md for complete subscription setup with drain plugins.


Pattern 9: Federation Subgraph

Use @apollo/subgraph to build a subgraph that participates in a federated supergraph. Entities use @key directives and __resolveReference resolvers.

import { buildSubgraphSchema } from "@apollo/subgraph";

const server = new ApolloServer({
  schema: buildSubgraphSchema({ typeDefs, resolvers }),
});

Key concepts: @key designates entity identity fields, __resolveReference fetches entities by their key fields, extend type contributes fields from other subgraphs.

See examples/advanced.md for federation schema and reference resolver patterns.

</patterns>

<red_flags>

RED FLAGS

High Priority:

  • Importing from deprecated packages (apollo-server, apollo-server-express) -- use @apollo/server exclusively
  • Sharing data source or DataLoader instances across requests -- causes stale data and cross-user leaks; create new instances in the context function
  • Throwing generic Error from resolvers -- exposes stack traces to clients; use GraphQLError with extension codes
  • Missing ApolloServerPluginDrainHttpServer when using framework integration -- server won't shut down gracefully, leaving connections hanging
  • Calling expressMiddleware before server.start() -- throws an error; start() must complete first

Medium Priority:

  • Using c.req.params instead of resolver args -- bypasses GraphQL argument validation
  • No pagination limits on list resolvers -- returns entire datasets; always enforce max limits
  • In-memory PubSub in production -- only works for a single server instance; use a distributed system
  • Missing encodeURIComponent on dynamic URL segments in RESTDataSource -- path traversal vulnerability
  • Not using formatError to sanitize errors -- internal error messages and stack traces leak to clients in development mode

Gotchas & Edge Cases:

  • Default resolvers: Apollo Server auto-resolves fields matching property names on the parent object -- you don't need explicit resolvers for simple property access
  • contextValue is shared: Never destructively modify contextValue in resolvers -- other resolvers in the same operation share the object
  • Resolver return value of undefined: Triggers the default resolver to try accessing a property on the parent -- may cause unexpected behavior if the parent doesn't have that field
  • Introspection disabled in production: By default, introspection is off when NODE_ENV=production -- override with introspection: true if needed
  • Variable coercion errors: In v5, malformed variables return HTTP 400 by default (v4 returned 200) -- existing clients may need updates
  • Express integration in v5: Import expressMiddleware from @as-integrations/express4 or @as-integrations/express5 (not from @apollo/server/express4 which was removed)
  • Subscription resolvers: Must return an AsyncIterator from subscribe, not a direct value -- the resolve function (optional) transforms the event payload
  • Plugin lifecycle: All plugin methods are async except willResolveField and schemaDidLoadOrUpdate

</red_flags>


<critical_reminders>

CRITICAL REMINDERS

(You MUST import from @apollo/server -- NOT the deprecated apollo-server or apollo-server-express packages)

(You MUST create new data source and DataLoader instances per request in the context function -- sharing across requests causes data leaks)

(You MUST throw GraphQLError (from graphql) with extension codes for client-facing errors -- generic Error exposes stack traces)

(You MUST use ApolloServerPluginDrainHttpServer when integrating with an HTTP framework -- without it the server doesn't shut down gracefully)

Failure to follow these rules will cause data leaks between users, expose internal errors to clients, and prevent graceful shutdown.

</critical_reminders>

评价

还没有评价。欢迎分享你的使用感受。

评论

无需登录即可发表。欢迎分享使用感受、提问,或说明在哪些环境下无法运行。

还没有评论。来写第一条吧。

提交后会立即公开。请勿填写邮箱、电话等个人信息。URL 最多 2 个。

0 / 1000 字

此表单受 reCAPTCHA 保护,适用 Google 的隐私权政策和服务条款。

同一仓库的技能

Hugging Face Inference SDK patterns for TypeScript/Node.js — InferenceClient setup, chat completion, text generation, streaming, embeddings, image generation, audio transcription, translation, summarization, and Inference Endpoints

中文简介正在准备中。当前显示原文说明。

agents-inc/skills252026年10月17日 更新

LiteLLM proxy server setup, TypeScript client patterns via OpenAI SDK, model routing, fallbacks, load balancing, spend tracking, virtual keys, and production deployment

中文简介正在准备中。当前显示原文说明。

agents-inc/skills252026年10月17日 更新

Serverless GPU compute platform for AI model deployment — web endpoints, GPU functions, model serving, and TypeScript client patterns

中文简介正在准备中。当前显示原文说明。

agents-inc/skills252026年10月17日 更新

Local LLM inference with the Ollama JavaScript client -- chat, streaming, tool calling, vision, embeddings, structured output, model management, and OpenAI-compatible endpoint

中文简介正在准备中。当前显示原文说明。

agents-inc/skills252026年10月17日 更新

Replicate SDK patterns for TypeScript/Node.js -- client setup, predictions, streaming, webhooks, file handling, model versioning, deployments, and training

中文简介正在准备中。当前显示原文说明。

agents-inc/skills252026年10月17日 更新

Together AI SDK patterns for TypeScript — client setup, chat completions, streaming, structured output, function calling, embeddings, image generation, fine-tuning, and OpenAI-compatible endpoints

中文简介正在准备中。当前显示原文说明。

agents-inc/skills252026年10月17日 更新

查看 agents-inc 的全部技能

报告此技能的问题