@paa1997/metho 1.0.6 → 1.0.7
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/package.json +1 -1
- package/src/tools/installer.js +38 -13
- package/src/tools/manager.js +5 -5
package/package.json
CHANGED
package/src/tools/installer.js
CHANGED
|
@@ -1,13 +1,40 @@
|
|
|
1
|
-
import { execSync } from 'child_process';
|
|
1
|
+
import { exec, execSync } from 'child_process';
|
|
2
2
|
import { existsSync, mkdirSync } from 'fs';
|
|
3
3
|
import { join } from 'path';
|
|
4
4
|
|
|
5
5
|
const isWin = process.platform === 'win32';
|
|
6
6
|
|
|
7
|
+
function execAsync(cmd, options = {}) {
|
|
8
|
+
return new Promise((resolve, reject) => {
|
|
9
|
+
exec(cmd, options, (err, stdout, stderr) => {
|
|
10
|
+
if (err) {
|
|
11
|
+
err.stdout = stdout;
|
|
12
|
+
err.stderr = stderr;
|
|
13
|
+
reject(err);
|
|
14
|
+
} else {
|
|
15
|
+
resolve({ stdout, stderr });
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
|
|
7
21
|
/**
|
|
8
22
|
* Check if a binary is available on PATH.
|
|
9
23
|
*/
|
|
10
|
-
export function isBinaryAvailable(binary) {
|
|
24
|
+
export async function isBinaryAvailable(binary) {
|
|
25
|
+
try {
|
|
26
|
+
const cmd = isWin ? `where ${binary}` : `which ${binary}`;
|
|
27
|
+
await execAsync(cmd, { stdio: 'pipe' });
|
|
28
|
+
return true;
|
|
29
|
+
} catch {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Synchronous version for quick checks that don't need to yield.
|
|
36
|
+
*/
|
|
37
|
+
export function isBinaryAvailableSync(binary) {
|
|
11
38
|
try {
|
|
12
39
|
const cmd = isWin ? `where ${binary}` : `which ${binary}`;
|
|
13
40
|
execSync(cmd, { stdio: 'pipe' });
|
|
@@ -20,9 +47,9 @@ export function isBinaryAvailable(binary) {
|
|
|
20
47
|
/**
|
|
21
48
|
* Check if httpx on PATH is ProjectDiscovery's version (not Python's httpx CLI).
|
|
22
49
|
*/
|
|
23
|
-
export function isProjectDiscoveryHttpx() {
|
|
50
|
+
export async function isProjectDiscoveryHttpx() {
|
|
24
51
|
try {
|
|
25
|
-
|
|
52
|
+
await execAsync('httpx -version', { stdio: 'pipe', timeout: 5000 });
|
|
26
53
|
return true;
|
|
27
54
|
} catch (err) {
|
|
28
55
|
const stderr = err.stderr ? err.stderr.toString() : '';
|
|
@@ -42,13 +69,13 @@ export function isProjectDiscoveryHttpx() {
|
|
|
42
69
|
* Attempt to install a tool using its install command (globally via go install).
|
|
43
70
|
* Returns true if install succeeded, false otherwise.
|
|
44
71
|
*/
|
|
45
|
-
export function attemptInstall(toolDef, logger) {
|
|
72
|
+
export async function attemptInstall(toolDef, logger) {
|
|
46
73
|
if (!toolDef.installCmd) {
|
|
47
74
|
return false;
|
|
48
75
|
}
|
|
49
76
|
|
|
50
77
|
if (toolDef.installCmd.startsWith('go install')) {
|
|
51
|
-
if (!isBinaryAvailable('go')) {
|
|
78
|
+
if (!await isBinaryAvailable('go')) {
|
|
52
79
|
logger.warn('Go is not installed. Cannot auto-install Go tools.');
|
|
53
80
|
logger.warn('Install Go from https://go.dev/dl/ and ensure GOPATH/bin is in PATH.');
|
|
54
81
|
return false;
|
|
@@ -57,12 +84,11 @@ export function attemptInstall(toolDef, logger) {
|
|
|
57
84
|
|
|
58
85
|
logger.info(`Installing ${toolDef.binary}: ${toolDef.installCmd}`);
|
|
59
86
|
try {
|
|
60
|
-
|
|
61
|
-
stdio: 'pipe',
|
|
87
|
+
await execAsync(toolDef.installCmd, {
|
|
62
88
|
timeout: 120000,
|
|
63
89
|
env: { ...process.env },
|
|
64
90
|
});
|
|
65
|
-
return isBinaryAvailable(toolDef.binary);
|
|
91
|
+
return await isBinaryAvailable(toolDef.binary);
|
|
66
92
|
} catch (err) {
|
|
67
93
|
logger.debug(`Install failed for ${toolDef.binary}: ${err.message}`);
|
|
68
94
|
return false;
|
|
@@ -73,12 +99,12 @@ export function attemptInstall(toolDef, logger) {
|
|
|
73
99
|
* Install a Go tool to a local directory instead of GOPATH/bin.
|
|
74
100
|
* Returns the full path to the installed binary, or null on failure.
|
|
75
101
|
*/
|
|
76
|
-
export function installToLocal(toolDef, localBinDir, logger) {
|
|
102
|
+
export async function installToLocal(toolDef, localBinDir, logger) {
|
|
77
103
|
if (!toolDef.installCmd || !toolDef.installCmd.startsWith('go install')) {
|
|
78
104
|
return null;
|
|
79
105
|
}
|
|
80
106
|
|
|
81
|
-
if (!isBinaryAvailable('go')) {
|
|
107
|
+
if (!await isBinaryAvailable('go')) {
|
|
82
108
|
logger.warn('Go is not installed. Cannot auto-install Go tools.');
|
|
83
109
|
logger.warn('Install Go from https://go.dev/dl/ and ensure GOPATH/bin is in PATH.');
|
|
84
110
|
return null;
|
|
@@ -91,8 +117,7 @@ export function installToLocal(toolDef, localBinDir, logger) {
|
|
|
91
117
|
|
|
92
118
|
logger.info(`Installing ${toolDef.binary} to ${localBinDir}...`);
|
|
93
119
|
try {
|
|
94
|
-
|
|
95
|
-
stdio: 'pipe',
|
|
120
|
+
await execAsync(toolDef.installCmd, {
|
|
96
121
|
timeout: 120000,
|
|
97
122
|
env: { ...process.env, GOBIN: localBinDir },
|
|
98
123
|
});
|
package/src/tools/manager.js
CHANGED
|
@@ -48,13 +48,13 @@ export async function ensureTools(config, logger) {
|
|
|
48
48
|
|
|
49
49
|
logger.debug(`Checking for ${toolName} (${toolDef.binary})...`);
|
|
50
50
|
|
|
51
|
-
if (isBinaryAvailable(toolDef.binary)) {
|
|
51
|
+
if (await isBinaryAvailable(toolDef.binary)) {
|
|
52
52
|
// Special check: verify httpx is ProjectDiscovery's, not Python's
|
|
53
|
-
if (toolName === 'httpx' && !isProjectDiscoveryHttpx()) {
|
|
53
|
+
if (toolName === 'httpx' && !await isProjectDiscoveryHttpx()) {
|
|
54
54
|
logger.warn('Found Python\'s httpx on PATH (not ProjectDiscovery\'s)');
|
|
55
55
|
logger.info('Installing ProjectDiscovery httpx locally to avoid conflict...');
|
|
56
56
|
|
|
57
|
-
const localPath = installToLocal(toolDef, LOCAL_BIN_DIR, logger);
|
|
57
|
+
const localPath = await installToLocal(toolDef, LOCAL_BIN_DIR, logger);
|
|
58
58
|
if (localPath) {
|
|
59
59
|
resolvedPaths[toolName] = localPath;
|
|
60
60
|
logger.success(`ProjectDiscovery httpx installed at ${localPath}`);
|
|
@@ -76,7 +76,7 @@ export async function ensureTools(config, logger) {
|
|
|
76
76
|
|
|
77
77
|
// Tool not found at all — try global install first
|
|
78
78
|
logger.warn(`${toolName} not found, installing...`);
|
|
79
|
-
const installed = attemptInstall(toolDef, logger);
|
|
79
|
+
const installed = await attemptInstall(toolDef, logger);
|
|
80
80
|
|
|
81
81
|
if (installed) {
|
|
82
82
|
resolvedPaths[toolName] = toolDef.binary;
|
|
@@ -85,7 +85,7 @@ export async function ensureTools(config, logger) {
|
|
|
85
85
|
// Try local install as fallback
|
|
86
86
|
if (toolDef.installCmd && toolDef.installCmd.startsWith('go install')) {
|
|
87
87
|
logger.info(`Global install failed, trying local install to ${LOCAL_BIN_DIR}...`);
|
|
88
|
-
const localPath = installToLocal(toolDef, LOCAL_BIN_DIR, logger);
|
|
88
|
+
const localPath = await installToLocal(toolDef, LOCAL_BIN_DIR, logger);
|
|
89
89
|
if (localPath) {
|
|
90
90
|
resolvedPaths[toolName] = localPath;
|
|
91
91
|
logger.success(`${toolName} installed locally at ${localPath}`);
|