sandboxedjs 0.1.0 → 0.1.1
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 +329 -4
- package/dist/index.cjs +355 -56
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +15 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +355 -56
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -3,8 +3,6 @@
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
5
|
var headless = require('@scelar/nodepod/headless');
|
|
6
|
-
var zlib = require('zlib');
|
|
7
|
-
var crypto$1 = require('crypto');
|
|
8
6
|
|
|
9
7
|
var __defProp = Object.defineProperty;
|
|
10
8
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
@@ -15137,6 +15135,206 @@ var commands5 = [grep, find, xargs, diff, cmp];
|
|
|
15137
15135
|
// src/bin/archive.ts
|
|
15138
15136
|
init_mode();
|
|
15139
15137
|
init_path();
|
|
15138
|
+
|
|
15139
|
+
// src/util/binary.ts
|
|
15140
|
+
var isNode = typeof process !== "undefined" && process.versions != null && process.versions.node != null;
|
|
15141
|
+
async function nodeBuiltin(name) {
|
|
15142
|
+
const specifier = `node:${name}`;
|
|
15143
|
+
return await import(
|
|
15144
|
+
/* @vite-ignore */
|
|
15145
|
+
/* webpackIgnore: true */
|
|
15146
|
+
specifier
|
|
15147
|
+
);
|
|
15148
|
+
}
|
|
15149
|
+
var zlibPromise = null;
|
|
15150
|
+
function nodeZlib() {
|
|
15151
|
+
zlibPromise ??= nodeBuiltin("zlib");
|
|
15152
|
+
return zlibPromise;
|
|
15153
|
+
}
|
|
15154
|
+
async function throughStream(data, stream) {
|
|
15155
|
+
const source = new Blob([data]).stream();
|
|
15156
|
+
const piped = source.pipeThrough(stream);
|
|
15157
|
+
return new Uint8Array(await new Response(piped).arrayBuffer());
|
|
15158
|
+
}
|
|
15159
|
+
async function gzip(data) {
|
|
15160
|
+
if (isNode) return new Uint8Array((await nodeZlib()).gzipSync(data));
|
|
15161
|
+
return throughStream(data, new CompressionStream("gzip"));
|
|
15162
|
+
}
|
|
15163
|
+
async function gunzip(data) {
|
|
15164
|
+
if (isNode) return new Uint8Array((await nodeZlib()).gunzipSync(data));
|
|
15165
|
+
return throughStream(data, new DecompressionStream("gzip"));
|
|
15166
|
+
}
|
|
15167
|
+
async function deflate(data) {
|
|
15168
|
+
if (isNode) return new Uint8Array((await nodeZlib()).deflateSync(data));
|
|
15169
|
+
return throughStream(data, new CompressionStream("deflate"));
|
|
15170
|
+
}
|
|
15171
|
+
async function inflate(data) {
|
|
15172
|
+
if (isNode) return new Uint8Array((await nodeZlib()).inflateSync(data));
|
|
15173
|
+
return throughStream(data, new DecompressionStream("deflate"));
|
|
15174
|
+
}
|
|
15175
|
+
async function inflateRaw(data) {
|
|
15176
|
+
if (isNode) return new Uint8Array((await nodeZlib()).inflateRawSync(data));
|
|
15177
|
+
return throughStream(data, new DecompressionStream("deflate-raw"));
|
|
15178
|
+
}
|
|
15179
|
+
var cryptoPromise = null;
|
|
15180
|
+
function nodeCrypto() {
|
|
15181
|
+
cryptoPromise ??= nodeBuiltin("crypto");
|
|
15182
|
+
return cryptoPromise;
|
|
15183
|
+
}
|
|
15184
|
+
var SUBTLE_NAMES = {
|
|
15185
|
+
sha1: "SHA-1",
|
|
15186
|
+
sha256: "SHA-256",
|
|
15187
|
+
sha384: "SHA-384",
|
|
15188
|
+
sha512: "SHA-512"
|
|
15189
|
+
};
|
|
15190
|
+
var UnsupportedAlgorithmError = class extends Error {
|
|
15191
|
+
constructor(algorithm) {
|
|
15192
|
+
super(`${algorithm} is not available in this environment`);
|
|
15193
|
+
this.name = "UnsupportedAlgorithmError";
|
|
15194
|
+
}
|
|
15195
|
+
};
|
|
15196
|
+
async function digestHex(algorithm, data) {
|
|
15197
|
+
if (isNode) {
|
|
15198
|
+
const { createHash } = await nodeCrypto();
|
|
15199
|
+
return createHash(algorithm).update(data).digest("hex");
|
|
15200
|
+
}
|
|
15201
|
+
if (algorithm === "md5") return md5Hex(data);
|
|
15202
|
+
const name = SUBTLE_NAMES[algorithm];
|
|
15203
|
+
if (!name) throw new UnsupportedAlgorithmError(algorithm);
|
|
15204
|
+
const buffer = await crypto.subtle.digest(name, data);
|
|
15205
|
+
return toHex(new Uint8Array(buffer));
|
|
15206
|
+
}
|
|
15207
|
+
async function randomUuid() {
|
|
15208
|
+
if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") return crypto.randomUUID();
|
|
15209
|
+
const { randomUUID } = await nodeCrypto();
|
|
15210
|
+
return randomUUID();
|
|
15211
|
+
}
|
|
15212
|
+
function toHex(bytes) {
|
|
15213
|
+
let out = "";
|
|
15214
|
+
for (const byte of bytes) out += byte.toString(16).padStart(2, "0");
|
|
15215
|
+
return out;
|
|
15216
|
+
}
|
|
15217
|
+
function md5Hex(input) {
|
|
15218
|
+
const S = [
|
|
15219
|
+
7,
|
|
15220
|
+
12,
|
|
15221
|
+
17,
|
|
15222
|
+
22,
|
|
15223
|
+
7,
|
|
15224
|
+
12,
|
|
15225
|
+
17,
|
|
15226
|
+
22,
|
|
15227
|
+
7,
|
|
15228
|
+
12,
|
|
15229
|
+
17,
|
|
15230
|
+
22,
|
|
15231
|
+
7,
|
|
15232
|
+
12,
|
|
15233
|
+
17,
|
|
15234
|
+
22,
|
|
15235
|
+
5,
|
|
15236
|
+
9,
|
|
15237
|
+
14,
|
|
15238
|
+
20,
|
|
15239
|
+
5,
|
|
15240
|
+
9,
|
|
15241
|
+
14,
|
|
15242
|
+
20,
|
|
15243
|
+
5,
|
|
15244
|
+
9,
|
|
15245
|
+
14,
|
|
15246
|
+
20,
|
|
15247
|
+
5,
|
|
15248
|
+
9,
|
|
15249
|
+
14,
|
|
15250
|
+
20,
|
|
15251
|
+
4,
|
|
15252
|
+
11,
|
|
15253
|
+
16,
|
|
15254
|
+
23,
|
|
15255
|
+
4,
|
|
15256
|
+
11,
|
|
15257
|
+
16,
|
|
15258
|
+
23,
|
|
15259
|
+
4,
|
|
15260
|
+
11,
|
|
15261
|
+
16,
|
|
15262
|
+
23,
|
|
15263
|
+
4,
|
|
15264
|
+
11,
|
|
15265
|
+
16,
|
|
15266
|
+
23,
|
|
15267
|
+
6,
|
|
15268
|
+
10,
|
|
15269
|
+
15,
|
|
15270
|
+
21,
|
|
15271
|
+
6,
|
|
15272
|
+
10,
|
|
15273
|
+
15,
|
|
15274
|
+
21,
|
|
15275
|
+
6,
|
|
15276
|
+
10,
|
|
15277
|
+
15,
|
|
15278
|
+
21,
|
|
15279
|
+
6,
|
|
15280
|
+
10,
|
|
15281
|
+
15,
|
|
15282
|
+
21
|
|
15283
|
+
];
|
|
15284
|
+
const K = new Uint32Array(64);
|
|
15285
|
+
for (let i = 0; i < 64; i++) K[i] = Math.floor(Math.abs(Math.sin(i + 1)) * 2 ** 32);
|
|
15286
|
+
const bitLength = input.length * 8;
|
|
15287
|
+
const padded = new Uint8Array(((input.length + 8 >> 6) + 1) * 64);
|
|
15288
|
+
padded.set(input);
|
|
15289
|
+
padded[input.length] = 128;
|
|
15290
|
+
const view = new DataView(padded.buffer);
|
|
15291
|
+
view.setUint32(padded.length - 8, bitLength >>> 0, true);
|
|
15292
|
+
view.setUint32(padded.length - 4, Math.floor(bitLength / 2 ** 32), true);
|
|
15293
|
+
let a0 = 1732584193;
|
|
15294
|
+
let b0 = 4023233417;
|
|
15295
|
+
let c0 = 2562383102;
|
|
15296
|
+
let d0 = 271733878;
|
|
15297
|
+
for (let chunk = 0; chunk < padded.length; chunk += 64) {
|
|
15298
|
+
const M = new Uint32Array(16);
|
|
15299
|
+
for (let i = 0; i < 16; i++) M[i] = view.getUint32(chunk + i * 4, true);
|
|
15300
|
+
let [a, b, c, d] = [a0, b0, c0, d0];
|
|
15301
|
+
for (let i = 0; i < 64; i++) {
|
|
15302
|
+
let f;
|
|
15303
|
+
let g;
|
|
15304
|
+
if (i < 16) {
|
|
15305
|
+
f = b & c | ~b & d;
|
|
15306
|
+
g = i;
|
|
15307
|
+
} else if (i < 32) {
|
|
15308
|
+
f = d & b | ~d & c;
|
|
15309
|
+
g = (5 * i + 1) % 16;
|
|
15310
|
+
} else if (i < 48) {
|
|
15311
|
+
f = b ^ c ^ d;
|
|
15312
|
+
g = (3 * i + 5) % 16;
|
|
15313
|
+
} else {
|
|
15314
|
+
f = c ^ (b | ~d);
|
|
15315
|
+
g = 7 * i % 16;
|
|
15316
|
+
}
|
|
15317
|
+
const tmp = d;
|
|
15318
|
+
d = c;
|
|
15319
|
+
c = b;
|
|
15320
|
+
const sum = a + f + K[i] + M[g] >>> 0;
|
|
15321
|
+
b = b + (sum << S[i] | sum >>> 32 - S[i]) >>> 0;
|
|
15322
|
+
a = tmp;
|
|
15323
|
+
}
|
|
15324
|
+
a0 = a0 + a >>> 0;
|
|
15325
|
+
b0 = b0 + b >>> 0;
|
|
15326
|
+
c0 = c0 + c >>> 0;
|
|
15327
|
+
d0 = d0 + d >>> 0;
|
|
15328
|
+
}
|
|
15329
|
+
const out = new Uint8Array(16);
|
|
15330
|
+
new DataView(out.buffer).setUint32(0, a0, true);
|
|
15331
|
+
new DataView(out.buffer).setUint32(4, b0, true);
|
|
15332
|
+
new DataView(out.buffer).setUint32(8, c0, true);
|
|
15333
|
+
new DataView(out.buffer).setUint32(12, d0, true);
|
|
15334
|
+
return toHex(out);
|
|
15335
|
+
}
|
|
15336
|
+
|
|
15337
|
+
// src/bin/archive.ts
|
|
15140
15338
|
var BLOCK = 512;
|
|
15141
15339
|
var encoder4 = new TextEncoder();
|
|
15142
15340
|
var decoder6 = new TextDecoder();
|
|
@@ -15294,7 +15492,7 @@ var tar = defineCommand({
|
|
|
15294
15492
|
};
|
|
15295
15493
|
for (const operand of args.positional) add(resolve(baseDir, operand), operand);
|
|
15296
15494
|
let bytes2 = createTar(entries2);
|
|
15297
|
-
if (compressed) bytes2 =
|
|
15495
|
+
if (compressed) bytes2 = await gzip(bytes2);
|
|
15298
15496
|
if (archive === void 0 || archive === "-") ctx.write(bytes2);
|
|
15299
15497
|
else ctx.vfs.writeFile(ctx.path(archive), bytes2, { cred: ctx.cred, mode: 420 });
|
|
15300
15498
|
return 0;
|
|
@@ -15308,7 +15506,7 @@ var tar = defineCommand({
|
|
|
15308
15506
|
return ctx.reportError(e, archive);
|
|
15309
15507
|
}
|
|
15310
15508
|
}
|
|
15311
|
-
if (bytes[0] === 31 && bytes[1] === 139) bytes =
|
|
15509
|
+
if (bytes[0] === 31 && bytes[1] === 139) bytes = await gunzip(bytes);
|
|
15312
15510
|
const entries = readTar(bytes);
|
|
15313
15511
|
const strip = args.num("strip-components", 0);
|
|
15314
15512
|
if (args.has("list")) {
|
|
@@ -15354,7 +15552,7 @@ var tar = defineCommand({
|
|
|
15354
15552
|
return 2;
|
|
15355
15553
|
}
|
|
15356
15554
|
});
|
|
15357
|
-
var
|
|
15555
|
+
var gzip2 = defineCommand({
|
|
15358
15556
|
name: "gzip",
|
|
15359
15557
|
path: "/bin/gzip",
|
|
15360
15558
|
summary: "compress files",
|
|
@@ -15377,28 +15575,28 @@ var gzip = defineCommand({
|
|
|
15377
15575
|
toStdout,
|
|
15378
15576
|
keep: args.has("keep") || ctx.name === "zcat",
|
|
15379
15577
|
suffix: ".gz",
|
|
15380
|
-
compress: (data) =>
|
|
15381
|
-
expand: (data) =>
|
|
15578
|
+
compress: (data) => gzip(data),
|
|
15579
|
+
expand: (data) => gunzip(data)
|
|
15382
15580
|
});
|
|
15383
15581
|
}
|
|
15384
15582
|
});
|
|
15385
|
-
var
|
|
15583
|
+
var gunzip2 = defineCommand({
|
|
15386
15584
|
name: "gunzip",
|
|
15387
15585
|
path: "/bin/gunzip",
|
|
15388
15586
|
summary: "decompress files",
|
|
15389
|
-
run: (ctx) =>
|
|
15587
|
+
run: (ctx) => gzip2.run(ctx)
|
|
15390
15588
|
});
|
|
15391
15589
|
var zcat = defineCommand({
|
|
15392
15590
|
name: "zcat",
|
|
15393
15591
|
path: "/bin/zcat",
|
|
15394
15592
|
summary: "decompress files to standard output",
|
|
15395
|
-
run: (ctx) =>
|
|
15593
|
+
run: (ctx) => gzip2.run(ctx)
|
|
15396
15594
|
});
|
|
15397
15595
|
async function runCompressor(ctx, operands, opts) {
|
|
15398
15596
|
if (operands.length === 0) {
|
|
15399
15597
|
const data = await ctx.stdin.readAll();
|
|
15400
15598
|
try {
|
|
15401
|
-
ctx.write(opts.decompress ? opts.expand(data) : opts.compress(data));
|
|
15599
|
+
ctx.write(opts.decompress ? await opts.expand(data) : await opts.compress(data));
|
|
15402
15600
|
return 0;
|
|
15403
15601
|
} catch (e) {
|
|
15404
15602
|
return ctx.fail(e instanceof Error ? e.message : String(e));
|
|
@@ -15415,7 +15613,7 @@ async function runCompressor(ctx, operands, opts) {
|
|
|
15415
15613
|
continue;
|
|
15416
15614
|
}
|
|
15417
15615
|
try {
|
|
15418
|
-
const result = opts.decompress ? opts.expand(data) : opts.compress(data);
|
|
15616
|
+
const result = opts.decompress ? await opts.expand(data) : await opts.compress(data);
|
|
15419
15617
|
if (opts.toStdout) {
|
|
15420
15618
|
ctx.write(result);
|
|
15421
15619
|
continue;
|
|
@@ -15441,12 +15639,14 @@ var zlibCompress = defineCommand({
|
|
|
15441
15639
|
toStdout: args.has("stdout"),
|
|
15442
15640
|
keep: false,
|
|
15443
15641
|
suffix: ".Z",
|
|
15444
|
-
compress: (data) =>
|
|
15445
|
-
expand: (data) =>
|
|
15642
|
+
compress: (data) => deflate(data),
|
|
15643
|
+
expand: (data) => inflate(data)
|
|
15446
15644
|
});
|
|
15447
15645
|
}
|
|
15448
15646
|
});
|
|
15449
|
-
var commands6 = [tar,
|
|
15647
|
+
var commands6 = [tar, gzip2, gunzip2, zcat, zlibCompress];
|
|
15648
|
+
|
|
15649
|
+
// src/bin/hash.ts
|
|
15450
15650
|
function makeSum(name, algorithm, path) {
|
|
15451
15651
|
return defineCommand({
|
|
15452
15652
|
name,
|
|
@@ -15465,7 +15665,7 @@ function makeSum(name, algorithm, path) {
|
|
|
15465
15665
|
if (args.has("check")) return checkSums(ctx, algorithm, args.positional, args.has("quiet") || args.has("status"));
|
|
15466
15666
|
const { sources, ok } = await readInputs(ctx, args.positional, { stdinName: "-" });
|
|
15467
15667
|
for (const source of sources) {
|
|
15468
|
-
const digest =
|
|
15668
|
+
const digest = await digestHex(algorithm, source.bytes);
|
|
15469
15669
|
if (args.has("tag")) ctx.line(`${algorithm.toUpperCase()} (${source.name}) = ${digest}`);
|
|
15470
15670
|
else ctx.line(`${digest} ${source.name}`);
|
|
15471
15671
|
}
|
|
@@ -15486,7 +15686,7 @@ async function checkSums(ctx, algorithm, files, quiet) {
|
|
|
15486
15686
|
const [, expected, name] = m;
|
|
15487
15687
|
try {
|
|
15488
15688
|
const bytes = ctx.vfs.readFile(ctx.path(name), ctx.cred);
|
|
15489
|
-
const actual =
|
|
15689
|
+
const actual = await digestHex(algorithm, bytes);
|
|
15490
15690
|
if (actual === expected.toLowerCase()) {
|
|
15491
15691
|
if (!quiet) ctx.line(`${name}: OK`);
|
|
15492
15692
|
} else {
|
|
@@ -15617,8 +15817,8 @@ var uuidgen = defineCommand({
|
|
|
15617
15817
|
name: "uuidgen",
|
|
15618
15818
|
path: "/usr/bin/uuidgen",
|
|
15619
15819
|
summary: "create a new UUID value",
|
|
15620
|
-
run(ctx) {
|
|
15621
|
-
ctx.line(
|
|
15820
|
+
async run(ctx) {
|
|
15821
|
+
ctx.line(await randomUuid());
|
|
15622
15822
|
return 0;
|
|
15623
15823
|
}
|
|
15624
15824
|
});
|
|
@@ -17692,7 +17892,7 @@ var pip = defineCommand({
|
|
|
17692
17892
|
}
|
|
17693
17893
|
const data = new Uint8Array(await (await fetch(wheel.url)).arrayBuffer());
|
|
17694
17894
|
ctx.line(` Downloading ${wheel.filename} (${Math.round(data.length / 1024)} kB)`);
|
|
17695
|
-
installWheel(ctx, siteDir, data, name, chosen);
|
|
17895
|
+
await installWheel(ctx, siteDir, data, name, chosen);
|
|
17696
17896
|
ctx.line(`Successfully installed ${name}-${chosen}`);
|
|
17697
17897
|
} catch (e) {
|
|
17698
17898
|
ctx.warn(`ERROR: Could not install ${spec}: ${e instanceof Error ? e.message : String(e)}`);
|
|
@@ -17702,8 +17902,8 @@ var pip = defineCommand({
|
|
|
17702
17902
|
return status;
|
|
17703
17903
|
}
|
|
17704
17904
|
});
|
|
17705
|
-
function installWheel(ctx, siteDir, data, name, version) {
|
|
17706
|
-
const entries = readZip(data);
|
|
17905
|
+
async function installWheel(ctx, siteDir, data, name, version) {
|
|
17906
|
+
const entries = await readZip(data);
|
|
17707
17907
|
for (const entry of entries) {
|
|
17708
17908
|
if (entry.name.endsWith("/")) continue;
|
|
17709
17909
|
const target = join(siteDir, entry.name);
|
|
@@ -17717,7 +17917,7 @@ function installWheel(ctx, siteDir, data, name, version) {
|
|
|
17717
17917
|
Version: ${version}
|
|
17718
17918
|
`, { cred: ctx.cred });
|
|
17719
17919
|
}
|
|
17720
|
-
function readZip(data) {
|
|
17920
|
+
async function readZip(data) {
|
|
17721
17921
|
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
17722
17922
|
const entries = [];
|
|
17723
17923
|
let eocd = -1;
|
|
@@ -17743,7 +17943,7 @@ function readZip(data) {
|
|
|
17743
17943
|
const localExtraLength = view.getUint16(localOffset + 28, true);
|
|
17744
17944
|
const dataStart = localOffset + 30 + localNameLength + localExtraLength;
|
|
17745
17945
|
const raw = data.subarray(dataStart, dataStart + compressedSize);
|
|
17746
|
-
entries.push({ name, data: method === 0 ? raw.slice() :
|
|
17946
|
+
entries.push({ name, data: method === 0 ? raw.slice() : await inflateRaw(raw) });
|
|
17747
17947
|
offset += 46 + nameLength + extraLength + commentLength;
|
|
17748
17948
|
}
|
|
17749
17949
|
return entries;
|
|
@@ -17774,9 +17974,17 @@ function findProjectRoot(ctx) {
|
|
|
17774
17974
|
function writeManifest(ctx, path, manifest) {
|
|
17775
17975
|
ctx.vfs.writeFile(path, JSON.stringify(manifest, null, 2) + "\n", { cred: ctx.cred, mode: 420 });
|
|
17776
17976
|
}
|
|
17977
|
+
function splitPackageSpec(spec) {
|
|
17978
|
+
const at = spec.lastIndexOf("@");
|
|
17979
|
+
if (at <= 0) return { name: spec };
|
|
17980
|
+
return { name: spec.slice(0, at), version: spec.slice(at + 1) };
|
|
17981
|
+
}
|
|
17777
17982
|
async function installPackages(ctx, specs, opts) {
|
|
17778
17983
|
const installer = opts.cwd === "/" ? ctx.kernel.pod.packages : new headless.DependencyInstaller(ctx.vfs.volume, { cwd: opts.cwd });
|
|
17779
|
-
const onProgress = (message) =>
|
|
17984
|
+
const onProgress = (message) => {
|
|
17985
|
+
if (!opts.quiet) ctx.stderr.write(message.endsWith("\n") ? message : message + "\n");
|
|
17986
|
+
};
|
|
17987
|
+
const note = (text) => opts.quiet ? ctx.stderr.write(text + "\n") : ctx.line(text);
|
|
17780
17988
|
if (!ctx.kernel.net.options.allowOutbound) {
|
|
17781
17989
|
ctx.warn("npm error code ENOTFOUND");
|
|
17782
17990
|
ctx.warn("npm error network request to https://registry.npmjs.org failed");
|
|
@@ -17786,7 +17994,7 @@ async function installPackages(ctx, specs, opts) {
|
|
|
17786
17994
|
}
|
|
17787
17995
|
try {
|
|
17788
17996
|
if (specs.length === 0) {
|
|
17789
|
-
|
|
17997
|
+
note(`npm install (project at ${opts.cwd})`);
|
|
17790
17998
|
await installer.installFromManifest(join(opts.cwd, "package.json"), {
|
|
17791
17999
|
withDevDeps: true,
|
|
17792
18000
|
onProgress,
|
|
@@ -17794,11 +18002,8 @@ async function installPackages(ctx, specs, opts) {
|
|
|
17794
18002
|
});
|
|
17795
18003
|
} else {
|
|
17796
18004
|
for (const spec of specs) {
|
|
17797
|
-
const
|
|
17798
|
-
|
|
17799
|
-
const name = at > 0 && !(scoped && at === 0) ? spec.slice(0, at) : spec;
|
|
17800
|
-
const version = at > 0 && !(scoped && at === 0) ? spec.slice(at + 1) : void 0;
|
|
17801
|
-
ctx.line(`added ${name}${version ? `@${version}` : ""}`);
|
|
18005
|
+
const { name, version } = splitPackageSpec(spec);
|
|
18006
|
+
note(`added ${name}${version ? `@${version}` : ""}`);
|
|
17802
18007
|
await installer.install(name, version, {
|
|
17803
18008
|
onProgress,
|
|
17804
18009
|
persist: opts.save !== false,
|
|
@@ -18042,33 +18247,127 @@ function printNpmHelp(ctx) {
|
|
|
18042
18247
|
ctx.line("");
|
|
18043
18248
|
ctx.line(`npm@${NPM_VERSION} /usr/lib/node_modules/npm`);
|
|
18044
18249
|
}
|
|
18250
|
+
function packageBinaries(ctx, root, packageName) {
|
|
18251
|
+
const manifestPath = join(root, "node_modules", packageName, "package.json");
|
|
18252
|
+
try {
|
|
18253
|
+
const manifest = JSON.parse(ctx.vfs.readText(manifestPath, ctx.cred));
|
|
18254
|
+
if (typeof manifest.bin === "string") return [basename(packageName)];
|
|
18255
|
+
if (manifest.bin && typeof manifest.bin === "object") return Object.keys(manifest.bin);
|
|
18256
|
+
} catch {
|
|
18257
|
+
}
|
|
18258
|
+
return [];
|
|
18259
|
+
}
|
|
18260
|
+
function findLocalBin(ctx, name) {
|
|
18261
|
+
let dir3 = ctx.cwd;
|
|
18262
|
+
for (let i = 0; i < 64; i++) {
|
|
18263
|
+
const candidate = join(dir3, "node_modules", ".bin", name);
|
|
18264
|
+
if (ctx.vfs.lexists(candidate)) return candidate;
|
|
18265
|
+
const parent = dirname(dir3);
|
|
18266
|
+
if (parent === dir3) break;
|
|
18267
|
+
dir3 = parent;
|
|
18268
|
+
}
|
|
18269
|
+
return null;
|
|
18270
|
+
}
|
|
18045
18271
|
var npx = defineCommand({
|
|
18046
18272
|
name: "npx",
|
|
18047
18273
|
path: "/usr/bin/npx",
|
|
18048
18274
|
summary: "run a command from a local or remote npm package",
|
|
18275
|
+
usage: "npx [-y] [-p package] <command> [args]",
|
|
18276
|
+
manual: `Runs a package binary, installing the package first if it is not
|
|
18277
|
+
already present. Installation needs outbound network access, which is off
|
|
18278
|
+
unless the container was created with network: { allowOutbound: true }.`,
|
|
18049
18279
|
async run(ctx) {
|
|
18050
|
-
const args = parseArgs(
|
|
18051
|
-
|
|
18052
|
-
|
|
18053
|
-
|
|
18280
|
+
const args = parseArgs(
|
|
18281
|
+
ctx.args,
|
|
18282
|
+
[
|
|
18283
|
+
{ short: "y", long: "yes" },
|
|
18284
|
+
{ long: "no-install" },
|
|
18285
|
+
{ short: "p", long: "package", arg: true, multiple: true },
|
|
18286
|
+
{ short: "q", long: "quiet" },
|
|
18287
|
+
{ short: "c", long: "call", arg: true },
|
|
18288
|
+
{ long: "version" },
|
|
18289
|
+
{ long: "help" }
|
|
18290
|
+
],
|
|
18291
|
+
{ stopAtFirstPositional: true, allowUnknown: true }
|
|
18292
|
+
);
|
|
18293
|
+
if (args.has("version")) {
|
|
18294
|
+
ctx.line(NPM_VERSION);
|
|
18295
|
+
return 0;
|
|
18296
|
+
}
|
|
18297
|
+
if (args.has("help")) {
|
|
18298
|
+
ctx.line("Usage: npx [options] <command>[@version] [command-arg]...");
|
|
18299
|
+
ctx.line("");
|
|
18300
|
+
ctx.line("Options:");
|
|
18301
|
+
ctx.line(" -y, --yes skip the install confirmation (always implied here)");
|
|
18302
|
+
ctx.line(" -p, --package <pkg> package providing the command (repeatable)");
|
|
18303
|
+
ctx.line(" --no-install fail instead of installing a missing package");
|
|
18304
|
+
ctx.line(" -q, --quiet suppress install progress");
|
|
18305
|
+
return 0;
|
|
18306
|
+
}
|
|
18307
|
+
const call = args.str("call");
|
|
18308
|
+
const operands = call ? call.split(/\s+/).filter(Boolean) : args.positional;
|
|
18309
|
+
if (operands.length === 0) {
|
|
18310
|
+
ctx.warn("a command is required");
|
|
18311
|
+
ctx.warn("usage: npx [options] <command>[@version] [command-arg]...");
|
|
18312
|
+
return 1;
|
|
18313
|
+
}
|
|
18054
18314
|
const root = findProjectRoot(ctx);
|
|
18055
|
-
const
|
|
18056
|
-
const
|
|
18057
|
-
|
|
18058
|
-
|
|
18315
|
+
const binDir = join(root, "node_modules", ".bin");
|
|
18316
|
+
const [spec, ...rest] = operands;
|
|
18317
|
+
const { name: specName, version } = splitPackageSpec(spec);
|
|
18318
|
+
const packages = args.list("package");
|
|
18319
|
+
const packageSpec = packages[0] ?? spec;
|
|
18320
|
+
const packageName = packages[0] ? splitPackageSpec(packages[0]).name : specName;
|
|
18321
|
+
let command = packages.length > 0 ? spec : basename(specName);
|
|
18322
|
+
const run = async (binary) => {
|
|
18323
|
+
const env2 = {
|
|
18324
|
+
...ctx.env,
|
|
18325
|
+
PATH: `${binDir}:${ctx.env.PATH ?? ""}`,
|
|
18326
|
+
npm_config_user_agent: `npm/${NPM_VERSION} node/${NODE_VERSION} linux x64`
|
|
18327
|
+
};
|
|
18328
|
+
return await ctx.kernel.spawn([binary, ...rest], {
|
|
18329
|
+
cwd: ctx.cwd,
|
|
18330
|
+
env: env2,
|
|
18331
|
+
cred: ctx.cred,
|
|
18332
|
+
ppid: ctx.proc.pid,
|
|
18333
|
+
stdin: ctx.stdin,
|
|
18334
|
+
stdout: ctx.stdout,
|
|
18335
|
+
stderr: ctx.stderr
|
|
18336
|
+
}).wait();
|
|
18337
|
+
};
|
|
18338
|
+
if (!version) {
|
|
18339
|
+
if (findLocalBin(ctx, command)) return run(command);
|
|
18340
|
+
if (ctx.kernel.which(command, ctx.cwd, ctx.env, ctx.cred)) return run(command);
|
|
18341
|
+
}
|
|
18342
|
+
if (args.has("no-install")) {
|
|
18343
|
+
ctx.warn(`command not found: ${command}`);
|
|
18344
|
+
return 127;
|
|
18345
|
+
}
|
|
18346
|
+
if (!ctx.kernel.net.options.allowOutbound) {
|
|
18347
|
+
ctx.warn(`could not determine executable to run: ${command}`);
|
|
18348
|
+
ctx.warn(`'${packageName}' is not installed, and installing it needs network access.`);
|
|
18349
|
+
ctx.warn("Outbound network access is disabled for this container.");
|
|
18350
|
+
ctx.warn("Enable it with createContainer({ network: { allowOutbound: true } }).");
|
|
18351
|
+
return 127;
|
|
18352
|
+
}
|
|
18353
|
+
ctx.stderr.write(`npx: installing ${packageSpec}...
|
|
18059
18354
|
`);
|
|
18060
|
-
|
|
18355
|
+
const installed = await installPackages(ctx, [packageSpec], {
|
|
18356
|
+
cwd: root,
|
|
18357
|
+
save: false,
|
|
18358
|
+
quiet: true
|
|
18359
|
+
});
|
|
18360
|
+
if (installed !== 0) return installed;
|
|
18361
|
+
if (!findLocalBin(ctx, command)) {
|
|
18362
|
+
const binaries = packageBinaries(ctx, root, packageName);
|
|
18363
|
+
const chosen = binaries.includes(command) ? command : binaries[0];
|
|
18364
|
+
if (chosen === void 0) {
|
|
18365
|
+
ctx.warn(`could not determine executable to run: ${packageName} provides no binary`);
|
|
18366
|
+
return 127;
|
|
18367
|
+
}
|
|
18368
|
+
command = chosen;
|
|
18061
18369
|
}
|
|
18062
|
-
|
|
18063
|
-
return await ctx.kernel.spawn([name, ...rest], {
|
|
18064
|
-
cwd: ctx.cwd,
|
|
18065
|
-
env: env2,
|
|
18066
|
-
cred: ctx.cred,
|
|
18067
|
-
ppid: ctx.proc.pid,
|
|
18068
|
-
stdin: ctx.stdin,
|
|
18069
|
-
stdout: ctx.stdout,
|
|
18070
|
-
stderr: ctx.stderr
|
|
18071
|
-
}).wait();
|
|
18370
|
+
return run(command);
|
|
18072
18371
|
}
|
|
18073
18372
|
});
|
|
18074
18373
|
function makeNpmAlias(name, path) {
|
|
@@ -18487,7 +18786,7 @@ var Container = class _Container {
|
|
|
18487
18786
|
}
|
|
18488
18787
|
// ── boot ──────────────────────────────────────────────────────────────────
|
|
18489
18788
|
static async create(opts = {}) {
|
|
18490
|
-
const pod = await headless.Nodepod.boot({
|
|
18789
|
+
const pod = opts.pod ?? await headless.Nodepod.boot({
|
|
18491
18790
|
headless: true,
|
|
18492
18791
|
serviceWorker: false,
|
|
18493
18792
|
env: opts.env ?? {},
|
|
@@ -18538,8 +18837,8 @@ var Container = class _Container {
|
|
|
18538
18837
|
/** Copy a directory tree from the host filesystem into the container. */
|
|
18539
18838
|
async copyIn(hostPath, containerPath) {
|
|
18540
18839
|
this.assertActive();
|
|
18541
|
-
const { readdir, readFile, stat: stat2 } = await
|
|
18542
|
-
const nodePath = await
|
|
18840
|
+
const { readdir, readFile, stat: stat2 } = await nodeBuiltin("fs/promises");
|
|
18841
|
+
const nodePath = await nodeBuiltin("path");
|
|
18543
18842
|
const walk = async (src, dest) => {
|
|
18544
18843
|
const st = await stat2(src);
|
|
18545
18844
|
if (st.isDirectory()) {
|
|
@@ -18566,8 +18865,8 @@ var Container = class _Container {
|
|
|
18566
18865
|
/** Copy a file or directory out of the container onto the host. */
|
|
18567
18866
|
async copyOut(containerPath, hostPath) {
|
|
18568
18867
|
this.assertActive();
|
|
18569
|
-
const { mkdir: mkdir2, writeFile } = await
|
|
18570
|
-
const nodePath = await
|
|
18868
|
+
const { mkdir: mkdir2, writeFile } = await nodeBuiltin("fs/promises");
|
|
18869
|
+
const nodePath = await nodeBuiltin("path");
|
|
18571
18870
|
const src = resolve(this.defaults.cwd, containerPath);
|
|
18572
18871
|
const walk = async (from, to) => {
|
|
18573
18872
|
const st = this.kernel.vfs.lstat(from);
|
|
@@ -18791,7 +19090,7 @@ var Container = class _Container {
|
|
|
18791
19090
|
*/
|
|
18792
19091
|
async expose(port, opts = {}) {
|
|
18793
19092
|
this.assertActive();
|
|
18794
|
-
const http = await
|
|
19093
|
+
const http = await nodeBuiltin("http");
|
|
18795
19094
|
const container = this;
|
|
18796
19095
|
const server = http.createServer((req, res) => {
|
|
18797
19096
|
const chunks = [];
|