@slicervm/sdk 0.1.5 → 0.1.6
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/dist/index.cjs +150 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +67 -1
- package/dist/index.d.ts +67 -1
- package/dist/index.js +145 -5
- package/dist/index.js.map +1 -1
- package/dist/shell.cjs +152 -0
- package/dist/shell.cjs.map +1 -0
- package/dist/shell.d.cts +67 -0
- package/dist/shell.d.ts +67 -0
- package/dist/shell.js +143 -0
- package/dist/shell.js.map +1 -0
- package/package.json +11 -1
package/dist/index.cjs
CHANGED
|
@@ -976,8 +976,8 @@ var VMBg = class {
|
|
|
976
976
|
q.set("cmd", req.command);
|
|
977
977
|
for (const a of req.args ?? []) q.append("args", a);
|
|
978
978
|
for (const e of req.env ?? []) q.append("env", e);
|
|
979
|
-
if (req.uid !== void 0
|
|
980
|
-
if (req.gid !== void 0
|
|
979
|
+
if (req.uid !== void 0) q.set("uid", String(req.uid));
|
|
980
|
+
if (req.gid !== void 0) q.set("gid", String(req.gid));
|
|
981
981
|
if (req.shell) q.set("shell", req.shell);
|
|
982
982
|
if (req.cwd) q.set("cwd", req.cwd);
|
|
983
983
|
if (req.ringBytes !== void 0 && req.ringBytes > 0) {
|
|
@@ -1289,8 +1289,153 @@ var SlicerClient = class _SlicerClient {
|
|
|
1289
1289
|
}
|
|
1290
1290
|
};
|
|
1291
1291
|
|
|
1292
|
+
// src/shell.ts
|
|
1293
|
+
var FRAME_TYPE_DATA = 1;
|
|
1294
|
+
var FRAME_TYPE_WINDOW_SIZE = 2;
|
|
1295
|
+
var FRAME_TYPE_SHUTDOWN = 3;
|
|
1296
|
+
var FRAME_TYPE_HEARTBEAT = 4;
|
|
1297
|
+
var FRAME_TYPE_SESSION_CLOSE = 5;
|
|
1298
|
+
var HEADER_SIZE = 5;
|
|
1299
|
+
function encodeFrame(frameType, payload) {
|
|
1300
|
+
const payloadLen = payload ? payload.byteLength : 0;
|
|
1301
|
+
const buf = new Uint8Array(HEADER_SIZE + payloadLen);
|
|
1302
|
+
const view = new DataView(buf.buffer);
|
|
1303
|
+
view.setUint8(0, frameType);
|
|
1304
|
+
view.setUint32(1, payloadLen, false);
|
|
1305
|
+
if (payload) buf.set(payload, HEADER_SIZE);
|
|
1306
|
+
return buf;
|
|
1307
|
+
}
|
|
1308
|
+
function parseFrame(data) {
|
|
1309
|
+
if (data.byteLength < HEADER_SIZE) return null;
|
|
1310
|
+
const view = new DataView(data);
|
|
1311
|
+
const frameType = view.getUint8(0);
|
|
1312
|
+
const payloadLen = view.getUint32(1, false);
|
|
1313
|
+
if (data.byteLength < HEADER_SIZE + payloadLen) return null;
|
|
1314
|
+
const payload = new Uint8Array(data, HEADER_SIZE, payloadLen);
|
|
1315
|
+
return { frameType, payload };
|
|
1316
|
+
}
|
|
1317
|
+
var encoder = new TextEncoder();
|
|
1318
|
+
var decoder = new TextDecoder();
|
|
1319
|
+
var SlicerShellSession = class {
|
|
1320
|
+
constructor(terminal, options) {
|
|
1321
|
+
this.terminal = terminal;
|
|
1322
|
+
this.options = options;
|
|
1323
|
+
}
|
|
1324
|
+
terminal;
|
|
1325
|
+
options;
|
|
1326
|
+
ws = null;
|
|
1327
|
+
heartbeatTimer = null;
|
|
1328
|
+
dataDisposable = null;
|
|
1329
|
+
/** True when the WebSocket is open and relaying. */
|
|
1330
|
+
get connected() {
|
|
1331
|
+
return this.ws !== null && this.ws.readyState === WebSocket.OPEN;
|
|
1332
|
+
}
|
|
1333
|
+
/** Open the WebSocket and begin relaying. */
|
|
1334
|
+
connect() {
|
|
1335
|
+
if (this.ws) return;
|
|
1336
|
+
this.options.onStateChange?.("connecting");
|
|
1337
|
+
const ws = new WebSocket(this.options.url);
|
|
1338
|
+
ws.binaryType = "arraybuffer";
|
|
1339
|
+
this.ws = ws;
|
|
1340
|
+
ws.onopen = () => {
|
|
1341
|
+
this.options.onStateChange?.("connected");
|
|
1342
|
+
this.terminal.reset();
|
|
1343
|
+
this.sendResize(this.terminal.cols, this.terminal.rows);
|
|
1344
|
+
this.startHeartbeat();
|
|
1345
|
+
};
|
|
1346
|
+
ws.onmessage = (ev) => {
|
|
1347
|
+
if (!(ev.data instanceof ArrayBuffer)) return;
|
|
1348
|
+
const frame = parseFrame(ev.data);
|
|
1349
|
+
if (!frame) return;
|
|
1350
|
+
switch (frame.frameType) {
|
|
1351
|
+
case FRAME_TYPE_DATA:
|
|
1352
|
+
this.terminal.write(decoder.decode(frame.payload));
|
|
1353
|
+
break;
|
|
1354
|
+
case FRAME_TYPE_SHUTDOWN:
|
|
1355
|
+
case FRAME_TYPE_SESSION_CLOSE:
|
|
1356
|
+
this.teardown();
|
|
1357
|
+
break;
|
|
1358
|
+
}
|
|
1359
|
+
};
|
|
1360
|
+
ws.onclose = () => {
|
|
1361
|
+
this.teardown();
|
|
1362
|
+
};
|
|
1363
|
+
ws.onerror = () => {
|
|
1364
|
+
this.options.onError?.("WebSocket error");
|
|
1365
|
+
this.teardown();
|
|
1366
|
+
};
|
|
1367
|
+
this.dataDisposable = this.terminal.onData((data) => {
|
|
1368
|
+
if (!this.connected) return;
|
|
1369
|
+
const payload = encoder.encode(data);
|
|
1370
|
+
this.ws.send(encodeFrame(FRAME_TYPE_DATA, payload));
|
|
1371
|
+
});
|
|
1372
|
+
}
|
|
1373
|
+
/** Send a graceful shutdown frame and close. */
|
|
1374
|
+
disconnect() {
|
|
1375
|
+
if (this.ws) {
|
|
1376
|
+
try {
|
|
1377
|
+
this.ws.send(encodeFrame(FRAME_TYPE_SHUTDOWN));
|
|
1378
|
+
} catch {
|
|
1379
|
+
}
|
|
1380
|
+
}
|
|
1381
|
+
this.teardown();
|
|
1382
|
+
}
|
|
1383
|
+
/** Send a window resize. Call this from FitAddon's onResize or a ResizeObserver. */
|
|
1384
|
+
resize(cols, rows) {
|
|
1385
|
+
if (!this.connected) return;
|
|
1386
|
+
this.sendResize(cols, rows);
|
|
1387
|
+
}
|
|
1388
|
+
// --- internals -------------------------------------------------------------
|
|
1389
|
+
sendResize(cols, rows) {
|
|
1390
|
+
const payload = new Uint8Array(8);
|
|
1391
|
+
const view = new DataView(payload.buffer);
|
|
1392
|
+
view.setUint32(0, cols, false);
|
|
1393
|
+
view.setUint32(4, rows, false);
|
|
1394
|
+
this.ws.send(encodeFrame(FRAME_TYPE_WINDOW_SIZE, payload));
|
|
1395
|
+
}
|
|
1396
|
+
startHeartbeat() {
|
|
1397
|
+
this.stopHeartbeat();
|
|
1398
|
+
const intervalMs = this.options.heartbeatIntervalMs ?? 3e4;
|
|
1399
|
+
this.heartbeatTimer = setInterval(() => {
|
|
1400
|
+
if (!this.connected) return;
|
|
1401
|
+
this.ws.send(encodeFrame(FRAME_TYPE_HEARTBEAT));
|
|
1402
|
+
}, intervalMs);
|
|
1403
|
+
}
|
|
1404
|
+
stopHeartbeat() {
|
|
1405
|
+
if (this.heartbeatTimer !== null) {
|
|
1406
|
+
clearInterval(this.heartbeatTimer);
|
|
1407
|
+
this.heartbeatTimer = null;
|
|
1408
|
+
}
|
|
1409
|
+
}
|
|
1410
|
+
teardown() {
|
|
1411
|
+
this.stopHeartbeat();
|
|
1412
|
+
if (this.dataDisposable) {
|
|
1413
|
+
this.dataDisposable.dispose();
|
|
1414
|
+
this.dataDisposable = null;
|
|
1415
|
+
}
|
|
1416
|
+
if (this.ws) {
|
|
1417
|
+
const ws = this.ws;
|
|
1418
|
+
this.ws = null;
|
|
1419
|
+
ws.onopen = null;
|
|
1420
|
+
ws.onmessage = null;
|
|
1421
|
+
ws.onclose = null;
|
|
1422
|
+
ws.onerror = null;
|
|
1423
|
+
try {
|
|
1424
|
+
ws.close();
|
|
1425
|
+
} catch {
|
|
1426
|
+
}
|
|
1427
|
+
}
|
|
1428
|
+
this.options.onStateChange?.("disconnected");
|
|
1429
|
+
}
|
|
1430
|
+
};
|
|
1431
|
+
|
|
1292
1432
|
exports.ExecStdioBase64 = ExecStdioBase64;
|
|
1293
1433
|
exports.ExecStdioText = ExecStdioText;
|
|
1434
|
+
exports.FRAME_TYPE_DATA = FRAME_TYPE_DATA;
|
|
1435
|
+
exports.FRAME_TYPE_HEARTBEAT = FRAME_TYPE_HEARTBEAT;
|
|
1436
|
+
exports.FRAME_TYPE_SESSION_CLOSE = FRAME_TYPE_SESSION_CLOSE;
|
|
1437
|
+
exports.FRAME_TYPE_SHUTDOWN = FRAME_TYPE_SHUTDOWN;
|
|
1438
|
+
exports.FRAME_TYPE_WINDOW_SIZE = FRAME_TYPE_WINDOW_SIZE;
|
|
1294
1439
|
exports.Forwarder = Forwarder;
|
|
1295
1440
|
exports.GiB = GiB;
|
|
1296
1441
|
exports.HostGroupsAPI = HostGroupsAPI;
|
|
@@ -1300,11 +1445,14 @@ exports.SecretExistsError = SecretExistsError;
|
|
|
1300
1445
|
exports.SecretsAPI = SecretsAPI;
|
|
1301
1446
|
exports.SlicerAPIError = SlicerAPIError;
|
|
1302
1447
|
exports.SlicerClient = SlicerClient;
|
|
1448
|
+
exports.SlicerShellSession = SlicerShellSession;
|
|
1303
1449
|
exports.VM = VM;
|
|
1304
1450
|
exports.VMBg = VMBg;
|
|
1305
1451
|
exports.VMFileSystem = VMFileSystem;
|
|
1306
1452
|
exports.VMsAPI = VMsAPI;
|
|
1453
|
+
exports.encodeFrame = encodeFrame;
|
|
1307
1454
|
exports.parseAddressMapping = parseAddressMapping;
|
|
1455
|
+
exports.parseFrame = parseFrame;
|
|
1308
1456
|
exports.resolveTransport = resolveTransport;
|
|
1309
1457
|
//# sourceMappingURL=index.cjs.map
|
|
1310
1458
|
//# sourceMappingURL=index.cjs.map
|