@cloudflare/sandbox 0.4.17 → 0.5.1
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/.turbo/turbo-build.log +8 -8
- package/CHANGELOG.md +58 -0
- package/Dockerfile +5 -1
- package/LICENSE +176 -0
- package/README.md +1 -1
- package/dist/index.d.ts +296 -312
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +527 -57
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/clients/base-client.ts +107 -46
- package/src/clients/file-client.ts +2 -2
- package/src/index.ts +19 -2
- package/src/request-handler.ts +2 -1
- package/src/sandbox.ts +637 -24
- package/src/storage-mount/credential-detection.ts +41 -0
- package/src/storage-mount/errors.ts +51 -0
- package/src/storage-mount/index.ts +17 -0
- package/src/storage-mount/provider-detection.ts +93 -0
- package/src/storage-mount/types.ts +17 -0
- package/src/version.ts +1 -1
- package/tests/base-client.test.ts +218 -0
- package/tests/get-sandbox.test.ts +24 -1
- package/tests/sandbox.test.ts +121 -0
- package/tests/storage-mount/credential-detection.test.ts +119 -0
- package/tests/storage-mount/provider-detection.test.ts +77 -0
- package/tsdown.config.ts +2 -1
package/dist/index.d.ts
CHANGED
|
@@ -2,20 +2,6 @@ import { Container } from "@cloudflare/containers";
|
|
|
2
2
|
|
|
3
3
|
//#region ../shared/dist/logger/types.d.ts
|
|
4
4
|
|
|
5
|
-
/**
|
|
6
|
-
* Logger types for Cloudflare Sandbox SDK
|
|
7
|
-
*
|
|
8
|
-
* Provides structured, trace-aware logging across Worker, Durable Object, and Container.
|
|
9
|
-
*/
|
|
10
|
-
/**
|
|
11
|
-
* Log levels (from most to least verbose)
|
|
12
|
-
*/
|
|
13
|
-
declare enum LogLevel {
|
|
14
|
-
DEBUG = 0,
|
|
15
|
-
INFO = 1,
|
|
16
|
-
WARN = 2,
|
|
17
|
-
ERROR = 3,
|
|
18
|
-
}
|
|
19
5
|
type LogComponent = 'container' | 'sandbox-do' | 'executor';
|
|
20
6
|
/**
|
|
21
7
|
* Context metadata included in every log entry
|
|
@@ -111,182 +97,6 @@ interface Logger {
|
|
|
111
97
|
child(context: Partial<LogContext>): Logger;
|
|
112
98
|
}
|
|
113
99
|
//#endregion
|
|
114
|
-
//#region ../shared/dist/logger/trace-context.d.ts
|
|
115
|
-
/**
|
|
116
|
-
* Trace context utilities for request correlation
|
|
117
|
-
*
|
|
118
|
-
* Trace IDs enable correlating logs across distributed components:
|
|
119
|
-
* Worker → Durable Object → Container → back
|
|
120
|
-
*
|
|
121
|
-
* The trace ID is propagated via the X-Trace-Id HTTP header.
|
|
122
|
-
*/
|
|
123
|
-
/**
|
|
124
|
-
* Utility for managing trace context across distributed components
|
|
125
|
-
*/
|
|
126
|
-
declare class TraceContext {
|
|
127
|
-
/**
|
|
128
|
-
* HTTP header name for trace ID propagation
|
|
129
|
-
*/
|
|
130
|
-
private static readonly TRACE_HEADER;
|
|
131
|
-
/**
|
|
132
|
-
* Generate a new trace ID
|
|
133
|
-
*
|
|
134
|
-
* Format: "tr_" + 16 random hex characters
|
|
135
|
-
* Example: "tr_7f3a9b2c4e5d6f1a"
|
|
136
|
-
*
|
|
137
|
-
* @returns Newly generated trace ID
|
|
138
|
-
*/
|
|
139
|
-
static generate(): string;
|
|
140
|
-
/**
|
|
141
|
-
* Extract trace ID from HTTP request headers
|
|
142
|
-
*
|
|
143
|
-
* @param headers Request headers
|
|
144
|
-
* @returns Trace ID if present, null otherwise
|
|
145
|
-
*/
|
|
146
|
-
static fromHeaders(headers: Headers): string | null;
|
|
147
|
-
/**
|
|
148
|
-
* Create headers object with trace ID for outgoing requests
|
|
149
|
-
*
|
|
150
|
-
* @param traceId Trace ID to include
|
|
151
|
-
* @returns Headers object with X-Trace-Id set
|
|
152
|
-
*/
|
|
153
|
-
static toHeaders(traceId: string): Record<string, string>;
|
|
154
|
-
/**
|
|
155
|
-
* Get the header name used for trace ID propagation
|
|
156
|
-
*
|
|
157
|
-
* @returns Header name ("X-Trace-Id")
|
|
158
|
-
*/
|
|
159
|
-
static getHeaderName(): string;
|
|
160
|
-
}
|
|
161
|
-
//#endregion
|
|
162
|
-
//#region ../shared/dist/logger/index.d.ts
|
|
163
|
-
|
|
164
|
-
/**
|
|
165
|
-
* Create a no-op logger for testing
|
|
166
|
-
*
|
|
167
|
-
* Returns a logger that implements the Logger interface but does nothing.
|
|
168
|
-
* Useful for tests that don't need actual logging output.
|
|
169
|
-
*
|
|
170
|
-
* @returns No-op logger instance
|
|
171
|
-
*
|
|
172
|
-
* @example
|
|
173
|
-
* ```typescript
|
|
174
|
-
* // In tests
|
|
175
|
-
* const client = new HttpClient({
|
|
176
|
-
* baseUrl: 'http://test.com',
|
|
177
|
-
* logger: createNoOpLogger() // Optional - tests can enable real logging if needed
|
|
178
|
-
* });
|
|
179
|
-
* ```
|
|
180
|
-
*/
|
|
181
|
-
declare function createNoOpLogger(): Logger;
|
|
182
|
-
/**
|
|
183
|
-
* Get the current logger from AsyncLocalStorage
|
|
184
|
-
*
|
|
185
|
-
* @throws Error if no logger is initialized in the current async context
|
|
186
|
-
* @returns Current logger instance
|
|
187
|
-
*
|
|
188
|
-
* @example
|
|
189
|
-
* ```typescript
|
|
190
|
-
* function someHelperFunction() {
|
|
191
|
-
* const logger = getLogger(); // Automatically has all context!
|
|
192
|
-
* logger.info('Helper called');
|
|
193
|
-
* }
|
|
194
|
-
* ```
|
|
195
|
-
*/
|
|
196
|
-
declare function getLogger(): Logger;
|
|
197
|
-
/**
|
|
198
|
-
* Run a function with a logger stored in AsyncLocalStorage
|
|
199
|
-
*
|
|
200
|
-
* The logger is available to all code within the function via getLogger().
|
|
201
|
-
* This is typically called at request entry points (fetch handler) and when
|
|
202
|
-
* creating child loggers with additional context.
|
|
203
|
-
*
|
|
204
|
-
* @param logger Logger instance to store in context
|
|
205
|
-
* @param fn Function to execute with logger context
|
|
206
|
-
* @returns Result of the function
|
|
207
|
-
*
|
|
208
|
-
* @example
|
|
209
|
-
* ```typescript
|
|
210
|
-
* // At request entry point
|
|
211
|
-
* async fetch(request: Request): Promise<Response> {
|
|
212
|
-
* const logger = createLogger({ component: 'sandbox-do', traceId: 'tr_abc' });
|
|
213
|
-
* return runWithLogger(logger, async () => {
|
|
214
|
-
* return await this.handleRequest(request);
|
|
215
|
-
* });
|
|
216
|
-
* }
|
|
217
|
-
*
|
|
218
|
-
* // When adding operation context
|
|
219
|
-
* async exec(command: string) {
|
|
220
|
-
* const logger = getLogger().child({ operation: 'exec', commandId: 'cmd-123' });
|
|
221
|
-
* return runWithLogger(logger, async () => {
|
|
222
|
-
* logger.info('Command started');
|
|
223
|
-
* await this.executeCommand(command); // Nested calls get the child logger
|
|
224
|
-
* logger.info('Command completed');
|
|
225
|
-
* });
|
|
226
|
-
* }
|
|
227
|
-
* ```
|
|
228
|
-
*/
|
|
229
|
-
declare function runWithLogger<T>(logger: Logger, fn: () => T | Promise<T>): T | Promise<T>;
|
|
230
|
-
/**
|
|
231
|
-
* Create a new logger instance
|
|
232
|
-
*
|
|
233
|
-
* @param context Base context for the logger. Must include 'component'.
|
|
234
|
-
* TraceId will be auto-generated if not provided.
|
|
235
|
-
* @returns New logger instance
|
|
236
|
-
*
|
|
237
|
-
* @example
|
|
238
|
-
* ```typescript
|
|
239
|
-
* // In Durable Object
|
|
240
|
-
* const logger = createLogger({
|
|
241
|
-
* component: 'sandbox-do',
|
|
242
|
-
* traceId: TraceContext.fromHeaders(request.headers) || TraceContext.generate(),
|
|
243
|
-
* sandboxId: this.id
|
|
244
|
-
* });
|
|
245
|
-
*
|
|
246
|
-
* // In Container
|
|
247
|
-
* const logger = createLogger({
|
|
248
|
-
* component: 'container',
|
|
249
|
-
* traceId: TraceContext.fromHeaders(request.headers)!,
|
|
250
|
-
* sessionId: this.id
|
|
251
|
-
* });
|
|
252
|
-
* ```
|
|
253
|
-
*/
|
|
254
|
-
declare function createLogger(context: Partial<LogContext> & {
|
|
255
|
-
component: LogComponent;
|
|
256
|
-
}): Logger;
|
|
257
|
-
//#endregion
|
|
258
|
-
//#region ../shared/dist/git.d.ts
|
|
259
|
-
/**
|
|
260
|
-
* Redact credentials from URLs for secure logging
|
|
261
|
-
*
|
|
262
|
-
* Replaces any credentials (username:password, tokens, etc.) embedded
|
|
263
|
-
* in URLs with ****** to prevent sensitive data exposure in logs.
|
|
264
|
-
* Works with URLs embedded in text (e.g., "Error: https://token@github.com/repo.git failed")
|
|
265
|
-
*
|
|
266
|
-
* @param text - String that may contain URLs with credentials
|
|
267
|
-
* @returns String with credentials redacted from any URLs
|
|
268
|
-
*/
|
|
269
|
-
declare function redactCredentials(text: string): string;
|
|
270
|
-
/**
|
|
271
|
-
* Sanitize data by redacting credentials from any strings
|
|
272
|
-
* Recursively processes objects and arrays to ensure credentials are never leaked
|
|
273
|
-
*/
|
|
274
|
-
declare function sanitizeGitData<T>(data: T): T;
|
|
275
|
-
/**
|
|
276
|
-
* Logger wrapper that automatically sanitizes git credentials
|
|
277
|
-
*/
|
|
278
|
-
declare class GitLogger implements Logger {
|
|
279
|
-
private readonly baseLogger;
|
|
280
|
-
constructor(baseLogger: Logger);
|
|
281
|
-
private sanitizeContext;
|
|
282
|
-
private sanitizeError;
|
|
283
|
-
debug(message: string, context?: Partial<LogContext>): void;
|
|
284
|
-
info(message: string, context?: Partial<LogContext>): void;
|
|
285
|
-
warn(message: string, context?: Partial<LogContext>): void;
|
|
286
|
-
error(message: string, error?: Error, context?: Partial<LogContext>): void;
|
|
287
|
-
child(context: Partial<LogContext>): Logger;
|
|
288
|
-
}
|
|
289
|
-
//#endregion
|
|
290
100
|
//#region ../shared/dist/interpreter-types.d.ts
|
|
291
101
|
interface CreateContextOptions {
|
|
292
102
|
/**
|
|
@@ -529,22 +339,6 @@ declare class Execution {
|
|
|
529
339
|
*/
|
|
530
340
|
toJSON(): ExecutionResult;
|
|
531
341
|
}
|
|
532
|
-
declare class ResultImpl implements Result {
|
|
533
|
-
private raw;
|
|
534
|
-
constructor(raw: any);
|
|
535
|
-
get text(): string | undefined;
|
|
536
|
-
get html(): string | undefined;
|
|
537
|
-
get png(): string | undefined;
|
|
538
|
-
get jpeg(): string | undefined;
|
|
539
|
-
get svg(): string | undefined;
|
|
540
|
-
get latex(): string | undefined;
|
|
541
|
-
get markdown(): string | undefined;
|
|
542
|
-
get javascript(): string | undefined;
|
|
543
|
-
get json(): any;
|
|
544
|
-
get chart(): ChartData | undefined;
|
|
545
|
-
get data(): any;
|
|
546
|
-
formats(): string[];
|
|
547
|
-
}
|
|
548
342
|
//#endregion
|
|
549
343
|
//#region ../shared/dist/request-types.d.ts
|
|
550
344
|
/**
|
|
@@ -561,51 +355,6 @@ interface StartProcessRequest {
|
|
|
561
355
|
encoding?: string;
|
|
562
356
|
autoCleanup?: boolean;
|
|
563
357
|
}
|
|
564
|
-
/**
|
|
565
|
-
* Request to delete a file
|
|
566
|
-
*/
|
|
567
|
-
interface DeleteFileRequest {
|
|
568
|
-
path: string;
|
|
569
|
-
sessionId?: string;
|
|
570
|
-
}
|
|
571
|
-
/**
|
|
572
|
-
* Request to rename a file
|
|
573
|
-
*/
|
|
574
|
-
interface RenameFileRequest {
|
|
575
|
-
oldPath: string;
|
|
576
|
-
newPath: string;
|
|
577
|
-
sessionId?: string;
|
|
578
|
-
}
|
|
579
|
-
/**
|
|
580
|
-
* Request to move a file
|
|
581
|
-
*/
|
|
582
|
-
interface MoveFileRequest {
|
|
583
|
-
sourcePath: string;
|
|
584
|
-
destinationPath: string;
|
|
585
|
-
sessionId?: string;
|
|
586
|
-
}
|
|
587
|
-
/**
|
|
588
|
-
* Request to check if a file or directory exists
|
|
589
|
-
*/
|
|
590
|
-
interface FileExistsRequest {
|
|
591
|
-
path: string;
|
|
592
|
-
sessionId?: string;
|
|
593
|
-
}
|
|
594
|
-
/**
|
|
595
|
-
* Request to create a session
|
|
596
|
-
*/
|
|
597
|
-
interface SessionCreateRequest {
|
|
598
|
-
id?: string;
|
|
599
|
-
name?: string;
|
|
600
|
-
env?: Record<string, string>;
|
|
601
|
-
cwd?: string;
|
|
602
|
-
}
|
|
603
|
-
/**
|
|
604
|
-
* Request to delete a session
|
|
605
|
-
*/
|
|
606
|
-
interface SessionDeleteRequest {
|
|
607
|
-
sessionId: string;
|
|
608
|
-
}
|
|
609
358
|
//#endregion
|
|
610
359
|
//#region ../shared/dist/types.d.ts
|
|
611
360
|
interface BaseExecOptions {
|
|
@@ -834,6 +583,72 @@ interface SandboxOptions {
|
|
|
834
583
|
* Default: false
|
|
835
584
|
*/
|
|
836
585
|
keepAlive?: boolean;
|
|
586
|
+
/**
|
|
587
|
+
* Normalize sandbox ID to lowercase for preview URL compatibility
|
|
588
|
+
*
|
|
589
|
+
* Required for preview URLs because hostnames are case-insensitive (RFC 3986), which
|
|
590
|
+
* would route requests to a different Durable Object instance with IDs containing uppercase letters.
|
|
591
|
+
*
|
|
592
|
+
* **Important:** Different normalizeId values create different Durable Object instances:
|
|
593
|
+
* - `getSandbox(ns, "MyProject")` → DO key: "MyProject"
|
|
594
|
+
* - `getSandbox(ns, "MyProject", {normalizeId: true})` → DO key: "myproject"
|
|
595
|
+
*
|
|
596
|
+
* **Future change:** In a future version, this will default to `true` (automatically lowercase all IDs).
|
|
597
|
+
* IDs with uppercase letters will trigger a warning. To prepare, use lowercase IDs or explicitly
|
|
598
|
+
* pass `normalizeId: true`.
|
|
599
|
+
*
|
|
600
|
+
* @example
|
|
601
|
+
* getSandbox(ns, "my-project") // Works with preview URLs (lowercase)
|
|
602
|
+
* getSandbox(ns, "MyProject", {normalizeId: true}) // Normalized to "myproject"
|
|
603
|
+
*
|
|
604
|
+
* @default false
|
|
605
|
+
*/
|
|
606
|
+
normalizeId?: boolean;
|
|
607
|
+
/**
|
|
608
|
+
* Container startup timeout configuration
|
|
609
|
+
*
|
|
610
|
+
* Tune timeouts based on your container's characteristics. SDK defaults (30s instance, 90s ports)
|
|
611
|
+
* work for most use cases. Adjust for heavy containers or fail-fast applications.
|
|
612
|
+
*
|
|
613
|
+
* Can also be configured via environment variables:
|
|
614
|
+
* - SANDBOX_INSTANCE_TIMEOUT_MS
|
|
615
|
+
* - SANDBOX_PORT_TIMEOUT_MS
|
|
616
|
+
* - SANDBOX_POLL_INTERVAL_MS
|
|
617
|
+
*
|
|
618
|
+
* Precedence: options > env vars > SDK defaults
|
|
619
|
+
*
|
|
620
|
+
* @example
|
|
621
|
+
* // Heavy containers (ML models, large apps)
|
|
622
|
+
* getSandbox(ns, id, {
|
|
623
|
+
* containerTimeouts: { portReadyTimeoutMS: 180_000 }
|
|
624
|
+
* })
|
|
625
|
+
*
|
|
626
|
+
* @example
|
|
627
|
+
* // Fail-fast for latency-sensitive apps
|
|
628
|
+
* getSandbox(ns, id, {
|
|
629
|
+
* containerTimeouts: {
|
|
630
|
+
* instanceGetTimeoutMS: 15_000,
|
|
631
|
+
* portReadyTimeoutMS: 30_000
|
|
632
|
+
* }
|
|
633
|
+
* })
|
|
634
|
+
*/
|
|
635
|
+
containerTimeouts?: {
|
|
636
|
+
/**
|
|
637
|
+
* Time to wait for container instance provisioning
|
|
638
|
+
* @default 30000 (30s) - or SANDBOX_INSTANCE_TIMEOUT_MS env var
|
|
639
|
+
*/
|
|
640
|
+
instanceGetTimeoutMS?: number;
|
|
641
|
+
/**
|
|
642
|
+
* Time to wait for application startup and ports to be ready
|
|
643
|
+
* @default 90000 (90s) - or SANDBOX_PORT_TIMEOUT_MS env var
|
|
644
|
+
*/
|
|
645
|
+
portReadyTimeoutMS?: number;
|
|
646
|
+
/**
|
|
647
|
+
* How often to poll for container readiness
|
|
648
|
+
* @default 1000 (1s) - or SANDBOX_POLL_INTERVAL_MS env var
|
|
649
|
+
*/
|
|
650
|
+
waitIntervalMS?: number;
|
|
651
|
+
};
|
|
837
652
|
}
|
|
838
653
|
/**
|
|
839
654
|
* Execution session - isolated execution context within a sandbox
|
|
@@ -1019,35 +834,17 @@ interface ProcessCleanupResult {
|
|
|
1019
834
|
cleanedCount: number;
|
|
1020
835
|
timestamp: string;
|
|
1021
836
|
}
|
|
1022
|
-
interface SessionCreateResult {
|
|
1023
|
-
success: boolean;
|
|
1024
|
-
sessionId: string;
|
|
1025
|
-
name?: string;
|
|
1026
|
-
cwd?: string;
|
|
1027
|
-
timestamp: string;
|
|
1028
|
-
}
|
|
1029
837
|
interface SessionDeleteResult {
|
|
1030
838
|
success: boolean;
|
|
1031
839
|
sessionId: string;
|
|
1032
840
|
timestamp: string;
|
|
1033
841
|
}
|
|
1034
|
-
interface EnvSetResult {
|
|
1035
|
-
success: boolean;
|
|
1036
|
-
timestamp: string;
|
|
1037
|
-
}
|
|
1038
842
|
interface PortExposeResult {
|
|
1039
843
|
success: boolean;
|
|
1040
844
|
port: number;
|
|
1041
845
|
url: string;
|
|
1042
846
|
timestamp: string;
|
|
1043
847
|
}
|
|
1044
|
-
interface PortStatusResult {
|
|
1045
|
-
success: boolean;
|
|
1046
|
-
port: number;
|
|
1047
|
-
status: 'active' | 'inactive';
|
|
1048
|
-
url?: string;
|
|
1049
|
-
timestamp: string;
|
|
1050
|
-
}
|
|
1051
848
|
interface PortListResult {
|
|
1052
849
|
success: boolean;
|
|
1053
850
|
ports: Array<{
|
|
@@ -1062,42 +859,6 @@ interface PortCloseResult {
|
|
|
1062
859
|
port: number;
|
|
1063
860
|
timestamp: string;
|
|
1064
861
|
}
|
|
1065
|
-
interface InterpreterHealthResult {
|
|
1066
|
-
success: boolean;
|
|
1067
|
-
status: 'healthy' | 'unhealthy';
|
|
1068
|
-
timestamp: string;
|
|
1069
|
-
}
|
|
1070
|
-
interface ContextCreateResult {
|
|
1071
|
-
success: boolean;
|
|
1072
|
-
contextId: string;
|
|
1073
|
-
language: string;
|
|
1074
|
-
cwd?: string;
|
|
1075
|
-
timestamp: string;
|
|
1076
|
-
}
|
|
1077
|
-
interface ContextListResult {
|
|
1078
|
-
success: boolean;
|
|
1079
|
-
contexts: Array<{
|
|
1080
|
-
id: string;
|
|
1081
|
-
language: string;
|
|
1082
|
-
cwd?: string;
|
|
1083
|
-
}>;
|
|
1084
|
-
timestamp: string;
|
|
1085
|
-
}
|
|
1086
|
-
interface ContextDeleteResult {
|
|
1087
|
-
success: boolean;
|
|
1088
|
-
contextId: string;
|
|
1089
|
-
timestamp: string;
|
|
1090
|
-
}
|
|
1091
|
-
interface HealthCheckResult {
|
|
1092
|
-
success: boolean;
|
|
1093
|
-
status: 'healthy' | 'unhealthy';
|
|
1094
|
-
timestamp: string;
|
|
1095
|
-
}
|
|
1096
|
-
interface ShutdownResult {
|
|
1097
|
-
success: boolean;
|
|
1098
|
-
message: string;
|
|
1099
|
-
timestamp: string;
|
|
1100
|
-
}
|
|
1101
862
|
interface ExecutionSession {
|
|
1102
863
|
/** Unique session identifier */
|
|
1103
864
|
readonly id: string;
|
|
@@ -1142,6 +903,68 @@ interface ExecutionSession {
|
|
|
1142
903
|
runCodeStream(code: string, options?: RunCodeOptions): Promise<ReadableStream<Uint8Array>>;
|
|
1143
904
|
listCodeContexts(): Promise<CodeContext[]>;
|
|
1144
905
|
deleteCodeContext(contextId: string): Promise<void>;
|
|
906
|
+
mountBucket(bucket: string, mountPath: string, options: MountBucketOptions): Promise<void>;
|
|
907
|
+
unmountBucket(mountPath: string): Promise<void>;
|
|
908
|
+
}
|
|
909
|
+
/**
|
|
910
|
+
* Supported S3-compatible storage providers
|
|
911
|
+
*/
|
|
912
|
+
type BucketProvider = 'r2' | 's3' | 'gcs';
|
|
913
|
+
/**
|
|
914
|
+
* Credentials for S3-compatible storage
|
|
915
|
+
*/
|
|
916
|
+
interface BucketCredentials {
|
|
917
|
+
accessKeyId: string;
|
|
918
|
+
secretAccessKey: string;
|
|
919
|
+
}
|
|
920
|
+
/**
|
|
921
|
+
* Options for mounting an S3-compatible bucket
|
|
922
|
+
*/
|
|
923
|
+
interface MountBucketOptions {
|
|
924
|
+
/**
|
|
925
|
+
* S3-compatible endpoint URL
|
|
926
|
+
*
|
|
927
|
+
* Examples:
|
|
928
|
+
* - R2: 'https://abc123.r2.cloudflarestorage.com'
|
|
929
|
+
* - AWS S3: 'https://s3.us-west-2.amazonaws.com'
|
|
930
|
+
* - GCS: 'https://storage.googleapis.com'
|
|
931
|
+
*
|
|
932
|
+
* Required field
|
|
933
|
+
*/
|
|
934
|
+
endpoint: string;
|
|
935
|
+
/**
|
|
936
|
+
* Optional provider hint for automatic s3fs flag configuration
|
|
937
|
+
* If not specified, will attempt to detect from endpoint URL.
|
|
938
|
+
*
|
|
939
|
+
* Examples:
|
|
940
|
+
* - 'r2' - Cloudflare R2 (adds nomixupload)
|
|
941
|
+
* - 's3' - Amazon S3 (standard configuration)
|
|
942
|
+
* - 'gcs' - Google Cloud Storage (no special flags needed)
|
|
943
|
+
*/
|
|
944
|
+
provider?: BucketProvider;
|
|
945
|
+
/**
|
|
946
|
+
* Explicit credentials (overrides env var auto-detection)
|
|
947
|
+
*/
|
|
948
|
+
credentials?: BucketCredentials;
|
|
949
|
+
/**
|
|
950
|
+
* Mount filesystem as read-only
|
|
951
|
+
* Default: false
|
|
952
|
+
*/
|
|
953
|
+
readOnly?: boolean;
|
|
954
|
+
/**
|
|
955
|
+
* Advanced: Override or extend s3fs options
|
|
956
|
+
*
|
|
957
|
+
* These will be merged with provider-specific defaults.
|
|
958
|
+
* To override defaults completely, specify all options here.
|
|
959
|
+
*
|
|
960
|
+
* Common options:
|
|
961
|
+
* - 'use_path_request_style' - Use path-style URLs (bucket/path vs bucket.host/path)
|
|
962
|
+
* - 'nomixupload' - Disable mixed multipart uploads (needed for some providers)
|
|
963
|
+
* - 'nomultipart' - Disable all multipart operations
|
|
964
|
+
* - 'sigv2' - Use signature version 2 instead of v4
|
|
965
|
+
* - 'no_check_certificate' - Skip SSL certificate validation (dev/testing only)
|
|
966
|
+
*/
|
|
967
|
+
s3fsOptions?: string[];
|
|
1145
968
|
}
|
|
1146
969
|
interface ISandbox {
|
|
1147
970
|
exec(command: string, options?: ExecOptions): Promise<ExecResult>;
|
|
@@ -1179,6 +1002,8 @@ interface ISandbox {
|
|
|
1179
1002
|
branch?: string;
|
|
1180
1003
|
targetDir?: string;
|
|
1181
1004
|
}): Promise<GitCheckoutResult>;
|
|
1005
|
+
mountBucket(bucket: string, mountPath: string, options: MountBucketOptions): Promise<void>;
|
|
1006
|
+
unmountBucket(mountPath: string): Promise<void>;
|
|
1182
1007
|
createSession(options?: SessionOptions): Promise<ExecutionSession>;
|
|
1183
1008
|
deleteSession(sessionId: string): Promise<SessionDeleteResult>;
|
|
1184
1009
|
createCodeContext(options?: CreateContextOptions): Promise<CodeContext>;
|
|
@@ -1253,13 +1078,14 @@ declare abstract class BaseHttpClient {
|
|
|
1253
1078
|
protected logger: Logger;
|
|
1254
1079
|
constructor(options?: HttpClientOptions);
|
|
1255
1080
|
/**
|
|
1256
|
-
* Core HTTP request method with automatic retry for container
|
|
1081
|
+
* Core HTTP request method with automatic retry for container startup delays
|
|
1082
|
+
* Retries both 503 (provisioning) and 500 (startup failure) errors when they're container-related
|
|
1257
1083
|
*/
|
|
1258
1084
|
protected doFetch(path: string, options?: RequestInit): Promise<Response>;
|
|
1259
1085
|
/**
|
|
1260
1086
|
* Make a POST request with JSON body
|
|
1261
1087
|
*/
|
|
1262
|
-
protected post<T>(endpoint: string, data:
|
|
1088
|
+
protected post<T>(endpoint: string, data: unknown, responseHandler?: ResponseHandler<T>): Promise<T>;
|
|
1263
1089
|
/**
|
|
1264
1090
|
* Make a GET request
|
|
1265
1091
|
*/
|
|
@@ -1293,10 +1119,17 @@ declare abstract class BaseHttpClient {
|
|
|
1293
1119
|
*/
|
|
1294
1120
|
protected logError(operation: string, error: unknown): void;
|
|
1295
1121
|
/**
|
|
1296
|
-
* Check if
|
|
1297
|
-
*
|
|
1122
|
+
* Check if response indicates a retryable container error
|
|
1123
|
+
* Uses fail-safe strategy: only retry known transient errors
|
|
1124
|
+
*
|
|
1125
|
+
* TODO: This relies on string matching error messages, which is brittle.
|
|
1126
|
+
* Ideally, the container API should return structured errors with a
|
|
1127
|
+
* `retryable: boolean` field to avoid coupling to error message format.
|
|
1128
|
+
*
|
|
1129
|
+
* @param response - HTTP response to check
|
|
1130
|
+
* @returns true if error is retryable container error, false otherwise
|
|
1298
1131
|
*/
|
|
1299
|
-
private
|
|
1132
|
+
private isRetryableContainerError;
|
|
1300
1133
|
private executeFetch;
|
|
1301
1134
|
}
|
|
1302
1135
|
//#endregion
|
|
@@ -1671,18 +1504,73 @@ declare class Sandbox<Env = unknown> extends Container<Env> implements ISandbox
|
|
|
1671
1504
|
client: SandboxClient;
|
|
1672
1505
|
private codeInterpreter;
|
|
1673
1506
|
private sandboxName;
|
|
1507
|
+
private normalizeId;
|
|
1674
1508
|
private baseUrl;
|
|
1675
1509
|
private portTokens;
|
|
1676
1510
|
private defaultSession;
|
|
1677
1511
|
envVars: Record<string, string>;
|
|
1678
1512
|
private logger;
|
|
1679
1513
|
private keepAliveEnabled;
|
|
1514
|
+
private activeMounts;
|
|
1515
|
+
/**
|
|
1516
|
+
* Default container startup timeouts (conservative for production)
|
|
1517
|
+
* Based on Cloudflare docs: "Containers take several minutes to provision"
|
|
1518
|
+
*/
|
|
1519
|
+
private readonly DEFAULT_CONTAINER_TIMEOUTS;
|
|
1520
|
+
/**
|
|
1521
|
+
* Active container timeout configuration
|
|
1522
|
+
* Can be set via options, env vars, or defaults
|
|
1523
|
+
*/
|
|
1524
|
+
private containerTimeouts;
|
|
1680
1525
|
constructor(ctx: DurableObjectState<{}>, env: Env);
|
|
1681
|
-
setSandboxName(name: string): Promise<void>;
|
|
1526
|
+
setSandboxName(name: string, normalizeId?: boolean): Promise<void>;
|
|
1682
1527
|
setBaseUrl(baseUrl: string): Promise<void>;
|
|
1683
1528
|
setSleepAfter(sleepAfter: string | number): Promise<void>;
|
|
1684
1529
|
setKeepAlive(keepAlive: boolean): Promise<void>;
|
|
1685
1530
|
setEnvVars(envVars: Record<string, string>): Promise<void>;
|
|
1531
|
+
/**
|
|
1532
|
+
* RPC method to configure container startup timeouts
|
|
1533
|
+
*/
|
|
1534
|
+
setContainerTimeouts(timeouts: NonNullable<SandboxOptions['containerTimeouts']>): Promise<void>;
|
|
1535
|
+
/**
|
|
1536
|
+
* Validate a timeout value is within acceptable range
|
|
1537
|
+
* Throws error if invalid - used for user-provided values
|
|
1538
|
+
*/
|
|
1539
|
+
private validateTimeout;
|
|
1540
|
+
/**
|
|
1541
|
+
* Get default timeouts with env var fallbacks and validation
|
|
1542
|
+
* Precedence: SDK defaults < Env vars < User config
|
|
1543
|
+
*/
|
|
1544
|
+
private getDefaultTimeouts;
|
|
1545
|
+
mountBucket(bucket: string, mountPath: string, options: MountBucketOptions): Promise<void>;
|
|
1546
|
+
/**
|
|
1547
|
+
* Manually unmount a bucket filesystem
|
|
1548
|
+
*
|
|
1549
|
+
* @param mountPath - Absolute path where the bucket is mounted
|
|
1550
|
+
* @throws InvalidMountConfigError if mount path doesn't exist or isn't mounted
|
|
1551
|
+
*/
|
|
1552
|
+
unmountBucket(mountPath: string): Promise<void>;
|
|
1553
|
+
/**
|
|
1554
|
+
* Validate mount options
|
|
1555
|
+
*/
|
|
1556
|
+
private validateMountOptions;
|
|
1557
|
+
/**
|
|
1558
|
+
* Generate unique password file path for s3fs credentials
|
|
1559
|
+
*/
|
|
1560
|
+
private generatePasswordFilePath;
|
|
1561
|
+
/**
|
|
1562
|
+
* Create password file with s3fs credentials
|
|
1563
|
+
* Format: bucket:accessKeyId:secretAccessKey
|
|
1564
|
+
*/
|
|
1565
|
+
private createPasswordFile;
|
|
1566
|
+
/**
|
|
1567
|
+
* Delete password file
|
|
1568
|
+
*/
|
|
1569
|
+
private deletePasswordFile;
|
|
1570
|
+
/**
|
|
1571
|
+
* Execute S3FS mount command
|
|
1572
|
+
*/
|
|
1573
|
+
private executeS3FSMount;
|
|
1686
1574
|
/**
|
|
1687
1575
|
* Cleanup and destroy the sandbox container
|
|
1688
1576
|
*/
|
|
@@ -1695,6 +1583,19 @@ declare class Sandbox<Env = unknown> extends Container<Env> implements ISandbox
|
|
|
1695
1583
|
private checkVersionCompatibility;
|
|
1696
1584
|
onStop(): void;
|
|
1697
1585
|
onError(error: unknown): void;
|
|
1586
|
+
/**
|
|
1587
|
+
* Override Container.containerFetch to use production-friendly timeouts
|
|
1588
|
+
* Automatically starts container with longer timeouts if not running
|
|
1589
|
+
*/
|
|
1590
|
+
containerFetch(requestOrUrl: Request | string | URL, portOrInit?: number | RequestInit, portParam?: number): Promise<Response>;
|
|
1591
|
+
/**
|
|
1592
|
+
* Helper: Check if error is "no container instance available"
|
|
1593
|
+
*/
|
|
1594
|
+
private isNoInstanceError;
|
|
1595
|
+
/**
|
|
1596
|
+
* Helper: Parse containerFetch arguments (supports multiple signatures)
|
|
1597
|
+
*/
|
|
1598
|
+
private parseContainerFetchArgs;
|
|
1698
1599
|
/**
|
|
1699
1600
|
* Override onActivityExpired to prevent automatic shutdown when keepAlive is enabled
|
|
1700
1601
|
* When keepAlive is disabled, calls parent implementation which stops the container
|
|
@@ -1949,5 +1850,88 @@ declare function asyncIterableToSSEStream<T>(events: AsyncIterable<T>, options?:
|
|
|
1949
1850
|
serialize?: (event: T) => string;
|
|
1950
1851
|
}): ReadableStream<Uint8Array>;
|
|
1951
1852
|
//#endregion
|
|
1952
|
-
|
|
1853
|
+
//#region ../shared/dist/errors/codes.d.ts
|
|
1854
|
+
/**
|
|
1855
|
+
* Centralized error code registry
|
|
1856
|
+
* Each code maps to a specific error type with consistent semantics
|
|
1857
|
+
*/
|
|
1858
|
+
declare const ErrorCode: {
|
|
1859
|
+
readonly FILE_NOT_FOUND: "FILE_NOT_FOUND";
|
|
1860
|
+
readonly PERMISSION_DENIED: "PERMISSION_DENIED";
|
|
1861
|
+
readonly FILE_EXISTS: "FILE_EXISTS";
|
|
1862
|
+
readonly IS_DIRECTORY: "IS_DIRECTORY";
|
|
1863
|
+
readonly NOT_DIRECTORY: "NOT_DIRECTORY";
|
|
1864
|
+
readonly NO_SPACE: "NO_SPACE";
|
|
1865
|
+
readonly TOO_MANY_FILES: "TOO_MANY_FILES";
|
|
1866
|
+
readonly RESOURCE_BUSY: "RESOURCE_BUSY";
|
|
1867
|
+
readonly READ_ONLY: "READ_ONLY";
|
|
1868
|
+
readonly NAME_TOO_LONG: "NAME_TOO_LONG";
|
|
1869
|
+
readonly TOO_MANY_LINKS: "TOO_MANY_LINKS";
|
|
1870
|
+
readonly FILESYSTEM_ERROR: "FILESYSTEM_ERROR";
|
|
1871
|
+
readonly COMMAND_NOT_FOUND: "COMMAND_NOT_FOUND";
|
|
1872
|
+
readonly COMMAND_PERMISSION_DENIED: "COMMAND_PERMISSION_DENIED";
|
|
1873
|
+
readonly INVALID_COMMAND: "INVALID_COMMAND";
|
|
1874
|
+
readonly COMMAND_EXECUTION_ERROR: "COMMAND_EXECUTION_ERROR";
|
|
1875
|
+
readonly STREAM_START_ERROR: "STREAM_START_ERROR";
|
|
1876
|
+
readonly PROCESS_NOT_FOUND: "PROCESS_NOT_FOUND";
|
|
1877
|
+
readonly PROCESS_PERMISSION_DENIED: "PROCESS_PERMISSION_DENIED";
|
|
1878
|
+
readonly PROCESS_ERROR: "PROCESS_ERROR";
|
|
1879
|
+
readonly PORT_ALREADY_EXPOSED: "PORT_ALREADY_EXPOSED";
|
|
1880
|
+
readonly PORT_IN_USE: "PORT_IN_USE";
|
|
1881
|
+
readonly PORT_NOT_EXPOSED: "PORT_NOT_EXPOSED";
|
|
1882
|
+
readonly INVALID_PORT_NUMBER: "INVALID_PORT_NUMBER";
|
|
1883
|
+
readonly INVALID_PORT: "INVALID_PORT";
|
|
1884
|
+
readonly SERVICE_NOT_RESPONDING: "SERVICE_NOT_RESPONDING";
|
|
1885
|
+
readonly PORT_OPERATION_ERROR: "PORT_OPERATION_ERROR";
|
|
1886
|
+
readonly CUSTOM_DOMAIN_REQUIRED: "CUSTOM_DOMAIN_REQUIRED";
|
|
1887
|
+
readonly GIT_REPOSITORY_NOT_FOUND: "GIT_REPOSITORY_NOT_FOUND";
|
|
1888
|
+
readonly GIT_BRANCH_NOT_FOUND: "GIT_BRANCH_NOT_FOUND";
|
|
1889
|
+
readonly GIT_AUTH_FAILED: "GIT_AUTH_FAILED";
|
|
1890
|
+
readonly GIT_NETWORK_ERROR: "GIT_NETWORK_ERROR";
|
|
1891
|
+
readonly INVALID_GIT_URL: "INVALID_GIT_URL";
|
|
1892
|
+
readonly GIT_CLONE_FAILED: "GIT_CLONE_FAILED";
|
|
1893
|
+
readonly GIT_CHECKOUT_FAILED: "GIT_CHECKOUT_FAILED";
|
|
1894
|
+
readonly GIT_OPERATION_FAILED: "GIT_OPERATION_FAILED";
|
|
1895
|
+
readonly BUCKET_MOUNT_ERROR: "BUCKET_MOUNT_ERROR";
|
|
1896
|
+
readonly S3FS_MOUNT_ERROR: "S3FS_MOUNT_ERROR";
|
|
1897
|
+
readonly MISSING_CREDENTIALS: "MISSING_CREDENTIALS";
|
|
1898
|
+
readonly INVALID_MOUNT_CONFIG: "INVALID_MOUNT_CONFIG";
|
|
1899
|
+
readonly INTERPRETER_NOT_READY: "INTERPRETER_NOT_READY";
|
|
1900
|
+
readonly CONTEXT_NOT_FOUND: "CONTEXT_NOT_FOUND";
|
|
1901
|
+
readonly CODE_EXECUTION_ERROR: "CODE_EXECUTION_ERROR";
|
|
1902
|
+
readonly VALIDATION_FAILED: "VALIDATION_FAILED";
|
|
1903
|
+
readonly INVALID_JSON_RESPONSE: "INVALID_JSON_RESPONSE";
|
|
1904
|
+
readonly UNKNOWN_ERROR: "UNKNOWN_ERROR";
|
|
1905
|
+
readonly INTERNAL_ERROR: "INTERNAL_ERROR";
|
|
1906
|
+
};
|
|
1907
|
+
type ErrorCode = (typeof ErrorCode)[keyof typeof ErrorCode];
|
|
1908
|
+
//#endregion
|
|
1909
|
+
//#region src/storage-mount/errors.d.ts
|
|
1910
|
+
/**
|
|
1911
|
+
* Base error for bucket mounting operations
|
|
1912
|
+
*/
|
|
1913
|
+
declare class BucketMountError extends Error {
|
|
1914
|
+
readonly code: ErrorCode;
|
|
1915
|
+
constructor(message: string, code?: ErrorCode);
|
|
1916
|
+
}
|
|
1917
|
+
/**
|
|
1918
|
+
* Thrown when S3FS mount command fails
|
|
1919
|
+
*/
|
|
1920
|
+
declare class S3FSMountError extends BucketMountError {
|
|
1921
|
+
constructor(message: string);
|
|
1922
|
+
}
|
|
1923
|
+
/**
|
|
1924
|
+
* Thrown when no credentials found in environment
|
|
1925
|
+
*/
|
|
1926
|
+
declare class MissingCredentialsError extends BucketMountError {
|
|
1927
|
+
constructor(message: string);
|
|
1928
|
+
}
|
|
1929
|
+
/**
|
|
1930
|
+
* Thrown when bucket name, mount path, or options are invalid
|
|
1931
|
+
*/
|
|
1932
|
+
declare class InvalidMountConfigError extends BucketMountError {
|
|
1933
|
+
constructor(message: string);
|
|
1934
|
+
}
|
|
1935
|
+
//#endregion
|
|
1936
|
+
export { type BaseApiResponse, type BaseExecOptions, type BucketCredentials, BucketMountError, type BucketProvider, type CodeContext, CodeInterpreter, CommandClient, type ExecuteResponse as CommandExecuteResponse, type CommandsResponse, type ContainerStub, type CreateContextOptions, type CreateSessionRequest, type CreateSessionResponse, type DeleteSessionRequest, type DeleteSessionResponse, type ErrorResponse, type ExecEvent, type ExecOptions, type ExecResult, type ExecuteRequest, type ExecutionCallbacks, type ExecutionResult, type ExecutionSession, type ExposePortRequest, type FileChunk, FileClient, type FileMetadata, type FileOperationRequest, type FileStreamEvent, type GitCheckoutRequest, type GitCheckoutResult, GitClient, type ISandbox, type InterpreterClient, InvalidMountConfigError, type ListFilesOptions, type LogEvent, MissingCredentialsError, type MkdirRequest, type MountBucketOptions, type PingResponse, PortClient, type PortCloseResult, type PortExposeResult, type PortListResult, type Process, type ProcessCleanupResult, ProcessClient, type ProcessInfoResult, type ProcessKillResult, type ProcessListResult, type ProcessLogsResult, type ProcessOptions, type ProcessStartResult, type ProcessStatus, type ReadFileRequest, type RequestConfig, type ResponseHandler, type RouteInfo, type RunCodeOptions, S3FSMountError, Sandbox, SandboxClient, type HttpClientOptions as SandboxClientOptions, type SandboxEnv, type SandboxOptions, type SessionOptions, type SessionRequest, type StartProcessRequest, type StreamOptions, type UnexposePortRequest, UtilityClient, type WriteFileRequest, asyncIterableToSSEStream, collectFile, getSandbox, isExecResult, isProcess, isProcessStatus, parseSSEStream, proxyToSandbox, responseToAsyncIterable, streamFile };
|
|
1953
1937
|
//# sourceMappingURL=index.d.ts.map
|