Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@
### Installation

```bash
npm install devbox-sdk
npm install @labring/devbox-sdk
```

### Secure Code Execution

```typescript
import { DevboxSDK } from 'devbox-sdk'
import { DevboxSDK } from '@labring/devbox-sdk'

// Initialize SDK
const sdk = new DevboxSDK({
Expand Down Expand Up @@ -99,7 +99,7 @@ Each sandbox runs in an isolated Kubernetes Pod, ensuring:

This is a monorepo containing multiple packages:

### devbox-sdk (Main Package)
### @labring/devbox-sdk (Main Package)
The primary TypeScript SDK for secure sandbox execution. See [packages/sdk/README.md](./packages/sdk/README.md) for detailed documentation.

### devbox-shared
Expand Down
2 changes: 1 addition & 1 deletion apps/docs/components/landing/footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export function Footer() {
</li>
<li>
<a
href="https://www.npmjs.com/package/devbox-sdk"
href="https://www.npmjs.com/package/@labring/devbox-sdk"
className="hover:text-black transition-colors"
>
NPM
Expand Down
2 changes: 1 addition & 1 deletion apps/docs/components/landing/hero-section.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ export function HeroSection() {
<span className="text-[#ff79c6]">import</span>{' '}
<span className="text-[#f8f8f2]">{'{ DevboxSDK }'}</span>{' '}
<span className="text-[#ff79c6]">from</span>{' '}
<span className="text-[#f1fa8c]">'devbox-sdk'</span>
<span className="text-[#f1fa8c]">'@labring/devbox-sdk'</span>
{'\n\n'}
<span className="text-[#6272a4]">{'// Initialize SDK'}</span>
{'\n'}
Expand Down
2 changes: 1 addition & 1 deletion apps/docs/content/docs/api/devbox-instance.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,7 @@ waitForReady(
## Complete Example

```typescript
import { DevboxSDK } from 'devbox-sdk'
import { DevboxSDK } from '@labring/devbox-sdk'

