Apollo Server

repository·main·Indexed 11 days ago

https://github.com/apollographql/apollo-server

A production-ready, spec-compliant GraphQL server for Node.js environments. It supports standalone operation, integration with web frameworks like Express, and serves as a building block for federated architectures as subgraphs and gateways. Includes features such as response caching, CSRF and XS-Search protection, and a dedicated integration testsuite for HTTP binding authors.

Tokens
134.8K
Snippets
377
Records
536
Agent score
93%

What's inside Apollo Server

  1. What is Apollo Server?

    main

    Apollo Server is an open-source, spec-compliant GraphQL server for TypeScript and JavaScript. It is compatible with any GraphQL client (including Apollo Client) and can be used in several ways:

    • Standalone Server: A minimally-configurable server that handles CORS and body parsing out of the box.
    • Subgraph: A component of a federated supergraph.
    • Gateway: The entry point for a federated supergraph.

    It provides a simple API for integrating with Node.js web frameworks or serverless environments.

  2. Introduction to Apollo Server

    main

    Apollo Server is an open-source, spec-compliant GraphQL server designed to build production-ready, self-documenting GraphQL APIs. It is compatible with any GraphQL client (such as Apollo Client) and can connect to any data source.

    Common Deployment Patterns

    You can use Apollo Server in several ways:

    • As a Subgraph: Part of a federated supergraph architecture.
    • As an Add-on to Node.js Apps: Integrate it into existing or new applications using middleware or specific integrations, including:
      • Express (including MERN stack apps)
      • Fastify
      • Serverless Functions: AWS Lambda, Azure Functions, and Cloudflare Workers.
  3. Use the Apollo Server Integration Testsuite

    main

    The @apollo/server-integration-testsuite is a set of Jest tests designed for integration authors. If you are building a Node package that acts as an HTTP binding or an HTTP framework integration for Apollo Server, you can use these tests to ensure your implementation maintains parity with the built-in "standalone" implementation.

    Warning: This package is intended for integration authors only. If you are simply running an Apollo Server instance in your application, you should not use this package.

  4. Understand the purpose of `apollo-reporting-protobuf`

    main

    The @apollo/usage-reporting-protobuf module provides JavaScript and TypeScript Protocol Buffer definitions for the Apollo usage reporting API. These definitions are generated from the internal reports.proto file used by Apollo.

    Warning: The Apollo usage reporting API is subject to change. It is strongly recommended to contact Apollo support at support@apollographql.com before building a custom reporting agent using this module.

  5. What is a resolver in Apollo Server

    main

    A resolver is a function responsible for populating the data for a single field in your GraphQL schema. It can fetch data from any source, such as a database or a third-party API.

    If you do not define a resolver for a specific field, Apollo Server uses a default resolver that attempts to obtain the value directly from the object returned by the parent resolver.

  6. What is an Apollo Server plugin and how to create one

    main

    Apollo Server plugins are JavaScript objects used to extend server functionality by responding to specific lifecycle events (e.g., logging, authentication, or custom metrics).

    If you are using TypeScript, plugins should implement the ApolloServerPlugin interface. Most plugin methods are async, with the exceptions of willResolveField and schemaDidLoadOrUpdate.

    To create a plugin that accepts configuration, wrap the plugin object in a function that accepts an options object.

    // A basic plugin responding to server startup
    const myPlugin = {
      async serverWillStart() {
        console.log('Server starting up!');
      },
    };
    
    // A plugin that accepts options
    export default (options: { logMessage: string }) => {
      return {
        async serverWillStart() {
          console.log(options.logMessage);
        },
      };
    };
  7. Understand CORS and Apollo Server security defaults

    main

    Cross-Origin Resource Sharing (CORS) is an HTTP-header-based protocol that allows a server to specify which web origins (combinations of domain, protocol, and port) are permitted to access its resources via a browser.

    Apollo Server Security Defaults:

    • CSRF Protection: By default, Apollo Server protects against Cross-Site Request Forgery (CSRF) and XS-Search attacks. Any client sending operations via GET or multipart upload requests must include a special header, such as Apollo-Require-Preflight.
    • Standalone Server CORS: The startStandaloneServer function uses a wildcard (*) for the Access-Control-Allow-Origin (ACAO) header. This allows any website on the internet to make requests to your server, but it does not allow passing credentials (like cookies) and is not secure for applications running on private networks.
  8. Understand the dual-publishing build system

    main

    Apollo Server is dual-published, supporting both ESM and CJS. This requires specific configuration patterns:

    • TSConfigs: Each dual-published package must have two tsconfig files: one for ESM and one for CJS. These must be referenced at the top-level in the respective esm/ or cjs/ specific tsconfig files.
    • Package Exports: Deep imports in @apollo/server must be defined in the package.json "exports" property. Entries must follow this specific order: "types", "import", then "require".
    • Deep Import Structure: For new deep imports, you must create a directory structure like server/<new-import-name> containing a package.json. The actual source code resides in server/src/<new-import-name>. This pattern supports TypeScript's CommonJS configuration (moduleResolution: "node").
    • Verification: Use the smoke-test directory to ensure new deep imports are correctly built and importable.
  9. Using end hooks to handle lifecycle completion

    main

    Certain lifecycle events support "end hooks"—functions that are invoked after the corresponding phase completes. This is useful for error handling or cleanup after a specific step (like parsing or validation) finishes.

    • parsingDidStart and validationDidStart return a function as an end hook.
    • validationDidStart's end hook is unique because it receives an array of errors.
    • executionDidStart returns an object containing an executionDidEnd function.
    • willResolveField's end hook receives the error and the resolver result as arguments.
    const myPlugin = {
      async requestDidStart() {
        return {
          async parsingDidStart() {
            return async (err) => {
              if (err) console.error(err);
            }
          },
          async validationDidStart() {
            // Receives an array of errors
            return async (errs) => {
              if (errs) errs.forEach(err => console.error(err));
            }
          },
          async executionDidStart() {
            return {
              async executionDidEnd(err) {
                if (err) console.error(err);
              }
            };
          },
        };
      },
    }
  10. Follow GraphQL naming conventions

    main

    While the GraphQL specification is flexible, following these conventions ensures consistency and compatibility with common client-side languages (JavaScript, Java, Kotlin, Swift):

    • Field names: Use camelCase.
    • Type names: Use PascalCase.
    • Enum names: Use PascalCase.
    • Enum values: Use ALL_CAPS (similar to constants).