or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

graphql-resolvers.mdimage-cdn-polyfill.mdindex.mdjoi-schemas.mdruntime-compatibility.mdschema-validation.md
tile.json

runtime-compatibility.mddocs/

Runtime Compatibility

Runtime detection system for Gatsby node lifecycle APIs and feature availability, enabling plugins to support multiple Gatsby versions gracefully.

Capabilities

isGatsbyNodeLifecycleSupported

Checks if a specific Gatsby node lifecycle API is supported in the current Gatsby version.

/**
 * Checks if a Gatsby node lifecycle API is supported
 * @param apiName - Name of the lifecycle API to check
 * @returns Boolean indicating if the API is available
 * @throws Error if gatsby version is incompatible (< 2.13.41)
 */
function isGatsbyNodeLifecycleSupported(apiName: string): boolean;

Usage Examples:

import { isGatsbyNodeLifecycleSupported } from "gatsby-plugin-utils";

// Check for modern schema customization API
if (isGatsbyNodeLifecycleSupported('createSchemaCustomization')) {
  exports.createSchemaCustomization = ({ actions, schema }) => {
    actions.createTypes(schema.buildObjectType({
      name: 'MyCustomType',
      fields: {
        id: 'ID!',
        title: 'String!'
      }
    }));
  };
} else {
  // Fall back to older setFieldsOnGraphQLNodeType API
  exports.setFieldsOnGraphQLNodeType = ({ type }) => {
    if (type.name === 'MyCustomType') {
      return {
        customField: {
          type: 'String',
          resolve: (source) => source.title
        }
      };
    }
  };
}

// Check for newer lifecycle APIs
if (isGatsbyNodeLifecycleSupported('createResolvers')) {
  exports.createResolvers = (resolvers) => {
    // Use modern resolver API
  };
}

if (isGatsbyNodeLifecycleSupported('sourceNodes')) {
  exports.sourceNodes = async ({ actions, createNodeId, createContentDigest }) => {
    // Create source nodes
  };
}

hasFeature

Checks if a specific Gatsby feature is available in the current version.

/**
 * Checks if a Gatsby feature is available
 * @param name - Feature name to check for availability
 * @returns Boolean indicating if the feature is available
 * @throws Error if gatsby version is incompatible (< 2.13.41)
 */
function hasFeature(name: AvailableFeatures): boolean;

Usage Examples:

import { hasFeature } from "gatsby-plugin-utils";

// Check for image CDN support
if (hasFeature('image-cdn')) {
  // Use native Gatsby image CDN
  console.log("Using native image CDN");
} else {
  // Use polyfill functionality
  console.log("Using image CDN polyfill");
  const { addRemoteFilePolyfillInterface } = require("gatsby-plugin-utils/polyfill-remote-file");
  // Setup polyfill...
}

// Check for other features
if (hasFeature('graphql-typegen')) {
  // Use GraphQL type generation features
} else {
  // Handle without type generation
}

if (hasFeature('tracing')) {
  // Enable performance tracing
}

if (hasFeature('webpack-5')) {
  // Use Webpack 5 specific features
}

Supported Lifecycle APIs

Common Gatsby node lifecycle APIs that can be checked:

  • createSchemaCustomization - Modern GraphQL schema customization
  • createResolvers - Custom GraphQL resolvers
  • sourceNodes - Source node creation
  • onCreateNode - Node creation hooks
  • createPages - Page creation API
  • onPreBootstrap - Pre-bootstrap lifecycle
  • createPagesStatefully - Stateful page creation
  • preprocessSource - Source preprocessing
  • resolvableExtensions - File extension resolution
  • setFieldsOnGraphQLNodeType - Legacy field customization

Feature Detection

Available features that can be detected:

type AvailableFeatures = 
  | "image-cdn"
  | "graphql-typegen" 
  | "tracing"
  | "webpack-5"
  | "fast-refresh"
  | "incremental-builds"
  | "parallel-sourcing";

Error Handling

Both functions will throw an error if the Gatsby version is too old:

try {
  const isSupported = isGatsbyNodeLifecycleSupported('createSchemaCustomization');
} catch (error) {
  // Error: Couldn't check available APIs. Make sure you are on gatsby version >=2.13.41
  console.error("Gatsby version too old:", error.message);
  // Handle graceful degradation
}

try {
  const hasImageCdn = hasFeature('image-cdn');
} catch (error) {
  // Error: Couldn't check available APIs. Make sure you are on gatsby version >=2.13.41
  console.error("Feature detection unavailable:", error.message);
  // Assume feature is not available
}

Version-Safe Plugin Development

// gatsby-node.js
const { isGatsbyNodeLifecycleSupported, hasFeature } = require("gatsby-plugin-utils");

// Conditional exports based on API availability
const nodeApis = {};

// Always available in modern Gatsby
nodeApis.onPreInit = async ({ reporter }) => {
  reporter.info("Plugin initializing...");
};

// Conditionally export based on API support
if (isGatsbyNodeLifecycleSupported('createSchemaCustomization')) {
  nodeApis.createSchemaCustomization = ({ actions, schema }) => {
    // Modern schema API
    actions.createTypes(`
      type MyNode implements Node {
        id: ID!
        title: String!
        slug: String!
      }
    `);
  };
}

if (isGatsbyNodeLifecycleSupported('createResolvers')) {
  nodeApis.createResolvers = (resolvers) => {
    resolvers.MyNode = {
      slug: {
        resolve: (source) => source.title.toLowerCase().replace(/\s+/g, '-')
      }
    };
  };
}

// Feature-based conditional logic  
if (hasFeature('image-cdn')) {
  nodeApis.onCreateNode = ({ node, actions }) => {
    // Use native image CDN processing
  };
} else {
  // Use polyfill or alternative approach
  const { addRemoteFilePolyfillInterface } = require("gatsby-plugin-utils/polyfill-remote-file");
  
  nodeApis.createSchemaCustomization = ({ actions, schema, store }) => {
    actions.createTypes([
      addRemoteFilePolyfillInterface(
        schema.buildObjectType({
          name: 'MyImageNode',
          fields: {
            url: 'String!',
            alt: 'String'
          },
          interfaces: ['Node', 'RemoteFile']
        }),
        { schema, actions, store }
      )
    ]);
  };
}

// Export conditionally created APIs
module.exports = nodeApis;

Best Practices

  1. Always wrap in try-catch: Version detection can fail on very old Gatsby versions
  2. Graceful degradation: Provide fallbacks when features aren't available
  3. Feature-first development: Use hasFeature() to enable optimal paths when available
  4. Conditional exports: Only export lifecycle APIs that are supported
  5. User communication: Inform users about version compatibility requirements