@cloudflare/sandbox 0.0.0-2b087c4 → 0.0.0-2f85e95
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/CHANGELOG.md +38 -0
- package/README.md +2 -0
- package/container_src/index.ts +8 -2
- package/package.json +5 -3
- package/src/client.ts +34 -3
- package/src/index.ts +30 -23
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,43 @@
|
|
|
1
1
|
# @cloudflare/sandbox
|
|
2
2
|
|
|
3
|
+
## 0.0.8
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`60af265`](https://github.com/cloudflare/sandbox-sdk/commit/60af265d834e83fd30a921a3e1be232f13fe24da) Thanks [@threepointone](https://github.com/threepointone)! - update dependencies
|
|
8
|
+
|
|
9
|
+
## 0.0.7
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- [`d1c7c99`](https://github.com/cloudflare/sandbox-sdk/commit/d1c7c99df6555eff71bcd59852e4b8eed2ad8cb6) Thanks [@threepointone](https://github.com/threepointone)! - fix file operations
|
|
14
|
+
|
|
15
|
+
## 0.0.6
|
|
16
|
+
|
|
17
|
+
### Patch Changes
|
|
18
|
+
|
|
19
|
+
- [#9](https://github.com/cloudflare/sandbox-sdk/pull/9) [`24f5470`](https://github.com/cloudflare/sandbox-sdk/commit/24f547048d5a26137de4656cea13d83ad2cc0b43) Thanks [@ItsWendell](https://github.com/ItsWendell)! - fix baseUrl for stub and stub forwarding
|
|
20
|
+
|
|
21
|
+
## 0.0.5
|
|
22
|
+
|
|
23
|
+
### Patch Changes
|
|
24
|
+
|
|
25
|
+
- [#5](https://github.com/cloudflare/sandbox-sdk/pull/5) [`7c15b81`](https://github.com/cloudflare/sandbox-sdk/commit/7c15b817899e4d9e1f25747aaf439e5e9e880d15) Thanks [@ghostwriternr](https://github.com/ghostwriternr)! - Make package ready for deployment
|
|
26
|
+
|
|
27
|
+
## 0.0.4
|
|
28
|
+
|
|
29
|
+
### Patch Changes
|
|
30
|
+
|
|
31
|
+
- [`c0d9d33`](https://github.com/cloudflare/sandbox-sdk/commit/c0d9d3396badee1eab45e6b4a73d48957f31409b) Thanks [@threepointone](https://github.com/threepointone)! - actually work
|
|
32
|
+
|
|
33
|
+
- [`444d2da`](https://github.com/cloudflare/sandbox-sdk/commit/444d2dafde9a0f190e50c879b0e768da1b289b51) Thanks [@threepointone](https://github.com/threepointone)! - add experimental label
|
|
34
|
+
|
|
35
|
+
## 0.0.3
|
|
36
|
+
|
|
37
|
+
### Patch Changes
|
|
38
|
+
|
|
39
|
+
- [`2b087c4`](https://github.com/cloudflare/sandbox-sdk/commit/2b087c40a29697c20dad19b4e3b8512f5d404bd3) Thanks [@ghostwriternr](https://github.com/ghostwriternr)! - Fix worker unable to find container port
|
|
40
|
+
|
|
3
41
|
## 0.0.2
|
|
4
42
|
|
|
5
43
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
## @cloudflare/sandbox
|
|
2
2
|
|
|
3
|
+
> **⚠️ Experimental** - This library is currently experimental and we're actively seeking feedback. Please try it out and let us know what you think!
|
|
4
|
+
|
|
3
5
|
A library to spin up a sandboxed environment.
|
|
4
6
|
|
|
5
7
|
First, setup your wrangler.json to use the sandbox:
|
package/container_src/index.ts
CHANGED
|
@@ -84,6 +84,8 @@ const server = serve({
|
|
|
84
84
|
const url = new URL(req.url);
|
|
85
85
|
const pathname = url.pathname;
|
|
86
86
|
|
|
87
|
+
console.log(`[Container] Incoming ${req.method} request to ${pathname}`);
|
|
88
|
+
|
|
87
89
|
// Handle CORS
|
|
88
90
|
const corsHeaders = {
|
|
89
91
|
"Access-Control-Allow-Headers": "Content-Type, Authorization",
|
|
@@ -93,11 +95,13 @@ const server = serve({
|
|
|
93
95
|
|
|
94
96
|
// Handle preflight requests
|
|
95
97
|
if (req.method === "OPTIONS") {
|
|
98
|
+
console.log(`[Container] Handling CORS preflight for ${pathname}`);
|
|
96
99
|
return new Response(null, { headers: corsHeaders, status: 200 });
|
|
97
100
|
}
|
|
98
101
|
|
|
99
102
|
try {
|
|
100
103
|
// Handle different routes
|
|
104
|
+
console.log(`[Container] Processing ${req.method} ${pathname}`);
|
|
101
105
|
switch (pathname) {
|
|
102
106
|
case "/":
|
|
103
107
|
return new Response("Hello from Bun server! 🚀", {
|
|
@@ -352,13 +356,14 @@ const server = serve({
|
|
|
352
356
|
break;
|
|
353
357
|
|
|
354
358
|
default:
|
|
359
|
+
console.log(`[Container] Route not found: ${pathname}`);
|
|
355
360
|
return new Response("Not Found", {
|
|
356
361
|
headers: corsHeaders,
|
|
357
362
|
status: 404,
|
|
358
363
|
});
|
|
359
364
|
}
|
|
360
365
|
} catch (error) {
|
|
361
|
-
console.error(
|
|
366
|
+
console.error(`[Container] Error handling ${req.method} ${pathname}:`, error);
|
|
362
367
|
return new Response(
|
|
363
368
|
JSON.stringify({
|
|
364
369
|
error: "Internal server error",
|
|
@@ -374,6 +379,7 @@ const server = serve({
|
|
|
374
379
|
);
|
|
375
380
|
}
|
|
376
381
|
},
|
|
382
|
+
hostname: "0.0.0.0",
|
|
377
383
|
port: 3000,
|
|
378
384
|
} as any);
|
|
379
385
|
|
|
@@ -2874,7 +2880,7 @@ function executeMoveFile(
|
|
|
2874
2880
|
});
|
|
2875
2881
|
}
|
|
2876
2882
|
|
|
2877
|
-
console.log(`🚀 Bun server running on http://
|
|
2883
|
+
console.log(`🚀 Bun server running on http://0.0.0.0:${server.port}`);
|
|
2878
2884
|
console.log(`📡 HTTP API endpoints available:`);
|
|
2879
2885
|
console.log(` POST /api/session/create - Create a new session`);
|
|
2880
2886
|
console.log(` GET /api/session/list - List all sessions`);
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cloudflare/sandbox",
|
|
3
|
-
"version": "0.0.0-
|
|
3
|
+
"version": "0.0.0-2f85e95",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/cloudflare/sandbox-sdk"
|
|
7
7
|
},
|
|
8
8
|
"description": "A sandboxed environment for running commands",
|
|
9
9
|
"dependencies": {
|
|
10
|
-
"@cloudflare/containers": "^0.0.
|
|
10
|
+
"@cloudflare/containers": "^0.0.19"
|
|
11
11
|
},
|
|
12
12
|
"tags": [
|
|
13
13
|
"sandbox",
|
|
@@ -17,7 +17,9 @@
|
|
|
17
17
|
"durable objects"
|
|
18
18
|
],
|
|
19
19
|
"scripts": {
|
|
20
|
-
"build": "tsup src/*.ts --outDir dist --dts --sourcemap --format esm"
|
|
20
|
+
"build": "rm -rf dist && tsup src/*.ts --outDir dist --dts --sourcemap --format esm",
|
|
21
|
+
"docker:build": "docker build -t ghostwriternr/cloudflare-sandbox:$npm_package_version .",
|
|
22
|
+
"docker:publish": "docker push docker.io/ghostwriternr/cloudflare-sandbox:$npm_package_version"
|
|
21
23
|
},
|
|
22
24
|
"exports": {
|
|
23
25
|
".": {
|
package/src/client.ts
CHANGED
|
@@ -203,10 +203,41 @@ export class HttpClient {
|
|
|
203
203
|
path: string,
|
|
204
204
|
options?: RequestInit
|
|
205
205
|
): Promise<Response> {
|
|
206
|
-
|
|
207
|
-
|
|
206
|
+
const url = this.options.stub
|
|
207
|
+
? `http://localhost:${this.options.port}${path}`
|
|
208
|
+
: `${this.baseUrl}${path}`;
|
|
209
|
+
const method = options?.method || "GET";
|
|
210
|
+
|
|
211
|
+
console.log(`[HTTP Client] Making ${method} request to ${url}`);
|
|
212
|
+
|
|
213
|
+
try {
|
|
214
|
+
let response: Response;
|
|
215
|
+
|
|
216
|
+
if (this.options.stub) {
|
|
217
|
+
response = await this.options.stub.containerFetch(
|
|
218
|
+
url,
|
|
219
|
+
options,
|
|
220
|
+
this.options.port
|
|
221
|
+
);
|
|
222
|
+
} else {
|
|
223
|
+
response = await fetch(url, options);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
console.log(
|
|
227
|
+
`[HTTP Client] Response: ${response.status} ${response.statusText}`
|
|
228
|
+
);
|
|
229
|
+
|
|
230
|
+
if (!response.ok) {
|
|
231
|
+
console.error(
|
|
232
|
+
`[HTTP Client] Request failed: ${method} ${url} - ${response.status} ${response.statusText}`
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
return response;
|
|
237
|
+
} catch (error) {
|
|
238
|
+
console.error(`[HTTP Client] Request error: ${method} ${url}`, error);
|
|
239
|
+
throw error;
|
|
208
240
|
}
|
|
209
|
-
return fetch(this.baseUrl + path, options);
|
|
210
241
|
}
|
|
211
242
|
// Public methods to set event handlers
|
|
212
243
|
setOnOutput(
|
package/src/index.ts
CHANGED
|
@@ -8,24 +8,31 @@ export function getSandbox(ns: DurableObjectNamespace<Sandbox>, id: string) {
|
|
|
8
8
|
export class Sandbox<Env = unknown> extends Container<Env> {
|
|
9
9
|
defaultPort = 3000; // The default port for the container to listen on
|
|
10
10
|
sleepAfter = "3m"; // Sleep the sandbox if no requests are made in this timeframe
|
|
11
|
+
client: HttpClient;
|
|
11
12
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
13
|
+
constructor(ctx: DurableObjectState, env: Env) {
|
|
14
|
+
super(ctx, env);
|
|
15
|
+
this.client = new HttpClient({
|
|
16
|
+
onCommandComplete: (success, exitCode, stdout, stderr, command, args) => {
|
|
17
|
+
console.log(
|
|
18
|
+
`[Container] Command completed: ${command}, Success: ${success}, Exit code: ${exitCode}`
|
|
19
|
+
);
|
|
20
|
+
},
|
|
21
|
+
onCommandStart: (command, args) => {
|
|
22
|
+
console.log(
|
|
23
|
+
`[Container] Command started: ${command} ${args.join(" ")}`
|
|
24
|
+
);
|
|
25
|
+
},
|
|
26
|
+
onError: (error, command, args) => {
|
|
27
|
+
console.error(`[Container] Command error: ${error}`);
|
|
28
|
+
},
|
|
29
|
+
onOutput: (stream, data, command) => {
|
|
30
|
+
console.log(`[Container] [${stream}] ${data}`);
|
|
31
|
+
},
|
|
32
|
+
port: this.defaultPort,
|
|
33
|
+
stub: this,
|
|
34
|
+
});
|
|
35
|
+
}
|
|
29
36
|
|
|
30
37
|
envVars = {
|
|
31
38
|
MESSAGE: "I was passed in via the Sandbox class!",
|
|
@@ -69,7 +76,7 @@ export class Sandbox<Env = unknown> extends Container<Env> {
|
|
|
69
76
|
|
|
70
77
|
async mkdir(
|
|
71
78
|
path: string,
|
|
72
|
-
options: { recursive?: boolean; stream?: boolean }
|
|
79
|
+
options: { recursive?: boolean; stream?: boolean } = {}
|
|
73
80
|
) {
|
|
74
81
|
if (options?.stream) {
|
|
75
82
|
return this.client.mkdirStream(path, options.recursive);
|
|
@@ -80,7 +87,7 @@ export class Sandbox<Env = unknown> extends Container<Env> {
|
|
|
80
87
|
async writeFile(
|
|
81
88
|
path: string,
|
|
82
89
|
content: string,
|
|
83
|
-
options: { encoding?: string; stream?: boolean }
|
|
90
|
+
options: { encoding?: string; stream?: boolean } = {}
|
|
84
91
|
) {
|
|
85
92
|
if (options?.stream) {
|
|
86
93
|
return this.client.writeFileStream(path, content, options.encoding);
|
|
@@ -88,7 +95,7 @@ export class Sandbox<Env = unknown> extends Container<Env> {
|
|
|
88
95
|
return this.client.writeFile(path, content, options.encoding);
|
|
89
96
|
}
|
|
90
97
|
|
|
91
|
-
async deleteFile(path: string, options: { stream?: boolean }) {
|
|
98
|
+
async deleteFile(path: string, options: { stream?: boolean } = {}) {
|
|
92
99
|
if (options?.stream) {
|
|
93
100
|
return this.client.deleteFileStream(path);
|
|
94
101
|
}
|
|
@@ -98,7 +105,7 @@ export class Sandbox<Env = unknown> extends Container<Env> {
|
|
|
98
105
|
async renameFile(
|
|
99
106
|
oldPath: string,
|
|
100
107
|
newPath: string,
|
|
101
|
-
options: { stream?: boolean }
|
|
108
|
+
options: { stream?: boolean } = {}
|
|
102
109
|
) {
|
|
103
110
|
if (options?.stream) {
|
|
104
111
|
return this.client.renameFileStream(oldPath, newPath);
|
|
@@ -109,7 +116,7 @@ export class Sandbox<Env = unknown> extends Container<Env> {
|
|
|
109
116
|
async moveFile(
|
|
110
117
|
sourcePath: string,
|
|
111
118
|
destinationPath: string,
|
|
112
|
-
options: { stream?: boolean }
|
|
119
|
+
options: { stream?: boolean } = {}
|
|
113
120
|
) {
|
|
114
121
|
if (options?.stream) {
|
|
115
122
|
return this.client.moveFileStream(sourcePath, destinationPath);
|
|
@@ -119,7 +126,7 @@ export class Sandbox<Env = unknown> extends Container<Env> {
|
|
|
119
126
|
|
|
120
127
|
async readFile(
|
|
121
128
|
path: string,
|
|
122
|
-
options: { encoding?: string; stream?: boolean }
|
|
129
|
+
options: { encoding?: string; stream?: boolean } = {}
|
|
123
130
|
) {
|
|
124
131
|
if (options?.stream) {
|
|
125
132
|
return this.client.readFileStream(path, options.encoding);
|