const sdk = new DevboxSDK({
kubeconfig: process.env.KUBECONFIG
Expand Down
4 changes: 2 additions & 2 deletions apps/docs/content/docs/api/devbox-sdk.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ new DevboxSDK(config: DevboxSDKConfig)
### Example

```typescript
import { DevboxSDK } from 'devbox-sdk'
import { DevboxSDK } from '@labring/devbox-sdk'

const sdk = new DevboxSDK({
kubeconfig: process.env.KUBECONFIG,
Expand Down Expand Up @@ -212,7 +212,7 @@ try {
## Complete Example

```typescript
import { DevboxSDK } from 'devbox-sdk'
import { DevboxSDK } from '@labring/devbox-sdk'

async function main() {
const sdk = new DevboxSDK({
Expand Down
2 changes: 1 addition & 1 deletion apps/docs/content/docs/api/types.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ import type {
ProcessExecResponse,
FileChangeEvent,
GitCloneOptions
} from 'devbox-sdk'
} from '@labring/devbox-sdk'
```

## Next Steps
Expand Down
5 changes: 3 additions & 2 deletions apps/docs/content/docs/examples/ai-agent-workflow.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ This example demonstrates a complete workflow for executing AI-generated code sa
## Complete Example

```typescript
import { DevboxSDK } from 'devbox-sdk'
import { DevboxSDK } from '@labring/devbox-sdk'

async function executeAIAgent(aiGeneratedCode: string) {
const sdk = new DevboxSDK({
Expand Down Expand Up @@ -114,7 +114,7 @@ import {
DevboxSDKError,
FileOperationError,
ValidationError
} from 'devbox-sdk'
} from '@labring/devbox-sdk'

async function safeExecuteAI(code: string) {
const sdk = new DevboxSDK({
Expand Down Expand Up @@ -226,4 +226,5 @@ async function processAIBatch(tasks: Array<{ id: string; code: string }>) {

- Learn about [Automation Tasks](/docs/examples/automation-tasks)
- Explore [CI/CD Integration](/docs/examples/ci-cd-integration)
- See the [Full Lifecycle Example](/docs/examples/full-lifecycle) for a complete workflow

3 changes: 2 additions & 1 deletion apps/docs/content/docs/examples/automation-tasks.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Execute untrusted automation scripts safely in isolated sandboxes.
## Basic Automation

```typescript
import { DevboxSDK } from 'devbox-sdk'
import { DevboxSDK } from '@labring/devbox-sdk'

async function runAutomation(script: string) {
const sdk = new DevboxSDK({
Expand Down Expand Up @@ -249,5 +249,6 @@ async function processFiles(
## Next Steps

- Learn about [CI/CD Integration](/docs/examples/ci-cd-integration)
- See the [Full Lifecycle Example](/docs/examples/full-lifecycle) for a complete workflow
- Explore [API Reference](/docs/api/devbox-instance)

3 changes: 2 additions & 1 deletion apps/docs/content/docs/examples/ci-cd-integration.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ jobs:

```typescript
// scripts/ci-test.js
import { DevboxSDK } from 'devbox-sdk'
import { DevboxSDK } from '@labring/devbox-sdk'
import fs from 'fs'

async function runCITests() {
Expand Down Expand Up @@ -255,6 +255,7 @@ async function runParallelTests(testSuites: string[]) {

## Next Steps

- See the [Full Lifecycle Example](/docs/examples/full-lifecycle) for a complete workflow
- Read [API Reference](/docs/api/devbox-sdk)
- Explore [Guides](/docs/guides/secure-code-execution)

254 changes: 254 additions & 0 deletions apps/docs/content/docs/examples/full-lifecycle.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,254 @@
---
title: Full Lifecycle Example
description: Complete example demonstrating the full devbox lifecycle from creation to cleanup
---

# Full Lifecycle Example

This example demonstrates a complete workflow for creating, managing, and cleaning up a devbox instance. It covers environment setup, devbox creation, execution of commands, and proper resource cleanup.

## Complete Example

This example shows how to:

- Load environment variables and kubeconfig
- Create a devbox instance
- Start the devbox and wait for it to be ready
- Execute commands in the devbox
- Handle errors properly
- Clean up resources

```typescript
import { config as loadEnv } from 'dotenv'
import { existsSync, readFileSync } from 'node:fs'
import { resolve, dirname } from 'node:path'
import { fileURLToPath } from 'node:url'
import { DevboxSDK } from '@labring/devbox-sdk'
import { DevboxRuntime } from '@labring/devbox-sdk'

// Load environment variables from .env file
const __filename = fileURLToPath(import.meta.url)
const __dirname = dirname(__filename)

const envPaths = [
resolve(__dirname, '.env'),
resolve(__dirname, '../.env'),
resolve(__dirname, '../../.env'),
resolve(process.cwd(), '.env'),
]

let envLoaded = false
for (const envPath of envPaths) {
if (existsSync(envPath)) {
loadEnv({ path: envPath, override: false })
console.log(`✅ Loaded environment variables from ${envPath}`)
envLoaded = true
break
}
}

if (!envLoaded) {
console.warn('⚠️ .env file not found, using system environment variables')
}

if (!process.env.KUBECONFIG) {
console.error('❌ Missing required environment variable: KUBECONFIG')
process.exit(1)
}

let kubeconfigContent = process.env.KUBECONFIG

// Handle kubeconfig as file path or content
if (!kubeconfigContent.includes('apiVersion') && existsSync(kubeconfigContent)) {
kubeconfigContent = readFileSync(kubeconfigContent, 'utf-8')
} else if (kubeconfigContent.includes('\\n')) {
kubeconfigContent = kubeconfigContent.replace(/\\n/g, '\n')
}

const SDK_CONFIG = {
kubeconfig: kubeconfigContent,
http: {
timeout: 300000, // 5 minutes
retries: 3,
rejectUnauthorized: false,
},
}

// Generate unique devbox name
const generateDevboxName = (prefix: string) => {
const timestamp = Date.now()
const random = Math.floor(Math.random() * 1000)
const sanitizedPrefix = prefix.replace(/\./g, '-')
return `example-${sanitizedPrefix}-${timestamp}-${random}`
}

async function main() {
const sdk = new DevboxSDK(SDK_CONFIG)
const name = generateDevboxName('full-lifecycle')

try {
console.log('🚀 Starting full lifecycle example...')
console.log(`📦 Creating devbox: ${name}`)

// 1. Create devbox
const devbox = await sdk.createDevbox({
name,
runtime: DevboxRuntime.TEST_AGENT,
resource: { cpu: 1, memory: 2 },
})

console.log(`✅ Devbox created: ${devbox.name}`)
console.log('⏳ Starting devbox...')

// 2. Start devbox
await devbox.start()

// 3. Wait for devbox to be ready
let currentDevbox = await sdk.getDevbox(name)
const startTime = Date.now()
const timeout = 30000 // 30 seconds

while (currentDevbox.status !== 'Running' && Date.now() - startTime < timeout) {
await new Promise(resolve => setTimeout(resolve, 2000))
currentDevbox = await sdk.getDevbox(name)
process.stdout.write('.')
}

console.log('')
console.log(`✅ Devbox is ${currentDevbox.status}`)

if (currentDevbox.status !== 'Running') {
throw new Error(`Devbox failed to start. Status: ${currentDevbox.status}`)
}

// 4. Execute commands in the devbox
console.log('')
console.log('🔍 Testing command execution...')

// Method 1: Execute command with arguments
const homeResult1 = await currentDevbox.execSync({
command: 'echo',
args: ['$HOME'],
})
console.log(`📁 HOME: ${homeResult1.stdout.trim()}`)

// Method 2: Execute command with environment variable expansion
const homeResult2 = await currentDevbox.execSync({
command: 'echo',
args: ['My home is $HOME'],
})
console.log(`📁 Result: ${homeResult2.stdout.trim()}`)

// Method 3: Execute shell command with pipes
const homeResult3 = await currentDevbox.execSync({
command: 'echo $HOME | wc -c',
})
console.log(`📁 HOME length: ${homeResult3.stdout.trim()} characters`)

// 5. Additional operations can be added here:
// - File operations (writeFile, readFile, listFiles)
// - Git operations (clone, pull, push)
// - Process management (exec, getProcessStatus)
// - File watching (watchFiles)

console.log('')
console.log('🎉 Full lifecycle example completed successfully!')

} catch (error) {
console.error('❌ Error occurred:', error)
throw error
} finally {
// 6. Always clean up resources
try {
const devboxToDelete = await sdk.getDevbox(name).catch(() => null)
if (devboxToDelete) {
console.log(`🧹 Cleaning up devbox: ${name}`)
await devboxToDelete.delete()
console.log('✅ Devbox deleted successfully')
}
} catch (error) {
console.warn('⚠️ Failed to delete devbox:', error)
}

await sdk.close()
console.log('✅ SDK connections closed')
}
}

main().catch((error) => {
console.error('Failed to run example:', error)
process.exit(1)
})
```

## Key Features Demonstrated

### 1. Environment Configuration

The example shows how to:
- Load environment variables from multiple possible locations
- Handle kubeconfig as both file path and content string
- Configure SDK with appropriate timeouts and retry settings

### 2. Devbox Lifecycle Management

- **Creation**: Create a devbox with specified runtime and resources
- **Starting**: Start the devbox instance
- **Status Checking**: Poll for devbox status until it's ready
- **Cleanup**: Properly delete the devbox and close SDK connections

### 3. Command Execution

The example demonstrates three methods of executing commands:
- Direct command execution with arguments
- Environment variable expansion in commands
- Shell features like pipes

### 4. Error Handling

- Try-catch blocks for error handling
- Proper cleanup in finally block
- Graceful handling of cleanup errors

## Running the Example

1. **Install dependencies**:

```bash
npm install @labring/devbox-sdk dotenv
```

2. **Set up environment variables**:

Create a `.env` file or set the `KUBECONFIG` environment variable:

```bash
export KUBECONFIG=/path/to/your/kubeconfig
```

Or in a `.env` file:

```
KUBECONFIG=/path/to/your/kubeconfig
```

3. **Run the example**:

```bash
node full-lifecycle.js
```

## Best Practices

1. **Always clean up**: Use try-finally blocks to ensure resources are cleaned up even if errors occur
2. **Generate unique names**: Use timestamps and random numbers to avoid naming conflicts
3. **Wait for readiness**: Always wait for devbox to be in "Running" status before executing commands
4. **Handle timeouts**: Set appropriate timeouts for operations that might take time
5. **Error handling**: Catch and handle errors appropriately, logging useful information

## Next Steps

- Learn about [File Operations](/docs/guides/file-operations)
- Explore [Git Integration](/docs/guides/git-integration)
- Read the [API Reference](/docs/api/devbox-sdk)

Loading
Loading