CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-gatsby-codemods

A collection of codemod scripts for use with JSCodeshift that help migrate to newer versions of Gatsby.

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

index.mddocs/

gatsby-codemods

gatsby-codemods is a collection of automated code transformation scripts (codemods) built on JSCodeshift that help developers migrate their Gatsby projects to newer versions by automatically updating deprecated APIs and patterns.

Package Information

  • Package Name: gatsby-codemods
  • Package Type: npm
  • Language: JavaScript/TypeScript
  • Installation: npm install gatsby-codemods

Core Imports

// The package is primarily used via CLI, but transforms can be imported directly
// Note: transforms are built from src/transforms/ to the package root during build
const globalGraphqlCalls = require('gatsby-codemods/transforms/global-graphql-calls');
const importLink = require('gatsby-codemods/transforms/import-link');
const navigateCalls = require('gatsby-codemods/transforms/navigate-calls');
const renameBoundActionCreators = require('gatsby-codemods/transforms/rename-bound-action-creators');
const gatsbyPluginImage = require('gatsby-codemods/transforms/gatsby-plugin-image');

For CLI usage (most common):

npx gatsby-codemods <codemod-name> <filepath>

Basic Usage

# Run a codemod via npx (recommended)
npx gatsby-codemods global-graphql-calls ./src

# Use JSCodeshift directly for more control
jscodeshift -t node_modules/gatsby-codemods/transforms/global-graphql-calls.js ./src --extensions js,jsx,ts,tsx

Architecture

gatsby-codemods follows a modular architecture:

  • CLI Interface: Simplified command-line tool (gatsby-codemods binary) that wraps JSCodeshift
  • Transform Library: Individual codemod modules that follow the JSCodeshift API pattern
  • Built-in Safety: Automatic file extension filtering and directory exclusions to prevent unintended modifications

The package automatically processes JavaScript, JSX, TypeScript, and TSX files while ignoring node_modules, .cache, and public directories.

Capabilities

CLI Interface

The main interface for running codemods with simplified usage patterns.

/**
 * Main CLI entry point that parses arguments and executes transforms
 */
function run(): void;

/**
 * Executes a specific codemod transform on a target directory
 * @param transform - Name of the transform to run
 * @param targetDir - Directory path to run the transform against
 */
function runTransform(transform: string, targetDir: string): void;

// Available codemod names
const codemods: string[];
// Value: ['gatsby-plugin-image', 'global-graphql-calls', 'import-link', 'navigate-calls', 'rename-bound-action-creators']

// Path to the transforms directory
const transformerDirectory: string;

// Path to the jscodeshift executable
const jscodeshiftExecutable: string;

Usage:

# Basic usage - runs transform on current directory
npx gatsby-codemods global-graphql-calls

# Specify target directory
npx gatsby-codemods import-link ./src

# Using JSCodeshift directly
jscodeshift -t node_modules/gatsby-codemods/transforms/global-graphql-calls.js ./src

Transform: global-graphql-calls

Adds graphql import to modules that use the graphql tag function without an import. This migration was needed for Gatsby v1 to v2.

/**
 * JSCodeshift transform that adds graphql imports where needed
 * @param file - File information object containing source code
 * @param api - JSCodeshift API object with transformation utilities
 * @param options - Transform options (unused)
 * @returns Transformed source code or false if no changes needed
 */
function globalGraphqlCallsTransform(
  file: FileInfo, 
  api: API, 
  options: Options
): string | false;

Before:

export const query = graphql`
  query {
    site {
      siteMetadata {
        title
      }
    }
  }
`;

After:

import { graphql } from "gatsby";

export const query = graphql`
  query {
    site {
      siteMetadata {
        title
      }
    }
  }
`;

Transform: import-link

Changes Link imports from gatsby-link to gatsby and removes the gatsby-link import.

/**
 * JSCodeshift transform that updates Link imports
 * @param file - File information object containing source code
 * @param api - JSCodeshift API object with transformation utilities  
 * @param options - Transform options (unused)
 * @returns Transformed source code or false if no changes needed
 */
function importLinkTransform(
  file: FileInfo,
  api: API, 
  options: Options
): string | false;

Before:

import Link from "gatsby-link";

export default props => (
  <Link to="/">Home</Link>
);

After:

import { Link } from "gatsby";

export default props => (
  <Link to="/">Home</Link>
);

Transform: navigate-calls

Changes the deprecated navigateTo method from gatsby-link to navigate from the gatsby module.

/**
 * JSCodeshift transform that updates navigate function calls
 * @param file - File information object containing source code
 * @param api - JSCodeshift API object with transformation utilities
 * @param options - Transform options (unused)
 * @returns Transformed source code or false if no changes needed
 */
function navigateCallsTransform(
  file: FileInfo,
  api: API,
  options: Options
): string | false;

Before:

import { navigateTo } from "gatsby-link";

