]> git.proxmox.com Git - pve-eslint.git/blob - eslint/lib/shared/runtime-info.js
import 8.41.0 source
[pve-eslint.git] / eslint / lib / shared / runtime-info.js
1 /**
2 * @fileoverview Utility to get information about the execution environment.
3 * @author Kai Cataldo
4 */
5
6 "use strict";
7
8 //------------------------------------------------------------------------------
9 // Requirements
10 //------------------------------------------------------------------------------
11
12 const path = require("path");
13 const spawn = require("cross-spawn");
14 const os = require("os");
15 const log = require("../shared/logging");
16 const packageJson = require("../../package.json");
17
18 //------------------------------------------------------------------------------
19 // Helpers
20 //------------------------------------------------------------------------------
21
22 /**
23 * Generates and returns execution environment information.
24 * @returns {string} A string that contains execution environment information.
25 */
26 function environment() {
27 const cache = new Map();
28
29 /**
30 * Checks if a path is a child of a directory.
31 * @param {string} parentPath The parent path to check.
32 * @param {string} childPath The path to check.
33 * @returns {boolean} Whether or not the given path is a child of a directory.
34 */
35 function isChildOfDirectory(parentPath, childPath) {
36 return !path.relative(parentPath, childPath).startsWith("..");
37 }
38
39 /**
40 * Synchronously executes a shell command and formats the result.
41 * @param {string} cmd The command to execute.
42 * @param {Array} args The arguments to be executed with the command.
43 * @throws {Error} As may be collected by `cross-spawn.sync`.
44 * @returns {string} The version returned by the command.
45 */
46 function execCommand(cmd, args) {
47 const key = [cmd, ...args].join(" ");
48
49 if (cache.has(key)) {
50 return cache.get(key);
51 }
52
53 const process = spawn.sync(cmd, args, { encoding: "utf8" });
54
55 if (process.error) {
56 throw process.error;
57 }
58
59 const result = process.stdout.trim();
60
61 cache.set(key, result);
62 return result;
63 }
64
65 /**
66 * Normalizes a version number.
67 * @param {string} versionStr The string to normalize.
68 * @returns {string} The normalized version number.
69 */
70 function normalizeVersionStr(versionStr) {
71 return versionStr.startsWith("v") ? versionStr : `v${versionStr}`;
72 }
73
74 /**
75 * Gets bin version.
76 * @param {string} bin The bin to check.
77 * @throws {Error} As may be collected by `cross-spawn.sync`.
78 * @returns {string} The normalized version returned by the command.
79 */
80 function getBinVersion(bin) {
81 const binArgs = ["--version"];
82
83 try {
84 return normalizeVersionStr(execCommand(bin, binArgs));
85 } catch (e) {
86 log.error(`Error finding ${bin} version running the command \`${bin} ${binArgs.join(" ")}\``);
87 throw e;
88 }
89 }
90
91 /**
92 * Gets installed npm package version.
93 * @param {string} pkg The package to check.
94 * @param {boolean} global Whether to check globally or not.
95 * @throws {Error} As may be collected by `cross-spawn.sync`.
96 * @returns {string} The normalized version returned by the command.
97 */
98 function getNpmPackageVersion(pkg, { global = false } = {}) {
99 const npmBinArgs = ["bin", "-g"];
100 const npmLsArgs = ["ls", "--depth=0", "--json", pkg];
101
102 if (global) {
103 npmLsArgs.push("-g");
104 }
105
106 try {
107 const parsedStdout = JSON.parse(execCommand("npm", npmLsArgs));
108
109 /*
110 * Checking globally returns an empty JSON object, while local checks
111 * include the name and version of the local project.
112 */
113 if (Object.keys(parsedStdout).length === 0 || !(parsedStdout.dependencies && parsedStdout.dependencies.eslint)) {
114 return "Not found";
115 }
116
117 const [, processBinPath] = process.argv;
118 let npmBinPath;
119
120 try {
121 npmBinPath = execCommand("npm", npmBinArgs);
122 } catch (e) {
123 log.error(`Error finding npm binary path when running command \`npm ${npmBinArgs.join(" ")}\``);
124 throw e;
125 }
126
127 const isGlobal = isChildOfDirectory(npmBinPath, processBinPath);
128 let pkgVersion = parsedStdout.dependencies.eslint.version;
129
130 if ((global && isGlobal) || (!global && !isGlobal)) {
131 pkgVersion += " (Currently used)";
132 }
133
134 return normalizeVersionStr(pkgVersion);
135 } catch (e) {
136 log.error(`Error finding ${pkg} version running the command \`npm ${npmLsArgs.join(" ")}\``);
137 throw e;
138 }
139 }
140
141 return [
142 "Environment Info:",
143 "",
144 `Node version: ${getBinVersion("node")}`,
145 `npm version: ${getBinVersion("npm")}`,
146 `Local ESLint version: ${getNpmPackageVersion("eslint", { global: false })}`,
147 `Global ESLint version: ${getNpmPackageVersion("eslint", { global: true })}`,
148 `Operating System: ${os.platform()} ${os.release()}`
149 ].join("\n");
150 }
151
152 /**
153 * Returns version of currently executing ESLint.
154 * @returns {string} The version from the currently executing ESLint's package.json.
155 */
156 function version() {
157 return `v${packageJson.version}`;
158 }
159
160 //------------------------------------------------------------------------------
161 // Public Interface
162 //------------------------------------------------------------------------------
163
164 module.exports = {
165 environment,
166 version
167 };