@cloudflare/sandbox 0.0.0-037c848

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/src/index.ts ADDED
@@ -0,0 +1,136 @@
1
+ import { Container, getContainer } from "@cloudflare/containers";
2
+ import { HttpClient } from "./client";
3
+
4
+ export function getSandbox(ns: DurableObjectNamespace<Sandbox>, id: string) {
5
+ return getContainer(ns, id);
6
+ }
7
+
8
+ export class Sandbox<Env = unknown> extends Container<Env> {
9
+ defaultPort = 3000; // The default port for the container to listen on
10
+ sleepAfter = "3m"; // Sleep the sandbox if no requests are made in this timeframe
11
+ client: HttpClient;
12
+
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
+ }
36
+
37
+ envVars = {
38
+ MESSAGE: "I was passed in via the Sandbox class!",
39
+ };
40
+
41
+ override onStart() {
42
+ console.log("Sandbox successfully started");
43
+ }
44
+
45
+ override onStop() {
46
+ console.log("Sandbox successfully shut down");
47
+ if (this.client) {
48
+ this.client.clearSession();
49
+ }
50
+ }
51
+
52
+ override onError(error: unknown) {
53
+ console.log("Sandbox error:", error);
54
+ }
55
+
56
+ async exec(command: string, args: string[], options?: { stream?: boolean }) {
57
+ if (options?.stream) {
58
+ return this.client.executeStream(command, args);
59
+ }
60
+ return this.client.execute(command, args);
61
+ }
62
+
63
+ async gitCheckout(
64
+ repoUrl: string,
65
+ options: { branch?: string; targetDir?: string; stream?: boolean }
66
+ ) {
67
+ if (options?.stream) {
68
+ return this.client.gitCheckoutStream(
69
+ repoUrl,
70
+ options.branch,
71
+ options.targetDir
72
+ );
73
+ }
74
+ return this.client.gitCheckout(repoUrl, options.branch, options.targetDir);
75
+ }
76
+
77
+ async mkdir(
78
+ path: string,
79
+ options: { recursive?: boolean; stream?: boolean } = {}
80
+ ) {
81
+ if (options?.stream) {
82
+ return this.client.mkdirStream(path, options.recursive);
83
+ }
84
+ return this.client.mkdir(path, options.recursive);
85
+ }
86
+
87
+ async writeFile(
88
+ path: string,
89
+ content: string,
90
+ options: { encoding?: string; stream?: boolean } = {}
91
+ ) {
92
+ if (options?.stream) {
93
+ return this.client.writeFileStream(path, content, options.encoding);
94
+ }
95
+ return this.client.writeFile(path, content, options.encoding);
96
+ }
97
+
98
+ async deleteFile(path: string, options: { stream?: boolean } = {}) {
99
+ if (options?.stream) {
100
+ return this.client.deleteFileStream(path);
101
+ }
102
+ return this.client.deleteFile(path);
103
+ }
104
+
105
+ async renameFile(
106
+ oldPath: string,
107
+ newPath: string,
108
+ options: { stream?: boolean } = {}
109
+ ) {
110
+ if (options?.stream) {
111
+ return this.client.renameFileStream(oldPath, newPath);
112
+ }
113
+ return this.client.renameFile(oldPath, newPath);
114
+ }
115
+
116
+ async moveFile(
117
+ sourcePath: string,
118
+ destinationPath: string,
119
+ options: { stream?: boolean } = {}
120
+ ) {
121
+ if (options?.stream) {
122
+ return this.client.moveFileStream(sourcePath, destinationPath);
123
+ }
124
+ return this.client.moveFile(sourcePath, destinationPath);
125
+ }
126
+
127
+ async readFile(
128
+ path: string,
129
+ options: { encoding?: string; stream?: boolean } = {}
130
+ ) {
131
+ if (options?.stream) {
132
+ return this.client.readFileStream(path, options.encoding);
133
+ }
134
+ return this.client.readFile(path, options.encoding);
135
+ }
136
+ }
@@ -0,0 +1,308 @@
1
+ import {
2
+ createClient,
3
+ quickExecute,
4
+ quickExecuteStream,
5
+ quickGitCheckout,
6
+ quickGitCheckoutStream,
7
+ quickMkdir,
8
+ quickMkdirStream,
9
+ } from "../../sandbox/src/client";
10
+
11
+ // Example 1: Basic client usage
12
+ async function basicExample() {
13
+ console.log("=== Basic Client Example ===");
14
+
15
+ const client = createClient({
16
+ baseUrl: "http://localhost:3000",
17
+ onCommandComplete: (success, exitCode, stdout, stderr, command, args) => {
18
+ console.log(
19
+ `Command completed: ${command}, success=${success}, exitCode=${exitCode}`
20
+ );
21
+ if (stderr) console.log(`Stderr: ${stderr}`);
22
+ },
23
+ onCommandStart: (command, args) => {
24
+ console.log(`Starting command: ${command} ${args.join(" ")}`);
25
+ },
26
+ onError: (error, command, args) => {
27
+ console.error(`Error in ${command}: ${error}`);
28
+ },
29
+ onOutput: (stream, data, command) => {
30
+ console.log(`[${stream}] ${data}`);
31
+ },
32
+ });
33
+
34
+ try {
35
+ // Create a session
36
+ const sessionId = await client.createSession();
37
+ console.log(`Created session: ${sessionId}`);
38
+
39
+ // Execute some commands
40
+ const lsResult = await client.execute("ls", ["-la"]);
41
+ console.log("LS result:", lsResult.stdout);
42
+
43
+ const pwdResult = await client.ping();
44
+ console.log("Ping result:", pwdResult);
45
+
46
+ const commands = await client.getCommands();
47
+ console.log("Available commands:", commands.slice(0, 5));
48
+
49
+ // List sessions
50
+ const sessions = await client.listSessions();
51
+ console.log(`Active sessions: ${sessions.count}`);
52
+ } catch (error) {
53
+ console.error("Operation failed:", error);
54
+ } finally {
55
+ client.clearSession();
56
+ }
57
+ }
58
+
59
+ // Example 2: Streaming command execution
60
+ async function streamingExample() {
61
+ console.log("\n=== Streaming Command Example ===");
62
+
63
+ const client = createClient({
64
+ baseUrl: "http://localhost:3000",
65
+ onCommandComplete: (success, exitCode, stdout, stderr, command, args) => {
66
+ console.log(
67
+ `\n✅ Completed: ${command}, success=${success}, exitCode=${exitCode}`
68
+ );
69
+ },
70
+ onCommandStart: (command, args) => {
71
+ console.log(`🚀 Starting: ${command} ${args.join(" ")}`);
72
+ },
73
+ onOutput: (stream, data, command) => {
74
+ process.stdout.write(data);
75
+ },
76
+ });
77
+
78
+ try {
79
+ await client.createSession();
80
+
81
+ // Execute a long-running command with streaming
82
+ console.log("Executing 'find . -name '*.ts' -type f' with streaming...");
83
+ await client.executeStream("find", [".", "-name", "*.ts", "-type", "f"]);
84
+
85
+ console.log("\nExecuting 'ls -la' with streaming...");
86
+ await client.executeStream("ls", ["-la"]);
87
+ } catch (error) {
88
+ console.error("Streaming failed:", error);
89
+ } finally {
90
+ client.clearSession();
91
+ }
92
+ }
93
+
94
+ // Example 3: Git operations
95
+ async function gitExample() {
96
+ console.log("\n=== Git Operations Example ===");
97
+
98
+ const client = createClient({
99
+ baseUrl: "http://localhost:3000",
100
+ onCommandComplete: (success, exitCode, stdout, stderr, command, args) => {
101
+ console.log(`✅ Git operation completed: ${command}, success=${success}`);
102
+ },
103
+ onCommandStart: (command, args) => {
104
+ console.log(`🔧 Starting: ${command} ${args.join(" ")}`);
105
+ },
106
+ onOutput: (stream, data, command) => {
107
+ console.log(`[${stream}] ${data.trim()}`);
108
+ },
109
+ });
110
+
111
+ try {
112
+ await client.createSession();
113
+
114
+ // Create a directory for the repository
115
+ console.log("Creating directory for repository...");
116
+ const mkdirResult = await client.mkdir("test-repo", true);
117
+ console.log(`Directory created: ${mkdirResult.success}`);
118
+
119
+ // Checkout a small test repository
120
+ console.log("Checking out a test repository...");
121
+ const gitResult = await client.gitCheckout(
122
+ "https://github.com/octocat/Hello-World.git",
123
+ "main",
124
+ "test-repo/hello-world"
125
+ );
126
+ console.log(
127
+ `Repository cloned: ${gitResult.success}, target: ${gitResult.targetDir}`
128
+ );
129
+
130
+ // List the contents of the cloned repository
131
+ console.log("Listing repository contents...");
132
+ const lsResult = await client.execute("ls", [
133
+ "-la",
134
+ "test-repo/hello-world",
135
+ ]);
136
+ console.log("Repository contents:", lsResult.stdout);
137
+ } catch (error) {
138
+ console.error("Git operations failed:", error);
139
+ } finally {
140
+ client.clearSession();
141
+ }
142
+ }
143
+
144
+ // Example 4: Streaming git operations
145
+ async function streamingGitExample() {
146
+ console.log("\n=== Streaming Git Operations Example ===");
147
+
148
+ const client = createClient({
149
+ baseUrl: "http://localhost:3000",
150
+ onCommandComplete: (success, exitCode, stdout, stderr, command, args) => {
151
+ console.log(
152
+ `\n🎉 Git operation completed: ${command}, success=${success}`
153
+ );
154
+ },
155
+ onCommandStart: (command, args) => {
156
+ console.log(`🌐 Starting git operation: ${command} ${args.join(" ")}`);
157
+ },
158
+ onOutput: (stream, data, command) => {
159
+ if (stream === "stderr") {
160
+ process.stderr.write(data);
161
+ } else {
162
+ process.stdout.write(data);
163
+ }
164
+ },
165
+ });
166
+
167
+ try {
168
+ await client.createSession();
169
+
170
+ // Create directory with streaming
171
+ console.log("Creating directory with streaming...");
172
+ await client.mkdirStream("streaming-test", true);
173
+
174
+ // Checkout repository with streaming (real-time progress)
175
+ console.log("Checking out repository with streaming...");
176
+ await client.gitCheckoutStream(
177
+ "https://github.com/octocat/Hello-World.git",
178
+ "main",
179
+ "streaming-test/hello-world"
180
+ );
181
+ } catch (error) {
182
+ console.error("Streaming git operations failed:", error);
183
+ } finally {
184
+ client.clearSession();
185
+ }
186
+ }
187
+
188
+ // Example 5: Quick execute utilities
189
+ async function quickExecuteExample() {
190
+ console.log("\n=== Quick Execute Utilities Example ===");
191
+
192
+ try {
193
+ // Quick command execution
194
+ console.log("Quick command execution...");
195
+ const dateResult = await quickExecute("date");
196
+ console.log("Date:", dateResult.stdout.trim());
197
+
198
+ const whoamiResult = await quickExecute("whoami");
199
+ console.log("User:", whoamiResult.stdout.trim());
200
+
201
+ // Quick directory creation
202
+ console.log("Quick directory creation...");
203
+ const mkdirResult = await quickMkdir("quick-test", true);
204
+ console.log(`Directory created: ${mkdirResult.success}`);
205
+
206
+ // Quick git checkout
207
+ console.log("Quick git checkout...");
208
+ const gitResult = await quickGitCheckout(
209
+ "https://github.com/octocat/Hello-World.git",
210
+ "main",
211
+ "quick-test/repo"
212
+ );
213
+ console.log(`Repository cloned: ${gitResult.success}`);
214
+
215
+ // Quick streaming execution
216
+ console.log("Quick streaming execution...");
217
+ await quickExecuteStream("ls", ["-la", "quick-test"]);
218
+ } catch (error) {
219
+ console.error("Quick execute failed:", error);
220
+ }
221
+ }
222
+
223
+ // Example 6: Error handling
224
+ async function errorHandlingExample() {
225
+ console.log("\n=== Error Handling Example ===");
226
+
227
+ const client = createClient({
228
+ baseUrl: "http://localhost:3000",
229
+ onError: (error, command, args) => {
230
+ console.error(`❌ Error in ${command}: ${error}`);
231
+ },
232
+ });
233
+
234
+ try {
235
+ await client.createSession();
236
+
237
+ // Try to execute a non-existent command
238
+ console.log("Trying to execute non-existent command...");
239
+ try {
240
+ await client.execute("nonexistentcommand");
241
+ } catch (error) {
242
+ console.log(
243
+ "Expected error caught:",
244
+ error instanceof Error ? error.message : error
245
+ );
246
+ }
247
+
248
+ // Try to create a directory in a protected location
249
+ console.log("Trying to create directory in protected location...");
250
+ try {
251
+ await client.mkdir("/etc/test", false);
252
+ } catch (error) {
253
+ console.log(
254
+ "Expected error caught:",
255
+ error instanceof Error ? error.message : error
256
+ );
257
+ }
258
+
259
+ // Try to checkout an invalid repository
260
+ console.log("Trying to checkout invalid repository...");
261
+ try {
262
+ await client.gitCheckout("invalid-url");
263
+ } catch (error) {
264
+ console.log(
265
+ "Expected error caught:",
266
+ error instanceof Error ? error.message : error
267
+ );
268
+ }
269
+ } catch (error) {
270
+ console.error("Error handling example failed:", error);
271
+ } finally {
272
+ client.clearSession();
273
+ }
274
+ }
275
+
276
+ // Run examples
277
+ async function runExamples() {
278
+ console.log("🚀 HTTP Client Examples\n");
279
+
280
+ try {
281
+ await basicExample();
282
+ await streamingExample();
283
+ await gitExample();
284
+ await streamingGitExample();
285
+ await quickExecuteExample();
286
+ await errorHandlingExample();
287
+
288
+ console.log("\n✅ All examples completed!");
289
+ } catch (error) {
290
+ console.error("❌ Example failed:", error);
291
+ }
292
+ }
293
+
294
+ // Export for use in other modules
295
+ export {
296
+ createClient,
297
+ quickExecute,
298
+ quickExecuteStream,
299
+ quickGitCheckout,
300
+ quickMkdir,
301
+ quickGitCheckoutStream,
302
+ quickMkdirStream,
303
+ };
304
+
305
+ // Run examples if this file is executed directly
306
+ if (require.main === module) {
307
+ runExamples();
308
+ }
@@ -0,0 +1,81 @@
1
+ import { HttpClient } from "../../sandbox/src/client";
2
+
3
+ async function connectionTest() {
4
+ console.log("🔌 Testing HTTP Connection Only");
5
+
6
+ const client = new HttpClient({
7
+ baseUrl: "http://localhost:3000",
8
+ onCommandComplete: (
9
+ success: boolean,
10
+ exitCode: number,
11
+ stdout: string,
12
+ stderr: string,
13
+ command: string,
14
+ args: string[]
15
+ ) => {
16
+ console.log(
17
+ `✅ Command completed: ${command}, Success: ${success}, Exit code: ${exitCode}`
18
+ );
19
+ },
20
+ onCommandStart: (command: string, args: string[]) => {
21
+ console.log("📝 Command started:", command, args);
22
+ },
23
+ onError: (error: string, command?: string, args?: string[]) => {
24
+ console.error(`❌ Error: ${error}`);
25
+ },
26
+ onOutput: (stream: "stdout" | "stderr", data: string, command: string) => {
27
+ console.log(`📤 [${stream}] ${data.trim()}`);
28
+ },
29
+ });
30
+
31
+ try {
32
+ // Test ping to verify server is reachable
33
+ console.log("🏓 Testing ping...");
34
+ const pingResult = await client.ping();
35
+ console.log("✅ Ping successful:", pingResult);
36
+
37
+ // Create a session
38
+ console.log("🔗 Creating session...");
39
+ const sessionId = await client.createSession();
40
+ console.log("✅ Session created:", sessionId);
41
+
42
+ // Test getting available commands
43
+ console.log("📋 Getting available commands...");
44
+ const commands = await client.getCommands();
45
+ console.log("✅ Available commands:", commands.length);
46
+
47
+ // Test listing sessions
48
+ console.log("📝 Listing sessions...");
49
+ const sessions = await client.listSessions();
50
+ console.log("✅ Active sessions:", sessions.count);
51
+
52
+ // Wait a moment
53
+ await new Promise((resolve) => setTimeout(resolve, 1000));
54
+
55
+ console.log("✅ Connection test successful");
56
+ } catch (error) {
57
+ console.error("❌ Connection test failed:", error);
58
+ throw error;
59
+ } finally {
60
+ client.clearSession();
61
+ console.log("🔌 Session cleared");
62
+ }
63
+ }
64
+
65
+ // Add a timeout to prevent hanging
66
+ const timeout = setTimeout(() => {
67
+ console.error("❌ Connection test timed out after 15 seconds");
68
+ process.exit(1);
69
+ }, 15000);
70
+
71
+ connectionTest()
72
+ .then(() => {
73
+ clearTimeout(timeout);
74
+ console.log("✅ Connection test finished successfully");
75
+ process.exit(0);
76
+ })
77
+ .catch((error) => {
78
+ clearTimeout(timeout);
79
+ console.error("❌ Connection test failed:", error);
80
+ process.exit(1);
81
+ });
@@ -0,0 +1,81 @@
1
+ import {
2
+ HttpClient,
3
+ quickExecute,
4
+ quickExecuteStream,
5
+ } from "../../sandbox/src/client";
6
+
7
+ async function testHttpClient() {
8
+ console.log("🚀 Testing HTTP Client...\n");
9
+
10
+ // Create a client instance
11
+ const client = new HttpClient({
12
+ baseUrl: "http://localhost:3000",
13
+ onCommandComplete: (success, exitCode, stdout, stderr, command, args) => {
14
+ console.log(
15
+ `✅ Command completed: ${command}, Success: ${success}, Exit code: ${exitCode}`
16
+ );
17
+ },
18
+ onCommandStart: (command, args) => {
19
+ console.log(`📝 Command started: ${command} ${args.join(" ")}`);
20
+ },
21
+ onError: (error, command, args) => {
22
+ console.error(`❌ Command error: ${error}`);
23
+ },
24
+ onOutput: (stream, data, command) => {
25
+ console.log(`📤 [${stream}] ${data.trim()}`);
26
+ },
27
+ });
28
+
29
+ try {
30
+ // Test ping
31
+ console.log("1. Testing ping...");
32
+ const pingTime = await client.ping();
33
+ console.log(` Ping response time: ${pingTime}\n`);
34
+
35
+ // Test getting available commands
36
+ console.log("2. Testing get commands...");
37
+ const commands = await client.getCommands();
38
+ console.log(` Available commands: ${commands.join(", ")}\n`);
39
+
40
+ // Test session creation
41
+ console.log("3. Testing session creation...");
42
+ const sessionId = await client.createSession();
43
+ console.log(` Created session: ${sessionId}\n`);
44
+
45
+ // Test listing sessions
46
+ console.log("4. Testing session listing...");
47
+ const sessions = await client.listSessions();
48
+ console.log(` Active sessions: ${sessions.count}\n`);
49
+
50
+ // Test regular command execution
51
+ console.log("5. Testing regular command execution...");
52
+ const result = await client.execute("echo", ["Hello from HTTP client!"]);
53
+ console.log(` Command result: ${result.stdout.trim()}\n`);
54
+
55
+ // Test another command
56
+ console.log("6. Testing another command...");
57
+ const pwdResult = await client.execute("pwd");
58
+ console.log(` Current directory: ${pwdResult.stdout.trim()}\n`);
59
+
60
+ // Test streaming command execution
61
+ console.log("7. Testing streaming command execution...");
62
+ await client.executeStream("ls", ["-la"]);
63
+ console.log(" Streaming command completed\n");
64
+
65
+ // Test quick execute utility
66
+ console.log("8. Testing quick execute utility...");
67
+ const quickResult = await quickExecute("whoami");
68
+ console.log(` Quick execute result: ${quickResult.stdout.trim()}\n`);
69
+
70
+ console.log("🎉 All tests completed successfully!");
71
+ } catch (error) {
72
+ console.error("❌ Test failed:", error);
73
+ }
74
+ }
75
+
76
+ // Run the test if this file is executed directly
77
+ if (import.meta.main) {
78
+ testHttpClient().catch(console.error);
79
+ }
80
+
81
+ export { testHttpClient };