@cloudflare/sandbox 0.4.11 → 0.4.12

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.
@@ -458,10 +458,12 @@ declare class Sandbox<Env = unknown> extends Container<Env> implements ISandbox
458
458
  private defaultSession;
459
459
  envVars: Record<string, string>;
460
460
  private logger;
461
+ private keepAliveEnabled;
461
462
  constructor(ctx: DurableObject['ctx'], env: Env);
462
463
  setSandboxName(name: string): Promise<void>;
463
464
  setBaseUrl(baseUrl: string): Promise<void>;
464
465
  setSleepAfter(sleepAfter: string | number): Promise<void>;
466
+ setKeepAlive(keepAlive: boolean): Promise<void>;
465
467
  setEnvVars(envVars: Record<string, string>): Promise<void>;
466
468
  /**
467
469
  * Cleanup and destroy the sandbox container
@@ -475,6 +477,11 @@ declare class Sandbox<Env = unknown> extends Container<Env> implements ISandbox
475
477
  private checkVersionCompatibility;
476
478
  onStop(): void;
477
479
  onError(error: unknown): void;
480
+ /**
481
+ * Override onActivityExpired to prevent automatic shutdown when keepAlive is enabled
482
+ * When keepAlive is disabled, calls parent implementation which stops the container
483
+ */
484
+ onActivityExpired(): Promise<void>;
478
485
  fetch(request: Request): Promise<Response>;
479
486
  private determinePort;
480
487
  /**
@@ -516,6 +523,9 @@ declare class Sandbox<Env = unknown> extends Container<Env> implements ISandbox
516
523
  * Internal session-aware execStream implementation
517
524
  */
518
525
  private execStreamWithSession;
526
+ /**
527
+ * Stream logs from a background process as a ReadableStream.
528
+ */
519
529
  streamProcessLogs(processId: string, options?: {
520
530
  signal?: AbortSignal;
521
531
  }): Promise<ReadableStream<Uint8Array>>;
package/dist/sandbox.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  import '@repo/shared';
2
2
  import 'cloudflare:workers';
3
3
  import '@cloudflare/containers';
4
- export { b as Sandbox, g as getSandbox } from './sandbox-DWQVgVTY.js';
4
+ export { b as Sandbox, g as getSandbox } from './sandbox-CLZWpfGc.js';
package/dist/sandbox.js CHANGED
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  Sandbox,
3
3
  getSandbox
4
- } from "./chunk-SVWLTRHD.js";
4
+ } from "./chunk-YE265ASX.js";
5
5
  import "./chunk-JXZMAU2C.js";
6
6
  import "./chunk-Z532A7QC.js";
7
7
  import "./chunk-EKSWCBCA.js";
8
- import "./chunk-FE4PJSRB.js";
8
+ import "./chunk-UJ3TV4M6.js";
9
9
  export {
10
10
  Sandbox,
11
11
  getSandbox
package/dist/version.d.ts CHANGED
@@ -3,6 +3,6 @@
3
3
  * This file is auto-updated by .github/changeset-version.ts during releases
4
4
  * DO NOT EDIT MANUALLY - Changes will be overwritten on the next version bump
5
5
  */
6
- declare const SDK_VERSION = "0.4.11";
6
+ declare const SDK_VERSION = "0.4.12";
7
7
 
8
8
  export { SDK_VERSION };
package/dist/version.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  SDK_VERSION
3
- } from "./chunk-FE4PJSRB.js";
3
+ } from "./chunk-UJ3TV4M6.js";
4
4
  export {
5
5
  SDK_VERSION
6
6
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cloudflare/sandbox",
3
- "version": "0.4.11",
3
+ "version": "0.4.12",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/cloudflare/sandbox-sdk"
@@ -1,5 +1,5 @@
1
- import { createLogger, type LogContext, TraceContext } from "@repo/shared";
2
1
  import { switchPort } from "@cloudflare/containers";
2
+ import { createLogger, type LogContext, TraceContext } from "@repo/shared";
3
3
  import { getSandbox, type Sandbox } from "./sandbox";
4
4
  import {
5
5
  sanitizeSandboxId,
package/src/sandbox.ts CHANGED
@@ -49,6 +49,10 @@ export function getSandbox(
49
49
  stub.setSleepAfter(options.sleepAfter);
50
50
  }
51
51
 
52
+ if (options?.keepAlive !== undefined) {
53
+ stub.setKeepAlive(options.keepAlive);
54
+ }
55
+
52
56
  return stub;
53
57
  }
54
58
 
@@ -64,6 +68,7 @@ export class Sandbox<Env = unknown> extends Container<Env> implements ISandbox {
64
68
  private defaultSession: string | null = null;
65
69
  envVars: Record<string, string> = {};
66
70
  private logger: ReturnType<typeof createLogger>;
71
+ private keepAliveEnabled: boolean = false;
67
72
 
68
73
  constructor(ctx: DurableObject['ctx'], env: Env) {
69
74
  super(ctx, env);
@@ -131,6 +136,16 @@ export class Sandbox<Env = unknown> extends Container<Env> implements ISandbox {
131
136
  this.sleepAfter = sleepAfter;
132
137
  }
133
138
 
139
+ // RPC method to enable keepAlive mode
140
+ async setKeepAlive(keepAlive: boolean): Promise<void> {
141
+ this.keepAliveEnabled = keepAlive;
142
+ if (keepAlive) {
143
+ this.logger.info('KeepAlive mode enabled - container will stay alive until explicitly destroyed');
144
+ } else {
145
+ this.logger.info('KeepAlive mode disabled - container will timeout normally');
146
+ }
147
+ }
148
+
134
149
  // RPC method to set environment variables
135
150
  async setEnvVars(envVars: Record<string, string>): Promise<void> {
136
151
  // Update local state for new sessions
@@ -220,6 +235,22 @@ export class Sandbox<Env = unknown> extends Container<Env> implements ISandbox {
220
235
  this.logger.error('Sandbox error', error instanceof Error ? error : new Error(String(error)));
221
236
  }
222
237
 
238
+ /**
239
+ * Override onActivityExpired to prevent automatic shutdown when keepAlive is enabled
240
+ * When keepAlive is disabled, calls parent implementation which stops the container
241
+ */
242
+ override async onActivityExpired(): Promise<void> {
243
+ if (this.keepAliveEnabled) {
244
+ this.logger.debug('Activity expired but keepAlive is enabled - container will stay alive');
245
+ // Do nothing - don't call stop(), container stays alive
246
+ } else {
247
+ // Default behavior: stop the container
248
+ this.logger.debug('Activity expired - stopping container');
249
+ await super.onActivityExpired();
250
+ }
251
+ }
252
+
253
+
223
254
  // Override fetch to route internal container requests to appropriate ports
224
255
  override async fetch(request: Request): Promise<Response> {
225
256
  // Extract or generate trace ID from request
@@ -327,7 +358,6 @@ export class Sandbox<Env = unknown> extends Container<Env> implements ISandbox {
327
358
  const startTime = Date.now();
328
359
  const timestamp = new Date().toISOString();
329
360
 
330
- // Handle timeout
331
361
  let timeoutId: NodeJS.Timeout | undefined;
332
362
 
333
363
  try {
@@ -592,8 +622,7 @@ export class Sandbox<Env = unknown> extends Container<Env> implements ISandbox {
592
622
  };
593
623
  }
594
624
 
595
-
596
- // Streaming methods - return ReadableStream for RPC compatibility
625
+ // Streaming methods - return ReadableStream for RPC compatibility
597
626
  async execStream(command: string, options?: StreamOptions): Promise<ReadableStream<Uint8Array>> {
598
627
  // Check for cancellation
599
628
  if (options?.signal?.aborted) {
@@ -617,6 +646,9 @@ export class Sandbox<Env = unknown> extends Container<Env> implements ISandbox {
617
646
  return this.client.commands.executeStream(command, sessionId);
618
647
  }
619
648
 
649
+ /**
650
+ * Stream logs from a background process as a ReadableStream.
651
+ */
620
652
  async streamProcessLogs(processId: string, options?: { signal?: AbortSignal }): Promise<ReadableStream<Uint8Array>> {
621
653
  // Check for cancellation
622
654
  if (options?.signal?.aborted) {
package/src/version.ts CHANGED
@@ -3,4 +3,4 @@
3
3
  * This file is auto-updated by .github/changeset-version.ts during releases
4
4
  * DO NOT EDIT MANUALLY - Changes will be overwritten on the next version bump
5
5
  */
6
- export const SDK_VERSION = '0.4.11';
6
+ export const SDK_VERSION = '0.4.12';
@@ -30,6 +30,7 @@ describe('getSandbox', () => {
30
30
  setSleepAfter: vi.fn((value: string | number) => {
31
31
  mockStub.sleepAfter = value;
32
32
  }),
33
+ setKeepAlive: vi.fn(),
33
34
  };
34
35
 
35
36
  // Mock getContainer to return our stub
@@ -107,4 +108,42 @@ describe('getSandbox', () => {
107
108
  expect(sandbox.sleepAfter).toBe(timeString);
108
109
  }
109
110
  });
111
+
112
+ it('should apply keepAlive option when provided as true', () => {
113
+ const mockNamespace = {} as any;
114
+ const sandbox = getSandbox(mockNamespace, 'test-sandbox', {
115
+ keepAlive: true,
116
+ });
117
+
118
+ expect(sandbox.setKeepAlive).toHaveBeenCalledWith(true);
119
+ });
120
+
121
+ it('should apply keepAlive option when provided as false', () => {
122
+ const mockNamespace = {} as any;
123
+ const sandbox = getSandbox(mockNamespace, 'test-sandbox', {
124
+ keepAlive: false,
125
+ });
126
+
127
+ expect(sandbox.setKeepAlive).toHaveBeenCalledWith(false);
128
+ });
129
+
130
+ it('should not call setKeepAlive when keepAlive option not provided', () => {
131
+ const mockNamespace = {} as any;
132
+ getSandbox(mockNamespace, 'test-sandbox');
133
+
134
+ expect(mockStub.setKeepAlive).not.toHaveBeenCalled();
135
+ });
136
+
137
+ it('should apply keepAlive alongside other options', () => {
138
+ const mockNamespace = {} as any;
139
+ const sandbox = getSandbox(mockNamespace, 'test-sandbox', {
140
+ sleepAfter: '5m',
141
+ baseUrl: 'https://example.com',
142
+ keepAlive: true,
143
+ });
144
+
145
+ expect(sandbox.sleepAfter).toBe('5m');
146
+ expect(sandbox.setBaseUrl).toHaveBeenCalledWith('https://example.com');
147
+ expect(sandbox.setKeepAlive).toHaveBeenCalledWith(true);
148
+ });
110
149
  });
@@ -1,7 +1,7 @@
1
+ import { Container } from '@cloudflare/containers';
1
2
  import type { DurableObjectState } from '@cloudflare/workers-types';
2
3
  import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
3
4
  import { Sandbox } from '../src/sandbox';
4
- import { Container } from '@cloudflare/containers';
5
5
 
6
6
  // Mock dependencies before imports
7
7
  vi.mock('./interpreter', () => ({
@@ -48,7 +48,7 @@ describe('Sandbox - Automatic Session Management', () => {
48
48
  delete: vi.fn().mockResolvedValue(undefined),
49
49
  list: vi.fn().mockResolvedValue(new Map()),
50
50
  } as any,
51
- blockConcurrencyWhile: vi.fn((fn: () => Promise<void>) => fn()),
51
+ blockConcurrencyWhile: vi.fn().mockImplementation(<T>(callback: () => Promise<T>): Promise<T> => callback()),
52
52
  id: {
53
53
  toString: () => 'test-sandbox-id',
54
54
  equals: vi.fn(),
@@ -1,7 +0,0 @@
1
- // src/version.ts
2
- var SDK_VERSION = "0.4.11";
3
-
4
- export {
5
- SDK_VERSION
6
- };
7
- //# sourceMappingURL=chunk-FE4PJSRB.js.map