sandboxedjs 0.1.99 → 0.1.100

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 CHANGED
@@ -20959,7 +20959,7 @@ var wheels_default = {
20959
20959
 
20960
20960
  // package.json
20961
20961
  var package_default = {
20962
- version: "0.1.99"};
20962
+ version: "0.1.100"};
20963
20963
 
20964
20964
  // src/python/extension-abi.ts
20965
20965
  var EXTENSION_ABI = {
@@ -38746,7 +38746,17 @@ async function createPreview(box, options = {}) {
38746
38746
  channel = new MessageChannel();
38747
38747
  serveContainerOn(channel.port1, box);
38748
38748
  const target = registration.active ?? worker;
38749
- target.postMessage({ type: "sandboxedjs:connect", injectSockets: options.websocket !== false }, [channel.port2]);
38749
+ target.postMessage(
38750
+ {
38751
+ type: "sandboxedjs:connect",
38752
+ injectSockets: options.websocket !== false,
38753
+ /* Sent with the channel, like `injectSockets`, because the worker is
38754
+ * restarted at the browser's convenience and remembers nothing: every
38755
+ * connect has to carry the settings again. */
38756
+ ...options.timeoutMs === void 0 ? {} : { timeoutMs: options.timeoutMs }
38757
+ },
38758
+ [channel.port2]
38759
+ );
38750
38760
  };
38751
38761
  const onWorkerMessage = (event) => {
38752
38762
  const type = event.data?.type;
package/dist/index.d.cts CHANGED
@@ -1678,6 +1678,16 @@ interface PreviewOptions {
1678
1678
  * re-optimizing dependencies; {@link onStale} is the fallback for that.
1679
1679
  */
1680
1680
  websocket?: boolean;
1681
+ /**
1682
+ * How long a previewed request may take before the worker reports a timeout.
1683
+ *
1684
+ * Defaults to five minutes. Responses cross this bridge whole rather than
1685
+ * streamed, so this covers the *entire* answer: a model generating tokens, a
1686
+ * server-sent-event endpoint running to its last event, a cold build. Raise
1687
+ * it for work that legitimately takes longer; lower it when a preview should
1688
+ * fail fast.
1689
+ */
1690
+ timeoutMs?: number;
1681
1691
  }
1682
1692
  interface Preview {
1683
1693
  /** The URL an iframe should be pointed at to see `port`. */
package/dist/index.d.ts CHANGED
@@ -1678,6 +1678,16 @@ interface PreviewOptions {
1678
1678
  * re-optimizing dependencies; {@link onStale} is the fallback for that.
1679
1679
  */
1680
1680
  websocket?: boolean;
1681
+ /**
1682
+ * How long a previewed request may take before the worker reports a timeout.
1683
+ *
1684
+ * Defaults to five minutes. Responses cross this bridge whole rather than
1685
+ * streamed, so this covers the *entire* answer: a model generating tokens, a
1686
+ * server-sent-event endpoint running to its last event, a cold build. Raise
1687
+ * it for work that legitimately takes longer; lower it when a preview should
1688
+ * fail fast.
1689
+ */
1690
+ timeoutMs?: number;
1681
1691
  }
1682
1692
  interface Preview {
1683
1693
  /** The URL an iframe should be pointed at to see `port`. */
package/dist/index.js CHANGED
@@ -20942,7 +20942,7 @@ var wheels_default = {
20942
20942
 
20943
20943
  // package.json
20944
20944
  var package_default = {
20945
- version: "0.1.99"};
20945
+ version: "0.1.100"};
20946
20946
 
20947
20947
  // src/python/extension-abi.ts
20948
20948
  var EXTENSION_ABI = {
@@ -38729,7 +38729,17 @@ async function createPreview(box, options = {}) {
38729
38729
  channel = new MessageChannel();
38730
38730
  serveContainerOn(channel.port1, box);
38731
38731
  const target = registration.active ?? worker;
38732
- target.postMessage({ type: "sandboxedjs:connect", injectSockets: options.websocket !== false }, [channel.port2]);
38732
+ target.postMessage(
38733
+ {
38734
+ type: "sandboxedjs:connect",
38735
+ injectSockets: options.websocket !== false,
38736
+ /* Sent with the channel, like `injectSockets`, because the worker is
38737
+ * restarted at the browser's convenience and remembers nothing: every
38738
+ * connect has to carry the settings again. */
38739
+ ...options.timeoutMs === void 0 ? {} : { timeoutMs: options.timeoutMs }
38740
+ },
38741
+ [channel.port2]
38742
+ );
38733
38743
  };
38734
38744
  const onWorkerMessage = (event) => {
38735
38745
  const type = event.data?.type;
@@ -365,6 +365,7 @@ function containerTarget(value) {
365
365
  }
366
366
  var OUTDATED = /outdated optimize dep/i;
367
367
  var NOT_CONNECTED = 503;
368
+ var DEFAULT_TIMEOUT_MS = 5 * 6e4;
368
369
  var PreviewRouter = class {
369
370
  constructor(options2) {
370
371
  this.options = options2;
@@ -447,16 +448,15 @@ var PreviewRouter = class {
447
448
  { id, port, path, method: request.method, headers: headerRecord(request.headers), ...sent ? { body: sent } : {} },
448
449
  sent ? [sent] : []
449
450
  );
450
- const timeoutMs = this.options.timeoutMs ?? 3e4;
451
+ const timeoutMs = this.options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
452
+ let timer;
451
453
  const result = await Promise.race([
452
454
  answered,
453
- new Promise(
454
- (resolve) => setTimeout(
455
- () => resolve({ status: 504, statusText: "Gateway Timeout", headers: {}, body: new ArrayBuffer(0) }),
456
- timeoutMs
457
- )
458
- )
455
+ new Promise((resolve) => {
456
+ timer = setTimeout(() => resolve(timedOut(port, path, timeoutMs)), timeoutMs);
457
+ })
459
458
  ]);
459
+ clearTimeout(timer);
460
460
  this.pending.delete(id);
461
461
  if (result.status === 504 && OUTDATED.test(result.statusText)) {
462
462
  this.options.onStale?.(clientId);
@@ -468,6 +468,19 @@ var PreviewRouter = class {
468
468
  return new Response(body, { status: result.status, statusText: result.statusText, headers });
469
469
  }
470
470
  };
471
+ function timedOut(port, path, timeoutMs) {
472
+ const message = `The sandbox preview gave up waiting for ${path} on port ${port} after ${Math.round(timeoutMs / 1e3)}s.
473
+
474
+ The server inside the container has not finished this response. Preview responses are delivered whole rather than streamed, so a long one \u2014 a model's answer, a server-sent-event stream \u2014 is outstanding until it ends.
475
+
476
+ Raise createPreview(box, { timeoutMs }) if this work legitimately takes longer.`;
477
+ return {
478
+ status: 504,
479
+ statusText: "Gateway Timeout",
480
+ headers: { "content-type": "text/plain; charset=utf-8" },
481
+ body: new TextEncoder().encode(message).buffer
482
+ };
483
+ }
471
484
  function isolated(response) {
472
485
  const headers = new Headers(response.headers);
473
486
  headers.set("Content-Type", "text/plain; charset=utf-8");
@@ -553,6 +566,8 @@ worker.addEventListener("message", (event) => {
553
566
  host = event.ports[0] ?? null;
554
567
  if (!host) return;
555
568
  options.injectSockets = event.data.injectSockets !== false;
569
+ const timeoutMs = event.data.timeoutMs;
570
+ if (typeof timeoutMs === "number" && timeoutMs > 0) options.timeoutMs = timeoutMs;
556
571
  host.onmessage = (message) => {
557
572
  const reply = message.data;
558
573
  router.settle(reply.id, reply.response);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sandboxedjs",
3
- "version": "0.1.99",
3
+ "version": "0.1.100",
4
4
  "description": "A Linux-like container that runs entirely inside Node.js — POSIX shell, ~140 coreutils, Node.js and Python runtimes, virtual filesystem and networking. No Docker, no VM, no native modules.",
5
5
  "type": "module",
6
6
  "license": "MIT",