@cloudflare/sandbox 0.10.3 → 0.11.0

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.
@@ -1200,26 +1200,6 @@ interface SessionDeleteResult {
1200
1200
  sessionId: string;
1201
1201
  timestamp: string;
1202
1202
  }
1203
- interface PortExposeResult {
1204
- success: boolean;
1205
- port: number;
1206
- url: string;
1207
- timestamp: string;
1208
- }
1209
- interface PortListResult {
1210
- success: boolean;
1211
- ports: Array<{
1212
- port: number;
1213
- url: string;
1214
- status: 'active' | 'inactive';
1215
- }>;
1216
- timestamp: string;
1217
- }
1218
- interface PortCloseResult {
1219
- success: boolean;
1220
- port: number;
1221
- timestamp: string;
1222
- }
1223
1203
  interface ExecutionSession {
1224
1204
  /** Unique session identifier */
1225
1205
  readonly id: string;
@@ -1571,13 +1551,6 @@ interface StartProcessRequest {
1571
1551
  autoCleanup?: boolean;
1572
1552
  origin?: 'user' | 'internal';
1573
1553
  }
1574
- /**
1575
- * Request to expose a port
1576
- */
1577
- interface ExposePortRequest {
1578
- port: number;
1579
- name?: string;
1580
- }
1581
1554
  /**
1582
1555
  * Request to create a backup archive from a directory.
1583
1556
  * The container creates a squashfs archive at archivePath.
@@ -1715,9 +1688,6 @@ interface SandboxProcessesAPI {
1715
1688
  streamProcessLogs(id: string): Promise<ReadableStream<Uint8Array>>;
1716
1689
  }
1717
1690
  interface SandboxPortsAPI {
1718
- exposePort(port: number, sessionId: string, name?: string): Promise<PortExposeResult>;
1719
- getExposedPorts(sessionId: string): Promise<PortListResult>;
1720
- unexposePort(port: number, sessionId: string): Promise<PortCloseResult>;
1721
1691
  watchPort(request: PortWatchRequest): Promise<ReadableStream<Uint8Array>>;
1722
1692
  }
1723
1693
  interface SandboxGitAPI {
@@ -1837,26 +1807,61 @@ interface SandboxWatchAPI {
1837
1807
  checkChanges(request: CheckChangesRequest): Promise<CheckChangesResult>;
1838
1808
  }
1839
1809
  /**
1840
- * Public-facing tunnel record.
1841
- *
1842
- * Today only quick tunnels (`*.trycloudflare.com`) are supported. Future
1843
- * PRs will add named tunnels, which will carry a `name: string` field;
1844
- * `TunnelInfo` will then become a discriminated union keyed on the
1845
- * presence of `name`. The quick variant declares `name?: never` so the
1846
- * narrowing works without a breaking change here.
1810
+ * Public-facing tunnel record. Discriminated on the presence of `name`:
1811
+ * quick tunnels (`*.trycloudflare.com`) omit it, named tunnels carry the
1812
+ * label that was passed to `get(port, { name })`.
1847
1813
  */
1848
- interface TunnelInfo {
1814
+ type TunnelInfo = QuickTunnelInfo | NamedTunnelInfo;
1815
+ interface QuickTunnelInfo {
1849
1816
  id: string;
1850
1817
  port: number;
1818
+ /** `https://<random>.trycloudflare.com`. */
1851
1819
  url: string;
1820
+ /** Hostname portion of `url`. */
1852
1821
  hostname: string;
1853
1822
  createdAt: string;
1854
- /** Reserved for the named-tunnel variant in a future PR. */
1823
+ /** Absent on quick tunnels; narrows the union. */
1855
1824
  name?: never;
1856
1825
  }
1826
+ interface NamedTunnelInfo {
1827
+ /** Cloudflare tunnel UUID (8-4-4-4-12). */
1828
+ id: string;
1829
+ port: number;
1830
+ /** `https://<hostname>`. */
1831
+ url: string;
1832
+ /** Full hostname bound to the tunnel (without scheme). */
1833
+ hostname: string;
1834
+ createdAt: string;
1835
+ /** Label originally passed via `TunnelOptions.name`. */
1836
+ name: string;
1837
+ }
1838
+ /**
1839
+ * Options accepted by `sandbox.tunnels.get(port, options)`. Omitting
1840
+ * `name` (or omitting the options object) selects the zero-config quick
1841
+ * tunnel; setting `name` selects the named-tunnel flow.
1842
+ */
1843
+ interface TunnelOptions {
1844
+ /**
1845
+ * Single DNS label under the configured zone. The full hostname is
1846
+ * `<name>.<zone-name>`. See `validateTunnelName` for the format rules.
1847
+ */
1848
+ name?: string;
1849
+ }
1857
1850
  interface SandboxTunnelsAPI {
1858
1851
  /** Spawn `cloudflared tunnel --url`. No credentials required. */
1859
1852
  runQuickTunnel(id: string, port: number): Promise<TunnelInfo>;
1853
+ /**
1854
+ * Spawn `cloudflared tunnel run --token <token> --url http://localhost:<port>`.
1855
+ *
1856
+ * The SDK is the source of truth for the hostname this tunnel binds to;
1857
+ * the container only sees the opaque token and the local port. The
1858
+ * returned `TunnelInfo` carries empty `url`/`hostname` fields — the SDK
1859
+ * enriches them with the values from the Cloudflare API before handing
1860
+ * the record to user code.
1861
+ *
1862
+ * The token must never be logged, persisted, or echoed back to callers.
1863
+ */
1864
+ runNamedTunnel(id: string, token: string, port: number): Promise<TunnelInfo>;
1860
1865
  /** Stop the cloudflared process for the given tunnel id. */
1861
1866
  destroyTunnel(id: string): Promise<{
1862
1867
  success: true;
@@ -2534,33 +2539,9 @@ declare class InterpreterClient extends BaseHttpClient implements SandboxInterpr
2534
2539
  //#endregion
2535
2540
  //#region src/clients/port-client.d.ts
2536
2541
  /**
2537
- * Request interface for unexposing ports
2542
+ * Client for port readiness operations.
2538
2543
  */
2539
- interface UnexposePortRequest {
2540
- port: number;
2541
- }
2542
- /**
2543
- * Client for port management and preview URL operations
2544
- */
2545
- declare class PortClient extends BaseHttpClient implements SandboxPortsAPI {
2546
- /**
2547
- * Expose a port and get a preview URL
2548
- * @param port - Port number to expose
2549
- * @param sessionId - The session ID for this operation
2550
- * @param name - Optional name for the port
2551
- */
2552
- exposePort(port: number, sessionId: string, name?: string): Promise<PortExposeResult>;
2553
- /**
2554
- * Unexpose a port and remove its preview URL
2555
- * @param port - Port number to unexpose
2556
- * @param sessionId - The session ID for this operation
2557
- */
2558
- unexposePort(port: number, sessionId: string): Promise<PortCloseResult>;
2559
- /**
2560
- * Get all currently exposed ports
2561
- * @param sessionId - The session ID for this operation
2562
- */
2563
- getExposedPorts(sessionId: string): Promise<PortListResult>;
2544
+ declare class PortClient extends BaseHttpClient {
2564
2545
  /**
2565
2546
  * Watch a port for readiness via SSE stream
2566
2547
  * @param request - Port watch configuration
@@ -2933,7 +2914,7 @@ declare class ContainerControlClient {
2933
2914
  //#endregion
2934
2915
  //#region src/tunnels/tunnels-handler.d.ts
2935
2916
  interface TunnelsHandler {
2936
- get(port: number): Promise<TunnelInfo>;
2917
+ get(port: number, options?: TunnelOptions): Promise<TunnelInfo>;
2937
2918
  list(): Promise<TunnelInfo[]>;
2938
2919
  destroy(portOrInfo: number | TunnelInfo): Promise<void>;
2939
2920
  }
@@ -2958,6 +2939,7 @@ declare class Sandbox<Env = unknown> extends Container<Env> implements ISandbox
2958
2939
  private sandboxName;
2959
2940
  private tunnelsHandler;
2960
2941
  private tunnelExitHandler;
2942
+ private destroyAllTunnels;
2961
2943
  private readonly controlCallback;
2962
2944
  private normalizeId;
2963
2945
  private defaultSession;
@@ -2967,6 +2949,7 @@ declare class Sandbox<Env = unknown> extends Container<Env> implements ISandbox
2967
2949
  private logger;
2968
2950
  private keepAliveEnabled;
2969
2951
  private activeMounts;
2952
+ private currentRuntime;
2970
2953
  private transport;
2971
2954
  /**
2972
2955
  * True once transport has been written to storage at least once (either
@@ -2992,7 +2975,22 @@ declare class Sandbox<Env = unknown> extends Container<Env> implements ISandbox
2992
2975
  private r2SecretAccessKey;
2993
2976
  private r2AccountId;
2994
2977
  private backupBucketName;
2978
+ private backupBucketEndpoint;
2995
2979
  private r2Client;
2980
+ /**
2981
+ * Lazily-resolved Cloudflare account id for named-tunnel provisioning.
2982
+ * Resolved on first access via `tunnels/credentials.ts` and cached for
2983
+ * the lifetime of this DO instance. See the credentials helper for
2984
+ * the precedence chain.
2985
+ */
2986
+ private tunnelAccountIdPromise;
2987
+ /**
2988
+ * Lazily-resolved Cloudflare zone id for named-tunnel provisioning.
2989
+ * Falls back to the single zone the token can see under the resolved
2990
+ * account id when `CLOUDFLARE_ZONE_ID` is not set. Cached for the
2991
+ * lifetime of this DO instance.
2992
+ */
2993
+ private tunnelZoneIdPromise;
2996
2994
  /**
2997
2995
  * Default container startup timeouts (conservative for production)
2998
2996
  * Based on Cloudflare docs: "Containers take several minutes to provision"
@@ -3157,18 +3155,7 @@ declare class Sandbox<Env = unknown> extends Container<Env> implements ISandbox
3157
3155
  destroy(): Promise<void>;
3158
3156
  private doDestroy;
3159
3157
  onStart(): Promise<void>;
3160
- /**
3161
- * Re-expose ports on the container runtime using tokens persisted in DO
3162
- * storage. Called from onStart() after a container (re)start.
3163
- *
3164
- * The DO storage holds the source of truth for which ports should be
3165
- * exposed, which tokens authorize them, and the friendly name (if any)
3166
- * that the caller set when first exposing the port. If a port is already
3167
- * exposed on the container this is a no-op for that port. Individual port
3168
- * failures are logged but do not abort the overall restore — a transient
3169
- * failure for one port must not prevent the others from being restored.
3170
- */
3171
- private restoreExposedPorts;
3158
+ stop(signal?: Parameters<Container<Env>['stop']>[0]): Promise<void>;
3172
3159
  /**
3173
3160
  * Read the `portTokens` map from DO storage, normalizing the legacy
3174
3161
  * string-valued format (just a token) to the current object format
@@ -3176,6 +3163,10 @@ declare class Sandbox<Env = unknown> extends Container<Env> implements ISandbox
3176
3163
  * can appear on any DO whose storage was written before that change.
3177
3164
  */
3178
3165
  private readPortTokens;
3166
+ private readActivePreviewPorts;
3167
+ private writeActivePreviewPorts;
3168
+ private readPreviewState;
3169
+ private clearActivePreviewPorts;
3179
3170
  /**
3180
3171
  * Check if the container version matches the SDK version
3181
3172
  * Logs a warning if there's a mismatch
@@ -3230,6 +3221,14 @@ declare class Sandbox<Env = unknown> extends Container<Env> implements ISandbox
3230
3221
  * When keepAlive is disabled, calls parent implementation which stops the container
3231
3222
  */
3232
3223
  onActivityExpired(): Promise<void>;
3224
+ private isPreviewProxyRequest;
3225
+ private invalidPreviewTokenResponse;
3226
+ private stalePreviewURLResponse;
3227
+ private getPreviewForwardingContainer;
3228
+ private beginPreviewForward;
3229
+ private fetchPreviewIfRunning;
3230
+ private buildPreviewProxyRequest;
3231
+ private proxyPreviewRequest;
3233
3232
  fetch(request: Request): Promise<Response>;
3234
3233
  wsConnect(request: Request, port: number): Promise<Response>;
3235
3234
  private determinePort;
@@ -3448,11 +3447,10 @@ declare class Sandbox<Env = unknown> extends Container<Env> implements ISandbox
3448
3447
  /**
3449
3448
  * Expose a port and get a preview URL for accessing services running in the sandbox
3450
3449
  *
3451
- * Preview URLs survive transient container restarts: the token and any
3452
- * friendly name are persisted in Durable Object storage, and the port is
3453
- * automatically re-exposed on the container when it comes back up. Tokens
3454
- * are cleared only on explicit `unexposePort()` or full sandbox
3455
- * `destroy()`.
3450
+ * Preview URL authorization survives transient container restarts, but
3451
+ * forwarding is active only for the runtime where `exposePort()` was last
3452
+ * called. Call `exposePort()` again after a restart to reactivate an
3453
+ * existing URL for the current runtime.
3456
3454
  *
3457
3455
  * @param port - Port number to expose (1024-65535)
3458
3456
  * @param options - Configuration options
@@ -3484,11 +3482,22 @@ declare class Sandbox<Env = unknown> extends Container<Env> implements ISandbox
3484
3482
  port: number;
3485
3483
  name: string | undefined;
3486
3484
  }>;
3485
+ /**
3486
+ * Revoke preview URL authorization and current-runtime activation for a port.
3487
+ *
3488
+ * Revocation is idempotent: calling this for a port with no preview state is
3489
+ * still successful. The operation clears Durable Object-owned preview state
3490
+ * only and does not contact, probe, wake, or clean up the container runtime.
3491
+ */
3487
3492
  unexposePort(port: number): Promise<void>;
3493
+ /**
3494
+ * Returns preview URLs that are currently forwardable in the active runtime.
3495
+ * Durable authorization without current-runtime activation is omitted.
3496
+ */
3488
3497
  getExposedPorts(hostname: string): Promise<{
3489
3498
  url: string;
3490
3499
  port: number;
3491
- status: "active" | "inactive";
3500
+ status: "active";
3492
3501
  }[]>;
3493
3502
  /**
3494
3503
  * Namespaced tunnel API. Quick tunnels are zero-config preview URLs
@@ -3517,8 +3526,45 @@ declare class Sandbox<Env = unknown> extends Container<Env> implements ISandbox
3517
3526
  * fields.
3518
3527
  */
3519
3528
  private ensureTunnelsBuilt;
3529
+ /**
3530
+ * Resolve the Cloudflare account id used for named-tunnel provisioning.
3531
+ *
3532
+ * Memoised for the lifetime of this DO instance. The first call may hit
3533
+ * `GET /user/tokens/verify` to derive the account id from the configured
3534
+ * `CLOUDFLARE_API_TOKEN`; subsequent calls return the cached promise.
3535
+ *
3536
+ * Only successful resolutions are cached: a rejected lookup clears the
3537
+ * slot so the next caller retries. Otherwise a transient failure on
3538
+ * first use would permanently poison every later named-tunnel `get()`
3539
+ * on this DO instance.
3540
+ */
3541
+ private getTunnelAccountId;
3542
+ /**
3543
+ * Resolve the Cloudflare zone id used for named-tunnel provisioning.
3544
+ *
3545
+ * Memoised for the lifetime of this DO instance. Falls back to the
3546
+ * single zone the token can see under `accountId` via `GET /zones`
3547
+ * when `CLOUDFLARE_ZONE_ID` is not set. Failed lookups clear the cache
3548
+ * so the next caller retries — see `getTunnelAccountId` for the
3549
+ * rationale.
3550
+ */
3551
+ private getTunnelZoneId;
3552
+ /**
3553
+ * Returns whether a port is currently preview-forwardable.
3554
+ * This checks Durable Object-owned auth and runtime activation without
3555
+ * contacting or waking the container.
3556
+ */
3520
3557
  isPortExposed(port: number): Promise<boolean>;
3558
+ /**
3559
+ * Checks durable preview URL authorization for a port/token pair.
3560
+ *
3561
+ * This does not check whether the port is activated for the current runtime
3562
+ * and is not sufficient to decide whether preview traffic may forward.
3563
+ */
3521
3564
  validatePortToken(port: number, token: string): Promise<boolean>;
3565
+ private validatePreviewURLForRuntime;
3566
+ private getCurrentPreviewPorts;
3567
+ private previewTokensMatch;
3522
3568
  private validateCustomToken;
3523
3569
  private generatePortToken;
3524
3570
  private constructPreviewUrl;
@@ -3598,17 +3644,19 @@ declare class Sandbox<Env = unknown> extends Container<Env> implements ISandbox
3598
3644
  * Returns validated presigned URL configuration or throws if not configured.
3599
3645
  * All credential fields plus the R2 binding are required for backup to work.
3600
3646
  */
3601
- private requirePresignedUrlSupport;
3647
+ private requirePresignedURLSupport;
3648
+ private getBackupBucketEndpoint;
3649
+ private getBackupObjectURL;
3602
3650
  /**
3603
3651
  * Generate a presigned GET URL for downloading an object from R2.
3604
3652
  * The container can curl this URL directly without credentials.
3605
3653
  */
3606
- private generatePresignedGetUrl;
3654
+ private generatePresignedGetURL;
3607
3655
  /**
3608
3656
  * Generate a presigned PUT URL for uploading an object to R2.
3609
3657
  * The container can curl PUT to this URL directly without credentials.
3610
3658
  */
3611
- private generatePresignedPutUrl;
3659
+ private generatePresignedPutURL;
3612
3660
  /**
3613
3661
  * Upload a backup archive via presigned PUT URL.
3614
3662
  * The container curls the archive directly to R2, bypassing the DO.
@@ -3618,7 +3666,7 @@ declare class Sandbox<Env = unknown> extends Container<Env> implements ISandbox
3618
3666
  /**
3619
3667
  * Generate a presigned PUT URL for a single part in a multipart upload.
3620
3668
  */
3621
- private generatePresignedPartUrl;
3669
+ private generatePresignedPartURL;
3622
3670
  /**
3623
3671
  * Upload a backup archive to R2 using parallel multipart upload.
3624
3672
  * Uses the S3-compatible API exclusively for create/complete/abort so that
@@ -3712,5 +3760,5 @@ declare class Sandbox<Env = unknown> extends Container<Env> implements ISandbox
3712
3760
  private configureR2EgressOutbound;
3713
3761
  }
3714
3762
  //#endregion
3715
- export { StartProcessRequest as $, DesktopStopResponse as A, ProcessOptions as At, ExecuteResponse as B, WaitForPortOptions as Bt, ClickOptions as C, PortListResult as Ct, DesktopStartOptions as D, ProcessKillResult as Dt, DesktopClient as E, ProcessInfoResult as Et, ScreenshotRegion as F, SandboxOptions as Ft, HttpClientOptions as G, PtyOptions as Gt, BaseApiResponse as H, isExecResult as Ht, ScreenshotResponse as I, SandboxTransport as It, SessionRequest as J, Execution as Jt, RequestConfig as K, CodeContext as Kt, ScrollDirection as L, SessionOptions as Lt, ScreenSizeResponse as M, ProcessStatus as Mt, ScreenshotBytesResponse as N, RemoteMountBucketOptions as Nt, DesktopStartResponse as O, ProcessListResult as Ot, ScreenshotOptions as P, RestoreBackupResult as Pt, ExposePortRequest as Q, TypeOptions as R, StreamOptions as Rt, WriteFileRequest as S, PortExposeResult as St, Desktop as T, ProcessCleanupResult as Tt, ContainerStub as U, isProcess as Ut, BackupClient as V, WatchOptions as Vt, ErrorResponse as W, isProcessStatus as Wt, TunnelInfo as X, RunCodeOptions as Xt, SandboxInterpreterAPI as Y, ExecutionResult as Yt, ExecuteRequest as Z, GitClient as _, ListFilesOptions as _t, CreateSessionRequest as a, CheckChangesResult as at, MkdirRequest as b, MountBucketOptions as bt, DeleteSessionResponse as c, ExecOptions as ct, ProcessClient as d, FileChunk as dt, BackupOptions as et, PortClient as f, FileMetadata as ft, GitCheckoutRequest as g, ISandbox as gt, InterpreterClient as h, GitCheckoutResult as ht, CommandsResponse as i, CheckChangesOptions as it, KeyInput as j, ProcessStartResult as jt, DesktopStatusResponse as k, ProcessLogsResult as kt, PingResponse as l, ExecResult as lt, ExecutionCallbacks as m, FileWatchSSEEvent as mt, getSandbox as n, BucketCredentials as nt, CreateSessionResponse as o, DirectoryBackup as ot, UnexposePortRequest as p, FileStreamEvent as pt, ResponseHandler as q, CreateContextOptions as qt, SandboxClient as r, BucketProvider as rt, DeleteSessionRequest as s, ExecEvent as st, Sandbox as t, BaseExecOptions as tt, UtilityClient as u, ExecutionSession as ut, FileClient as v, LocalMountBucketOptions as vt, CursorPositionResponse as w, Process as wt, ReadFileRequest as x, PortCloseResult as xt, FileOperationRequest as y, LogEvent as yt, CommandClient as z, WaitForLogResult as zt };
3716
- //# sourceMappingURL=sandbox-CwcSm_60.d.ts.map
3763
+ export { ExecuteRequest as $, KeyInput as A, ProcessStatus as At, BackupClient as B, isExecResult as Bt, CursorPositionResponse as C, ProcessCleanupResult as Ct, DesktopStartResponse as D, ProcessLogsResult as Dt, DesktopStartOptions as E, ProcessListResult as Et, ScreenshotResponse as F, SessionOptions as Ft, RequestConfig as G, CreateContextOptions as Gt, ContainerStub as H, isProcessStatus as Ht, ScrollDirection as I, StreamOptions as It, NamedTunnelInfo as J, RunCodeOptions as Jt, ResponseHandler as K, Execution as Kt, TypeOptions as L, WaitForLogResult as Lt, ScreenshotBytesResponse as M, RestoreBackupResult as Mt, ScreenshotOptions as N, SandboxOptions as Nt, DesktopStatusResponse as O, ProcessOptions as Ot, ScreenshotRegion as P, SandboxTransport as Pt, TunnelOptions as Q, CommandClient as R, WaitForPortOptions as Rt, ClickOptions as S, Process as St, DesktopClient as T, ProcessKillResult as Tt, ErrorResponse as U, PtyOptions as Ut, BaseApiResponse as V, isProcess as Vt, HttpClientOptions as W, CodeContext as Wt, SandboxInterpreterAPI as X, QuickTunnelInfo as Y, TunnelInfo as Z, FileClient as _, ISandbox as _t, CreateSessionRequest as a, CheckChangesOptions as at, ReadFileRequest as b, LogEvent as bt, DeleteSessionResponse as c, ExecEvent as ct, ProcessClient as d, ExecutionSession as dt, StartProcessRequest as et, PortClient as f, FileChunk as ft, GitClient as g, GitCheckoutResult as gt, GitCheckoutRequest as h, FileWatchSSEEvent as ht, CommandsResponse as i, BucketProvider as it, ScreenSizeResponse as j, RemoteMountBucketOptions as jt, DesktopStopResponse as k, ProcessStartResult as kt, PingResponse as l, ExecOptions as lt, InterpreterClient as m, FileStreamEvent as mt, getSandbox as n, BaseExecOptions as nt, CreateSessionResponse as o, CheckChangesResult as ot, ExecutionCallbacks as p, FileMetadata as pt, SessionRequest as q, ExecutionResult as qt, SandboxClient as r, BucketCredentials as rt, DeleteSessionRequest as s, DirectoryBackup as st, Sandbox as t, BackupOptions as tt, UtilityClient as u, ExecResult as ut, FileOperationRequest as v, ListFilesOptions as vt, Desktop as w, ProcessInfoResult as wt, WriteFileRequest as x, MountBucketOptions as xt, MkdirRequest as y, LocalMountBucketOptions as yt, ExecuteResponse as z, WatchOptions as zt };
3764
+ //# sourceMappingURL=sandbox-B9LOT0cg.d.ts.map