or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/npm-gatsby-source-graphql

Gatsby plugin which adds a third-party GraphQL API to Gatsby GraphQL

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/gatsby-source-graphql@5.15.x

To install, run

npx @tessl/cli install tessl/npm-gatsby-source-graphql@5.15.0

index.mddocs/

gatsby-source-graphql

gatsby-source-graphql is a Gatsby plugin that enables integration of third-party GraphQL APIs into Gatsby's unified GraphQL layer through schema stitching. It wraps remote schema Query types under configurable field names within the Gatsby GraphQL query structure, supporting authentication, custom Apollo Links, query batching, and schema transformation capabilities.

Package Information

  • Package Name: gatsby-source-graphql
  • Package Type: npm
  • Language: JavaScript
  • Installation: npm install gatsby-source-graphql

Core Imports

This is a Gatsby plugin, so it's configured in gatsby-config.js rather than imported directly:

// gatsby-config.js
module.exports = {
  plugins: [
    {
      resolve: "gatsby-source-graphql",
      options: {
        // Configuration options
      },
    },
  ],
};

Basic Usage

// gatsby-config.js
module.exports = {
  plugins: [
    {
      resolve: "gatsby-source-graphql",
      options: {
        // Arbitrary name for the remote schema Query type
        typeName: "SWAPI",
        // Field under which the remote schema will be accessible
        fieldName: "swapi", 
        // GraphQL endpoint URL
        url: "https://swapi-graphql.netlify.app/.netlify/functions/index",
      },
    },
  ],
};

Then query the remote GraphQL API through Gatsby's GraphQL layer:

{
  swapi {
    allSpecies {
      name
      classification
    }
  }
}

Capabilities

Plugin Configuration Schema

Defines and validates the plugin configuration options using Joi schema validation.

/**
 * Gatsby plugin option validation schema
 * @param {{ Joi: typeof import('joi') }} gatsbyAPI - Gatsby API with Joi validation library
 * @returns {import('joi').ObjectSchema} Joi validation schema for plugin options
 */
function pluginOptionsSchema({ Joi });

Configuration Options:

interface PluginOptions {
  /** Arbitrary name for the remote schema Query type (required) */
  typeName: string;
  /** Field name under which the remote schema will be accessible (required) */
  fieldName: string;
  /** GraphQL endpoint URL (required if no createLink) */
  url?: string;
  /** HTTP headers or async function returning headers */
  headers?: Record<string, string> | (() => Promise<Record<string, string>>);
  /** Custom fetch implementation */
  fetch?: (uri: string, options?: any) => Promise<Response>;
  /** Additional options to pass to fetch */
  fetchOptions?: Record<string, any>;
  /** Custom Apollo Link factory function */
  createLink?: (options: PluginOptions) => Promise<import('@apollo/client').ApolloLink>;
  /** Custom schema factory function */
  createSchema?: (options: PluginOptions) => Promise<import('graphql').GraphQLSchema>;
  /** Enable query batching for performance */
  batch?: boolean;
  /** Custom schema transformation function */
  transformSchema?: (params: TransformSchemaParams) => import('graphql').GraphQLSchema;
  /** DataLoader configuration options */
  dataLoaderOptions?: DataLoaderOptions;
  /** Refetch interval in seconds (development only) */
  refetchInterval?: number;
}

interface TransformSchemaParams {
  schema: import('graphql').GraphQLSchema;
  link: import('@apollo/client').ApolloLink;
  resolver: (parent: any, args: any, context: any, info: any) => any;
  defaultTransforms: Array<any>;
  options: PluginOptions;
}

interface DataLoaderOptions {
  batch?: boolean;
  maxBatchSize?: number;
  batchScheduleFn?: (callback: () => void) => void;
  cache?: boolean;
  cacheKeyFn?: (key: any) => any;
  cacheMap?: {
    get: (key: any) => any;
    set: (key: any, value: any) => void;
    delete: (key: any) => boolean;
    clear: () => void;
  };
}

Schema Integration

Integrates the remote GraphQL schema into Gatsby's unified GraphQL layer.

