@jssg/utils provides reusable utility functions for JSSG codemods. These helpers handle common import manipulation tasks that are tedious and error-prone when done manually with AST queries.
Installation
Add@jssg/utils to your codemod project:
package.json
Import
These utilities work with JavaScript, TypeScript, JSX, and TSX ASTs. They handle both ESM (
import) and CJS (require()) formats automatically.getImport
Locate an import of a given module and return its alias/identifier node.
Parameters
The root program node to search within.
What to look for:
{ type: "default", from: string }— Find the default import from a module.{ type: "named", name: string, from: string }— Find a specific named import from a module.
Returns
GetImportResult<T> | null — An object containing:
| Field | Type | Description |
|---|---|---|
alias | string | The local name used at call sites (e.g., baz in import { foo as baz }) |
isNamespace | boolean | true if the import is import * as xyz from '...' |
moduleType | "esm" | "cjs" | Whether the import is ESM (import) or CJS (require()) |
node | SgNode<T, "identifier"> | The identifier AST node for the local binding |
null if the import is not found.
Supported Import Shapes
| Format | Example |
|---|---|
| ESM default | import foo from "module" |
| ESM named | import { bar } from "module" |
| ESM aliased | import { bar as baz } from "module" |
| ESM namespace | import * as foo from "module" |
| ESM bare | import "module" |
| CJS default | const foo = require("module") |
| CJS destructured | const { bar } = require("module") |
| CJS aliased | const { bar: baz } = require("module") |
| Dynamic import | const foo = await import("module") |
Example
addImport
Add an import to the program. Smart behavior:
- Skips if the import already exists
- Merges named specifiers into an existing import statement from the same source
- Creates a new import statement otherwise
- Inserts after the last existing import (or at file start if no imports exist)
Parameters
The root program node.
One of:
{ type: "default", name: string, from: string, moduleType?: "esm" | "cjs" }— Add a default import.{ type: "namespace", name: string, from: string }— Add a namespace import (import * as name).{ type: "named", specifiers: Array<{ name: string, alias?: string }>, from: string, moduleType?: "esm" | "cjs" }— Add named imports.
Returns
Edit | null — An edit to apply via rootNode.commitEdits(), or null if the import already exists.
Example
removeImport
Remove an import from the program. Smart behavior:
- Default/namespace: Removes the entire import statement.
- Named (multiple specifiers): Removes only the specified specifiers, keeping the rest.
- Named (last specifier): Removes the entire import statement.
- Handles both ESM and CJS formats.
Parameters
The root program node.
One of:
{ type: "default", from: string }— Remove the default import from a module.{ type: "namespace", from: string }— Remove the namespace import from a module.{ type: "named", specifiers: string[], from: string }— Remove specific named imports.
Returns
Edit | null — An edit to apply via rootNode.commitEdits(), or null if the import was not found.
Example
stringToExactRegexString
Escape a string for use as an exact-match regex pattern. Wraps in ^...$ and escapes special characters.
Common Patterns
Verify Import Before Transforming
Always verify that a symbol is imported from the expected package before transforming its usage:Replace One Import With Another
Match Existing Module Style
getImport automatically detects the module type. Use moduleType when adding imports to match the existing style: