@cloudflare/sandbox 0.0.0-1a42464 → 0.0.0-1ab3f9d
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 +18 -0
- package/Dockerfile +2 -5
- package/README.md +3 -5
- package/container_src/handler/exec.ts +14 -13
- package/container_src/types.ts +8 -3
- package/package.json +1 -1
- package/src/client.ts +11 -11
- package/src/sandbox.ts +5 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# @cloudflare/sandbox
|
|
2
2
|
|
|
3
|
+
## 0.1.4
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#46](https://github.com/cloudflare/sandbox-sdk/pull/46) [`7de28be`](https://github.com/cloudflare/sandbox-sdk/commit/7de28be482d9634551572d548c7c4b5842df812d) Thanks [@ghostwriternr](https://github.com/ghostwriternr)! - Update README
|
|
8
|
+
|
|
9
|
+
- [#44](https://github.com/cloudflare/sandbox-sdk/pull/44) [`215ab49`](https://github.com/cloudflare/sandbox-sdk/commit/215ab494427d7e2a92bb9a25384cb493a221c200) Thanks [@ghostwriternr](https://github.com/ghostwriternr)! - Update example to use env & cwd
|
|
10
|
+
|
|
11
|
+
- [#42](https://github.com/cloudflare/sandbox-sdk/pull/42) [`bb72193`](https://github.com/cloudflare/sandbox-sdk/commit/bb72193ad75695979bd1132206f481e91fe37325) Thanks [@jonasnobile](https://github.com/jonasnobile)! - Propagate `cwd` and `env` options in `executeCommand`
|
|
12
|
+
|
|
13
|
+
- [#27](https://github.com/cloudflare/sandbox-sdk/pull/27) [`fd5ec7f`](https://github.com/cloudflare/sandbox-sdk/commit/fd5ec7f34bc12b06320a89356c4af07801f52d64) Thanks [@threepointone](https://github.com/threepointone)! - remove yarn and pnpm from the image
|
|
14
|
+
|
|
15
|
+
## 0.1.3
|
|
16
|
+
|
|
17
|
+
### Patch Changes
|
|
18
|
+
|
|
19
|
+
- [#32](https://github.com/cloudflare/sandbox-sdk/pull/32) [`1a42464`](https://github.com/cloudflare/sandbox-sdk/commit/1a4246479369c5d0160705caf192aa1816540d52) Thanks [@ghostwriternr](https://github.com/ghostwriternr)! - Bring back package README
|
|
20
|
+
|
|
3
21
|
## 0.1.2
|
|
4
22
|
|
|
5
23
|
### Patch Changes
|
package/Dockerfile
CHANGED
|
@@ -55,8 +55,6 @@ RUN apt-get update && apt-get install -y ca-certificates curl gnupg \
|
|
|
55
55
|
COPY --from=bun-source /usr/local/bin/bun /usr/local/bin/bun
|
|
56
56
|
COPY --from=bun-source /usr/local/bin/bunx /usr/local/bin/bunx
|
|
57
57
|
|
|
58
|
-
# Install global npm packages as root
|
|
59
|
-
RUN npm install -g yarn pnpm
|
|
60
58
|
|
|
61
59
|
# Set up working directory
|
|
62
60
|
WORKDIR /app
|
|
@@ -65,9 +63,8 @@ WORKDIR /app
|
|
|
65
63
|
RUN python3 --version && \
|
|
66
64
|
node --version && \
|
|
67
65
|
npm --version && \
|
|
68
|
-
bun --version
|
|
69
|
-
|
|
70
|
-
pnpm --version
|
|
66
|
+
bun --version
|
|
67
|
+
|
|
71
68
|
|
|
72
69
|
# Copy container source files
|
|
73
70
|
COPY container_src/ ./
|
package/README.md
CHANGED
|
@@ -64,12 +64,10 @@ npm install @cloudflare/sandbox
|
|
|
64
64
|
1. **Create a Dockerfile** (temporary requirement, will be removed in future releases):
|
|
65
65
|
|
|
66
66
|
```dockerfile
|
|
67
|
-
FROM docker.io/cloudflare/sandbox:0.1.
|
|
67
|
+
FROM docker.io/cloudflare/sandbox:0.1.4
|
|
68
68
|
|
|
69
|
+
# Expose the ports you want to expose
|
|
69
70
|
EXPOSE 3000
|
|
70
|
-
|
|
71
|
-
# Run the same command as the original image
|
|
72
|
-
CMD ["bun", "index.ts"]
|
|
73
71
|
```
|
|
74
72
|
|
|
75
73
|
2. **Configure wrangler.json**:
|
|
@@ -284,7 +282,7 @@ The SDK handles:
|
|
|
284
282
|
|
|
285
283
|
```dockerfile
|
|
286
284
|
# In your Dockerfile (only needed for local dev)
|
|
287
|
-
FROM
|
|
285
|
+
FROM docker.io/cloudflare/sandbox:0.1.3
|
|
288
286
|
|
|
289
287
|
# Expose the ports you'll be using
|
|
290
288
|
EXPOSE 3000 # For a web server
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { type SpawnOptions, spawn } from "node:child_process";
|
|
2
|
-
import type { ExecuteRequest, SessionData } from "../types";
|
|
2
|
+
import type { ExecuteOptions, ExecuteRequest, SessionData } from "../types";
|
|
3
3
|
|
|
4
4
|
function executeCommand(
|
|
5
5
|
sessions: Map<string, SessionData>,
|
|
6
6
|
command: string,
|
|
7
|
-
|
|
8
|
-
background?: boolean
|
|
7
|
+
options: ExecuteOptions,
|
|
9
8
|
): Promise<{
|
|
10
9
|
success: boolean;
|
|
11
10
|
stdout: string;
|
|
@@ -16,14 +15,16 @@ function executeCommand(
|
|
|
16
15
|
const spawnOptions: SpawnOptions = {
|
|
17
16
|
shell: true,
|
|
18
17
|
stdio: ["pipe", "pipe", "pipe"] as const,
|
|
19
|
-
detached: background || false,
|
|
18
|
+
detached: options.background || false,
|
|
19
|
+
cwd: options.cwd,
|
|
20
|
+
env: options.env ? { ...process.env, ...options.env } : process.env
|
|
20
21
|
};
|
|
21
22
|
|
|
22
23
|
const child = spawn(command, spawnOptions);
|
|
23
24
|
|
|
24
25
|
// Store the process reference for cleanup if sessionId is provided
|
|
25
|
-
if (sessionId && sessions.has(sessionId)) {
|
|
26
|
-
const session = sessions.get(sessionId)!;
|
|
26
|
+
if (options.sessionId && sessions.has(options.sessionId)) {
|
|
27
|
+
const session = sessions.get(options.sessionId)!;
|
|
27
28
|
session.activeProcess = child;
|
|
28
29
|
}
|
|
29
30
|
|
|
@@ -38,7 +39,7 @@ function executeCommand(
|
|
|
38
39
|
stderr += data.toString();
|
|
39
40
|
});
|
|
40
41
|
|
|
41
|
-
if (background) {
|
|
42
|
+
if (options.background) {
|
|
42
43
|
// For background processes, unref and return quickly
|
|
43
44
|
child.unref();
|
|
44
45
|
|
|
@@ -61,8 +62,8 @@ function executeCommand(
|
|
|
61
62
|
// Normal synchronous execution
|
|
62
63
|
child.on("close", (code) => {
|
|
63
64
|
// Clear the active process reference
|
|
64
|
-
if (sessionId && sessions.has(sessionId)) {
|
|
65
|
-
const session = sessions.get(sessionId)!;
|
|
65
|
+
if (options.sessionId && sessions.has(options.sessionId)) {
|
|
66
|
+
const session = sessions.get(options.sessionId)!;
|
|
66
67
|
session.activeProcess = null;
|
|
67
68
|
}
|
|
68
69
|
|
|
@@ -78,8 +79,8 @@ function executeCommand(
|
|
|
78
79
|
|
|
79
80
|
child.on("error", (error) => {
|
|
80
81
|
// Clear the active process reference
|
|
81
|
-
if (sessionId && sessions.has(sessionId)) {
|
|
82
|
-
const session = sessions.get(sessionId)!;
|
|
82
|
+
if (options.sessionId && sessions.has(options.sessionId)) {
|
|
83
|
+
const session = sessions.get(options.sessionId)!;
|
|
83
84
|
session.activeProcess = null;
|
|
84
85
|
}
|
|
85
86
|
|
|
@@ -96,7 +97,7 @@ export async function handleExecuteRequest(
|
|
|
96
97
|
): Promise<Response> {
|
|
97
98
|
try {
|
|
98
99
|
const body = (await req.json()) as ExecuteRequest;
|
|
99
|
-
const { command, sessionId, background } = body;
|
|
100
|
+
const { command, sessionId, background, cwd, env } = body;
|
|
100
101
|
|
|
101
102
|
if (!command || typeof command !== "string") {
|
|
102
103
|
return new Response(
|
|
@@ -115,7 +116,7 @@ export async function handleExecuteRequest(
|
|
|
115
116
|
|
|
116
117
|
console.log(`[Server] Executing command: ${command}`);
|
|
117
118
|
|
|
118
|
-
const result = await executeCommand(sessions, command, sessionId, background);
|
|
119
|
+
const result = await executeCommand(sessions, command, { sessionId, background, cwd, env });
|
|
119
120
|
|
|
120
121
|
return new Response(
|
|
121
122
|
JSON.stringify({
|
package/container_src/types.ts
CHANGED
|
@@ -38,10 +38,15 @@ export interface StartProcessRequest {
|
|
|
38
38
|
};
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
export interface
|
|
42
|
-
|
|
43
|
-
sessionId?: string;
|
|
41
|
+
export interface ExecuteOptions {
|
|
42
|
+
sessionId?: string | null;
|
|
44
43
|
background?: boolean;
|
|
44
|
+
cwd?: string | URL;
|
|
45
|
+
env?: Record<string, string>;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export interface ExecuteRequest extends ExecuteOptions {
|
|
49
|
+
command: string;
|
|
45
50
|
}
|
|
46
51
|
|
|
47
52
|
export interface GitCheckoutRequest {
|
package/package.json
CHANGED
package/src/client.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import type { ExecuteRequest } from "../container_src/types";
|
|
1
2
|
import type { Sandbox } from "./index";
|
|
2
3
|
import type {
|
|
4
|
+
BaseExecOptions,
|
|
3
5
|
GetProcessLogsResponse,
|
|
4
6
|
GetProcessResponse,
|
|
5
7
|
ListProcessesResponse,
|
|
@@ -7,11 +9,6 @@ import type {
|
|
|
7
9
|
StartProcessResponse
|
|
8
10
|
} from "./types";
|
|
9
11
|
|
|
10
|
-
interface ExecuteRequest {
|
|
11
|
-
command: string;
|
|
12
|
-
sessionId?: string;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
12
|
export interface ExecuteResponse {
|
|
16
13
|
success: boolean;
|
|
17
14
|
stdout: string;
|
|
@@ -255,16 +252,19 @@ export class HttpClient {
|
|
|
255
252
|
|
|
256
253
|
async execute(
|
|
257
254
|
command: string,
|
|
258
|
-
sessionId
|
|
255
|
+
options: Pick<BaseExecOptions, 'sessionId' | 'cwd' | 'env'>
|
|
259
256
|
): Promise<ExecuteResponse> {
|
|
260
257
|
try {
|
|
261
|
-
const targetSessionId = sessionId || this.sessionId;
|
|
258
|
+
const targetSessionId = options.sessionId || this.sessionId;
|
|
259
|
+
const executeRequest = {
|
|
260
|
+
command,
|
|
261
|
+
sessionId: targetSessionId,
|
|
262
|
+
cwd: options.cwd,
|
|
263
|
+
env: options.env,
|
|
264
|
+
} satisfies ExecuteRequest;
|
|
262
265
|
|
|
263
266
|
const response = await this.doFetch(`/api/execute`, {
|
|
264
|
-
body: JSON.stringify(
|
|
265
|
-
command,
|
|
266
|
-
sessionId: targetSessionId,
|
|
267
|
-
} as ExecuteRequest),
|
|
267
|
+
body: JSON.stringify(executeRequest),
|
|
268
268
|
headers: {
|
|
269
269
|
"Content-Type": "application/json",
|
|
270
270
|
},
|
package/src/sandbox.ts
CHANGED
|
@@ -150,7 +150,11 @@ export class Sandbox<Env = unknown> extends Container<Env> implements ISandbox {
|
|
|
150
150
|
// Regular execution
|
|
151
151
|
const response = await this.client.execute(
|
|
152
152
|
command,
|
|
153
|
-
|
|
153
|
+
{
|
|
154
|
+
sessionId: options?.sessionId,
|
|
155
|
+
cwd: options?.cwd,
|
|
156
|
+
env: options?.env,
|
|
157
|
+
}
|
|
154
158
|
);
|
|
155
159
|
|
|
156
160
|
const duration = Date.now() - startTime;
|