@slicervm/sdk 0.1.0 → 0.1.2
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 +1 -1
- package/dist/index.cjs +309 -26
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +105 -3
- package/dist/index.d.ts +105 -3
- package/dist/index.js +305 -26
- package/dist/index.js.map +1 -1
- package/package.json +5 -1
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
TypeScript SDK for the [Slicer](https://slicervm.com) VM control-plane API.
|
|
4
4
|
|
|
5
|
-
Mirrors the [Go SDK](https://github.com/slicervm/sdk) semantically
|
|
5
|
+
Mirrors the [Go SDK](https://github.com/slicervm/sdk) semantically. The top-level `SlicerClient` exposes `hostGroups`, `vms`, and `secrets` namespaces for control-plane operations; per-VM operations live on a `VM` handle returned from `client.vms.create()` / `client.vms.attach()`.
|
|
6
6
|
|
|
7
7
|
Supports Unix socket and HTTP(S) transports.
|
|
8
8
|
|
package/dist/index.cjs
CHANGED
|
@@ -4,14 +4,19 @@ var http = require('http');
|
|
|
4
4
|
var https = require('https');
|
|
5
5
|
var url = require('url');
|
|
6
6
|
var os = require('os');
|
|
7
|
-
var
|
|
7
|
+
var path2 = require('path');
|
|
8
|
+
var net = require('net');
|
|
9
|
+
var fs = require('fs');
|
|
10
|
+
var ws = require('ws');
|
|
8
11
|
|
|
9
12
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
10
13
|
|
|
11
14
|
var http__default = /*#__PURE__*/_interopDefault(http);
|
|
12
15
|
var https__default = /*#__PURE__*/_interopDefault(https);
|
|
13
16
|
var os__default = /*#__PURE__*/_interopDefault(os);
|
|
14
|
-
var
|
|
17
|
+
var path2__default = /*#__PURE__*/_interopDefault(path2);
|
|
18
|
+
var net__default = /*#__PURE__*/_interopDefault(net);
|
|
19
|
+
var fs__default = /*#__PURE__*/_interopDefault(fs);
|
|
15
20
|
|
|
16
21
|
// src/types.ts
|
|
17
22
|
var ExecStdioText = "text";
|
|
@@ -27,11 +32,11 @@ var SlicerAPIError = class extends Error {
|
|
|
27
32
|
method;
|
|
28
33
|
path;
|
|
29
34
|
body;
|
|
30
|
-
constructor(method,
|
|
31
|
-
super(`slicer ${method} ${
|
|
35
|
+
constructor(method, path3, status, body) {
|
|
36
|
+
super(`slicer ${method} ${path3} failed: ${status} ${body}`);
|
|
32
37
|
this.name = "SlicerAPIError";
|
|
33
38
|
this.method = method;
|
|
34
|
-
this.path =
|
|
39
|
+
this.path = path3;
|
|
35
40
|
this.status = status;
|
|
36
41
|
this.body = body;
|
|
37
42
|
}
|
|
@@ -44,7 +49,7 @@ function resolveTransport(baseURL) {
|
|
|
44
49
|
if (!trimmed) throw new Error("Slicer baseURL is required");
|
|
45
50
|
let candidate = trimmed;
|
|
46
51
|
if (candidate.startsWith("unix://")) candidate = candidate.slice("unix://".length);
|
|
47
|
-
if (candidate.startsWith("~/")) candidate =
|
|
52
|
+
if (candidate.startsWith("~/")) candidate = path2__default.default.join(os__default.default.homedir(), candidate.slice(2));
|
|
48
53
|
const socketLike = candidate.startsWith("/") || candidate.startsWith("./") || candidate.startsWith("../") || candidate.endsWith(".sock");
|
|
49
54
|
if (socketLike) return { kind: "socket", socketPath: candidate };
|
|
50
55
|
return { kind: "net", url: new url.URL(trimmed) };
|
|
@@ -303,6 +308,258 @@ function secretFromWire(w) {
|
|
|
303
308
|
...w.modified_at !== void 0 && { modifiedAt: w.modified_at }
|
|
304
309
|
};
|
|
305
310
|
}
|
|
311
|
+
function looksLikeUnixSocketPath(s) {
|
|
312
|
+
if (!s) return false;
|
|
313
|
+
return s.startsWith("/") || s.startsWith("./") || s.startsWith("../") || s.includes("/");
|
|
314
|
+
}
|
|
315
|
+
function parseAddressMapping(spec) {
|
|
316
|
+
const lastColon = spec.lastIndexOf(":");
|
|
317
|
+
if (lastColon !== -1) {
|
|
318
|
+
const localPart = spec.slice(0, lastColon);
|
|
319
|
+
const remotePart = spec.slice(lastColon + 1);
|
|
320
|
+
if (looksLikeUnixSocketPath(localPart) && looksLikeUnixSocketPath(remotePart)) {
|
|
321
|
+
const localAbs = path2__default.default.isAbsolute(localPart) ? localPart : path2__default.default.resolve(localPart);
|
|
322
|
+
return { rawSpec: spec, listenUnixPath: localAbs, remoteUnixPath: remotePart };
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
const tcpToUnix = spec.indexOf(":/");
|
|
326
|
+
if (tcpToUnix !== -1) {
|
|
327
|
+
const listenPart = spec.slice(0, tcpToUnix);
|
|
328
|
+
const socketPath = spec.slice(tcpToUnix + 1);
|
|
329
|
+
const innerColon = listenPart.lastIndexOf(":");
|
|
330
|
+
if (innerColon === -1) {
|
|
331
|
+
return {
|
|
332
|
+
rawSpec: spec,
|
|
333
|
+
listenAddr: "0.0.0.0",
|
|
334
|
+
listenPort: parsePort(listenPart, spec),
|
|
335
|
+
remoteUnixPath: socketPath
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
return {
|
|
339
|
+
rawSpec: spec,
|
|
340
|
+
listenAddr: listenPart.slice(0, innerColon),
|
|
341
|
+
listenPort: parsePort(listenPart.slice(innerColon + 1), spec),
|
|
342
|
+
remoteUnixPath: socketPath
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
const parts = spec.split(":");
|
|
346
|
+
switch (parts.length) {
|
|
347
|
+
case 2:
|
|
348
|
+
return {
|
|
349
|
+
rawSpec: spec,
|
|
350
|
+
listenAddr: parts[0],
|
|
351
|
+
listenPort: parsePort(parts[1], spec),
|
|
352
|
+
remoteHost: parts[0],
|
|
353
|
+
remotePort: parsePort(parts[1], spec)
|
|
354
|
+
};
|
|
355
|
+
case 3:
|
|
356
|
+
return {
|
|
357
|
+
rawSpec: spec,
|
|
358
|
+
listenAddr: parts[1],
|
|
359
|
+
listenPort: parsePort(parts[0], spec),
|
|
360
|
+
remoteHost: parts[1],
|
|
361
|
+
remotePort: parsePort(parts[2], spec)
|
|
362
|
+
};
|
|
363
|
+
case 4:
|
|
364
|
+
return {
|
|
365
|
+
rawSpec: spec,
|
|
366
|
+
listenAddr: parts[0],
|
|
367
|
+
listenPort: parsePort(parts[1], spec),
|
|
368
|
+
remoteHost: parts[2],
|
|
369
|
+
remotePort: parsePort(parts[3], spec)
|
|
370
|
+
};
|
|
371
|
+
default:
|
|
372
|
+
throw new Error(`invalid forward spec ${JSON.stringify(spec)}: expected 2-4 colon-separated parts`);
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
function parsePort(s, spec) {
|
|
376
|
+
const n = Number(s);
|
|
377
|
+
if (!Number.isInteger(n) || n < 0 || n > 65535) {
|
|
378
|
+
throw new Error(`invalid port ${JSON.stringify(s)} in forward spec ${JSON.stringify(spec)}`);
|
|
379
|
+
}
|
|
380
|
+
return n;
|
|
381
|
+
}
|
|
382
|
+
function isListenUnix(m) {
|
|
383
|
+
return m.listenUnixPath !== void 0;
|
|
384
|
+
}
|
|
385
|
+
function remoteTargetHeader(m) {
|
|
386
|
+
if (m.remoteUnixPath) return `unix:${m.remoteUnixPath}`;
|
|
387
|
+
return `${m.remoteHost}:${m.remotePort}`;
|
|
388
|
+
}
|
|
389
|
+
function listenAddressDescription(m) {
|
|
390
|
+
if (isListenUnix(m)) return m.listenUnixPath;
|
|
391
|
+
return `${m.listenAddr}:${m.listenPort}`;
|
|
392
|
+
}
|
|
393
|
+
var Forwarder = class _Forwarder {
|
|
394
|
+
constructor(init, mappings) {
|
|
395
|
+
this.init = init;
|
|
396
|
+
this.mappings = mappings;
|
|
397
|
+
}
|
|
398
|
+
init;
|
|
399
|
+
mappings;
|
|
400
|
+
listeners = [];
|
|
401
|
+
servers = [];
|
|
402
|
+
liveSockets = /* @__PURE__ */ new Set();
|
|
403
|
+
closed = false;
|
|
404
|
+
static async start(init) {
|
|
405
|
+
if (init.specs.length === 0) {
|
|
406
|
+
throw new Error("Forwarder requires at least one forward spec");
|
|
407
|
+
}
|
|
408
|
+
const mappings = init.specs.map(parseAddressMapping);
|
|
409
|
+
const fwd = new _Forwarder(init, mappings);
|
|
410
|
+
try {
|
|
411
|
+
await fwd.bindAll();
|
|
412
|
+
} catch (err) {
|
|
413
|
+
await fwd.close();
|
|
414
|
+
throw err;
|
|
415
|
+
}
|
|
416
|
+
return fwd;
|
|
417
|
+
}
|
|
418
|
+
async bindAll() {
|
|
419
|
+
for (const m of this.mappings) {
|
|
420
|
+
const server = net.createServer((socket) => this.handleAccept(m, socket));
|
|
421
|
+
const { local, port } = await listen(server, m);
|
|
422
|
+
this.servers.push(server);
|
|
423
|
+
this.listeners.push({
|
|
424
|
+
spec: m.rawSpec,
|
|
425
|
+
local,
|
|
426
|
+
remote: remoteTargetHeader(m),
|
|
427
|
+
...port !== void 0 && { port }
|
|
428
|
+
});
|
|
429
|
+
this.log(`listen ${local} \u2192 ${remoteTargetHeader(m)}`);
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
handleAccept(mapping, socket) {
|
|
433
|
+
if (this.closed) {
|
|
434
|
+
socket.destroy();
|
|
435
|
+
return;
|
|
436
|
+
}
|
|
437
|
+
socket.on("error", () => {
|
|
438
|
+
});
|
|
439
|
+
const ws$1 = openWebSocket(this.init, mapping);
|
|
440
|
+
let closed = false;
|
|
441
|
+
const cleanup = () => {
|
|
442
|
+
if (closed) return;
|
|
443
|
+
closed = true;
|
|
444
|
+
try {
|
|
445
|
+
socket.destroy();
|
|
446
|
+
} catch {
|
|
447
|
+
}
|
|
448
|
+
try {
|
|
449
|
+
ws$1.close();
|
|
450
|
+
} catch {
|
|
451
|
+
}
|
|
452
|
+
this.liveSockets.delete(handle);
|
|
453
|
+
};
|
|
454
|
+
const handle = { close: cleanup };
|
|
455
|
+
this.liveSockets.add(handle);
|
|
456
|
+
ws$1.binaryType = "nodebuffer";
|
|
457
|
+
ws$1.on("open", () => {
|
|
458
|
+
const wsStream = ws.createWebSocketStream(ws$1);
|
|
459
|
+
wsStream.on("error", cleanup);
|
|
460
|
+
socket.pipe(wsStream);
|
|
461
|
+
wsStream.pipe(socket);
|
|
462
|
+
});
|
|
463
|
+
ws$1.on("close", cleanup);
|
|
464
|
+
ws$1.on("error", (err) => {
|
|
465
|
+
this.log(`tunnel error: ${err.message}`);
|
|
466
|
+
cleanup();
|
|
467
|
+
});
|
|
468
|
+
socket.on("close", cleanup);
|
|
469
|
+
}
|
|
470
|
+
/** Tear down all listeners and any in-flight tunnel sockets. */
|
|
471
|
+
async close() {
|
|
472
|
+
this.closed = true;
|
|
473
|
+
for (const handle of [...this.liveSockets]) handle.close();
|
|
474
|
+
this.liveSockets.clear();
|
|
475
|
+
await Promise.all(
|
|
476
|
+
this.servers.map(
|
|
477
|
+
(s) => new Promise((resolve) => {
|
|
478
|
+
s.close(() => resolve());
|
|
479
|
+
})
|
|
480
|
+
)
|
|
481
|
+
);
|
|
482
|
+
for (const m of this.mappings) {
|
|
483
|
+
if (isListenUnix(m) && m.listenUnixPath) {
|
|
484
|
+
try {
|
|
485
|
+
fs__default.default.rmSync(m.listenUnixPath, { force: true });
|
|
486
|
+
} catch {
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
log(msg) {
|
|
492
|
+
this.init.options?.log?.(msg);
|
|
493
|
+
}
|
|
494
|
+
};
|
|
495
|
+
function listen(server, mapping) {
|
|
496
|
+
return new Promise((resolve, reject) => {
|
|
497
|
+
server.once("error", reject);
|
|
498
|
+
if (isListenUnix(mapping)) {
|
|
499
|
+
const p = mapping.listenUnixPath;
|
|
500
|
+
try {
|
|
501
|
+
fs__default.default.rmSync(p, { force: true });
|
|
502
|
+
} catch {
|
|
503
|
+
}
|
|
504
|
+
server.listen(p, () => {
|
|
505
|
+
try {
|
|
506
|
+
fs__default.default.chmodSync(p, 432);
|
|
507
|
+
} catch {
|
|
508
|
+
}
|
|
509
|
+
resolve({ local: p });
|
|
510
|
+
});
|
|
511
|
+
return;
|
|
512
|
+
}
|
|
513
|
+
server.listen({ host: mapping.listenAddr, port: mapping.listenPort }, () => {
|
|
514
|
+
const addr = server.address();
|
|
515
|
+
if (addr && typeof addr === "object") {
|
|
516
|
+
const local = `${mapping.listenAddr}:${addr.port}`;
|
|
517
|
+
resolve({ local, port: addr.port });
|
|
518
|
+
} else {
|
|
519
|
+
resolve({ local: listenAddressDescription(mapping) });
|
|
520
|
+
}
|
|
521
|
+
});
|
|
522
|
+
});
|
|
523
|
+
}
|
|
524
|
+
function openWebSocket(init, mapping) {
|
|
525
|
+
const url = wsURLForVM(init.transport, init.hostname);
|
|
526
|
+
const headers = {
|
|
527
|
+
"X-Inlets-Client-ID": init.options?.clientId ?? os__default.default.hostname(),
|
|
528
|
+
"X-Inlets-Mode": "local",
|
|
529
|
+
"X-Inlets-Upstream": remoteTargetHeader(mapping),
|
|
530
|
+
"User-Agent": init.userAgent
|
|
531
|
+
};
|
|
532
|
+
if (init.token) headers["Authorization"] = `Bearer ${init.token}`;
|
|
533
|
+
const opts = {
|
|
534
|
+
headers,
|
|
535
|
+
handshakeTimeout: init.options?.dialTimeoutMs ?? 1e4
|
|
536
|
+
};
|
|
537
|
+
if (init.transport.kind === "socket") {
|
|
538
|
+
opts.agent = unixAgent(init.transport.socketPath);
|
|
539
|
+
}
|
|
540
|
+
return new ws.WebSocket(url, opts);
|
|
541
|
+
}
|
|
542
|
+
function wsURLForVM(transport, hostname) {
|
|
543
|
+
if (transport.kind === "socket") {
|
|
544
|
+
return `ws://localhost/vm/${encodeURIComponent(hostname)}/forward`;
|
|
545
|
+
}
|
|
546
|
+
const u = transport.url;
|
|
547
|
+
const scheme = u.protocol === "https:" ? "wss" : "ws";
|
|
548
|
+
const port = u.port ? `:${u.port}` : "";
|
|
549
|
+
return `${scheme}://${u.hostname}${port}/vm/${encodeURIComponent(hostname)}/forward`;
|
|
550
|
+
}
|
|
551
|
+
function unixAgent(socketPath) {
|
|
552
|
+
const agent = new http__default.default.Agent({ keepAlive: false });
|
|
553
|
+
agent.createConnection = ((_opts, cb) => {
|
|
554
|
+
const conn = net__default.default.createConnection({ path: socketPath });
|
|
555
|
+
if (cb) {
|
|
556
|
+
conn.once("connect", () => cb(null, conn));
|
|
557
|
+
conn.once("error", (err) => cb(err));
|
|
558
|
+
}
|
|
559
|
+
return conn;
|
|
560
|
+
});
|
|
561
|
+
return agent;
|
|
562
|
+
}
|
|
306
563
|
|
|
307
564
|
// src/vm.ts
|
|
308
565
|
var VMFileSystem = class {
|
|
@@ -312,16 +569,16 @@ var VMFileSystem = class {
|
|
|
312
569
|
}
|
|
313
570
|
transport;
|
|
314
571
|
hostname;
|
|
315
|
-
async readDir(
|
|
316
|
-
const q = new URLSearchParams({ path:
|
|
572
|
+
async readDir(path3) {
|
|
573
|
+
const q = new URLSearchParams({ path: path3 });
|
|
317
574
|
const wire = await this.transport.request(
|
|
318
575
|
"GET",
|
|
319
576
|
`/vm/${encodeURIComponent(this.hostname)}/fs/readdir?${q.toString()}`
|
|
320
577
|
);
|
|
321
578
|
return (wire ?? []).map(fsEntryFromWire);
|
|
322
579
|
}
|
|
323
|
-
async stat(
|
|
324
|
-
const q = new URLSearchParams({ path:
|
|
580
|
+
async stat(path3) {
|
|
581
|
+
const q = new URLSearchParams({ path: path3 });
|
|
325
582
|
try {
|
|
326
583
|
const wire = await this.transport.request(
|
|
327
584
|
"GET",
|
|
@@ -333,8 +590,8 @@ var VMFileSystem = class {
|
|
|
333
590
|
throw err;
|
|
334
591
|
}
|
|
335
592
|
}
|
|
336
|
-
async exists(
|
|
337
|
-
return await this.stat(
|
|
593
|
+
async exists(path3) {
|
|
594
|
+
return await this.stat(path3) !== null;
|
|
338
595
|
}
|
|
339
596
|
async mkdir(req) {
|
|
340
597
|
await this.transport.request(
|
|
@@ -347,22 +604,22 @@ var VMFileSystem = class {
|
|
|
347
604
|
}
|
|
348
605
|
);
|
|
349
606
|
}
|
|
350
|
-
async remove(
|
|
351
|
-
const q = new URLSearchParams({ path:
|
|
607
|
+
async remove(path3, recursive = false) {
|
|
608
|
+
const q = new URLSearchParams({ path: path3, recursive: String(recursive) });
|
|
352
609
|
await this.transport.request(
|
|
353
610
|
"DELETE",
|
|
354
611
|
`/vm/${encodeURIComponent(this.hostname)}/fs/remove?${q.toString()}`
|
|
355
612
|
);
|
|
356
613
|
}
|
|
357
|
-
async readFile(
|
|
358
|
-
const q = new URLSearchParams({ path:
|
|
614
|
+
async readFile(path3) {
|
|
615
|
+
const q = new URLSearchParams({ path: path3, mode: "binary" });
|
|
359
616
|
return this.transport.requestRaw(
|
|
360
617
|
"GET",
|
|
361
618
|
`/vm/${encodeURIComponent(this.hostname)}/cp?${q.toString()}`
|
|
362
619
|
);
|
|
363
620
|
}
|
|
364
|
-
async writeFile(
|
|
365
|
-
const q = new URLSearchParams({ path:
|
|
621
|
+
async writeFile(path3, content, opts = {}) {
|
|
622
|
+
const q = new URLSearchParams({ path: path3, mode: "binary" });
|
|
366
623
|
if (opts.uid !== void 0) q.set("uid", String(opts.uid));
|
|
367
624
|
if (opts.gid !== void 0) q.set("gid", String(opts.gid));
|
|
368
625
|
if (opts.permissions) q.set("permissions", opts.permissions);
|
|
@@ -374,8 +631,8 @@ var VMFileSystem = class {
|
|
|
374
631
|
);
|
|
375
632
|
}
|
|
376
633
|
/** Upload a tar archive, expanded into the VM at `path`. */
|
|
377
|
-
async tarTo(
|
|
378
|
-
const q = new URLSearchParams({ path:
|
|
634
|
+
async tarTo(path3, tar) {
|
|
635
|
+
const q = new URLSearchParams({ path: path3, mode: "tar" });
|
|
379
636
|
if (tar instanceof Buffer) {
|
|
380
637
|
await this.transport.requestRaw(
|
|
381
638
|
"POST",
|
|
@@ -394,8 +651,8 @@ var VMFileSystem = class {
|
|
|
394
651
|
for await (const _ of res) void _;
|
|
395
652
|
}
|
|
396
653
|
/** Download `path` from the VM as a tar archive. */
|
|
397
|
-
async tarFrom(
|
|
398
|
-
const q = new URLSearchParams({ path:
|
|
654
|
+
async tarFrom(path3) {
|
|
655
|
+
const q = new URLSearchParams({ path: path3, mode: "tar" });
|
|
399
656
|
return this.transport.requestRaw(
|
|
400
657
|
"GET",
|
|
401
658
|
`/vm/${encodeURIComponent(this.hostname)}/cp?${q.toString()}`
|
|
@@ -500,6 +757,30 @@ var VM = class {
|
|
|
500
757
|
async restore() {
|
|
501
758
|
await this.transport.request("POST", `/vm/${encodeURIComponent(this.hostname)}/restore`);
|
|
502
759
|
}
|
|
760
|
+
// --- port forwarding ---------------------------------------------------
|
|
761
|
+
/**
|
|
762
|
+
* Open one or more port forwards from the host to this VM. Each spec follows
|
|
763
|
+
* the same syntax as `slicer vm forward -L`:
|
|
764
|
+
*
|
|
765
|
+
* `127.0.0.1:9000` — listen and forward on the same TCP port
|
|
766
|
+
* `8081:127.0.0.1:8080` — listen on `0.0.0.0:8081`, forward to `127.0.0.1:8080`
|
|
767
|
+
* `0.0.0.0:8080:127.0.0.1:8080` — fully explicit
|
|
768
|
+
* `9000:/var/run/docker.sock` — TCP listen, Unix socket forward
|
|
769
|
+
* `/tmp/docker.sock:/var/run/docker.sock` — Unix-to-Unix
|
|
770
|
+
*
|
|
771
|
+
* Returns a {@link Forwarder} handle. Call `forwarder.close()` to tear down
|
|
772
|
+
* all listeners and any in-flight tunnel sockets.
|
|
773
|
+
*/
|
|
774
|
+
async forward(specs, options) {
|
|
775
|
+
return Forwarder.start({
|
|
776
|
+
hostname: this.hostname,
|
|
777
|
+
transport: this.transport.transport,
|
|
778
|
+
...this.transport.token !== void 0 && { token: this.transport.token },
|
|
779
|
+
userAgent: this.transport.userAgent,
|
|
780
|
+
specs: typeof specs === "string" ? [specs] : specs,
|
|
781
|
+
...options !== void 0 && { options }
|
|
782
|
+
});
|
|
783
|
+
}
|
|
503
784
|
// --- exec -------------------------------------------------------------
|
|
504
785
|
/**
|
|
505
786
|
* Streaming exec — yields NDJSON frames (`started`, `stdout`, `stderr`, `exit`).
|
|
@@ -508,8 +789,8 @@ var VM = class {
|
|
|
508
789
|
* `dataBytes`/`stdoutBytes`/`stderrBytes` Buffers alongside for convenience.
|
|
509
790
|
*/
|
|
510
791
|
async *exec(req) {
|
|
511
|
-
const { path:
|
|
512
|
-
for await (const frame of this.transport.requestNDJSON("POST",
|
|
792
|
+
const { path: path3, body } = buildExecPath(this.hostname, req, false);
|
|
793
|
+
for await (const frame of this.transport.requestNDJSON("POST", path3, body)) {
|
|
513
794
|
if (frame.encoding === "base64") {
|
|
514
795
|
if (frame.data) frame.dataBytes = Buffer.from(frame.data, "base64");
|
|
515
796
|
if (frame.stdout) frame.stdoutBytes = Buffer.from(frame.stdout, "base64");
|
|
@@ -522,8 +803,8 @@ var VM = class {
|
|
|
522
803
|
if (req.stdin !== void 0) {
|
|
523
804
|
throw new Error("stdin is not supported by execBuffered; use exec() instead");
|
|
524
805
|
}
|
|
525
|
-
const { path:
|
|
526
|
-
const raw = await this.transport.requestRaw("POST",
|
|
806
|
+
const { path: path3, body } = buildExecPath(this.hostname, req, true);
|
|
807
|
+
const raw = await this.transport.requestRaw("POST", path3, body);
|
|
527
808
|
const text = raw.toString("utf8");
|
|
528
809
|
const parsed = text ? JSON.parse(text) : {};
|
|
529
810
|
const common = {
|
|
@@ -749,6 +1030,7 @@ var SlicerClient = class _SlicerClient {
|
|
|
749
1030
|
|
|
750
1031
|
exports.ExecStdioBase64 = ExecStdioBase64;
|
|
751
1032
|
exports.ExecStdioText = ExecStdioText;
|
|
1033
|
+
exports.Forwarder = Forwarder;
|
|
752
1034
|
exports.GiB = GiB;
|
|
753
1035
|
exports.HostGroupsAPI = HostGroupsAPI;
|
|
754
1036
|
exports.MiB = MiB;
|
|
@@ -760,6 +1042,7 @@ exports.SlicerClient = SlicerClient;
|
|
|
760
1042
|
exports.VM = VM;
|
|
761
1043
|
exports.VMFileSystem = VMFileSystem;
|
|
762
1044
|
exports.VMsAPI = VMsAPI;
|
|
1045
|
+
exports.parseAddressMapping = parseAddressMapping;
|
|
763
1046
|
exports.resolveTransport = resolveTransport;
|
|
764
1047
|
//# sourceMappingURL=index.cjs.map
|
|
765
1048
|
//# sourceMappingURL=index.cjs.map
|