@mondoohq/xgrep 0.80.0 → 0.82.0

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.
Files changed (2) hide show
  1. package/bin/xgrep.js +73 -21
  2. package/package.json +7 -7
package/bin/xgrep.js CHANGED
@@ -48,39 +48,85 @@ function fail(message) {
48
48
  process.exit(EXIT_FATAL);
49
49
  }
50
50
 
51
+ // candidateKeys lists the PLATFORM_PACKAGES keys to try, most preferred first.
52
+ //
53
+ // npm installs the optionalDependency matching the arch of the Node that ran
54
+ // `npm install`, not the machine's, so a user who later switches Node builds
55
+ // finds the "wrong" package on disk. Where the OS can run the other arch's
56
+ // binary anyway, that package is an acceptable fallback:
57
+ //
58
+ // - win32: Windows on ARM64 runs both arm64 and x64 binaries (x64 under
59
+ // emulation), and an x64 Node there is common. arm64 <-> x64 both ways.
60
+ // - darwin: Apple Silicon runs x64 binaries under Rosetta, so an arm64 Node
61
+ // may use the x64 package. Not the reverse: an x64 Node may be on an Intel
62
+ // Mac, which cannot run arm64.
63
+ // - linux: strict. There is no general cross-arch execution, and a binary
64
+ // that fails to exec is worse than a clear "not installed".
65
+ function candidateKeys(platform, arch) {
66
+ const keys = [`${platform}_${arch}`];
67
+ if (platform === 'win32') {
68
+ if (arch === 'arm64') keys.push('win32_x64');
69
+ else if (arch === 'x64') keys.push('win32_arm64');
70
+ } else if (platform === 'darwin' && arch === 'arm64') {
71
+ keys.push('darwin_x64');
72
+ }
73
+ return keys;
74
+ }
75
+
51
76
  // resolveBinary finds the platform binary, or explains why it cannot.
52
77
  //
53
78
  // The failure modes here are all things a user can act on — an unsupported
54
79
  // platform, or an install that skipped optionalDependencies (`--no-optional`,
55
80
  // `--omit=optional`, or a lockfile built on another platform) — so each gets a
56
81
  // sentence rather than a module-resolution stack trace.
57
- function resolveBinary() {
58
- const key = `${process.platform}_${process.arch}`;
59
- const target = PLATFORM_PACKAGES[key];
60
- if (!target) {
82
+ //
83
+ // platform, arch and resolve default to the real process and require.resolve;
84
+ // tests inject them. Returns { path } on success or { error } with the message.
85
+ function resolveBinary({
86
+ platform = process.platform,
87
+ arch = process.arch,
88
+ resolve = require.resolve,
89
+ } = {}) {
90
+ const targets = candidateKeys(platform, arch)
91
+ .map((key) => PLATFORM_PACKAGES[key])
92
+ .filter(Boolean);
93
+ if (targets.length === 0) {
61
94
  const supported = Object.keys(PLATFORM_PACKAGES).sort().join(', ');
62
- fail(
63
- `no prebuilt binary for ${process.platform}/${process.arch}.\n` +
95
+ return {
96
+ error:
97
+ `no prebuilt binary for ${platform}/${arch}.\n` +
64
98
  ` supported: ${supported}\n` +
65
- ' build from source: https://xgrep.ai'
66
- );
99
+ ' build from source: https://xgrep.ai',
100
+ };
67
101
  }
68
- let pkgJson;
69
- try {
70
- pkgJson = require.resolve(path.posix.join(target.pkg, 'package.json'));
71
- } catch {
72
- fail(
73
- `the platform package ${target.pkg} is not installed.\n` +
74
- ' it ships as an optionalDependency, so this usually means the install ran with\n' +
75
- ' --no-optional / --omit=optional, or a lockfile from a different platform was used.\n' +
76
- ` fix: npm install ${target.pkg}`
77
- );
102
+ for (const target of targets) {
103
+ let pkgJson;
104
+ try {
105
+ pkgJson = resolve(path.posix.join(target.pkg, 'package.json'));
106
+ } catch {
107
+ continue;
108
+ }
109
+ return { path: path.join(path.dirname(pkgJson), target.bin) };
78
110
  }
79
- return path.join(path.dirname(pkgJson), target.bin);
111
+ const preferred = targets[0].pkg;
112
+ const fallbacks = targets.slice(1).map((t) => t.pkg);
113
+ const which =
114
+ `the platform package ${preferred} is not installed` +
115
+ (fallbacks.length ? `, and neither is the fallback ${fallbacks.join(', ')}.` : '.');
116
+ return {
117
+ error:
118
+ `${which}\n` +
119
+ ' it ships as an optionalDependency, so this usually means the install ran with\n' +
120
+ ' --no-optional / --omit=optional, or a lockfile from a different platform was used,\n' +
121
+ ` or node_modules was installed by a Node build for a different CPU than this one (${arch}).\n` +
122
+ ` fix: npm install ${preferred}`,
123
+ };
80
124
  }
81
125
 
82
126
  function main() {
83
- const child = spawn(resolveBinary(), process.argv.slice(2), {
127
+ const resolved = resolveBinary();
128
+ if (resolved.error) fail(resolved.error);
129
+ const child = spawn(resolved.path, process.argv.slice(2), {
84
130
  stdio: 'inherit',
85
131
  env: process.env,
86
132
  });
@@ -122,4 +168,10 @@ function main() {
122
168
  });
123
169
  }
124
170
 
125
- main();
171
+ // Run when executed as the `xgrep` bin; export the resolution logic when
172
+ // required, so scripts/npm-launcher.test.mjs can test it without spawning.
173
+ if (require.main === module) {
174
+ main();
175
+ } else {
176
+ module.exports = { PLATFORM_PACKAGES, candidateKeys, resolveBinary };
177
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mondoohq/xgrep",
3
- "version": "0.80.0",
3
+ "version": "0.82.0",
4
4
  "description": "A fast, Semgrep-compatible code scanner written in Go.",
5
5
  "keywords": [
6
6
  "sast",
@@ -27,11 +27,11 @@
27
27
  "node": ">=18"
28
28
  },
29
29
  "optionalDependencies": {
30
- "@mondoohq/xgrep_darwin_amd64": "0.80.0",
31
- "@mondoohq/xgrep_darwin_arm64": "0.80.0",
32
- "@mondoohq/xgrep_linux_amd64": "0.80.0",
33
- "@mondoohq/xgrep_linux_arm64": "0.80.0",
34
- "@mondoohq/xgrep_windows_amd64": "0.80.0",
35
- "@mondoohq/xgrep_windows_arm64": "0.80.0"
30
+ "@mondoohq/xgrep_darwin_amd64": "0.82.0",
31
+ "@mondoohq/xgrep_darwin_arm64": "0.82.0",
32
+ "@mondoohq/xgrep_linux_amd64": "0.82.0",
33
+ "@mondoohq/xgrep_linux_arm64": "0.82.0",
34
+ "@mondoohq/xgrep_windows_amd64": "0.82.0",
35
+ "@mondoohq/xgrep_windows_arm64": "0.82.0"
36
36
  }
37
37
  }