npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@kamaalio/codemod-kit

v0.0.42

Published

A toolkit to run codemods.

Readme

Codemod kit

A toolkit to run codemods.

Installation

pnpm add @kamaalio/codemod-kit

Usage

import { runCodemods } from '@kamaalio/codemod-kit';
import type { CodeMod } from '@kamaalio/codemod-kit';

const myCodemod: CodeMod = {
  name: 'my-codemod',
  languages: ['typescript'],
  transformer: async (content, filename) => {
    // ... transform the content
  },
};

runCodemods([myCodemod], './src');

API

runCodemods(codemods, transformationPath, options?)

Runs a list of codemods on a given path.

  • codemods: An array of Codemod objects.
  • transformationPath: The path to the directory to transform.
  • options: Optional configuration for the run.

runCodemod(codemod, transformationPath, globItems, options?)

Runs a single codemod.

  • codemod: A Codemod object.
  • transformationPath: The path to the directory to transform.
  • globItems: An array of file paths to transform.
  • options: Optional configuration for the run.

findAndReplace(content, rule, transformer)

A utility function for finding and replacing AST nodes based on a rule.

  • content: An SgRoot<TypesMap> object representing the parsed AST.
  • rule: A Rule<TypesMap> object defining the pattern to search for.
  • transformer: A function that takes a matched node and returns an optional string replacement, or a string for direct replacement.

Returns the transformed content as a string with all matching nodes replaced.

import { findAndReplace } from '@kamaalio/codemod-kit';
import { parseAsync } from '@ast-grep/napi';

const code = `
function oldFunction() {
  return "hello";
}
`;

const ast = await parseAsync('javascript', code);

// Using a function transformer
const result1 = findAndReplace(
  ast,
  { pattern: 'function oldFunction() { $$$ }' },
  node => 'function newFunction() { return "hello world"; }',
);

// Using a string transformer
const result2 = findAndReplace(
  ast,
  { pattern: 'function oldFunction() { $$$ }' },
  'function newFunction() { return "hello world"; }',
);

findAndReplaceEdits(content, rule, transformer)

A utility function for finding AST nodes and generating edit operations without committing them.

  • content: An SgRoot<TypesMap> object representing the parsed AST.
  • rule: A Rule<TypesMap> object defining the pattern to search for.
  • transformer: A function that takes a matched node and returns an optional string replacement, or a string for direct replacement.

Returns an array of Edit objects that can be committed later using commitEdits().

import { findAndReplaceEdits } from '@kamaalio/codemod-kit';
import { parseAsync } from '@ast-grep/napi';

const code = `
function oldFunction() {
  return "hello";
}
`;

const ast = await parseAsync('javascript', code);

// Using a function transformer
const edits1 = findAndReplaceEdits(
  ast,
  { pattern: 'function oldFunction() { $$$ }' },
  node => 'function newFunction() { return "hello world"; }',
);

// Using a string transformer
const edits2 = findAndReplaceEdits(
  ast,
  { pattern: 'function oldFunction() { $$$ }' },
  'function newFunction() { return "hello world"; }',
);

// Commit the edits later
const result = ast.root().commitEdits(edits1);

findAndReplaceConfig(content, lang, config)

A utility function for applying multiple find-and-replace operations sequentially on AST content.

  • content: An SgRoot<TypesMap> object representing the parsed AST.
  • lang: A NapiLang value specifying the language for re-parsing after each transformation.
  • config: An array of objects containing rule and transformer pairs to apply sequentially. The transformer can be either a function or a string.

Returns the final transformed content as a string after applying all transformations.

import { findAndReplaceConfig } from '@kamaalio/codemod-kit';
import { parseAsync } from '@ast-grep/napi';

const code = `
function oldFunction() {
  return "hello";
}
const value = 42;
`;

const ast = await parseAsync('javascript', code);
const result = await findAndReplaceConfig(ast, 'javascript', [
  {
    rule: { pattern: 'function oldFunction() { $$$ }' },
    transformer: node => 'function newFunction() { return "hello world"; }',
  },
  {
    rule: { pattern: 'const value = $VAL' },
    transformer: 'const value = 100', // String transformer
  },
]);

findAndReplaceConfigModifications(modifications, config)

A utility function for applying multiple find-and-replace operations sequentially on a Modifications object.

  • modifications: A Modifications object containing the AST, language, and transformation history.
  • config: An array of objects containing rule and transformer pairs to apply sequentially. The transformer can be either a function or a string.

Returns a Promise<Modifications> with the updated AST, accumulated edit count, and transformation history.

import { findAndReplaceConfigModifications } from '@kamaalio/codemod-kit';
import { parseAsync } from '@ast-grep/napi';

const code = `
function oldFunction() {
  return "hello";
}
const value = 42;
`;

const ast = await parseAsync('javascript', code);
const initialModifications = {
  ast,
  lang: 'javascript' as const,
  filename: 'example.js',
  report: { changesApplied: 0 },
  history: [ast],
};

const result = await findAndReplaceConfigModifications(initialModifications, [
  {
    rule: { pattern: 'function oldFunction() { $$$ }' },
    transformer: node => 'function newFunction() { return "hello world"; }',
  },
  {
    rule: { pattern: 'const value = $VAL' },
    transformer: 'const value = 100', // String transformer
  },
]);

// result.ast contains the final transformed AST
// result.report.changesApplied contains the total number of edits applied
// result.history contains the transformation history

Codemod

A codemod is defined by the Codemod type:

export type Codemod = {
  name: string;
  languages: Set<NapiLang> | Array<NapiLang>;
  transformer: (content: SgRoot<TypesMap> | string, filename?: Optional<string>) => Promise<Modifications>;
};
  • name: The name of the codemod.
  • languages: The languages the codemod applies to.
  • transformer: The function that transforms the code.

Modifications

The transformer function returns a Modifications object:

export type Modifications = {
  ast: SgRoot<TypesMap>;
  report: ModificationsReport;
  lang: NapiLang;
  filename: Optional<string>;
  history: Array<SgRoot<TypesMap>>;
};
  • ast: The modified AST.
  • report: A report of the changes.
  • lang: The language of the file.
  • filename: The name of the file.
  • history: A history of the modifications.

Hooks

You can provide hooks to customize the codemod run:

type RunCodemodHooks = {
  targetFiltering?: (filepath: string) => boolean;
  preCodemodRun?: (codemod: Codemod) => Promise<void>;
  postTransform?: (transformedContent: string) => Promise<string>;
};
  • targetFiltering: A function to filter the files to transform.
  • preCodemodRun: A function to run before each codemod.
  • postTransform: A function to run after each transformation.

Options

You can provide options to customize the codemod run:

type RunCodemodOptions = {
  hooks?: RunCodemodHooks;
  log?: boolean;
  dry?: boolean;
};
  • hooks: The hooks to use.
  • log: Whether to log the output.
  • dry: Whether to run in dry mode (no changes are written to disk).