@@ -87,26 +87,42 @@ for await (const event of parseSSEStream<ExecEvent>(stream)) {
8787Start a long-running background process.
8888
8989``` ts
90- const process = await sandbox .startProcess (command : string , options ?: ProcessOptions ): Promise < ProcessInfo >
90+ const process = await sandbox .startProcess (command : string , options ?: ProcessOptions ): Promise < Process >
9191```
9292
9393** Parameters** :
9494- ` command ` - The command to start as a background process
9595- ` options ` (optional):
9696 - ` cwd ` - Working directory
9797 - ` env ` - Environment variables
98+ - ` ready ` - Condition to wait for before returning (string, RegExp, or port number)
99+ - ` readyTimeout ` - Maximum time to wait for ready condition in milliseconds (default: ` 30000 ` )
98100
99- ** Returns** : ` Promise<ProcessInfo> ` with ` id ` , ` pid ` , ` command ` , ` status `
101+ ** Returns** : ` Promise<Process> ` with ` id ` , ` pid ` , ` command ` , ` status ` , and methods:
102+ - ` waitFor(condition, timeout?) ` - Wait for additional conditions
100103
101104<TypeScriptExample >
102105```
106+ // Basic usage
103107const server = await sandbox.startProcess('python -m http.server 8000');
104108console.log('Started with PID:', server.pid);
105109
106- // With custom environment
107- const app = await sandbox.startProcess('node app.js', {
110+ // Wait for log pattern before proceeding
111+ const app = await sandbox.startProcess('npm start', {
112+ ready: 'Server listening on port 3000',
113+ readyTimeout: 30000
114+ });
115+
116+ // Wait for port to be available
117+ const api = await sandbox.startProcess('node app.js', {
118+ ready: 8080,
108119 cwd: '/workspace/my-app',
109- env: { NODE_ENV: 'production', PORT: '3000' }
120+ env: { NODE_ENV: 'production' }
121+ });
122+
123+ // Wait for regex pattern
124+ const db = await sandbox.startProcess('postgres', {
125+ ready: /database system is ready/i
110126});
111127```
112128</TypeScriptExample >
@@ -195,21 +211,139 @@ for await (const log of parseSSEStream<LogEvent>(logStream)) {
195211Get accumulated logs from a process.
196212
197213``` ts
198- const logs = await sandbox .getProcessLogs (processId : string ): Promise < string >
214+ const logs = await sandbox .getProcessLogs (processId : string ): Promise < { stdout: string , stderr: string } >
199215```
200216
201217** Parameters** :
202218- ` processId ` - The process ID
203219
204- ** Returns** : ` Promise<string> ` with all accumulated output
220+ ** Returns** : ` Promise<{ stdout: string, stderr: string } > ` with all accumulated output
205221
206222<TypeScriptExample >
207223```
208224const server = await sandbox.startProcess('node server.js');
209225await new Promise(resolve => setTimeout(resolve, 5000));
210226
211227const logs = await sandbox.getProcessLogs(server.id);
212- console.log('Server logs:', logs);
228+ console.log('Server logs:', logs.stdout);
229+ console.log('Server errors:', logs.stderr);
230+ ```
231+ </TypeScriptExample >
232+
233+ ### ` serve() `
234+
235+ Start a server process, wait for it to be ready, and optionally expose it with a preview URL.
236+
237+ ``` ts
238+ const result = await sandbox .serve (
239+ command : string ,
240+ portOrOptions : number | ServeOptions
241+ ): Promise < string | { url: string , process: Process }>
242+ ```
243+
244+ ** Parameters** :
245+ - ` command ` - The command to start the server
246+ - ` portOrOptions ` - Port number or options object:
247+ - ` port ` - Port number to expose
248+ - ` hostname ` - Hostname for preview URL (required for URL exposure)
249+ - ` ready ` - Custom readiness condition (defaults to port check)
250+ - ` timeout ` - Readiness timeout in milliseconds (default: ` 60000 ` )
251+ - ` env ` - Environment variables
252+ - ` cwd ` - Working directory
253+
254+ ** Returns** :
255+ - If ` hostname ` provided: ` Promise<{ url: string, process: Process }> ` with preview URL
256+ - If no ` hostname ` : ` Promise<string> ` with local URL indication
257+
258+ <TypeScriptExample >
259+ ```
260+ // Simple port exposure with preview URL
261+ const { url, process } = await sandbox.serve('npm start', {
262+ port: 3000,
263+ hostname: request.url.hostname
264+ });
265+
266+ console.log('Server accessible at:', url);
267+
268+ // With custom readiness pattern
269+ const { url, process } = await sandbox.serve('python -m http.server 8080', {
270+ port: 8080,
271+ hostname: request.url.hostname,
272+ ready: 'Serving HTTP',
273+ timeout: 60000
274+ });
275+
276+ // Without hostname (for internal use)
277+ const localUrl = await sandbox.serve('node api.js', 3000);
278+ // Returns: "http://localhost:3000"
279+ ```
280+ </TypeScriptExample >
281+
282+ ### ` process.waitFor() `
283+
284+ Wait for a condition to be met for a running process. Available on the ` Process ` object returned by ` startProcess() ` .
285+
286+ ``` ts
287+ const result = await process .waitFor (
288+ condition : ReadyCondition ,
289+ timeout ?: number
290+ ): Promise < WaitForResult >
291+ ```
292+
293+ ** Parameters** :
294+ - ` condition ` - String pattern, RegExp, or port number to wait for
295+ - ` timeout ` - Maximum wait time in milliseconds (default: ` 30000 ` )
296+
297+ ** Returns** : ` Promise<WaitForResult> ` with:
298+ - ` line ` - The matching log line (for string/regex conditions)
299+ - ` match ` - RegExp capture groups (for regex conditions)
300+
301+ <TypeScriptExample >
302+ ```
303+ const app = await sandbox.startProcess('npm run dev');
304+
305+ // Wait for database connection
306+ await app.waitFor('Database connected');
307+
308+ // Wait for port availability
309+ await app.waitFor(3000);
310+
311+ // Wait for regex with capture groups
312+ const result = await app.waitFor(/Server started on port (\d+)/);
313+ console.log('Port:', result.match?.[1]); // "3000"
314+
315+ // With custom timeout
316+ await app.waitFor('Ready', 60000);
317+ ```
318+ </TypeScriptExample >
319+
320+ ## Error handling
321+
322+ Process readiness operations may throw specific errors:
323+
324+ <TypeScriptExample >
325+ ```
326+ import {
327+ ProcessReadyTimeoutError,
328+ ProcessExitedBeforeReadyError
329+ } from '@cloudflare/sandbox';
330+
331+ try {
332+ const server = await sandbox.startProcess('npm start', {
333+ ready: 'Server listening',
334+ readyTimeout: 10000
335+ });
336+ } catch (error) {
337+ if (error instanceof ProcessReadyTimeoutError) {
338+ // Process did not become ready in time
339+ console.error('Timeout waiting for:', error.condition);
340+ console.error('Last output:', error.stdout, error.stderr);
341+ } else if (error instanceof ProcessExitedBeforeReadyError) {
342+ // Process crashed before becoming ready
343+ console.error('Process exited with code:', error.exitCode);
344+ console.error('Output:', error.stdout, error.stderr);
345+ }
346+ }
213347```
214348</TypeScriptExample >
215349
0 commit comments