@computesdk/blaxel 1.0.0

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 computesdk
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,666 @@
1
+ # @computesdk/blaxel
2
+
3
+ Blaxel provider for ComputeSDK - Execute code in secure Blaxel cloud sandboxes.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @computesdk/blaxel
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ### With ComputeSDK
14
+
15
+ ```typescript
16
+ import { compute } from 'computesdk';
17
+ import { blaxel } from '@computesdk/blaxel';
18
+
19
+ // Set as default provider
20
+ compute.setConfig({
21
+ provider: blaxel({ apiKey: process.env.BL_API_KEY })
22
+ });
23
+
24
+ // Create sandbox
25
+ const sandbox = await compute.sandbox.create();
26
+
27
+ // Execute code
28
+ const result = await sandbox.runCode('console.log("Hello from Blaxel!")');
29
+ console.log(result.stdout); // "Hello from Blaxel!"
30
+
31
+ // Clean up
32
+ await sandbox.destroy();
33
+ ```
34
+
35
+ ### Direct Usage
36
+
37
+ ```typescript
38
+ import { blaxel } from '@computesdk/blaxel';
39
+
40
+ // Create provider with configuration
41
+ const provider = blaxel({
42
+ workspace: 'your-workspace',
43
+ apiKey: 'your-api-key',
44
+ image: 'blaxel/prod-py-app:latest', // Python image
45
+ memory: 8192, // 8GB RAM
46
+ ports: [3000, 8080] // Exposed ports
47
+ });
48
+
49
+ // Use with compute singleton
50
+ const sandbox = await compute.sandbox.create({
51
+ provider,
52
+ options: {
53
+ runtime: 'python', // Runtime specified at creation time
54
+ timeout: 3600000, // 1 hour timeout
55
+ envs: {
56
+ DEBUG: 'true'
57
+ }
58
+ }
59
+ });
60
+ ```
61
+
62
+ ## Configuration
63
+
64
+ ### Environment Variables
65
+
66
+ ```bash
67
+ export BL_WORKSPACE=your_workspace_id
68
+ export BL_API_KEY=your_api_key_here
69
+ ```
70
+
71
+ ### Configuration Options
72
+
73
+ ```typescript
74
+ interface BlaxelConfig {
75
+ /** Blaxel workspace ID - fallback to BL_WORKSPACE env var */
76
+ workspace?: string;
77
+ /** Blaxel API key - fallback to BL_API_KEY env var */
78
+ apiKey?: string;
79
+ /** Default image for sandboxes */
80
+ image?: string;
81
+ /** Default region for sandbox deployment */
82
+ region?: string;
83
+ /** Default memory allocation in MB (default: 4096) */
84
+ memory?: number;
85
+ /** Default ports for sandbox (default: [3000]) */
86
+ ports?: number[];
87
+ }
88
+ ```
89
+
90
+ > 💡 **Note:** For persistent storage across sandbox sessions, see [Mounting & using sandbox volumes](https://docs.blaxel.ai/Sandboxes/Volumes)
91
+
92
+ ### Default Images
93
+
94
+ The provider automatically selects images based on runtime:
95
+ - **Python:** `blaxel/prod-py-app:latest`
96
+ - **Node.js:** `blaxel/prod-ts-app:latest`
97
+ - **Default:** `blaxel/prod-base:latest`
98
+
99
+ ## Features
100
+
101
+ - ✅ **Code Execution** - Python and Node.js runtime support with proper stdout/stderr streaming
102
+ - ✅ **Command Execution** - Run shell commands with background support
103
+ - ✅ **Filesystem Operations** - Full file system access (read, write, mkdir, ls, rm)
104
+ - ✅ **Auto Runtime Detection** - Automatically detects Python vs Node.js from code patterns
105
+ - ✅ **Custom Images** - Support for custom Docker images
106
+ - ✅ **Memory Configuration** - Configurable memory allocation
107
+ - ✅ **Preview URLs** - Public/private preview URLs with TTL, custom domains, and headers
108
+ - ✅ **Environment Variables** - Pass custom environment variables to sandboxes
109
+ - ✅ **Metadata Labels** - Attach custom metadata to sandboxes
110
+ - ✅ **Multi-Port Support** - Configure multiple ports for sandbox access
111
+ - ✅ **Status Detection** - Automatic conversion of Blaxel status to standard format
112
+
113
+ > 📚 For more details, see the [Sandbox technical guide](https://docs.blaxel.ai/Sandboxes/Overview)
114
+
115
+ ## API Reference
116
+
117
+ ### Code Execution
118
+
119
+ ```typescript
120
+ // Execute Python code
121
+ const result = await sandbox.runCode(`
122
+ import json
123
+ data = {"message": "Hello from Python"}
124
+ print(json.dumps(data))
125
+ `, 'python');
126
+
127
+ // Execute Node.js code
128
+ const result = await sandbox.runCode(`
129
+ const data = { message: "Hello from Node.js" };
130
+ console.log(JSON.stringify(data));
131
+ `, 'node');
132
+
133
+ // Auto-detection (based on code patterns)
134
+ const result = await sandbox.runCode('print("Auto-detected as Python")');
135
+ ```
136
+
137
+ ### Command Execution
138
+
139
+ ```typescript
140
+ // List files
141
+ const result = await sandbox.runCommand('ls', ['-la']);
142
+
143
+ // Install packages
144
+ const result = await sandbox.runCommand('pip', ['install', 'requests']);
145
+
146
+ // Run background process
147
+ const bgResult = await sandbox.runCommand('npm', ['start'], { background: true });
148
+ console.log('Process started in background');
149
+ ```
150
+
151
+ ### Filesystem Operations
152
+
153
+ > 📚 For detailed filesystem API documentation, see the [Sandbox API reference](https://docs.blaxel.ai/api-reference/filesystem/get-file-or-directory-information)
154
+
155
+ ```typescript
156
+ // Write file
157
+ await sandbox.filesystem.writeFile('/tmp/hello.py', 'print("Hello World")');
158
+
159
+ // Read file
160
+ const content = await sandbox.filesystem.readFile('/tmp/hello.py');
161
+
162
+ // Create directory
163
+ await sandbox.filesystem.mkdir('/tmp/data');
164
+
165
+ // List directory contents with metadata
166
+ const files = await sandbox.filesystem.readdir('/tmp');
167
+ // Returns FileEntry[] with name, path, isDirectory, size, lastModified
168
+
169
+ // Check if file exists
170
+ const exists = await sandbox.filesystem.exists('/tmp/hello.py');
171
+
172
+ // Remove file or directory
173
+ await sandbox.filesystem.remove('/tmp/hello.py');
174
+ ```
175
+
176
+ ### Sandbox Management
177
+
178
+ ```typescript
179
+ // Get sandbox info
180
+ const info = await sandbox.getInfo();
181
+ console.log(info.id, info.provider, info.status, info.runtime);
182
+ // Status: 'running', 'stopped', or 'error'
183
+ // Runtime: Automatically detected from image name
184
+
185
+ // Create with specific configuration
186
+ const sandbox = await provider.sandbox.create({
187
+ runtime: 'python', // Selects appropriate image
188
+ timeout: 1800000, // 30 minutes in milliseconds (converted to "1800s")
189
+ envs: { // Environment variables
190
+ API_KEY: 'secret-key',
191
+ NODE_ENV: 'production'
192
+ },
193
+ metadata: { // Custom metadata labels
194
+ labels: {
195
+ project: 'my-project',
196
+ environment: 'staging'
197
+ }
198
+ }
199
+ });
200
+
201
+ // Create with custom memory and region
202
+ const customSandbox = await provider.sandbox.create({
203
+ memory: 8192, // 8GB RAM
204
+ region: 'us-pdx-1', // See regions documentation below
205
+ ports: [3000, 8080, 9000] // Multiple ports
206
+ });
207
+
208
+ > 📚 Learn more: [Deployment regions](https://docs.blaxel.ai/Infrastructure/Regions) | [Specifying region when creating sandboxes](https://docs.blaxel.ai/Sandboxes/Overview#create-a-sandbox)
209
+
210
+ // Reconnect to existing sandbox
211
+ const existing = await provider.sandbox.create({
212
+ sandboxId: 'blaxel-1234567890'
213
+ });
214
+
215
+ // Get sandbox by ID
216
+ const sandbox = await provider.sandbox.getById('blaxel-1234567890');
217
+
218
+ // Destroy sandbox
219
+ await provider.sandbox.destroy('blaxel-1234567890');
220
+ ```
221
+
222
+ ### Preview URLs
223
+
224
+ > 📚 For a complete guide, see [Creating preview URLs & custom domains](https://docs.blaxel.ai/Sandboxes/Preview-url)
225
+
226
+ ```typescript
227
+ // getUrl options interface
228
+ interface GetUrlOptions {
229
+ port: number; // Port number to expose
230
+ ttl?: number; // Preview TTL in milliseconds
231
+ prefixUrl?: string; // Custom prefix URL for the preview
232
+ customDomain?: string; // Custom domain for the preview
233
+ headers?: {
234
+ response?: Record<string, string>; // Response headers sent to clients
235
+ request?: Record<string, string>; // Request headers for internal routing
236
+ };
237
+ authentication?: {
238
+ public?: boolean; // Create public preview (default: true)
239
+ tokenExpiryMinutes?: number; // Token expiry for private previews (default: 60)
240
+ };
241
+ }
242
+
243
+ // Create a public preview URL (default headers applied)
244
+ const publicUrl = await sandbox.getUrl({ port: 3000 });
245
+ console.log(publicUrl); // https://tkmu0oj2bf6iuoag6mmlt8.preview.bl.run
246
+
247
+ // Create a private preview URL with authentication token
248
+ const privateUrl = await sandbox.getUrl({
249
+ port: 3000,
250
+ authentication: {
251
+ public: false,
252
+ tokenExpiryMinutes: 30 // Token expires in 30 minutes (default: 60)
253
+ }
254
+ });
255
+ console.log(privateUrl);
256
+ // https://tkmu0oj2bf6iuoag6mmlt8.preview.bl.run?bl_preview_token=<token>
257
+
258
+ // Create preview with custom TTL (Time To Live)
259
+ const shortLivedUrl = await sandbox.getUrl({
260
+ port: 3000,
261
+ ttl: 300000 // Preview expires in 5 minutes (300,000 ms)
262
+ });
263
+
264
+ // Create preview with custom CORS headers (replaces all defaults)
265
+ const customUrl = await sandbox.getUrl({
266
+ port: 3000,
267
+ headers: {
268
+ response: {
269
+ "Access-Control-Allow-Origin": "https://mydomain.com",
270
+ "Access-Control-Allow-Methods": "GET, POST",
271
+ "Access-Control-Allow-Credentials": "true",
272
+ "X-Custom-Header": "custom-value"
273
+ },
274
+ request: {
275
+ "X-Internal-Auth": "internal-token"
276
+ }
277
+ }
278
+ });
279
+
280
+ // Create preview with custom domain
281
+ const customDomainUrl = await sandbox.getUrl({
282
+ port: 3000,
283
+ customDomain: "app.example.com"
284
+ });
285
+
286
+ // Create preview with custom prefix URL
287
+ const prefixedUrl = await sandbox.getUrl({
288
+ port: 3000,
289
+ prefixUrl: "my-preview"
290
+ });
291
+ // https://my-preview-my-workspace.preview.bl.run
292
+
293
+ // Full example with all options
294
+ const advancedUrl = await sandbox.getUrl({
295
+ port: 3000,
296
+ ttl: 3600000, // 1 hour TTL
297
+ prefixUrl: "my-preview",
298
+ customDomain: "preview.myapp.com",
299
+ headers: {
300
+ response: {
301
+ "Access-Control-Allow-Origin": "https://myapp.com",
302
+ "X-Frame-Options": "SAMEORIGIN"
303
+ },
304
+ request: {
305
+ "X-API-Version": "v2"
306
+ }
307
+ },
308
+ authentication: {
309
+ public: false,
310
+ tokenExpiryMinutes: 120 // 2 hour token
311
+ }
312
+ });
313
+
314
+ // The token is automatically appended to the URL for private previews
315
+ // You can also pass the token as a header: X-Blaxel-Preview-Token
316
+ ```
317
+
318
+ ### Direct Instance Access
319
+
320
+ > 📚 You can also [connect to sandboxes remotely from a terminal](https://docs.blaxel.ai/Sandboxes/Overview#connect-to-a-sandbox-with-a-terminal) for direct access
321
+
322
+ ```typescript
323
+ import { createBlaxelCompute } from '@computesdk/blaxel';
324
+
325
+ const compute = createBlaxelCompute({
326
+ workspace: 'your-workspace',
327
+ apiKey: 'your-key',
328
+ memory: 4096,
329
+ ports: [3000]
330
+ });
331
+
332
+ const sandbox = await compute.sandbox.create();
333
+ const instance = sandbox.getInstance(); // Typed as SandboxInstance
334
+
335
+ // Use Blaxel-specific features directly
336
+ const result = await instance.process.exec({
337
+ command: 'ls -la'
338
+ });
339
+
340
+ // Stream logs from process
341
+ const stream = instance.process.streamLogs(result.name, {
342
+ onStdout(data) { console.log('stdout:', data); },
343
+ onStderr(data) { console.error('stderr:', data); }
344
+ });
345
+
346
+ // Wait for completion
347
+ await instance.process.wait(result.name);
348
+ stream.close();
349
+
350
+ // Access Blaxel filesystem API
351
+ await instance.fs.write('/tmp/test.txt', 'Hello Blaxel');
352
+ const content = await instance.fs.read('/tmp/test.txt');
353
+
354
+ // Create preview with Blaxel API
355
+ const preview = await instance.previews.create({
356
+ spec: {
357
+ port: 3000,
358
+ public: true
359
+ }
360
+ });
361
+ ```
362
+
363
+ ## Runtime Detection
364
+
365
+ The provider automatically detects the runtime based on code patterns:
366
+
367
+ **Python indicators:**
368
+ - `print(` statements
369
+ - `import` statements
370
+ - `def` function definitions
371
+ - Python-specific syntax (`f"`, `f'`, `__`, `sys.`, `json.`)
372
+
373
+ **Default:** Node.js for all other cases
374
+
375
+ ## Error Handling
376
+
377
+ ```typescript
378
+ try {
379
+ const result = await sandbox.runCode('invalid code');
380
+ } catch (error) {
381
+ if (error.message.includes('Syntax error')) {
382
+ console.error('Code has syntax errors');
383
+ } else if (error.message.includes('authentication')) {
384
+ console.error('Check your BL_API_KEY');
385
+ } else if (error.message.includes('quota')) {
386
+ console.error('Blaxel usage limits reached');
387
+ }
388
+ }
389
+ ```
390
+
391
+ ### Exit Codes
392
+ - `0` - Success
393
+ - `1` - General error or runtime error
394
+ - `127` - Command not found
395
+
396
+ ## Web Framework Integration
397
+
398
+ Use with web frameworks via the request handler:
399
+
400
+ ```typescript
401
+ import { handleComputeRequest } from 'computesdk';
402
+ import { blaxel } from '@computesdk/blaxel';
403
+
404
+ export async function POST(request: Request) {
405
+ return handleComputeRequest({
406
+ request,
407
+ provider: blaxel({ apiKey: process.env.BL_API_KEY })
408
+ });
409
+ }
410
+ ```
411
+
412
+ ## Examples
413
+
414
+ ### Data Processing
415
+
416
+ ```typescript
417
+ const result = await sandbox.runCode(`
418
+ import json
419
+
420
+ # Process data
421
+ data = [1, 2, 3, 4, 5]
422
+ result = {
423
+ "sum": sum(data),
424
+ "average": sum(data) / len(data),
425
+ "max": max(data)
426
+ }
427
+
428
+ print(json.dumps(result))
429
+ `);
430
+
431
+ const output = JSON.parse(result.stdout);
432
+ console.log(output); // { sum: 15, average: 3, max: 5 }
433
+ ```
434
+
435
+ ### File Processing
436
+
437
+ ```typescript
438
+ // Create data file
439
+ await sandbox.filesystem.writeFile('/tmp/data.json',
440
+ JSON.stringify({ users: ['Alice', 'Bob', 'Charlie'] })
441
+ );
442
+
443
+ // Process file
444
+ const result = await sandbox.runCode(`
445
+ import json
446
+
447
+ with open('/tmp/data.json', 'r') as f:
448
+ data = json.load(f)
449
+
450
+ # Process users
451
+ user_count = len(data['users'])
452
+ print(f"Found {user_count} users")
453
+
454
+ # Save result
455
+ result = {"user_count": user_count, "processed": True}
456
+ with open('/tmp/result.json', 'w') as f:
457
+ json.dump(result, f)
458
+ `);
459
+
460
+ // Read result
461
+ const resultData = await sandbox.filesystem.readFile('/tmp/result.json');
462
+ console.log(JSON.parse(resultData));
463
+ ```
464
+
465
+ ### Web Scraping Example
466
+
467
+ ```typescript
468
+ // Install dependencies
469
+ await sandbox.runCommand('pip', ['install', 'requests', 'beautifulsoup4']);
470
+
471
+ // Scrape website
472
+ const result = await sandbox.runCode(`
473
+ import requests
474
+ from bs4 import BeautifulSoup
475
+ import json
476
+
477
+ # Fetch webpage
478
+ response = requests.get('https://example.com')
479
+ soup = BeautifulSoup(response.text, 'html.parser')
480
+
481
+ # Extract title
482
+ title = soup.find('title').text if soup.find('title') else 'No title'
483
+
484
+ # Output result
485
+ result = {
486
+ "status_code": response.status_code,
487
+ "title": title,
488
+ "content_length": len(response.text)
489
+ }
490
+
491
+ print(json.dumps(result))
492
+ `);
493
+
494
+ console.log(JSON.parse(result.stdout));
495
+ ```
496
+
497
+ ### API Development
498
+
499
+ ```typescript
500
+ // Create a simple API server
501
+ await sandbox.filesystem.writeFile('/tmp/server.js', `
502
+ const http = require('http');
503
+
504
+ const server = http.createServer((req, res) => {
505
+ res.writeHead(200, { 'Content-Type': 'application/json' });
506
+ res.end(JSON.stringify({
507
+ message: 'Hello from Blaxel!',
508
+ timestamp: new Date().toISOString()
509
+ }));
510
+ });
511
+
512
+ server.listen(3000, () => {
513
+ console.log('Server running on port 3000');
514
+ });
515
+ `);
516
+
517
+ // Start server in background
518
+ await sandbox.runCommand('node', ['/tmp/server.js'], { background: true });
519
+
520
+ // Get the preview URL (public by default)
521
+ const url = await sandbox.getUrl({ port: 3000 });
522
+ console.log(`API available at: ${url}`);
523
+ // Example: https://tkmu0oj2bf6iuoag6mmlt8.preview.bl.run
524
+
525
+ // Or create a private API endpoint with authentication
526
+ const privateUrl = await sandbox.getUrl({
527
+ port: 3000,
528
+ authentication: {
529
+ public: false,
530
+ tokenExpiryMinutes: 120 // 2 hour token
531
+ }
532
+ });
533
+ console.log(`Private API: ${privateUrl}`);
534
+ ```
535
+
536
+ ## Authentication Methods
537
+
538
+ 1. **Automatic (when running on Blaxel)** - No configuration needed
539
+ 2. **Via Configuration** - Pass credentials directly
540
+ 3. **Via Environment Variables** - Set BL_WORKSPACE and BL_API_KEY
541
+ 4. **Via Blaxel CLI** - Run `bl login` for local development
542
+
543
+ ## Sandbox URLs
544
+
545
+ Blaxel sandboxes are accessible via dynamically generated preview URLs:
546
+ ```
547
+ https://{unique-id}.preview.bl.run or https://{unique-id}.{region}.preview.bl.run
548
+ ```
549
+
550
+ Or with custom domain:
551
+ ```
552
+ https://{unique-id}.{custom-domain}
553
+ ```
554
+
555
+ > 📚 Learn more about [preview URLs and custom domains](https://docs.blaxel.ai/Sandboxes/Preview-url)
556
+
557
+ ### Public vs Private Previews
558
+
559
+ **Public Previews** (default):
560
+ - No authentication required
561
+ - Accessible to anyone with the URL
562
+ - Suitable for public demos and testing
563
+
564
+ **Private Previews**:
565
+ - Require authentication token
566
+ - Token can be passed as `bl_preview_token` query parameter
567
+ - Token can also be passed as `X-Blaxel-Preview-Token` header
568
+ - Configurable token expiry time
569
+
570
+ ### Preview Configuration Options
571
+
572
+ **TTL (Time To Live)**:
573
+ - Controls how long the preview URL remains active
574
+ - Specified in milliseconds
575
+ - Automatically converted to Blaxel's format (e.g., "300s" for 5 minutes)
576
+
577
+ **Custom Domain**:
578
+ - Use your own domain for preview URLs
579
+ - Must be configured in Blaxel settings
580
+
581
+ **Prefix URL**:
582
+ - Add a path prefix to all preview URLs
583
+ - Useful for API versioning or routing
584
+
585
+ **Headers**:
586
+ - `response`: Headers sent to clients accessing the preview
587
+ - `request`: Headers used for internal routing within Blaxel
588
+
589
+ **Default Response Headers**:
590
+
591
+ The provider applies these CORS headers by default when no custom response headers are provided:
592
+ ```javascript
593
+ {
594
+ "Access-Control-Allow-Origin": "*",
595
+ "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS, PATCH",
596
+ "Access-Control-Allow-Headers": "Content-Type, Authorization, X-Requested-With, X-Blaxel-Preview-Token, X-Blaxel-Authorization",
597
+ "Access-Control-Allow-Credentials": "true",
598
+ "Access-Control-Expose-Headers": "Content-Length, X-Request-Id",
599
+ "Access-Control-Max-Age": "86400",
600
+ "Vary": "Origin"
601
+ }
602
+ ```
603
+
604
+ **Note:** If you provide custom response headers, they completely replace the defaults. Make sure to include all necessary CORS headers when providing custom headers.
605
+
606
+ Example:
607
+ ```typescript
608
+ // Public preview with default headers and settings
609
+ const url = await sandbox.getUrl({ port: 3000 });
610
+
611
+ // Private preview with 2-hour token and 24-hour TTL
612
+ const secureUrl = await sandbox.getUrl({
613
+ port: 3000,
614
+ ttl: 86400000, // 24 hours in milliseconds
615
+ authentication: {
616
+ public: false,
617
+ tokenExpiryMinutes: 120
618
+ }
619
+ });
620
+
621
+ // Private preview with complete custom headers (replaces all defaults)
622
+ const customSecureUrl = await sandbox.getUrl({
623
+ port: 3000,
624
+ authentication: {
625
+ public: false,
626
+ tokenExpiryMinutes: 60
627
+ },
628
+ headers: {
629
+ response: {
630
+ // Must include all necessary CORS headers when providing custom headers, if you want ot
631
+ "Access-Control-Allow-Origin": "https://app.example.com",
632
+ "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE",
633
+ "Access-Control-Allow-Headers": "Content-Type, Authorization, X-Blaxel-Preview-Token",
634
+ "Access-Control-Allow-Credentials": "true",
635
+ "X-Frame-Options": "SAMEORIGIN"
636
+ },
637
+ request: {
638
+ "X-Service-Name": "preview-service",
639
+ "X-Request-ID": "unique-request-id"
640
+ }
641
+ }
642
+ });
643
+ ```
644
+
645
+ The provider automatically creates appropriate preview URLs with CORS headers configured for broad compatibility.
646
+
647
+ ## Further Reading
648
+
649
+ ### Core Documentation
650
+ - [Sandbox technical guide](https://docs.blaxel.ai/Sandboxes/Overview) - Comprehensive overview of Blaxel sandboxes
651
+ - [Sandbox API reference](https://docs.blaxel.ai/api-reference/filesystem/get-file-or-directory-information) - Complete API documentation for filesystem operations
652
+ - [ComputeSDK documentation](https://github.com/computesdk/computesdk) - Main SDK documentation
653
+
654
+ ### Guides
655
+ - [Creating preview URLs & custom domains](https://docs.blaxel.ai/Sandboxes/Preview-url) - Detailed guide on preview configuration
656
+ - [Connecting to sandboxes remotely](https://docs.blaxel.ai/Sandboxes/Overview#connect-to-a-sandbox-with-a-terminal) - Terminal access to running sandboxes
657
+ - [Deployment regions](https://docs.blaxel.ai/Infrastructure/Regions) - Available regions and selection guide
658
+ - [Specifying regions for sandboxes](https://docs.blaxel.ai/Sandboxes/Overview#create-a-sandbox) - Region configuration during sandbox creation
659
+ - [Mounting & using sandbox volumes](https://docs.blaxel.ai/Sandboxes/Volumes) - Persistent storage with volumes
660
+
661
+ ### Support
662
+ Feel free to reach out if you have any questions — we're here to help!
663
+
664
+ ## License
665
+
666
+ MIT