fenge 0.7.4 → 0.7.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/package.json +5 -5
- package/src/bin/fenge.cli.js +26 -6
- package/src/utils.js +17 -29
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# fenge
|
|
2
2
|
|
|
3
|
+
## 0.7.6
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 5c5cbc9: fix: correct exit code
|
|
8
|
+
- Updated dependencies [db50469]
|
|
9
|
+
- @fenge/eslint-config@0.6.6
|
|
10
|
+
|
|
11
|
+
## 0.7.5
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- @fenge/eslint-config@0.6.5
|
|
16
|
+
|
|
3
17
|
## 0.7.4
|
|
4
18
|
|
|
5
19
|
### Patch Changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fenge",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.6",
|
|
4
4
|
"description": "A CLI tool for code quality",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cli",
|
|
@@ -51,14 +51,14 @@
|
|
|
51
51
|
"ora": "8.2.0",
|
|
52
52
|
"prettier": "3.5.3",
|
|
53
53
|
"yoctocolors": "2.1.1",
|
|
54
|
-
"@fenge/eslint-config": "0.6.
|
|
54
|
+
"@fenge/eslint-config": "0.6.6",
|
|
55
55
|
"@fenge/prettier-config": "0.3.0",
|
|
56
56
|
"@fenge/tsconfig": "0.5.0",
|
|
57
|
-
"
|
|
58
|
-
"
|
|
57
|
+
"prettier-ignore": "0.3.0",
|
|
58
|
+
"@fenge/types": "0.3.0"
|
|
59
59
|
},
|
|
60
60
|
"devDependencies": {
|
|
61
|
-
"@types/node": "22.
|
|
61
|
+
"@types/node": "22.14.1"
|
|
62
62
|
},
|
|
63
63
|
"peerDependencies": {
|
|
64
64
|
"typescript": "^5.7.0"
|
package/src/bin/fenge.cli.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// @ts-check
|
|
3
|
+
import os from "node:os";
|
|
3
4
|
import process from "node:process";
|
|
4
5
|
import { initAction, setup } from "@fenge/tsconfig/setup";
|
|
5
6
|
import { Command } from "commander";
|
|
@@ -9,6 +10,22 @@ import { install } from "../command/install.js";
|
|
|
9
10
|
import { lint } from "../command/lint.js";
|
|
10
11
|
import { uninstall } from "../command/uninstall.js";
|
|
11
12
|
|
|
13
|
+
/**
|
|
14
|
+
* @param {{code: number|null, signal: NodeJS.Signals | null}} param
|
|
15
|
+
* @returns {never}
|
|
16
|
+
*/
|
|
17
|
+
function exit({ code, signal }) {
|
|
18
|
+
if (code !== null) {
|
|
19
|
+
process.exit(code);
|
|
20
|
+
} else if (signal !== null) {
|
|
21
|
+
process.exit(128 + os.constants.signals[signal]);
|
|
22
|
+
} else {
|
|
23
|
+
throw new Error(
|
|
24
|
+
"Internal Error. Code and signal should not be null at the same time.",
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
12
29
|
const program = new Command().enablePositionalOptions();
|
|
13
30
|
|
|
14
31
|
program
|
|
@@ -35,11 +52,14 @@ program
|
|
|
35
52
|
)
|
|
36
53
|
.argument("[paths...]", "dir or file paths to format and lint")
|
|
37
54
|
.action(async (paths, options) => {
|
|
38
|
-
let
|
|
39
|
-
if (
|
|
40
|
-
|
|
55
|
+
let result = await format(paths, options);
|
|
56
|
+
if (result.code === 0) {
|
|
57
|
+
result = await lint(paths, options);
|
|
58
|
+
if (result.code === 0) {
|
|
59
|
+
result = await format(paths, options);
|
|
60
|
+
}
|
|
41
61
|
}
|
|
42
|
-
|
|
62
|
+
exit(result);
|
|
43
63
|
});
|
|
44
64
|
|
|
45
65
|
program
|
|
@@ -58,7 +78,7 @@ program
|
|
|
58
78
|
"print what command will be executed under the hood instead of executing",
|
|
59
79
|
)
|
|
60
80
|
.argument("[paths...]", "dir or file paths to lint")
|
|
61
|
-
.action(async (paths, options) =>
|
|
81
|
+
.action(async (paths, options) => exit(await lint(paths, options)));
|
|
62
82
|
|
|
63
83
|
program
|
|
64
84
|
.command("format")
|
|
@@ -75,7 +95,7 @@ program
|
|
|
75
95
|
"print what command will be executed under the hood instead of executing",
|
|
76
96
|
)
|
|
77
97
|
.argument("[paths...]", "dir or file paths to format")
|
|
78
|
-
.action(async (paths, options) =>
|
|
98
|
+
.action(async (paths, options) => exit(await format(paths, options)));
|
|
79
99
|
|
|
80
100
|
program
|
|
81
101
|
.command("install")
|
package/src/utils.js
CHANGED
|
@@ -58,7 +58,7 @@ function getSpentTime(startTime) {
|
|
|
58
58
|
/**
|
|
59
59
|
* @param {string[]} command
|
|
60
60
|
* @param {{topic: string, dryRun: boolean, env: Record<string, string>}} options
|
|
61
|
-
* @returns {Promise<number>}
|
|
61
|
+
* @returns {Promise<{code: number|null, signal: NodeJS.Signals | null}>}
|
|
62
62
|
*/
|
|
63
63
|
export function execAsync(command, { topic, dryRun, env }) {
|
|
64
64
|
return new Promise((resolve, reject) => {
|
|
@@ -70,11 +70,14 @@ export function execAsync(command, { topic, dryRun, env }) {
|
|
|
70
70
|
}
|
|
71
71
|
if (dryRun) {
|
|
72
72
|
process.stdout.write(`${colors.green(cmd)} ${args.join(" ")};\n\n`);
|
|
73
|
-
return resolve(0);
|
|
73
|
+
return resolve({ code: 0, signal: null });
|
|
74
74
|
}
|
|
75
75
|
|
|
76
76
|
const spinner = ora(`${topic}...`).start();
|
|
77
|
-
|
|
77
|
+
/**
|
|
78
|
+
* @type {childProcess.ChildProcessWithoutNullStreams | undefined}
|
|
79
|
+
*/
|
|
80
|
+
let cp = childProcess.spawn(cmd, args, {
|
|
78
81
|
env: { FORCE_COLOR: "true", ...process.env, ...env },
|
|
79
82
|
});
|
|
80
83
|
let stdout = Buffer.alloc(0);
|
|
@@ -86,18 +89,13 @@ export function execAsync(command, { topic, dryRun, env }) {
|
|
|
86
89
|
stderr = Buffer.concat([stderr, data]);
|
|
87
90
|
});
|
|
88
91
|
cp.on("error", (err) => {
|
|
89
|
-
|
|
90
|
-
`${topic} got error in ${colors.yellow(getSpentTime(startTime))}`,
|
|
91
|
-
);
|
|
92
|
-
process.stderr.write(err.message);
|
|
93
|
-
resolve(getExitCode(err));
|
|
92
|
+
reject(err);
|
|
94
93
|
});
|
|
95
94
|
// Why not listen to the 'exit' event?
|
|
96
95
|
// 1. The 'close' event will always emit after 'exit' was already emitted, or 'error' if the child failed to spawn.
|
|
97
96
|
// 2. The 'exit' event may or may not fire after an error has occurred.
|
|
98
97
|
cp.on("close", (code, signal) => {
|
|
99
|
-
|
|
100
|
-
if (exitCode === 0) {
|
|
98
|
+
if (code === 0) {
|
|
101
99
|
spinner.succeed(
|
|
102
100
|
`${topic} succeeded in ${colors.yellow(getSpentTime(startTime))}`,
|
|
103
101
|
);
|
|
@@ -108,27 +106,17 @@ export function execAsync(command, { topic, dryRun, env }) {
|
|
|
108
106
|
}
|
|
109
107
|
process.stdout.write(stdout);
|
|
110
108
|
process.stderr.write(stderr);
|
|
111
|
-
|
|
109
|
+
cp = undefined; // When the cp exited, we should clean cp to prevent memory leak.
|
|
110
|
+
resolve({ code, signal });
|
|
112
111
|
});
|
|
113
|
-
process.on("SIGINT", () => !cp.killed && cp.kill("SIGINT"));
|
|
114
|
-
process.on("SIGTERM", () => !cp.killed && cp.kill("SIGTERM"));
|
|
115
|
-
});
|
|
116
|
-
}
|
|
117
112
|
|
|
118
|
-
/**
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
}
|
|
125
|
-
if ("signal" in error && error.signal === "SIGTERM") {
|
|
126
|
-
return 15;
|
|
127
|
-
}
|
|
128
|
-
if ("code" in error && typeof error.code === "number") {
|
|
129
|
-
return error.code;
|
|
130
|
-
}
|
|
131
|
-
return 1;
|
|
113
|
+
/**
|
|
114
|
+
* @param {NodeJS.Signals} signal
|
|
115
|
+
*/
|
|
116
|
+
const listener = (signal) => cp && !cp.killed && cp.kill(signal);
|
|
117
|
+
process.on("SIGINT", listener);
|
|
118
|
+
process.on("SIGTERM", listener);
|
|
119
|
+
});
|
|
132
120
|
}
|
|
133
121
|
|
|
134
122
|
/**
|