/**
 * Gatsby hook that integrates remote GraphQL schema into Gatsby's schema
 * @param {GatsbyCreateSchemaCustomizationAPI} gatsbyAPI - Gatsby API with actions, createNodeId, cache
 * @param {PluginOptions} options - Plugin configuration options
 * @returns {Promise<void>}
 */
async function createSchemaCustomization(gatsbyAPI, options);

interface GatsbyCreateSchemaCustomizationAPI {
  actions: {
    addThirdPartySchema: (params: { schema: import('graphql').GraphQLSchema }) => void;
  };
  createNodeId: (input: string) => string;
  cache: {
    get: (key: string) => Promise<any>;
    set: (key: string, value: any) => Promise<void>;
  };
}

Node Creation

Creates schema tracking nodes for cache invalidation and refetching capabilities.

/**
 * Gatsby hook that creates schema tracking node for cache invalidation and refetching
 * @param {GatsbySourceNodesAPI} gatsbyAPI - Gatsby API with actions, createNodeId, createContentDigest
 * @param {PluginOptions} options - Plugin configuration options
 * @returns {Promise<void>}
 */
async function sourceNodes(gatsbyAPI, options);

interface GatsbySourceNodesAPI {
  actions: {
    createNode: (node: GatsbyNode) => void;
  };
  createNodeId: (input: string) => string;
  createContentDigest: (input: any) => string;
}

interface GatsbyNode {
  id: string;
  typeName: string;
  fieldName: string;
  parent: string | null;
  children: string[];
  internal: {
    type: string;
    contentDigest: string;
    ignoreType: boolean;
  };
}

Schema Transformations

Provides schema transformation classes for customizing how remote schemas are integrated.

/**
 * Transforms remote schema to be nested under specified field name
 */
class NamespaceUnderFieldTransform {
  /**
   * @param {Object} params - Transform parameters
   * @param {string} params.typeName - Name for the wrapped query type
   * @param {string} params.fieldName - Field name for accessing remote schema
   * @param {Function} params.resolver - Custom resolver function
   */
  constructor({ typeName, fieldName, resolver });
  
  /**
   * Applies namespace transformation to GraphQL schema
   * @param {import('graphql').GraphQLSchema} schema - Input GraphQL schema
   * @returns {import('graphql').GraphQLSchema} Transformed schema
   */
  transformSchema(schema);
}

/**
 * Removes Mutation and Subscription types from remote schema
 */
class StripNonQueryTransform {
  /**
   * Strips non-Query operations from GraphQL schema
   * @param {import('graphql').GraphQLSchema} schema - Input GraphQL schema
   * @returns {import('graphql').GraphQLSchema} Transformed schema with only Query type
   */
  transformSchema(schema);
}

HTTP Fetch Utilities

Enhanced fetch wrapper with GraphQL-specific error handling.

/**
 * Enhanced fetch wrapper with error handling for GraphQL requests
 * @param {string} uri - Request URL
 * @param {RequestInit} options - Fetch options
 * @returns {Promise<Response>} Response object
 * @throws {Error} Descriptive errors for HTTP status >= 400
 */
async function fetchWrapper(uri, options);

Query Batching

Apollo Link implementation with DataLoader for automatic query batching and performance optimization.

/**
 * Creates Apollo Link with DataLoader for query batching
 * @param {BatchingOptions} options - Configuration for batching behavior
 * @returns {import('@apollo/client').ApolloLink} Apollo Link instance with batching support
 */
function createDataloaderLink(options);

interface BatchingOptions {
  uri: string;
  headers?: Record<string, string>;
  fetch: (uri: string, options?: any) => Promise<Response>;
  fetchOptions?: Record<string, any>;
  dataLoaderOptions?: DataLoaderOptions;
}

Query Merging Utilities

Utilities for merging multiple GraphQL queries into batched requests.

/**
 * Merges multiple GraphQL queries into single batched query
 * @param {QueryRequest[]} queries - Array of query objects
 * @returns {BatchedQuery} Object with merged query and variables
 */
function merge(queries);

/**
 * Splits merged query result back into individual query results
 * @param {GraphQLResult} mergedQueryResult - Result from merged query
 * @returns {GraphQLResult[]} Array of individual query results
 */
