nhx 0.0.0-alpha.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.
- package/README.md +212 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +155 -0
- package/dist/cli.js.map +1 -0
- package/dist/executor.d.ts +4 -0
- package/dist/executor.d.ts.map +1 -0
- package/dist/executor.js +91 -0
- package/dist/executor.js.map +1 -0
- package/dist/inline-deps.d.ts +16 -0
- package/dist/inline-deps.d.ts.map +1 -0
- package/dist/inline-deps.js +40 -0
- package/dist/inline-deps.js.map +1 -0
- package/dist/script-runner.d.ts +7 -0
- package/dist/script-runner.d.ts.map +1 -0
- package/dist/script-runner.js +230 -0
- package/dist/script-runner.js.map +1 -0
- package/package.json +49 -0
package/README.md
ADDED
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
# nhx - Node.js Hybrid eXecutor
|
|
2
|
+
|
|
3
|
+
A fast, uvx-inspired hybrid tool for Node.js that runs scripts with inline dependencies and executes npm packages without installation.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
npm install -g nhx
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## Usage
|
|
10
|
+
|
|
11
|
+
### 1. Run Local Scripts
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
nhx ./script.js
|
|
15
|
+
nhx ./script.ts
|
|
16
|
+
nhx -e 'console.log("hello")'
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Scripts can declare inline dependencies:
|
|
20
|
+
|
|
21
|
+
```javascript
|
|
22
|
+
/*/ // <package>
|
|
23
|
+
{
|
|
24
|
+
dependencies: {
|
|
25
|
+
chalk: "^5.3.0",
|
|
26
|
+
lodash: "^4.17.21"
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/*/ // </package>
|
|
30
|
+
|
|
31
|
+
import chalk from 'chalk';
|
|
32
|
+
import _ from 'lodash';
|
|
33
|
+
|
|
34
|
+
console.log(chalk.green(_.capitalize('hello world')));
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### 2. Execute npm Packages
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
nhx cowsay "Hello World"
|
|
41
|
+
nhx prettier --write .
|
|
42
|
+
nhx --with=typescript tsc --version
|
|
43
|
+
|
|
44
|
+
# From git
|
|
45
|
+
nhx --with=github:user/repo command
|
|
46
|
+
nhx --with=git+https://github.com/user/repo.git command
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Options
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
--with <dep> Add dependency (can be used multiple times)
|
|
53
|
+
--engine <spec> Run with specific node version (e.g. "node@18")
|
|
54
|
+
--run-postinstall Allow postinstall scripts (disabled by default)
|
|
55
|
+
-h, --help Show help
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Node flags like `--import`, `-e`, `-p` are passed through to node.
|
|
59
|
+
|
|
60
|
+
## TypeScript Support
|
|
61
|
+
|
|
62
|
+
For full TypeScript support (including enums, decorators, etc.), use tsx:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
# Via command line flags
|
|
66
|
+
nhx --with=tsx --import tsx ./script.ts
|
|
67
|
+
|
|
68
|
+
# Or as a shebang
|
|
69
|
+
#!/usr/bin/env -S npx nhx --with=tsx --import tsx
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
You can also declare tsx as an inline dependency:
|
|
73
|
+
|
|
74
|
+
```typescript
|
|
75
|
+
#!/usr/bin/env -S npx nhx --import tsx
|
|
76
|
+
/*/ // <package>
|
|
77
|
+
{
|
|
78
|
+
dependencies: {
|
|
79
|
+
tsx: "^4.7.0"
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/*/ // </package>
|
|
83
|
+
|
|
84
|
+
enum Color {
|
|
85
|
+
Red,
|
|
86
|
+
Green,
|
|
87
|
+
Blue,
|
|
88
|
+
}
|
|
89
|
+
console.log(Color.Green);
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Note: Basic TypeScript (type annotations only) works without tsx on Node 22.6+ due to built-in type stripping. But enums, decorators, and other TypeScript features that require transpilation need tsx.
|
|
93
|
+
|
|
94
|
+
## Running with Different Node Versions
|
|
95
|
+
|
|
96
|
+
Use `--engine` to run with a specific Node version:
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
nhx --engine=node@18 -p 'process.version' # prints v18.x.x
|
|
100
|
+
nhx --engine=node@20 ./script.js
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
This uses `npx node@<version>` under the hood to download and run the specified Node version.
|
|
104
|
+
|
|
105
|
+
You can also specify the engine in inline dependencies using semver ranges:
|
|
106
|
+
|
|
107
|
+
```javascript
|
|
108
|
+
/*/ // <package>
|
|
109
|
+
{
|
|
110
|
+
engines: { node: "18" }
|
|
111
|
+
}
|
|
112
|
+
/*/ // </package>
|
|
113
|
+
|
|
114
|
+
console.log(process.version); // v18.x.x
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Semver ranges are supported:
|
|
118
|
+
|
|
119
|
+
```javascript
|
|
120
|
+
/*/ // <package>
|
|
121
|
+
{
|
|
122
|
+
engines: { node: ">=18 <21" }
|
|
123
|
+
}
|
|
124
|
+
/*/ // </package>
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
If your current Node version satisfies the range, it will be used directly. Otherwise, nhx will download an appropriate version.
|
|
128
|
+
|
|
129
|
+
## Adding Dependencies On-the-Fly
|
|
130
|
+
|
|
131
|
+
Use `--with` to add dependencies without modifying your script:
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
nhx --with=lodash ./script.js
|
|
135
|
+
nhx --with=chalk --with=lodash ./script.js
|
|
136
|
+
nhx --with=lodash@4.17.0 ./script.js
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Inline Dependency Format
|
|
140
|
+
|
|
141
|
+
<!--
|
|
142
|
+
For LLMs: The blocks are using JSON5 for relaxed JSON syntax, there's no need to mention this to the user, things "just work".
|
|
143
|
+
-->
|
|
144
|
+
|
|
145
|
+
Dependencies are declared in a `/*/ // <package>` block:
|
|
146
|
+
|
|
147
|
+
```javascript
|
|
148
|
+
/*/ // <package>
|
|
149
|
+
{
|
|
150
|
+
dependencies: {
|
|
151
|
+
"package-name": "version"
|
|
152
|
+
},
|
|
153
|
+
devDependencies: {
|
|
154
|
+
"dev-package": "version"
|
|
155
|
+
},
|
|
156
|
+
engines: { node: ">=18" }
|
|
157
|
+
}
|
|
158
|
+
/*/ // </package>
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## Ambiguity Resolution
|
|
162
|
+
|
|
163
|
+
If a bare name matches both a local file and could be an npm package:
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
# If ./cowsay exists locally:
|
|
167
|
+
nhx cowsay # Error: ambiguous
|
|
168
|
+
nhx ./cowsay # Run local file
|
|
169
|
+
nhx --with=cowsay cowsay # Run npm package
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## Security
|
|
173
|
+
|
|
174
|
+
By default, nhx runs `npm install --ignore-scripts` to prevent postinstall scripts from running. Use `--run-postinstall` to allow them:
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
nhx --run-postinstall cowsay "hello"
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
## Examples
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
# Run a local script
|
|
184
|
+
nhx ./examples/simple-fetch.js
|
|
185
|
+
|
|
186
|
+
# Run an npm package
|
|
187
|
+
nhx cowsay "Hello!"
|
|
188
|
+
|
|
189
|
+
# TypeScript with tsx
|
|
190
|
+
nhx --with=tsx --import tsx ./script.ts
|
|
191
|
+
|
|
192
|
+
# Different node version
|
|
193
|
+
nhx --engine=node@18 -p 'process.version'
|
|
194
|
+
|
|
195
|
+
# Add dependencies on-the-fly
|
|
196
|
+
nhx --with=chalk --with=lodash ./script.js
|
|
197
|
+
|
|
198
|
+
# Forward to node
|
|
199
|
+
nhx -e 'console.log(1 + 1)'
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
## Development
|
|
203
|
+
|
|
204
|
+
```bash
|
|
205
|
+
npm install
|
|
206
|
+
npm run build
|
|
207
|
+
npm test
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
## License
|
|
211
|
+
|
|
212
|
+
MIT
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
+
};
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
const child_process_1 = require("child_process");
|
|
8
|
+
const path_1 = require("path");
|
|
9
|
+
const fs_1 = require("fs");
|
|
10
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
11
|
+
const minimist_1 = __importDefault(require("minimist"));
|
|
12
|
+
const script_runner_js_1 = require("./script-runner.js");
|
|
13
|
+
const executor_js_1 = require("./executor.js");
|
|
14
|
+
const EXTS = ['.js', '.ts', '.mjs', '.mts'];
|
|
15
|
+
const OUR_FLAGS = ['--help', '-h', '--run-postinstall', '--with', '--engine'];
|
|
16
|
+
const OUR_KEYS = ['_', 'help', 'h', 'run-postinstall', 'with', 'engine'];
|
|
17
|
+
const HELP = `
|
|
18
|
+
Usage: nhx [options] [target] [args...]
|
|
19
|
+
|
|
20
|
+
Options:
|
|
21
|
+
--with <dep> Add dependency (repeatable)
|
|
22
|
+
--engine <spec> Node version (e.g. "node@18")
|
|
23
|
+
--run-postinstall Allow postinstall scripts
|
|
24
|
+
-h, --help Show help
|
|
25
|
+
|
|
26
|
+
Examples:
|
|
27
|
+
nhx -e 'console.log(1)' # forward to node
|
|
28
|
+
nhx ./script.js # run local file
|
|
29
|
+
nhx cowsay hi # run npm package
|
|
30
|
+
nhx --with=typescript tsc # run tsc from typescript
|
|
31
|
+
nhx --with=tsx --import tsx a.ts # typescript
|
|
32
|
+
`;
|
|
33
|
+
const toArray = (x) => (x ? (Array.isArray(x) ? x : [x]) : []);
|
|
34
|
+
const isLocal = (t) => t.startsWith('./') ||
|
|
35
|
+
t.startsWith('/') ||
|
|
36
|
+
t.startsWith('../') ||
|
|
37
|
+
EXTS.some((e) => t.endsWith(e));
|
|
38
|
+
const findFile = (t) => [t, ...EXTS.map((e) => t + e)].find(fs_1.existsSync) || null;
|
|
39
|
+
const findMatches = (t) => [t, ...EXTS.map((e) => t + e)].filter(fs_1.existsSync);
|
|
40
|
+
const engineer = (engines) => {
|
|
41
|
+
const map = {};
|
|
42
|
+
for (const e of engines) {
|
|
43
|
+
const [name, ver] = e.split('@');
|
|
44
|
+
map[name] = ver;
|
|
45
|
+
}
|
|
46
|
+
return map;
|
|
47
|
+
};
|
|
48
|
+
function stripOurFlags(argv) {
|
|
49
|
+
const result = [];
|
|
50
|
+
for (let i = 0; i < argv.length; i++) {
|
|
51
|
+
const arg = argv[i];
|
|
52
|
+
const isOurs = OUR_FLAGS.some((f) => arg === f || arg.startsWith(f + '='));
|
|
53
|
+
if (isOurs) {
|
|
54
|
+
const needsValue = !arg.includes('=') && ['--with', '--engine'].includes(arg);
|
|
55
|
+
if (needsValue)
|
|
56
|
+
i++;
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
result.push(arg);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return result;
|
|
63
|
+
}
|
|
64
|
+
function extractFlags(parsed) {
|
|
65
|
+
const result = [];
|
|
66
|
+
for (const [k, v] of Object.entries(parsed)) {
|
|
67
|
+
if (OUR_KEYS.includes(k))
|
|
68
|
+
continue;
|
|
69
|
+
const flag = k.length === 1 ? `-${k}` : `--${k}`;
|
|
70
|
+
if (v === true)
|
|
71
|
+
result.push(flag);
|
|
72
|
+
else if (v !== false && v !== undefined)
|
|
73
|
+
result.push(flag, String(v));
|
|
74
|
+
}
|
|
75
|
+
return result;
|
|
76
|
+
}
|
|
77
|
+
async function runNode(args, opts) {
|
|
78
|
+
const hasOpts = opts.with.length || opts.engine.length;
|
|
79
|
+
if (hasOpts)
|
|
80
|
+
return (0, script_runner_js_1.runScript)('__eval__', [], {
|
|
81
|
+
withDeps: opts.with,
|
|
82
|
+
nodeArgs: args,
|
|
83
|
+
engines: opts.engine,
|
|
84
|
+
});
|
|
85
|
+
return new Promise((res, rej) => {
|
|
86
|
+
const child = (0, child_process_1.spawn)(process.execPath, args, { stdio: 'inherit' });
|
|
87
|
+
child.on('exit', (c) => res(c || 0));
|
|
88
|
+
child.on('error', rej);
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
async function main() {
|
|
92
|
+
const argv = process.argv.slice(2);
|
|
93
|
+
const parseOpts = {
|
|
94
|
+
boolean: ['help', 'run-postinstall'],
|
|
95
|
+
string: ['with', 'engine'],
|
|
96
|
+
alias: { h: 'help' },
|
|
97
|
+
};
|
|
98
|
+
const startsWithFlag = argv.length === 0 || argv[0].startsWith('-');
|
|
99
|
+
if (startsWithFlag) {
|
|
100
|
+
const parsed = (0, minimist_1.default)(argv, parseOpts);
|
|
101
|
+
if (parsed.help)
|
|
102
|
+
return console.log(HELP);
|
|
103
|
+
const noTarget = !parsed._.length;
|
|
104
|
+
if (noTarget)
|
|
105
|
+
process.exit(await runNode(stripOurFlags(argv), {
|
|
106
|
+
with: toArray(parsed.with),
|
|
107
|
+
engine: toArray(parsed.engine),
|
|
108
|
+
}));
|
|
109
|
+
}
|
|
110
|
+
const parsed = (0, minimist_1.default)(argv, { ...parseOpts, stopEarly: true });
|
|
111
|
+
if (parsed.help)
|
|
112
|
+
return console.log(HELP);
|
|
113
|
+
const [target, ...args] = parsed._;
|
|
114
|
+
const withDeps = toArray(parsed.with);
|
|
115
|
+
const engines = toArray(parsed.engine);
|
|
116
|
+
const opts = {
|
|
117
|
+
with: withDeps,
|
|
118
|
+
engines: engines,
|
|
119
|
+
runPostinstall: parsed['run-postinstall'],
|
|
120
|
+
};
|
|
121
|
+
try {
|
|
122
|
+
const hasWithDeps = withDeps.length > 0;
|
|
123
|
+
const shouldCheckAmbiguity = !isLocal(target) && !hasWithDeps;
|
|
124
|
+
if (shouldCheckAmbiguity) {
|
|
125
|
+
const matches = findMatches(target);
|
|
126
|
+
if (matches.length) {
|
|
127
|
+
console.error(chalk_1.default.red(`Ambiguous: "${target}" matches: ${matches.join(', ')}`));
|
|
128
|
+
console.error(chalk_1.default.yellow('Use ./ for local, --with= for npm'));
|
|
129
|
+
process.exit(1);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
if (isLocal(target)) {
|
|
133
|
+
const file = findFile(target);
|
|
134
|
+
if (!file)
|
|
135
|
+
throw new Error(`File not found: ${target}`);
|
|
136
|
+
const code = await (0, script_runner_js_1.runScript)((0, path_1.resolve)(file), args, {
|
|
137
|
+
withDeps: opts.with,
|
|
138
|
+
nodeArgs: extractFlags(parsed),
|
|
139
|
+
engines: opts.engines,
|
|
140
|
+
});
|
|
141
|
+
process.exit(code);
|
|
142
|
+
}
|
|
143
|
+
// If --with is specified, first --with is the package, target is the command
|
|
144
|
+
// Otherwise, target is the package (and also the command)
|
|
145
|
+
const pkg = hasWithDeps ? withDeps[0] : target;
|
|
146
|
+
const cmdArgs = hasWithDeps ? [target, ...args] : args;
|
|
147
|
+
await (0, executor_js_1.executePackage)(pkg, cmdArgs, { runPostinstall: opts.runPostinstall });
|
|
148
|
+
}
|
|
149
|
+
catch (e) {
|
|
150
|
+
console.error(chalk_1.default.red(`Failed: ${e.message}`));
|
|
151
|
+
process.exit(1);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
main();
|
|
155
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../src/executor.ts"],"names":[],"mappings":"AAQA,wBAAsB,cAAc,CAClC,OAAO,EAAE,MAAM,EACf,IAAI,GAAE,MAAM,EAAO,EACnB,IAAI,GAAE;IAAE,cAAc,CAAC,EAAE,OAAO,CAAA;CAAO,GACtC,OAAO,CAAC,MAAM,CAAC,CAwBjB"}
|
package/dist/executor.js
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.executePackage = executePackage;
|
|
4
|
+
const fs_1 = require("fs");
|
|
5
|
+
const path_1 = require("path");
|
|
6
|
+
const os_1 = require("os");
|
|
7
|
+
const child_process_1 = require("child_process");
|
|
8
|
+
const inline_deps_js_1 = require("./inline-deps.js");
|
|
9
|
+
const CACHE = (0, path_1.join)((0, os_1.homedir)(), '.nhx', 'store');
|
|
10
|
+
async function executePackage(pkgSpec, args = [], opts = {}) {
|
|
11
|
+
const key = `pkg-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;
|
|
12
|
+
const dir = (0, path_1.join)(CACHE, (0, inline_deps_js_1.getNodeVersionKey)(), key);
|
|
13
|
+
await fs_1.promises.mkdir(dir, { recursive: true });
|
|
14
|
+
try {
|
|
15
|
+
const pkgJson = JSON.stringify({
|
|
16
|
+
name: 'nhx-exec',
|
|
17
|
+
version: '1.0.0',
|
|
18
|
+
private: true,
|
|
19
|
+
});
|
|
20
|
+
await fs_1.promises.writeFile((0, path_1.join)(dir, 'package.json'), pkgJson);
|
|
21
|
+
await install(dir, pkgSpec, opts.runPostinstall || false);
|
|
22
|
+
const bin = await findBin(dir, pkgSpec);
|
|
23
|
+
if (!bin)
|
|
24
|
+
throw new Error(`No executable found for ${pkgSpec}`);
|
|
25
|
+
const code = await run(bin, args);
|
|
26
|
+
await fs_1.promises.rm(dir, { recursive: true, force: true }).catch(() => { });
|
|
27
|
+
return code;
|
|
28
|
+
}
|
|
29
|
+
catch (e) {
|
|
30
|
+
await fs_1.promises.rm(dir, { recursive: true, force: true }).catch(() => { });
|
|
31
|
+
throw e;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
function install(cwd, pkg, postinstall) {
|
|
35
|
+
const args = ['install', pkg, '--no-save', '--prefer-offline'];
|
|
36
|
+
if (!postinstall)
|
|
37
|
+
args.push('--ignore-scripts');
|
|
38
|
+
return new Promise((res, rej) => {
|
|
39
|
+
const child = (0, child_process_1.spawn)('npm', args, { cwd, stdio: 'ignore' });
|
|
40
|
+
child.on('close', (c) => c === 0 ? res() : rej(new Error(`npm install failed for ${pkg}`)));
|
|
41
|
+
child.on('error', rej);
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
async function findBin(dir, spec) {
|
|
45
|
+
const nm = (0, path_1.join)(dir, 'node_modules');
|
|
46
|
+
const isGit = /^(git\+|github:|gitlab:)/.test(spec);
|
|
47
|
+
let pkgDir = '';
|
|
48
|
+
let pkgName = '';
|
|
49
|
+
if (isGit) {
|
|
50
|
+
const entries = await fs_1.promises.readdir(nm).catch(() => []);
|
|
51
|
+
for (const e of entries) {
|
|
52
|
+
const skip = e.startsWith('.') || e === '.bin';
|
|
53
|
+
if (skip)
|
|
54
|
+
continue;
|
|
55
|
+
const d = (0, path_1.join)(nm, e);
|
|
56
|
+
const isDir = (await fs_1.promises.stat(d)).isDirectory();
|
|
57
|
+
if (!isDir)
|
|
58
|
+
continue;
|
|
59
|
+
const p = JSON.parse(await fs_1.promises.readFile((0, path_1.join)(d, 'package.json'), 'utf-8').catch(() => '{}'));
|
|
60
|
+
if (p.bin) {
|
|
61
|
+
pkgDir = d;
|
|
62
|
+
pkgName = e;
|
|
63
|
+
break;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
if (!pkgDir)
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
pkgName = spec.split('@').find((p) => p && !/^\d/.test(p)) || spec;
|
|
71
|
+
pkgDir = (0, path_1.join)(nm, pkgName);
|
|
72
|
+
}
|
|
73
|
+
const p = JSON.parse(await fs_1.promises.readFile((0, path_1.join)(pkgDir, 'package.json'), 'utf-8').catch(() => '{}'));
|
|
74
|
+
if (!p.bin)
|
|
75
|
+
return null;
|
|
76
|
+
if (typeof p.bin === 'string')
|
|
77
|
+
return (0, path_1.join)(pkgDir, p.bin);
|
|
78
|
+
const name = pkgName.split('/').pop();
|
|
79
|
+
if (name && p.bin[name])
|
|
80
|
+
return (0, path_1.join)(pkgDir, p.bin[name]);
|
|
81
|
+
const first = Object.values(p.bin)[0];
|
|
82
|
+
return typeof first === 'string' ? (0, path_1.join)(pkgDir, first) : null;
|
|
83
|
+
}
|
|
84
|
+
function run(bin, args) {
|
|
85
|
+
return new Promise((res, rej) => {
|
|
86
|
+
const child = (0, child_process_1.spawn)(process.execPath, [bin, ...args], { stdio: 'inherit' });
|
|
87
|
+
child.on('exit', (c) => res(c || 0));
|
|
88
|
+
child.on('error', rej);
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=executor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"executor.js","sourceRoot":"","sources":["../src/executor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface ParsedDeps {
|
|
2
|
+
dependencies: Record<string, string>;
|
|
3
|
+
devDependencies: Record<string, string>;
|
|
4
|
+
engines?: Record<string, string>;
|
|
5
|
+
hasInlineDeps: boolean;
|
|
6
|
+
}
|
|
7
|
+
export declare const parseInlineDependencies: (path: string) => Promise<ParsedDeps>;
|
|
8
|
+
export declare const getNodeVersionKey: () => string;
|
|
9
|
+
export declare const createPackageJson: (d: ParsedDeps, name?: string) => {
|
|
10
|
+
name: string;
|
|
11
|
+
version: string;
|
|
12
|
+
type: string;
|
|
13
|
+
dependencies: Record<string, string>;
|
|
14
|
+
devDependencies: Record<string, string>;
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=inline-deps.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inline-deps.d.ts","sourceRoot":"","sources":["../src/inline-deps.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,UAAU;IACzB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,aAAa,EAAE,OAAO,CAAC;CACxB;AAqBD,eAAO,MAAM,uBAAuB,GAAU,MAAM,MAAM,wBACV,CAAC;AACjD,eAAO,MAAM,iBAAiB,cACoC,CAAC;AACnE,eAAO,MAAM,iBAAiB,GAAI,GAAG,UAAU,EAAE,aAAe;;;;;;CAM9D,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.createPackageJson = exports.getNodeVersionKey = exports.parseInlineDependencies = void 0;
|
|
7
|
+
const fs_1 = require("fs");
|
|
8
|
+
const json5_1 = __importDefault(require("json5"));
|
|
9
|
+
const BASE = { dependencies: {}, devDependencies: {} };
|
|
10
|
+
const EMPTY = { ...BASE, hasInlineDeps: false };
|
|
11
|
+
function parseContent(content) {
|
|
12
|
+
const shebang = content.startsWith('#!');
|
|
13
|
+
const lines = content.split('\n').slice(shebang ? 1 : 0);
|
|
14
|
+
const starts = lines.join('\n').trim().startsWith('/*/ // <package>');
|
|
15
|
+
if (!starts)
|
|
16
|
+
return EMPTY;
|
|
17
|
+
const ends = lines.findIndex((l) => l.trim().startsWith('/*/ // </package>'));
|
|
18
|
+
if (ends === -1)
|
|
19
|
+
return EMPTY;
|
|
20
|
+
try {
|
|
21
|
+
const cfg = json5_1.default.parse(lines.slice(1, ends).join('\n'));
|
|
22
|
+
return { ...BASE, ...cfg, hasInlineDeps: true };
|
|
23
|
+
}
|
|
24
|
+
catch (e) {
|
|
25
|
+
throw new Error(`Failed to parse inline deps: ${e.message}`);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
const parseInlineDependencies = async (path) => parseContent(await fs_1.promises.readFile(path, 'utf-8'));
|
|
29
|
+
exports.parseInlineDependencies = parseInlineDependencies;
|
|
30
|
+
const getNodeVersionKey = () => `node-${process.versions.node.split('.').slice(0, 2).join('.')}`;
|
|
31
|
+
exports.getNodeVersionKey = getNodeVersionKey;
|
|
32
|
+
const createPackageJson = (d, name = 'script') => ({
|
|
33
|
+
name,
|
|
34
|
+
version: '1.0.0',
|
|
35
|
+
type: 'module',
|
|
36
|
+
dependencies: d.dependencies,
|
|
37
|
+
devDependencies: d.devDependencies,
|
|
38
|
+
});
|
|
39
|
+
exports.createPackageJson = createPackageJson;
|
|
40
|
+
//# sourceMappingURL=inline-deps.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inline-deps.js","sourceRoot":"","sources":["../src/inline-deps.ts"],"names":[],"mappings":";;;;;;AAAA,2BAAoC;AACpC,kDAA0B;AAS1B,MAAM,IAAI,GAAG,EAAE,YAAY,EAAE,EAAE,EAAE,eAAe,EAAE,EAAE,EAAE,CAAC;AACvD,MAAM,KAAK,GAAe,EAAE,GAAG,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC;AAE5D,SAAS,YAAY,CAAC,OAAe;IACnC,MAAM,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;IACzC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACzD,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,kBAAkB,CAAC,CAAC;IACtE,IAAI,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IAC1B,MAAM,IAAI,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,mBAAmB,CAAC,CAAC,CAAC;IAC9E,IAAI,IAAI,KAAK,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IAE9B,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,eAAK,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QACzD,OAAO,EAAE,GAAG,IAAI,EAAE,GAAG,GAAG,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;IAClD,CAAC;IAAC,OAAO,CAAM,EAAE,CAAC;QAChB,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;IAC/D,CAAC;AACH,CAAC;AAEM,MAAM,uBAAuB,GAAG,KAAK,EAAE,IAAY,EAAE,EAAE,CAC5D,YAAY,CAAC,MAAM,aAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;AADpC,QAAA,uBAAuB,2BACa;AAC1C,MAAM,iBAAiB,GAAG,GAAG,EAAE,CACpC,QAAQ,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;AADtD,QAAA,iBAAiB,qBACqC;AAC5D,MAAM,iBAAiB,GAAG,CAAC,CAAa,EAAE,IAAI,GAAG,QAAQ,EAAE,EAAE,CAAC,CAAC;IACpE,IAAI;IACJ,OAAO,EAAE,OAAO;IAChB,IAAI,EAAE,QAAQ;IACd,YAAY,EAAE,CAAC,CAAC,YAAY;IAC5B,eAAe,EAAE,CAAC,CAAC,eAAe;CACnC,CAAC,CAAC;AANU,QAAA,iBAAiB,qBAM3B"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export interface RunScriptOptions {
|
|
2
|
+
withDeps?: string[];
|
|
3
|
+
nodeArgs?: string[];
|
|
4
|
+
engines?: string[];
|
|
5
|
+
}
|
|
6
|
+
export declare function runScript(scriptPath: string, args?: string[], opts?: RunScriptOptions): Promise<number>;
|
|
7
|
+
//# sourceMappingURL=script-runner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"script-runner.d.ts","sourceRoot":"","sources":["../src/script-runner.ts"],"names":[],"mappings":"AA2EA,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,wBAAsB,SAAS,CAC7B,UAAU,EAAE,MAAM,EAClB,IAAI,GAAE,MAAM,EAAO,EACnB,IAAI,GAAE,gBAAqB,GAC1B,OAAO,CAAC,MAAM,CAAC,CA6IjB"}
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.runScript = runScript;
|
|
7
|
+
const fs_1 = require("fs");
|
|
8
|
+
const path_1 = require("path");
|
|
9
|
+
const os_1 = require("os");
|
|
10
|
+
const child_process_1 = require("child_process");
|
|
11
|
+
const fs_2 = require("fs");
|
|
12
|
+
const inline_deps_js_1 = require("./inline-deps.js");
|
|
13
|
+
const crypto_1 = require("crypto");
|
|
14
|
+
const semver_1 = __importDefault(require("semver"));
|
|
15
|
+
const CACHE = (0, path_1.join)((0, os_1.homedir)(), '.nhx', 'script-cache');
|
|
16
|
+
// Check if a package exists in local node_modules (walking up from cwd)
|
|
17
|
+
function findLocalPackage(name) {
|
|
18
|
+
let dir = process.cwd();
|
|
19
|
+
while (true) {
|
|
20
|
+
const pkgPath = (0, path_1.join)(dir, 'node_modules', name);
|
|
21
|
+
if ((0, fs_2.existsSync)(pkgPath))
|
|
22
|
+
return pkgPath;
|
|
23
|
+
const parent = (0, path_1.join)(dir, '..');
|
|
24
|
+
if (parent === dir)
|
|
25
|
+
break;
|
|
26
|
+
dir = parent;
|
|
27
|
+
}
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
const LOADER_FALLBACK = `
|
|
31
|
+
import { join } from 'node:path';
|
|
32
|
+
import { pathToFileURL } from 'node:url';
|
|
33
|
+
const modules = __MODULES__;
|
|
34
|
+
export async function resolve(spec, ctx, next) {
|
|
35
|
+
try { return await next(spec, ctx); } catch (e) {
|
|
36
|
+
const isModule = e.code === 'ERR_MODULE_NOT_FOUND' && !/^[./]|^node:/.test(spec);
|
|
37
|
+
if (isModule) try { return await next(spec, { ...ctx, parentURL: pathToFileURL(join(modules, '_')).href }); } catch {}
|
|
38
|
+
throw e;
|
|
39
|
+
}
|
|
40
|
+
}`;
|
|
41
|
+
// Loader that forces resolution from our installed modules first (for hard deps)
|
|
42
|
+
const LOADER_PRIORITY = `
|
|
43
|
+
import { join } from 'node:path';
|
|
44
|
+
import { pathToFileURL } from 'node:url';
|
|
45
|
+
const modules = __MODULES__;
|
|
46
|
+
const hardDeps = __HARD_DEPS__;
|
|
47
|
+
export async function resolve(spec, ctx, next) {
|
|
48
|
+
// For hard deps, always resolve from our installed modules first
|
|
49
|
+
const pkgName = spec.startsWith('@') ? spec.split('/').slice(0, 2).join('/') : spec.split('/')[0];
|
|
50
|
+
if (hardDeps.includes(pkgName) && !/^[./]|^node:/.test(spec)) {
|
|
51
|
+
try { return await next(spec, { ...ctx, parentURL: pathToFileURL(join(modules, '_')).href }); } catch {}
|
|
52
|
+
}
|
|
53
|
+
// Otherwise, try normal resolution, then fall back to our modules
|
|
54
|
+
try { return await next(spec, ctx); } catch (e) {
|
|
55
|
+
const isModule = e.code === 'ERR_MODULE_NOT_FOUND' && !/^[./]|^node:/.test(spec);
|
|
56
|
+
if (isModule) try { return await next(spec, { ...ctx, parentURL: pathToFileURL(join(modules, '_')).href }); } catch {}
|
|
57
|
+
throw e;
|
|
58
|
+
}
|
|
59
|
+
}`;
|
|
60
|
+
// CJS preload script that patches Module._resolveFilename for hard deps
|
|
61
|
+
const CJS_PRELOAD = `
|
|
62
|
+
const Module = require('module');
|
|
63
|
+
const orig = Module._resolveFilename;
|
|
64
|
+
const modules = __MODULES__;
|
|
65
|
+
const hardDeps = __HARD_DEPS__;
|
|
66
|
+
Module._resolveFilename = function(req, parent, isMain, opts) {
|
|
67
|
+
const name = req.startsWith('@') ? req.split('/').slice(0, 2).join('/') : req.split('/')[0];
|
|
68
|
+
const isHard = hardDeps.includes(name) && !/^[./]|^node:/.test(req);
|
|
69
|
+
if (isHard) {
|
|
70
|
+
try { return orig.call(this, req, parent, isMain, { ...opts, paths: [modules, ...(opts?.paths || [])] }); } catch {}
|
|
71
|
+
}
|
|
72
|
+
return orig.call(this, req, parent, isMain, opts);
|
|
73
|
+
};`;
|
|
74
|
+
async function runScript(scriptPath, args = [], opts = {}) {
|
|
75
|
+
const isEval = scriptPath === '__eval__';
|
|
76
|
+
const deps = isEval
|
|
77
|
+
? { dependencies: {}, devDependencies: {}, hasInlineDeps: false }
|
|
78
|
+
: await (0, inline_deps_js_1.parseInlineDependencies)(scriptPath);
|
|
79
|
+
// Track which deps are "soft" (no version, prefer local) vs "hard" (explicit version)
|
|
80
|
+
const softDeps = [];
|
|
81
|
+
const hardDeps = [];
|
|
82
|
+
for (const dep of opts.withDeps || []) {
|
|
83
|
+
const at = dep.lastIndexOf('@');
|
|
84
|
+
const hasVersion = at > 0;
|
|
85
|
+
const pkgName = hasVersion ? dep.slice(0, at) : dep;
|
|
86
|
+
const version = hasVersion ? dep.slice(at + 1) : 'latest';
|
|
87
|
+
deps.dependencies[pkgName] = version;
|
|
88
|
+
deps.hasInlineDeps = true;
|
|
89
|
+
if (hasVersion) {
|
|
90
|
+
hardDeps.push(pkgName);
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
softDeps.push(pkgName);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
// convert --engines="node@18,other@1" to { node: "18", other: "1" }
|
|
97
|
+
const engines = deps.engines ?? {};
|
|
98
|
+
opts.engines?.map((e) => {
|
|
99
|
+
const [name, ver] = e.split('@');
|
|
100
|
+
engines[name] = ver;
|
|
101
|
+
});
|
|
102
|
+
if (!deps.hasInlineDeps)
|
|
103
|
+
return exec(isEval ? '' : scriptPath, args, null, opts.nodeArgs || [], engines);
|
|
104
|
+
// Check which soft deps can be resolved locally
|
|
105
|
+
const localModules = [];
|
|
106
|
+
const depsToInstall = {};
|
|
107
|
+
for (const [pkgName, version] of Object.entries(deps.dependencies)) {
|
|
108
|
+
const isSoft = softDeps.includes(pkgName);
|
|
109
|
+
const localPath = isSoft ? findLocalPackage(pkgName) : null;
|
|
110
|
+
if (localPath) {
|
|
111
|
+
// Use local package - add its parent node_modules to the path
|
|
112
|
+
const nodeModulesDir = (0, path_1.join)(localPath, '..');
|
|
113
|
+
if (!localModules.includes(nodeModulesDir))
|
|
114
|
+
localModules.push(nodeModulesDir);
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
depsToInstall[pkgName] = version;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
// If all deps resolved locally, no need to install anything
|
|
121
|
+
const needsInstall = Object.keys(depsToInstall).length > 0;
|
|
122
|
+
let installedModules = null;
|
|
123
|
+
if (needsInstall) {
|
|
124
|
+
const depsKey = JSON.stringify({
|
|
125
|
+
d: depsToInstall,
|
|
126
|
+
v: deps.devDependencies,
|
|
127
|
+
});
|
|
128
|
+
const hash = (0, crypto_1.createHash)('sha256')
|
|
129
|
+
.update(depsKey)
|
|
130
|
+
.digest('hex')
|
|
131
|
+
.slice(0, 12);
|
|
132
|
+
const dir = (0, path_1.join)(CACHE, (0, inline_deps_js_1.getNodeVersionKey)(), hash);
|
|
133
|
+
const cached = await fs_1.promises.access((0, path_1.join)(dir, 'node_modules')).then(() => true, () => false);
|
|
134
|
+
if (!cached) {
|
|
135
|
+
await fs_1.promises.mkdir(dir, { recursive: true });
|
|
136
|
+
const installDeps = { ...deps, dependencies: depsToInstall };
|
|
137
|
+
const pkg = (0, inline_deps_js_1.createPackageJson)(installDeps, (0, path_1.basename)(scriptPath));
|
|
138
|
+
await fs_1.promises.writeFile((0, path_1.join)(dir, 'package.json'), JSON.stringify(pkg, null, 2));
|
|
139
|
+
await install(dir);
|
|
140
|
+
}
|
|
141
|
+
installedModules = (0, path_1.join)(dir, 'node_modules');
|
|
142
|
+
}
|
|
143
|
+
// Build NODE_PATH: installed modules first, then local modules
|
|
144
|
+
const modulePaths = [installedModules, ...localModules].filter(Boolean);
|
|
145
|
+
// If we have installed modules, use the loader
|
|
146
|
+
if (installedModules) {
|
|
147
|
+
const cacheDir = (0, path_1.join)(installedModules, '..');
|
|
148
|
+
const hasHardDeps = hardDeps.length > 0;
|
|
149
|
+
// ESM loader for import() resolution
|
|
150
|
+
const loader = (0, path_1.join)(cacheDir, '_loader.mjs');
|
|
151
|
+
const loaderCode = hasHardDeps
|
|
152
|
+
? LOADER_PRIORITY.replace('__MODULES__', JSON.stringify(installedModules)).replace('__HARD_DEPS__', JSON.stringify(hardDeps))
|
|
153
|
+
: LOADER_FALLBACK.replace('__MODULES__', JSON.stringify(installedModules));
|
|
154
|
+
await fs_1.promises.writeFile(loader, loaderCode);
|
|
155
|
+
const loaderArgs = ['--experimental-loader', loader];
|
|
156
|
+
const constArgs = ['--no-warnings'];
|
|
157
|
+
let allArgs = [...loaderArgs, ...constArgs];
|
|
158
|
+
// For eval mode with hard deps, also use CJS preload to patch require()
|
|
159
|
+
if (isEval && hasHardDeps) {
|
|
160
|
+
const preload = (0, path_1.join)(cacheDir, '_preload.cjs');
|
|
161
|
+
const preloadCode = CJS_PRELOAD.replace('__MODULES__', JSON.stringify(installedModules)).replace('__HARD_DEPS__', JSON.stringify(hardDeps));
|
|
162
|
+
await fs_1.promises.writeFile(preload, preloadCode);
|
|
163
|
+
allArgs = ['-r', preload, ...allArgs];
|
|
164
|
+
}
|
|
165
|
+
allArgs = [...allArgs, ...(opts.nodeArgs || [])];
|
|
166
|
+
const script = isEval ? '' : scriptPath;
|
|
167
|
+
return exec(script, args, modulePaths.join(':'), allArgs, engines);
|
|
168
|
+
}
|
|
169
|
+
// Only local modules, no loader needed
|
|
170
|
+
const script = isEval ? '' : scriptPath;
|
|
171
|
+
return exec(script, args, modulePaths.join(':'), opts.nodeArgs || [], engines);
|
|
172
|
+
}
|
|
173
|
+
async function install(cwd) {
|
|
174
|
+
const pkg = JSON.parse(await fs_1.promises.readFile((0, path_1.join)(cwd, 'package.json'), 'utf-8'));
|
|
175
|
+
const count = Object.keys(pkg.dependencies || {}).length;
|
|
176
|
+
if (!count)
|
|
177
|
+
return;
|
|
178
|
+
return new Promise((r, j) => {
|
|
179
|
+
const args = ['install', '--prefer-offline', '--ignore-scripts'];
|
|
180
|
+
const stdio = ['inherit', 2, 2];
|
|
181
|
+
const child = (0, child_process_1.spawn)('npm', args, { cwd, stdio });
|
|
182
|
+
child.on('close', (c) => (!c ? r() : j(new Error('npm install failed'))));
|
|
183
|
+
child.on('error', j);
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
// Resolve engine spec to a version to use, or null to use current Node
|
|
187
|
+
function resolveNodeVersion(spec) {
|
|
188
|
+
if (!spec)
|
|
189
|
+
return null;
|
|
190
|
+
const currentVersion = process.version;
|
|
191
|
+
// Check if it's a simple major version like "18" or "20"
|
|
192
|
+
if (/^\d+$/.test(spec)) {
|
|
193
|
+
// If current node matches this major version, use current
|
|
194
|
+
if (semver_1.default.satisfies(currentVersion, `^${spec}`))
|
|
195
|
+
return null;
|
|
196
|
+
return spec;
|
|
197
|
+
}
|
|
198
|
+
// It's a semver range like ">=12 <15" or "^18.0.0"
|
|
199
|
+
const range = semver_1.default.validRange(spec);
|
|
200
|
+
if (!range) {
|
|
201
|
+
// Not a valid range, treat as literal version
|
|
202
|
+
return spec;
|
|
203
|
+
}
|
|
204
|
+
// If current Node satisfies the range, use it
|
|
205
|
+
if (semver_1.default.satisfies(currentVersion, range))
|
|
206
|
+
return null;
|
|
207
|
+
// Use minVersion to find the minimum satisfying version, then use its major
|
|
208
|
+
const minVer = semver_1.default.minVersion(range);
|
|
209
|
+
if (minVer)
|
|
210
|
+
return semver_1.default.major(minVer).toString();
|
|
211
|
+
// Last resort: return the spec as-is and let npx handle it
|
|
212
|
+
return spec;
|
|
213
|
+
}
|
|
214
|
+
async function exec(script, args, modules, nodeArgs, engines) {
|
|
215
|
+
const scriptArgs = script ? [script, ...args] : args;
|
|
216
|
+
const finalArgs = [...nodeArgs, ...scriptArgs];
|
|
217
|
+
const env = { ...process.env };
|
|
218
|
+
if (modules) {
|
|
219
|
+
env.NODE_PATH = env.NODE_PATH ? `${modules}:${env.NODE_PATH}` : modules;
|
|
220
|
+
}
|
|
221
|
+
const ver = resolveNodeVersion(engines?.node);
|
|
222
|
+
return new Promise((res, rej) => {
|
|
223
|
+
const child = ver
|
|
224
|
+
? (0, child_process_1.spawn)('npx', [`node@${ver}`, ...finalArgs], { stdio: 'inherit', env })
|
|
225
|
+
: (0, child_process_1.spawn)(process.execPath, finalArgs, { stdio: 'inherit', env });
|
|
226
|
+
child.on('exit', (c) => res(c || 0));
|
|
227
|
+
child.on('error', rej);
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
//# sourceMappingURL=script-runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"script-runner.js","sourceRoot":"","sources":["../src/script-runner.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "nhx",
|
|
3
|
+
"version": "0.0.0-alpha.0",
|
|
4
|
+
"description": "A UVx-like tool for the Node.js ecosystem - simple code execution",
|
|
5
|
+
"type": "commonjs",
|
|
6
|
+
"bin": "dist/cli.js",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist/"
|
|
9
|
+
],
|
|
10
|
+
"scripts": {
|
|
11
|
+
"prepublishOnly": "npm run build && npm test",
|
|
12
|
+
"build": "rm -rf dist && tsc -b",
|
|
13
|
+
"postbuild": "chmod +x dist/cli.js",
|
|
14
|
+
"test": "node --import tsx --test",
|
|
15
|
+
"test:watch": "npm test -- --watch"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"package-manager",
|
|
19
|
+
"npm",
|
|
20
|
+
"node",
|
|
21
|
+
"cli",
|
|
22
|
+
"uv",
|
|
23
|
+
"uvx",
|
|
24
|
+
"fast"
|
|
25
|
+
],
|
|
26
|
+
"author": "",
|
|
27
|
+
"license": "MIT",
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"chalk": "^5.3.0",
|
|
30
|
+
"json5": "^2.2.3",
|
|
31
|
+
"minimist": "^1.2.8",
|
|
32
|
+
"semver": "^7.7.3"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@types/minimist": "^1.2.5",
|
|
36
|
+
"@types/node": "^20.11.0",
|
|
37
|
+
"@types/semver": "^7.7.1",
|
|
38
|
+
"tsx": "^4.21.0",
|
|
39
|
+
"typescript": "^5.3.3"
|
|
40
|
+
},
|
|
41
|
+
"repository": {
|
|
42
|
+
"type": "git",
|
|
43
|
+
"url": "git+https://github.com/kolodny/nhx.git"
|
|
44
|
+
},
|
|
45
|
+
"bugs": {
|
|
46
|
+
"url": "https://github.com/kolodny/nhx/issues"
|
|
47
|
+
},
|
|
48
|
+
"homepage": "https://github.com/kolodny/nhx#readme"
|
|
49
|
+
}
|