Skip to content

Commit 6a2c669

Browse files
committed
Update README
1 parent cecde0a commit 6a2c669

File tree

3 files changed

+211
-435
lines changed

3 files changed

+211
-435
lines changed

README.md

Lines changed: 138 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ export default {
9898
const sandbox = getSandbox(env.Sandbox, "my-sandbox");
9999

100100
// Execute a command
101-
const result = await sandbox.exec("echo", ["Hello from the edge!"]);
101+
const result = await sandbox.exec("echo 'Hello from the edge!'");
102102
return new Response(result.stdout);
103103
},
104104
};
@@ -108,13 +108,51 @@ export default {
108108

109109
### Core Methods
110110

111-
#### `exec(command, args, options?)`
111+
#### Command Execution
112112

113-
Execute a command in the sandbox.
113+
**`exec(command, options?)`** - Enhanced command execution that always returns results
114114

115115
```typescript
116-
const result = await sandbox.exec("npm", ["install", "express"]);
117-
console.log(result.stdout);
116+
// Simple execution
117+
const result = await sandbox.exec("npm install express");
118+
console.log(result.stdout, result.exitCode);
119+
120+
// With streaming callbacks
121+
const result = await sandbox.exec("npm run build", {
122+
stream: true,
123+
onOutput: (stream, data) => console.log(`[${stream}] ${data}`)
124+
});
125+
```
126+
127+
**`execStream(command, options?)`** - Dedicated streaming method returning SSE stream
128+
129+
```typescript
130+
import { parseSSEStream, type ExecEvent } from '@cloudflare/sandbox';
131+
132+
const stream = await sandbox.execStream("npm run test");
133+
for await (const event of parseSSEStream<ExecEvent>(stream)) {
134+
switch (event.type) {
135+
case 'stdout':
136+
console.log(`Test output: ${event.data}`);
137+
break;
138+
case 'complete':
139+
console.log(`Tests ${event.exitCode === 0 ? 'passed' : 'failed'}`);
140+
break;
141+
}
142+
}
143+
```
144+
145+
**`startProcess(command, options?)`** - Start background processes with lifecycle management
146+
147+
```typescript
148+
const process = await sandbox.startProcess("node server.js");
149+
console.log(`Started process ${process.id} with PID ${process.pid}`);
150+
151+
// Monitor the process
152+
const logStream = await sandbox.streamProcessLogs(process.id);
153+
for await (const log of parseSSEStream<LogEvent>(logStream)) {
154+
console.log(`Server: ${log.data}`);
155+
}
118156
```
119157

120158
#### `writeFile(path, content, options?)`
@@ -145,16 +183,26 @@ await sandbox.gitCheckout("https://github.com/user/repo", {
145183
});
146184
```
147185

148-
### File System Methods
186+
#### Process Management
187+
188+
- `listProcesses()` - List all running processes
189+
- `getProcess(id)` - Get detailed process status
190+
- `killProcess(id, signal?)` - Terminate specific processes
191+
- `killAllProcesses()` - Kill all processes
192+
- `streamProcessLogs(id, options?)` - Stream logs from running processes
193+
- `getProcessLogs(id)` - Get accumulated process output
194+
195+
#### File System Methods
149196

150197
- `writeFile(path, content, options?)` - Write content to a file
151198
- `readFile(path, options?)` - Read a file from the sandbox
152199
- `mkdir(path, options?)` - Create a directory
153200
- `deleteFile(path)` - Delete a file
154201
- `renameFile(oldPath, newPath)` - Rename a file
155202
- `moveFile(sourcePath, destinationPath)` - Move a file
203+
- `gitCheckout(repoUrl, options?)` - Clone git repositories
156204

157-
### Network Methods
205+
#### Network Methods
158206

159207
- `exposePort(port, options?)` - Expose a port and get a public URL
160208
- `unexposePort(port)` - Remove port exposure
@@ -188,8 +236,7 @@ console.log(preview.url); // https://3000-sandbox-id.your-worker.dev
188236

189237
The SDK handles:
190238

191-
- Production subdomain routing (`3000-sandbox-id.domain.com`)
192-
- Local development routing (`localhost:8787/preview/3000/sandbox-id`)
239+
- Subdomain routing (`3000-sandbox-id.domain.com`) for both production and local development
193240
- All localhost variants (127.0.0.1, ::1, etc.)
194241
- Request forwarding with proper headers
195242

@@ -243,9 +290,9 @@ await sandbox.writeFile(
243290
);
244291

245292
// Install dependencies and start the server
246-
await sandbox.exec("npm", ["init", "-y"]);
247-
await sandbox.exec("npm", ["install", "express"]);
248-
await sandbox.exec("node", ["app.js"]);
293+
await sandbox.exec("npm init -y");
294+
await sandbox.exec("npm install express");
295+
const server = await sandbox.startProcess("node app.js");
249296

250297
// Expose it to the internet
251298
const preview = await sandbox.exposePort(3000);
@@ -261,10 +308,10 @@ const sandbox = getSandbox(env.Sandbox, "test-env");
261308
await sandbox.gitCheckout("https://github.com/user/project");
262309

263310
// Run tests
264-
const testResult = await sandbox.exec("npm", ["test"]);
311+
const testResult = await sandbox.exec("npm test");
265312

266313
// Build the project
267-
const buildResult = await sandbox.exec("npm", ["run", "build"]);
314+
const buildResult = await sandbox.exec("npm run build");
268315

269316
return new Response(
270317
JSON.stringify({
@@ -283,10 +330,10 @@ const sandbox = getSandbox(env.Sandbox, "dev-env");
283330

284331
// Set up the project
285332
await sandbox.gitCheckout("https://github.com/user/my-app");
286-
await sandbox.exec("npm", ["install"]);
333+
await sandbox.exec("npm install");
287334

288335
// Start dev server
289-
await sandbox.exec("npm", ["run", "dev"]);
336+
const devServer = await sandbox.startProcess("npm run dev");
290337

291338
// Expose the dev server
292339
const preview = await sandbox.exposePort(3000, { name: "dev-server" });
@@ -309,7 +356,7 @@ await sandbox.writeFile(
309356
});`
310357
);
311358