function resolveResult(mergedQueryResult);

interface QueryRequest {
  query: import('graphql').DocumentNode;
  variables: Record<string, any>;
}

interface BatchedQuery {
  query: import('graphql').DocumentNode;
  variables: Record<string, any>;
}

interface GraphQLResult {
  data?: any;
  errors?: Array<{
    message: string;
    path?: Array<string | number>;
  }>;
}

Advanced Configuration Examples

Authentication with Headers

{
  resolve: "gatsby-source-graphql",
  options: {
    typeName: "GitHub",
    fieldName: "github",
    url: "https://api.github.com/graphql",
    headers: {
      Authorization: `Bearer ${process.env.GITHUB_TOKEN}`,
    },
  },
}

Async Headers

{
  resolve: "gatsby-source-graphql",
  options: {
    typeName: "API",
    fieldName: "api",
    url: "https://api.example.com/graphql",
    headers: async () => {
      const token = await getAuthToken();
      return {
        Authorization: `Bearer ${token}`,
      };
    },
  },
}

Custom Apollo Link

const { createHttpLink, from } = require("@apollo/client");
const { RetryLink } = require("@apollo/client/link/retry");

{
  resolve: "gatsby-source-graphql",
  options: {
    typeName: "API",
    fieldName: "api",
    createLink: (pluginOptions) => {
      const retryLink = new RetryLink({
        delay: { initial: 100, max: 2000, jitter: true },
        attempts: { max: 5 },
      });
      return from([retryLink, createHttpLink({ uri: "https://api.example.com/graphql" })]);
    },
  },
}

Query Batching Configuration

{
  resolve: "gatsby-source-graphql",
  options: {
    typeName: "API",
    fieldName: "api", 
    url: "https://api.example.com/graphql",
    batch: true,
    dataLoaderOptions: {
      maxBatchSize: 10,
      batchScheduleFn: (callback) => setTimeout(callback, 50),
    },
  },
}

Custom Schema Creation

const { buildSchema, buildClientSchema } = require("graphql");

{
  resolve: "gatsby-source-graphql",
  options: {
    typeName: "API",
    fieldName: "api",
    url: "https://api.example.com/graphql",
    createSchema: async () => {
      const introspectionResult = JSON.parse(
        fs.readFileSync(`${__dirname}/schema.json`)
      );
      return buildClientSchema(introspectionResult.data);
    },
  },
}

Schema Transformation

const { wrapSchema } = require("@graphql-tools/wrap");
const { linkToExecutor } = require("@graphql-tools/links");

{
  resolve: "gatsby-source-graphql",
  options: {
    typeName: "API",
    fieldName: "api",
    url: "https://api.example.com/graphql",
    transformSchema: ({ schema, link, resolver, defaultTransforms, options }) => {
      return wrapSchema({
        schema,
        executor: linkToExecutor(link),
        transforms: defaultTransforms,
      });
    },
  },
}

Development Refetching

{
  resolve: "gatsby-source-graphql",
  options: {
    typeName: "API",
    fieldName: "api",
    url: "https://api.example.com/graphql",
    refetchInterval: 60, // Refetch every 60 seconds in development
  },
}

Performance Considerations

Query Batching

Enable batching for improved performance when making multiple GraphQL queries:

  • Set batch: true to enable automatic query merging
  • Increase GATSBY_EXPERIMENTAL_QUERY_CONCURRENCY environment variable
  • Configure dataLoaderOptions.maxBatchSize for optimal batch sizes
  • Batching requires compatible remote GraphQL servers

Caching Behavior

  • Schema introspection results are cached in .cache directory
  • Cache persists across builds unless manually cleared
  • Use custom createSchema to disable caching
  • Clear cache by restarting gatsby develop or deleting .cache

Limitations

  • ⚠️ No support for Incremental Builds
  • ⚠️ No support for CMS Preview functionality
  • ⚠️ Limited GraphQL data layer support (no image optimization)
  • Only Query operations supported (Mutations and Subscriptions stripped)
  • Query batching bounded by Gatsby's parallel query limit
  • Batch failures affect all queries in the batch