Skip to content

Commit f55edef

Browse files
feat(util-log): introduce (#181)
Co-authored-by: Augustin Mauroy <[email protected]>
1 parent e7d43ce commit f55edef

23 files changed

+304
-4
lines changed

package-lock.json

Lines changed: 17 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# `util.log` DEP0059
2+
3+
This recipe transforms the usage of `log.util()` to use `console.log()`.
4+
5+
See [DEP0059](https://nodejs.org/api/deprecations.html#DEP0059).
6+
7+
## Example
8+
9+
**Before:**
10+
11+
```js
12+
const util = require("node:util");
13+
14+
util.log("Hello world");
15+
```
16+
17+
**After:**
18+
19+
```js
20+
console.log(new Date().toLocaleString(), "Hello world");
21+
```
22+
23+
**Before:**
24+
25+
```js
26+
const { log } = require("node:util");
27+
28+
log("Application started");
29+
log("Processing request");
30+
```
31+
32+
After:
33+
34+
```js
35+
console.log(new Date().toLocaleString(), "Application started");
36+
console.log(new Date().toLocaleString(), "Processing request");
37+
```
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
schema_version: "1.0"
2+
name: "@nodejs/util-log-to-console-log"
3+
version: 1.0.0
4+
description: Handle DEP0059 via transforming `log.util()` to `console.log()`.
5+
author: Bruno Rodrigues
6+
license: MIT
7+
workflow: workflow.yaml
8+
category: migration
9+
10+
targets:
11+
languages:
12+
- javascript
13+
- typescript
14+
15+
keywords:
16+
- transformation
17+
- migration
18+
19+
registry:
20+
access: public
21+
visibility: public
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
"name": "@nodejs/util-log-to-console-log",
3+
"version": "1.0.0",
4+
"description": "Handle DEP0059 via transforming `log.util()` to `console.log()`",
5+
"type": "module",
6+
"scripts": {
7+
"test": "npx codemod jssg test -l typescript ./src/workflow.ts ./"
8+
},
9+
"repository": {
10+
"type": "git",
11+
"url": "git+https://github.com/nodejs/userland-migrations.git",
12+
"directory": "recipes/util-log-to-console-log",
13+
"bugs": "https://github.com/nodejs/userland-migrations/issues"
14+
},
15+
"author": "Bruno Rodrigues",
16+
"license": "MIT",
17+
"homepage": "https://github.com/nodejs/userland-migrations/blob/main/recipes/util-log-to-console-log/README.md",
18+
"devDependencies": {
19+
"@codemod.com/jssg-types": "^1.0.3"
20+
},
21+
"dependencies": {
22+
"@nodejs/codemod-utils": "*"
23+
}
24+
}
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
import type {
2+
Edit,
3+
Kinds,
4+
Range,
5+
Rule,
6+
SgNode,
7+
SgRoot,
8+
TypesMap,
9+
} from "@codemod.com/jssg-types/main";
10+
import { getNodeRequireCalls } from "@nodejs/codemod-utils/ast-grep/require-call";
11+
import { getNodeImportStatements } from "@nodejs/codemod-utils/ast-grep/import-statement";
12+
import { resolveBindingPath } from "@nodejs/codemod-utils/ast-grep/resolve-binding-path";
13+
import { removeBinding } from "@nodejs/codemod-utils/ast-grep/remove-binding";
14+
import { removeLines } from "@nodejs/codemod-utils/ast-grep/remove-lines";
15+
16+
type BindingToReplace = {
17+
rule: Rule<TypesMap>;
18+
node: SgNode<TypesMap, Kinds<TypesMap>>;
19+
binding: string;
20+
};
21+
22+
/*
23+
* Transforms `util.log($$$ARG)` usage to `console.log(new Date().toLocaleString(), $$$ARG)`.
24+
*
25+
* Steps:
26+
*
27+
* Locate all util.log imports, noting the replacement rule, import node, and binding name.
28+
*
29+
* For each binding, replace calls to util.log($$$ARG) with the new console.log format,
30+
* and determine if the import line should be updated or removed.
31+
*
32+
* Apply all changes, removing or updating the import line as needed.
33+
*/
34+
export default function transform(root: SgRoot): string | null {
35+
const rootNode = root.root();
36+
const edits: Edit[] = [];
37+
const linesToRemove: Range[] = [];
38+
const bindsToReplace: BindingToReplace[] = [];
39+
40+
const nodeRequires = getNodeRequireCalls(root, "util");
41+
const nodeImports = getNodeImportStatements(root, "util");
42+
const path = "$.log";
43+
const importRequireStatement = [...nodeRequires, ...nodeImports];
44+
45+
if (!importRequireStatement.length) return null;
46+
47+
for (const node of importRequireStatement) {
48+
const bind = resolveBindingPath(node, path);
49+
50+
// if `log` function ins't coming from `node:util`
51+
if (!bind) continue;
52+
53+
bindsToReplace.push({
54+
rule: {
55+
pattern: `${bind}($$$ARG)`,
56+
},
57+
node,
58+
binding: bind,
59+
});
60+
}
61+
62+
for (const bind of bindsToReplace) {
63+
const matches = rootNode.findAll({
64+
rule: bind.rule,
65+
});
66+
67+
for (const match of matches) {
68+
const args = match.getMultipleMatches("ARG");
69+
70+
const argsStr = args
71+
.map((arg) => {
72+
const text = arg.text();
73+
if (text === ",") {
74+
// if arg is a comman, add a space at end
75+
return text.padEnd(2, " ");
76+
}
77+
return text;
78+
})
79+
.join("");
80+
81+
edits.push(match.replace(`console.log(new Date().toLocaleString(), ${argsStr})`));
82+
}
83+
84+
const result = removeBinding(bind.node, bind.binding.split(".").at(0));
85+
86+
if (result?.lineToRemove) {
87+
linesToRemove.push(result.lineToRemove);
88+
}
89+
90+
if (result?.edit) {
91+
edits.push(result.edit);
92+
}
93+
}
94+
95+
if (!edits.length) return;
96+
97+
const sourceCode = rootNode.commitEdits(edits);
98+
99+
return removeLines(sourceCode, linesToRemove);
100+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
2+
console.log(new Date().toLocaleString(), "Server listening on port 3000");
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
2+
console.log(new Date().toLocaleString(), "Debug message");
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
2+
console.log(new Date().toLocaleString(), "User:", "john", "logged in");
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
const { inspect } = require("node:util");
2+
3+
console.log(new Date().toLocaleString(), "Starting application");
4+
const formatted = inspect({ foo: "bar" });
5+
console.log(formatted);
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
2+
console.log(new Date().toLocaleString(), "Application started");
3+
console.log(new Date().toLocaleString(), "Processing request");

0 commit comments

Comments
 (0)