export default props => (
  <div onClick={() => navigateTo(`/`)}>Click to go to home</div>
);

After:

import { navigate } from "gatsby";

export default props => (
  <div onClick={() => navigate(`/`)}>Click to go to home</div>
);

Transform: rename-bound-action-creators

Renames boundActionCreators to actions. This addresses a deprecation in Gatsby v2.

/**
 * JSCodeshift transform that renames boundActionCreators to actions
 * @param file - File information object containing source code
 * @param api - JSCodeshift API object with transformation utilities
 * @param options - Transform options (unused)
 * @returns Transformed source code or false if no changes needed
 */
function renameBoundActionCreatorsTransform(
  file: FileInfo,
  api: API,
  options: Options
): string | false;

Before:

exports.onCreateNode = ({ node, getNode, boundActionCreators }) => {
  const { createNodeField } = boundActionCreators;
  // ... rest of function
};

After:

exports.onCreateNode = ({ node, getNode, actions }) => {
  const { createNodeField } = actions;
  // ... rest of function  
};

Transform: gatsby-plugin-image

Migrates gatsby-image to gatsby-plugin-image usage. This is a complex Babel-based transform that handles GraphQL fragments, component props, and import statements.

/**
 * Main JSCodeshift entry point for gatsby-plugin-image migration
 * @param file - File information object containing source code
 * @returns Transformed source code or original source if no changes needed
 */
function jsCodeShift(file: FileInfo): string;

/**
 * Babel/Recast transform that performs the actual migration
 * @param code - Source code string
 * @param filePath - Path to the file being transformed
 * @returns Transformed source code or original code if no changes needed
 */
function babelRecast(code: string, filePath: string): string;

/**
 * Babel plugin that updates imports and transforms usage patterns
 * @param babel - Babel instance with types and template
 * @returns Babel plugin object with visitor methods
 */
function updateImport(babel: BabelTypes): BabelPlugin;

// Transform constants
const propNames: string[];
// Value: ['fixed', 'fluid']

const legacyFragments: string[];
// Value: ['GatsbyImageSharpFixed', 'GatsbyImageSharpFixed_withWebp', 'GatsbyImageSharpFluid', 'GatsbyImageSharpFluid_withWebp']

const transformOptions: string[];
// Value: ['grayscale', 'duotone', 'rotate', 'trim', 'cropFocus', 'fit']

const typeMapper: Record<string, string>;
// Value: { fixed: 'FIXED', fluid: 'FULL_WIDTH', constrained: 'CONSTRAINED' }

This transform handles multiple migration patterns including:

  • Converting gatsby-image imports to gatsby-plugin-image
  • Updating GraphQL fragments from legacy names to new ones
  • Converting component props from fixed/fluid to new prop structure
  • Handling image processing options and transformations
  • Transforming member expressions for image access patterns
  • Supporting TypeScript and JSX syntax

Before:

import Img from "gatsby-image";

export const query = graphql`
  query {
    file(relativePath: { eq: "example.png" }) {
      childImageSharp {
        fixed(width: 300, height: 300) {
          ...GatsbyImageSharpFixed
        }
      }
    }
  }
`;

const MyComponent = ({ data }) => (
  <Img fixed={data.file.childImageSharp.fixed} alt="Example" />
);

After:

import { GatsbyImage } from "gatsby-plugin-image";

export const query = graphql`
  query {
    file(relativePath: { eq: "example.png" }) {
      childImageSharp {
        gatsbyImageData(width: 300, height: 300, layout: FIXED)
      }
    }
  }
`;

const MyComponent = ({ data }) => (
  <GatsbyImage image={data.file.childImageSharp.gatsbyImageData} alt="Example" />
);

File Extensions and Exclusions

All transforms automatically process these file extensions:

  • .js - JavaScript
  • .jsx - JSX (React)
  • .ts - TypeScript
  • .tsx - TypeScript JSX

All transforms automatically ignore these directories:

  • node_modules/ - Package dependencies
  • .cache/ - Gatsby cache directory
  • public/ - Gatsby build output

Error Handling

Transforms are designed to be safe and idempotent:

  • Return false when no changes are needed
  • Preserve existing code formatting where possible
  • Can be run multiple times safely
  • Use recast for AST parsing to maintain code style

Types

// JSCodeshift core types used by all transforms
interface FileInfo {
  path: string;
  source: string;
}

interface API {
  jscodeshift: JSCodeshift;
  stats: (name: string, quantity?: number) => void;
}

interface Options {
  [key: string]: any;
}

// Transform function signature
type TransformFunction = (
  file: FileInfo,
  api: API,
  options: Options
) => string | false;

// Babel-specific types for gatsby-plugin-image transform
interface BabelTypes {
  types: any;
  template: any;
}

interface BabelPlugin {
  visitor: {
    ImportDeclaration?(path: any, state: any): void;
    MemberExpression?(path: any, state: any): void;
  };
}

docs

index.md

tile.json