312-
await sandbox.exec("bun", ["run", "/server.js"]);
359+
const server = await sandbox.startProcess("bun run /server.js");
313360

314361
// Expose the port - returns a public URL
315362
const preview = await sandbox.exposePort(8080);
@@ -330,19 +377,78 @@ The SDK leverages Cloudflare's infrastructure:
330377

331378
## 🛠️ Advanced Usage
332379

333-
### Streaming Output
380+
### AsyncIterable Streaming Support
334381

335-
For long-running commands, use streaming:
382+
The SDK provides powerful streaming capabilities with typed AsyncIterable support:
383+
384+
```typescript
385+
import { parseSSEStream, type ExecEvent } from '@cloudflare/sandbox';
386+
387+
// Stream command execution
388+
const stream = await sandbox.execStream('npm run build');
389+
for await (const event of parseSSEStream<ExecEvent>(stream)) {
390+
switch (event.type) {
391+
case 'start':
392+
console.log(`Build started: ${event.command}`);
393+
break;
394+
case 'stdout':
395+
console.log(`Build: ${event.data}`);
396+
break;
397+
case 'complete':
398+
console.log(`Exit code: ${event.exitCode}`);
399+
break;
400+
case 'error':
401+
console.error(`Error: ${event.error}`);
402+
break;
403+
}
404+
}
405+
```
406+
407+
#### Streaming Utilities
408+
409+
The SDK exports utilities for working with Server-Sent Event streams:
410+
411+
- **`parseSSEStream<T>(stream)`** - Convert ReadableStream to typed AsyncIterable
412+
- **`responseToAsyncIterable<T>(response)`** - Convert SSE Response to AsyncIterable
413+
- **`asyncIterableToSSEStream<T>(iterable)`** - Convert AsyncIterable back to SSE stream
414+
415+
#### Advanced Streaming Examples
416+
417+
**CI/CD Build System:**
418+
```typescript
419+
export async function runBuild(env: Env, buildId: string) {
420+
const sandbox = getSandbox(env.SANDBOX, buildId);
421+
const stream = await sandbox.execStream('npm run build');
422+
423+
for await (const event of parseSSEStream<ExecEvent>(stream)) {
424+
switch (event.type) {
425+
case 'start':
426+
await env.BUILDS.put(buildId, { status: 'running' });
427+
break;
428+
case 'complete':
429+
await env.BUILDS.put(buildId, {
430+
status: event.exitCode === 0 ? 'success' : 'failed',
431+
exitCode: event.exitCode
432+
});
433+
break;
434+
}
435+
}
436+
}
437+
```
336438

439+
**System Monitoring:**
337440
```typescript
338-
const response = await sandbox.exec("npm", ["install"], { stream: true });
339-
340-
// Process the stream
341-
const reader = response.body.getReader();
342-
while (true) {
343-
const { done, value } = await reader.read();
344-
if (done) break;
345-
console.log(new TextDecoder().decode(value));
441+
const monitor = await sandbox.startProcess('tail -f /var/log/system.log');
442+
const logStream = await sandbox.streamProcessLogs(monitor.id);
443+
444+
for await (const log of parseSSEStream<LogEvent>(logStream)) {
445+
if (log.type === 'stdout' && log.data.includes('ERROR')) {
446+
await env.ALERTS.send({
447+
severity: 'high',
448+
message: log.data,
449+
timestamp: log.timestamp
450+
});
451+
}
346452
}
347453
```
348454

@@ -354,9 +460,9 @@ Maintain context across commands:
354460
const sessionId = crypto.randomUUID();
355461

356462
// Commands in the same session share working directory
357-
await sandbox.exec("cd", ["/app"], { sessionId });
358-
await sandbox.exec("npm", ["install"], { sessionId });
359-
await sandbox.exec("npm", ["start"], { sessionId });
463+
await sandbox.exec("cd /app", { sessionId });
464+
await sandbox.exec("npm install", { sessionId });
465+
const app = await sandbox.startProcess("npm start", { sessionId });
360466
```
361467

362468
## 🔍 Debugging
@@ -399,17 +505,16 @@ npm run build
399505

400506
## 📄 License
401507

402-
[MIT License](LICENSE) - feel free to use this in your projects!
508+
[MIT License](LICENSE)
403509

404510
## 🙌 Acknowledgments
405511

406-
Built with ❤️ by the Cloudflare team. Special thanks to all early adopters and contributors who are helping shape the future of edge computing.
512+
Built with ❤️ by the Cloudflare team. Special thanks to all early adopters and contributors.
407513

408514
---
409515

410516
<div align="center">
411517
<p>
412-
<a href="https://developers.cloudflare.com">Docs</a> •
413518
<a href="https://github.com/cloudflare/sandbox-sdk/issues">Issues</a> •
414519
<a href="https://discord.gg/cloudflaredev">Discord</a> •
415520
<a href="https://twitter.com/CloudflareDev">Twitter</a>

0 commit comments

Comments
 (0)