Utilities for finding ES module imports, CommonJS requires, and dynamic imports for specific Node.js modules.
Overview
These utilities help locate module dependencies in different formats:
- ES Module Imports:
import fs from 'fs' or import { readFile } from 'node:fs'
- CommonJS Requires:
const fs = require('fs') or const { readFile } = require('node:fs')
- Dynamic Imports:
const fs = await import('fs')
All detection functions automatically support both bare module names ('fs') and node: prefixed imports ('node:fs').
Core Functions
getModuleDependencies
Finds all module import/require statements for a specific Node.js module. This is the most comprehensive function that combines results from all other detection methods.
import { getModuleDependencies } from '@nodejs/codemod-utils/ast-grep/module-dependencies';
const ast = context.getAST();
const fsImports = getModuleDependencies(ast, 'fs');
// Finds:
// - import fs from 'fs';
// - import { readFile } from 'node:fs';
// - const fs = require('fs')
// - const fs = await import('fs')
The root AST node to search
The Node.js module name to search for (e.g., ‘fs’, ‘path’, ‘util’)
Returns: SgNode<Js>[] - Array of nodes representing all import/require statements for the module
Under the hood, this function calls getNodeRequireCalls, getNodeImportStatements, and getNodeImportCalls, then combines the results.
ES Module Import Detection
getNodeImportStatements
Finds all ES module import statements for a specific Node.js module.
import { getNodeImportStatements } from '@nodejs/codemod-utils/ast-grep/import-statement';
// Finds: import fs from 'fs';
// Finds: import { readFile } from 'node:fs';
// Finds: import * as fs from 'fs';
const fsImports = getNodeImportStatements(ast, 'fs');
The root AST node to search
The Node.js module name to search for
Returns: SgNode<Js>[] - Array of import_statement nodes
getNodeImportCalls
Finds dynamic import calls assigned to variables. Excludes unassigned imports.
import { getNodeImportCalls } from '@nodejs/codemod-utils/ast-grep/import-statement';
// Finds: const fs = await import('node:fs');
// Finds: import('fs').then(fs => ...);
// Ignores: import('fs'); // unassigned
const fsImportCalls = getNodeImportCalls(ast, 'fs');
The root AST node to search
The Node.js module name to search for
Returns: SgNode<Js>[] - Array of variable_declarator or expression_statement nodes with import calls
This function captures both const fs = await import('fs') patterns and .then() chained patterns like import('fs').then(...), but ignores simple unassigned import('fs') calls.
CommonJS Require Detection
getNodeRequireCalls
Finds CommonJS require calls assigned to variables.
import { getNodeRequireCalls } from '@nodejs/codemod-utils/ast-grep/require-call';
// Finds: const fs = require('fs');
// Finds: const { readFile } = require('node:fs');
// Finds: const readFile = require('fs').readFile;
const fsRequires = getNodeRequireCalls(ast, 'fs');
The root AST node to search
The Node.js module name to search for
Returns: SgNode<Js>[] - Array of variable_declarator nodes with require calls
Simple require('fs') calls without variable assignment are not captured, as they have no effect in codemod context.
Usage Examples
Finding All FS Module Usage
const ast = context.getAST();
const allFsUsage = getModuleDependencies(ast, 'fs');
if (allFsUsage.length > 0) {
console.log(`Found ${allFsUsage.length} fs module imports/requires`);
for (const usage of allFsUsage) {
console.log(usage.text());
}
}
Detecting Import Style
const esImports = getNodeImportStatements(ast, 'util');
const cjsRequires = getNodeRequireCalls(ast, 'util');
const dynamicImports = getNodeImportCalls(ast, 'util');
if (esImports.length > 0 && cjsRequires.length > 0) {
console.warn('Mixed import styles detected!');
}
Processing All Module Imports
import { getModuleDependencies } from '@nodejs/codemod-utils/ast-grep/module-dependencies';
import { resolveBindingPath } from '@nodejs/codemod-utils/ast-grep/resolve-binding-path';
const utilImports = getModuleDependencies(ast, 'util');
for (const importNode of utilImports) {
// Resolve how types.isNativeError should be accessed
const path = resolveBindingPath(importNode, '$.types.isNativeError');
if (path) {
console.log(`Access pattern: ${path}`);
// Could be: 'types.isNativeError', 'util.types.isNativeError', etc.
}
}
Migration Example: Consolidating Imports
const fsImports = getModuleDependencies(ast, 'fs');
if (fsImports.length > 1) {
// Multiple fs imports detected - could consolidate them
console.log('Consider consolidating multiple fs imports');
const allBindings = [];
for (const imp of fsImports) {
// Extract bindings from each import
const bindings = imp.findAll({
rule: { kind: 'identifier' }
});
allBindings.push(...bindings.map(b => b.text()));
}
console.log('All bindings:', allBindings);
}