Replacing `console.log` with custom `logger`
readme.mdMarkdownreplace-console-with-logger.jsJavaScript
readme.md
Setup Instructions
1. Install Dependencies
Install jscodeshift
globally if not already installed:
npm install -g jscodeshift
Install dev dependencies
npm i -D @babel/parser @babel/traverse @babel/types @babel/generator
2. Run the Codemod
Run the codemod across your project with the following command:
jscodeshift -t replace-console-with-logger.js --parser=babel --extensions=ts,tsx,js,jsx src/
Explanation of Options:
-t replace-console-with-logger.js
: Specifies the codemod script.--extensions=ts,tsx,js,jsx
: Tellsjscodeshift
to process files with these extensions.--parser=babel-ts
: Uses Babel to parse TypeScript and JavaScript.src/
: The root directory of your source files.
Testing the Codemod
- Choose a small subset of your files and run the codemod on them:
jscodeshift -t replace-console-with-logger.js --extensions=ts,tsx,js,jsx --parser=babel-ts src/some/subdirectory
- Verify that:
- All
console.log
,console.warn
, andconsole.error
are replaced withlogger.log
,logger.warn
, andlogger.error
. import { logger } from "~/logger";
is correctly added at the top of the file (if not already present).
- All
Handling Edge Cases
If you encounter any parsing issues, ensure that:
- The project uses valid TypeScript/JavaScript syntax.
- JSX components are properly structured.
replace-console-with-logger.js
const { parse } = require("@babel/parser");
const traverse = require("@babel/traverse").default;
const t = require("@babel/types");
const generate = require("@babel/generator").default;
module.exports = function transformer(fileInfo, api) {
const j = api.jscodeshift;
const source = fileInfo.source;
const ast = parse(source, {
sourceType: "module",
plugins: ["typescript", "jsx"], // Support TS, TSX, JS, and JSX syntax
});
let loggerImported = false;
// Check if `logger` is already imported
traverse(ast, {
ImportDeclaration(path) {
if (path.node.source.value === "~/logger") {
loggerImported = true;
}
},
});
if (!loggerImported) {
// Add `import { logger } from "~/logger";` at the top
const importDeclaration = t.importDeclaration(
[t.importSpecifier(t.identifier("logger"), t.identifier("logger"))],
t.stringLiteral("~/logger")
);
ast.program.body.unshift(importDeclaration);
}
// Replace console.* calls with logger.*
traverse(ast, {
CallExpression(path) {
const callee = path.node.callee;
if (
t.isMemberExpression(callee) &&
t.isIdentifier(callee.object, { name: "console" }) &&
["log", "warn", "error"].includes(callee.property.name)
) {
const loggerMethod = t.memberExpression(
t.identifier("logger"),
t.identifier(callee.property.name)
);
path.node.callee = loggerMethod;
}
},
});
return generate(ast).code;
};
Updated: 12/3/2024