From 4d593a769cbc83442f45eb3dd72cca77e7f3ccdf Mon Sep 17 00:00:00 2001 From: katereznykova Date: Sun, 19 Oct 2025 19:00:08 +0100 Subject: [PATCH 01/16] websockets lightweight wrapper --- examples/websocket/.gitignore | 7 + examples/websocket/README.md | 564 +++++++ examples/websocket/package-lock.json | 1589 ++++++++++++++++++ examples/websocket/package.json | 22 + examples/websocket/src/index-with-helpers.ts | 254 +++ examples/websocket/src/index.ts | 767 +++++++++ examples/websocket/tsconfig.json | 18 + examples/websocket/wrangler.jsonc | 36 + packages/sandbox/src/index.ts | 13 + packages/sandbox/src/websocket.ts | 417 +++++ 10 files changed, 3687 insertions(+) create mode 100644 examples/websocket/.gitignore create mode 100644 examples/websocket/README.md create mode 100644 examples/websocket/package-lock.json create mode 100644 examples/websocket/package.json create mode 100644 examples/websocket/src/index-with-helpers.ts create mode 100644 examples/websocket/src/index.ts create mode 100644 examples/websocket/tsconfig.json create mode 100644 examples/websocket/wrangler.jsonc create mode 100644 packages/sandbox/src/websocket.ts diff --git a/examples/websocket/.gitignore b/examples/websocket/.gitignore new file mode 100644 index 00000000..dd7799e6 --- /dev/null +++ b/examples/websocket/.gitignore @@ -0,0 +1,7 @@ +node_modules/ +dist/ +.wrangler/ +.dev.vars +.env +*.log +.DS_Store diff --git a/examples/websocket/README.md b/examples/websocket/README.md new file mode 100644 index 00000000..ad2003f5 --- /dev/null +++ b/examples/websocket/README.md @@ -0,0 +1,564 @@ +# WebSocket Examples for Sandbox SDK + +This example demonstrates how to use WebSockets with the Cloudflare Sandbox SDK for real-time, bidirectional communication between clients and sandboxed containers. + +## Setup + +```bash +# Install dependencies +npm install + +# Run locally +npm run dev + +# Deploy to Cloudflare +npm run deploy +``` + +## Usage + +### Local Development + +1. Start the development server: + ```bash + npm run dev + ``` + +2. Open your browser to `http://localhost:8787` + + +### WebSocket Endpoints + +#### `/ws/echo` +Basic echo server with sandbox command execution. + +**Client Message Format:** +```json +{ + "type": "echo", + "data": "Hello, sandbox!" +} +``` + +```json +{ + "type": "execute", + "command": "python --version" +} +``` + +**Server Response Format:** +```json +{ + "type": "echo", + "data": "Hello, sandbox!", + "timestamp": 1234567890 +} +``` + +```json +{ + "type": "result", + "stdout": "Python 3.11.0\n", + "stderr": "", + "exitCode": 0 +} +``` + +#### `/ws/code` +Real-time code execution with streaming output. + +**Client Message Format:** +```json +{ + "type": "execute", + "code": "print('Hello from Python')", + "language": "python", + "sessionId": "session-123" +} +``` + +**Server Response Format:** +```json +{ + "type": "stdout", + "data": "Hello from Python\n", + "sessionId": "session-123" +} +``` + +```json +{ + "type": "result", + "sessionId": "session-123", + "results": [...], + "error": null, + "logs": { "stdout": [...], "stderr": [...] } +} +``` + +#### `/ws/process` +Stream output from long-running processes. + +**Client Message Format:** +```json +{ + "type": "start", + "command": "ping", + "args": ["-c", "5", "cloudflare.com"] +} +``` + +```json +{ + "type": "kill" +} +``` + +**Server Response Format:** +```json +{ + "type": "started", + "pid": 12345 +} +``` + +```json +{ + "type": "stdout", + "data": "PING cloudflare.com...\n", + "pid": 12345 +} +``` + +```json +{ + "type": "completed", + "pid": 12345 +} +``` + +#### `/ws/terminal` +Interactive terminal session. + +**Client Message Format:** +``` +ls -la\n +``` + +```json +{ + "type": "resize", + "rows": 24, + "cols": 80 +} +``` + +**Server Response:** +Raw terminal output or JSON status messages. + +## Code Examples + +### JavaScript Client + +```javascript +// Connect to echo server +const ws = new WebSocket('wss://your-worker.workers.dev/ws/echo?id=my-session'); + +ws.onopen = () => { + console.log('Connected'); + + // Send echo message + ws.send(JSON.stringify({ + type: 'echo', + data: 'Hello!' + })); + + // Execute command + ws.send(JSON.stringify({ + type: 'execute', + command: 'python -c "print(2+2)"' + })); +}; + +ws.onmessage = (event) => { + const data = JSON.parse(event.data); + console.log('Received:', data); +}; + +ws.onclose = () => { + console.log('Disconnected'); +}; +``` + +### Python Client + +```python +import asyncio +import websockets +import json + +async def execute_code(): + uri = "wss://your-worker.workers.dev/ws/code?id=my-session" + + async with websockets.connect(uri) as websocket: + # Send code to execute + await websocket.send(json.dumps({ + "type": "execute", + "code": """ +import time +for i in range(5): + print(f'Count: {i}') + time.sleep(0.5) + """, + "sessionId": "test-1" + })) + + # Receive streaming output + while True: + try: + message = await websocket.recv() + data = json.loads(message) + + if data['type'] == 'stdout': + print(data['data'], end='') + elif data['type'] == 'result': + print('Execution complete') + break + except websockets.exceptions.ConnectionClosed: + break + +asyncio.run(execute_code()) +``` + +### Node.js Client + +```javascript +import WebSocket from 'ws'; + +const ws = new WebSocket('ws://localhost:8787/ws/process?id=node-client'); + +ws.on('open', () => { + console.log('Connected to process streamer'); + + // Start a long-running process + ws.send(JSON.stringify({ + type: 'start', + command: 'python', + args: ['-u', 'long_script.py'] + })); +}); + +ws.on('message', (data) => { + const message = JSON.parse(data); + + if (message.type === 'stdout' || message.type === 'stderr') { + process.stdout.write(message.data); + } else if (message.type === 'completed') { + console.log('Process completed'); + ws.close(); + } +}); + +// Kill process after 10 seconds +setTimeout(() => { + ws.send(JSON.stringify({ type: 'kill' })); +}, 10000); +``` + +## Use Cases + +### 1. Real-Time Data Analysis + +Stream data processing results as they're computed: + +```javascript +const ws = new WebSocket('wss://your-worker.workers.dev/ws/code'); + +ws.send(JSON.stringify({ + type: 'execute', + code: ` +import pandas as pd +import time + +for chunk in pd.read_csv('large_file.csv', chunksize=1000): + result = chunk.describe() + print(result) + time.sleep(0.1) + `, + sessionId: 'analysis-1' +})); +``` + +### 2. AI Code Agent + +AI agent that generates and executes code with real-time feedback: + +```javascript +// Generate code with AI +const code = await generateWithAI(userPrompt); + +// Execute and stream results +ws.send(JSON.stringify({ + type: 'execute', + code: code, + sessionId: 'ai-agent-1' +})); + +// User sees live output as code runs +ws.onmessage = (event) => { + const data = JSON.parse(event.data); + if (data.type === 'stdout') { + updateUI(data.data); + } +}; +``` + +### 3. Collaborative IDE + +Multiple users share a sandbox: + +```javascript +// User A's connection +const wsA = new WebSocket('wss://your-worker.workers.dev/ws/code?id=shared-123'); + +// User B's connection (same sandbox) +const wsB = new WebSocket('wss://your-worker.workers.dev/ws/code?id=shared-123'); + +// Both see the same execution results +wsA.send(JSON.stringify({ + type: 'execute', + code: 'x = 42' +})); + +wsB.send(JSON.stringify({ + type: 'execute', + code: 'print(x)' // Prints 42 from shared context +})); +``` + +### 4. Live Monitoring + +Monitor sandbox metrics and logs: + +```javascript +const ws = new WebSocket('wss://your-worker.workers.dev/ws/process'); + +ws.send(JSON.stringify({ + type: 'start', + command: 'top', + args: ['-b', '-d', '1'] // Update every second +})); + +// Real-time system monitoring +ws.onmessage = (event) => { + const data = JSON.parse(event.data); + if (data.type === 'stdout') { + updateMonitoringDashboard(data.data); + } +}; +``` + +## Best Practices + +### 1. Error Handling + +Always handle errors gracefully: + +```javascript +ws.onerror = (error) => { + console.error('WebSocket error:', error); + // Attempt reconnection + setTimeout(() => reconnect(), 1000); +}; + +ws.onclose = (event) => { + if (event.code !== 1000) { // Not a normal closure + console.log('Unexpected close, reconnecting...'); + reconnect(); + } +}; +``` + +### 2. Heartbeat/Ping-Pong + +Keep connections alive: + +```javascript +let pingInterval; + +ws.onopen = () => { + // Send ping every 30 seconds + pingInterval = setInterval(() => { + ws.send(JSON.stringify({ type: 'ping' })); + }, 30000); +}; + +ws.onclose = () => { + clearInterval(pingInterval); +}; +``` + +### 3. Message Buffering + +Buffer messages when disconnected: + +```javascript +const messageQueue = []; +let isConnected = false; + +function sendMessage(msg) { + if (isConnected) { + ws.send(JSON.stringify(msg)); + } else { + messageQueue.push(msg); + } +} + +ws.onopen = () => { + isConnected = true; + // Flush queue + while (messageQueue.length > 0) { + ws.send(JSON.stringify(messageQueue.shift())); + } +}; +``` + +### 4. Rate Limiting + +Prevent overwhelming the sandbox: + +```javascript +class RateLimitedWebSocket { + constructor(url, messagesPerSecond = 10) { + this.ws = new WebSocket(url); + this.queue = []; + this.limit = messagesPerSecond; + this.interval = 1000 / messagesPerSecond; + + setInterval(() => this.processQueue(), this.interval); + } + + send(message) { + this.queue.push(message); + } + + processQueue() { + if (this.queue.length > 0 && this.ws.readyState === 1) { + this.ws.send(this.queue.shift()); + } + } +} +``` + +## Security Considerations + +### Authentication + +Add authentication to WebSocket connections: + +```typescript +// Server side +const token = new URL(request.url).searchParams.get('token'); +if (!token || !(await verifyToken(token))) { + return new Response('Unauthorized', { status: 401 }); +} +``` + +### Input Validation + +Always validate and sanitize inputs: + +```typescript +server.addEventListener('message', async (event) => { + const message = JSON.parse(event.data); + + // Validate message structure + if (!message.type || typeof message.type !== 'string') { + server.send(JSON.stringify({ type: 'error', message: 'Invalid format' })); + return; + } + + // Prevent command injection + if (message.command && /[;&|`$]/.test(message.command)) { + server.send(JSON.stringify({ type: 'error', message: 'Invalid characters' })); + return; + } +}); +``` + +### Resource Limits + +Set limits on connections and execution time: + +```typescript +const MAX_CONNECTIONS = 100; +const MAX_EXECUTION_TIME = 60000; // 60 seconds + +if (activeConnections.size >= MAX_CONNECTIONS) { + server.close(1008, 'Connection limit reached'); + return; +} + +// Set execution timeout +const timeout = setTimeout(() => { + server.close(1000, 'Execution timeout'); +}, MAX_EXECUTION_TIME); +``` + +## Troubleshooting + +### Connection Refused + +Check that WebSocket upgrades are properly handled: +- Verify `Upgrade: websocket` header is present +- Ensure status code 101 is returned +- Check that WebSocketPair is created correctly + +### Messages Not Received + +Ensure proper message formatting: +- Use `JSON.stringify()` for structured data +- Check for serialization errors +- Verify server is calling `server.accept()` + +### Connection Drops + +Implement reconnection logic: +```javascript +let reconnectAttempts = 0; +const MAX_RECONNECT_ATTEMPTS = 5; + +function connect() { + const ws = new WebSocket(url); + + ws.onclose = () => { + if (reconnectAttempts < MAX_RECONNECT_ATTEMPTS) { + reconnectAttempts++; + setTimeout(connect, 1000 * reconnectAttempts); + } + }; + + ws.onopen = () => { + reconnectAttempts = 0; + }; +} +``` + +## Performance Tips + +1. **Use Binary Frames** for large data transfers +2. **Buffer Small Messages** to reduce syscalls +3. **Implement Backpressure** to handle slow clients +4. **Use Compression** for text-heavy streams +5. **Batch Updates** when sending frequent small updates + +## Further Reading + +- [Cloudflare Workers WebSocket Documentation](https://developers.cloudflare.com/workers/runtime-apis/websockets/) +- [Sandbox SDK Documentation](https://developers.cloudflare.com/sandbox/) +- [WebSocket RFC 6455](https://datatracker.ietf.org/doc/html/rfc6455) + +## License + +MIT diff --git a/examples/websocket/package-lock.json b/examples/websocket/package-lock.json new file mode 100644 index 00000000..3c89098a --- /dev/null +++ b/examples/websocket/package-lock.json @@ -0,0 +1,1589 @@ +{ + "name": "@cloudflare/sandbox-websocket-example", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "@cloudflare/sandbox-websocket-example", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "@cloudflare/sandbox": "*" + }, + "devDependencies": { + "@cloudflare/workers-types": "^4.20250111.0", + "typescript": "^5.3.3", + "wrangler": "^4.43.0" + } + }, + "node_modules/@cloudflare/containers": { + "version": "0.0.28", + "resolved": "https://registry.npmjs.org/@cloudflare/containers/-/containers-0.0.28.tgz", + "integrity": "sha512-wzR9UWcGvZ9znd4elkXklilPcHX6srncsjSkx696SZRZyTygNbWsLlHegvc1C+e9gn28HRZU3dLiAzXiC9IY1w==", + "license": "ISC" + }, + "node_modules/@cloudflare/kv-asset-handler": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.4.0.tgz", + "integrity": "sha512-+tv3z+SPp+gqTIcImN9o0hqE9xyfQjI1XD9pL6NuKjua9B1y7mNYv0S9cP+QEbA4ppVgGZEmKOvHX5G5Ei1CVA==", + "dev": true, + "license": "MIT OR Apache-2.0", + "dependencies": { + "mime": "^3.0.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@cloudflare/sandbox": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@cloudflare/sandbox/-/sandbox-0.4.3.tgz", + "integrity": "sha512-ODynUVKLID9viGLDDnFpWXNToy4vvN2WCQliJiWvtgBee8K1WiRDI3SYzUHFt3onV8kBHKjkoCbADQHOPBAllA==", + "license": "ISC", + "dependencies": { + "@cloudflare/containers": "^0.0.28" + } + }, + "node_modules/@cloudflare/unenv-preset": { + "version": "2.7.7", + "resolved": "https://registry.npmjs.org/@cloudflare/unenv-preset/-/unenv-preset-2.7.7.tgz", + "integrity": "sha512-HtZuh166y0Olbj9bqqySckz0Rw9uHjggJeoGbDx5x+sgezBXlxO6tQSig2RZw5tgObF8mWI8zaPvQMkQZtAODw==", + "dev": true, + "license": "MIT OR Apache-2.0", + "peerDependencies": { + "unenv": "2.0.0-rc.21", + "workerd": "^1.20250927.0" + }, + "peerDependenciesMeta": { + "workerd": { + "optional": true + } + } + }, + "node_modules/@cloudflare/workerd-darwin-64": { + "version": "1.20251008.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20251008.0.tgz", + "integrity": "sha512-yph0H+8mMOK5Z9oDwjb8rI96oTVt4no5lZ43aorcbzsWG9VUIaXSXlBBoB3von6p4YCRW+J3n36fBM9XZ6TLaA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@cloudflare/workerd-darwin-arm64": { + "version": "1.20251008.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20251008.0.tgz", + "integrity": "sha512-Yc4lMGSbM4AEtYRpyDpmk77MsHb6X2BSwJgMgGsLVPmckM7ZHivZkJChfcNQjZ/MGR6nkhYc4iF6TcVS+UMEVw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@cloudflare/workerd-linux-64": { + "version": "1.20251008.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20251008.0.tgz", + "integrity": "sha512-AjoQnylw4/5G6SmfhZRsli7EuIK7ZMhmbxtU0jkpciTlVV8H01OsFOgS1d8zaTXMfkWamEfMouy8oH/L7B9YcQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@cloudflare/workerd-linux-arm64": { + "version": "1.20251008.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20251008.0.tgz", + "integrity": "sha512-hRy9yyvzVq1HsqHZUmFkAr0C8JGjAD/PeeVEGCKL3jln3M9sNCKIrbDXiL+efe+EwajJNNlDxpO+s30uVWVaRg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@cloudflare/workerd-windows-64": { + "version": "1.20251008.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20251008.0.tgz", + "integrity": "sha512-Gm0RR+ehfNMsScn2pUcn3N9PDUpy7FyvV9ecHEyclKttvztyFOcmsF14bxEaSVv7iM4TxWEBn1rclmYHxDM4ow==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@cloudflare/workers-types": { + "version": "4.20251011.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workers-types/-/workers-types-4.20251011.0.tgz", + "integrity": "sha512-gQpih+pbq3sP4uXltUeCSbPgZxTNp2gQd8639SaIbQMwgA6oJNHLhIART1fWy6DQACngiRzDVULA2x0ohmkGTQ==", + "dev": true, + "license": "MIT OR Apache-2.0" + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.5.0.tgz", + "integrity": "sha512-97/BJ3iXHww3djw6hYIfErCZFee7qCtrneuLa20UXFCOTCfBM2cvQHjWJ2EG0s0MtdNwInarqCTz35i4wWXHsQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.4.tgz", + "integrity": "sha512-1VCICWypeQKhVbE9oW/sJaAmjLxhVqacdkvPLEjwlttjfwENRSClS8EjBz0KzRyFSCPDIkuXW34Je/vk7zdB7Q==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.4.tgz", + "integrity": "sha512-QNdQEps7DfFwE3hXiU4BZeOV68HHzYwGd0Nthhd3uCkkEKK7/R6MTgM0P7H7FAs5pU/DIWsviMmEGxEoxIZ+ZQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.4.tgz", + "integrity": "sha512-bBy69pgfhMGtCnwpC/x5QhfxAz/cBgQ9enbtwjf6V9lnPI/hMyT9iWpR1arm0l3kttTr4L0KSLpKmLp/ilKS9A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.4.tgz", + "integrity": "sha512-TVhdVtQIFuVpIIR282btcGC2oGQoSfZfmBdTip2anCaVYcqWlZXGcdcKIUklfX2wj0JklNYgz39OBqh2cqXvcQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.4.tgz", + "integrity": "sha512-Y1giCfM4nlHDWEfSckMzeWNdQS31BQGs9/rouw6Ub91tkK79aIMTH3q9xHvzH8d0wDru5Ci0kWB8b3up/nl16g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.4.tgz", + "integrity": "sha512-CJsry8ZGM5VFVeyUYB3cdKpd/H69PYez4eJh1W/t38vzutdjEjtP7hB6eLKBoOdxcAlCtEYHzQ/PJ/oU9I4u0A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.4.tgz", + "integrity": "sha512-yYq+39NlTRzU2XmoPW4l5Ifpl9fqSk0nAJYM/V/WUGPEFfek1epLHJIkTQM6bBs1swApjO5nWgvr843g6TjxuQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.4.tgz", + "integrity": "sha512-0FgvOJ6UUMflsHSPLzdfDnnBBVoCDtBTVyn/MrWloUNvq/5SFmh13l3dvgRPkDihRxb77Y17MbqbCAa2strMQQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.4.tgz", + "integrity": "sha512-kro4c0P85GMfFYqW4TWOpvmF8rFShbWGnrLqlzp4X1TNWjRY3JMYUfDCtOxPKOIY8B0WC8HN51hGP4I4hz4AaQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.4.tgz", + "integrity": "sha512-+89UsQTfXdmjIvZS6nUnOOLoXnkUTB9hR5QAeLrQdzOSWZvNSAXAtcRDHWtqAUtAmv7ZM1WPOOeSxDzzzMogiQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.4.tgz", + "integrity": "sha512-yTEjoapy8UP3rv8dB0ip3AfMpRbyhSN3+hY8mo/i4QXFeDxmiYbEKp3ZRjBKcOP862Ua4b1PDfwlvbuwY7hIGQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.4.tgz", + "integrity": "sha512-NeqqYkrcGzFwi6CGRGNMOjWGGSYOpqwCjS9fvaUlX5s3zwOtn1qwg1s2iE2svBe4Q/YOG1q6875lcAoQK/F4VA==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.4.tgz", + "integrity": "sha512-IcvTlF9dtLrfL/M8WgNI/qJYBENP3ekgsHbYUIzEzq5XJzzVEV/fXY9WFPfEEXmu3ck2qJP8LG/p3Q8f7Zc2Xg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.4.tgz", + "integrity": "sha512-HOy0aLTJTVtoTeGZh4HSXaO6M95qu4k5lJcH4gxv56iaycfz1S8GO/5Jh6X4Y1YiI0h7cRyLi+HixMR+88swag==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.4.tgz", + "integrity": "sha512-i8JUDAufpz9jOzo4yIShCTcXzS07vEgWzyX3NH2G7LEFVgrLEhjwL3ajFE4fZI3I4ZgiM7JH3GQ7ReObROvSUA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.4.tgz", + "integrity": "sha512-jFnu+6UbLlzIjPQpWCNh5QtrcNfMLjgIavnwPQAfoGx4q17ocOU9MsQ2QVvFxwQoWpZT8DvTLooTvmOQXkO51g==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.4.tgz", + "integrity": "sha512-6e0cvXwzOnVWJHq+mskP8DNSrKBr1bULBvnFLpc1KY+d+irZSgZ02TGse5FsafKS5jg2e4pbvK6TPXaF/A6+CA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.4.tgz", + "integrity": "sha512-vUnkBYxZW4hL/ie91hSqaSNjulOnYXE1VSLusnvHg2u3jewJBz3YzB9+oCw8DABeVqZGg94t9tyZFoHma8gWZQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.4.tgz", + "integrity": "sha512-XAg8pIQn5CzhOB8odIcAm42QsOfa98SBeKUdo4xa8OvX8LbMZqEtgeWE9P/Wxt7MlG2QqvjGths+nq48TrUiKw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.4.tgz", + "integrity": "sha512-Ct2WcFEANlFDtp1nVAXSNBPDxyU+j7+tId//iHXU2f/lN5AmO4zLyhDcpR5Cz1r08mVxzt3Jpyt4PmXQ1O6+7A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.4.tgz", + "integrity": "sha512-xAGGhyOQ9Otm1Xu8NT1ifGLnA6M3sJxZ6ixylb+vIUVzvvd6GOALpwQrYrtlPouMqd/vSbgehz6HaVk4+7Afhw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.4.tgz", + "integrity": "sha512-Mw+tzy4pp6wZEK0+Lwr76pWLjrtjmJyUB23tHKqEDP74R3q95luY/bXqXZeYl4NYlvwOqoRKlInQialgCKy67Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.4.tgz", + "integrity": "sha512-AVUP428VQTSddguz9dO9ngb+E5aScyg7nOeJDrF1HPYu555gmza3bDGMPhmVXL8svDSoqPCsCPjb265yG/kLKQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.4.tgz", + "integrity": "sha512-i1sW+1i+oWvQzSgfRcxxG2k4I9n3O9NRqy8U+uugaT2Dy7kLO9Y7wI72haOahxceMX8hZAzgGou1FhndRldxRg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.4.tgz", + "integrity": "sha512-nOT2vZNw6hJ+z43oP1SPea/G/6AbN6X+bGNhNuq8NtRHy4wsMhw765IKLNmnjek7GvjWBYQ8Q5VBoYTFg9y1UQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz", + "integrity": "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.0.4" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.5.tgz", + "integrity": "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.0.4" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.4.tgz", + "integrity": "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.4.tgz", + "integrity": "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz", + "integrity": "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz", + "integrity": "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.4.tgz", + "integrity": "sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz", + "integrity": "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.4.tgz", + "integrity": "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.4.tgz", + "integrity": "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz", + "integrity": "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.0.5" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz", + "integrity": "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.0.4" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.5.tgz", + "integrity": "sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.0.4" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz", + "integrity": "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.0.4" + } + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.5.tgz", + "integrity": "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.0.4" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.5.tgz", + "integrity": "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.0.4" + } + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.33.5.tgz", + "integrity": "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.2.0" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-ia32": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.5.tgz", + "integrity": "sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz", + "integrity": "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@poppinss/colors": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@poppinss/colors/-/colors-4.1.5.tgz", + "integrity": "sha512-FvdDqtcRCtz6hThExcFOgW0cWX+xwSMWcRuQe5ZEb2m7cVQOAVZOIMt+/v9RxGiD9/OY16qJBXK4CVKWAPalBw==", + "dev": true, + "license": "MIT", + "dependencies": { + "kleur": "^4.1.5" + } + }, + "node_modules/@poppinss/dumper": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/@poppinss/dumper/-/dumper-0.6.4.tgz", + "integrity": "sha512-iG0TIdqv8xJ3Lt9O8DrPRxw1MRLjNpoqiSGU03P/wNLP/s0ra0udPJ1J2Tx5M0J3H/cVyEgpbn8xUKRY9j59kQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@poppinss/colors": "^4.1.5", + "@sindresorhus/is": "^7.0.2", + "supports-color": "^10.0.0" + } + }, + "node_modules/@poppinss/exception": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@poppinss/exception/-/exception-1.2.2.tgz", + "integrity": "sha512-m7bpKCD4QMlFCjA/nKTs23fuvoVFoA83brRKmObCUNmi/9tVu8Ve3w4YQAnJu4q3Tjf5fr685HYIC/IA2zHRSg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@sindresorhus/is": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-7.1.0.tgz", + "integrity": "sha512-7F/yz2IphV39hiS2zB4QYVkivrptHHh0K8qJJd9HhuWSdvf8AN7NpebW3CcDZDBQsUPMoDKWsY2WWgW7bqOcfA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@speed-highlight/core": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@speed-highlight/core/-/core-1.2.7.tgz", + "integrity": "sha512-0dxmVj4gxg3Jg879kvFS/msl4s9F3T9UXC1InxgOf7t5NvcPD97u/WTA5vL/IxWHMn7qSxBozqrnnE2wvl1m8g==", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/acorn": { + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", + "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/blake3-wasm": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/blake3-wasm/-/blake3-wasm-2.1.5.tgz", + "integrity": "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==", + "dev": true, + "license": "MIT" + }, + "node_modules/color": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", + "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1", + "color-string": "^1.9.0" + }, + "engines": { + "node": ">=12.5.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "node_modules/cookie": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz", + "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/defu": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", + "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", + "dev": true, + "license": "MIT" + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/error-stack-parser-es": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/error-stack-parser-es/-/error-stack-parser-es-1.0.5.tgz", + "integrity": "sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/esbuild": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.4.tgz", + "integrity": "sha512-8pgjLUcUjcgDg+2Q4NYXnPbo/vncAY4UmyaCm0jZevERqCHZIaWwdJHkf8XQtu4AxSKCdvrUbT0XUr1IdZzI8Q==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.4", + "@esbuild/android-arm": "0.25.4", + "@esbuild/android-arm64": "0.25.4", + "@esbuild/android-x64": "0.25.4", + "@esbuild/darwin-arm64": "0.25.4", + "@esbuild/darwin-x64": "0.25.4", + "@esbuild/freebsd-arm64": "0.25.4", + "@esbuild/freebsd-x64": "0.25.4", + "@esbuild/linux-arm": "0.25.4", + "@esbuild/linux-arm64": "0.25.4", + "@esbuild/linux-ia32": "0.25.4", + "@esbuild/linux-loong64": "0.25.4", + "@esbuild/linux-mips64el": "0.25.4", + "@esbuild/linux-ppc64": "0.25.4", + "@esbuild/linux-riscv64": "0.25.4", + "@esbuild/linux-s390x": "0.25.4", + "@esbuild/linux-x64": "0.25.4", + "@esbuild/netbsd-arm64": "0.25.4", + "@esbuild/netbsd-x64": "0.25.4", + "@esbuild/openbsd-arm64": "0.25.4", + "@esbuild/openbsd-x64": "0.25.4", + "@esbuild/sunos-x64": "0.25.4", + "@esbuild/win32-arm64": "0.25.4", + "@esbuild/win32-ia32": "0.25.4", + "@esbuild/win32-x64": "0.25.4" + } + }, + "node_modules/exit-hook": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-2.2.1.tgz", + "integrity": "sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/exsolve": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.7.tgz", + "integrity": "sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/is-arrayish": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.4.tgz", + "integrity": "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/kleur": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", + "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/mime": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", + "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", + "dev": true, + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/miniflare": { + "version": "4.20251008.0", + "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-4.20251008.0.tgz", + "integrity": "sha512-sKCNYNzXG6l8qg0Oo7y8WcDKcpbgw0qwZsxNpdZilFTR4EavRow2TlcwuPSVN99jqAjhz0M4VXvTdSGdtJ2VfQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspotcode/source-map-support": "0.8.1", + "acorn": "8.14.0", + "acorn-walk": "8.3.2", + "exit-hook": "2.2.1", + "glob-to-regexp": "0.4.1", + "sharp": "^0.33.5", + "stoppable": "1.1.0", + "undici": "7.14.0", + "workerd": "1.20251008.0", + "ws": "8.18.0", + "youch": "4.1.0-beta.10", + "zod": "3.22.3" + }, + "bin": { + "miniflare": "bootstrap.js" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/ohash": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz", + "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-to-regexp": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz", + "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/sharp": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz", + "integrity": "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==", + "dev": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "color": "^4.2.3", + "detect-libc": "^2.0.3", + "semver": "^7.6.3" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.33.5", + "@img/sharp-darwin-x64": "0.33.5", + "@img/sharp-libvips-darwin-arm64": "1.0.4", + "@img/sharp-libvips-darwin-x64": "1.0.4", + "@img/sharp-libvips-linux-arm": "1.0.5", + "@img/sharp-libvips-linux-arm64": "1.0.4", + "@img/sharp-libvips-linux-s390x": "1.0.4", + "@img/sharp-libvips-linux-x64": "1.0.4", + "@img/sharp-libvips-linuxmusl-arm64": "1.0.4", + "@img/sharp-libvips-linuxmusl-x64": "1.0.4", + "@img/sharp-linux-arm": "0.33.5", + "@img/sharp-linux-arm64": "0.33.5", + "@img/sharp-linux-s390x": "0.33.5", + "@img/sharp-linux-x64": "0.33.5", + "@img/sharp-linuxmusl-arm64": "0.33.5", + "@img/sharp-linuxmusl-x64": "0.33.5", + "@img/sharp-wasm32": "0.33.5", + "@img/sharp-win32-ia32": "0.33.5", + "@img/sharp-win32-x64": "0.33.5" + } + }, + "node_modules/simple-swizzle": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.4.tgz", + "integrity": "sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, + "node_modules/stoppable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stoppable/-/stoppable-1.1.0.tgz", + "integrity": "sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4", + "npm": ">=6" + } + }, + "node_modules/supports-color": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-10.2.2.tgz", + "integrity": "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD", + "optional": true + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/ufo": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.1.tgz", + "integrity": "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==", + "dev": true, + "license": "MIT" + }, + "node_modules/undici": { + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.14.0.tgz", + "integrity": "sha512-Vqs8HTzjpQXZeXdpsfChQTlafcMQaaIwnGwLam1wudSSjlJeQ3bw1j+TLPePgrCnCpUXx7Ba5Pdpf5OBih62NQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.18.1" + } + }, + "node_modules/unenv": { + "version": "2.0.0-rc.21", + "resolved": "https://registry.npmjs.org/unenv/-/unenv-2.0.0-rc.21.tgz", + "integrity": "sha512-Wj7/AMtE9MRnAXa6Su3Lk0LNCfqDYgfwVjwRFVum9U7wsto1imuHqk4kTm7Jni+5A0Hn7dttL6O/zjvUvoo+8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "defu": "^6.1.4", + "exsolve": "^1.0.7", + "ohash": "^2.0.11", + "pathe": "^2.0.3", + "ufo": "^1.6.1" + } + }, + "node_modules/workerd": { + "version": "1.20251008.0", + "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20251008.0.tgz", + "integrity": "sha512-HwaJmXO3M1r4S8x2ea2vy8Rw/y/38HRQuK/gNDRQ7w9cJXn6xSl1sIIqKCffULSUjul3wV3I3Nd/GfbmsRReEA==", + "dev": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "bin": { + "workerd": "bin/workerd" + }, + "engines": { + "node": ">=16" + }, + "optionalDependencies": { + "@cloudflare/workerd-darwin-64": "1.20251008.0", + "@cloudflare/workerd-darwin-arm64": "1.20251008.0", + "@cloudflare/workerd-linux-64": "1.20251008.0", + "@cloudflare/workerd-linux-arm64": "1.20251008.0", + "@cloudflare/workerd-windows-64": "1.20251008.0" + } + }, + "node_modules/wrangler": { + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-4.43.0.tgz", + "integrity": "sha512-IBNqXlYHSUSCNNWj/tQN4hFiQy94l7fTxEnJWETXyW69+cjUyjQ7MfeoId3vIV9KBgY8y5M5uf2XulU95OikJg==", + "dev": true, + "license": "MIT OR Apache-2.0", + "dependencies": { + "@cloudflare/kv-asset-handler": "0.4.0", + "@cloudflare/unenv-preset": "2.7.7", + "blake3-wasm": "2.1.5", + "esbuild": "0.25.4", + "miniflare": "4.20251008.0", + "path-to-regexp": "6.3.0", + "unenv": "2.0.0-rc.21", + "workerd": "1.20251008.0" + }, + "bin": { + "wrangler": "bin/wrangler.js", + "wrangler2": "bin/wrangler.js" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + }, + "peerDependencies": { + "@cloudflare/workers-types": "^4.20251008.0" + }, + "peerDependenciesMeta": { + "@cloudflare/workers-types": { + "optional": true + } + } + }, + "node_modules/ws": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/youch": { + "version": "4.1.0-beta.10", + "resolved": "https://registry.npmjs.org/youch/-/youch-4.1.0-beta.10.tgz", + "integrity": "sha512-rLfVLB4FgQneDr0dv1oddCVZmKjcJ6yX6mS4pU82Mq/Dt9a3cLZQ62pDBL4AUO+uVrCvtWz3ZFUL2HFAFJ/BXQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@poppinss/colors": "^4.1.5", + "@poppinss/dumper": "^0.6.4", + "@speed-highlight/core": "^1.2.7", + "cookie": "^1.0.2", + "youch-core": "^0.3.3" + } + }, + "node_modules/youch-core": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/youch-core/-/youch-core-0.3.3.tgz", + "integrity": "sha512-ho7XuGjLaJ2hWHoK8yFnsUGy2Y5uDpqSTq1FkHLK4/oqKtyUU1AFbOOxY4IpC9f0fTLjwYbslUz0Po5BpD1wrA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@poppinss/exception": "^1.2.2", + "error-stack-parser-es": "^1.0.5" + } + }, + "node_modules/zod": { + "version": "3.22.3", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.3.tgz", + "integrity": "sha512-EjIevzuJRiRPbVH4mGc8nApb/lVLKVpmUhAaR5R5doKGfAnGJ6Gr3CViAVjP+4FWSxCsybeWQdcgCtbX+7oZug==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + } + } +} diff --git a/examples/websocket/package.json b/examples/websocket/package.json new file mode 100644 index 00000000..75c12cb3 --- /dev/null +++ b/examples/websocket/package.json @@ -0,0 +1,22 @@ +{ + "name": "@cloudflare/sandbox-websocket-example", + "version": "1.0.0", + "type": "module", + "private": true, + "description": "WebSocket example for Cloudflare Sandbox SDK", + "scripts": { + "dev": "wrangler dev", + "deploy": "wrangler deploy", + "build": "tsc --noEmit" + }, + "author": "", + "license": "MIT", + "dependencies": { + "@cloudflare/sandbox": "*" + }, + "devDependencies": { + "@cloudflare/workers-types": "^4.20250111.0", + "typescript": "^5.3.3", + "wrangler": "^4.43.0" + } +} diff --git a/examples/websocket/src/index-with-helpers.ts b/examples/websocket/src/index-with-helpers.ts new file mode 100644 index 00000000..371085cc --- /dev/null +++ b/examples/websocket/src/index-with-helpers.ts @@ -0,0 +1,254 @@ +/** + * WebSocket Example Using SDK Helpers + * + * This demonstrates the simplified approach using the new WebSocket helpers + * from @cloudflare/sandbox. Compare with index.ts to see the difference! + */ + +import { createWebSocketHandler, Sandbox } from "@cloudflare/sandbox"; + +interface Env { + Sandbox: DurableObjectNamespace; +} + +export default { + async fetch(request: Request, env: Env): Promise { + const url = new URL(request.url); + const pathname = url.pathname; + + // Check for WebSocket upgrade + const upgradeHeader = request.headers.get("Upgrade"); + if (upgradeHeader !== "websocket") { + // Serve a simple HTML page for testing + if (pathname === "/") { + return new Response(getTestHTML(), { + headers: { "Content-Type": "text/html" }, + }); + } + return new Response("Expected WebSocket", { status: 426 }); + } + + // Route to different WebSocket handlers + switch (pathname) { + case "/ws/echo": + return handleEchoWebSocket(request, env); + case "/ws/code": + return handleCodeExecutionWebSocket(request, env); + case "/ws/process": + return handleProcessStreamWebSocket(request, env); + case "/ws/terminal": + return handleTerminalWebSocket(request, env); + default: + return new Response("Unknown WebSocket endpoint", { status: 404 }); + } + }, +}; + +/** + * Example 1: Echo Server (Simplified) + */ +async function handleEchoWebSocket( + request: Request, + env: Env +): Promise { + const { response, websocket } = await createWebSocketHandler(request, env.Sandbox, { + onReady: (ws, sandboxId) => { + ws.sendReady("Echo server connected", sandboxId); + }, + onMessage: async (ws, message) => { + switch (message.type) { + case "echo": + ws.send({ + type: "echo", + data: message.data, + timestamp: Date.now(), + }); + break; + + case "execute": + try { + const result = await ws.raw.sandbox.exec(message.command); + ws.sendResult({ + stdout: result.stdout, + stderr: result.stderr, + exitCode: result.exitCode, + }); + } catch (error) { + ws.sendError(error as Error); + } + break; + } + }, + }); + + return response; +} + +/** + * Example 2: Code Execution (Simplified) + */ +async function handleCodeExecutionWebSocket( + request: Request, + env: Env +): Promise { + let context: any = null; + + const { response, websocket, sandbox } = await createWebSocketHandler( + request, + env.Sandbox, + { + onReady: (ws) => { + ws.sendReady("Code interpreter ready"); + }, + onMessage: async (ws, message) => { + switch (message.type) { + case "execute": + try { + // Create context if needed + if (!context) { + context = await sandbox.createCodeContext({ + language: message.language || "python", + }); + } + + // Use the helper method for streaming execution! + await ws.runCodeWithStreaming(message.code, { + language: message.language || "python", + context, + }); + } catch (error) { + ws.sendError(error as Error); + } + break; + + case "reset": + if (context) { + await sandbox.deleteCodeContext(context.id); + context = null; + } + ws.sendStatus("reset", "Context cleared"); + break; + } + }, + } + ); + + return response; +} + +/** + * Example 3: Process Streaming (Simplified) + */ +async function handleProcessStreamWebSocket( + request: Request, + env: Env +): Promise { + const { response, websocket } = await createWebSocketHandler(request, env.Sandbox, { + onReady: (ws) => { + ws.sendReady("Process streaming ready"); + }, + onMessage: async (ws, message) => { + switch (message.type) { + case "start": + try { + // Use the helper method that auto-streams logs! + await ws.startProcessWithStreaming(message.command); + } catch (error) { + ws.sendError(error as Error); + } + break; + } + }, + }); + + return response; +} + +/** + * Example 4: Interactive Terminal (Simplified) + */ +async function handleTerminalWebSocket( + request: Request, + env: Env +): Promise { + let shellProcess: any = null; + + const { response, websocket, sandbox } = await createWebSocketHandler( + request, + env.Sandbox, + { + onReady: async (ws) => { + // Start shell process with streaming + shellProcess = await ws.startProcessWithStreaming("/bin/bash"); + ws.sendReady("Terminal ready"); + }, + onMessage: async (ws, message) => { + if (message.type === "input" && shellProcess) { + try { + // Write to stdin (this would need to be added to the SDK) + await sandbox.exec(`echo "${message.data}" | /proc/${shellProcess.pid}/fd/0`); + } catch (error) { + ws.sendError(error as Error); + } + } + }, + onClose: async (ws) => { + // Cleanup + if (shellProcess) { + await sandbox.killProcess(shellProcess.id); + } + }, + } + ); + + return response; +} + +// HTML test interface (same as before) +function getTestHTML(): string { + return ` + + + Sandbox WebSocket Examples (With Helpers) + + + +

Sandbox WebSocket Examples

+
+ Note: This version uses the new SDK WebSocket helpers! + Check index-with-helpers.ts vs index.ts to see the difference. +
+

Open index-with-helpers.ts to see how much simpler the code is!

+ +

Key Improvements

+
    +
  • createWebSocketHandler() - Handles all boilerplate setup
  • +
  • ws.sendReady(), ws.sendError(), etc - Type-safe message sending
  • +
  • ws.runCodeWithStreaming() - Auto-streams code execution output
  • +
  • ws.startProcessWithStreaming() - Auto-streams process logs
  • +
  • Lifecycle callbacks - onReady, onMessage, onClose, onError
  • +
+ +`; +} + +export { Sandbox }; diff --git a/examples/websocket/src/index.ts b/examples/websocket/src/index.ts new file mode 100644 index 00000000..3ad06caf --- /dev/null +++ b/examples/websocket/src/index.ts @@ -0,0 +1,767 @@ +/** + * WebSocket Example for Cloudflare Sandbox SDK + * + * This example demonstrates various WebSocket patterns: + * 1. Basic echo server + * 2. Real-time code execution + * 3. Process streaming + * 4. Interactive terminal + */ + +import { getSandbox, parseSSEStream, Sandbox, type LogEvent } from "@cloudflare/sandbox"; + +interface Env { + Sandbox: DurableObjectNamespace; +} + +export default { + async fetch(request: Request, env: Env): Promise { + const url = new URL(request.url); + const pathname = url.pathname; + + // Check for WebSocket upgrade + const upgradeHeader = request.headers.get("Upgrade"); + if (upgradeHeader !== "websocket") { + // Serve a simple HTML page for testing + if (pathname === "/") { + return new Response(getTestHTML(), { + headers: { "Content-Type": "text/html" }, + }); + } + return new Response("Expected WebSocket", { status: 426 }); + } + + // Route to different WebSocket handlers + switch (pathname) { + case "/ws/echo": + return handleEchoWebSocket(request, env); + case "/ws/code": + return handleCodeExecutionWebSocket(request, env); + case "/ws/process": + return handleProcessStreamWebSocket(request, env); + case "/ws/terminal": + return handleTerminalWebSocket(request, env); + default: + return new Response("Unknown WebSocket endpoint", { status: 404 }); + } + }, +}; + +/** + * Example 1: Basic Echo Server + * Demonstrates basic WebSocket handling with sandbox execution + */ +async function handleEchoWebSocket( + request: Request, + env: Env +): Promise { + const pair = new WebSocketPair(); + const [client, server] = Object.values(pair); + + // Get sandbox instance + const sandboxId = new URL(request.url).searchParams.get("id") || "echo-sandbox"; + const sandbox = getSandbox(env.Sandbox, sandboxId); + + // Accept the connection + server.accept(); + + // Send welcome message + server.send( + JSON.stringify({ + type: "connected", + message: "Echo server connected", + sandboxId, + }) + ); + + // Handle incoming messages + server.addEventListener("message", async (event) => { + try { + const message = JSON.parse(event.data as string); + + switch (message.type) { + case "echo": + // Simple echo back + server.send( + JSON.stringify({ + type: "echo", + data: message.data, + timestamp: Date.now(), + }) + ); + break; + + case "execute": + // Execute a command in the sandbox and echo the result + const result = await sandbox.exec(message.command); + server.send( + JSON.stringify({ + type: "result", + stdout: result.stdout, + stderr: result.stderr, + exitCode: result.exitCode, + }) + ); + break; + + case "ping": + server.send(JSON.stringify({ type: "pong" })); + break; + + default: + server.send( + JSON.stringify({ + type: "error", + message: "Unknown message type", + }) + ); + } + } catch (error: any) { + server.send( + JSON.stringify({ + type: "error", + message: error.message, + }) + ); + } + }); + + server.addEventListener("close", () => { + console.log("WebSocket closed"); + }); + + return new Response(null, { + status: 101, + webSocket: client, + }); +} + +/** + * Example 2: Real-Time Code Execution + * Executes Python/JavaScript code and streams output + */ +async function handleCodeExecutionWebSocket( + request: Request, + env: Env +): Promise { + const pair = new WebSocketPair(); + const [client, server] = Object.values(pair); + + const sandboxId = + new URL(request.url).searchParams.get("id") || "code-interpreter"; + const sandbox = getSandbox(env.Sandbox, sandboxId); + + server.accept(); + + // Create persistent code context + let context: any = null; + + server.send( + JSON.stringify({ + type: "ready", + message: "Code interpreter ready", + }) + ); + + server.addEventListener("message", async (event) => { + try { + const message = JSON.parse(event.data as string); + + if (message.type === "execute") { + const { code, language = "python", sessionId } = message; + + // Send acknowledgment + server.send( + JSON.stringify({ + type: "executing", + sessionId, + }) + ); + + // Create context if needed + if (!context) { + context = await sandbox.createCodeContext({ language }); + } + + // Execute with streaming callbacks + const execution = await sandbox.runCode(code, { + context, + onStdout: (output) => { + server.send( + JSON.stringify({ + type: "stdout", + data: output.text, + sessionId, + }) + ); + }, + onStderr: (output) => { + server.send( + JSON.stringify({ + type: "stderr", + data: output.text, + sessionId, + }) + ); + }, + }); + + // Send final results + server.send( + JSON.stringify({ + type: "result", + sessionId, + results: execution.results, + error: execution.error, + logs: execution.logs, + }) + ); + } else if (message.type === "reset") { + // Reset the code context + context = null; + server.send( + JSON.stringify({ + type: "reset", + message: "Context reset", + }) + ); + } + } catch (error: any) { + server.send( + JSON.stringify({ + type: "error", + message: error.message, + }) + ); + } + }); + + server.addEventListener("close", async () => { + // Clean up context + if (context && context.cleanup) { + await context.cleanup(); + } + }); + + return new Response(null, { + status: 101, + webSocket: client, + }); +} + +/** + * Example 3: Process Output Streaming + * Starts a long-running process and streams its output + */ +async function handleProcessStreamWebSocket( + request: Request, + env: Env +): Promise { + const pair = new WebSocketPair(); + const [client, server] = Object.values(pair); + + const sandboxId = + new URL(request.url).searchParams.get("id") || "process-stream"; + const sandbox = getSandbox(env.Sandbox, sandboxId); + + server.accept(); + + let currentProcess: any = null; + + server.send( + JSON.stringify({ + type: "ready", + message: "Process streamer ready", + }) + ); + + server.addEventListener("message", async (event) => { + try { + const message = JSON.parse(event.data as string); + + if (message.type === "start") { + const { command, args = [] } = message; + + // Build full command string + const fullCommand = args.length > 0 ? `${command} ${args.join(' ')}` : command; + + // Start the process + currentProcess = await sandbox.startProcess(fullCommand); + + server.send( + JSON.stringify({ + type: "started", + pid: currentProcess.pid, + }) + ); + + // Stream logs in the background + (async () => { + try { + const logStream = await sandbox.streamProcessLogs(currentProcess.id); + + for await (const event of parseSSEStream(logStream)) { + if (event.type === "stdout" || event.type === "stderr") { + server.send( + JSON.stringify({ + type: event.type, + data: event.data, + pid: currentProcess.pid, + }) + ); + } + } + + // Process completed + server.send( + JSON.stringify({ + type: "completed", + pid: currentProcess.pid, + }) + ); + } catch (error: any) { + server.send( + JSON.stringify({ + type: "error", + message: error.message, + }) + ); + } + })(); + } else if (message.type === "kill" && currentProcess) { + await sandbox.killProcess(currentProcess.id); + server.send( + JSON.stringify({ + type: "killed", + pid: currentProcess.pid, + }) + ); + currentProcess = null; + } + } catch (error: any) { + server.send( + JSON.stringify({ + type: "error", + message: error.message, + }) + ); + } + }); + + server.addEventListener("close", async () => { + if (currentProcess) { + try { + await sandbox.killProcess(currentProcess.id); + } catch { + // Process might already be done + } + } + }); + + return new Response(null, { + status: 101, + webSocket: client, + }); +} + +/** + * Example 4: Interactive Terminal + * Provides a full interactive shell session + */ +async function handleTerminalWebSocket( + request: Request, + env: Env +): Promise { + const pair = new WebSocketPair(); + const [client, server] = Object.values(pair); + + const sandboxId = + new URL(request.url).searchParams.get("id") || "terminal-session"; + const sandbox = getSandbox(env.Sandbox, sandboxId); + + server.accept(); + + // Start an interactive bash shell + const shell = await sandbox.startProcess("/bin/bash -i", { + env: { + TERM: "xterm-256color", + PS1: "\\[\\033[01;32m\\]sandbox\\[\\033[00m\\]:\\[\\033[01;34m\\]\\w\\[\\033[00m\\]$ ", + }, + }); + + server.send( + JSON.stringify({ + type: "ready", + pid: shell.pid, + message: "Terminal connected", + }) + ); + + // Stream shell output to client + (async () => { + try { + const logStream = await sandbox.streamProcessLogs(shell.id); + + for await (const event of parseSSEStream(logStream)) { + if (event.type === "stdout") { + // Send raw output for terminal rendering + server.send(event.data); + } + } + + // Shell exited + server.send( + JSON.stringify({ + type: "exit", + message: "Shell process exited", + }) + ); + server.close(1000, "Shell exited"); + } catch (error: any) { + server.send( + JSON.stringify({ + type: "error", + message: error.message, + }) + ); + server.close(1011, "Error"); + } + })(); + + // Send client input to shell + server.addEventListener("message", async (event) => { + try { + const input = event.data as string; + + // Handle special commands + if (input.startsWith("{")) { + const command = JSON.parse(input); + + if (command.type === "resize") { + // Handle terminal resize (would need TTY support) + // For now, just acknowledge + server.send( + JSON.stringify({ + type: "resized", + rows: command.rows, + cols: command.cols, + }) + ); + } + } else { + // Regular input - send to shell stdin + // Note: This requires implementing sendToProcess in the sandbox + // await sandbox.sendToProcess(shell.pid, input); + + // For now, we'll use a workaround by executing each line + if (input.includes('\n')) { + const result = await sandbox.exec(input.trim()); + server.send(result.stdout + result.stderr); + } + } + } catch (error: any) { + server.send( + JSON.stringify({ + type: "error", + message: error.message, + }) + ); + } + }); + + server.addEventListener("close", async () => { + try { + await sandbox.killProcess(shell.id); + } catch { + // Process might already be done + } + }); + + return new Response(null, { + status: 101, + webSocket: client, + }); +} + +/** + * Simple HTML test page for WebSocket examples + */ +function getTestHTML(): string { + return ` + + + Sandbox WebSocket Examples + + + +

Sandbox SDK WebSocket Examples

+ +
+

1. Echo Server

+
Disconnected
+ + + + + +
+
+ +
+

2. Code Execution

+
Disconnected
+ + + + + +
+
+ +
+

3. Process Streaming

+
Disconnected
+ + + + + +
+
+ + + +`; +} + +export { Sandbox }; diff --git a/examples/websocket/tsconfig.json b/examples/websocket/tsconfig.json new file mode 100644 index 00000000..1747331b --- /dev/null +++ b/examples/websocket/tsconfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "target": "esnext", + "lib": ["esnext"], + "module": "esnext", + "moduleResolution": "bundler", + "types": ["@cloudflare/workers-types"], + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "skipLibCheck": true, + "noEmit": true, + "resolveJsonModule": true, + "isolatedModules": true + }, + "include": ["src/**/*.ts"], + "exclude": ["node_modules"] +} diff --git a/examples/websocket/wrangler.jsonc b/examples/websocket/wrangler.jsonc new file mode 100644 index 00000000..a1a1f126 --- /dev/null +++ b/examples/websocket/wrangler.jsonc @@ -0,0 +1,36 @@ +{ + "$schema": "../../node_modules/wrangler/config-schema.json", + "name": "sandbox-websocket-example", + "main": "src/index.ts", + "compatibility_date": "2025-05-06", + "compatibility_flags": ["nodejs_compat"], + "observability": { + "enabled": true + }, + + "containers": [ + { + "class_name": "Sandbox", + "image": "../basic/Dockerfile", + "name": "sandbox", + "max_instances": 10, + "instance_type": "standard-2" + } + ], + + "durable_objects": { + "bindings": [ + { + "class_name": "Sandbox", + "name": "Sandbox" + } + ] + }, + + "migrations": [ + { + "new_sqlite_classes": ["Sandbox"], + "tag": "v1" + } + ] +} diff --git a/packages/sandbox/src/index.ts b/packages/sandbox/src/index.ts index 0db9a17d..a3a313d3 100644 --- a/packages/sandbox/src/index.ts +++ b/packages/sandbox/src/index.ts @@ -91,3 +91,16 @@ export { } from './request-handler'; // Export SSE parser for converting ReadableStream to AsyncIterable export { asyncIterableToSSEStream, parseSSEStream, responseToAsyncIterable } from "./sse-parser"; + +export { + createWebSocketHandler, + SandboxWebSocket, + type ErrorMessage, + type OutputMessage, + type ReadyMessage, + type ResultMessage, + type StatusMessage, + type WebSocketHandlerOptions, + type WebSocketHandlerResult, + type WebSocketMessage +} from './websocket'; diff --git a/packages/sandbox/src/websocket.ts b/packages/sandbox/src/websocket.ts new file mode 100644 index 00000000..b8d32ae5 --- /dev/null +++ b/packages/sandbox/src/websocket.ts @@ -0,0 +1,417 @@ +/** + * WebSocket helpers for Cloudflare Sandbox SDK + */ + +import type { ISandbox, LogEvent, Process } from '@repo/shared'; +import { parseSSEStream } from './sse-parser'; + +/** + * Standard message types for sandbox WebSocket communication + */ +export interface WebSocketMessage { + type: string; + [key: string]: any; +} + +export interface ReadyMessage extends WebSocketMessage { + type: 'ready'; + message: string; + sandboxId?: string; +} + +export interface OutputMessage extends WebSocketMessage { + type: 'stdout' | 'stderr'; + data: string; + pid?: number; +} + +export interface ErrorMessage extends WebSocketMessage { + type: 'error'; + message: string; + code?: string; + stack?: string; +} + +export interface StatusMessage extends WebSocketMessage { + type: 'status'; + status: string; + message?: string; +} + +export interface ResultMessage extends WebSocketMessage { + type: 'result'; + data: any; + executionTime?: number; +} + +/** + * Type-safe wrapper around WebSocket for sandbox communication + * + * Provides helpers for: + * - Sending structured messages with automatic JSON serialization + * - Streaming process logs to the client + * - Running code with real-time output streaming + * - Error handling and connection management + */ +export class SandboxWebSocket { + constructor( + private readonly server: WebSocket, + private readonly sandbox: ISandbox + ) {} + + /** + * Send a type-safe message to the client + */ + send(message: WebSocketMessage): void { + try { + this.server.send(JSON.stringify(message)); + } catch (error) { + console.error('Failed to send WebSocket message:', error); + } + } + + /** + * Send a ready notification + */ + sendReady(message: string, sandboxId?: string): void { + this.send({ + type: 'ready', + message, + sandboxId, + } as ReadyMessage); + } + + /** + * Send output (stdout or stderr) + */ + sendOutput(type: 'stdout' | 'stderr', data: string, pid?: number): void { + this.send({ + type, + data, + pid, + } as OutputMessage); + } + + /** + * Send an error message + */ + sendError(error: Error | string, code?: string): void { + const message = typeof error === 'string' ? error : error.message; + const stack = typeof error === 'string' ? undefined : error.stack; + + this.send({ + type: 'error', + message, + code, + stack, + } as ErrorMessage); + } + + /** + * Send a status update + */ + sendStatus(status: string, message?: string): void { + this.send({ + type: 'status', + status, + message, + } as StatusMessage); + } + + /** + * Send a result + */ + sendResult(data: any, executionTime?: number): void { + this.send({ + type: 'result', + data, + executionTime, + } as ResultMessage); + } + + /** + * Stream process logs to the WebSocket client + * + * This bridges the sandbox's SSE log stream to WebSocket, + * automatically parsing and forwarding log events. + * + * @param process - The process to stream logs from + * @returns Promise that resolves when streaming completes + */ + async streamProcessLogs(process: Process): Promise { + try { + const logStream = await this.sandbox.streamProcessLogs(process.id); + + for await (const event of parseSSEStream(logStream)) { + if (event.type === 'stdout' || event.type === 'stderr') { + this.sendOutput(event.type, event.data, process.pid); + } else if (event.type === 'exit') { + this.send({ + type: 'exit', + pid: process.pid, + exitCode: event.exitCode, + }); + } + } + } catch (error) { + this.sendError(error as Error); + } + } + + /** + * Execute code with real-time output streaming + * + * @param code - Code to execute + * @param options - Execution options including language and context + * @returns Promise that resolves with the execution result + */ + async runCodeWithStreaming( + code: string, + options?: { language?: 'python' | 'javascript'; context?: any; } + ): Promise { + const startTime = Date.now(); + + try { + this.sendStatus('executing'); + + // Use runCodeStream for streaming support + const stream = await this.sandbox.runCodeStream(code, { + language: options?.language || 'python', + context: options?.context, + }); + + // Stream results back to client + for await (const chunk of parseSSEStream(stream)) { + if (chunk.type === 'stdout' || chunk.type === 'stderr') { + this.sendOutput(chunk.type, chunk.data); + } else if (chunk.type === 'result') { + const executionTime = Date.now() - startTime; + this.sendResult(chunk.data, executionTime); + return chunk.data; + } else if (chunk.type === 'error') { + this.sendError(chunk.data); + throw new Error(chunk.data); + } + } + } catch (error) { + this.sendError(error as Error); + throw error; + } + } + + /** + * Start a process and stream its output + * + * @param command - Command to execute (including arguments) + * @returns Promise that resolves with the process + */ + async startProcessWithStreaming(command: string): Promise { + try { + const process = await this.sandbox.startProcess(command); + + this.send({ + type: 'process_started', + pid: process.pid, + id: process.id, + command, + }); + + // Stream logs in the background + this.streamProcessLogs(process).catch(error => { + console.error('Error streaming process logs:', error); + }); + + return process; + } catch (error) { + this.sendError(error as Error); + throw error; + } + } + + /** + * Close the WebSocket connection + */ + close(code?: number, reason?: string): void { + try { + this.server.close(code, reason); + } catch (error) { + console.error('Failed to close WebSocket:', error); + } + } + + /** + * Get the underlying WebSocket server instance + */ + get raw(): WebSocket { + return this.server; + } +} + +/** + * Options for creating a WebSocket handler + */ +export interface WebSocketHandlerOptions { + /** + * Custom sandbox ID (defaults to URL param or random UUID) + */ + sandboxId?: string; + + /** + * Callback when WebSocket is ready + */ + onReady?: (ws: SandboxWebSocket, sandboxId: string) => void | Promise; + + /** + * Callback for incoming messages + */ + onMessage?: (ws: SandboxWebSocket, message: any, event: MessageEvent) => void | Promise; + + /** + * Callback when WebSocket closes + */ + onClose?: (ws: SandboxWebSocket, event: CloseEvent) => void | Promise; + + /** + * Callback for WebSocket errors + */ + onError?: (ws: SandboxWebSocket, event: Event | ErrorEvent) => void | Promise; +} + +/** + * Result of creating a WebSocket handler + */ +export interface WebSocketHandlerResult { + /** + * The Response object to return from fetch() + */ + response: Response; + + /** + * The SandboxWebSocket wrapper + */ + websocket: SandboxWebSocket; + + /** + * The sandbox instance + */ + sandbox: ISandbox; + + /** + * The sandbox ID used + */ + sandboxId: string; +} + +/** + * Create a WebSocket handler with automatic setup and lifecycle management + * + * This is the main entry point for using WebSocket helpers. It: + * - Creates a WebSocket pair + * - Gets or creates a sandbox instance + * - Wraps everything in a SandboxWebSocket + * - Sets up event handlers + * - Returns both the Response and the wrapper for further customization + * + * @example + * ```typescript + * async function handleWebSocket(request: Request, env: Env) { + * const { response, websocket, sandbox } = await createWebSocketHandler( + * request, + * env.Sandbox, + * { + * onReady: (ws, sandboxId) => { + * ws.sendReady('Connected to sandbox', sandboxId); + * }, + * onMessage: async (ws, message) => { + * if (message.type === 'execute') { + * await ws.runPythonWithStreaming(message.code); + * } + * } + * } + * ); + * + * return response; + * } + * ``` + */ +export async function createWebSocketHandler( + request: Request, + sandboxNamespace: DurableObjectNamespace, + options: WebSocketHandlerOptions = {} +): Promise { + // Create WebSocket pair + const pair = new WebSocketPair(); + const [client, server] = Object.values(pair); + + // Get sandbox ID + const url = new URL(request.url); + const sandboxId = + options.sandboxId || + url.searchParams.get('id') || + crypto.randomUUID(); + + // Get sandbox instance + const id = sandboxNamespace.idFromName(sandboxId); + const stub = sandboxNamespace.get(id); + const sandbox = stub as unknown as ISandbox; + + // Accept connection + server.accept(); + + // Create wrapper + const ws = new SandboxWebSocket(server, sandbox); + + // Set up event handlers + if (options.onMessage) { + server.addEventListener('message', async (event) => { + try { + const message = JSON.parse(event.data as string); + await options.onMessage!(ws, message, event); + } catch (error) { + console.error('Error handling message:', error); + ws.sendError(error as Error); + } + }); + } + + if (options.onClose) { + server.addEventListener('close', async (event) => { + try { + await options.onClose!(ws, event); + } catch (error) { + console.error('Error handling close:', error); + } + }); + } + + if (options.onError) { + server.addEventListener('error', async (event) => { + try { + await options.onError!(ws, event); + } catch (error) { + console.error('Error handling error:', error); + } + }); + } + + // Call onReady callback + if (options.onReady) { + try { + await options.onReady(ws, sandboxId); + } catch (error) { + console.error('Error in onReady callback:', error); + ws.sendError(error as Error); + } + } + + // Return response and wrapper + return { + response: new Response(null, { + status: 101, + webSocket: client, + }), + websocket: ws, + sandbox, + sandboxId, + }; +} From 7e09ebe7c99accdf3f321a1ce17862332b7379a0 Mon Sep 17 00:00:00 2001 From: katereznykova Date: Sun, 19 Oct 2025 19:02:44 +0100 Subject: [PATCH 02/16] fix formatting --- packages/sandbox/src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/sandbox/src/index.ts b/packages/sandbox/src/index.ts index a3a313d3..6bd83040 100644 --- a/packages/sandbox/src/index.ts +++ b/packages/sandbox/src/index.ts @@ -94,11 +94,11 @@ export { asyncIterableToSSEStream, parseSSEStream, responseToAsyncIterable } fro export { createWebSocketHandler, - SandboxWebSocket, type ErrorMessage, type OutputMessage, type ReadyMessage, type ResultMessage, + SandboxWebSocket, type StatusMessage, type WebSocketHandlerOptions, type WebSocketHandlerResult, From 34b2e228ed503ffbfdd7aaf8d3221b9ac954b361 Mon Sep 17 00:00:00 2001 From: katereznykova Date: Thu, 23 Oct 2025 18:36:48 +0100 Subject: [PATCH 03/16] fix ws --- examples/basic/Dockerfile | 4 +- examples/websocket/src/index-with-helpers.ts | 254 ---------------- examples/websocket/src/index.ts | 226 ++++++++++++++ packages/sandbox/src/sandbox.ts | 37 +++ packages/sandbox/src/websocket.ts | 295 +++++++++++++++++++ packages/shared/src/types.ts | 1 + 6 files changed, 561 insertions(+), 256 deletions(-) delete mode 100644 examples/websocket/src/index-with-helpers.ts diff --git a/examples/basic/Dockerfile b/examples/basic/Dockerfile index adde8145..b2d843a8 100644 --- a/examples/basic/Dockerfile +++ b/examples/basic/Dockerfile @@ -1,8 +1,8 @@ # This image is unique to this repo, and you'll never need it. # Whenever you're integrating with sandbox SDK in your own project, # you should use the official image instead: -# FROM docker.io/cloudflare/sandbox:0.4.3 -FROM cloudflare/sandbox-test:0.4.3 + FROM docker.io/cloudflare/sandbox:0.4.3 +#FROM cloudflare/sandbox-test:0.4.3 # On a mac, you might need to actively pick up the # arm64 build of the image. diff --git a/examples/websocket/src/index-with-helpers.ts b/examples/websocket/src/index-with-helpers.ts deleted file mode 100644 index 371085cc..00000000 --- a/examples/websocket/src/index-with-helpers.ts +++ /dev/null @@ -1,254 +0,0 @@ -/** - * WebSocket Example Using SDK Helpers - * - * This demonstrates the simplified approach using the new WebSocket helpers - * from @cloudflare/sandbox. Compare with index.ts to see the difference! - */ - -import { createWebSocketHandler, Sandbox } from "@cloudflare/sandbox"; - -interface Env { - Sandbox: DurableObjectNamespace; -} - -export default { - async fetch(request: Request, env: Env): Promise { - const url = new URL(request.url); - const pathname = url.pathname; - - // Check for WebSocket upgrade - const upgradeHeader = request.headers.get("Upgrade"); - if (upgradeHeader !== "websocket") { - // Serve a simple HTML page for testing - if (pathname === "/") { - return new Response(getTestHTML(), { - headers: { "Content-Type": "text/html" }, - }); - } - return new Response("Expected WebSocket", { status: 426 }); - } - - // Route to different WebSocket handlers - switch (pathname) { - case "/ws/echo": - return handleEchoWebSocket(request, env); - case "/ws/code": - return handleCodeExecutionWebSocket(request, env); - case "/ws/process": - return handleProcessStreamWebSocket(request, env); - case "/ws/terminal": - return handleTerminalWebSocket(request, env); - default: - return new Response("Unknown WebSocket endpoint", { status: 404 }); - } - }, -}; - -/** - * Example 1: Echo Server (Simplified) - */ -async function handleEchoWebSocket( - request: Request, - env: Env -): Promise { - const { response, websocket } = await createWebSocketHandler(request, env.Sandbox, { - onReady: (ws, sandboxId) => { - ws.sendReady("Echo server connected", sandboxId); - }, - onMessage: async (ws, message) => { - switch (message.type) { - case "echo": - ws.send({ - type: "echo", - data: message.data, - timestamp: Date.now(), - }); - break; - - case "execute": - try { - const result = await ws.raw.sandbox.exec(message.command); - ws.sendResult({ - stdout: result.stdout, - stderr: result.stderr, - exitCode: result.exitCode, - }); - } catch (error) { - ws.sendError(error as Error); - } - break; - } - }, - }); - - return response; -} - -/** - * Example 2: Code Execution (Simplified) - */ -async function handleCodeExecutionWebSocket( - request: Request, - env: Env -): Promise { - let context: any = null; - - const { response, websocket, sandbox } = await createWebSocketHandler( - request, - env.Sandbox, - { - onReady: (ws) => { - ws.sendReady("Code interpreter ready"); - }, - onMessage: async (ws, message) => { - switch (message.type) { - case "execute": - try { - // Create context if needed - if (!context) { - context = await sandbox.createCodeContext({ - language: message.language || "python", - }); - } - - // Use the helper method for streaming execution! - await ws.runCodeWithStreaming(message.code, { - language: message.language || "python", - context, - }); - } catch (error) { - ws.sendError(error as Error); - } - break; - - case "reset": - if (context) { - await sandbox.deleteCodeContext(context.id); - context = null; - } - ws.sendStatus("reset", "Context cleared"); - break; - } - }, - } - ); - - return response; -} - -/** - * Example 3: Process Streaming (Simplified) - */ -async function handleProcessStreamWebSocket( - request: Request, - env: Env -): Promise { - const { response, websocket } = await createWebSocketHandler(request, env.Sandbox, { - onReady: (ws) => { - ws.sendReady("Process streaming ready"); - }, - onMessage: async (ws, message) => { - switch (message.type) { - case "start": - try { - // Use the helper method that auto-streams logs! - await ws.startProcessWithStreaming(message.command); - } catch (error) { - ws.sendError(error as Error); - } - break; - } - }, - }); - - return response; -} - -/** - * Example 4: Interactive Terminal (Simplified) - */ -async function handleTerminalWebSocket( - request: Request, - env: Env -): Promise { - let shellProcess: any = null; - - const { response, websocket, sandbox } = await createWebSocketHandler( - request, - env.Sandbox, - { - onReady: async (ws) => { - // Start shell process with streaming - shellProcess = await ws.startProcessWithStreaming("/bin/bash"); - ws.sendReady("Terminal ready"); - }, - onMessage: async (ws, message) => { - if (message.type === "input" && shellProcess) { - try { - // Write to stdin (this would need to be added to the SDK) - await sandbox.exec(`echo "${message.data}" | /proc/${shellProcess.pid}/fd/0`); - } catch (error) { - ws.sendError(error as Error); - } - } - }, - onClose: async (ws) => { - // Cleanup - if (shellProcess) { - await sandbox.killProcess(shellProcess.id); - } - }, - } - ); - - return response; -} - -// HTML test interface (same as before) -function getTestHTML(): string { - return ` - - - Sandbox WebSocket Examples (With Helpers) - - - -

Sandbox WebSocket Examples

-
- Note: This version uses the new SDK WebSocket helpers! - Check index-with-helpers.ts vs index.ts to see the difference. -
-

Open index-with-helpers.ts to see how much simpler the code is!

- -

Key Improvements

-
    -
  • createWebSocketHandler() - Handles all boilerplate setup
  • -
  • ws.sendReady(), ws.sendError(), etc - Type-safe message sending
  • -
  • ws.runCodeWithStreaming() - Auto-streams code execution output
  • -
  • ws.startProcessWithStreaming() - Auto-streams process logs
  • -
  • Lifecycle callbacks - onReady, onMessage, onClose, onError
  • -
- -`; -} - -export { Sandbox }; diff --git a/examples/websocket/src/index.ts b/examples/websocket/src/index.ts index 3ad06caf..5b38780a 100644 --- a/examples/websocket/src/index.ts +++ b/examples/websocket/src/index.ts @@ -6,6 +6,13 @@ * 2. Real-time code execution * 3. Process streaming * 4. Interactive terminal + * + * IMPORTANT: This example shows Worker → DO → Container WebSocket communication. + * For connecting to WebSocket servers INSIDE the container, use sandbox.connect() + * instead of containerFetch. See WEBSOCKET_FIX.md for details. + * + * These examples include optional rate limiting and timeout management. + * Uncomment the rate limiting sections to enable protection. */ import { getSandbox, parseSSEStream, Sandbox, type LogEvent } from "@cloudflare/sandbox"; @@ -41,6 +48,8 @@ export default { return handleProcessStreamWebSocket(request, env); case "/ws/terminal": return handleTerminalWebSocket(request, env); + case "/ws/protected": + return handleProtectedWebSocket(request, env); default: return new Response("Unknown WebSocket endpoint", { status: 404 }); } @@ -483,6 +492,223 @@ async function handleTerminalWebSocket( }); } +/** + * Example 5: Protected WebSocket with Rate Limiting & Timeouts + * Demonstrates production-ready WebSocket with security features + */ +async function handleProtectedWebSocket( + request: Request, + env: Env +): Promise { + const pair = new WebSocketPair(); + const [client, server] = Object.values(pair); + + const sandboxId = + new URL(request.url).searchParams.get("id") || "protected-session"; + const sandbox = getSandbox(env.Sandbox, sandboxId); + + server.accept(); + + // Rate limiting state (in production, store this in Durable Object storage) + const rateLimitState = { + messages: [] as number[], + maxMessages: 100, + windowMs: 60000, // 1 minute + maxMessageSize: 1024 * 1024, // 1MB + }; + + // Timeout state + let idleTimeout: number; + let maxConnectionTimeout: number; + let heartbeatInterval: number; + let lastActivity = Date.now(); + + // Heartbeat mechanism + heartbeatInterval = setInterval(() => { + const timeSinceActivity = Date.now() - lastActivity; + if (timeSinceActivity > 300000) { + // 5 minutes idle + server.close(1000, "Idle timeout"); + clearAllTimers(); + return; + } + try { + server.send(JSON.stringify({ type: "ping", timestamp: Date.now() })); + } catch (error) { + console.error("Failed to send heartbeat:", error); + } + }, 30000); // Ping every 30 seconds + + // Max connection time + maxConnectionTimeout = setTimeout(() => { + server.send( + JSON.stringify({ type: "info", message: "Maximum connection time reached" }) + ); + server.close(1000, "Maximum connection time reached"); + clearAllTimers(); + }, 1800000); // 30 minutes + + // Idle timeout reset function + const resetIdleTimeout = () => { + lastActivity = Date.now(); + if (idleTimeout) clearTimeout(idleTimeout); + idleTimeout = setTimeout(() => { + server.close(1000, "Idle timeout"); + clearAllTimers(); + }, 300000); // 5 minutes + }; + + // Initial idle timeout + resetIdleTimeout(); + + // Send welcome with limits info + server.send( + JSON.stringify({ + type: "connected", + message: "Protected WebSocket connected", + sandboxId, + limits: { + maxMessages: rateLimitState.maxMessages, + windowMs: rateLimitState.windowMs, + maxMessageSize: rateLimitState.maxMessageSize, + idleTimeout: 300000, + maxConnectionTime: 1800000, + }, + }) + ); + + // Handle incoming messages + server.addEventListener("message", async (event) => { + try { + // Reset idle timer on activity + resetIdleTimeout(); + + // Rate limiting check + const now = Date.now(); + const messageSize = new Blob([event.data as string]).size; + + // Check message size + if (messageSize > rateLimitState.maxMessageSize) { + server.send( + JSON.stringify({ + type: "error", + code: "RATE_LIMIT_EXCEEDED", + message: `Message size ${messageSize} exceeds limit of ${rateLimitState.maxMessageSize} bytes`, + }) + ); + return; + } + + // Clean old timestamps + rateLimitState.messages = rateLimitState.messages.filter( + (timestamp) => now - timestamp < rateLimitState.windowMs + ); + + // Check rate limit + if (rateLimitState.messages.length >= rateLimitState.maxMessages) { + server.send( + JSON.stringify({ + type: "error", + code: "RATE_LIMIT_EXCEEDED", + message: `Rate limit exceeded: ${rateLimitState.maxMessages} messages per ${rateLimitState.windowMs}ms`, + remaining: 0, + }) + ); + return; + } + + // Record this message + rateLimitState.messages.push(now); + + const message = JSON.parse(event.data as string); + + // Handle pong for heartbeat + if (message.type === "pong") { + return; // Just acknowledge, don't process + } + + // Send rate limit info with response + const remaining = rateLimitState.maxMessages - rateLimitState.messages.length; + + switch (message.type) { + case "echo": + server.send( + JSON.stringify({ + type: "echo", + data: message.data, + rateLimit: { remaining }, + timestamp: Date.now(), + }) + ); + break; + + case "execute": + const result = await sandbox.exec(message.command); + server.send( + JSON.stringify({ + type: "result", + stdout: result.stdout, + stderr: result.stderr, + exitCode: result.exitCode, + rateLimit: { remaining }, + }) + ); + break; + + case "status": + server.send( + JSON.stringify({ + type: "status", + connected: true, + sandboxId, + rateLimit: { + messagesInWindow: rateLimitState.messages.length, + maxMessages: rateLimitState.maxMessages, + remaining, + }, + timeout: { + timeSinceActivity: Date.now() - lastActivity, + idleTimeoutRemaining: Math.max(0, 300000 - (Date.now() - lastActivity)), + }, + }) + ); + break; + + default: + server.send( + JSON.stringify({ + type: "error", + message: "Unknown message type", + }) + ); + } + } catch (error: any) { + server.send( + JSON.stringify({ + type: "error", + message: error.message, + }) + ); + } + }); + + function clearAllTimers() { + if (idleTimeout) clearTimeout(idleTimeout); + if (maxConnectionTimeout) clearTimeout(maxConnectionTimeout); + if (heartbeatInterval) clearInterval(heartbeatInterval); + } + + server.addEventListener("close", () => { + console.log("Protected WebSocket closed"); + clearAllTimers(); + }); + + return new Response(null, { + status: 101, + webSocket: client, + }); +} + /** * Simple HTML test page for WebSocket examples */ diff --git a/packages/sandbox/src/sandbox.ts b/packages/sandbox/src/sandbox.ts index 8b2318bf..b8c2ea97 100644 --- a/packages/sandbox/src/sandbox.ts +++ b/packages/sandbox/src/sandbox.ts @@ -889,6 +889,43 @@ export class Sandbox extends Container implements ISandbox { }; } + /** + * Connect to a WebSocket endpoint running inside the container. + * + * This method bypasses containerFetch and uses the underlying container.fetch() + * directly + * + * @param portOrUrl - Port number (e.g., 3001) or full path (e.g., "/ws/endpoint") + * If a number, connects to `http://localhost:` + * If a string starting with "/", connects to `http://localhost:3000` + * @param options - Optional request init options (headers, etc.) + * @returns WebSocket upgrade response + */ + async connect(portOrUrl: number | string, options?: RequestInit): Promise { + let url: string; + + if (typeof portOrUrl === 'number') { + // Connect to specific port + url = `http://localhost:${portOrUrl}`; + } else if (portOrUrl.startsWith('/')) { + // Connect to path on default port (3000) + url = `http://localhost:${this.defaultPort}${portOrUrl}`; + } else { + throw new Error('Invalid portOrUrl: must be a port number or path starting with "/"'); + } + + // Create WebSocket upgrade request + const upgradeRequest = new Request(url, { + ...options, + headers: { + 'Upgrade': 'websocket', + 'Connection': 'Upgrade', + ...options?.headers, + }, + }); + return super.fetch(upgradeRequest); + } + // ============================================================================ // Code interpreter methods - delegate to CodeInterpreter wrapper // ============================================================================ diff --git a/packages/sandbox/src/websocket.ts b/packages/sandbox/src/websocket.ts index b8d32ae5..43cacc39 100644 --- a/packages/sandbox/src/websocket.ts +++ b/packages/sandbox/src/websocket.ts @@ -247,6 +247,46 @@ export class SandboxWebSocket { } } +/** + * Rate limiting configuration + */ +export interface RateLimitConfig { + /** + * Maximum messages per window (default: 100) + */ + maxMessages?: number; + + /** + * Time window in milliseconds (default: 60000 = 1 minute) + */ + windowMs?: number; + + /** + * Maximum message size in bytes (default: 1MB) + */ + maxMessageSize?: number; +} + +/** + * Connection timeout configuration + */ +export interface TimeoutConfig { + /** + * Idle timeout - close connection if no messages received (default: 5 minutes) + */ + idleTimeout?: number; + + /** + * Maximum connection duration (default: 30 minutes) + */ + maxConnectionTime?: number; + + /** + * Heartbeat interval - send ping to keep connection alive (default: 30 seconds) + */ + heartbeatInterval?: number; +} + /** * Options for creating a WebSocket handler */ @@ -256,6 +296,16 @@ export interface WebSocketHandlerOptions { */ sandboxId?: string; + /** + * Rate limiting configuration + */ + rateLimit?: RateLimitConfig; + + /** + * Connection timeout configuration + */ + timeout?: TimeoutConfig; + /** * Callback when WebSocket is ready */ @@ -275,6 +325,11 @@ export interface WebSocketHandlerOptions { * Callback for WebSocket errors */ onError?: (ws: SandboxWebSocket, event: Event | ErrorEvent) => void | Promise; + + /** + * Callback when rate limit is exceeded + */ + onRateLimitExceeded?: (ws: SandboxWebSocket) => void | Promise; } /** @@ -302,6 +357,194 @@ export interface WebSocketHandlerResult { sandboxId: string; } +/** + * Rate limiter using sliding window algorithm + */ +class RateLimiter { + private timestamps: number[] = []; + private readonly maxMessages: number; + private readonly windowMs: number; + private readonly maxMessageSize: number; + + constructor(config: RateLimitConfig = {}) { + this.maxMessages = config.maxMessages ?? 100; + this.windowMs = config.windowMs ?? 60000; // 1 minute + this.maxMessageSize = config.maxMessageSize ?? 1024 * 1024; // 1MB + } + + /** + * Check if a message is allowed under rate limits + */ + checkMessage(messageSize: number): { allowed: boolean; reason?: string } { + // Check message size + if (messageSize > this.maxMessageSize) { + return { + allowed: false, + reason: `Message size ${messageSize} exceeds limit of ${this.maxMessageSize} bytes`, + }; + } + + const now = Date.now(); + + // Remove timestamps outside the current window + this.timestamps = this.timestamps.filter( + (timestamp) => now - timestamp < this.windowMs + ); + + // Check if we're at the limit + if (this.timestamps.length >= this.maxMessages) { + return { + allowed: false, + reason: `Rate limit exceeded: ${this.maxMessages} messages per ${this.windowMs}ms`, + }; + } + + // Record this message + this.timestamps.push(now); + return { allowed: true }; + } + + /** + * Get current usage statistics + */ + getStats() { + const now = Date.now(); + this.timestamps = this.timestamps.filter( + (timestamp) => now - timestamp < this.windowMs + ); + + return { + messagesInWindow: this.timestamps.length, + maxMessages: this.maxMessages, + windowMs: this.windowMs, + remaining: Math.max(0, this.maxMessages - this.timestamps.length), + }; + } + + /** + * Reset the rate limiter + */ + reset(): void { + this.timestamps = []; + } +} + +/** + * Connection timeout manager + */ +class TimeoutManager { + private idleTimer?: number; + private maxConnectionTimer?: number; + private heartbeatTimer?: number; + private lastActivity: number; + private readonly config: Required; + + constructor( + private readonly ws: SandboxWebSocket, + config: TimeoutConfig = {} + ) { + this.config = { + idleTimeout: config.idleTimeout ?? 300000, // 5 minutes + maxConnectionTime: config.maxConnectionTime ?? 1800000, // 30 minutes + heartbeatInterval: config.heartbeatInterval ?? 30000, // 30 seconds + }; + this.lastActivity = Date.now(); + } + + /** + * Start all timeout timers + */ + start(): void { + // Start idle timeout + this.resetIdleTimer(); + + // Start max connection timer + this.maxConnectionTimer = setTimeout(() => { + this.ws.close(1000, 'Maximum connection time reached'); + }, this.config.maxConnectionTime) as unknown as number; + + // Start heartbeat + if (this.config.heartbeatInterval > 0) { + this.startHeartbeat(); + } + } + + /** + * Reset idle timer (call this on activity) + */ + resetIdleTimer(): void { + this.lastActivity = Date.now(); + + if (this.idleTimer) { + clearTimeout(this.idleTimer); + } + + this.idleTimer = setTimeout(() => { + this.ws.close(1000, 'Idle timeout'); + }, this.config.idleTimeout) as unknown as number; + } + + /** + * Start heartbeat ping/pong mechanism + */ + private startHeartbeat(): void { + this.heartbeatTimer = setInterval(() => { + // Check if we're past idle timeout + const timeSinceActivity = Date.now() - this.lastActivity; + if (timeSinceActivity > this.config.idleTimeout) { + this.ws.close(1000, 'Heartbeat timeout'); + this.stop(); + return; + } + + // Send heartbeat + try { + this.ws.send({ type: 'ping', timestamp: Date.now() }); + } catch (error) { + console.error('Failed to send heartbeat:', error); + } + }, this.config.heartbeatInterval) as unknown as number; + } + + /** + * Stop all timers + */ + stop(): void { + if (this.idleTimer) { + clearTimeout(this.idleTimer); + this.idleTimer = undefined; + } + + if (this.maxConnectionTimer) { + clearTimeout(this.maxConnectionTimer); + this.maxConnectionTimer = undefined; + } + + if (this.heartbeatTimer) { + clearInterval(this.heartbeatTimer); + this.heartbeatTimer = undefined; + } + } + + /** + * Get timeout statistics + */ + getStats() { + const now = Date.now(); + const timeSinceActivity = now - this.lastActivity; + + return { + lastActivity: this.lastActivity, + timeSinceActivity, + idleTimeoutRemaining: Math.max( + 0, + this.config.idleTimeout - timeSinceActivity + ), + config: this.config, + }; + } +} + /** * Create a WebSocket handler with automatic setup and lifecycle management * @@ -361,11 +604,58 @@ export async function createWebSocketHandler( // Create wrapper const ws = new SandboxWebSocket(server, sandbox); + // Initialize rate limiter if configured + const rateLimiter = options.rateLimit + ? new RateLimiter(options.rateLimit) + : null; + + // Initialize timeout manager if configured + const timeoutManager = options.timeout + ? new TimeoutManager(ws, options.timeout) + : null; + + // Start timeout tracking + if (timeoutManager) { + timeoutManager.start(); + } + // Set up event handlers if (options.onMessage) { server.addEventListener('message', async (event) => { try { + // Reset idle timer on activity + if (timeoutManager) { + timeoutManager.resetIdleTimer(); + } + + // Check rate limit + if (rateLimiter) { + const messageSize = new Blob([event.data as string]).size; + const rateLimitResult = rateLimiter.checkMessage(messageSize); + + if (!rateLimitResult.allowed) { + ws.sendError( + `Rate limit exceeded: ${rateLimitResult.reason}`, + 'RATE_LIMIT_EXCEEDED' + ); + + // Call rate limit callback if provided + if (options.onRateLimitExceeded) { + await options.onRateLimitExceeded(ws); + } + + // Don't process the message + return; + } + } + const message = JSON.parse(event.data as string); + + // Handle pong messages for heartbeat + if (message.type === 'pong') { + return; // Just acknowledge, don't process + } + await options.onMessage!(ws, message, event); } catch (error) { console.error('Error handling message:', error); @@ -377,6 +667,11 @@ export async function createWebSocketHandler( if (options.onClose) { server.addEventListener('close', async (event) => { try { + // Stop timeout manager + if (timeoutManager) { + timeoutManager.stop(); + } + await options.onClose!(ws, event); } catch (error) { console.error('Error handling close:', error); diff --git a/packages/shared/src/types.ts b/packages/shared/src/types.ts index 732fbb87..b3c8b3e6 100644 --- a/packages/shared/src/types.ts +++ b/packages/shared/src/types.ts @@ -643,6 +643,7 @@ export interface ISandbox { runCodeStream(code: string, options?: RunCodeOptions): Promise; listCodeContexts(): Promise; deleteCodeContext(contextId: string): Promise; + connect(portOrUrl: number | string, options?: RequestInit): Promise; } // Type guards for runtime validation From 7867acdf459113566a30a22b1a4b731b329b8cc8 Mon Sep 17 00:00:00 2001 From: katereznykova Date: Thu, 23 Oct 2025 18:37:51 +0100 Subject: [PATCH 04/16] minor fixes --- examples/websocket/src/index.ts | 13 ------------- packages/sandbox/src/websocket.ts | 29 ----------------------------- 2 files changed, 42 deletions(-) diff --git a/examples/websocket/src/index.ts b/examples/websocket/src/index.ts index 5b38780a..89699806 100644 --- a/examples/websocket/src/index.ts +++ b/examples/websocket/src/index.ts @@ -1,18 +1,5 @@ /** * WebSocket Example for Cloudflare Sandbox SDK - * - * This example demonstrates various WebSocket patterns: - * 1. Basic echo server - * 2. Real-time code execution - * 3. Process streaming - * 4. Interactive terminal - * - * IMPORTANT: This example shows Worker → DO → Container WebSocket communication. - * For connecting to WebSocket servers INSIDE the container, use sandbox.connect() - * instead of containerFetch. See WEBSOCKET_FIX.md for details. - * - * These examples include optional rate limiting and timeout management. - * Uncomment the rate limiting sections to enable protection. */ import { getSandbox, parseSSEStream, Sandbox, type LogEvent } from "@cloudflare/sandbox"; diff --git a/packages/sandbox/src/websocket.ts b/packages/sandbox/src/websocket.ts index 43cacc39..7bfb2090 100644 --- a/packages/sandbox/src/websocket.ts +++ b/packages/sandbox/src/websocket.ts @@ -547,35 +547,6 @@ class TimeoutManager { /** * Create a WebSocket handler with automatic setup and lifecycle management - * - * This is the main entry point for using WebSocket helpers. It: - * - Creates a WebSocket pair - * - Gets or creates a sandbox instance - * - Wraps everything in a SandboxWebSocket - * - Sets up event handlers - * - Returns both the Response and the wrapper for further customization - * - * @example - * ```typescript - * async function handleWebSocket(request: Request, env: Env) { - * const { response, websocket, sandbox } = await createWebSocketHandler( - * request, - * env.Sandbox, - * { - * onReady: (ws, sandboxId) => { - * ws.sendReady('Connected to sandbox', sandboxId); - * }, - * onMessage: async (ws, message) => { - * if (message.type === 'execute') { - * await ws.runPythonWithStreaming(message.code); - * } - * } - * } - * ); - * - * return response; - * } - * ``` */ export async function createWebSocketHandler( request: Request, From cfc2dd158f66da1eb97bb128552a572e5dfe3eeb Mon Sep 17 00:00:00 2001 From: katereznykova Date: Mon, 27 Oct 2025 12:38:56 +0000 Subject: [PATCH 05/16] WIP --- packages/sandbox/tests/connect.test.ts | 240 +++++++++++++++++++++++++ packages/sandbox/tests/sandbox.test.ts | 3 + 2 files changed, 243 insertions(+) create mode 100644 packages/sandbox/tests/connect.test.ts diff --git a/packages/sandbox/tests/connect.test.ts b/packages/sandbox/tests/connect.test.ts new file mode 100644 index 00000000..eeb2bd1c --- /dev/null +++ b/packages/sandbox/tests/connect.test.ts @@ -0,0 +1,240 @@ +import type { DurableObjectState } from '@cloudflare/workers-types'; +import { beforeEach, describe, expect, it, vi } from 'vitest'; +import { Sandbox } from '../src/sandbox'; + +// Mock Container before imports - same pattern as sandbox.test.ts +vi.mock('@cloudflare/containers', () => ({ + Container: class Container { + ctx: any; + env: any; + constructor(ctx: any, env: any) { + this.ctx = ctx; + this.env = env; + } + // Minimal fetch implementation that will be spied on + async fetch(_request: Request): Promise { + return new Response('Not implemented'); + } + }, + getContainer: vi.fn(), +})); + +/** + * Tests for Sandbox.connect() method + * + * This test suite validates that sandbox.connect() properly calls super.fetch() + * (Container.fetch) with the correct WebSocket upgrade request. + */ +describe('Sandbox.connect() - WebSocket connection method', () => { + let sandbox: Sandbox; + let capturedRequest: Request | null = null; + let fetchSpy: any; + + beforeEach(async () => { + // Create minimal mock DurableObjectState - same pattern as sandbox.test.ts + const mockCtx: Partial = { + storage: { + get: vi.fn().mockResolvedValue(null), + put: vi.fn().mockResolvedValue(undefined), + delete: vi.fn().mockResolvedValue(undefined), + list: vi.fn().mockResolvedValue(new Map()), + } as any, + blockConcurrencyWhile: vi.fn((fn: () => Promise) => fn()), + id: { + toString: () => 'test-connect-sandbox', + equals: vi.fn(), + name: 'test-connect', + } as any, + }; + + const mockEnv = {}; + + // Create real Sandbox instance + sandbox = new Sandbox(mockCtx as DurableObjectState, mockEnv); + + // Wait for initialization + await new Promise(resolve => setTimeout(resolve, 10)); + + // Spy on the sandbox's parent fetch to verify connect() calls super.fetch() + fetchSpy = vi.spyOn(Object.getPrototypeOf(Object.getPrototypeOf(sandbox)), 'fetch') + .mockImplementation(async function(request: RequestInfo | Request) { + if (request instanceof Request) { + capturedRequest = request; + } + // Return mock response + return new Response(null, { + status: 200, + headers: { + 'Upgrade': 'websocket', + 'Connection': 'Upgrade', + }, + }); + }); + }); + + afterEach(() => { + capturedRequest = null; + if (fetchSpy) { + fetchSpy.mockRestore(); + } + }); + + describe('URL construction', () => { + it('should construct correct URL for port number and call super.fetch()', async () => { + await sandbox.connect(3001); + + // Verify super.fetch() was called + expect(fetchSpy).toHaveBeenCalledTimes(1); + expect(capturedRequest).not.toBeNull(); + expect(capturedRequest!.url).toBe('http://localhost:3001/'); + expect(capturedRequest!.headers.get('Upgrade')).toBe('websocket'); + expect(capturedRequest!.headers.get('Connection')).toBe('Upgrade'); + }); + + it('should construct correct URL for path string and call super.fetch()', async () => { + await sandbox.connect('/ws/chat'); + + expect(fetchSpy).toHaveBeenCalledTimes(1); + expect(capturedRequest).not.toBeNull(); + expect(capturedRequest!.url).toBe('http://localhost:3000/ws/chat'); + expect(capturedRequest!.headers.get('Upgrade')).toBe('websocket'); + expect(capturedRequest!.headers.get('Connection')).toBe('Upgrade'); + }); + + it('should throw error for invalid portOrUrl (not a number or path)', async () => { + await expect(sandbox.connect('invalid-url' as any)).rejects.toThrow( + 'Invalid portOrUrl: must be a port number or path starting with "/"' + ); + + // Should not call super.fetch() if validation fails + expect(fetchSpy).not.toHaveBeenCalled(); + }); + + it('should throw error for empty string', async () => { + await expect(sandbox.connect('')).rejects.toThrow( + 'Invalid portOrUrl: must be a port number or path starting with "/"' + ); + + expect(fetchSpy).not.toHaveBeenCalled(); + }); + + it('should throw error for relative path without leading slash', async () => { + await expect(sandbox.connect('ws/chat')).rejects.toThrow( + 'Invalid portOrUrl: must be a port number or path starting with "/"' + ); + + expect(fetchSpy).not.toHaveBeenCalled(); + }); + }); + + describe('Request headers', () => { + it('should include WebSocket upgrade headers', async () => { + await sandbox.connect(3001); + + expect(capturedRequest).not.toBeNull(); + expect(capturedRequest!.headers.get('Upgrade')).toBe('websocket'); + expect(capturedRequest!.headers.get('Connection')).toBe('Upgrade'); + }); + + it('should include custom headers alongside WebSocket headers', async () => { + await sandbox.connect(3001, { + headers: { + 'Authorization': 'Bearer token123', + 'X-Custom-Header': 'value', + }, + }); + + expect(capturedRequest).not.toBeNull(); + expect(capturedRequest!.headers.get('Upgrade')).toBe('websocket'); + expect(capturedRequest!.headers.get('Connection')).toBe('Upgrade'); + expect(capturedRequest!.headers.get('Authorization')).toBe('Bearer token123'); + expect(capturedRequest!.headers.get('X-Custom-Header')).toBe('value'); + }); + + it('should allow custom headers to override defaults (spread operator behavior)', async () => { + await sandbox.connect(3001, { + headers: { + 'Upgrade': 'custom-protocol', + }, + }); + + expect(capturedRequest).not.toBeNull(); + // Since options?.headers comes after the defaults in spread, + // custom header overrides the default + expect(capturedRequest!.headers.get('Upgrade')).toBe('custom-protocol'); + }); + }); + + describe('RequestInit options', () => { + it('should pass through method option', async () => { + await sandbox.connect(3001, { + method: 'GET', + }); + + expect(capturedRequest).not.toBeNull(); + expect(capturedRequest!.method).toBe('GET'); + }); + + it('should pass through multiple options', async () => { + await sandbox.connect(3001, { + method: 'GET', + headers: { + 'User-Agent': 'test-client', + }, + }); + + expect(capturedRequest).not.toBeNull(); + expect(capturedRequest!.method).toBe('GET'); + expect(capturedRequest!.headers.get('User-Agent')).toBe('test-client'); + }); + + it('should work with no options provided', async () => { + await sandbox.connect(3001); + + expect(capturedRequest).not.toBeNull(); + expect(capturedRequest!.url).toBe('http://localhost:3001/'); + expect(capturedRequest!.headers.get('Upgrade')).toBe('websocket'); + }); + }); + + describe('Port and path variations', () => { + it('should handle different port numbers correctly', async () => { + const testCases = [ + { port: 3000, expected: 'http://localhost:3000/' }, + { port: 3001, expected: 'http://localhost:3001/' }, + { port: 8080, expected: 'http://localhost:8080/' }, + { port: 8888, expected: 'http://localhost:8888/' }, + ]; + + for (const { port, expected } of testCases) { + capturedRequest = null; + await sandbox.connect(port); + expect(capturedRequest).not.toBeNull(); + expect(capturedRequest!.url).toBe(expected); + } + }); + + it('should handle different path formats correctly', async () => { + const testCases = [ + { path: '/ws', expected: 'http://localhost:3000/ws' }, + { path: '/ws/chat', expected: 'http://localhost:3000/ws/chat' }, + { path: '/api/v1/websocket', expected: 'http://localhost:3000/api/v1/websocket' }, + { path: '/socket.io', expected: 'http://localhost:3000/socket.io' }, + ]; + + for (const { path, expected } of testCases) { + capturedRequest = null; + await sandbox.connect(path); + expect(capturedRequest).not.toBeNull(); + expect(capturedRequest!.url).toBe(expected); + } + }); + + it('should use defaultPort (3000) for path-based connections', async () => { + await sandbox.connect('/ws/test'); + + expect(capturedRequest).not.toBeNull(); + expect(capturedRequest!.url).toBe('http://localhost:3000/ws/test'); + }); + }); +}); diff --git a/packages/sandbox/tests/sandbox.test.ts b/packages/sandbox/tests/sandbox.test.ts index 479a40ec..325f2b2d 100644 --- a/packages/sandbox/tests/sandbox.test.ts +++ b/packages/sandbox/tests/sandbox.test.ts @@ -15,6 +15,9 @@ vi.mock('@cloudflare/containers', () => ({ this.ctx = ctx; this.env = env; } + async fetch(_request: Request): Promise { + return new Response('Not implemented'); + } }, getContainer: vi.fn(), })); From 448a2e441cad78ef715a111fedb2632911fb441d Mon Sep 17 00:00:00 2001 From: katereznykova Date: Tue, 28 Oct 2025 14:21:20 +0000 Subject: [PATCH 06/16] working draft --- examples/websocket/Dockerfile | 14 + examples/websocket/src/index.ts | 1083 ++++++++++++------------ examples/websocket/wrangler.jsonc | 2 +- packages/sandbox/src/index.ts | 2 +- packages/sandbox/src/sandbox.ts | 60 +- packages/sandbox/tests/connect.test.ts | 240 ------ packages/shared/src/types.ts | 1 - 7 files changed, 576 insertions(+), 826 deletions(-) create mode 100644 examples/websocket/Dockerfile delete mode 100644 packages/sandbox/tests/connect.test.ts diff --git a/examples/websocket/Dockerfile b/examples/websocket/Dockerfile new file mode 100644 index 00000000..ff21181a --- /dev/null +++ b/examples/websocket/Dockerfile @@ -0,0 +1,14 @@ +# This image is unique to this repo, and you'll never need it. +# Whenever you're integrating with sandbox SDK in your own project, +# you should use the official image instead: +FROM docker.io/cloudflare/sandbox:0.4.10 +# FROM cloudflare/sandbox-test:0.4.10 + +# On a mac, you might need to actively pick up the +# arm64 build of the image. +# FROM --platform=linux/arm64 cloudflare/sandbox-test:0.4.10 + +# Expose the ports you want to expose +EXPOSE 8080 +EXPOSE 3001 + diff --git a/examples/websocket/src/index.ts b/examples/websocket/src/index.ts index 89699806..5e064346 100644 --- a/examples/websocket/src/index.ts +++ b/examples/websocket/src/index.ts @@ -2,7 +2,15 @@ * WebSocket Example for Cloudflare Sandbox SDK */ -import { getSandbox, parseSSEStream, Sandbox, type LogEvent } from "@cloudflare/sandbox"; +import { + connect, + createWebSocketHandler, + getSandbox, + parseSSEStream, + Sandbox, + SandboxWebSocket, + type LogEvent +} from "@cloudflare/sandbox"; interface Env { Sandbox: DurableObjectNamespace; @@ -37,6 +45,8 @@ export default { return handleTerminalWebSocket(request, env); case "/ws/protected": return handleProtectedWebSocket(request, env); + case "/ws/container": + return handleContainerWebSocket(request, env); default: return new Response("Unknown WebSocket endpoint", { status: 404 }); } @@ -45,655 +55,529 @@ export default { /** * Example 1: Basic Echo Server - * Demonstrates basic WebSocket handling with sandbox execution + * Demonstrates basic WebSocket handling with sandbox execution using createWebSocketHandler */ async function handleEchoWebSocket( request: Request, env: Env ): Promise { - const pair = new WebSocketPair(); - const [client, server] = Object.values(pair); - - // Get sandbox instance - const sandboxId = new URL(request.url).searchParams.get("id") || "echo-sandbox"; - const sandbox = getSandbox(env.Sandbox, sandboxId); - - // Accept the connection - server.accept(); - - // Send welcome message - server.send( - JSON.stringify({ - type: "connected", - message: "Echo server connected", - sandboxId, - }) - ); - - // Handle incoming messages - server.addEventListener("message", async (event) => { - try { - const message = JSON.parse(event.data as string); - - switch (message.type) { - case "echo": - // Simple echo back - server.send( - JSON.stringify({ + // Use the createWebSocketHandler helper for automatic setup + const { response, websocket: ws, sandbox, sandboxId } = await createWebSocketHandler( + request, + env.Sandbox as any as DurableObjectNamespace, + { + sandboxId: new URL(request.url).searchParams.get("id") || "echo-sandbox", + onReady: (ws, sandboxId) => { + // Send welcome message when connection is ready + ws.send({ + type: "connected", + message: "Echo server connected", + sandboxId, + }); + }, + onMessage: async (ws, message) => { + switch (message.type) { + case "echo": + // Simple echo back + ws.send({ type: "echo", data: message.data, timestamp: Date.now(), - }) - ); - break; - - case "execute": - // Execute a command in the sandbox and echo the result - const result = await sandbox.exec(message.command); - server.send( - JSON.stringify({ + }); + break; + + case "execute": + // Execute a command in the sandbox and echo the result + const result = await sandbox.exec(message.command); + ws.send({ type: "result", stdout: result.stdout, stderr: result.stderr, exitCode: result.exitCode, - }) - ); - break; - - case "ping": - server.send(JSON.stringify({ type: "pong" })); - break; - - default: - server.send( - JSON.stringify({ - type: "error", - message: "Unknown message type", - }) - ); - } - } catch (error: any) { - server.send( - JSON.stringify({ - type: "error", - message: error.message, - }) - ); - } - }); + }); + break; - server.addEventListener("close", () => { - console.log("WebSocket closed"); - }); + case "ping": + ws.send({ type: "pong" }); + break; - return new Response(null, { - status: 101, - webSocket: client, - }); + default: + ws.sendError("Unknown message type"); + } + }, + onClose: () => { + console.log("WebSocket closed"); + }, + } + ); + + return response; } /** * Example 2: Real-Time Code Execution - * Executes Python/JavaScript code and streams output + * Executes Python/JavaScript code using basic shell execution */ async function handleCodeExecutionWebSocket( request: Request, env: Env ): Promise { - const pair = new WebSocketPair(); - const [client, server] = Object.values(pair); - - const sandboxId = - new URL(request.url).searchParams.get("id") || "code-interpreter"; - const sandbox = getSandbox(env.Sandbox, sandboxId); - - server.accept(); - - // Create persistent code context - let context: any = null; + const { response, websocket: ws, sandbox } = await createWebSocketHandler( + request, + env.Sandbox as any as DurableObjectNamespace, + { + sandboxId: new URL(request.url).searchParams.get("id") || "code-interpreter", + onReady: (ws) => { + ws.sendReady("Code interpreter ready"); + }, + onMessage: async (ws, message) => { + if (message.type === "execute") { + const { code, language = "python", sessionId } = message; - server.send( - JSON.stringify({ - type: "ready", - message: "Code interpreter ready", - }) - ); + // Send acknowledgment + ws.send({ + type: "executing", + sessionId, + }); - server.addEventListener("message", async (event) => { - try { - const message = JSON.parse(event.data as string); + try { + // Write code to a temporary file and execute it + const filename = `/tmp/code_${Date.now()}.${language === "javascript" ? "js" : "py"}`; + await sandbox.writeFile(filename, code); - if (message.type === "execute") { - const { code, language = "python", sessionId } = message; + // Execute the code + const command = language === "javascript" + ? `node ${filename}` + : `python3 ${filename}`; - // Send acknowledgment - server.send( - JSON.stringify({ - type: "executing", - sessionId, - }) - ); + const result = await sandbox.exec(command); - // Create context if needed - if (!context) { - context = await sandbox.createCodeContext({ language }); - } + // Send output + if (result.stdout) { + ws.sendOutput("stdout", result.stdout); + } + if (result.stderr) { + ws.sendOutput("stderr", result.stderr); + } - // Execute with streaming callbacks - const execution = await sandbox.runCode(code, { - context, - onStdout: (output) => { - server.send( - JSON.stringify({ - type: "stdout", - data: output.text, - sessionId, - }) - ); - }, - onStderr: (output) => { - server.send( - JSON.stringify({ - type: "stderr", - data: output.text, - sessionId, - }) - ); - }, - }); + // Send final result + ws.send({ + type: "result", + sessionId, + exitCode: result.exitCode, + success: result.exitCode === 0, + }); - // Send final results - server.send( - JSON.stringify({ - type: "result", - sessionId, - results: execution.results, - error: execution.error, - logs: execution.logs, - }) - ); - } else if (message.type === "reset") { - // Reset the code context - context = null; - server.send( - JSON.stringify({ + // Clean up + await sandbox.exec(`rm -f ${filename}`); + } catch (error: any) { + ws.sendError(error); + } + } else if (message.type === "reset") { + // Clean up any temporary files + await sandbox.exec("rm -f /tmp/code_*.py /tmp/code_*.js").catch(() => {}); + ws.send({ type: "reset", message: "Context reset", - }) - ); - } - } catch (error: any) { - server.send( - JSON.stringify({ - type: "error", - message: error.message, - }) - ); - } - }); - - server.addEventListener("close", async () => { - // Clean up context - if (context && context.cleanup) { - await context.cleanup(); + }); + } + }, } - }); + ); - return new Response(null, { - status: 101, - webSocket: client, - }); + return response; } /** * Example 3: Process Output Streaming - * Starts a long-running process and streams its output + * Starts a long-running process and streams its output using createWebSocketHandler */ async function handleProcessStreamWebSocket( request: Request, env: Env ): Promise { - const pair = new WebSocketPair(); - const [client, server] = Object.values(pair); - - const sandboxId = - new URL(request.url).searchParams.get("id") || "process-stream"; - const sandbox = getSandbox(env.Sandbox, sandboxId); - - server.accept(); - let currentProcess: any = null; - server.send( - JSON.stringify({ - type: "ready", - message: "Process streamer ready", - }) - ); - - server.addEventListener("message", async (event) => { - try { - const message = JSON.parse(event.data as string); - - if (message.type === "start") { - const { command, args = [] } = message; + const { response, websocket: ws, sandbox } = await createWebSocketHandler( + request, + env.Sandbox as any as DurableObjectNamespace, + { + sandboxId: new URL(request.url).searchParams.get("id") || "process-stream", + onReady: (ws) => { + ws.sendReady("Process streamer ready"); + }, + onMessage: async (ws, message) => { + if (message.type === "start") { + const { command, args = [] } = message; - // Build full command string - const fullCommand = args.length > 0 ? `${command} ${args.join(' ')}` : command; + // Build full command string + const fullCommand = args.length > 0 ? `${command} ${args.join(' ')}` : command; - // Start the process - currentProcess = await sandbox.startProcess(fullCommand); + // Start the process using the built-in helper + currentProcess = await ws.startProcessWithStreaming(fullCommand); - server.send( - JSON.stringify({ + ws.send({ type: "started", pid: currentProcess.pid, - }) - ); - - // Stream logs in the background - (async () => { - try { - const logStream = await sandbox.streamProcessLogs(currentProcess.id); - - for await (const event of parseSSEStream(logStream)) { - if (event.type === "stdout" || event.type === "stderr") { - server.send( - JSON.stringify({ - type: event.type, - data: event.data, - pid: currentProcess.pid, - }) - ); + }); + + // Stream logs in the background (handled by startProcessWithStreaming) + // But we need to listen for completion + (async () => { + try { + const logStream = await sandbox.streamProcessLogs(currentProcess.id); + + for await (const event of parseSSEStream(logStream)) { + if (event.type === "stdout" || event.type === "stderr") { + ws.sendOutput(event.type, event.data, currentProcess.pid); + } } - } - // Process completed - server.send( - JSON.stringify({ + // Process completed + ws.send({ type: "completed", pid: currentProcess.pid, - }) - ); - } catch (error: any) { - server.send( - JSON.stringify({ - type: "error", - message: error.message, - }) - ); - } - })(); - } else if (message.type === "kill" && currentProcess) { - await sandbox.killProcess(currentProcess.id); - server.send( - JSON.stringify({ + }); + } catch (error: any) { + ws.sendError(error); + } + })(); + } else if (message.type === "kill" && currentProcess) { + await sandbox.killProcess(currentProcess.id); + ws.send({ type: "killed", pid: currentProcess.pid, - }) - ); - currentProcess = null; - } - } catch (error: any) { - server.send( - JSON.stringify({ - type: "error", - message: error.message, - }) - ); - } - }); - - server.addEventListener("close", async () => { - if (currentProcess) { - try { - await sandbox.killProcess(currentProcess.id); - } catch { - // Process might already be done - } + }); + currentProcess = null; + } + }, + onClose: async () => { + if (currentProcess) { + try { + await sandbox.killProcess(currentProcess.id); + } catch { + // Process might already be done + } + } + }, } - }); + ); - return new Response(null, { - status: 101, - webSocket: client, - }); + return response; } /** * Example 4: Interactive Terminal - * Provides a full interactive shell session + * Provides a full interactive shell session using createWebSocketHandler */ async function handleTerminalWebSocket( request: Request, env: Env ): Promise { - const pair = new WebSocketPair(); - const [client, server] = Object.values(pair); - - const sandboxId = - new URL(request.url).searchParams.get("id") || "terminal-session"; - const sandbox = getSandbox(env.Sandbox, sandboxId); + let shell: any = null; + + const { response, websocket: ws, sandbox } = await createWebSocketHandler( + request, + env.Sandbox as any as DurableObjectNamespace, + { + sandboxId: new URL(request.url).searchParams.get("id") || "terminal-session", + onReady: async (ws) => { + // Start an interactive bash shell + shell = await sandbox.startProcess("/bin/bash -i", { + env: { + TERM: "xterm-256color", + PS1: "\\[\\033[01;32m\\]sandbox\\[\\033[00m\\]:\\[\\033[01;34m\\]\\w\\[\\033[00m\\]$ ", + }, + }); - server.accept(); + ws.send({ + type: "ready", + pid: shell.pid, + message: "Terminal connected", + }); - // Start an interactive bash shell - const shell = await sandbox.startProcess("/bin/bash -i", { - env: { - TERM: "xterm-256color", - PS1: "\\[\\033[01;32m\\]sandbox\\[\\033[00m\\]:\\[\\033[01;34m\\]\\w\\[\\033[00m\\]$ ", - }, - }); + // Stream shell output to client + (async () => { + try { + const logStream = await sandbox.streamProcessLogs(shell.id); - server.send( - JSON.stringify({ - type: "ready", - pid: shell.pid, - message: "Terminal connected", - }) - ); + for await (const event of parseSSEStream(logStream)) { + if (event.type === "stdout") { + // Send raw output for terminal rendering + ws.raw.send(event.data); + } + } - // Stream shell output to client - (async () => { - try { - const logStream = await sandbox.streamProcessLogs(shell.id); + // Shell exited + ws.send({ + type: "exit", + message: "Shell process exited", + }); + ws.close(1000, "Shell exited"); + } catch (error: any) { + ws.sendError(error); + ws.close(1011, "Error"); + } + })(); + }, + onMessage: async (ws, message, event) => { + const input = event.data as string; - for await (const event of parseSSEStream(logStream)) { - if (event.type === "stdout") { - // Send raw output for terminal rendering - server.send(event.data); - } - } + // Handle special commands + if (input.startsWith("{")) { + const command = JSON.parse(input); - // Shell exited - server.send( - JSON.stringify({ - type: "exit", - message: "Shell process exited", - }) - ); - server.close(1000, "Shell exited"); - } catch (error: any) { - server.send( - JSON.stringify({ - type: "error", - message: error.message, - }) - ); - server.close(1011, "Error"); - } - })(); - - // Send client input to shell - server.addEventListener("message", async (event) => { - try { - const input = event.data as string; - - // Handle special commands - if (input.startsWith("{")) { - const command = JSON.parse(input); - - if (command.type === "resize") { - // Handle terminal resize (would need TTY support) - // For now, just acknowledge - server.send( - JSON.stringify({ + if (command.type === "resize") { + // Handle terminal resize (would need TTY support) + // For now, just acknowledge + ws.send({ type: "resized", rows: command.rows, cols: command.cols, - }) - ); + }); + } + } else { + // Regular input - send to shell stdin + // Note: This requires implementing sendToProcess in the sandbox + // await sandbox.sendToProcess(shell.pid, input); + + // For now, we'll use a workaround by executing each line + if (input.includes('\n')) { + const result = await sandbox.exec(input.trim()); + ws.raw.send(result.stdout + result.stderr); + } } - } else { - // Regular input - send to shell stdin - // Note: This requires implementing sendToProcess in the sandbox - // await sandbox.sendToProcess(shell.pid, input); - - // For now, we'll use a workaround by executing each line - if (input.includes('\n')) { - const result = await sandbox.exec(input.trim()); - server.send(result.stdout + result.stderr); + }, + onClose: async () => { + if (shell) { + try { + await sandbox.killProcess(shell.id); + } catch { + // Process might already be done + } } - } - } catch (error: any) { - server.send( - JSON.stringify({ - type: "error", - message: error.message, - }) - ); - } - }); - - server.addEventListener("close", async () => { - try { - await sandbox.killProcess(shell.id); - } catch { - // Process might already be done + }, } - }); + ); - return new Response(null, { - status: 101, - webSocket: client, - }); + return response; } /** * Example 5: Protected WebSocket with Rate Limiting & Timeouts - * Demonstrates production-ready WebSocket with security features */ async function handleProtectedWebSocket( request: Request, env: Env ): Promise { - const pair = new WebSocketPair(); - const [client, server] = Object.values(pair); - - const sandboxId = - new URL(request.url).searchParams.get("id") || "protected-session"; - const sandbox = getSandbox(env.Sandbox, sandboxId); - - server.accept(); - - // Rate limiting state (in production, store this in Durable Object storage) - const rateLimitState = { - messages: [] as number[], - maxMessages: 100, - windowMs: 60000, // 1 minute - maxMessageSize: 1024 * 1024, // 1MB - }; - - // Timeout state - let idleTimeout: number; - let maxConnectionTimeout: number; - let heartbeatInterval: number; - let lastActivity = Date.now(); - - // Heartbeat mechanism - heartbeatInterval = setInterval(() => { - const timeSinceActivity = Date.now() - lastActivity; - if (timeSinceActivity > 300000) { - // 5 minutes idle - server.close(1000, "Idle timeout"); - clearAllTimers(); - return; - } - try { - server.send(JSON.stringify({ type: "ping", timestamp: Date.now() })); - } catch (error) { - console.error("Failed to send heartbeat:", error); - } - }, 30000); // Ping every 30 seconds - - // Max connection time - maxConnectionTimeout = setTimeout(() => { - server.send( - JSON.stringify({ type: "info", message: "Maximum connection time reached" }) - ); - server.close(1000, "Maximum connection time reached"); - clearAllTimers(); - }, 1800000); // 30 minutes - - // Idle timeout reset function - const resetIdleTimeout = () => { - lastActivity = Date.now(); - if (idleTimeout) clearTimeout(idleTimeout); - idleTimeout = setTimeout(() => { - server.close(1000, "Idle timeout"); - clearAllTimers(); - }, 300000); // 5 minutes - }; - - // Initial idle timeout - resetIdleTimeout(); - - // Send welcome with limits info - server.send( - JSON.stringify({ - type: "connected", - message: "Protected WebSocket connected", - sandboxId, - limits: { - maxMessages: rateLimitState.maxMessages, - windowMs: rateLimitState.windowMs, - maxMessageSize: rateLimitState.maxMessageSize, - idleTimeout: 300000, - maxConnectionTime: 1800000, + const { response, websocket: ws, sandbox, sandboxId } = await createWebSocketHandler( + request, + env.Sandbox as any as DurableObjectNamespace, + { + sandboxId: new URL(request.url).searchParams.get("id") || "protected-session", + // Configure rate limiting + rateLimit: { + maxMessages: 100, + windowMs: 60000, // 1 minute + maxMessageSize: 1024 * 1024, // 1MB }, - }) - ); - - // Handle incoming messages - server.addEventListener("message", async (event) => { - try { - // Reset idle timer on activity - resetIdleTimeout(); - - // Rate limiting check - const now = Date.now(); - const messageSize = new Blob([event.data as string]).size; - - // Check message size - if (messageSize > rateLimitState.maxMessageSize) { - server.send( - JSON.stringify({ - type: "error", - code: "RATE_LIMIT_EXCEEDED", - message: `Message size ${messageSize} exceeds limit of ${rateLimitState.maxMessageSize} bytes`, - }) - ); - return; - } - - // Clean old timestamps - rateLimitState.messages = rateLimitState.messages.filter( - (timestamp) => now - timestamp < rateLimitState.windowMs - ); - - // Check rate limit - if (rateLimitState.messages.length >= rateLimitState.maxMessages) { - server.send( - JSON.stringify({ - type: "error", - code: "RATE_LIMIT_EXCEEDED", - message: `Rate limit exceeded: ${rateLimitState.maxMessages} messages per ${rateLimitState.windowMs}ms`, - remaining: 0, - }) - ); - return; - } - - // Record this message - rateLimitState.messages.push(now); - - const message = JSON.parse(event.data as string); - - // Handle pong for heartbeat - if (message.type === "pong") { - return; // Just acknowledge, don't process - } - - // Send rate limit info with response - const remaining = rateLimitState.maxMessages - rateLimitState.messages.length; - - switch (message.type) { - case "echo": - server.send( - JSON.stringify({ + // Configure connection timeouts + timeout: { + idleTimeout: 300000, // 5 minutes + maxConnectionTime: 1800000, // 30 minutes + heartbeatInterval: 30000, // 30 seconds + }, + onReady: (ws, sandboxId) => { + // Send welcome with limits info + ws.send({ + type: "connected", + message: "Protected WebSocket connected", + sandboxId, + limits: { + maxMessages: 100, + windowMs: 60000, + maxMessageSize: 1024 * 1024, + idleTimeout: 300000, + maxConnectionTime: 1800000, + }, + }); + }, + onMessage: async (ws, message) => { + switch (message.type) { + case "echo": + ws.send({ type: "echo", data: message.data, - rateLimit: { remaining }, timestamp: Date.now(), - }) - ); - break; - - case "execute": - const result = await sandbox.exec(message.command); - server.send( - JSON.stringify({ + }); + break; + + case "execute": + const result = await sandbox.exec(message.command); + ws.send({ type: "result", stdout: result.stdout, stderr: result.stderr, exitCode: result.exitCode, - rateLimit: { remaining }, - }) - ); - break; - - case "status": - server.send( - JSON.stringify({ + }); + break; + + case "status": + ws.send({ type: "status", connected: true, sandboxId, - rateLimit: { - messagesInWindow: rateLimitState.messages.length, - maxMessages: rateLimitState.maxMessages, - remaining, - }, - timeout: { - timeSinceActivity: Date.now() - lastActivity, - idleTimeoutRemaining: Math.max(0, 300000 - (Date.now() - lastActivity)), - }, - }) - ); - break; - - default: - server.send( - JSON.stringify({ - type: "error", - message: "Unknown message type", - }) - ); + }); + break; + + default: + ws.sendError("Unknown message type"); + } + }, + onRateLimitExceeded: (ws) => { + console.log("Rate limit exceeded for protected WebSocket"); + }, + onClose: () => { + console.log("Protected WebSocket closed"); + }, + } + ); + + return response; +} + +/** + * Example 6: Connect to WebSocket Server Inside Container + * Demonstrates using connect() to proxy to a WebSocket server running in the container + * + * This example shows how to connect to a WebSocket server that's running inside + * the sandbox container. We use connect(sandbox, request, port) to route the incoming + * WebSocket request to port 8080 where our Node.js WebSocket server is listening. + */ +async function handleContainerWebSocket( + request: Request, + env: Env +): Promise { + const sandboxId = new URL(request.url).searchParams.get("id") || "container-ws"; + + // Get sandbox instance using getSandbox helper + const sandbox = getSandbox(env.Sandbox, sandboxId); + + // Create a simple Node.js WebSocket echo server + // Using Node.js because it should be available in the container + const serverScript = ` +const http = require('http'); +const crypto = require('crypto'); + +const server = http.createServer((req, res) => { + res.writeHead(200); + res.end('WebSocket server running'); +}); + +server.on('upgrade', (req, socket) => { + const key = req.headers['sec-websocket-key']; + const acceptKey = crypto + .createHash('sha1') + .update(key + '258EAFA5-E914-47DA-95CA-C5AB0DC85B11') + .digest('base64'); + + socket.write( + 'HTTP/1.1 101 Switching Protocols\\r\\n' + + 'Upgrade: websocket\\r\\n' + + 'Connection: Upgrade\\r\\n' + + 'Sec-WebSocket-Accept: ' + acceptKey + '\\r\\n\\r\\n' + ); + + socket.on('data', (data) => { + // Simple echo - parse WebSocket frame and echo back + if (data[0] === 0x81) { + const len = data[1] & 127; + const maskStart = 2; + const dataStart = maskStart + 4; + const mask = data.slice(maskStart, dataStart); + const payload = data.slice(dataStart, dataStart + len); + + // Unmask the payload + const decoded = Buffer.alloc(len); + for (let i = 0; i < len; i++) { + decoded[i] = payload[i] ^ mask[i % 4]; } - } catch (error: any) { - server.send( - JSON.stringify({ - type: "error", - message: error.message, - }) - ); + + // Echo back (server doesn't mask) + const response = Buffer.alloc(2 + len); + response[0] = 0x81; // Text frame + response[1] = len; + decoded.copy(response, 2); + socket.write(response); } }); - function clearAllTimers() { - if (idleTimeout) clearTimeout(idleTimeout); - if (maxConnectionTimeout) clearTimeout(maxConnectionTimeout); - if (heartbeatInterval) clearInterval(heartbeatInterval); + socket.on('close', () => { + console.log('WebSocket closed'); + }); +}); + +server.listen(8080, '0.0.0.0', () => { + console.log('WebSocket server listening on port 8080'); +}); +`; + + // Write the server script + await sandbox.writeFile('/tmp/ws_server.js', serverScript); + + // Start the server using startProcess (better for long-running processes) + try { + await sandbox.startProcess('node /tmp/ws_server.js', { + processId: 'ws-server-8080' + }); + console.log('WebSocket server process started'); + } catch (error: any) { + // Server might already be running, that's okay + if (!error.message?.includes('already exists')) { + console.error('Failed to start WebSocket server:', error); + throw error; + } + console.log('WebSocket server already running'); } - server.addEventListener("close", () => { - console.log("Protected WebSocket closed"); - clearAllTimers(); - }); + // Give the server time to start and begin listening + await new Promise(resolve => setTimeout(resolve, 2000)); - return new Response(null, { - status: 101, - webSocket: client, - }); + // Check if the process is still running + try { + const processes = await sandbox.listProcesses(); + const serverProcess = processes.find(p => p.id === 'ws-server-8080'); + + if (!serverProcess || serverProcess.status !== 'running') { + console.error('WebSocket server process not running:', serverProcess); + return new Response('WebSocket server failed to start', { status: 503 }); + } + + console.log('WebSocket server process is running:', serverProcess); + } catch (e) { + console.error('Failed to check process status:', e); + } + + // Use connect() to route the incoming WebSocket to port 8080 + // This is a convenient helper that uses switchPort internally + console.log('Using connect(sandbox, request, 8080) to route WebSocket...'); + + try { + const response = await connect(sandbox, request, 8080); + + console.log('connect() returned status:', response.status); + console.log('Response headers:', Object.fromEntries(response.headers)); + + return response; + } catch (error: any) { + console.error('connect() failed:', error); + console.error('Error type:', error.constructor.name); + console.error('Error message:', error.message); + console.error('Error stack:', error.stack); + return new Response(`Failed to connect to container WebSocket: ${error.message}`, { + status: 500 + }); + } } /** @@ -776,8 +660,43 @@ function getTestHTML(): string {

Sandbox SDK WebSocket Examples

+
+

Two WebSocket Communication Methods

+ +
+

+ createWebSocketHandler() - DO <--> Client with Sandbox Operations +

+

+ Use this when you want to communicate between the Durable Object and the client, + performing sandbox operations (run code, start processes, execute commands). + The DO handles messages and interacts with the sandbox. +

+

+ Examples: Echo Server, Code Execution, Process Streaming +

+
+ +
+

+ connect(sandbox, request, port) - Route Client -> Container Service +

+

+ Use this when you have a WebSocket server running inside the container + (e.g., a Node.js app on port 8080) and want to route incoming client + WebSocket connections directly to it. +

+

+ Example: Container WebSocket (routes to Node.js WebSocket server on port 8080) +

+
+
+

1. Echo Server

+

+ Method: createWebSocketHandler() - DO <--> Client with Sandbox Operations +

Disconnected
@@ -789,6 +708,9 @@ function getTestHTML(): string {

2. Code Execution

+

+ Method: createWebSocketHandler() - DO <--> Client with Sandbox Operations +

Disconnected

3. Process Streaming

+

+ Method: createWebSocketHandler() - DO <--> Client with Sandbox Operations +

Disconnected
@@ -813,11 +738,28 @@ print('Done!')
+
+

4. Container WebSocket

+

+ Method: connect(sandbox, request, port) - Route Client -> Container Service +

+

+ Routes WebSocket to a Node.js server running on port 8080 inside the container +

+
Disconnected
+ + + + +
+
+ `; diff --git a/examples/websocket/wrangler.jsonc b/examples/websocket/wrangler.jsonc index a1a1f126..ffa1a010 100644 --- a/examples/websocket/wrangler.jsonc +++ b/examples/websocket/wrangler.jsonc @@ -11,7 +11,7 @@ "containers": [ { "class_name": "Sandbox", - "image": "../basic/Dockerfile", + "image": "./Dockerfile", "name": "sandbox", "max_instances": 10, "instance_type": "standard-2" diff --git a/packages/sandbox/src/index.ts b/packages/sandbox/src/index.ts index 6bd83040..e5f54e0b 100644 --- a/packages/sandbox/src/index.ts +++ b/packages/sandbox/src/index.ts @@ -11,7 +11,7 @@ export { SandboxClient, UtilityClient } from "./clients"; -export { getSandbox, Sandbox } from "./sandbox"; +export { getSandbox, Sandbox, connect } from "./sandbox"; // Legacy types are now imported from the new client architecture diff --git a/packages/sandbox/src/sandbox.ts b/packages/sandbox/src/sandbox.ts index 782327a5..d9fe29da 100644 --- a/packages/sandbox/src/sandbox.ts +++ b/packages/sandbox/src/sandbox.ts @@ -1,5 +1,5 @@ import type { DurableObject } from 'cloudflare:workers'; -import { Container, getContainer } from "@cloudflare/containers"; +import { Container, getContainer, switchPort } from "@cloudflare/containers"; import type { CodeContext, CreateContextOptions, @@ -35,8 +35,8 @@ export function getSandbox( ns: DurableObjectNamespace, id: string, options?: SandboxOptions -) { - const stub = getContainer(ns, id); +): Sandbox { + const stub = getContainer(ns, id) as any as Sandbox; // Store the name on first access stub.setSandboxName?.(id); @@ -52,6 +52,23 @@ export function getSandbox( return stub; } +/** + * Connect an incoming WebSocket request to a specific port inside the container. + * + * @param sandbox - The sandbox instance (stub) to connect to + * @param request - The incoming WebSocket upgrade request from the client + * @param port - The port number to connect to inside the container + * @returns Promise - The WebSocket upgrade response + */ +export async function connect( + sandbox: Sandbox, + request: Request, + port: number +): Promise { + const portSwitchedRequest = switchPort(request, port); + return await sandbox.fetch(portSwitchedRequest); +} + export class Sandbox extends Container implements ISandbox { defaultPort = 3000; // Default port for the container's Bun server sleepAfter: string | number = "10m"; // Sleep the sandbox if no requests are made in this timeframe @@ -986,43 +1003,6 @@ export class Sandbox extends Container implements ISandbox { }; } - /** - * Connect to a WebSocket endpoint running inside the container. - * - * This method bypasses containerFetch and uses the underlying container.fetch() - * directly - * - * @param portOrUrl - Port number (e.g., 3001) or full path (e.g., "/ws/endpoint") - * If a number, connects to `http://localhost:` - * If a string starting with "/", connects to `http://localhost:3000` - * @param options - Optional request init options (headers, etc.) - * @returns WebSocket upgrade response - */ - async connect(portOrUrl: number | string, options?: RequestInit): Promise { - let url: string; - - if (typeof portOrUrl === 'number') { - // Connect to specific port - url = `http://localhost:${portOrUrl}`; - } else if (portOrUrl.startsWith('/')) { - // Connect to path on default port (3000) - url = `http://localhost:${this.defaultPort}${portOrUrl}`; - } else { - throw new Error('Invalid portOrUrl: must be a port number or path starting with "/"'); - } - - // Create WebSocket upgrade request - const upgradeRequest = new Request(url, { - ...options, - headers: { - 'Upgrade': 'websocket', - 'Connection': 'Upgrade', - ...options?.headers, - }, - }); - return super.fetch(upgradeRequest); - } - // ============================================================================ // Code interpreter methods - delegate to CodeInterpreter wrapper // ============================================================================ diff --git a/packages/sandbox/tests/connect.test.ts b/packages/sandbox/tests/connect.test.ts deleted file mode 100644 index eeb2bd1c..00000000 --- a/packages/sandbox/tests/connect.test.ts +++ /dev/null @@ -1,240 +0,0 @@ -import type { DurableObjectState } from '@cloudflare/workers-types'; -import { beforeEach, describe, expect, it, vi } from 'vitest'; -import { Sandbox } from '../src/sandbox'; - -// Mock Container before imports - same pattern as sandbox.test.ts -vi.mock('@cloudflare/containers', () => ({ - Container: class Container { - ctx: any; - env: any; - constructor(ctx: any, env: any) { - this.ctx = ctx; - this.env = env; - } - // Minimal fetch implementation that will be spied on - async fetch(_request: Request): Promise { - return new Response('Not implemented'); - } - }, - getContainer: vi.fn(), -})); - -/** - * Tests for Sandbox.connect() method - * - * This test suite validates that sandbox.connect() properly calls super.fetch() - * (Container.fetch) with the correct WebSocket upgrade request. - */ -describe('Sandbox.connect() - WebSocket connection method', () => { - let sandbox: Sandbox; - let capturedRequest: Request | null = null; - let fetchSpy: any; - - beforeEach(async () => { - // Create minimal mock DurableObjectState - same pattern as sandbox.test.ts - const mockCtx: Partial = { - storage: { - get: vi.fn().mockResolvedValue(null), - put: vi.fn().mockResolvedValue(undefined), - delete: vi.fn().mockResolvedValue(undefined), - list: vi.fn().mockResolvedValue(new Map()), - } as any, - blockConcurrencyWhile: vi.fn((fn: () => Promise) => fn()), - id: { - toString: () => 'test-connect-sandbox', - equals: vi.fn(), - name: 'test-connect', - } as any, - }; - - const mockEnv = {}; - - // Create real Sandbox instance - sandbox = new Sandbox(mockCtx as DurableObjectState, mockEnv); - - // Wait for initialization - await new Promise(resolve => setTimeout(resolve, 10)); - - // Spy on the sandbox's parent fetch to verify connect() calls super.fetch() - fetchSpy = vi.spyOn(Object.getPrototypeOf(Object.getPrototypeOf(sandbox)), 'fetch') - .mockImplementation(async function(request: RequestInfo | Request) { - if (request instanceof Request) { - capturedRequest = request; - } - // Return mock response - return new Response(null, { - status: 200, - headers: { - 'Upgrade': 'websocket', - 'Connection': 'Upgrade', - }, - }); - }); - }); - - afterEach(() => { - capturedRequest = null; - if (fetchSpy) { - fetchSpy.mockRestore(); - } - }); - - describe('URL construction', () => { - it('should construct correct URL for port number and call super.fetch()', async () => { - await sandbox.connect(3001); - - // Verify super.fetch() was called - expect(fetchSpy).toHaveBeenCalledTimes(1); - expect(capturedRequest).not.toBeNull(); - expect(capturedRequest!.url).toBe('http://localhost:3001/'); - expect(capturedRequest!.headers.get('Upgrade')).toBe('websocket'); - expect(capturedRequest!.headers.get('Connection')).toBe('Upgrade'); - }); - - it('should construct correct URL for path string and call super.fetch()', async () => { - await sandbox.connect('/ws/chat'); - - expect(fetchSpy).toHaveBeenCalledTimes(1); - expect(capturedRequest).not.toBeNull(); - expect(capturedRequest!.url).toBe('http://localhost:3000/ws/chat'); - expect(capturedRequest!.headers.get('Upgrade')).toBe('websocket'); - expect(capturedRequest!.headers.get('Connection')).toBe('Upgrade'); - }); - - it('should throw error for invalid portOrUrl (not a number or path)', async () => { - await expect(sandbox.connect('invalid-url' as any)).rejects.toThrow( - 'Invalid portOrUrl: must be a port number or path starting with "/"' - ); - - // Should not call super.fetch() if validation fails - expect(fetchSpy).not.toHaveBeenCalled(); - }); - - it('should throw error for empty string', async () => { - await expect(sandbox.connect('')).rejects.toThrow( - 'Invalid portOrUrl: must be a port number or path starting with "/"' - ); - - expect(fetchSpy).not.toHaveBeenCalled(); - }); - - it('should throw error for relative path without leading slash', async () => { - await expect(sandbox.connect('ws/chat')).rejects.toThrow( - 'Invalid portOrUrl: must be a port number or path starting with "/"' - ); - - expect(fetchSpy).not.toHaveBeenCalled(); - }); - }); - - describe('Request headers', () => { - it('should include WebSocket upgrade headers', async () => { - await sandbox.connect(3001); - - expect(capturedRequest).not.toBeNull(); - expect(capturedRequest!.headers.get('Upgrade')).toBe('websocket'); - expect(capturedRequest!.headers.get('Connection')).toBe('Upgrade'); - }); - - it('should include custom headers alongside WebSocket headers', async () => { - await sandbox.connect(3001, { - headers: { - 'Authorization': 'Bearer token123', - 'X-Custom-Header': 'value', - }, - }); - - expect(capturedRequest).not.toBeNull(); - expect(capturedRequest!.headers.get('Upgrade')).toBe('websocket'); - expect(capturedRequest!.headers.get('Connection')).toBe('Upgrade'); - expect(capturedRequest!.headers.get('Authorization')).toBe('Bearer token123'); - expect(capturedRequest!.headers.get('X-Custom-Header')).toBe('value'); - }); - - it('should allow custom headers to override defaults (spread operator behavior)', async () => { - await sandbox.connect(3001, { - headers: { - 'Upgrade': 'custom-protocol', - }, - }); - - expect(capturedRequest).not.toBeNull(); - // Since options?.headers comes after the defaults in spread, - // custom header overrides the default - expect(capturedRequest!.headers.get('Upgrade')).toBe('custom-protocol'); - }); - }); - - describe('RequestInit options', () => { - it('should pass through method option', async () => { - await sandbox.connect(3001, { - method: 'GET', - }); - - expect(capturedRequest).not.toBeNull(); - expect(capturedRequest!.method).toBe('GET'); - }); - - it('should pass through multiple options', async () => { - await sandbox.connect(3001, { - method: 'GET', - headers: { - 'User-Agent': 'test-client', - }, - }); - - expect(capturedRequest).not.toBeNull(); - expect(capturedRequest!.method).toBe('GET'); - expect(capturedRequest!.headers.get('User-Agent')).toBe('test-client'); - }); - - it('should work with no options provided', async () => { - await sandbox.connect(3001); - - expect(capturedRequest).not.toBeNull(); - expect(capturedRequest!.url).toBe('http://localhost:3001/'); - expect(capturedRequest!.headers.get('Upgrade')).toBe('websocket'); - }); - }); - - describe('Port and path variations', () => { - it('should handle different port numbers correctly', async () => { - const testCases = [ - { port: 3000, expected: 'http://localhost:3000/' }, - { port: 3001, expected: 'http://localhost:3001/' }, - { port: 8080, expected: 'http://localhost:8080/' }, - { port: 8888, expected: 'http://localhost:8888/' }, - ]; - - for (const { port, expected } of testCases) { - capturedRequest = null; - await sandbox.connect(port); - expect(capturedRequest).not.toBeNull(); - expect(capturedRequest!.url).toBe(expected); - } - }); - - it('should handle different path formats correctly', async () => { - const testCases = [ - { path: '/ws', expected: 'http://localhost:3000/ws' }, - { path: '/ws/chat', expected: 'http://localhost:3000/ws/chat' }, - { path: '/api/v1/websocket', expected: 'http://localhost:3000/api/v1/websocket' }, - { path: '/socket.io', expected: 'http://localhost:3000/socket.io' }, - ]; - - for (const { path, expected } of testCases) { - capturedRequest = null; - await sandbox.connect(path); - expect(capturedRequest).not.toBeNull(); - expect(capturedRequest!.url).toBe(expected); - } - }); - - it('should use defaultPort (3000) for path-based connections', async () => { - await sandbox.connect('/ws/test'); - - expect(capturedRequest).not.toBeNull(); - expect(capturedRequest!.url).toBe('http://localhost:3000/ws/test'); - }); - }); -}); diff --git a/packages/shared/src/types.ts b/packages/shared/src/types.ts index db612287..45bb0220 100644 --- a/packages/shared/src/types.ts +++ b/packages/shared/src/types.ts @@ -669,7 +669,6 @@ export interface ISandbox { runCodeStream(code: string, options?: RunCodeOptions): Promise; listCodeContexts(): Promise; deleteCodeContext(contextId: string): Promise; - connect(portOrUrl: number | string, options?: RequestInit): Promise; } // Type guards for runtime validation From e057849d7dae0ddab7433ea81cdfe5ff766c143a Mon Sep 17 00:00:00 2001 From: katereznykova Date: Tue, 28 Oct 2025 18:51:58 +0000 Subject: [PATCH 07/16] cleanup connect() --- examples/websocket/Dockerfile | 5 +- examples/websocket/README.md | 731 +++++++++----------- examples/websocket/src/index.ts | 1066 ++++++++++------------------- packages/sandbox/src/index.ts | 13 - packages/sandbox/src/websocket.ts | 683 ------------------ 5 files changed, 688 insertions(+), 1810 deletions(-) delete mode 100644 packages/sandbox/src/websocket.ts diff --git a/examples/websocket/Dockerfile b/examples/websocket/Dockerfile index ff21181a..89e76e33 100644 --- a/examples/websocket/Dockerfile +++ b/examples/websocket/Dockerfile @@ -8,7 +8,8 @@ FROM docker.io/cloudflare/sandbox:0.4.10 # arm64 build of the image. # FROM --platform=linux/arm64 cloudflare/sandbox-test:0.4.10 -# Expose the ports you want to expose +# Expose the ports for WebSocket examples EXPOSE 8080 -EXPOSE 3001 +EXPOSE 8081 +EXPOSE 8082 diff --git a/examples/websocket/README.md b/examples/websocket/README.md index ad2003f5..bd94d5ce 100644 --- a/examples/websocket/README.md +++ b/examples/websocket/README.md @@ -1,6 +1,19 @@ # WebSocket Examples for Sandbox SDK -This example demonstrates how to use WebSockets with the Cloudflare Sandbox SDK for real-time, bidirectional communication between clients and sandboxed containers. +This example demonstrates how to use WebSockets with the Cloudflare Sandbox SDK by routing client connections to WebSocket servers running inside containers. + +## Architecture + +The WebSocket integration uses `connect(sandbox, request, port)` to route incoming WebSocket requests directly to WebSocket servers running inside the sandbox container: + +``` +Client ←WebSocket→ [Worker routes via connect()] → Container WebSocket Server +``` + +The pattern: +1. Start a WebSocket server inside the container (e.g., using Bun, Node.js, Python) +2. Use `connect(sandbox, request, port)` to route the incoming WebSocket upgrade request +3. Client communicates directly with the container's WebSocket server ## Setup @@ -26,537 +39,423 @@ npm run deploy 2. Open your browser to `http://localhost:8787` - ### WebSocket Endpoints #### `/ws/echo` -Basic echo server with sandbox command execution. - -**Client Message Format:** -```json -{ - "type": "echo", - "data": "Hello, sandbox!" -} -``` - -```json -{ - "type": "execute", - "command": "python --version" -} -``` - -**Server Response Format:** -```json -{ - "type": "echo", - "data": "Hello, sandbox!", - "timestamp": 1234567890 -} -``` - -```json -{ - "type": "result", - "stdout": "Python 3.11.0\n", - "stderr": "", - "exitCode": 0 -} -``` - -#### `/ws/code` -Real-time code execution with streaming output. - -**Client Message Format:** -```json -{ - "type": "execute", - "code": "print('Hello from Python')", - "language": "python", - "sessionId": "session-123" -} -``` +Simple echo server that sends back any message it receives. -**Server Response Format:** -```json -{ - "type": "stdout", - "data": "Hello from Python\n", - "sessionId": "session-123" -} -``` - -```json -{ - "type": "result", - "sessionId": "session-123", - "results": [...], - "error": null, - "logs": { "stdout": [...], "stderr": [...] } -} -``` - -#### `/ws/process` -Stream output from long-running processes. - -**Client Message Format:** -```json -{ - "type": "start", - "command": "ping", - "args": ["-c", "5", "cloudflare.com"] -} -``` - -```json -{ - "type": "kill" -} -``` - -**Server Response Format:** -```json -{ - "type": "started", - "pid": 12345 -} -``` - -```json -{ - "type": "stdout", - "data": "PING cloudflare.com...\n", - "pid": 12345 -} -``` - -```json -{ - "type": "completed", - "pid": 12345 -} -``` - -#### `/ws/terminal` -Interactive terminal session. +**Client Example:** +```javascript +const ws = new WebSocket('ws://localhost:8787/ws/echo?id=my-session'); -**Client Message Format:** -``` -ls -la\n -``` +ws.onmessage = (event) => { + console.log('Received:', event.data); +}; -```json -{ - "type": "resize", - "rows": 24, - "cols": 80 -} +ws.send('Hello!'); +// Receives: "Hello!" ``` -**Server Response:** -Raw terminal output or JSON status messages. - -## Code Examples - -### JavaScript Client +#### `/ws/broadcast` +Broadcasts messages to all connected clients (great for chat applications). +**Client Example:** ```javascript -// Connect to echo server -const ws = new WebSocket('wss://your-worker.workers.dev/ws/echo?id=my-session'); - -ws.onopen = () => { - console.log('Connected'); - - // Send echo message - ws.send(JSON.stringify({ - type: 'echo', - data: 'Hello!' - })); - - // Execute command - ws.send(JSON.stringify({ - type: 'execute', - command: 'python -c "print(2+2)"' - })); -}; +const ws = new WebSocket('ws://localhost:8787/ws/broadcast?id=shared-room'); ws.onmessage = (event) => { const data = JSON.parse(event.data); - console.log('Received:', data); -}; -ws.onclose = () => { - console.log('Disconnected'); + if (data.type === 'join') { + console.log(`User ${data.id} joined, ${data.count} online`); + } else if (data.type === 'message') { + console.log(`${data.from}: ${data.text}`); + } }; -``` - -### Python Client -```python -import asyncio -import websockets -import json - -async def execute_code(): - uri = "wss://your-worker.workers.dev/ws/code?id=my-session" - - async with websockets.connect(uri) as websocket: - # Send code to execute - await websocket.send(json.dumps({ - "type": "execute", - "code": """ -import time -for i in range(5): - print(f'Count: {i}') - time.sleep(0.5) - """, - "sessionId": "test-1" - })) - - # Receive streaming output - while True: - try: - message = await websocket.recv() - data = json.loads(message) - - if data['type'] == 'stdout': - print(data['data'], end='') - elif data['type'] == 'result': - print('Execution complete') - break - except websockets.exceptions.ConnectionClosed: - break - -asyncio.run(execute_code()) +ws.send('Hello everyone!'); ``` -### Node.js Client +#### `/ws/json` +JSON RPC server that handles structured commands. +**Client Example:** ```javascript -import WebSocket from 'ws'; +const ws = new WebSocket('ws://localhost:8787/ws/json?id=my-session'); -const ws = new WebSocket('ws://localhost:8787/ws/process?id=node-client'); +// Send ping +ws.send(JSON.stringify({ type: 'ping' })); -ws.on('open', () => { - console.log('Connected to process streamer'); +// Execute command in container +ws.send(JSON.stringify({ + type: 'exec', + id: Date.now(), + command: 'ls -la' +})); - // Start a long-running process - ws.send(JSON.stringify({ - type: 'start', - command: 'python', - args: ['-u', 'long_script.py'] - })); -}); +// Get system info +ws.send(JSON.stringify({ + type: 'info', + id: Date.now() +})); +``` -ws.on('message', (data) => { - const message = JSON.parse(data); +## Implementation Pattern - if (message.type === 'stdout' || message.type === 'stderr') { - process.stdout.write(message.data); - } else if (message.type === 'completed') { - console.log('Process completed'); - ws.close(); - } +Here's the basic pattern for creating a WebSocket endpoint: + +```typescript +import { connect, getSandbox, Sandbox } from "@cloudflare/sandbox"; + +async function handleWebSocket(request: Request, env: Env): Promise { + const sandboxId = "my-sandbox"; + const sandbox = getSandbox(env.Sandbox, sandboxId); + const port = 8080; + + // 1. Create WebSocket server script (using Bun) + const serverScript = ` +const port = ${port}; + +Bun.serve({ + port, + fetch(req, server) { + if (server.upgrade(req)) { + return; + } + return new Response('Expected WebSocket', { status: 400 }); + }, + websocket: { + message(ws, message) { + // Handle incoming messages + ws.send('Echo: ' + message); + }, + open(ws) { + console.log('Client connected'); + }, + close(ws) { + console.log('Client disconnected'); + }, + }, }); -// Kill process after 10 seconds -setTimeout(() => { - ws.send(JSON.stringify({ type: 'kill' })); -}, 10000); +console.log(\`WebSocket server listening on port \${port}\`); +`; + + // 2. Write server script to container + await sandbox.writeFile('/tmp/ws-server.ts', serverScript); + + // 3. Start the server as a background process + try { + await sandbox.startProcess(\`bun run /tmp/ws-server.ts\`, { + processId: \`ws-server-\${port}\` + }); + } catch (error: any) { + // Server might already be running + if (!error.message?.includes('already exists')) { + throw error; + } + } + + // 4. Give server time to start + await new Promise(resolve => setTimeout(resolve, 1000)); + + // 5. Route WebSocket to container server + return await connect(sandbox, request, port); +} ``` ## Use Cases -### 1. Real-Time Data Analysis - -Stream data processing results as they're computed: +### 1. Real-Time Communication +Build chat applications, collaborative tools, or live notifications: ```javascript -const ws = new WebSocket('wss://your-worker.workers.dev/ws/code'); +// All clients sharing the same sandbox ID see each other's messages +const ws = new WebSocket('wss://your-worker.workers.dev/ws/broadcast?id=room-123'); -ws.send(JSON.stringify({ - type: 'execute', - code: ` -import pandas as pd -import time - -for chunk in pd.read_csv('large_file.csv', chunksize=1000): - result = chunk.describe() - print(result) - time.sleep(0.1) - `, - sessionId: 'analysis-1' -})); +ws.send('Hello from client!'); +// All clients in room-123 receive this message ``` -### 2. AI Code Agent - -AI agent that generates and executes code with real-time feedback: +### 2. Remote Command Execution +Execute commands in the container with real-time output: ```javascript -// Generate code with AI -const code = await generateWithAI(userPrompt); +const ws = new WebSocket('wss://your-worker.workers.dev/ws/json'); -// Execute and stream results ws.send(JSON.stringify({ - type: 'execute', - code: code, - sessionId: 'ai-agent-1' + type: 'exec', + command: 'python train.py', + id: Date.now() })); -// User sees live output as code runs +// Receive execution results ws.onmessage = (event) => { - const data = JSON.parse(event.data); - if (data.type === 'stdout') { - updateUI(data.data); - } + const result = JSON.parse(event.data); + console.log('stdout:', result.stdout); + console.log('exit code:', result.exitCode); }; ``` -### 3. Collaborative IDE +### 3. Interactive Services +Host any WebSocket-based service in the container: -Multiple users share a sandbox: +- WebSocket terminals (xterm.js) +- Real-time data feeds +- Game servers +- Streaming APIs +- Custom protocols -```javascript -// User A's connection -const wsA = new WebSocket('wss://your-worker.workers.dev/ws/code?id=shared-123'); +## Server Technologies -// User B's connection (same sandbox) -const wsB = new WebSocket('wss://your-worker.workers.dev/ws/code?id=shared-123'); +You can run any WebSocket server inside the container: -// Both see the same execution results -wsA.send(JSON.stringify({ - type: 'execute', - code: 'x = 42' -})); - -wsB.send(JSON.stringify({ - type: 'execute', - code: 'print(x)' // Prints 42 from shared context -})); +### Bun (recommended - already in container) +```typescript +Bun.serve({ + port: 8080, + websocket: { + message(ws, message) { + ws.send(message); + } + } +}); ``` -### 4. Live Monitoring - -Monitor sandbox metrics and logs: - +### Node.js ```javascript -const ws = new WebSocket('wss://your-worker.workers.dev/ws/process'); - -ws.send(JSON.stringify({ - type: 'start', - command: 'top', - args: ['-b', '-d', '1'] // Update every second -})); +const WebSocket = require('ws'); +const wss = new WebSocket.Server({ port: 8080 }); -// Real-time system monitoring -ws.onmessage = (event) => { - const data = JSON.parse(event.data); - if (data.type === 'stdout') { - updateMonitoringDashboard(data.data); - } -}; +wss.on('connection', (ws) => { + ws.on('message', (message) => { + ws.send(message); + }); +}); ``` -## Best Practices +### Python +```python +import asyncio +import websockets -### 1. Error Handling +async def echo(websocket): + async for message in websocket: + await websocket.send(message) -Always handle errors gracefully: +start_server = websockets.serve(echo, "0.0.0.0", 8080) +asyncio.run(start_server) +``` -```javascript -ws.onerror = (error) => { - console.error('WebSocket error:', error); - // Attempt reconnection - setTimeout(() => reconnect(), 1000); -}; +## Advanced Patterns -ws.onclose = (event) => { - if (event.code !== 1000) { // Not a normal closure - console.log('Unexpected close, reconnecting...'); - reconnect(); - } -}; -``` +### Multiple Ports +Run different WebSocket services on different ports: -### 2. Heartbeat/Ping-Pong +```typescript +switch (pathname) { + case "/ws/chat": + return connect(sandbox, request, 8080); // Chat server + case "/ws/terminal": + return connect(sandbox, request, 8081); // Terminal + case "/ws/game": + return connect(sandbox, request, 8082); // Game server +} +``` -Keep connections alive: +### Shared vs Isolated Sandboxes +```typescript +// Shared sandbox - all clients connect to same server +const sandbox = getSandbox(env.Sandbox, "shared-room"); -```javascript -let pingInterval; +// Isolated sandbox - each user gets their own server +const sandbox = getSandbox(env.Sandbox, userId); +``` -ws.onopen = () => { - // Send ping every 30 seconds - pingInterval = setInterval(() => { - ws.send(JSON.stringify({ type: 'ping' })); - }, 30000); -}; +### Connection Management +```typescript +// Check if server is running before connecting +const processes = await sandbox.listProcesses(); +const serverRunning = processes.some(p => p.id === 'ws-server-8080'); + +if (!serverRunning) { + // Start server + await sandbox.startProcess('bun run /tmp/ws-server.ts', { + processId: 'ws-server-8080' + }); + await new Promise(resolve => setTimeout(resolve, 1000)); +} -ws.onclose = () => { - clearInterval(pingInterval); -}; +return connect(sandbox, request, 8080); ``` -### 3. Message Buffering +## Best Practices -Buffer messages when disconnected: +### 1. Process Management +Use named process IDs to avoid starting duplicate servers: -```javascript -const messageQueue = []; -let isConnected = false; - -function sendMessage(msg) { - if (isConnected) { - ws.send(JSON.stringify(msg)); - } else { - messageQueue.push(msg); +```typescript +try { + await sandbox.startProcess('bun run /tmp/server.ts', { + processId: 'ws-server-8080' // Named ID prevents duplicates + }); +} catch (error: any) { + if (!error.message?.includes('already exists')) { + throw error; } } +``` -ws.onopen = () => { - isConnected = true; - // Flush queue - while (messageQueue.length > 0) { - ws.send(JSON.stringify(messageQueue.shift())); - } -}; +### 2. Startup Delays +Give servers time to bind to ports before routing connections: + +```typescript +await sandbox.startProcess('bun run /tmp/server.ts'); +await new Promise(resolve => setTimeout(resolve, 1000)); // Wait 1 second +return connect(sandbox, request, port); ``` -### 4. Rate Limiting +### 3. Error Handling +Handle connection failures gracefully: -Prevent overwhelming the sandbox: +```typescript +try { + return await connect(sandbox, request, port); +} catch (error) { + console.error('Failed to connect:', error); + return new Response('WebSocket server unavailable', { status: 503 }); +} +``` + +### 4. Client Reconnection +Implement reconnection logic in clients: ```javascript -class RateLimitedWebSocket { - constructor(url, messagesPerSecond = 10) { - this.ws = new WebSocket(url); - this.queue = []; - this.limit = messagesPerSecond; - this.interval = 1000 / messagesPerSecond; - - setInterval(() => this.processQueue(), this.interval); - } +let reconnectAttempts = 0; +const maxAttempts = 5; - send(message) { - this.queue.push(message); - } +function connect() { + const ws = new WebSocket(url); - processQueue() { - if (this.queue.length > 0 && this.ws.readyState === 1) { - this.ws.send(this.queue.shift()); + ws.onclose = () => { + if (reconnectAttempts < maxAttempts) { + reconnectAttempts++; + setTimeout(connect, 1000 * reconnectAttempts); } - } + }; + + ws.onopen = () => { + reconnectAttempts = 0; + }; } ``` -## Security Considerations - -### Authentication - -Add authentication to WebSocket connections: +### 5. Message Validation +Always validate incoming messages in your container server: ```typescript -// Server side -const token = new URL(request.url).searchParams.get('token'); -if (!token || !(await verifyToken(token))) { - return new Response('Unauthorized', { status: 401 }); +websocket: { + message(ws, message) { + try { + const data = JSON.parse(message.toString()); + + if (!data.type || typeof data.type !== 'string') { + ws.send(JSON.stringify({ error: 'Invalid message format' })); + return; + } + + // Handle valid message + } catch (error) { + ws.send(JSON.stringify({ error: 'Invalid JSON' })); + } + } } ``` +## Security Considerations + ### Input Validation +Always validate commands and inputs in your container server: + +```typescript +case 'exec': + // Don't trust user input - validate and sanitize + const command = data.command; + if (!isValidCommand(command)) { + return { error: 'Invalid command' }; + } + // Execute safely + break; +``` -Always validate and sanitize inputs: +### Rate Limiting +Implement rate limiting in your container server: ```typescript -server.addEventListener('message', async (event) => { - const message = JSON.parse(event.data); +const rateLimits = new Map(); - // Validate message structure - if (!message.type || typeof message.type !== 'string') { - server.send(JSON.stringify({ type: 'error', message: 'Invalid format' })); - return; - } +websocket: { + message(ws, message) { + const clientId = ws.data.id; + const now = Date.now(); - // Prevent command injection - if (message.command && /[;&|`$]/.test(message.command)) { - server.send(JSON.stringify({ type: 'error', message: 'Invalid characters' })); - return; + const lastMessage = rateLimits.get(clientId) || 0; + if (now - lastMessage < 100) { // Max 10 msg/sec + ws.send(JSON.stringify({ error: 'Rate limit exceeded' })); + return; + } + + rateLimits.set(clientId, now); + // Handle message } -}); +} ``` -### Resource Limits - -Set limits on connections and execution time: +### Authentication +Add authentication before routing to WebSocket: ```typescript -const MAX_CONNECTIONS = 100; -const MAX_EXECUTION_TIME = 60000; // 60 seconds +async function handleWebSocket(request: Request, env: Env): Promise { + const url = new URL(request.url); + const token = url.searchParams.get('token'); -if (activeConnections.size >= MAX_CONNECTIONS) { - server.close(1008, 'Connection limit reached'); - return; -} + if (!await verifyToken(token)) { + return new Response('Unauthorized', { status: 401 }); + } -// Set execution timeout -const timeout = setTimeout(() => { - server.close(1000, 'Execution timeout'); -}, MAX_EXECUTION_TIME); + // Route to WebSocket + return connect(sandbox, request, port); +} ``` ## Troubleshooting ### Connection Refused - -Check that WebSocket upgrades are properly handled: -- Verify `Upgrade: websocket` header is present -- Ensure status code 101 is returned -- Check that WebSocketPair is created correctly +- Ensure server is running: check with `sandbox.listProcesses()` +- Verify port is correct +- Wait longer after starting server (increase delay) ### Messages Not Received +- Check WebSocket upgrade header is present +- Verify message format (text vs binary) +- Ensure server is calling `server.upgrade(req)` in Bun -Ensure proper message formatting: -- Use `JSON.stringify()` for structured data -- Check for serialization errors -- Verify server is calling `server.accept()` - -### Connection Drops - -Implement reconnection logic: -```javascript -let reconnectAttempts = 0; -const MAX_RECONNECT_ATTEMPTS = 5; - -function connect() { - const ws = new WebSocket(url); - - ws.onclose = () => { - if (reconnectAttempts < MAX_RECONNECT_ATTEMPTS) { - reconnectAttempts++; - setTimeout(connect, 1000 * reconnectAttempts); - } - }; - - ws.onopen = () => { - reconnectAttempts = 0; - }; -} -``` +### Server Not Starting +- Check for port conflicts (use different ports for each service) +- Verify server script has no syntax errors +- Check container logs for error messages ## Performance Tips -1. **Use Binary Frames** for large data transfers -2. **Buffer Small Messages** to reduce syscalls -3. **Implement Backpressure** to handle slow clients -4. **Use Compression** for text-heavy streams -5. **Batch Updates** when sending frequent small updates +1. **Reuse Servers**: Use named process IDs to avoid restarting servers on each connection +2. **Connection Pooling**: Share sandbox instances across multiple clients using the same sandbox ID +3. **Binary Messages**: Use binary frames for large data transfers to reduce overhead +4. **Batch Updates**: Send multiple updates in a single message when possible ## Further Reading - [Cloudflare Workers WebSocket Documentation](https://developers.cloudflare.com/workers/runtime-apis/websockets/) -- [Sandbox SDK Documentation](https://developers.cloudflare.com/sandbox/) +- [Bun WebSocket API](https://bun.sh/docs/api/websockets) - [WebSocket RFC 6455](https://datatracker.ietf.org/doc/html/rfc6455) ## License diff --git a/examples/websocket/src/index.ts b/examples/websocket/src/index.ts index 5e064346..78d8b4f3 100644 --- a/examples/websocket/src/index.ts +++ b/examples/websocket/src/index.ts @@ -1,16 +1,11 @@ /** * WebSocket Example for Cloudflare Sandbox SDK + * + * This example demonstrates how to use connect() to route WebSocket requests + * to WebSocket servers running inside sandbox containers. */ -import { - connect, - createWebSocketHandler, - getSandbox, - parseSSEStream, - Sandbox, - SandboxWebSocket, - type LogEvent -} from "@cloudflare/sandbox"; +import { connect, getSandbox, Sandbox } from "@cloudflare/sandbox"; interface Env { Sandbox: DurableObjectNamespace; @@ -21,6 +16,11 @@ export default { const url = new URL(request.url); const pathname = url.pathname; + // Initialize servers endpoint (called on page load) + if (pathname === "/api/init") { + return handleInitServers(request, env); + } + // Check for WebSocket upgrade const upgradeHeader = request.headers.get("Upgrade"); if (upgradeHeader !== "websocket") { @@ -38,15 +38,9 @@ export default { case "/ws/echo": return handleEchoWebSocket(request, env); case "/ws/code": - return handleCodeExecutionWebSocket(request, env); - case "/ws/process": - return handleProcessStreamWebSocket(request, env); + return handleCodeStreamingWebSocket(request, env); case "/ws/terminal": return handleTerminalWebSocket(request, env); - case "/ws/protected": - return handleProtectedWebSocket(request, env); - case "/ws/container": - return handleContainerWebSocket(request, env); default: return new Response("Unknown WebSocket endpoint", { status: 404 }); } @@ -54,530 +48,224 @@ export default { }; /** - * Example 1: Basic Echo Server - * Demonstrates basic WebSocket handling with sandbox execution using createWebSocketHandler + * Initialize all WebSocket servers on page load + * This ensures servers are ready when users click "Connect" */ -async function handleEchoWebSocket( - request: Request, - env: Env -): Promise { - // Use the createWebSocketHandler helper for automatic setup - const { response, websocket: ws, sandbox, sandboxId } = await createWebSocketHandler( - request, - env.Sandbox as any as DurableObjectNamespace, - { - sandboxId: new URL(request.url).searchParams.get("id") || "echo-sandbox", - onReady: (ws, sandboxId) => { - // Send welcome message when connection is ready - ws.send({ - type: "connected", - message: "Echo server connected", - sandboxId, - }); - }, - onMessage: async (ws, message) => { - switch (message.type) { - case "echo": - // Simple echo back - ws.send({ - type: "echo", - data: message.data, - timestamp: Date.now(), - }); - break; - - case "execute": - // Execute a command in the sandbox and echo the result - const result = await sandbox.exec(message.command); - ws.send({ - type: "result", - stdout: result.stdout, - stderr: result.stderr, - exitCode: result.exitCode, - }); - break; - - case "ping": - ws.send({ type: "pong" }); - break; - - default: - ws.sendError("Unknown message type"); - } - }, - onClose: () => { - console.log("WebSocket closed"); - }, - } - ); - - return response; -} - -/** - * Example 2: Real-Time Code Execution - * Executes Python/JavaScript code using basic shell execution - */ -async function handleCodeExecutionWebSocket( - request: Request, - env: Env -): Promise { - const { response, websocket: ws, sandbox } = await createWebSocketHandler( - request, - env.Sandbox as any as DurableObjectNamespace, - { - sandboxId: new URL(request.url).searchParams.get("id") || "code-interpreter", - onReady: (ws) => { - ws.sendReady("Code interpreter ready"); - }, - onMessage: async (ws, message) => { - if (message.type === "execute") { - const { code, language = "python", sessionId } = message; - - // Send acknowledgment - ws.send({ - type: "executing", - sessionId, - }); - - try { - // Write code to a temporary file and execute it - const filename = `/tmp/code_${Date.now()}.${language === "javascript" ? "js" : "py"}`; - await sandbox.writeFile(filename, code); - - // Execute the code - const command = language === "javascript" - ? `node ${filename}` - : `python3 ${filename}`; - - const result = await sandbox.exec(command); - - // Send output - if (result.stdout) { - ws.sendOutput("stdout", result.stdout); - } - if (result.stderr) { - ws.sendOutput("stderr", result.stderr); - } - - // Send final result - ws.send({ - type: "result", - sessionId, - exitCode: result.exitCode, - success: result.exitCode === 0, - }); - - // Clean up - await sandbox.exec(`rm -f ${filename}`); - } catch (error: any) { - ws.sendError(error); - } - } else if (message.type === "reset") { - // Clean up any temporary files - await sandbox.exec("rm -f /tmp/code_*.py /tmp/code_*.js").catch(() => {}); - ws.send({ - type: "reset", - message: "Context reset", - }); - } - }, - } - ); - - return response; -} +async function handleInitServers(request: Request, env: Env): Promise { + const sandboxId = new URL(request.url).searchParams.get("id") || "demo-sandbox"; + const sandbox = getSandbox(env.Sandbox, sandboxId); -/** - * Example 3: Process Output Streaming - * Starts a long-running process and streams its output using createWebSocketHandler - */ -async function handleProcessStreamWebSocket( - request: Request, - env: Env -): Promise { - let currentProcess: any = null; - - const { response, websocket: ws, sandbox } = await createWebSocketHandler( - request, - env.Sandbox as any as DurableObjectNamespace, - { - sandboxId: new URL(request.url).searchParams.get("id") || "process-stream", - onReady: (ws) => { - ws.sendReady("Process streamer ready"); - }, - onMessage: async (ws, message) => { - if (message.type === "start") { - const { command, args = [] } = message; - - // Build full command string - const fullCommand = args.length > 0 ? `${command} ${args.join(' ')}` : command; - - // Start the process using the built-in helper - currentProcess = await ws.startProcessWithStreaming(fullCommand); - - ws.send({ - type: "started", - pid: currentProcess.pid, - }); - - // Stream logs in the background (handled by startProcessWithStreaming) - // But we need to listen for completion + try { + // Check which servers are already running + const processes = await sandbox.listProcesses(); + const runningServers = new Set( + processes + .filter(p => p.status === 'running') + .map(p => p.id) + ); + + const serversToStart = []; + + // Echo server (port 8080) + if (!runningServers.has('echo-server-8080')) { + const echoScript = ` +const port = 8080; +Bun.serve({ + port, + fetch(req, server) { + if (server.upgrade(req)) return; + return new Response('Expected WebSocket', { status: 400 }); + }, + websocket: { + message(ws, message) { ws.send(message); }, + open(ws) { console.log('Client connected'); }, + close(ws) { console.log('Client disconnected'); }, + }, +}); +console.log('Echo server listening on port ' + port); +`; + await sandbox.writeFile('/tmp/echo-server.ts', echoScript); + serversToStart.push( + sandbox.startProcess('bun run /tmp/echo-server.ts', { + processId: 'echo-server-8080' + }).catch(() => {}) + ); + } + + // Code server (port 8081) + if (!runningServers.has('code-server-8081')) { + const codeScript = ` +const port = 8081; +Bun.serve({ + port, + fetch(req, server) { + if (server.upgrade(req)) return; + return new Response('Expected WebSocket', { status: 400 }); + }, + websocket: { + async message(ws, message) { + try { + const data = JSON.parse(message.toString()); + if (data.type === 'execute') { + const { code } = data; + ws.send(JSON.stringify({ type: 'executing', timestamp: Date.now() })); + const filename = '/tmp/code_' + Date.now() + '.py'; + await Bun.write(filename, code); + const proc = Bun.spawn(['python3', filename], { stdout: 'pipe', stderr: 'pipe' }); + const reader = proc.stdout.getReader(); + const textDecoder = new TextDecoder(); (async () => { try { - const logStream = await sandbox.streamProcessLogs(currentProcess.id); - - for await (const event of parseSSEStream(logStream)) { - if (event.type === "stdout" || event.type === "stderr") { - ws.sendOutput(event.type, event.data, currentProcess.pid); - } + while (true) { + const { done, value } = await reader.read(); + if (done) break; + const text = textDecoder.decode(value, { stream: true }); + if (text) ws.send(JSON.stringify({ type: 'stdout', data: text, timestamp: Date.now() })); } - - // Process completed - ws.send({ - type: "completed", - pid: currentProcess.pid, - }); - } catch (error: any) { - ws.sendError(error); - } + } catch (e) {} })(); - } else if (message.type === "kill" && currentProcess) { - await sandbox.killProcess(currentProcess.id); - ws.send({ - type: "killed", - pid: currentProcess.pid, - }); - currentProcess = null; + const stderrReader = proc.stderr.getReader(); + (async () => { + try { + while (true) { + const { done, value } = await stderrReader.read(); + if (done) break; + const text = textDecoder.decode(value, { stream: true }); + if (text) ws.send(JSON.stringify({ type: 'stderr', data: text, timestamp: Date.now() })); + } + } catch (e) {} + })(); + const exitCode = await proc.exited; + ws.send(JSON.stringify({ type: 'completed', exitCode, timestamp: Date.now() })); + try { await Bun.spawn(['rm', '-f', filename]).exited; } catch (e) {} } - }, - onClose: async () => { - if (currentProcess) { - try { - await sandbox.killProcess(currentProcess.id); - } catch { - // Process might already be done - } + } catch (error) { + ws.send(JSON.stringify({ type: 'error', message: error.message || String(error), timestamp: Date.now() })); + } + }, + open(ws) { + ws.send(JSON.stringify({ type: 'ready', message: 'Python code execution server ready', timestamp: Date.now() })); + }, + }, +}); +console.log('Code streaming server listening on port ' + port); +`; + await sandbox.writeFile('/tmp/code-server.ts', codeScript); + serversToStart.push( + sandbox.startProcess('bun run /tmp/code-server.ts', { + processId: 'code-server-8081' + }).catch(() => {}) + ); + } + + // Terminal server (port 8082) + if (!runningServers.has('terminal-server-8082')) { + const terminalScript = ` +const port = 8082; +Bun.serve({ + port, + fetch(req, server) { + if (server.upgrade(req)) return; + return new Response('Expected WebSocket', { status: 400 }); + }, + websocket: { + async message(ws, message) { + try { + const data = JSON.parse(message.toString()); + if (data.type === 'command') { + const { command } = data; + ws.send(JSON.stringify({ type: 'executing', command, timestamp: Date.now() })); + const proc = Bun.spawn(['sh', '-c', command], { stdout: 'pipe', stderr: 'pipe' }); + const stdout = await new Response(proc.stdout).text(); + const stderr = await new Response(proc.stderr).text(); + const exitCode = await proc.exited; + ws.send(JSON.stringify({ type: 'result', stdout, stderr, exitCode, timestamp: Date.now() })); + } else if (data.type === 'ping') { + ws.send(JSON.stringify({ type: 'pong', timestamp: Date.now() })); } - }, - } - ); - - return response; + } catch (error) { + ws.send(JSON.stringify({ type: 'error', message: error.message || String(error), timestamp: Date.now() })); + } + }, + open(ws) { + ws.send(JSON.stringify({ type: 'ready', message: 'Terminal server ready', cwd: process.cwd(), timestamp: Date.now() })); + }, + }, +}); +console.log('Terminal server listening on port ' + port); +`; + await sandbox.writeFile('/tmp/terminal-server.ts', terminalScript); + serversToStart.push( + sandbox.startProcess('bun run /tmp/terminal-server.ts', { + processId: 'terminal-server-8082' + }).catch(() => {}) + ); + } + + // Start all servers (fire and forget) + await Promise.all(serversToStart); + + return new Response(JSON.stringify({ + success: true, + message: 'Servers initialized', + serversStarted: serversToStart.length + }), { + headers: { 'Content-Type': 'application/json' } + }); + } catch (error: any) { + return new Response(JSON.stringify({ + success: false, + error: error.message + }), { + status: 500, + headers: { 'Content-Type': 'application/json' } + }); + } } /** - * Example 4: Interactive Terminal - * Provides a full interactive shell session using createWebSocketHandler + * Example 1: Basic Echo Server + * Echoes back any message received */ -async function handleTerminalWebSocket( +async function handleEchoWebSocket( request: Request, env: Env ): Promise { - let shell: any = null; - - const { response, websocket: ws, sandbox } = await createWebSocketHandler( - request, - env.Sandbox as any as DurableObjectNamespace, - { - sandboxId: new URL(request.url).searchParams.get("id") || "terminal-session", - onReady: async (ws) => { - // Start an interactive bash shell - shell = await sandbox.startProcess("/bin/bash -i", { - env: { - TERM: "xterm-256color", - PS1: "\\[\\033[01;32m\\]sandbox\\[\\033[00m\\]:\\[\\033[01;34m\\]\\w\\[\\033[00m\\]$ ", - }, - }); - - ws.send({ - type: "ready", - pid: shell.pid, - message: "Terminal connected", - }); - - // Stream shell output to client - (async () => { - try { - const logStream = await sandbox.streamProcessLogs(shell.id); - - for await (const event of parseSSEStream(logStream)) { - if (event.type === "stdout") { - // Send raw output for terminal rendering - ws.raw.send(event.data); - } - } - - // Shell exited - ws.send({ - type: "exit", - message: "Shell process exited", - }); - ws.close(1000, "Shell exited"); - } catch (error: any) { - ws.sendError(error); - ws.close(1011, "Error"); - } - })(); - }, - onMessage: async (ws, message, event) => { - const input = event.data as string; - - // Handle special commands - if (input.startsWith("{")) { - const command = JSON.parse(input); - - if (command.type === "resize") { - // Handle terminal resize (would need TTY support) - // For now, just acknowledge - ws.send({ - type: "resized", - rows: command.rows, - cols: command.cols, - }); - } - } else { - // Regular input - send to shell stdin - // Note: This requires implementing sendToProcess in the sandbox - // await sandbox.sendToProcess(shell.pid, input); - - // For now, we'll use a workaround by executing each line - if (input.includes('\n')) { - const result = await sandbox.exec(input.trim()); - ws.raw.send(result.stdout + result.stderr); - } - } - }, - onClose: async () => { - if (shell) { - try { - await sandbox.killProcess(shell.id); - } catch { - // Process might already be done - } - } - }, - } - ); + const sandboxId = new URL(request.url).searchParams.get("id") || "demo-sandbox"; + const sandbox = getSandbox(env.Sandbox, sandboxId); - return response; + // Server is pre-initialized on page load, just connect + return await connect(sandbox, request, 8080); } /** - * Example 5: Protected WebSocket with Rate Limiting & Timeouts + * Example 2: Code Streaming Server + * Executes code and streams output in real-time */ -async function handleProtectedWebSocket( +async function handleCodeStreamingWebSocket( request: Request, env: Env ): Promise { - const { response, websocket: ws, sandbox, sandboxId } = await createWebSocketHandler( - request, - env.Sandbox as any as DurableObjectNamespace, - { - sandboxId: new URL(request.url).searchParams.get("id") || "protected-session", - // Configure rate limiting - rateLimit: { - maxMessages: 100, - windowMs: 60000, // 1 minute - maxMessageSize: 1024 * 1024, // 1MB - }, - // Configure connection timeouts - timeout: { - idleTimeout: 300000, // 5 minutes - maxConnectionTime: 1800000, // 30 minutes - heartbeatInterval: 30000, // 30 seconds - }, - onReady: (ws, sandboxId) => { - // Send welcome with limits info - ws.send({ - type: "connected", - message: "Protected WebSocket connected", - sandboxId, - limits: { - maxMessages: 100, - windowMs: 60000, - maxMessageSize: 1024 * 1024, - idleTimeout: 300000, - maxConnectionTime: 1800000, - }, - }); - }, - onMessage: async (ws, message) => { - switch (message.type) { - case "echo": - ws.send({ - type: "echo", - data: message.data, - timestamp: Date.now(), - }); - break; - - case "execute": - const result = await sandbox.exec(message.command); - ws.send({ - type: "result", - stdout: result.stdout, - stderr: result.stderr, - exitCode: result.exitCode, - }); - break; - - case "status": - ws.send({ - type: "status", - connected: true, - sandboxId, - }); - break; - - default: - ws.sendError("Unknown message type"); - } - }, - onRateLimitExceeded: (ws) => { - console.log("Rate limit exceeded for protected WebSocket"); - }, - onClose: () => { - console.log("Protected WebSocket closed"); - }, - } - ); + const sandboxId = new URL(request.url).searchParams.get("id") || "demo-sandbox"; + const sandbox = getSandbox(env.Sandbox, sandboxId); - return response; + // Server is pre-initialized on page load, just connect + return await connect(sandbox, request, 8081); } /** - * Example 6: Connect to WebSocket Server Inside Container - * Demonstrates using connect() to proxy to a WebSocket server running in the container - * - * This example shows how to connect to a WebSocket server that's running inside - * the sandbox container. We use connect(sandbox, request, port) to route the incoming - * WebSocket request to port 8080 where our Node.js WebSocket server is listening. + * Example 3: Interactive Terminal + * Provides terminal-like command execution */ -async function handleContainerWebSocket( +async function handleTerminalWebSocket( request: Request, env: Env ): Promise { - const sandboxId = new URL(request.url).searchParams.get("id") || "container-ws"; - - // Get sandbox instance using getSandbox helper + const sandboxId = new URL(request.url).searchParams.get("id") || "demo-sandbox"; const sandbox = getSandbox(env.Sandbox, sandboxId); - // Create a simple Node.js WebSocket echo server - // Using Node.js because it should be available in the container - const serverScript = ` -const http = require('http'); -const crypto = require('crypto'); - -const server = http.createServer((req, res) => { - res.writeHead(200); - res.end('WebSocket server running'); -}); - -server.on('upgrade', (req, socket) => { - const key = req.headers['sec-websocket-key']; - const acceptKey = crypto - .createHash('sha1') - .update(key + '258EAFA5-E914-47DA-95CA-C5AB0DC85B11') - .digest('base64'); - - socket.write( - 'HTTP/1.1 101 Switching Protocols\\r\\n' + - 'Upgrade: websocket\\r\\n' + - 'Connection: Upgrade\\r\\n' + - 'Sec-WebSocket-Accept: ' + acceptKey + '\\r\\n\\r\\n' - ); - - socket.on('data', (data) => { - // Simple echo - parse WebSocket frame and echo back - if (data[0] === 0x81) { - const len = data[1] & 127; - const maskStart = 2; - const dataStart = maskStart + 4; - const mask = data.slice(maskStart, dataStart); - const payload = data.slice(dataStart, dataStart + len); - - // Unmask the payload - const decoded = Buffer.alloc(len); - for (let i = 0; i < len; i++) { - decoded[i] = payload[i] ^ mask[i % 4]; - } - - // Echo back (server doesn't mask) - const response = Buffer.alloc(2 + len); - response[0] = 0x81; // Text frame - response[1] = len; - decoded.copy(response, 2); - socket.write(response); - } - }); - - socket.on('close', () => { - console.log('WebSocket closed'); - }); -}); - -server.listen(8080, '0.0.0.0', () => { - console.log('WebSocket server listening on port 8080'); -}); -`; - - // Write the server script - await sandbox.writeFile('/tmp/ws_server.js', serverScript); - - // Start the server using startProcess (better for long-running processes) - try { - await sandbox.startProcess('node /tmp/ws_server.js', { - processId: 'ws-server-8080' - }); - console.log('WebSocket server process started'); - } catch (error: any) { - // Server might already be running, that's okay - if (!error.message?.includes('already exists')) { - console.error('Failed to start WebSocket server:', error); - throw error; - } - console.log('WebSocket server already running'); - } - - // Give the server time to start and begin listening - await new Promise(resolve => setTimeout(resolve, 2000)); - - // Check if the process is still running - try { - const processes = await sandbox.listProcesses(); - const serverProcess = processes.find(p => p.id === 'ws-server-8080'); - - if (!serverProcess || serverProcess.status !== 'running') { - console.error('WebSocket server process not running:', serverProcess); - return new Response('WebSocket server failed to start', { status: 503 }); - } - - console.log('WebSocket server process is running:', serverProcess); - } catch (e) { - console.error('Failed to check process status:', e); - } - - // Use connect() to route the incoming WebSocket to port 8080 - // This is a convenient helper that uses switchPort internally - console.log('Using connect(sandbox, request, 8080) to route WebSocket...'); - - try { - const response = await connect(sandbox, request, 8080); - - console.log('connect() returned status:', response.status); - console.log('Response headers:', Object.fromEntries(response.headers)); - - return response; - } catch (error: any) { - console.error('connect() failed:', error); - console.error('Error type:', error.constructor.name); - console.error('Error message:', error.message); - console.error('Error stack:', error.stack); - return new Response(`Failed to connect to container WebSocket: ${error.message}`, { - status: 500 - }); - } + // Server is pre-initialized on page load, just connect + return await connect(sandbox, request, 8082); } /** @@ -632,6 +320,7 @@ function getTestHTML(): string { color: #d4d4d4; font-family: 'Courier New', monospace; margin: 10px 0; + box-sizing: border-box; } .output { background: #1e1e1e; @@ -653,151 +342,136 @@ function getTestHTML(): string { } .connected { background: #0e639c; } .disconnected { background: #f48771; } - .error { color: #f48771; } - .success { color: #4ec9b0; } + .info { + background: #2d2d30; + border: 2px solid #4ec9b0; + border-radius: 8px; + padding: 20px; + margin: 20px 0; + }

Sandbox SDK WebSocket Examples

-
-

Two WebSocket Communication Methods

- -
-

- createWebSocketHandler() - DO <--> Client with Sandbox Operations -

-

- Use this when you want to communicate between the Durable Object and the client, - performing sandbox operations (run code, start processes, execute commands). - The DO handles messages and interacts with the sandbox. -

-

- Examples: Echo Server, Code Execution, Process Streaming -

-
- -
-

- connect(sandbox, request, port) - Route Client -> Container Service -

-

- Use this when you have a WebSocket server running inside the container - (e.g., a Node.js app on port 8080) and want to route incoming client - WebSocket connections directly to it. -

-

- Example: Container WebSocket (routes to Node.js WebSocket server on port 8080) -

-
+
+

WebSocket with connect()

+

+ All examples use connect(sandbox, request, port) to route incoming + WebSocket requests to WebSocket servers running inside the container. +

+

+ Initializing servers... +

1. Echo Server

-

- Method: createWebSocketHandler() - DO <--> Client with Sandbox Operations +

+ Simple echo - sends back any message you send to it

Disconnected
- +
-

2. Code Execution

-

- Method: createWebSocketHandler() - DO <--> Client with Sandbox Operations +

2. Python Code Streaming

+

+ Execute Python code with real-time streaming output

Disconnected
- - +
-

3. Process Streaming

-

- Method: createWebSocketHandler() - DO <--> Client with Sandbox Operations +

3. Interactive Terminal

+

+ Run shell commands and see results

-
Disconnected
- - - - - -
-
- -
-

4. Container WebSocket

-

- Method: connect(sandbox, request, port) - Route Client -> Container Service -

-

- Routes WebSocket to a Node.js server running on port 8080 inside the container -

-
Disconnected
- - - - -
+
Disconnected
+ + + + + +
`; diff --git a/packages/sandbox/src/index.ts b/packages/sandbox/src/index.ts index e5f54e0b..5ea896ae 100644 --- a/packages/sandbox/src/index.ts +++ b/packages/sandbox/src/index.ts @@ -91,16 +91,3 @@ export { } from './request-handler'; // Export SSE parser for converting ReadableStream to AsyncIterable export { asyncIterableToSSEStream, parseSSEStream, responseToAsyncIterable } from "./sse-parser"; - -export { - createWebSocketHandler, - type ErrorMessage, - type OutputMessage, - type ReadyMessage, - type ResultMessage, - SandboxWebSocket, - type StatusMessage, - type WebSocketHandlerOptions, - type WebSocketHandlerResult, - type WebSocketMessage -} from './websocket'; diff --git a/packages/sandbox/src/websocket.ts b/packages/sandbox/src/websocket.ts deleted file mode 100644 index 7bfb2090..00000000 --- a/packages/sandbox/src/websocket.ts +++ /dev/null @@ -1,683 +0,0 @@ -/** - * WebSocket helpers for Cloudflare Sandbox SDK - */ - -import type { ISandbox, LogEvent, Process } from '@repo/shared'; -import { parseSSEStream } from './sse-parser'; - -/** - * Standard message types for sandbox WebSocket communication - */ -export interface WebSocketMessage { - type: string; - [key: string]: any; -} - -export interface ReadyMessage extends WebSocketMessage { - type: 'ready'; - message: string; - sandboxId?: string; -} - -export interface OutputMessage extends WebSocketMessage { - type: 'stdout' | 'stderr'; - data: string; - pid?: number; -} - -export interface ErrorMessage extends WebSocketMessage { - type: 'error'; - message: string; - code?: string; - stack?: string; -} - -export interface StatusMessage extends WebSocketMessage { - type: 'status'; - status: string; - message?: string; -} - -export interface ResultMessage extends WebSocketMessage { - type: 'result'; - data: any; - executionTime?: number; -} - -/** - * Type-safe wrapper around WebSocket for sandbox communication - * - * Provides helpers for: - * - Sending structured messages with automatic JSON serialization - * - Streaming process logs to the client - * - Running code with real-time output streaming - * - Error handling and connection management - */ -export class SandboxWebSocket { - constructor( - private readonly server: WebSocket, - private readonly sandbox: ISandbox - ) {} - - /** - * Send a type-safe message to the client - */ - send(message: WebSocketMessage): void { - try { - this.server.send(JSON.stringify(message)); - } catch (error) { - console.error('Failed to send WebSocket message:', error); - } - } - - /** - * Send a ready notification - */ - sendReady(message: string, sandboxId?: string): void { - this.send({ - type: 'ready', - message, - sandboxId, - } as ReadyMessage); - } - - /** - * Send output (stdout or stderr) - */ - sendOutput(type: 'stdout' | 'stderr', data: string, pid?: number): void { - this.send({ - type, - data, - pid, - } as OutputMessage); - } - - /** - * Send an error message - */ - sendError(error: Error | string, code?: string): void { - const message = typeof error === 'string' ? error : error.message; - const stack = typeof error === 'string' ? undefined : error.stack; - - this.send({ - type: 'error', - message, - code, - stack, - } as ErrorMessage); - } - - /** - * Send a status update - */ - sendStatus(status: string, message?: string): void { - this.send({ - type: 'status', - status, - message, - } as StatusMessage); - } - - /** - * Send a result - */ - sendResult(data: any, executionTime?: number): void { - this.send({ - type: 'result', - data, - executionTime, - } as ResultMessage); - } - - /** - * Stream process logs to the WebSocket client - * - * This bridges the sandbox's SSE log stream to WebSocket, - * automatically parsing and forwarding log events. - * - * @param process - The process to stream logs from - * @returns Promise that resolves when streaming completes - */ - async streamProcessLogs(process: Process): Promise { - try { - const logStream = await this.sandbox.streamProcessLogs(process.id); - - for await (const event of parseSSEStream(logStream)) { - if (event.type === 'stdout' || event.type === 'stderr') { - this.sendOutput(event.type, event.data, process.pid); - } else if (event.type === 'exit') { - this.send({ - type: 'exit', - pid: process.pid, - exitCode: event.exitCode, - }); - } - } - } catch (error) { - this.sendError(error as Error); - } - } - - /** - * Execute code with real-time output streaming - * - * @param code - Code to execute - * @param options - Execution options including language and context - * @returns Promise that resolves with the execution result - */ - async runCodeWithStreaming( - code: string, - options?: { language?: 'python' | 'javascript'; context?: any; } - ): Promise { - const startTime = Date.now(); - - try { - this.sendStatus('executing'); - - // Use runCodeStream for streaming support - const stream = await this.sandbox.runCodeStream(code, { - language: options?.language || 'python', - context: options?.context, - }); - - // Stream results back to client - for await (const chunk of parseSSEStream(stream)) { - if (chunk.type === 'stdout' || chunk.type === 'stderr') { - this.sendOutput(chunk.type, chunk.data); - } else if (chunk.type === 'result') { - const executionTime = Date.now() - startTime; - this.sendResult(chunk.data, executionTime); - return chunk.data; - } else if (chunk.type === 'error') { - this.sendError(chunk.data); - throw new Error(chunk.data); - } - } - } catch (error) { - this.sendError(error as Error); - throw error; - } - } - - /** - * Start a process and stream its output - * - * @param command - Command to execute (including arguments) - * @returns Promise that resolves with the process - */ - async startProcessWithStreaming(command: string): Promise { - try { - const process = await this.sandbox.startProcess(command); - - this.send({ - type: 'process_started', - pid: process.pid, - id: process.id, - command, - }); - - // Stream logs in the background - this.streamProcessLogs(process).catch(error => { - console.error('Error streaming process logs:', error); - }); - - return process; - } catch (error) { - this.sendError(error as Error); - throw error; - } - } - - /** - * Close the WebSocket connection - */ - close(code?: number, reason?: string): void { - try { - this.server.close(code, reason); - } catch (error) { - console.error('Failed to close WebSocket:', error); - } - } - - /** - * Get the underlying WebSocket server instance - */ - get raw(): WebSocket { - return this.server; - } -} - -/** - * Rate limiting configuration - */ -export interface RateLimitConfig { - /** - * Maximum messages per window (default: 100) - */ - maxMessages?: number; - - /** - * Time window in milliseconds (default: 60000 = 1 minute) - */ - windowMs?: number; - - /** - * Maximum message size in bytes (default: 1MB) - */ - maxMessageSize?: number; -} - -/** - * Connection timeout configuration - */ -export interface TimeoutConfig { - /** - * Idle timeout - close connection if no messages received (default: 5 minutes) - */ - idleTimeout?: number; - - /** - * Maximum connection duration (default: 30 minutes) - */ - maxConnectionTime?: number; - - /** - * Heartbeat interval - send ping to keep connection alive (default: 30 seconds) - */ - heartbeatInterval?: number; -} - -/** - * Options for creating a WebSocket handler - */ -export interface WebSocketHandlerOptions { - /** - * Custom sandbox ID (defaults to URL param or random UUID) - */ - sandboxId?: string; - - /** - * Rate limiting configuration - */ - rateLimit?: RateLimitConfig; - - /** - * Connection timeout configuration - */ - timeout?: TimeoutConfig; - - /** - * Callback when WebSocket is ready - */ - onReady?: (ws: SandboxWebSocket, sandboxId: string) => void | Promise; - - /** - * Callback for incoming messages - */ - onMessage?: (ws: SandboxWebSocket, message: any, event: MessageEvent) => void | Promise; - - /** - * Callback when WebSocket closes - */ - onClose?: (ws: SandboxWebSocket, event: CloseEvent) => void | Promise; - - /** - * Callback for WebSocket errors - */ - onError?: (ws: SandboxWebSocket, event: Event | ErrorEvent) => void | Promise; - - /** - * Callback when rate limit is exceeded - */ - onRateLimitExceeded?: (ws: SandboxWebSocket) => void | Promise; -} - -/** - * Result of creating a WebSocket handler - */ -export interface WebSocketHandlerResult { - /** - * The Response object to return from fetch() - */ - response: Response; - - /** - * The SandboxWebSocket wrapper - */ - websocket: SandboxWebSocket; - - /** - * The sandbox instance - */ - sandbox: ISandbox; - - /** - * The sandbox ID used - */ - sandboxId: string; -} - -/** - * Rate limiter using sliding window algorithm - */ -class RateLimiter { - private timestamps: number[] = []; - private readonly maxMessages: number; - private readonly windowMs: number; - private readonly maxMessageSize: number; - - constructor(config: RateLimitConfig = {}) { - this.maxMessages = config.maxMessages ?? 100; - this.windowMs = config.windowMs ?? 60000; // 1 minute - this.maxMessageSize = config.maxMessageSize ?? 1024 * 1024; // 1MB - } - - /** - * Check if a message is allowed under rate limits - */ - checkMessage(messageSize: number): { allowed: boolean; reason?: string } { - // Check message size - if (messageSize > this.maxMessageSize) { - return { - allowed: false, - reason: `Message size ${messageSize} exceeds limit of ${this.maxMessageSize} bytes`, - }; - } - - const now = Date.now(); - - // Remove timestamps outside the current window - this.timestamps = this.timestamps.filter( - (timestamp) => now - timestamp < this.windowMs - ); - - // Check if we're at the limit - if (this.timestamps.length >= this.maxMessages) { - return { - allowed: false, - reason: `Rate limit exceeded: ${this.maxMessages} messages per ${this.windowMs}ms`, - }; - } - - // Record this message - this.timestamps.push(now); - return { allowed: true }; - } - - /** - * Get current usage statistics - */ - getStats() { - const now = Date.now(); - this.timestamps = this.timestamps.filter( - (timestamp) => now - timestamp < this.windowMs - ); - - return { - messagesInWindow: this.timestamps.length, - maxMessages: this.maxMessages, - windowMs: this.windowMs, - remaining: Math.max(0, this.maxMessages - this.timestamps.length), - }; - } - - /** - * Reset the rate limiter - */ - reset(): void { - this.timestamps = []; - } -} - -/** - * Connection timeout manager - */ -class TimeoutManager { - private idleTimer?: number; - private maxConnectionTimer?: number; - private heartbeatTimer?: number; - private lastActivity: number; - private readonly config: Required; - - constructor( - private readonly ws: SandboxWebSocket, - config: TimeoutConfig = {} - ) { - this.config = { - idleTimeout: config.idleTimeout ?? 300000, // 5 minutes - maxConnectionTime: config.maxConnectionTime ?? 1800000, // 30 minutes - heartbeatInterval: config.heartbeatInterval ?? 30000, // 30 seconds - }; - this.lastActivity = Date.now(); - } - - /** - * Start all timeout timers - */ - start(): void { - // Start idle timeout - this.resetIdleTimer(); - - // Start max connection timer - this.maxConnectionTimer = setTimeout(() => { - this.ws.close(1000, 'Maximum connection time reached'); - }, this.config.maxConnectionTime) as unknown as number; - - // Start heartbeat - if (this.config.heartbeatInterval > 0) { - this.startHeartbeat(); - } - } - - /** - * Reset idle timer (call this on activity) - */ - resetIdleTimer(): void { - this.lastActivity = Date.now(); - - if (this.idleTimer) { - clearTimeout(this.idleTimer); - } - - this.idleTimer = setTimeout(() => { - this.ws.close(1000, 'Idle timeout'); - }, this.config.idleTimeout) as unknown as number; - } - - /** - * Start heartbeat ping/pong mechanism - */ - private startHeartbeat(): void { - this.heartbeatTimer = setInterval(() => { - // Check if we're past idle timeout - const timeSinceActivity = Date.now() - this.lastActivity; - if (timeSinceActivity > this.config.idleTimeout) { - this.ws.close(1000, 'Heartbeat timeout'); - this.stop(); - return; - } - - // Send heartbeat - try { - this.ws.send({ type: 'ping', timestamp: Date.now() }); - } catch (error) { - console.error('Failed to send heartbeat:', error); - } - }, this.config.heartbeatInterval) as unknown as number; - } - - /** - * Stop all timers - */ - stop(): void { - if (this.idleTimer) { - clearTimeout(this.idleTimer); - this.idleTimer = undefined; - } - - if (this.maxConnectionTimer) { - clearTimeout(this.maxConnectionTimer); - this.maxConnectionTimer = undefined; - } - - if (this.heartbeatTimer) { - clearInterval(this.heartbeatTimer); - this.heartbeatTimer = undefined; - } - } - - /** - * Get timeout statistics - */ - getStats() { - const now = Date.now(); - const timeSinceActivity = now - this.lastActivity; - - return { - lastActivity: this.lastActivity, - timeSinceActivity, - idleTimeoutRemaining: Math.max( - 0, - this.config.idleTimeout - timeSinceActivity - ), - config: this.config, - }; - } -} - -/** - * Create a WebSocket handler with automatic setup and lifecycle management - */ -export async function createWebSocketHandler( - request: Request, - sandboxNamespace: DurableObjectNamespace, - options: WebSocketHandlerOptions = {} -): Promise { - // Create WebSocket pair - const pair = new WebSocketPair(); - const [client, server] = Object.values(pair); - - // Get sandbox ID - const url = new URL(request.url); - const sandboxId = - options.sandboxId || - url.searchParams.get('id') || - crypto.randomUUID(); - - // Get sandbox instance - const id = sandboxNamespace.idFromName(sandboxId); - const stub = sandboxNamespace.get(id); - const sandbox = stub as unknown as ISandbox; - - // Accept connection - server.accept(); - - // Create wrapper - const ws = new SandboxWebSocket(server, sandbox); - - // Initialize rate limiter if configured - const rateLimiter = options.rateLimit - ? new RateLimiter(options.rateLimit) - : null; - - // Initialize timeout manager if configured - const timeoutManager = options.timeout - ? new TimeoutManager(ws, options.timeout) - : null; - - // Start timeout tracking - if (timeoutManager) { - timeoutManager.start(); - } - - // Set up event handlers - if (options.onMessage) { - server.addEventListener('message', async (event) => { - try { - // Reset idle timer on activity - if (timeoutManager) { - timeoutManager.resetIdleTimer(); - } - - // Check rate limit - if (rateLimiter) { - const messageSize = new Blob([event.data as string]).size; - const rateLimitResult = rateLimiter.checkMessage(messageSize); - - if (!rateLimitResult.allowed) { - ws.sendError( - `Rate limit exceeded: ${rateLimitResult.reason}`, - 'RATE_LIMIT_EXCEEDED' - ); - - // Call rate limit callback if provided - if (options.onRateLimitExceeded) { - await options.onRateLimitExceeded(ws); - } - - // Don't process the message - return; - } - } - - const message = JSON.parse(event.data as string); - - // Handle pong messages for heartbeat - if (message.type === 'pong') { - return; // Just acknowledge, don't process - } - - await options.onMessage!(ws, message, event); - } catch (error) { - console.error('Error handling message:', error); - ws.sendError(error as Error); - } - }); - } - - if (options.onClose) { - server.addEventListener('close', async (event) => { - try { - // Stop timeout manager - if (timeoutManager) { - timeoutManager.stop(); - } - - await options.onClose!(ws, event); - } catch (error) { - console.error('Error handling close:', error); - } - }); - } - - if (options.onError) { - server.addEventListener('error', async (event) => { - try { - await options.onError!(ws, event); - } catch (error) { - console.error('Error handling error:', error); - } - }); - } - - // Call onReady callback - if (options.onReady) { - try { - await options.onReady(ws, sandboxId); - } catch (error) { - console.error('Error in onReady callback:', error); - ws.sendError(error as Error); - } - } - - // Return response and wrapper - return { - response: new Response(null, { - status: 101, - webSocket: client, - }), - websocket: ws, - sandbox, - sandboxId, - }; -} From da070d6852d1887b9ca52212086035de31571d9f Mon Sep 17 00:00:00 2001 From: katereznykova Date: Tue, 28 Oct 2025 19:28:20 +0000 Subject: [PATCH 08/16] add more tests --- .changeset/loud-nights-sneeze.md | 5 + tests/e2e/test-worker/index.ts | 155 +++++++- tests/e2e/test-worker/tsconfig.json | 18 + tests/e2e/websocket-connect.test.ts | 578 ++++++++++++++++++++++++++++ 4 files changed, 755 insertions(+), 1 deletion(-) create mode 100644 .changeset/loud-nights-sneeze.md create mode 100644 tests/e2e/test-worker/tsconfig.json create mode 100644 tests/e2e/websocket-connect.test.ts diff --git a/.changeset/loud-nights-sneeze.md b/.changeset/loud-nights-sneeze.md new file mode 100644 index 00000000..08ee4b3d --- /dev/null +++ b/.changeset/loud-nights-sneeze.md @@ -0,0 +1,5 @@ +--- +"@cloudflare/sandbox": minor +--- + +add websockets support via connect() method diff --git a/tests/e2e/test-worker/index.ts b/tests/e2e/test-worker/index.ts index bc0a9dc3..9f9a1570 100644 --- a/tests/e2e/test-worker/index.ts +++ b/tests/e2e/test-worker/index.ts @@ -4,7 +4,7 @@ * Exposes SDK methods via HTTP endpoints for E2E testing. * Supports both default sessions (implicit) and explicit sessions via X-Session-Id header. */ -import { Sandbox, getSandbox, proxyToSandbox, type ExecutionSession } from '@cloudflare/sandbox'; +import { Sandbox, getSandbox, proxyToSandbox, connect } from '@cloudflare/sandbox'; export { Sandbox }; interface Env { @@ -45,6 +45,159 @@ export default { : sandbox; try { + // WebSocket init endpoint - starts all WebSocket servers + if (url.pathname === '/api/init' && request.method === 'POST') { + const processes = await sandbox.listProcesses(); + const runningServers = new Set(processes.filter(p => p.status === 'running').map(p => p.id)); + + const serversToStart = []; + + // Echo server + if (!runningServers.has('ws-echo-8080')) { + const echoScript = ` +const port = 8080; +Bun.serve({ + port, + fetch(req, server) { + if (server.upgrade(req)) return; + return new Response('Expected WebSocket', { status: 400 }); + }, + websocket: { + message(ws, message) { ws.send(message); }, + open(ws) { console.log('Echo client connected'); }, + close(ws) { console.log('Echo client disconnected'); }, + }, +}); +console.log('Echo server on port ' + port); +`; + await sandbox.writeFile('/tmp/ws-echo.ts', echoScript); + serversToStart.push( + sandbox.startProcess('bun run /tmp/ws-echo.ts', { processId: 'ws-echo-8080' }).catch(() => {}) + ); + } + + // Python code server + if (!runningServers.has('ws-code-8081')) { + const codeScript = ` +const port = 8081; +Bun.serve({ + port, + fetch(req, server) { + if (server.upgrade(req)) return; + return new Response('Expected WebSocket', { status: 400 }); + }, + websocket: { + async message(ws, message) { + try { + const data = JSON.parse(message.toString()); + if (data.type === 'execute') { + ws.send(JSON.stringify({ type: 'executing', timestamp: Date.now() })); + const filename = '/tmp/code_' + Date.now() + '.py'; + await Bun.write(filename, data.code); + const proc = Bun.spawn(['python3', filename], { stdout: 'pipe', stderr: 'pipe' }); + const reader = proc.stdout.getReader(); + const decoder = new TextDecoder(); + (async () => { + try { + while (true) { + const { done, value } = await reader.read(); + if (done) break; + const text = decoder.decode(value, { stream: true }); + if (text) ws.send(JSON.stringify({ type: 'stdout', data: text, timestamp: Date.now() })); + } + } catch (e) {} + })(); + const stderrReader = proc.stderr.getReader(); + (async () => { + try { + while (true) { + const { done, value } = await stderrReader.read(); + if (done) break; + const text = decoder.decode(value, { stream: true }); + if (text) ws.send(JSON.stringify({ type: 'stderr', data: text, timestamp: Date.now() })); + } + } catch (e) {} + })(); + const exitCode = await proc.exited; + ws.send(JSON.stringify({ type: 'completed', exitCode, timestamp: Date.now() })); + try { await Bun.spawn(['rm', '-f', filename]).exited; } catch (e) {} + } + } catch (error) { + ws.send(JSON.stringify({ type: 'error', message: error.message, timestamp: Date.now() })); + } + }, + open(ws) { ws.send(JSON.stringify({ type: 'ready', message: 'Code server ready', timestamp: Date.now() })); }, + }, +}); +console.log('Code server on port ' + port); +`; + await sandbox.writeFile('/tmp/ws-code.ts', codeScript); + serversToStart.push( + sandbox.startProcess('bun run /tmp/ws-code.ts', { processId: 'ws-code-8081' }).catch(() => {}) + ); + } + + // Terminal server + if (!runningServers.has('ws-terminal-8082')) { + const terminalScript = ` +const port = 8082; +Bun.serve({ + port, + fetch(req, server) { + if (server.upgrade(req)) return; + return new Response('Expected WebSocket', { status: 400 }); + }, + websocket: { + async message(ws, message) { + try { + const data = JSON.parse(message.toString()); + if (data.type === 'command') { + ws.send(JSON.stringify({ type: 'executing', command: data.command, timestamp: Date.now() })); + const proc = Bun.spawn(['sh', '-c', data.command], { stdout: 'pipe', stderr: 'pipe' }); + const stdout = await new Response(proc.stdout).text(); + const stderr = await new Response(proc.stderr).text(); + const exitCode = await proc.exited; + ws.send(JSON.stringify({ type: 'result', stdout, stderr, exitCode, timestamp: Date.now() })); + } + } catch (error) { + ws.send(JSON.stringify({ type: 'error', message: error.message, timestamp: Date.now() })); + } + }, + open(ws) { ws.send(JSON.stringify({ type: 'ready', message: 'Terminal ready', cwd: process.cwd(), timestamp: Date.now() })); }, + }, +}); +console.log('Terminal server on port ' + port); +`; + await sandbox.writeFile('/tmp/ws-terminal.ts', terminalScript); + serversToStart.push( + sandbox.startProcess('bun run /tmp/ws-terminal.ts', { processId: 'ws-terminal-8082' }).catch(() => {}) + ); + } + + await Promise.all(serversToStart); + + return new Response(JSON.stringify({ + success: true, + serversStarted: serversToStart.length + }), { + headers: { 'Content-Type': 'application/json' } + }); + } + + // WebSocket endpoints + const upgradeHeader = request.headers.get('Upgrade'); + if (upgradeHeader === 'websocket') { + if (url.pathname === '/ws/echo') { + return await connect(sandbox, request, 8080); + } + if (url.pathname === '/ws/code') { + return await connect(sandbox, request, 8081); + } + if (url.pathname === '/ws/terminal') { + return await connect(sandbox, request, 8082); + } + } + // Health check if (url.pathname === '/health') { return new Response(JSON.stringify({ status: 'ok' }), { diff --git a/tests/e2e/test-worker/tsconfig.json b/tests/e2e/test-worker/tsconfig.json new file mode 100644 index 00000000..7a04c914 --- /dev/null +++ b/tests/e2e/test-worker/tsconfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "target": "esnext", + "lib": ["esnext"], + "module": "esnext", + "moduleResolution": "bundler", + "types": ["@cloudflare/workers-types"], + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "skipLibCheck": true, + "noEmit": true, + "resolveJsonModule": true, + "isolatedModules": true + }, + "include": ["*.ts"], + "exclude": ["node_modules"] +} diff --git a/tests/e2e/websocket-connect.test.ts b/tests/e2e/websocket-connect.test.ts new file mode 100644 index 00000000..01492906 --- /dev/null +++ b/tests/e2e/websocket-connect.test.ts @@ -0,0 +1,578 @@ +import { describe, test, expect, beforeAll, afterAll, afterEach } from 'vitest'; +import WebSocket from 'ws'; +import { getTestWorkerUrl, WranglerDevRunner } from './helpers/wrangler-runner'; +import { createSandboxId, createTestHeaders, cleanupSandbox } from './helpers/test-fixtures'; + +/** + * WebSocket connect() Integration Tests + * + * Tests the new connect() pattern for routing WebSocket requests directly to + * container services, plus the /api/init endpoint for pre-initializing servers. + * + * COVERAGE: + * - /api/init endpoint functionality + * - Direct WebSocket routing via connect() + * - Python code streaming with real-time output + * - Terminal command execution + * - Server persistence across connections + * - Multiple concurrent connections + */ +describe('WebSocket connect() Pattern', () => { + let runner: WranglerDevRunner | null = null; + let workerUrl: string; + let currentSandboxId: string | null = null; + + beforeAll(async () => { + const result = await getTestWorkerUrl(); + workerUrl = result.url; + runner = result.runner; + }); + + afterEach(async () => { + if (currentSandboxId) { + await cleanupSandbox(workerUrl, currentSandboxId); + currentSandboxId = null; + } + }); + + afterAll(async () => { + if (runner) { + await runner.stop(); + } + }); + + test('should initialize all servers via /api/init endpoint', async () => { + currentSandboxId = createSandboxId(); + const headers = createTestHeaders(currentSandboxId); + + // Call /api/init to start all servers + const response = await fetch(`${workerUrl}/api/init`, { + method: 'POST', + headers, + }); + + expect(response.status).toBe(200); + const data = await response.json(); + + expect(data.success).toBe(true); + expect(data.serversStarted).toBeGreaterThanOrEqual(0); // May be 0 if already running + + // Wait for servers to be ready + await new Promise(resolve => setTimeout(resolve, 2000)); + + // Verify all three server processes exist + const processesResponse = await fetch(`${workerUrl}/api/process/list`, { + method: 'GET', + headers, + }); + + expect(processesResponse.status).toBe(200); + const processes = await processesResponse.json(); + + const processIds = processes.map((p: any) => p.id); + expect(processIds).toContain('ws-echo-8080'); + expect(processIds).toContain('ws-code-8081'); + expect(processIds).toContain('ws-terminal-8082'); + + // Verify all are running + const runningProcesses = processes.filter((p: any) => p.status === 'running'); + expect(runningProcesses.length).toBeGreaterThanOrEqual(3); + }, 30000); + + test('should connect to echo server directly using connect()', async () => { + currentSandboxId = createSandboxId(); + const headers = createTestHeaders(currentSandboxId); + + // Initialize servers + await fetch(`${workerUrl}/api/init`, { + method: 'POST', + headers, + }); + + // Wait for servers to be ready + await new Promise(resolve => setTimeout(resolve, 2000)); + + // Connect via WebSocket using connect() pattern (no port exposure API) + const wsUrl = workerUrl.replace(/^http/, 'ws') + '/ws/echo'; + const ws = new WebSocket(wsUrl, { + headers: { + 'X-Sandbox-Id': currentSandboxId, + }, + }); + + // Wait for connection + await new Promise((resolve, reject) => { + ws.on('open', () => resolve()); + ws.on('error', (error) => reject(error)); + setTimeout(() => reject(new Error('Connection timeout')), 10000); + }); + + // Send message and verify echo + const testMessage = 'Hello from connect() test!'; + const messagePromise = new Promise((resolve, reject) => { + ws.on('message', (data) => resolve(data.toString())); + setTimeout(() => reject(new Error('Echo timeout')), 5000); + }); + + ws.send(testMessage); + const echoedMessage = await messagePromise; + + expect(echoedMessage).toBe(testMessage); + + // Close connection + ws.close(); + await new Promise((resolve) => { + ws.on('close', () => resolve()); + setTimeout(() => resolve(), 1000); + }); + }, 30000); + + test('should stream Python code execution output in real-time', async () => { + currentSandboxId = createSandboxId(); + const headers = createTestHeaders(currentSandboxId); + + // Initialize servers + await fetch(`${workerUrl}/api/init`, { + method: 'POST', + headers, + }); + + await new Promise(resolve => setTimeout(resolve, 2000)); + + // Connect to code streaming server + const wsUrl = workerUrl.replace(/^http/, 'ws') + '/ws/code'; + const ws = new WebSocket(wsUrl, { + headers: { + 'X-Sandbox-Id': currentSandboxId, + }, + }); + + await new Promise((resolve, reject) => { + ws.on('open', () => resolve()); + ws.on('error', (error) => reject(error)); + setTimeout(() => reject(new Error('Connection timeout')), 10000); + }); + + // Collect all messages + const messages: any[] = []; + ws.on('message', (data) => { + try { + messages.push(JSON.parse(data.toString())); + } catch (e) { + console.error('Failed to parse message:', data.toString()); + } + }); + + // Send Python code with multiple print statements and delays + const pythonCode = ` +import time +for i in range(3): + print(f'Count: {i}') + time.sleep(0.3) +print('Done!') +`; + + ws.send(JSON.stringify({ + type: 'execute', + code: pythonCode, + })); + + // Wait for completion + await new Promise((resolve, reject) => { + const checkComplete = () => { + const completed = messages.find(m => m.type === 'completed'); + if (completed) { + resolve(); + } else { + setTimeout(checkComplete, 100); + } + }; + checkComplete(); + setTimeout(() => reject(new Error('Execution timeout')), 10000); + }); + + // Verify message sequence + expect(messages.some(m => m.type === 'ready')).toBe(true); + expect(messages.some(m => m.type === 'executing')).toBe(true); + + // Verify we got stdout messages (streaming) + const stdoutMessages = messages.filter(m => m.type === 'stdout'); + expect(stdoutMessages.length).toBeGreaterThan(0); + + // Verify output contains our print statements + const fullOutput = stdoutMessages.map(m => m.data).join(''); + expect(fullOutput).toContain('Count: 0'); + expect(fullOutput).toContain('Count: 1'); + expect(fullOutput).toContain('Count: 2'); + expect(fullOutput).toContain('Done!'); + + // Verify completion with exit code 0 + const completedMsg = messages.find(m => m.type === 'completed'); + expect(completedMsg).toBeDefined(); + expect(completedMsg.exitCode).toBe(0); + + ws.close(); + }, 30000); + + test('should handle Python code execution errors with non-zero exit code', async () => { + currentSandboxId = createSandboxId(); + const headers = createTestHeaders(currentSandboxId); + + await fetch(`${workerUrl}/api/init`, { + method: 'POST', + headers, + }); + + await new Promise(resolve => setTimeout(resolve, 2000)); + + const wsUrl = workerUrl.replace(/^http/, 'ws') + '/ws/code'; + const ws = new WebSocket(wsUrl, { + headers: { + 'X-Sandbox-Id': currentSandboxId, + }, + }); + + await new Promise((resolve, reject) => { + ws.on('open', () => resolve()); + ws.on('error', (error) => reject(error)); + setTimeout(() => reject(new Error('Connection timeout')), 10000); + }); + + const messages: any[] = []; + ws.on('message', (data) => { + try { + messages.push(JSON.parse(data.toString())); + } catch (e) {} + }); + + // Send Python code that raises an error + const pythonCode = ` +print('Starting...') +raise ValueError('This is a test error') +print('This should not print') +`; + + ws.send(JSON.stringify({ + type: 'execute', + code: pythonCode, + })); + + // Wait for completion + await new Promise((resolve, reject) => { + const checkComplete = () => { + const completed = messages.find(m => m.type === 'completed'); + if (completed) { + resolve(); + } else { + setTimeout(checkComplete, 100); + } + }; + checkComplete(); + setTimeout(() => reject(new Error('Execution timeout')), 10000); + }); + + // Verify we got stderr with error message + const stderrMessages = messages.filter(m => m.type === 'stderr'); + expect(stderrMessages.length).toBeGreaterThan(0); + + const stderrOutput = stderrMessages.map(m => m.data).join(''); + expect(stderrOutput).toContain('ValueError'); + expect(stderrOutput).toContain('This is a test error'); + + // Verify non-zero exit code + const completedMsg = messages.find(m => m.type === 'completed'); + expect(completedMsg).toBeDefined(); + expect(completedMsg.exitCode).not.toBe(0); + + ws.close(); + }, 30000); + + test('should execute terminal commands and return results', async () => { + currentSandboxId = createSandboxId(); + const headers = createTestHeaders(currentSandboxId); + + await fetch(`${workerUrl}/api/init`, { + method: 'POST', + headers, + }); + + await new Promise(resolve => setTimeout(resolve, 2000)); + + const wsUrl = workerUrl.replace(/^http/, 'ws') + '/ws/terminal'; + const ws = new WebSocket(wsUrl, { + headers: { + 'X-Sandbox-Id': currentSandboxId, + }, + }); + + await new Promise((resolve, reject) => { + ws.on('open', () => resolve()); + ws.on('error', (error) => reject(error)); + setTimeout(() => reject(new Error('Connection timeout')), 10000); + }); + + const messages: any[] = []; + ws.on('message', (data) => { + try { + messages.push(JSON.parse(data.toString())); + } catch (e) {} + }); + + // Wait for ready message + await new Promise((resolve) => { + const checkReady = () => { + if (messages.some(m => m.type === 'ready')) { + resolve(); + } else { + setTimeout(checkReady, 100); + } + }; + checkReady(); + }); + + const readyMsg = messages.find(m => m.type === 'ready'); + expect(readyMsg).toBeDefined(); + expect(readyMsg.cwd).toBeDefined(); + + // Execute echo command + ws.send(JSON.stringify({ + type: 'command', + command: 'echo "Hello Terminal"', + })); + + // Wait for result + await new Promise((resolve) => { + const checkResult = () => { + if (messages.some(m => m.type === 'result')) { + resolve(); + } else { + setTimeout(checkResult, 100); + } + }; + checkResult(); + }); + + const resultMsg = messages.find(m => m.type === 'result'); + expect(resultMsg).toBeDefined(); + expect(resultMsg.stdout).toContain('Hello Terminal'); + expect(resultMsg.exitCode).toBe(0); + + ws.close(); + }, 30000); + + test('should handle terminal command errors with non-zero exit code', async () => { + currentSandboxId = createSandboxId(); + const headers = createTestHeaders(currentSandboxId); + + await fetch(`${workerUrl}/api/init`, { + method: 'POST', + headers, + }); + + await new Promise(resolve => setTimeout(resolve, 2000)); + + const wsUrl = workerUrl.replace(/^http/, 'ws') + '/ws/terminal'; + const ws = new WebSocket(wsUrl, { + headers: { + 'X-Sandbox-Id': currentSandboxId, + }, + }); + + await new Promise((resolve, reject) => { + ws.on('open', () => resolve()); + ws.on('error', (error) => reject(error)); + setTimeout(() => reject(new Error('Connection timeout')), 10000); + }); + + const messages: any[] = []; + ws.on('message', (data) => { + try { + messages.push(JSON.parse(data.toString())); + } catch (e) {} + }); + + // Wait for ready + await new Promise((resolve) => { + const checkReady = () => { + if (messages.some(m => m.type === 'ready')) resolve(); + else setTimeout(checkReady, 100); + }; + checkReady(); + }); + + // Execute command that fails + ws.send(JSON.stringify({ + type: 'command', + command: 'ls /nonexistent-directory', + })); + + // Wait for result + await new Promise((resolve) => { + const checkResult = () => { + if (messages.some(m => m.type === 'result')) resolve(); + else setTimeout(checkResult, 100); + }; + checkResult(); + }); + + const resultMsg = messages.find(m => m.type === 'result'); + expect(resultMsg).toBeDefined(); + expect(resultMsg.stderr).toContain('No such file or directory'); + expect(resultMsg.exitCode).not.toBe(0); + + ws.close(); + }, 30000); + + test('should reuse running servers across multiple connections', async () => { + currentSandboxId = createSandboxId(); + const headers = createTestHeaders(currentSandboxId); + + // Initialize servers once + await fetch(`${workerUrl}/api/init`, { + method: 'POST', + headers, + }); + + await new Promise(resolve => setTimeout(resolve, 2000)); + + // Get initial process list + const initialProcesses = await fetch(`${workerUrl}/api/process/list`, { + method: 'GET', + headers, + }).then(r => r.json()); + + const echoProcess = initialProcesses.find((p: any) => p.id === 'ws-echo-8080'); + expect(echoProcess).toBeDefined(); + + // Connect, disconnect, reconnect multiple times + for (let i = 0; i < 3; i++) { + const wsUrl = workerUrl.replace(/^http/, 'ws') + '/ws/echo'; + const ws = new WebSocket(wsUrl, { + headers: { + 'X-Sandbox-Id': currentSandboxId, + }, + }); + + await new Promise((resolve, reject) => { + ws.on('open', () => resolve()); + ws.on('error', (error) => reject(error)); + setTimeout(() => reject(new Error('Connection timeout')), 10000); + }); + + // Send a message + const messagePromise = new Promise((resolve) => { + ws.on('message', (data) => resolve(data.toString())); + }); + + ws.send(`Test ${i}`); + const echo = await messagePromise; + expect(echo).toBe(`Test ${i}`); + + // Close + ws.close(); + await new Promise((resolve) => { + ws.on('close', () => resolve()); + setTimeout(() => resolve(), 500); + }); + + // Small delay between connections + await new Promise(resolve => setTimeout(resolve, 100)); + } + + // Verify same process is still running (not restarted) + const finalProcesses = await fetch(`${workerUrl}/api/process/list`, { + method: 'GET', + headers, + }).then(r => r.json()); + + const finalEchoProcess = finalProcesses.find((p: any) => p.id === 'ws-echo-8080'); + expect(finalEchoProcess).toBeDefined(); + expect(finalEchoProcess.status).toBe('running'); + + // Process ID should be the same (server wasn't restarted) + expect(finalEchoProcess.id).toBe(echoProcess.id); + }, 60000); + + test('should handle multiple concurrent WebSocket connections', async () => { + currentSandboxId = createSandboxId(); + const headers = createTestHeaders(currentSandboxId); + + await fetch(`${workerUrl}/api/init`, { + method: 'POST', + headers, + }); + + await new Promise(resolve => setTimeout(resolve, 2000)); + + // Open 3 concurrent connections to different servers + const wsUrl1 = workerUrl.replace(/^http/, 'ws') + '/ws/echo'; + const wsUrl2 = workerUrl.replace(/^http/, 'ws') + '/ws/code'; + const wsUrl3 = workerUrl.replace(/^http/, 'ws') + '/ws/terminal'; + + const ws1 = new WebSocket(wsUrl1, { headers: { 'X-Sandbox-Id': currentSandboxId } }); + const ws2 = new WebSocket(wsUrl2, { headers: { 'X-Sandbox-Id': currentSandboxId } }); + const ws3 = new WebSocket(wsUrl3, { headers: { 'X-Sandbox-Id': currentSandboxId } }); + + // Wait for all connections + await Promise.all([ + new Promise((resolve, reject) => { + ws1.on('open', () => resolve()); + ws1.on('error', reject); + setTimeout(() => reject(new Error('WS1 timeout')), 10000); + }), + new Promise((resolve, reject) => { + ws2.on('open', () => resolve()); + ws2.on('error', reject); + setTimeout(() => reject(new Error('WS2 timeout')), 10000); + }), + new Promise((resolve, reject) => { + ws3.on('open', () => resolve()); + ws3.on('error', reject); + setTimeout(() => reject(new Error('WS3 timeout')), 10000); + }), + ]); + + // Send messages on all connections simultaneously + const results = await Promise.all([ + new Promise((resolve) => { + ws1.on('message', (data) => resolve(data.toString())); + ws1.send('Echo test'); + }), + new Promise((resolve) => { + const messages: any[] = []; + ws2.on('message', (data) => { + try { + const msg = JSON.parse(data.toString()); + messages.push(msg); + if (msg.type === 'completed') resolve(messages); + } catch (e) {} + }); + ws2.send(JSON.stringify({ type: 'execute', code: 'print("Code test")' })); + }), + new Promise((resolve) => { + const messages: any[] = []; + ws3.on('message', (data) => { + try { + const msg = JSON.parse(data.toString()); + messages.push(msg); + if (msg.type === 'result') resolve(messages); + } catch (e) {} + }); + // Wait for ready first + setTimeout(() => { + ws3.send(JSON.stringify({ type: 'command', command: 'echo "Terminal test"' })); + }, 500); + }), + ]); + + // Verify all worked independently + expect(results[0]).toBe('Echo test'); + expect(results[1].some((m: any) => m.type === 'stdout')).toBe(true); + expect(results[2].some((m: any) => m.type === 'result')).toBe(true); + + // Close all + ws1.close(); + ws2.close(); + ws3.close(); + }, 60000); +}); From e7db45752c1f5bd687cb6e3119da0ab1e04e4784 Mon Sep 17 00:00:00 2001 From: katereznykova Date: Tue, 28 Oct 2025 19:35:28 +0000 Subject: [PATCH 09/16] minor nits and fixes --- examples/websocket/src/index.ts | 38 ++++++++++++++--------- tests/e2e/test-worker/index.ts | 23 +++++++++----- tests/e2e/websocket-connect.test.ts | 47 ++++++++++++++--------------- 3 files changed, 61 insertions(+), 47 deletions(-) diff --git a/examples/websocket/src/index.ts b/examples/websocket/src/index.ts index 78d8b4f3..f0ff6fc8 100644 --- a/examples/websocket/src/index.ts +++ b/examples/websocket/src/index.ts @@ -67,7 +67,7 @@ async function handleInitServers(request: Request, env: Env): Promise const serversToStart = []; // Echo server (port 8080) - if (!runningServers.has('echo-server-8080')) { + if (!runningServers.has('ws-echo-8080')) { const echoScript = ` const port = 8080; Bun.serve({ @@ -87,13 +87,13 @@ console.log('Echo server listening on port ' + port); await sandbox.writeFile('/tmp/echo-server.ts', echoScript); serversToStart.push( sandbox.startProcess('bun run /tmp/echo-server.ts', { - processId: 'echo-server-8080' - }).catch(() => {}) + processId: 'ws-echo-8080' + }) ); } // Code server (port 8081) - if (!runningServers.has('code-server-8081')) { + if (!runningServers.has('ws-code-8081')) { const codeScript = ` const port = 8081; Bun.serve({ @@ -153,13 +153,13 @@ console.log('Code streaming server listening on port ' + port); await sandbox.writeFile('/tmp/code-server.ts', codeScript); serversToStart.push( sandbox.startProcess('bun run /tmp/code-server.ts', { - processId: 'code-server-8081' - }).catch(() => {}) + processId: 'ws-code-8081' + }) ); } // Terminal server (port 8082) - if (!runningServers.has('terminal-server-8082')) { + if (!runningServers.has('ws-terminal-8082')) { const terminalScript = ` const port = 8082; Bun.serve({ @@ -197,20 +197,28 @@ console.log('Terminal server listening on port ' + port); await sandbox.writeFile('/tmp/terminal-server.ts', terminalScript); serversToStart.push( sandbox.startProcess('bun run /tmp/terminal-server.ts', { - processId: 'terminal-server-8082' - }).catch(() => {}) + processId: 'ws-terminal-8082' + }) ); } - // Start all servers (fire and forget) - await Promise.all(serversToStart); + // Start all servers and track results + const results = await Promise.allSettled(serversToStart); + const failedCount = results.filter(r => r.status === "rejected").length; + const succeededCount = results.filter(r => r.status === "fulfilled").length; return new Response(JSON.stringify({ - success: true, - message: 'Servers initialized', - serversStarted: serversToStart.length + success: failedCount === 0, + message: failedCount === 0 ? 'All servers initialized' : `${failedCount} server(s) failed to start`, + serversStarted: succeededCount, + serversFailed: failedCount, + errors: failedCount > 0 ? results + .filter(r => r.status === "rejected") + .map(r => (r as PromiseRejectedResult).reason?.message || String((r as PromiseRejectedResult).reason)) + : undefined }), { - headers: { 'Content-Type': 'application/json' } + headers: { 'Content-Type': 'application/json' }, + status: failedCount > 0 ? 500 : 200 }); } catch (error: any) { return new Response(JSON.stringify({ diff --git a/tests/e2e/test-worker/index.ts b/tests/e2e/test-worker/index.ts index 9f9a1570..e025c267 100644 --- a/tests/e2e/test-worker/index.ts +++ b/tests/e2e/test-worker/index.ts @@ -72,7 +72,7 @@ console.log('Echo server on port ' + port); `; await sandbox.writeFile('/tmp/ws-echo.ts', echoScript); serversToStart.push( - sandbox.startProcess('bun run /tmp/ws-echo.ts', { processId: 'ws-echo-8080' }).catch(() => {}) + sandbox.startProcess('bun run /tmp/ws-echo.ts', { processId: 'ws-echo-8080' }) ); } @@ -133,7 +133,7 @@ console.log('Code server on port ' + port); `; await sandbox.writeFile('/tmp/ws-code.ts', codeScript); serversToStart.push( - sandbox.startProcess('bun run /tmp/ws-code.ts', { processId: 'ws-code-8081' }).catch(() => {}) + sandbox.startProcess('bun run /tmp/ws-code.ts', { processId: 'ws-code-8081' }) ); } @@ -170,17 +170,26 @@ console.log('Terminal server on port ' + port); `; await sandbox.writeFile('/tmp/ws-terminal.ts', terminalScript); serversToStart.push( - sandbox.startProcess('bun run /tmp/ws-terminal.ts', { processId: 'ws-terminal-8082' }).catch(() => {}) + sandbox.startProcess('bun run /tmp/ws-terminal.ts', { processId: 'ws-terminal-8082' }) ); } - await Promise.all(serversToStart); + // Start all servers and track results + const results = await Promise.allSettled(serversToStart); + const failedCount = results.filter(r => r.status === "rejected").length; + const succeededCount = results.filter(r => r.status === "fulfilled").length; return new Response(JSON.stringify({ - success: true, - serversStarted: serversToStart.length + success: failedCount === 0, + serversStarted: succeededCount, + serversFailed: failedCount, + errors: failedCount > 0 ? results + .filter(r => r.status === "rejected") + .map(r => (r as PromiseRejectedResult).reason?.message || String((r as PromiseRejectedResult).reason)) + : undefined }), { - headers: { 'Content-Type': 'application/json' } + headers: { 'Content-Type': 'application/json' }, + status: failedCount > 0 ? 500 : 200 }); } diff --git a/tests/e2e/websocket-connect.test.ts b/tests/e2e/websocket-connect.test.ts index 01492906..ac34406c 100644 --- a/tests/e2e/websocket-connect.test.ts +++ b/tests/e2e/websocket-connect.test.ts @@ -56,9 +56,7 @@ describe('WebSocket connect() Pattern', () => { expect(data.success).toBe(true); expect(data.serversStarted).toBeGreaterThanOrEqual(0); // May be 0 if already running - - // Wait for servers to be ready - await new Promise(resolve => setTimeout(resolve, 2000)); + expect(data.serversFailed).toBe(0); // No failures // Verify all three server processes exist const processesResponse = await fetch(`${workerUrl}/api/process/list`, { @@ -84,13 +82,12 @@ describe('WebSocket connect() Pattern', () => { const headers = createTestHeaders(currentSandboxId); // Initialize servers - await fetch(`${workerUrl}/api/init`, { + const initResponse = await fetch(`${workerUrl}/api/init`, { method: 'POST', headers, }); - - // Wait for servers to be ready - await new Promise(resolve => setTimeout(resolve, 2000)); + const initData = await initResponse.json(); + expect(initData.success).toBe(true); // Connect via WebSocket using connect() pattern (no port exposure API) const wsUrl = workerUrl.replace(/^http/, 'ws') + '/ws/echo'; @@ -132,12 +129,12 @@ describe('WebSocket connect() Pattern', () => { const headers = createTestHeaders(currentSandboxId); // Initialize servers - await fetch(`${workerUrl}/api/init`, { + const initResponse = await fetch(`${workerUrl}/api/init`, { method: 'POST', headers, }); - - await new Promise(resolve => setTimeout(resolve, 2000)); + const initData = await initResponse.json(); + expect(initData.success).toBe(true); // Connect to code streaming server const wsUrl = workerUrl.replace(/^http/, 'ws') + '/ws/code'; @@ -218,12 +215,12 @@ print('Done!') currentSandboxId = createSandboxId(); const headers = createTestHeaders(currentSandboxId); - await fetch(`${workerUrl}/api/init`, { + const initResponse = await fetch(`${workerUrl}/api/init`, { method: 'POST', headers, }); - - await new Promise(resolve => setTimeout(resolve, 2000)); + const initData = await initResponse.json(); + expect(initData.success).toBe(true); const wsUrl = workerUrl.replace(/^http/, 'ws') + '/ws/code'; const ws = new WebSocket(wsUrl, { @@ -291,12 +288,12 @@ print('This should not print') currentSandboxId = createSandboxId(); const headers = createTestHeaders(currentSandboxId); - await fetch(`${workerUrl}/api/init`, { + const initResponse = await fetch(`${workerUrl}/api/init`, { method: 'POST', headers, }); - - await new Promise(resolve => setTimeout(resolve, 2000)); + const initData = await initResponse.json(); + expect(initData.success).toBe(true); const wsUrl = workerUrl.replace(/^http/, 'ws') + '/ws/terminal'; const ws = new WebSocket(wsUrl, { @@ -364,12 +361,12 @@ print('This should not print') currentSandboxId = createSandboxId(); const headers = createTestHeaders(currentSandboxId); - await fetch(`${workerUrl}/api/init`, { + const initResponse = await fetch(`${workerUrl}/api/init`, { method: 'POST', headers, }); - - await new Promise(resolve => setTimeout(resolve, 2000)); + const initData = await initResponse.json(); + expect(initData.success).toBe(true); const wsUrl = workerUrl.replace(/^http/, 'ws') + '/ws/terminal'; const ws = new WebSocket(wsUrl, { @@ -428,12 +425,12 @@ print('This should not print') const headers = createTestHeaders(currentSandboxId); // Initialize servers once - await fetch(`${workerUrl}/api/init`, { + const initResponse = await fetch(`${workerUrl}/api/init`, { method: 'POST', headers, }); - - await new Promise(resolve => setTimeout(resolve, 2000)); + const initData = await initResponse.json(); + expect(initData.success).toBe(true); // Get initial process list const initialProcesses = await fetch(`${workerUrl}/api/process/list`, { @@ -497,12 +494,12 @@ print('This should not print') currentSandboxId = createSandboxId(); const headers = createTestHeaders(currentSandboxId); - await fetch(`${workerUrl}/api/init`, { + const initResponse = await fetch(`${workerUrl}/api/init`, { method: 'POST', headers, }); - - await new Promise(resolve => setTimeout(resolve, 2000)); + const initData = await initResponse.json(); + expect(initData.success).toBe(true); // Open 3 concurrent connections to different servers const wsUrl1 = workerUrl.replace(/^http/, 'ws') + '/ws/echo'; From 4e2fad55948536c32da6043597b17546d9efd34c Mon Sep 17 00:00:00 2001 From: katereznykova Date: Tue, 28 Oct 2025 19:45:18 +0000 Subject: [PATCH 10/16] add unit tests --- .changeset/loud-nights-sneeze.md | 4 +- examples/websocket/Dockerfile | 4 +- packages/sandbox/src/sandbox.ts | 15 +- packages/sandbox/tests/connect.test.ts | 310 +++++++++++++++++++++++++ tests/e2e/websocket-connect.test.ts | 4 +- 5 files changed, 330 insertions(+), 7 deletions(-) create mode 100644 packages/sandbox/tests/connect.test.ts diff --git a/.changeset/loud-nights-sneeze.md b/.changeset/loud-nights-sneeze.md index 08ee4b3d..59f27b46 100644 --- a/.changeset/loud-nights-sneeze.md +++ b/.changeset/loud-nights-sneeze.md @@ -1,5 +1,5 @@ --- -"@cloudflare/sandbox": minor +"@cloudflare/sandbox": patch --- -add websockets support via connect() method +Add WebSocket support via connect() method for routing client WebSocket connections directly to container services diff --git a/examples/websocket/Dockerfile b/examples/websocket/Dockerfile index 89e76e33..5bec3a6b 100644 --- a/examples/websocket/Dockerfile +++ b/examples/websocket/Dockerfile @@ -1,8 +1,8 @@ # This image is unique to this repo, and you'll never need it. # Whenever you're integrating with sandbox SDK in your own project, # you should use the official image instead: -FROM docker.io/cloudflare/sandbox:0.4.10 -# FROM cloudflare/sandbox-test:0.4.10 +# FROM docker.io/cloudflare/sandbox:0.4.10 +FROM cloudflare/sandbox-test:0.4.10 # On a mac, you might need to actively pick up the # arm64 build of the image. diff --git a/packages/sandbox/src/sandbox.ts b/packages/sandbox/src/sandbox.ts index d9fe29da..a81b21e9 100644 --- a/packages/sandbox/src/sandbox.ts +++ b/packages/sandbox/src/sandbox.ts @@ -262,7 +262,20 @@ export class Sandbox extends Container implements ISandbox { if (isWebSocket) { // WebSocket path: Let parent Container class handle WebSocket proxying // This bypasses containerFetch() which uses JSRPC and cannot handle WebSocket upgrades - return await super.fetch(request); + try { + requestLogger.debug('WebSocket upgrade requested', { + path: url.pathname, + port: this.determinePort(url) + }); + return await super.fetch(request); + } catch (error) { + requestLogger.error( + 'WebSocket connection failed', + error instanceof Error ? error : new Error(String(error)), + { path: url.pathname } + ); + throw error; + } } // Non-WebSocket: Use existing port determination and HTTP routing logic diff --git a/packages/sandbox/tests/connect.test.ts b/packages/sandbox/tests/connect.test.ts new file mode 100644 index 00000000..8df32fd7 --- /dev/null +++ b/packages/sandbox/tests/connect.test.ts @@ -0,0 +1,310 @@ +import type { DurableObjectState } from '@cloudflare/workers-types'; +import { beforeEach, describe, expect, it, vi } from 'vitest'; +import { connect, Sandbox } from '../src/sandbox'; + +// Mock @cloudflare/containers before importing +vi.mock('@cloudflare/containers', () => { + const mockSwitchPort = vi.fn((request: Request, port: number) => { + // Create a new request with the port in the URL path + const url = new URL(request.url); + url.pathname = `/proxy/${port}${url.pathname}`; + return new Request(url, request); + }); + + const MockContainer = class Container { + ctx: any; + env: any; + constructor(ctx: any, env: any) { + this.ctx = ctx; + this.env = env; + } + async fetch(request: Request): Promise { + // Mock WebSocket upgrade response + // Note: In Workers runtime, WebSocket upgrades don't return status 101 + // Instead, the runtime handles the upgrade internally + const upgradeHeader = request.headers.get('Upgrade'); + if (upgradeHeader?.toLowerCase() === 'websocket') { + return new Response('WebSocket Upgraded', { + status: 200, + headers: { + 'X-WebSocket-Upgraded': 'true', + 'Upgrade': 'websocket', + 'Connection': 'Upgrade', + }, + }); + } + return new Response('Mock fetch'); + } + }; + + return { + Container: MockContainer, + getContainer: vi.fn(), + switchPort: mockSwitchPort, + }; +}); + +describe('connect() - WebSocket Routing', () => { + let sandbox: Sandbox; + let mockCtx: Partial; + let mockEnv: any; + + beforeEach(async () => { + vi.clearAllMocks(); + + // Mock DurableObjectState + mockCtx = { + storage: { + get: vi.fn().mockResolvedValue(null), + put: vi.fn().mockResolvedValue(undefined), + delete: vi.fn().mockResolvedValue(undefined), + list: vi.fn().mockResolvedValue(new Map()), + } as any, + blockConcurrencyWhile: vi.fn((fn: () => Promise) => fn()), + id: { + toString: () => 'test-sandbox-id', + equals: vi.fn(), + name: 'test-sandbox', + } as any, + }; + + mockEnv = {}; + + // Create Sandbox instance + sandbox = new Sandbox(mockCtx as DurableObjectState, mockEnv); + + // Wait for initialization + await vi.waitFor(() => { + expect(mockCtx.blockConcurrencyWhile).toHaveBeenCalled(); + }); + }); + + describe('basic functionality', () => { + it('should route WebSocket request to specified port', async () => { + // Create a WebSocket upgrade request + const request = new Request('http://localhost/ws/echo', { + headers: { + 'Upgrade': 'websocket', + 'Connection': 'Upgrade', + 'Sec-WebSocket-Version': '13', + 'Sec-WebSocket-Key': 'dGhlIHNhbXBsZSBub25jZQ==', + }, + }); + + // Spy on sandbox.fetch to verify it's called + const fetchSpy = vi.spyOn(sandbox, 'fetch'); + + // Call connect() + const response = await connect(sandbox, request, 8080); + + // Verify sandbox.fetch was called + expect(fetchSpy).toHaveBeenCalledOnce(); + + // Verify response indicates WebSocket upgrade + expect(response.status).toBe(200); + expect(response.headers.get('X-WebSocket-Upgraded')).toBe('true'); + expect(response.headers.get('Upgrade')).toBe('websocket'); + }); + + it('should pass port number through switchPort', async () => { + const request = new Request('http://localhost/ws/terminal', { + headers: { + 'Upgrade': 'websocket', + 'Connection': 'Upgrade', + }, + }); + + const { switchPort } = await import('@cloudflare/containers'); + const switchPortMock = vi.mocked(switchPort); + + await connect(sandbox, request, 8082); + + // Verify switchPort was called with correct port + expect(switchPortMock).toHaveBeenCalledWith(request, 8082); + }); + + it('should preserve request headers when routing', async () => { + const request = new Request('http://localhost/ws/code', { + headers: { + 'Upgrade': 'websocket', + 'Connection': 'Upgrade', + 'X-Sandbox-Id': 'test-sandbox-123', + 'X-Custom-Header': 'custom-value', + }, + }); + + const fetchSpy = vi.spyOn(sandbox, 'fetch'); + + await connect(sandbox, request, 8081); + + // Get the request that was passed to fetch + const calledRequest = fetchSpy.mock.calls[0][0]; + + // Verify headers are preserved + expect(calledRequest.headers.get('Upgrade')).toBe('websocket'); + expect(calledRequest.headers.get('X-Sandbox-Id')).toBe('test-sandbox-123'); + expect(calledRequest.headers.get('X-Custom-Header')).toBe('custom-value'); + }); + }); + + describe('port routing', () => { + it('should route to port 8080 for echo server', async () => { + const request = new Request('http://localhost/ws/echo', { + headers: { 'Upgrade': 'websocket' }, + }); + + const { switchPort } = await import('@cloudflare/containers'); + const switchPortMock = vi.mocked(switchPort); + + await connect(sandbox, request, 8080); + + expect(switchPortMock).toHaveBeenCalledWith(request, 8080); + }); + + it('should route to port 8081 for code server', async () => { + const request = new Request('http://localhost/ws/code', { + headers: { 'Upgrade': 'websocket' }, + }); + + const { switchPort } = await import('@cloudflare/containers'); + const switchPortMock = vi.mocked(switchPort); + + await connect(sandbox, request, 8081); + + expect(switchPortMock).toHaveBeenCalledWith(request, 8081); + }); + + it('should route to port 8082 for terminal server', async () => { + const request = new Request('http://localhost/ws/terminal', { + headers: { 'Upgrade': 'websocket' }, + }); + + const { switchPort } = await import('@cloudflare/containers'); + const switchPortMock = vi.mocked(switchPort); + + await connect(sandbox, request, 8082); + + expect(switchPortMock).toHaveBeenCalledWith(request, 8082); + }); + + it('should support custom ports', async () => { + const request = new Request('http://localhost/ws/custom', { + headers: { 'Upgrade': 'websocket' }, + }); + + const { switchPort } = await import('@cloudflare/containers'); + const switchPortMock = vi.mocked(switchPort); + + await connect(sandbox, request, 9000); + + expect(switchPortMock).toHaveBeenCalledWith(request, 9000); + }); + }); + + describe('error handling', () => { + it('should propagate errors from sandbox.fetch', async () => { + const request = new Request('http://localhost/ws/error', { + headers: { 'Upgrade': 'websocket' }, + }); + + // Mock fetch to throw an error + vi.spyOn(sandbox, 'fetch').mockRejectedValueOnce( + new Error('Container connection failed') + ); + + await expect(connect(sandbox, request, 8080)).rejects.toThrow( + 'Container connection failed' + ); + }); + }); + + describe('WebSocket upgrade scenarios', () => { + it('should handle standard WebSocket headers', async () => { + const request = new Request('http://localhost/ws/test', { + headers: { + 'Upgrade': 'websocket', + 'Connection': 'Upgrade', + 'Sec-WebSocket-Version': '13', + 'Sec-WebSocket-Key': 'dGhlIHNhbXBsZSBub25jZQ==', + 'Sec-WebSocket-Protocol': 'chat', + }, + }); + + const response = await connect(sandbox, request, 8080); + + expect(response.status).toBe(200); + expect(response.headers.get('X-WebSocket-Upgraded')).toBe('true'); + }); + + it('should handle WebSocket with query parameters', async () => { + const request = new Request('http://localhost/ws/test?token=abc123&room=lobby', { + headers: { 'Upgrade': 'websocket' }, + }); + + const fetchSpy = vi.spyOn(sandbox, 'fetch'); + + await connect(sandbox, request, 8080); + + const calledRequest = fetchSpy.mock.calls[0][0]; + const url = new URL(calledRequest.url); + + // Verify query parameters are preserved + expect(url.searchParams.get('token')).toBe('abc123'); + expect(url.searchParams.get('room')).toBe('lobby'); + }); + + it('should handle WebSocket with path segments', async () => { + const request = new Request('http://localhost/ws/rooms/123/chat', { + headers: { 'Upgrade': 'websocket' }, + }); + + const fetchSpy = vi.spyOn(sandbox, 'fetch'); + + await connect(sandbox, request, 8080); + + const calledRequest = fetchSpy.mock.calls[0][0]; + const url = new URL(calledRequest.url); + + // Verify path is preserved in proxied request + expect(url.pathname).toContain('rooms/123/chat'); + }); + + it('should handle case-insensitive Upgrade header', async () => { + const request = new Request('http://localhost/ws/test', { + headers: { + 'Upgrade': 'WebSocket', // Mixed case + 'Connection': 'upgrade', + }, + }); + + const response = await connect(sandbox, request, 8080); + + // Should still work with non-lowercase Upgrade header + expect(response.status).toBe(200); + expect(response.headers.get('X-WebSocket-Upgraded')).toBe('true'); + }); + }); + + describe('integration with Sandbox', () => { + it('should work with getSandbox helper', async () => { + // This tests the typical usage pattern + const { getSandbox } = await import('../src/sandbox'); + const { getContainer } = await import('@cloudflare/containers'); + + const mockNamespace = {} as any; + const getContainerMock = vi.mocked(getContainer); + getContainerMock.mockReturnValue(sandbox as any); + + const sandboxStub = getSandbox(mockNamespace, 'test-id'); + + const request = new Request('http://localhost/ws/echo', { + headers: { 'Upgrade': 'websocket' }, + }); + + const response = await connect(sandboxStub, request, 8080); + + expect(response.status).toBe(200); + expect(response.headers.get('X-WebSocket-Upgraded')).toBe('true'); + }); + }); +}); diff --git a/tests/e2e/websocket-connect.test.ts b/tests/e2e/websocket-connect.test.ts index ac34406c..2624cc73 100644 --- a/tests/e2e/websocket-connect.test.ts +++ b/tests/e2e/websocket-connect.test.ts @@ -488,7 +488,7 @@ print('This should not print') // Process ID should be the same (server wasn't restarted) expect(finalEchoProcess.id).toBe(echoProcess.id); - }, 60000); + }, 30000); test('should handle multiple concurrent WebSocket connections', async () => { currentSandboxId = createSandboxId(); @@ -571,5 +571,5 @@ print('This should not print') ws1.close(); ws2.close(); ws3.close(); - }, 60000); + }, 30000); }); From 63e97ca794d413c7f985643bcc7da28bde097a23 Mon Sep 17 00:00:00 2001 From: katereznykova Date: Tue, 28 Oct 2025 19:56:21 +0000 Subject: [PATCH 11/16] add more tests --- examples/websocket/README.md | 4 ++ packages/sandbox/src/sandbox.ts | 19 ++++++-- packages/sandbox/tests/connect.test.ts | 66 ++++++++++++++++++++++---- packages/sandbox/tests/sandbox.test.ts | 2 + 4 files changed, 77 insertions(+), 14 deletions(-) diff --git a/examples/websocket/README.md b/examples/websocket/README.md index bd94d5ce..7dc91688 100644 --- a/examples/websocket/README.md +++ b/examples/websocket/README.md @@ -395,6 +395,10 @@ Implement rate limiting in your container server: const rateLimits = new Map(); websocket: { + open(ws) { + // Assign unique ID to track client + ws.data = { id: crypto.randomUUID() }; + }, message(ws, message) { const clientId = ws.data.id; const now = Date.now(); diff --git a/packages/sandbox/src/sandbox.ts b/packages/sandbox/src/sandbox.ts index a81b21e9..ee34404d 100644 --- a/packages/sandbox/src/sandbox.ts +++ b/packages/sandbox/src/sandbox.ts @@ -54,17 +54,25 @@ export function getSandbox( /** * Connect an incoming WebSocket request to a specific port inside the container. - * + * * @param sandbox - The sandbox instance (stub) to connect to * @param request - The incoming WebSocket upgrade request from the client - * @param port - The port number to connect to inside the container + * @param port - The port number to connect to inside the container (1024-65535) * @returns Promise - The WebSocket upgrade response + * @throws {SecurityError} - If port is invalid or in restricted range */ export async function connect( sandbox: Sandbox, request: Request, port: number ): Promise { + // Validate port before routing + if (!validatePort(port)) { + throw new SecurityError( + `Invalid or restricted port: ${port}. Ports must be in range 1024-65535 and not reserved.` + ); + } + const portSwitchedRequest = switchPort(request, port); return await sandbox.fetch(portSwitchedRequest); } @@ -255,9 +263,12 @@ export class Sandbox extends Container implements ISandbox { await this.ctx.storage.put('sandboxName', name); } - // Detect WebSocket upgrade request + // Detect WebSocket upgrade request (RFC 6455 compliant) const upgradeHeader = request.headers.get('Upgrade'); - const isWebSocket = upgradeHeader?.toLowerCase() === 'websocket'; + const connectionHeader = request.headers.get('Connection'); + const isWebSocket = + upgradeHeader?.toLowerCase() === 'websocket' && + connectionHeader?.toLowerCase().includes('upgrade'); if (isWebSocket) { // WebSocket path: Let parent Container class handle WebSocket proxying diff --git a/packages/sandbox/tests/connect.test.ts b/packages/sandbox/tests/connect.test.ts index 8df32fd7..1b36ba3c 100644 --- a/packages/sandbox/tests/connect.test.ts +++ b/packages/sandbox/tests/connect.test.ts @@ -60,7 +60,7 @@ describe('connect() - WebSocket Routing', () => { delete: vi.fn().mockResolvedValue(undefined), list: vi.fn().mockResolvedValue(new Map()), } as any, - blockConcurrencyWhile: vi.fn((fn: () => Promise) => fn()), + blockConcurrencyWhile: vi.fn((fn: () => Promise) => fn()), id: { toString: () => 'test-sandbox-id', equals: vi.fn(), @@ -81,7 +81,7 @@ describe('connect() - WebSocket Routing', () => { describe('basic functionality', () => { it('should route WebSocket request to specified port', async () => { - // Create a WebSocket upgrade request + // Create a WebSocket upgrade request (RFC 6455 compliant) const request = new Request('http://localhost/ws/echo', { headers: { 'Upgrade': 'websocket', @@ -150,7 +150,7 @@ describe('connect() - WebSocket Routing', () => { describe('port routing', () => { it('should route to port 8080 for echo server', async () => { const request = new Request('http://localhost/ws/echo', { - headers: { 'Upgrade': 'websocket' }, + headers: { 'Upgrade': 'websocket', 'Connection': 'Upgrade' }, }); const { switchPort } = await import('@cloudflare/containers'); @@ -163,7 +163,7 @@ describe('connect() - WebSocket Routing', () => { it('should route to port 8081 for code server', async () => { const request = new Request('http://localhost/ws/code', { - headers: { 'Upgrade': 'websocket' }, + headers: { 'Upgrade': 'websocket', 'Connection': 'Upgrade' }, }); const { switchPort } = await import('@cloudflare/containers'); @@ -176,7 +176,7 @@ describe('connect() - WebSocket Routing', () => { it('should route to port 8082 for terminal server', async () => { const request = new Request('http://localhost/ws/terminal', { - headers: { 'Upgrade': 'websocket' }, + headers: { 'Upgrade': 'websocket', 'Connection': 'Upgrade' }, }); const { switchPort } = await import('@cloudflare/containers'); @@ -189,7 +189,7 @@ describe('connect() - WebSocket Routing', () => { it('should support custom ports', async () => { const request = new Request('http://localhost/ws/custom', { - headers: { 'Upgrade': 'websocket' }, + headers: { 'Upgrade': 'websocket', 'Connection': 'Upgrade' }, }); const { switchPort } = await import('@cloudflare/containers'); @@ -204,7 +204,7 @@ describe('connect() - WebSocket Routing', () => { describe('error handling', () => { it('should propagate errors from sandbox.fetch', async () => { const request = new Request('http://localhost/ws/error', { - headers: { 'Upgrade': 'websocket' }, + headers: { 'Upgrade': 'websocket', 'Connection': 'Upgrade' }, }); // Mock fetch to throw an error @@ -216,6 +216,52 @@ describe('connect() - WebSocket Routing', () => { 'Container connection failed' ); }); + + it('should reject invalid port numbers', async () => { + const request = new Request('http://localhost/ws/test', { + headers: { 'Upgrade': 'websocket', 'Connection': 'Upgrade' }, + }); + + // Test with negative port + await expect(connect(sandbox, request, -1)).rejects.toThrow('Invalid or restricted port'); + + // Test with port 0 + await expect(connect(sandbox, request, 0)).rejects.toThrow('Invalid or restricted port'); + + // Test with port > 65535 + await expect(connect(sandbox, request, 70000)).rejects.toThrow('Invalid or restricted port'); + }); + + it('should reject privileged ports (< 1024)', async () => { + const request = new Request('http://localhost/ws/test', { + headers: { 'Upgrade': 'websocket', 'Connection': 'Upgrade' }, + }); + + // Test with port 80 (privileged) + await expect(connect(sandbox, request, 80)).rejects.toThrow('Invalid or restricted port'); + + // Test with port 443 (privileged) + await expect(connect(sandbox, request, 443)).rejects.toThrow('Invalid or restricted port'); + + // Test with port 22 (privileged) + await expect(connect(sandbox, request, 22)).rejects.toThrow('Invalid or restricted port'); + }); + + it('should allow valid user ports (1024-65535)', async () => { + const request = new Request('http://localhost/ws/test', { + headers: { 'Upgrade': 'websocket', 'Connection': 'Upgrade' }, + }); + + // Test boundary: port 1024 (first valid user port) + await expect(connect(sandbox, request, 1024)).resolves.toBeDefined(); + + // Test boundary: port 65535 (last valid port) + await expect(connect(sandbox, request, 65535)).resolves.toBeDefined(); + + // Test common ports + await expect(connect(sandbox, request, 8080)).resolves.toBeDefined(); + await expect(connect(sandbox, request, 3001)).resolves.toBeDefined(); + }); }); describe('WebSocket upgrade scenarios', () => { @@ -238,7 +284,7 @@ describe('connect() - WebSocket Routing', () => { it('should handle WebSocket with query parameters', async () => { const request = new Request('http://localhost/ws/test?token=abc123&room=lobby', { - headers: { 'Upgrade': 'websocket' }, + headers: { 'Upgrade': 'websocket', 'Connection': 'Upgrade' }, }); const fetchSpy = vi.spyOn(sandbox, 'fetch'); @@ -255,7 +301,7 @@ describe('connect() - WebSocket Routing', () => { it('should handle WebSocket with path segments', async () => { const request = new Request('http://localhost/ws/rooms/123/chat', { - headers: { 'Upgrade': 'websocket' }, + headers: { 'Upgrade': 'websocket', 'Connection': 'Upgrade' }, }); const fetchSpy = vi.spyOn(sandbox, 'fetch'); @@ -298,7 +344,7 @@ describe('connect() - WebSocket Routing', () => { const sandboxStub = getSandbox(mockNamespace, 'test-id'); const request = new Request('http://localhost/ws/echo', { - headers: { 'Upgrade': 'websocket' }, + headers: { 'Upgrade': 'websocket', 'Connection': 'Upgrade' }, }); const response = await connect(sandboxStub, request, 8080); diff --git a/packages/sandbox/tests/sandbox.test.ts b/packages/sandbox/tests/sandbox.test.ts index c6881cb0..31ab6e48 100644 --- a/packages/sandbox/tests/sandbox.test.ts +++ b/packages/sandbox/tests/sandbox.test.ts @@ -537,6 +537,7 @@ describe('Sandbox - Automatic Session Management', () => { const request = new Request('https://example.com/ws', { headers: { 'Upgrade': 'websocket', + 'Connection': 'Upgrade', 'Sec-WebSocket-Key': 'test-key-123', 'Sec-WebSocket-Version': '13', }, @@ -547,6 +548,7 @@ describe('Sandbox - Automatic Session Management', () => { expect(superFetchSpy).toHaveBeenCalledTimes(1); const passedRequest = superFetchSpy.mock.calls[0][0] as Request; expect(passedRequest.headers.get('Upgrade')).toBe('websocket'); + expect(passedRequest.headers.get('Connection')).toBe('Upgrade'); expect(passedRequest.headers.get('Sec-WebSocket-Key')).toBe('test-key-123'); expect(passedRequest.headers.get('Sec-WebSocket-Version')).toBe('13'); }); From 036b8f5c352114a57f08317359a8191eba994f94 Mon Sep 17 00:00:00 2001 From: Naresh Date: Wed, 29 Oct 2025 11:53:09 +0000 Subject: [PATCH 12/16] Move basic example to tests/integration The examples/basic directory was primarily used for integration testing rather than as a standalone example. This moves it to tests/integration to reflect its actual purpose. Merged WebSocket example functionality into tests/integration since it shared the same testing infrastructure. Simplified WebSocket E2E tests by removing redundant test coverage and focusing on core transport-level functionality. --- .github/changeset-version.ts | 7 + CLAUDE.md | 2 +- examples/claude-code/package.json | 2 +- examples/minimal/package.json | 2 +- examples/websocket/.gitignore | 7 - examples/websocket/Dockerfile | 15 - examples/websocket/README.md | 467 -- examples/websocket/package-lock.json | 1589 ----- examples/websocket/package.json | 22 - examples/websocket/src/index.ts | 659 -- examples/websocket/tsconfig.json | 18 - examples/websocket/wrangler.jsonc | 36 - package-lock.json | 6311 +++++++---------- package.json | 3 +- packages/sandbox/README.md | 1 - packages/sandbox/src/sandbox.ts | 18 +- packages/sandbox/tests/connect.test.ts | 356 - packages/sandbox/tests/sandbox.test.ts | 87 +- tests/e2e/test-worker/index.ts | 2 +- tests/e2e/websocket-connect.test.ts | 499 +- .../basic => tests/integration}/.gitignore | 0 .../basic => tests/integration}/Dockerfile | 0 .../basic => tests/integration}/README.md | 0 .../app/components/LaTeXRenderer.tsx | 0 .../app/components/MarkdownRenderer.tsx | 0 .../basic => tests/integration}/app/index.tsx | 223 +- .../basic => tests/integration}/app/style.css | 210 + .../basic => tests/integration}/index.html | 0 .../basic => tests/integration}/package.json | 4 +- .../integration}/public/favicon.ico | Bin .../integration}/shared/examples.ts | 0 .../src/endpoints/createTestBinary.ts | 0 .../integration}/src/endpoints/execute.ts | 0 .../src/endpoints/executeStream.ts | 0 .../integration}/src/endpoints/fileDelete.ts | 0 .../integration}/src/endpoints/fileList.ts | 0 .../integration}/src/endpoints/fileMove.ts | 0 .../integration}/src/endpoints/fileRead.ts | 0 .../src/endpoints/fileReadStream.ts | 0 .../integration}/src/endpoints/fileRename.ts | 0 .../integration}/src/endpoints/gitCheckout.ts | 0 .../integration}/src/endpoints/index.ts | 1 + .../integration}/src/endpoints/mkdir.ts | 0 .../integration}/src/endpoints/notebook.ts | 0 .../integration}/src/endpoints/ports.ts | 0 .../integration}/src/endpoints/processGet.ts | 0 .../integration}/src/endpoints/processKill.ts | 0 .../integration}/src/endpoints/processList.ts | 0 .../integration}/src/endpoints/processLogs.ts | 0 .../src/endpoints/processStart.ts | 0 .../integration}/src/endpoints/templates.ts | 0 .../src/endpoints/websocketInit.ts | 77 + .../basic => tests/integration}/src/http.ts | 0 .../basic => tests/integration}/src/index.ts | 21 +- .../basic => tests/integration}/tsconfig.json | 0 .../integration}/vite.config.ts | 0 .../integration}/wrangler.jsonc | 0 57 files changed, 3216 insertions(+), 7423 deletions(-) delete mode 100644 examples/websocket/.gitignore delete mode 100644 examples/websocket/Dockerfile delete mode 100644 examples/websocket/README.md delete mode 100644 examples/websocket/package-lock.json delete mode 100644 examples/websocket/package.json delete mode 100644 examples/websocket/src/index.ts delete mode 100644 examples/websocket/tsconfig.json delete mode 100644 examples/websocket/wrangler.jsonc delete mode 100644 packages/sandbox/tests/connect.test.ts rename {examples/basic => tests/integration}/.gitignore (100%) rename {examples/basic => tests/integration}/Dockerfile (100%) rename {examples/basic => tests/integration}/README.md (100%) rename {examples/basic => tests/integration}/app/components/LaTeXRenderer.tsx (100%) rename {examples/basic => tests/integration}/app/components/MarkdownRenderer.tsx (100%) rename {examples/basic => tests/integration}/app/index.tsx (94%) rename {examples/basic => tests/integration}/app/style.css (93%) rename {examples/basic => tests/integration}/index.html (100%) rename {examples/basic => tests/integration}/package.json (80%) rename {examples/basic => tests/integration}/public/favicon.ico (100%) rename {examples/basic => tests/integration}/shared/examples.ts (100%) rename {examples/basic => tests/integration}/src/endpoints/createTestBinary.ts (100%) rename {examples/basic => tests/integration}/src/endpoints/execute.ts (100%) rename {examples/basic => tests/integration}/src/endpoints/executeStream.ts (100%) rename {examples/basic => tests/integration}/src/endpoints/fileDelete.ts (100%) rename {examples/basic => tests/integration}/src/endpoints/fileList.ts (100%) rename {examples/basic => tests/integration}/src/endpoints/fileMove.ts (100%) rename {examples/basic => tests/integration}/src/endpoints/fileRead.ts (100%) rename {examples/basic => tests/integration}/src/endpoints/fileReadStream.ts (100%) rename {examples/basic => tests/integration}/src/endpoints/fileRename.ts (100%) rename {examples/basic => tests/integration}/src/endpoints/gitCheckout.ts (100%) rename {examples/basic => tests/integration}/src/endpoints/index.ts (93%) rename {examples/basic => tests/integration}/src/endpoints/mkdir.ts (100%) rename {examples/basic => tests/integration}/src/endpoints/notebook.ts (100%) rename {examples/basic => tests/integration}/src/endpoints/ports.ts (100%) rename {examples/basic => tests/integration}/src/endpoints/processGet.ts (100%) rename {examples/basic => tests/integration}/src/endpoints/processKill.ts (100%) rename {examples/basic => tests/integration}/src/endpoints/processList.ts (100%) rename {examples/basic => tests/integration}/src/endpoints/processLogs.ts (100%) rename {examples/basic => tests/integration}/src/endpoints/processStart.ts (100%) rename {examples/basic => tests/integration}/src/endpoints/templates.ts (100%) create mode 100644 tests/integration/src/endpoints/websocketInit.ts rename {examples/basic => tests/integration}/src/http.ts (100%) rename {examples/basic => tests/integration}/src/index.ts (92%) rename {examples/basic => tests/integration}/tsconfig.json (100%) rename {examples/basic => tests/integration}/vite.config.ts (100%) rename {examples/basic => tests/integration}/wrangler.jsonc (100%) diff --git a/.github/changeset-version.ts b/.github/changeset-version.ts index ff5737a3..ceaf9f3a 100644 --- a/.github/changeset-version.ts +++ b/.github/changeset-version.ts @@ -61,6 +61,12 @@ try { replacement: `cloudflare/sandbox-test:${newVersion}`, description: "Test Docker image reference", }, + // Example package.json dependencies + { + pattern: /"@cloudflare\/sandbox":\s*"\^[\d.]+"/g, + replacement: `"@cloudflare/sandbox": "^${newVersion}"`, + description: "Example package.json @cloudflare/sandbox dependencies", + }, ]; // Files to search and update @@ -73,6 +79,7 @@ try { "**/*.json", // JSON configs (but not package.json/package-lock.json) "**/*.yaml", // YAML configs "**/*.yml", // YML configs + "examples/**/package.json", // Example package.json files (exception to ignore rule below) ]; // Ignore patterns diff --git a/CLAUDE.md b/CLAUDE.md index 4344aa10..5f4ee531 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -96,7 +96,7 @@ npm run docker:rebuild # Rebuild container image locally (includes clean bui - Stable images when "Version Packages" PR is merged - Multi-arch builds (amd64, arm64) handled by CI -**Critical:** Docker image version MUST match npm package version (`@cloudflare/sandbox@0.4.7` → `cloudflare/sandbox:0.4.12`). This is enforced via `ARG SANDBOX_VERSION` in Dockerfile. +**Critical:** Docker image version MUST match npm package version (`@cloudflare/sandbox@0.4.12` → `cloudflare/sandbox:0.4.12`). This is enforced via `ARG SANDBOX_VERSION` in Dockerfile. ### Development Server diff --git a/examples/claude-code/package.json b/examples/claude-code/package.json index 7c8ed5ff..57f9e758 100644 --- a/examples/claude-code/package.json +++ b/examples/claude-code/package.json @@ -11,7 +11,7 @@ "types": "wrangler types" }, "devDependencies": { - "@cloudflare/sandbox": "^0.4.3", + "@cloudflare/sandbox": "^0.4.12", "@types/node": "^24.9.1", "typescript": "^5.8.3", "wrangler": "^4.44.0" diff --git a/examples/minimal/package.json b/examples/minimal/package.json index 0ae4b0c4..b9864a5a 100644 --- a/examples/minimal/package.json +++ b/examples/minimal/package.json @@ -11,7 +11,7 @@ "cf-typegen": "wrangler types" }, "devDependencies": { - "@cloudflare/sandbox": "^0.4.3", + "@cloudflare/sandbox": "^0.4.12", "@types/node": "^24.1.0", "typescript": "^5.8.3", "wrangler": "^4.41.0" diff --git a/examples/websocket/.gitignore b/examples/websocket/.gitignore deleted file mode 100644 index dd7799e6..00000000 --- a/examples/websocket/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -node_modules/ -dist/ -.wrangler/ -.dev.vars -.env -*.log -.DS_Store diff --git a/examples/websocket/Dockerfile b/examples/websocket/Dockerfile deleted file mode 100644 index 5bec3a6b..00000000 --- a/examples/websocket/Dockerfile +++ /dev/null @@ -1,15 +0,0 @@ -# This image is unique to this repo, and you'll never need it. -# Whenever you're integrating with sandbox SDK in your own project, -# you should use the official image instead: -# FROM docker.io/cloudflare/sandbox:0.4.10 -FROM cloudflare/sandbox-test:0.4.10 - -# On a mac, you might need to actively pick up the -# arm64 build of the image. -# FROM --platform=linux/arm64 cloudflare/sandbox-test:0.4.10 - -# Expose the ports for WebSocket examples -EXPOSE 8080 -EXPOSE 8081 -EXPOSE 8082 - diff --git a/examples/websocket/README.md b/examples/websocket/README.md deleted file mode 100644 index 7dc91688..00000000 --- a/examples/websocket/README.md +++ /dev/null @@ -1,467 +0,0 @@ -# WebSocket Examples for Sandbox SDK - -This example demonstrates how to use WebSockets with the Cloudflare Sandbox SDK by routing client connections to WebSocket servers running inside containers. - -## Architecture - -The WebSocket integration uses `connect(sandbox, request, port)` to route incoming WebSocket requests directly to WebSocket servers running inside the sandbox container: - -``` -Client ←WebSocket→ [Worker routes via connect()] → Container WebSocket Server -``` - -The pattern: -1. Start a WebSocket server inside the container (e.g., using Bun, Node.js, Python) -2. Use `connect(sandbox, request, port)` to route the incoming WebSocket upgrade request -3. Client communicates directly with the container's WebSocket server - -## Setup - -```bash -# Install dependencies -npm install - -# Run locally -npm run dev - -# Deploy to Cloudflare -npm run deploy -``` - -## Usage - -### Local Development - -1. Start the development server: - ```bash - npm run dev - ``` - -2. Open your browser to `http://localhost:8787` - -### WebSocket Endpoints - -#### `/ws/echo` -Simple echo server that sends back any message it receives. - -**Client Example:** -```javascript -const ws = new WebSocket('ws://localhost:8787/ws/echo?id=my-session'); - -ws.onmessage = (event) => { - console.log('Received:', event.data); -}; - -ws.send('Hello!'); -// Receives: "Hello!" -``` - -#### `/ws/broadcast` -Broadcasts messages to all connected clients (great for chat applications). - -**Client Example:** -```javascript -const ws = new WebSocket('ws://localhost:8787/ws/broadcast?id=shared-room'); - -ws.onmessage = (event) => { - const data = JSON.parse(event.data); - - if (data.type === 'join') { - console.log(`User ${data.id} joined, ${data.count} online`); - } else if (data.type === 'message') { - console.log(`${data.from}: ${data.text}`); - } -}; - -ws.send('Hello everyone!'); -``` - -#### `/ws/json` -JSON RPC server that handles structured commands. - -**Client Example:** -```javascript -const ws = new WebSocket('ws://localhost:8787/ws/json?id=my-session'); - -// Send ping -ws.send(JSON.stringify({ type: 'ping' })); - -// Execute command in container -ws.send(JSON.stringify({ - type: 'exec', - id: Date.now(), - command: 'ls -la' -})); - -// Get system info -ws.send(JSON.stringify({ - type: 'info', - id: Date.now() -})); -``` - -## Implementation Pattern - -Here's the basic pattern for creating a WebSocket endpoint: - -```typescript -import { connect, getSandbox, Sandbox } from "@cloudflare/sandbox"; - -async function handleWebSocket(request: Request, env: Env): Promise { - const sandboxId = "my-sandbox"; - const sandbox = getSandbox(env.Sandbox, sandboxId); - const port = 8080; - - // 1. Create WebSocket server script (using Bun) - const serverScript = ` -const port = ${port}; - -Bun.serve({ - port, - fetch(req, server) { - if (server.upgrade(req)) { - return; - } - return new Response('Expected WebSocket', { status: 400 }); - }, - websocket: { - message(ws, message) { - // Handle incoming messages - ws.send('Echo: ' + message); - }, - open(ws) { - console.log('Client connected'); - }, - close(ws) { - console.log('Client disconnected'); - }, - }, -}); - -console.log(\`WebSocket server listening on port \${port}\`); -`; - - // 2. Write server script to container - await sandbox.writeFile('/tmp/ws-server.ts', serverScript); - - // 3. Start the server as a background process - try { - await sandbox.startProcess(\`bun run /tmp/ws-server.ts\`, { - processId: \`ws-server-\${port}\` - }); - } catch (error: any) { - // Server might already be running - if (!error.message?.includes('already exists')) { - throw error; - } - } - - // 4. Give server time to start - await new Promise(resolve => setTimeout(resolve, 1000)); - - // 5. Route WebSocket to container server - return await connect(sandbox, request, port); -} -``` - -## Use Cases - -### 1. Real-Time Communication -Build chat applications, collaborative tools, or live notifications: - -```javascript -// All clients sharing the same sandbox ID see each other's messages -const ws = new WebSocket('wss://your-worker.workers.dev/ws/broadcast?id=room-123'); - -ws.send('Hello from client!'); -// All clients in room-123 receive this message -``` - -### 2. Remote Command Execution -Execute commands in the container with real-time output: - -```javascript -const ws = new WebSocket('wss://your-worker.workers.dev/ws/json'); - -ws.send(JSON.stringify({ - type: 'exec', - command: 'python train.py', - id: Date.now() -})); - -// Receive execution results -ws.onmessage = (event) => { - const result = JSON.parse(event.data); - console.log('stdout:', result.stdout); - console.log('exit code:', result.exitCode); -}; -``` - -### 3. Interactive Services -Host any WebSocket-based service in the container: - -- WebSocket terminals (xterm.js) -- Real-time data feeds -- Game servers -- Streaming APIs -- Custom protocols - -## Server Technologies - -You can run any WebSocket server inside the container: - -### Bun (recommended - already in container) -```typescript -Bun.serve({ - port: 8080, - websocket: { - message(ws, message) { - ws.send(message); - } - } -}); -``` - -### Node.js -```javascript -const WebSocket = require('ws'); -const wss = new WebSocket.Server({ port: 8080 }); - -wss.on('connection', (ws) => { - ws.on('message', (message) => { - ws.send(message); - }); -}); -``` - -### Python -```python -import asyncio -import websockets - -async def echo(websocket): - async for message in websocket: - await websocket.send(message) - -start_server = websockets.serve(echo, "0.0.0.0", 8080) -asyncio.run(start_server) -``` - -## Advanced Patterns - -### Multiple Ports -Run different WebSocket services on different ports: - -```typescript -switch (pathname) { - case "/ws/chat": - return connect(sandbox, request, 8080); // Chat server - case "/ws/terminal": - return connect(sandbox, request, 8081); // Terminal - case "/ws/game": - return connect(sandbox, request, 8082); // Game server -} -``` - -### Shared vs Isolated Sandboxes -```typescript -// Shared sandbox - all clients connect to same server -const sandbox = getSandbox(env.Sandbox, "shared-room"); - -// Isolated sandbox - each user gets their own server -const sandbox = getSandbox(env.Sandbox, userId); -``` - -### Connection Management -```typescript -// Check if server is running before connecting -const processes = await sandbox.listProcesses(); -const serverRunning = processes.some(p => p.id === 'ws-server-8080'); - -if (!serverRunning) { - // Start server - await sandbox.startProcess('bun run /tmp/ws-server.ts', { - processId: 'ws-server-8080' - }); - await new Promise(resolve => setTimeout(resolve, 1000)); -} - -return connect(sandbox, request, 8080); -``` - -## Best Practices - -### 1. Process Management -Use named process IDs to avoid starting duplicate servers: - -```typescript -try { - await sandbox.startProcess('bun run /tmp/server.ts', { - processId: 'ws-server-8080' // Named ID prevents duplicates - }); -} catch (error: any) { - if (!error.message?.includes('already exists')) { - throw error; - } -} -``` - -### 2. Startup Delays -Give servers time to bind to ports before routing connections: - -```typescript -await sandbox.startProcess('bun run /tmp/server.ts'); -await new Promise(resolve => setTimeout(resolve, 1000)); // Wait 1 second -return connect(sandbox, request, port); -``` - -### 3. Error Handling -Handle connection failures gracefully: - -```typescript -try { - return await connect(sandbox, request, port); -} catch (error) { - console.error('Failed to connect:', error); - return new Response('WebSocket server unavailable', { status: 503 }); -} -``` - -### 4. Client Reconnection -Implement reconnection logic in clients: - -```javascript -let reconnectAttempts = 0; -const maxAttempts = 5; - -function connect() { - const ws = new WebSocket(url); - - ws.onclose = () => { - if (reconnectAttempts < maxAttempts) { - reconnectAttempts++; - setTimeout(connect, 1000 * reconnectAttempts); - } - }; - - ws.onopen = () => { - reconnectAttempts = 0; - }; -} -``` - -### 5. Message Validation -Always validate incoming messages in your container server: - -```typescript -websocket: { - message(ws, message) { - try { - const data = JSON.parse(message.toString()); - - if (!data.type || typeof data.type !== 'string') { - ws.send(JSON.stringify({ error: 'Invalid message format' })); - return; - } - - // Handle valid message - } catch (error) { - ws.send(JSON.stringify({ error: 'Invalid JSON' })); - } - } -} -``` - -## Security Considerations - -### Input Validation -Always validate commands and inputs in your container server: - -```typescript -case 'exec': - // Don't trust user input - validate and sanitize - const command = data.command; - if (!isValidCommand(command)) { - return { error: 'Invalid command' }; - } - // Execute safely - break; -``` - -### Rate Limiting -Implement rate limiting in your container server: - -```typescript -const rateLimits = new Map(); - -websocket: { - open(ws) { - // Assign unique ID to track client - ws.data = { id: crypto.randomUUID() }; - }, - message(ws, message) { - const clientId = ws.data.id; - const now = Date.now(); - - const lastMessage = rateLimits.get(clientId) || 0; - if (now - lastMessage < 100) { // Max 10 msg/sec - ws.send(JSON.stringify({ error: 'Rate limit exceeded' })); - return; - } - - rateLimits.set(clientId, now); - // Handle message - } -} -``` - -### Authentication -Add authentication before routing to WebSocket: - -```typescript -async function handleWebSocket(request: Request, env: Env): Promise { - const url = new URL(request.url); - const token = url.searchParams.get('token'); - - if (!await verifyToken(token)) { - return new Response('Unauthorized', { status: 401 }); - } - - // Route to WebSocket - return connect(sandbox, request, port); -} -``` - -## Troubleshooting - -### Connection Refused -- Ensure server is running: check with `sandbox.listProcesses()` -- Verify port is correct -- Wait longer after starting server (increase delay) - -### Messages Not Received -- Check WebSocket upgrade header is present -- Verify message format (text vs binary) -- Ensure server is calling `server.upgrade(req)` in Bun - -### Server Not Starting -- Check for port conflicts (use different ports for each service) -- Verify server script has no syntax errors -- Check container logs for error messages - -## Performance Tips - -1. **Reuse Servers**: Use named process IDs to avoid restarting servers on each connection -2. **Connection Pooling**: Share sandbox instances across multiple clients using the same sandbox ID -3. **Binary Messages**: Use binary frames for large data transfers to reduce overhead -4. **Batch Updates**: Send multiple updates in a single message when possible - -## Further Reading - -- [Cloudflare Workers WebSocket Documentation](https://developers.cloudflare.com/workers/runtime-apis/websockets/) -- [Bun WebSocket API](https://bun.sh/docs/api/websockets) -- [WebSocket RFC 6455](https://datatracker.ietf.org/doc/html/rfc6455) - -## License - -MIT diff --git a/examples/websocket/package-lock.json b/examples/websocket/package-lock.json deleted file mode 100644 index 3c89098a..00000000 --- a/examples/websocket/package-lock.json +++ /dev/null @@ -1,1589 +0,0 @@ -{ - "name": "@cloudflare/sandbox-websocket-example", - "version": "1.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "@cloudflare/sandbox-websocket-example", - "version": "1.0.0", - "license": "MIT", - "dependencies": { - "@cloudflare/sandbox": "*" - }, - "devDependencies": { - "@cloudflare/workers-types": "^4.20250111.0", - "typescript": "^5.3.3", - "wrangler": "^4.43.0" - } - }, - "node_modules/@cloudflare/containers": { - "version": "0.0.28", - "resolved": "https://registry.npmjs.org/@cloudflare/containers/-/containers-0.0.28.tgz", - "integrity": "sha512-wzR9UWcGvZ9znd4elkXklilPcHX6srncsjSkx696SZRZyTygNbWsLlHegvc1C+e9gn28HRZU3dLiAzXiC9IY1w==", - "license": "ISC" - }, - "node_modules/@cloudflare/kv-asset-handler": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.4.0.tgz", - "integrity": "sha512-+tv3z+SPp+gqTIcImN9o0hqE9xyfQjI1XD9pL6NuKjua9B1y7mNYv0S9cP+QEbA4ppVgGZEmKOvHX5G5Ei1CVA==", - "dev": true, - "license": "MIT OR Apache-2.0", - "dependencies": { - "mime": "^3.0.0" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@cloudflare/sandbox": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/@cloudflare/sandbox/-/sandbox-0.4.3.tgz", - "integrity": "sha512-ODynUVKLID9viGLDDnFpWXNToy4vvN2WCQliJiWvtgBee8K1WiRDI3SYzUHFt3onV8kBHKjkoCbADQHOPBAllA==", - "license": "ISC", - "dependencies": { - "@cloudflare/containers": "^0.0.28" - } - }, - "node_modules/@cloudflare/unenv-preset": { - "version": "2.7.7", - "resolved": "https://registry.npmjs.org/@cloudflare/unenv-preset/-/unenv-preset-2.7.7.tgz", - "integrity": "sha512-HtZuh166y0Olbj9bqqySckz0Rw9uHjggJeoGbDx5x+sgezBXlxO6tQSig2RZw5tgObF8mWI8zaPvQMkQZtAODw==", - "dev": true, - "license": "MIT OR Apache-2.0", - "peerDependencies": { - "unenv": "2.0.0-rc.21", - "workerd": "^1.20250927.0" - }, - "peerDependenciesMeta": { - "workerd": { - "optional": true - } - } - }, - "node_modules/@cloudflare/workerd-darwin-64": { - "version": "1.20251008.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20251008.0.tgz", - "integrity": "sha512-yph0H+8mMOK5Z9oDwjb8rI96oTVt4no5lZ43aorcbzsWG9VUIaXSXlBBoB3von6p4YCRW+J3n36fBM9XZ6TLaA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=16" - } - }, - "node_modules/@cloudflare/workerd-darwin-arm64": { - "version": "1.20251008.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20251008.0.tgz", - "integrity": "sha512-Yc4lMGSbM4AEtYRpyDpmk77MsHb6X2BSwJgMgGsLVPmckM7ZHivZkJChfcNQjZ/MGR6nkhYc4iF6TcVS+UMEVw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=16" - } - }, - "node_modules/@cloudflare/workerd-linux-64": { - "version": "1.20251008.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20251008.0.tgz", - "integrity": "sha512-AjoQnylw4/5G6SmfhZRsli7EuIK7ZMhmbxtU0jkpciTlVV8H01OsFOgS1d8zaTXMfkWamEfMouy8oH/L7B9YcQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=16" - } - }, - "node_modules/@cloudflare/workerd-linux-arm64": { - "version": "1.20251008.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20251008.0.tgz", - "integrity": "sha512-hRy9yyvzVq1HsqHZUmFkAr0C8JGjAD/PeeVEGCKL3jln3M9sNCKIrbDXiL+efe+EwajJNNlDxpO+s30uVWVaRg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=16" - } - }, - "node_modules/@cloudflare/workerd-windows-64": { - "version": "1.20251008.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20251008.0.tgz", - "integrity": "sha512-Gm0RR+ehfNMsScn2pUcn3N9PDUpy7FyvV9ecHEyclKttvztyFOcmsF14bxEaSVv7iM4TxWEBn1rclmYHxDM4ow==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=16" - } - }, - "node_modules/@cloudflare/workers-types": { - "version": "4.20251011.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workers-types/-/workers-types-4.20251011.0.tgz", - "integrity": "sha512-gQpih+pbq3sP4uXltUeCSbPgZxTNp2gQd8639SaIbQMwgA6oJNHLhIART1fWy6DQACngiRzDVULA2x0ohmkGTQ==", - "dev": true, - "license": "MIT OR Apache-2.0" - }, - "node_modules/@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/trace-mapping": "0.3.9" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@emnapi/runtime": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.5.0.tgz", - "integrity": "sha512-97/BJ3iXHww3djw6hYIfErCZFee7qCtrneuLa20UXFCOTCfBM2cvQHjWJ2EG0s0MtdNwInarqCTz35i4wWXHsQ==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.4.tgz", - "integrity": "sha512-1VCICWypeQKhVbE9oW/sJaAmjLxhVqacdkvPLEjwlttjfwENRSClS8EjBz0KzRyFSCPDIkuXW34Je/vk7zdB7Q==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.4.tgz", - "integrity": "sha512-QNdQEps7DfFwE3hXiU4BZeOV68HHzYwGd0Nthhd3uCkkEKK7/R6MTgM0P7H7FAs5pU/DIWsviMmEGxEoxIZ+ZQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.4.tgz", - "integrity": "sha512-bBy69pgfhMGtCnwpC/x5QhfxAz/cBgQ9enbtwjf6V9lnPI/hMyT9iWpR1arm0l3kttTr4L0KSLpKmLp/ilKS9A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.4.tgz", - "integrity": "sha512-TVhdVtQIFuVpIIR282btcGC2oGQoSfZfmBdTip2anCaVYcqWlZXGcdcKIUklfX2wj0JklNYgz39OBqh2cqXvcQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.4.tgz", - "integrity": "sha512-Y1giCfM4nlHDWEfSckMzeWNdQS31BQGs9/rouw6Ub91tkK79aIMTH3q9xHvzH8d0wDru5Ci0kWB8b3up/nl16g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.4.tgz", - "integrity": "sha512-CJsry8ZGM5VFVeyUYB3cdKpd/H69PYez4eJh1W/t38vzutdjEjtP7hB6eLKBoOdxcAlCtEYHzQ/PJ/oU9I4u0A==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.4.tgz", - "integrity": "sha512-yYq+39NlTRzU2XmoPW4l5Ifpl9fqSk0nAJYM/V/WUGPEFfek1epLHJIkTQM6bBs1swApjO5nWgvr843g6TjxuQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.4.tgz", - "integrity": "sha512-0FgvOJ6UUMflsHSPLzdfDnnBBVoCDtBTVyn/MrWloUNvq/5SFmh13l3dvgRPkDihRxb77Y17MbqbCAa2strMQQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.4.tgz", - "integrity": "sha512-kro4c0P85GMfFYqW4TWOpvmF8rFShbWGnrLqlzp4X1TNWjRY3JMYUfDCtOxPKOIY8B0WC8HN51hGP4I4hz4AaQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.4.tgz", - "integrity": "sha512-+89UsQTfXdmjIvZS6nUnOOLoXnkUTB9hR5QAeLrQdzOSWZvNSAXAtcRDHWtqAUtAmv7ZM1WPOOeSxDzzzMogiQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.4.tgz", - "integrity": "sha512-yTEjoapy8UP3rv8dB0ip3AfMpRbyhSN3+hY8mo/i4QXFeDxmiYbEKp3ZRjBKcOP862Ua4b1PDfwlvbuwY7hIGQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.4.tgz", - "integrity": "sha512-NeqqYkrcGzFwi6CGRGNMOjWGGSYOpqwCjS9fvaUlX5s3zwOtn1qwg1s2iE2svBe4Q/YOG1q6875lcAoQK/F4VA==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.4.tgz", - "integrity": "sha512-IcvTlF9dtLrfL/M8WgNI/qJYBENP3ekgsHbYUIzEzq5XJzzVEV/fXY9WFPfEEXmu3ck2qJP8LG/p3Q8f7Zc2Xg==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.4.tgz", - "integrity": "sha512-HOy0aLTJTVtoTeGZh4HSXaO6M95qu4k5lJcH4gxv56iaycfz1S8GO/5Jh6X4Y1YiI0h7cRyLi+HixMR+88swag==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.4.tgz", - "integrity": "sha512-i8JUDAufpz9jOzo4yIShCTcXzS07vEgWzyX3NH2G7LEFVgrLEhjwL3ajFE4fZI3I4ZgiM7JH3GQ7ReObROvSUA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.4.tgz", - "integrity": "sha512-jFnu+6UbLlzIjPQpWCNh5QtrcNfMLjgIavnwPQAfoGx4q17ocOU9MsQ2QVvFxwQoWpZT8DvTLooTvmOQXkO51g==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.4.tgz", - "integrity": "sha512-6e0cvXwzOnVWJHq+mskP8DNSrKBr1bULBvnFLpc1KY+d+irZSgZ02TGse5FsafKS5jg2e4pbvK6TPXaF/A6+CA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.4.tgz", - "integrity": "sha512-vUnkBYxZW4hL/ie91hSqaSNjulOnYXE1VSLusnvHg2u3jewJBz3YzB9+oCw8DABeVqZGg94t9tyZFoHma8gWZQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.4.tgz", - "integrity": "sha512-XAg8pIQn5CzhOB8odIcAm42QsOfa98SBeKUdo4xa8OvX8LbMZqEtgeWE9P/Wxt7MlG2QqvjGths+nq48TrUiKw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.4.tgz", - "integrity": "sha512-Ct2WcFEANlFDtp1nVAXSNBPDxyU+j7+tId//iHXU2f/lN5AmO4zLyhDcpR5Cz1r08mVxzt3Jpyt4PmXQ1O6+7A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.4.tgz", - "integrity": "sha512-xAGGhyOQ9Otm1Xu8NT1ifGLnA6M3sJxZ6ixylb+vIUVzvvd6GOALpwQrYrtlPouMqd/vSbgehz6HaVk4+7Afhw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.4.tgz", - "integrity": "sha512-Mw+tzy4pp6wZEK0+Lwr76pWLjrtjmJyUB23tHKqEDP74R3q95luY/bXqXZeYl4NYlvwOqoRKlInQialgCKy67Q==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.4.tgz", - "integrity": "sha512-AVUP428VQTSddguz9dO9ngb+E5aScyg7nOeJDrF1HPYu555gmza3bDGMPhmVXL8svDSoqPCsCPjb265yG/kLKQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.4.tgz", - "integrity": "sha512-i1sW+1i+oWvQzSgfRcxxG2k4I9n3O9NRqy8U+uugaT2Dy7kLO9Y7wI72haOahxceMX8hZAzgGou1FhndRldxRg==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.4.tgz", - "integrity": "sha512-nOT2vZNw6hJ+z43oP1SPea/G/6AbN6X+bGNhNuq8NtRHy4wsMhw765IKLNmnjek7GvjWBYQ8Q5VBoYTFg9y1UQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@img/sharp-darwin-arm64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz", - "integrity": "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-darwin-arm64": "1.0.4" - } - }, - "node_modules/@img/sharp-darwin-x64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.5.tgz", - "integrity": "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-darwin-x64": "1.0.4" - } - }, - "node_modules/@img/sharp-libvips-darwin-arm64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.4.tgz", - "integrity": "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "darwin" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-darwin-x64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.4.tgz", - "integrity": "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "darwin" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-arm": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz", - "integrity": "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-arm64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz", - "integrity": "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-s390x": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.4.tgz", - "integrity": "sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-x64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz", - "integrity": "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linuxmusl-arm64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.4.tgz", - "integrity": "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linuxmusl-x64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.4.tgz", - "integrity": "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-linux-arm": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz", - "integrity": "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-arm": "1.0.5" - } - }, - "node_modules/@img/sharp-linux-arm64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz", - "integrity": "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-arm64": "1.0.4" - } - }, - "node_modules/@img/sharp-linux-s390x": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.5.tgz", - "integrity": "sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-s390x": "1.0.4" - } - }, - "node_modules/@img/sharp-linux-x64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz", - "integrity": "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-x64": "1.0.4" - } - }, - "node_modules/@img/sharp-linuxmusl-arm64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.5.tgz", - "integrity": "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-arm64": "1.0.4" - } - }, - "node_modules/@img/sharp-linuxmusl-x64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.5.tgz", - "integrity": "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-x64": "1.0.4" - } - }, - "node_modules/@img/sharp-wasm32": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.33.5.tgz", - "integrity": "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==", - "cpu": [ - "wasm32" - ], - "dev": true, - "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", - "optional": true, - "dependencies": { - "@emnapi/runtime": "^1.2.0" - }, - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-win32-ia32": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.5.tgz", - "integrity": "sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "Apache-2.0 AND LGPL-3.0-or-later", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-win32-x64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz", - "integrity": "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0 AND LGPL-3.0-or-later", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "dev": true, - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, - "node_modules/@poppinss/colors": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/@poppinss/colors/-/colors-4.1.5.tgz", - "integrity": "sha512-FvdDqtcRCtz6hThExcFOgW0cWX+xwSMWcRuQe5ZEb2m7cVQOAVZOIMt+/v9RxGiD9/OY16qJBXK4CVKWAPalBw==", - "dev": true, - "license": "MIT", - "dependencies": { - "kleur": "^4.1.5" - } - }, - "node_modules/@poppinss/dumper": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/@poppinss/dumper/-/dumper-0.6.4.tgz", - "integrity": "sha512-iG0TIdqv8xJ3Lt9O8DrPRxw1MRLjNpoqiSGU03P/wNLP/s0ra0udPJ1J2Tx5M0J3H/cVyEgpbn8xUKRY9j59kQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@poppinss/colors": "^4.1.5", - "@sindresorhus/is": "^7.0.2", - "supports-color": "^10.0.0" - } - }, - "node_modules/@poppinss/exception": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@poppinss/exception/-/exception-1.2.2.tgz", - "integrity": "sha512-m7bpKCD4QMlFCjA/nKTs23fuvoVFoA83brRKmObCUNmi/9tVu8Ve3w4YQAnJu4q3Tjf5fr685HYIC/IA2zHRSg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@sindresorhus/is": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-7.1.0.tgz", - "integrity": "sha512-7F/yz2IphV39hiS2zB4QYVkivrptHHh0K8qJJd9HhuWSdvf8AN7NpebW3CcDZDBQsUPMoDKWsY2WWgW7bqOcfA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sindresorhus/is?sponsor=1" - } - }, - "node_modules/@speed-highlight/core": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@speed-highlight/core/-/core-1.2.7.tgz", - "integrity": "sha512-0dxmVj4gxg3Jg879kvFS/msl4s9F3T9UXC1InxgOf7t5NvcPD97u/WTA5vL/IxWHMn7qSxBozqrnnE2wvl1m8g==", - "dev": true, - "license": "CC0-1.0" - }, - "node_modules/acorn": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", - "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", - "dev": true, - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-walk": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", - "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/blake3-wasm": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/blake3-wasm/-/blake3-wasm-2.1.5.tgz", - "integrity": "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==", - "dev": true, - "license": "MIT" - }, - "node_modules/color": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", - "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1", - "color-string": "^1.9.0" - }, - "engines": { - "node": ">=12.5.0" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "license": "MIT" - }, - "node_modules/color-string": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", - "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "^1.0.0", - "simple-swizzle": "^0.2.2" - } - }, - "node_modules/cookie": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz", - "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/defu": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", - "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", - "dev": true, - "license": "MIT" - }, - "node_modules/detect-libc": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", - "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=8" - } - }, - "node_modules/error-stack-parser-es": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/error-stack-parser-es/-/error-stack-parser-es-1.0.5.tgz", - "integrity": "sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, - "node_modules/esbuild": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.4.tgz", - "integrity": "sha512-8pgjLUcUjcgDg+2Q4NYXnPbo/vncAY4UmyaCm0jZevERqCHZIaWwdJHkf8XQtu4AxSKCdvrUbT0XUr1IdZzI8Q==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.4", - "@esbuild/android-arm": "0.25.4", - "@esbuild/android-arm64": "0.25.4", - "@esbuild/android-x64": "0.25.4", - "@esbuild/darwin-arm64": "0.25.4", - "@esbuild/darwin-x64": "0.25.4", - "@esbuild/freebsd-arm64": "0.25.4", - "@esbuild/freebsd-x64": "0.25.4", - "@esbuild/linux-arm": "0.25.4", - "@esbuild/linux-arm64": "0.25.4", - "@esbuild/linux-ia32": "0.25.4", - "@esbuild/linux-loong64": "0.25.4", - "@esbuild/linux-mips64el": "0.25.4", - "@esbuild/linux-ppc64": "0.25.4", - "@esbuild/linux-riscv64": "0.25.4", - "@esbuild/linux-s390x": "0.25.4", - "@esbuild/linux-x64": "0.25.4", - "@esbuild/netbsd-arm64": "0.25.4", - "@esbuild/netbsd-x64": "0.25.4", - "@esbuild/openbsd-arm64": "0.25.4", - "@esbuild/openbsd-x64": "0.25.4", - "@esbuild/sunos-x64": "0.25.4", - "@esbuild/win32-arm64": "0.25.4", - "@esbuild/win32-ia32": "0.25.4", - "@esbuild/win32-x64": "0.25.4" - } - }, - "node_modules/exit-hook": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-2.2.1.tgz", - "integrity": "sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/exsolve": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.7.tgz", - "integrity": "sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw==", - "dev": true, - "license": "MIT" - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true, - "license": "BSD-2-Clause" - }, - "node_modules/is-arrayish": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.4.tgz", - "integrity": "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA==", - "dev": true, - "license": "MIT" - }, - "node_modules/kleur": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", - "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/mime": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", - "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", - "dev": true, - "license": "MIT", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/miniflare": { - "version": "4.20251008.0", - "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-4.20251008.0.tgz", - "integrity": "sha512-sKCNYNzXG6l8qg0Oo7y8WcDKcpbgw0qwZsxNpdZilFTR4EavRow2TlcwuPSVN99jqAjhz0M4VXvTdSGdtJ2VfQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@cspotcode/source-map-support": "0.8.1", - "acorn": "8.14.0", - "acorn-walk": "8.3.2", - "exit-hook": "2.2.1", - "glob-to-regexp": "0.4.1", - "sharp": "^0.33.5", - "stoppable": "1.1.0", - "undici": "7.14.0", - "workerd": "1.20251008.0", - "ws": "8.18.0", - "youch": "4.1.0-beta.10", - "zod": "3.22.3" - }, - "bin": { - "miniflare": "bootstrap.js" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/ohash": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz", - "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/path-to-regexp": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz", - "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/pathe": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", - "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", - "dev": true, - "license": "MIT" - }, - "node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/sharp": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz", - "integrity": "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==", - "dev": true, - "hasInstallScript": true, - "license": "Apache-2.0", - "dependencies": { - "color": "^4.2.3", - "detect-libc": "^2.0.3", - "semver": "^7.6.3" - }, - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-darwin-arm64": "0.33.5", - "@img/sharp-darwin-x64": "0.33.5", - "@img/sharp-libvips-darwin-arm64": "1.0.4", - "@img/sharp-libvips-darwin-x64": "1.0.4", - "@img/sharp-libvips-linux-arm": "1.0.5", - "@img/sharp-libvips-linux-arm64": "1.0.4", - "@img/sharp-libvips-linux-s390x": "1.0.4", - "@img/sharp-libvips-linux-x64": "1.0.4", - "@img/sharp-libvips-linuxmusl-arm64": "1.0.4", - "@img/sharp-libvips-linuxmusl-x64": "1.0.4", - "@img/sharp-linux-arm": "0.33.5", - "@img/sharp-linux-arm64": "0.33.5", - "@img/sharp-linux-s390x": "0.33.5", - "@img/sharp-linux-x64": "0.33.5", - "@img/sharp-linuxmusl-arm64": "0.33.5", - "@img/sharp-linuxmusl-x64": "0.33.5", - "@img/sharp-wasm32": "0.33.5", - "@img/sharp-win32-ia32": "0.33.5", - "@img/sharp-win32-x64": "0.33.5" - } - }, - "node_modules/simple-swizzle": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.4.tgz", - "integrity": "sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-arrayish": "^0.3.1" - } - }, - "node_modules/stoppable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/stoppable/-/stoppable-1.1.0.tgz", - "integrity": "sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4", - "npm": ">=6" - } - }, - "node_modules/supports-color": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-10.2.2.tgz", - "integrity": "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "dev": true, - "license": "0BSD", - "optional": true - }, - "node_modules/typescript": { - "version": "5.9.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", - "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/ufo": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.1.tgz", - "integrity": "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==", - "dev": true, - "license": "MIT" - }, - "node_modules/undici": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.14.0.tgz", - "integrity": "sha512-Vqs8HTzjpQXZeXdpsfChQTlafcMQaaIwnGwLam1wudSSjlJeQ3bw1j+TLPePgrCnCpUXx7Ba5Pdpf5OBih62NQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=20.18.1" - } - }, - "node_modules/unenv": { - "version": "2.0.0-rc.21", - "resolved": "https://registry.npmjs.org/unenv/-/unenv-2.0.0-rc.21.tgz", - "integrity": "sha512-Wj7/AMtE9MRnAXa6Su3Lk0LNCfqDYgfwVjwRFVum9U7wsto1imuHqk4kTm7Jni+5A0Hn7dttL6O/zjvUvoo+8A==", - "dev": true, - "license": "MIT", - "dependencies": { - "defu": "^6.1.4", - "exsolve": "^1.0.7", - "ohash": "^2.0.11", - "pathe": "^2.0.3", - "ufo": "^1.6.1" - } - }, - "node_modules/workerd": { - "version": "1.20251008.0", - "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20251008.0.tgz", - "integrity": "sha512-HwaJmXO3M1r4S8x2ea2vy8Rw/y/38HRQuK/gNDRQ7w9cJXn6xSl1sIIqKCffULSUjul3wV3I3Nd/GfbmsRReEA==", - "dev": true, - "hasInstallScript": true, - "license": "Apache-2.0", - "bin": { - "workerd": "bin/workerd" - }, - "engines": { - "node": ">=16" - }, - "optionalDependencies": { - "@cloudflare/workerd-darwin-64": "1.20251008.0", - "@cloudflare/workerd-darwin-arm64": "1.20251008.0", - "@cloudflare/workerd-linux-64": "1.20251008.0", - "@cloudflare/workerd-linux-arm64": "1.20251008.0", - "@cloudflare/workerd-windows-64": "1.20251008.0" - } - }, - "node_modules/wrangler": { - "version": "4.43.0", - "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-4.43.0.tgz", - "integrity": "sha512-IBNqXlYHSUSCNNWj/tQN4hFiQy94l7fTxEnJWETXyW69+cjUyjQ7MfeoId3vIV9KBgY8y5M5uf2XulU95OikJg==", - "dev": true, - "license": "MIT OR Apache-2.0", - "dependencies": { - "@cloudflare/kv-asset-handler": "0.4.0", - "@cloudflare/unenv-preset": "2.7.7", - "blake3-wasm": "2.1.5", - "esbuild": "0.25.4", - "miniflare": "4.20251008.0", - "path-to-regexp": "6.3.0", - "unenv": "2.0.0-rc.21", - "workerd": "1.20251008.0" - }, - "bin": { - "wrangler": "bin/wrangler.js", - "wrangler2": "bin/wrangler.js" - }, - "engines": { - "node": ">=18.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - }, - "peerDependencies": { - "@cloudflare/workers-types": "^4.20251008.0" - }, - "peerDependenciesMeta": { - "@cloudflare/workers-types": { - "optional": true - } - } - }, - "node_modules/ws": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", - "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/youch": { - "version": "4.1.0-beta.10", - "resolved": "https://registry.npmjs.org/youch/-/youch-4.1.0-beta.10.tgz", - "integrity": "sha512-rLfVLB4FgQneDr0dv1oddCVZmKjcJ6yX6mS4pU82Mq/Dt9a3cLZQ62pDBL4AUO+uVrCvtWz3ZFUL2HFAFJ/BXQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@poppinss/colors": "^4.1.5", - "@poppinss/dumper": "^0.6.4", - "@speed-highlight/core": "^1.2.7", - "cookie": "^1.0.2", - "youch-core": "^0.3.3" - } - }, - "node_modules/youch-core": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/youch-core/-/youch-core-0.3.3.tgz", - "integrity": "sha512-ho7XuGjLaJ2hWHoK8yFnsUGy2Y5uDpqSTq1FkHLK4/oqKtyUU1AFbOOxY4IpC9f0fTLjwYbslUz0Po5BpD1wrA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@poppinss/exception": "^1.2.2", - "error-stack-parser-es": "^1.0.5" - } - }, - "node_modules/zod": { - "version": "3.22.3", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.3.tgz", - "integrity": "sha512-EjIevzuJRiRPbVH4mGc8nApb/lVLKVpmUhAaR5R5doKGfAnGJ6Gr3CViAVjP+4FWSxCsybeWQdcgCtbX+7oZug==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - } - } -} diff --git a/examples/websocket/package.json b/examples/websocket/package.json deleted file mode 100644 index 75c12cb3..00000000 --- a/examples/websocket/package.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "name": "@cloudflare/sandbox-websocket-example", - "version": "1.0.0", - "type": "module", - "private": true, - "description": "WebSocket example for Cloudflare Sandbox SDK", - "scripts": { - "dev": "wrangler dev", - "deploy": "wrangler deploy", - "build": "tsc --noEmit" - }, - "author": "", - "license": "MIT", - "dependencies": { - "@cloudflare/sandbox": "*" - }, - "devDependencies": { - "@cloudflare/workers-types": "^4.20250111.0", - "typescript": "^5.3.3", - "wrangler": "^4.43.0" - } -} diff --git a/examples/websocket/src/index.ts b/examples/websocket/src/index.ts deleted file mode 100644 index f0ff6fc8..00000000 --- a/examples/websocket/src/index.ts +++ /dev/null @@ -1,659 +0,0 @@ -/** - * WebSocket Example for Cloudflare Sandbox SDK - * - * This example demonstrates how to use connect() to route WebSocket requests - * to WebSocket servers running inside sandbox containers. - */ - -import { connect, getSandbox, Sandbox } from "@cloudflare/sandbox"; - -interface Env { - Sandbox: DurableObjectNamespace; -} - -export default { - async fetch(request: Request, env: Env): Promise { - const url = new URL(request.url); - const pathname = url.pathname; - - // Initialize servers endpoint (called on page load) - if (pathname === "/api/init") { - return handleInitServers(request, env); - } - - // Check for WebSocket upgrade - const upgradeHeader = request.headers.get("Upgrade"); - if (upgradeHeader !== "websocket") { - // Serve a simple HTML page for testing - if (pathname === "/") { - return new Response(getTestHTML(), { - headers: { "Content-Type": "text/html" }, - }); - } - return new Response("Expected WebSocket", { status: 426 }); - } - - // Route to different WebSocket handlers - switch (pathname) { - case "/ws/echo": - return handleEchoWebSocket(request, env); - case "/ws/code": - return handleCodeStreamingWebSocket(request, env); - case "/ws/terminal": - return handleTerminalWebSocket(request, env); - default: - return new Response("Unknown WebSocket endpoint", { status: 404 }); - } - }, -}; - -/** - * Initialize all WebSocket servers on page load - * This ensures servers are ready when users click "Connect" - */ -async function handleInitServers(request: Request, env: Env): Promise { - const sandboxId = new URL(request.url).searchParams.get("id") || "demo-sandbox"; - const sandbox = getSandbox(env.Sandbox, sandboxId); - - try { - // Check which servers are already running - const processes = await sandbox.listProcesses(); - const runningServers = new Set( - processes - .filter(p => p.status === 'running') - .map(p => p.id) - ); - - const serversToStart = []; - - // Echo server (port 8080) - if (!runningServers.has('ws-echo-8080')) { - const echoScript = ` -const port = 8080; -Bun.serve({ - port, - fetch(req, server) { - if (server.upgrade(req)) return; - return new Response('Expected WebSocket', { status: 400 }); - }, - websocket: { - message(ws, message) { ws.send(message); }, - open(ws) { console.log('Client connected'); }, - close(ws) { console.log('Client disconnected'); }, - }, -}); -console.log('Echo server listening on port ' + port); -`; - await sandbox.writeFile('/tmp/echo-server.ts', echoScript); - serversToStart.push( - sandbox.startProcess('bun run /tmp/echo-server.ts', { - processId: 'ws-echo-8080' - }) - ); - } - - // Code server (port 8081) - if (!runningServers.has('ws-code-8081')) { - const codeScript = ` -const port = 8081; -Bun.serve({ - port, - fetch(req, server) { - if (server.upgrade(req)) return; - return new Response('Expected WebSocket', { status: 400 }); - }, - websocket: { - async message(ws, message) { - try { - const data = JSON.parse(message.toString()); - if (data.type === 'execute') { - const { code } = data; - ws.send(JSON.stringify({ type: 'executing', timestamp: Date.now() })); - const filename = '/tmp/code_' + Date.now() + '.py'; - await Bun.write(filename, code); - const proc = Bun.spawn(['python3', filename], { stdout: 'pipe', stderr: 'pipe' }); - const reader = proc.stdout.getReader(); - const textDecoder = new TextDecoder(); - (async () => { - try { - while (true) { - const { done, value } = await reader.read(); - if (done) break; - const text = textDecoder.decode(value, { stream: true }); - if (text) ws.send(JSON.stringify({ type: 'stdout', data: text, timestamp: Date.now() })); - } - } catch (e) {} - })(); - const stderrReader = proc.stderr.getReader(); - (async () => { - try { - while (true) { - const { done, value } = await stderrReader.read(); - if (done) break; - const text = textDecoder.decode(value, { stream: true }); - if (text) ws.send(JSON.stringify({ type: 'stderr', data: text, timestamp: Date.now() })); - } - } catch (e) {} - })(); - const exitCode = await proc.exited; - ws.send(JSON.stringify({ type: 'completed', exitCode, timestamp: Date.now() })); - try { await Bun.spawn(['rm', '-f', filename]).exited; } catch (e) {} - } - } catch (error) { - ws.send(JSON.stringify({ type: 'error', message: error.message || String(error), timestamp: Date.now() })); - } - }, - open(ws) { - ws.send(JSON.stringify({ type: 'ready', message: 'Python code execution server ready', timestamp: Date.now() })); - }, - }, -}); -console.log('Code streaming server listening on port ' + port); -`; - await sandbox.writeFile('/tmp/code-server.ts', codeScript); - serversToStart.push( - sandbox.startProcess('bun run /tmp/code-server.ts', { - processId: 'ws-code-8081' - }) - ); - } - - // Terminal server (port 8082) - if (!runningServers.has('ws-terminal-8082')) { - const terminalScript = ` -const port = 8082; -Bun.serve({ - port, - fetch(req, server) { - if (server.upgrade(req)) return; - return new Response('Expected WebSocket', { status: 400 }); - }, - websocket: { - async message(ws, message) { - try { - const data = JSON.parse(message.toString()); - if (data.type === 'command') { - const { command } = data; - ws.send(JSON.stringify({ type: 'executing', command, timestamp: Date.now() })); - const proc = Bun.spawn(['sh', '-c', command], { stdout: 'pipe', stderr: 'pipe' }); - const stdout = await new Response(proc.stdout).text(); - const stderr = await new Response(proc.stderr).text(); - const exitCode = await proc.exited; - ws.send(JSON.stringify({ type: 'result', stdout, stderr, exitCode, timestamp: Date.now() })); - } else if (data.type === 'ping') { - ws.send(JSON.stringify({ type: 'pong', timestamp: Date.now() })); - } - } catch (error) { - ws.send(JSON.stringify({ type: 'error', message: error.message || String(error), timestamp: Date.now() })); - } - }, - open(ws) { - ws.send(JSON.stringify({ type: 'ready', message: 'Terminal server ready', cwd: process.cwd(), timestamp: Date.now() })); - }, - }, -}); -console.log('Terminal server listening on port ' + port); -`; - await sandbox.writeFile('/tmp/terminal-server.ts', terminalScript); - serversToStart.push( - sandbox.startProcess('bun run /tmp/terminal-server.ts', { - processId: 'ws-terminal-8082' - }) - ); - } - - // Start all servers and track results - const results = await Promise.allSettled(serversToStart); - const failedCount = results.filter(r => r.status === "rejected").length; - const succeededCount = results.filter(r => r.status === "fulfilled").length; - - return new Response(JSON.stringify({ - success: failedCount === 0, - message: failedCount === 0 ? 'All servers initialized' : `${failedCount} server(s) failed to start`, - serversStarted: succeededCount, - serversFailed: failedCount, - errors: failedCount > 0 ? results - .filter(r => r.status === "rejected") - .map(r => (r as PromiseRejectedResult).reason?.message || String((r as PromiseRejectedResult).reason)) - : undefined - }), { - headers: { 'Content-Type': 'application/json' }, - status: failedCount > 0 ? 500 : 200 - }); - } catch (error: any) { - return new Response(JSON.stringify({ - success: false, - error: error.message - }), { - status: 500, - headers: { 'Content-Type': 'application/json' } - }); - } -} - -/** - * Example 1: Basic Echo Server - * Echoes back any message received - */ -async function handleEchoWebSocket( - request: Request, - env: Env -): Promise { - const sandboxId = new URL(request.url).searchParams.get("id") || "demo-sandbox"; - const sandbox = getSandbox(env.Sandbox, sandboxId); - - // Server is pre-initialized on page load, just connect - return await connect(sandbox, request, 8080); -} - -/** - * Example 2: Code Streaming Server - * Executes code and streams output in real-time - */ -async function handleCodeStreamingWebSocket( - request: Request, - env: Env -): Promise { - const sandboxId = new URL(request.url).searchParams.get("id") || "demo-sandbox"; - const sandbox = getSandbox(env.Sandbox, sandboxId); - - // Server is pre-initialized on page load, just connect - return await connect(sandbox, request, 8081); -} - -/** - * Example 3: Interactive Terminal - * Provides terminal-like command execution - */ -async function handleTerminalWebSocket( - request: Request, - env: Env -): Promise { - const sandboxId = new URL(request.url).searchParams.get("id") || "demo-sandbox"; - const sandbox = getSandbox(env.Sandbox, sandboxId); - - // Server is pre-initialized on page load, just connect - return await connect(sandbox, request, 8082); -} - -/** - * Simple HTML test page for WebSocket examples - */ -function getTestHTML(): string { - return ` - - - Sandbox WebSocket Examples - - - -

Sandbox SDK WebSocket Examples

- -
-

WebSocket with connect()

-

- All examples use connect(sandbox, request, port) to route incoming - WebSocket requests to WebSocket servers running inside the container. -

-

- Initializing servers... -

-
- -
-

1. Echo Server

-

- Simple echo - sends back any message you send to it -

-
Disconnected
- - - - - -
-
- -
-

2. Python Code Streaming

-

- Execute Python code with real-time streaming output -

-
Disconnected
- - - - - -
-
- -
-

3. Interactive Terminal

-

- Run shell commands and see results -

-
Disconnected
- - - - - -
-
- - - -`; -} - -export { Sandbox }; diff --git a/examples/websocket/tsconfig.json b/examples/websocket/tsconfig.json deleted file mode 100644 index 1747331b..00000000 --- a/examples/websocket/tsconfig.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "compilerOptions": { - "target": "esnext", - "lib": ["esnext"], - "module": "esnext", - "moduleResolution": "bundler", - "types": ["@cloudflare/workers-types"], - "esModuleInterop": true, - "forceConsistentCasingInFileNames": true, - "strict": true, - "skipLibCheck": true, - "noEmit": true, - "resolveJsonModule": true, - "isolatedModules": true - }, - "include": ["src/**/*.ts"], - "exclude": ["node_modules"] -} diff --git a/examples/websocket/wrangler.jsonc b/examples/websocket/wrangler.jsonc deleted file mode 100644 index ffa1a010..00000000 --- a/examples/websocket/wrangler.jsonc +++ /dev/null @@ -1,36 +0,0 @@ -{ - "$schema": "../../node_modules/wrangler/config-schema.json", - "name": "sandbox-websocket-example", - "main": "src/index.ts", - "compatibility_date": "2025-05-06", - "compatibility_flags": ["nodejs_compat"], - "observability": { - "enabled": true - }, - - "containers": [ - { - "class_name": "Sandbox", - "image": "./Dockerfile", - "name": "sandbox", - "max_instances": 10, - "instance_type": "standard-2" - } - ], - - "durable_objects": { - "bindings": [ - { - "class_name": "Sandbox", - "name": "Sandbox" - } - ] - }, - - "migrations": [ - { - "new_sqlite_classes": ["Sandbox"], - "tag": "v1" - } - ] -} diff --git a/package-lock.json b/package-lock.json index 597cb49e..c8667f24 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,8 +11,7 @@ "workspaces": [ "packages/*", "tooling/*", - "examples/basic", - "examples/code-interpreter" + "tests/integration" ], "devDependencies": { "@biomejs/biome": "^2.1.2", @@ -46,6 +45,7 @@ "examples/basic": { "name": "@cloudflare/sandbox-example", "version": "1.0.0", + "extraneous": true, "license": "MIT", "dependencies": { "@cloudflare/sandbox": "*", @@ -58,2647 +58,2124 @@ "@types/react-katex": "^3.0.4" } }, - "examples/basic/node_modules/@types/mdast": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", - "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", + "examples/code-interpreter": { + "name": "@cloudflare/sandbox-code-interpreter-example", + "version": "1.0.0", + "extraneous": true, "license": "MIT", "dependencies": { - "@types/unist": "*" + "@cloudflare/sandbox": "^0.4.12", + "openai": "^5.12.0" + }, + "devDependencies": { + "@types/node": "^24.1.0", + "typescript": "^5.8.3", + "wrangler": "^4.41.0" } }, - "examples/basic/node_modules/@types/unist": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", - "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", - "license": "MIT" - }, - "examples/basic/node_modules/bail": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", - "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==", + "examples/minimal": { + "name": "@cloudflare/sandbox-minimal-example", + "version": "1.0.0", + "extraneous": true, "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "devDependencies": { + "@cloudflare/sandbox": "^0.3.6", + "@types/node": "^24.1.0", + "typescript": "^5.8.3", + "wrangler": "^4.41.0" } }, - "examples/basic/node_modules/ccount": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", - "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", + "node_modules/@actions/core": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.11.1.tgz", + "integrity": "sha512-hXJCSrkwfA46Vd9Z3q4cpEpHB1rL5NG04+/rbqW9d3+CSvtB1tYe8UTpAlixa1vj0m/ULglfEK2UKxMGxCxv5A==", + "dev": true, "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "dependencies": { + "@actions/exec": "^1.1.1", + "@actions/http-client": "^2.0.1" } }, - "examples/basic/node_modules/escape-string-regexp": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", - "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "node_modules/@actions/exec": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.1.1.tgz", + "integrity": "sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==", + "dev": true, "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "dependencies": { + "@actions/io": "^1.0.1" } }, - "examples/basic/node_modules/is-plain-obj": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", - "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "node_modules/@actions/http-client": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.2.3.tgz", + "integrity": "sha512-mx8hyJi/hjFvbPokCg4uRd4ZX78t+YyRPtnKWwIl+RzNaVuFpQHfmlGVfsKEJN8LwTCvL+DfVgAM04XaHkm6bA==", + "dev": true, "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "dependencies": { + "tunnel": "^0.0.6", + "undici": "^5.25.4" } }, - "examples/basic/node_modules/longest-streak": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", - "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", + "node_modules/@actions/http-client/node_modules/undici": { + "version": "5.29.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.29.0.tgz", + "integrity": "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==", + "dev": true, "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "dependencies": { + "@fastify/busboy": "^2.0.0" + }, + "engines": { + "node": ">=14.0" } }, - "examples/basic/node_modules/markdown-table": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz", - "integrity": "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } + "node_modules/@actions/io": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@actions/io/-/io-1.1.3.tgz", + "integrity": "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q==", + "dev": true, + "license": "MIT" }, - "examples/basic/node_modules/mdast-util-find-and-replace": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.2.tgz", - "integrity": "sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==", + "node_modules/@babel/code-frame": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", + "dev": true, "license": "MIT", "dependencies": { - "@types/mdast": "^4.0.0", - "escape-string-regexp": "^5.0.0", - "unist-util-is": "^6.0.0", - "unist-util-visit-parents": "^6.0.0" + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">=6.9.0" } }, - "examples/basic/node_modules/mdast-util-from-markdown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz", - "integrity": "sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==", + "node_modules/@babel/compat-data": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.4.tgz", + "integrity": "sha512-YsmSKC29MJwf0gF8Rjjrg5LQCmyh+j/nD8/eP7f+BeoQTKYqs9RoWbjGOdy0+1Ekr68RJZMUOPVQaQisnIo4Rw==", + "dev": true, "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "mdast-util-to-string": "^4.0.0", - "micromark": "^4.0.0", - "micromark-util-decode-numeric-character-reference": "^2.0.0", - "micromark-util-decode-string": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0", - "unist-util-stringify-position": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">=6.9.0" } }, - "examples/basic/node_modules/mdast-util-gfm": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-3.1.0.tgz", - "integrity": "sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==", + "node_modules/@babel/core": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.4.tgz", + "integrity": "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==", + "dev": true, "license": "MIT", "dependencies": { - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-gfm-autolink-literal": "^2.0.0", - "mdast-util-gfm-footnote": "^2.0.0", - "mdast-util-gfm-strikethrough": "^2.0.0", - "mdast-util-gfm-table": "^2.0.0", - "mdast-util-gfm-task-list-item": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.3", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-module-transforms": "^7.28.3", + "@babel/helpers": "^7.28.4", + "@babel/parser": "^7.28.4", + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.28.4", + "@babel/types": "^7.28.4", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://opencollective.com/babel" } }, - "examples/basic/node_modules/mdast-util-gfm-autolink-literal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-2.0.1.tgz", - "integrity": "sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "ccount": "^2.0.0", - "devlop": "^1.0.0", - "mdast-util-find-and-replace": "^3.0.0", - "micromark-util-character": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" } }, - "examples/basic/node_modules/mdast-util-gfm-strikethrough": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-2.0.0.tgz", - "integrity": "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==", + "node_modules/@babel/generator": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.3.tgz", + "integrity": "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==", + "dev": true, "license": "MIT", "dependencies": { - "@types/mdast": "^4.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" + "@babel/parser": "^7.28.3", + "@babel/types": "^7.28.2", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">=6.9.0" } }, - "examples/basic/node_modules/mdast-util-gfm-table": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-2.0.0.tgz", - "integrity": "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==", + "node_modules/@babel/helper-compilation-targets": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", + "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", + "dev": true, "license": "MIT", "dependencies": { - "@types/mdast": "^4.0.0", - "devlop": "^1.0.0", - "markdown-table": "^3.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" + "@babel/compat-data": "^7.27.2", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">=6.9.0" } }, - "examples/basic/node_modules/mdast-util-gfm-task-list-item": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.0.tgz", - "integrity": "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==", + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "dev": true, "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "devlop": "^1.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">=6.9.0" } }, - "examples/basic/node_modules/mdast-util-to-markdown": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz", - "integrity": "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==", + "node_modules/@babel/helper-module-imports": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", + "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", + "dev": true, "license": "MIT", "dependencies": { - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "longest-streak": "^3.0.0", - "mdast-util-phrasing": "^4.0.0", - "mdast-util-to-string": "^4.0.0", - "micromark-util-classify-character": "^2.0.0", - "micromark-util-decode-string": "^2.0.0", - "unist-util-visit": "^5.0.0", - "zwitch": "^2.0.0" + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">=6.9.0" } }, - "examples/basic/node_modules/mdast-util-to-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", - "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", + "node_modules/@babel/helper-module-transforms": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz", + "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==", + "dev": true, "license": "MIT", "dependencies": { - "@types/mdast": "^4.0.0" + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1", + "@babel/traverse": "^7.28.3" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "examples/basic/node_modules/micromark": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz", - "integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], + "node_modules/@babel/helper-plugin-utils": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", + "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", + "dev": true, "license": "MIT", - "dependencies": { - "@types/debug": "^4.0.0", - "debug": "^4.0.0", - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "micromark-core-commonmark": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-combine-extensions": "^2.0.0", - "micromark-util-decode-numeric-character-reference": "^2.0.0", - "micromark-util-encode": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-resolve-all": "^2.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "micromark-util-subtokenize": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" + "engines": { + "node": ">=6.9.0" } }, - "examples/basic/node_modules/micromark-extension-gfm": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz", - "integrity": "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==", + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "dev": true, "license": "MIT", - "dependencies": { - "micromark-extension-gfm-autolink-literal": "^2.0.0", - "micromark-extension-gfm-footnote": "^2.0.0", - "micromark-extension-gfm-strikethrough": "^2.0.0", - "micromark-extension-gfm-table": "^2.0.0", - "micromark-extension-gfm-tagfilter": "^2.0.0", - "micromark-extension-gfm-task-list-item": "^2.0.0", - "micromark-util-combine-extensions": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">=6.9.0" } }, - "examples/basic/node_modules/micromark-extension-gfm-autolink-literal": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz", - "integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==", + "node_modules/@babel/helper-validator-identifier": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", + "dev": true, "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">=6.9.0" } }, - "examples/basic/node_modules/micromark-extension-gfm-strikethrough": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.1.0.tgz", - "integrity": "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==", + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "dev": true, "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-classify-character": "^2.0.0", - "micromark-util-resolve-all": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">=6.9.0" } }, - "examples/basic/node_modules/micromark-extension-gfm-table": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.1.tgz", - "integrity": "sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==", + "node_modules/@babel/helpers": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz", + "integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==", + "dev": true, "license": "MIT", "dependencies": { - "devlop": "^1.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.4" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">=6.9.0" } }, - "examples/basic/node_modules/micromark-extension-gfm-tagfilter": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz", - "integrity": "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==", + "node_modules/@babel/parser": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.4.tgz", + "integrity": "sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg==", + "dev": true, "license": "MIT", "dependencies": { - "micromark-util-types": "^2.0.0" + "@babel/types": "^7.28.4" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" } }, - "examples/basic/node_modules/micromark-extension-gfm-task-list-item": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.1.0.tgz", - "integrity": "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==", + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz", + "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==", + "dev": true, "license": "MIT", "dependencies": { - "devlop": "^1.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" + "@babel/helper-plugin-utils": "^7.27.1" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "examples/basic/node_modules/remark-gfm": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.1.tgz", - "integrity": "sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==", + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz", + "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==", + "dev": true, "license": "MIT", "dependencies": { - "@types/mdast": "^4.0.0", - "mdast-util-gfm": "^3.0.0", - "micromark-extension-gfm": "^3.0.0", - "remark-parse": "^11.0.0", - "remark-stringify": "^11.0.0", - "unified": "^11.0.0" + "@babel/helper-plugin-utils": "^7.27.1" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "examples/basic/node_modules/remark-parse": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", - "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "mdast-util-from-markdown": "^2.0.0", - "micromark-util-types": "^2.0.0", - "unified": "^11.0.0" + "engines": { + "node": ">=6.9.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "examples/basic/node_modules/trough": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", - "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==", + "node_modules/@babel/runtime": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz", + "integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==", + "dev": true, "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "engines": { + "node": ">=6.9.0" } }, - "examples/basic/node_modules/unified": { - "version": "11.0.5", - "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", - "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==", + "node_modules/@babel/template": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", + "dev": true, "license": "MIT", "dependencies": { - "@types/unist": "^3.0.0", - "bail": "^2.0.0", - "devlop": "^1.0.0", - "extend": "^3.0.0", - "is-plain-obj": "^4.0.0", - "trough": "^2.0.0", - "vfile": "^6.0.0" + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">=6.9.0" } }, - "examples/basic/node_modules/unist-util-is": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", - "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", + "node_modules/@babel/traverse": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.4.tgz", + "integrity": "sha512-YEzuboP2qvQavAcjgQNVgsvHIDv6ZpwXvcvjmyySP2DIMuByS/6ioU5G9pYrWHM6T2YDfc7xga9iNzYOs12CFQ==", + "dev": true, "license": "MIT", "dependencies": { - "@types/unist": "^3.0.0" + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.3", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.28.4", + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.4", + "debug": "^4.3.1" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">=6.9.0" } }, - "examples/basic/node_modules/unist-util-stringify-position": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", - "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "node_modules/@babel/types": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.4.tgz", + "integrity": "sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==", + "dev": true, "license": "MIT", "dependencies": { - "@types/unist": "^3.0.0" + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">=6.9.0" } }, - "examples/basic/node_modules/unist-util-visit-parents": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", - "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0" + "node_modules/@biomejs/biome": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-2.2.5.tgz", + "integrity": "sha512-zcIi+163Rc3HtyHbEO7CjeHq8DjQRs40HsGbW6vx2WI0tg8mYQOPouhvHSyEnCBAorfYNnKdR64/IxO7xQ5faw==", + "dev": true, + "license": "MIT OR Apache-2.0", + "bin": { + "biome": "bin/biome" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "examples/basic/node_modules/vfile": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", - "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "vfile-message": "^4.0.0" + "engines": { + "node": ">=14.21.3" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "examples/basic/node_modules/vfile-message": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz", - "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-stringify-position": "^4.0.0" + "url": "https://opencollective.com/biome" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "optionalDependencies": { + "@biomejs/cli-darwin-arm64": "2.2.5", + "@biomejs/cli-darwin-x64": "2.2.5", + "@biomejs/cli-linux-arm64": "2.2.5", + "@biomejs/cli-linux-arm64-musl": "2.2.5", + "@biomejs/cli-linux-x64": "2.2.5", + "@biomejs/cli-linux-x64-musl": "2.2.5", + "@biomejs/cli-win32-arm64": "2.2.5", + "@biomejs/cli-win32-x64": "2.2.5" } }, - "examples/basic/node_modules/zwitch": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", - "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "node_modules/@biomejs/cli-darwin-arm64": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-2.2.5.tgz", + "integrity": "sha512-MYT+nZ38wEIWVcL5xLyOhYQQ7nlWD0b/4mgATW2c8dvq7R4OQjt/XGXFkXrmtWmQofaIM14L7V8qIz/M+bx5QQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.21.3" } }, - "examples/code-interpreter": { - "name": "@cloudflare/sandbox-code-interpreter-example", - "version": "1.0.0", - "license": "MIT", - "dependencies": { - "@cloudflare/sandbox": "^0.4.12", - "openai": "^5.12.0" - }, - "devDependencies": { - "@types/node": "^24.1.0", - "typescript": "^5.8.3", - "wrangler": "^4.41.0" + "node_modules/@biomejs/cli-darwin-x64": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-2.2.5.tgz", + "integrity": "sha512-FLIEl73fv0R7dI10EnEiZLw+IMz3mWLnF95ASDI0kbx6DDLJjWxE5JxxBfmG+udz1hIDd3fr5wsuP7nwuTRdAg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.21.3" } }, - "examples/minimal": { - "name": "@cloudflare/sandbox-minimal-example", - "version": "1.0.0", - "extraneous": true, - "license": "MIT", - "devDependencies": { - "@cloudflare/sandbox": "^0.3.6", - "@types/node": "^24.1.0", - "typescript": "^5.8.3", - "wrangler": "^4.41.0" + "node_modules/@biomejs/cli-linux-arm64": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-2.2.5.tgz", + "integrity": "sha512-5DjiiDfHqGgR2MS9D+AZ8kOfrzTGqLKywn8hoXpXXlJXIECGQ32t+gt/uiS2XyGBM2XQhR6ztUvbjZWeccFMoQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" } }, - "node_modules/@actions/core": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.11.1.tgz", - "integrity": "sha512-hXJCSrkwfA46Vd9Z3q4cpEpHB1rL5NG04+/rbqW9d3+CSvtB1tYe8UTpAlixa1vj0m/ULglfEK2UKxMGxCxv5A==", + "node_modules/@biomejs/cli-linux-arm64-musl": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.2.5.tgz", + "integrity": "sha512-5Ov2wgAFwqDvQiESnu7b9ufD1faRa+40uwrohgBopeY84El2TnBDoMNXx6iuQdreoFGjwW8vH6k68G21EpNERw==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "MIT", - "dependencies": { - "@actions/exec": "^1.1.1", - "@actions/http-client": "^2.0.1" + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" } }, - "node_modules/@actions/exec": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.1.1.tgz", - "integrity": "sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==", + "node_modules/@biomejs/cli-linux-x64": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-2.2.5.tgz", + "integrity": "sha512-fq9meKm1AEXeAWan3uCg6XSP5ObA6F/Ovm89TwaMiy1DNIwdgxPkNwxlXJX8iM6oRbFysYeGnT0OG8diCWb9ew==", + "cpu": [ + "x64" + ], "dev": true, - "license": "MIT", - "dependencies": { - "@actions/io": "^1.0.1" + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" } }, - "node_modules/@actions/http-client": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.2.3.tgz", - "integrity": "sha512-mx8hyJi/hjFvbPokCg4uRd4ZX78t+YyRPtnKWwIl+RzNaVuFpQHfmlGVfsKEJN8LwTCvL+DfVgAM04XaHkm6bA==", + "node_modules/@biomejs/cli-linux-x64-musl": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-2.2.5.tgz", + "integrity": "sha512-AVqLCDb/6K7aPNIcxHaTQj01sl1m989CJIQFQEaiQkGr2EQwyOpaATJ473h+nXDUuAcREhccfRpe/tu+0wu0eQ==", + "cpu": [ + "x64" + ], "dev": true, - "license": "MIT", - "dependencies": { - "tunnel": "^0.0.6", - "undici": "^5.25.4" + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" } }, - "node_modules/@actions/http-client/node_modules/undici": { - "version": "5.29.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.29.0.tgz", - "integrity": "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==", + "node_modules/@biomejs/cli-win32-arm64": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-2.2.5.tgz", + "integrity": "sha512-xaOIad4wBambwJa6mdp1FigYSIF9i7PCqRbvBqtIi9y29QtPVQ13sDGtUnsRoe6SjL10auMzQ6YAe+B3RpZXVg==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "MIT", - "dependencies": { - "@fastify/busboy": "^2.0.0" - }, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=14.0" + "node": ">=14.21.3" } }, - "node_modules/@actions/io": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@actions/io/-/io-1.1.3.tgz", - "integrity": "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/@babel/code-frame": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", - "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", + "node_modules/@biomejs/cli-win32-x64": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-2.2.5.tgz", + "integrity": "sha512-F/jhuXCssPFAuciMhHKk00xnCAxJRS/pUzVfXYmOMUp//XW7mO6QeCjsjvnm8L4AO/dG2VOB0O+fJPiJ2uXtIw==", + "cpu": [ + "x64" + ], "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-validator-identifier": "^7.27.1", - "js-tokens": "^4.0.0", - "picocolors": "^1.1.1" - }, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=6.9.0" + "node": ">=14.21.3" } }, - "node_modules/@babel/compat-data": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.4.tgz", - "integrity": "sha512-YsmSKC29MJwf0gF8Rjjrg5LQCmyh+j/nD8/eP7f+BeoQTKYqs9RoWbjGOdy0+1Ekr68RJZMUOPVQaQisnIo4Rw==", + "node_modules/@changesets/apply-release-plan": { + "version": "7.0.13", + "resolved": "https://registry.npmjs.org/@changesets/apply-release-plan/-/apply-release-plan-7.0.13.tgz", + "integrity": "sha512-BIW7bofD2yAWoE8H4V40FikC+1nNFEKBisMECccS16W1rt6qqhNTBDmIw5HaqmMgtLNz9e7oiALiEUuKrQ4oHg==", "dev": true, "license": "MIT", - "engines": { - "node": ">=6.9.0" + "dependencies": { + "@changesets/config": "^3.1.1", + "@changesets/get-version-range-type": "^0.4.0", + "@changesets/git": "^3.0.4", + "@changesets/should-skip-package": "^0.1.2", + "@changesets/types": "^6.1.0", + "@manypkg/get-packages": "^1.1.3", + "detect-indent": "^6.0.0", + "fs-extra": "^7.0.1", + "lodash.startcase": "^4.4.0", + "outdent": "^0.5.0", + "prettier": "^2.7.1", + "resolve-from": "^5.0.0", + "semver": "^7.5.3" } }, - "node_modules/@babel/core": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.4.tgz", - "integrity": "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==", + "node_modules/@changesets/assemble-release-plan": { + "version": "6.0.9", + "resolved": "https://registry.npmjs.org/@changesets/assemble-release-plan/-/assemble-release-plan-6.0.9.tgz", + "integrity": "sha512-tPgeeqCHIwNo8sypKlS3gOPmsS3wP0zHt67JDuL20P4QcXiw/O4Hl7oXiuLnP9yg+rXLQ2sScdV1Kkzde61iSQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.3", - "@babel/helper-compilation-targets": "^7.27.2", - "@babel/helper-module-transforms": "^7.28.3", - "@babel/helpers": "^7.28.4", - "@babel/parser": "^7.28.4", - "@babel/template": "^7.27.2", - "@babel/traverse": "^7.28.4", - "@babel/types": "^7.28.4", - "@jridgewell/remapping": "^2.3.5", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" + "@changesets/errors": "^0.2.0", + "@changesets/get-dependents-graph": "^2.1.3", + "@changesets/should-skip-package": "^0.1.2", + "@changesets/types": "^6.1.0", + "@manypkg/get-packages": "^1.1.3", + "semver": "^7.5.3" } }, - "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "node_modules/@changesets/changelog-git": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@changesets/changelog-git/-/changelog-git-0.2.1.tgz", + "integrity": "sha512-x/xEleCFLH28c3bQeQIyeZf8lFXyDFVn1SgcBiR2Tw/r4IAWlk1fzxCEZ6NxQAjF2Nwtczoen3OA2qR+UawQ8Q==", "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "license": "MIT", + "dependencies": { + "@changesets/types": "^6.1.0" } }, - "node_modules/@babel/generator": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.3.tgz", - "integrity": "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==", + "node_modules/@changesets/changelog-github": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@changesets/changelog-github/-/changelog-github-0.5.1.tgz", + "integrity": "sha512-BVuHtF+hrhUScSoHnJwTELB4/INQxVFc+P/Qdt20BLiBFIHFJDDUaGsZw+8fQeJTRP5hJZrzpt3oZWh0G19rAQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.28.3", - "@babel/types": "^7.28.2", - "@jridgewell/gen-mapping": "^0.3.12", - "@jridgewell/trace-mapping": "^0.3.28", - "jsesc": "^3.0.2" - }, - "engines": { - "node": ">=6.9.0" + "@changesets/get-github-info": "^0.6.0", + "@changesets/types": "^6.1.0", + "dotenv": "^8.1.0" } }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", - "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", + "node_modules/@changesets/cli": { + "version": "2.29.7", + "resolved": "https://registry.npmjs.org/@changesets/cli/-/cli-2.29.7.tgz", + "integrity": "sha512-R7RqWoaksyyKXbKXBTbT4REdy22yH81mcFK6sWtqSanxUCbUi9Uf+6aqxZtDQouIqPdem2W56CdxXgsxdq7FLQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.27.2", - "@babel/helper-validator-option": "^7.27.1", - "browserslist": "^4.24.0", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" + "@changesets/apply-release-plan": "^7.0.13", + "@changesets/assemble-release-plan": "^6.0.9", + "@changesets/changelog-git": "^0.2.1", + "@changesets/config": "^3.1.1", + "@changesets/errors": "^0.2.0", + "@changesets/get-dependents-graph": "^2.1.3", + "@changesets/get-release-plan": "^4.0.13", + "@changesets/git": "^3.0.4", + "@changesets/logger": "^0.1.1", + "@changesets/pre": "^2.0.2", + "@changesets/read": "^0.6.5", + "@changesets/should-skip-package": "^0.1.2", + "@changesets/types": "^6.1.0", + "@changesets/write": "^0.4.0", + "@inquirer/external-editor": "^1.0.0", + "@manypkg/get-packages": "^1.1.3", + "ansi-colors": "^4.1.3", + "ci-info": "^3.7.0", + "enquirer": "^2.4.1", + "fs-extra": "^7.0.1", + "mri": "^1.2.0", + "p-limit": "^2.2.0", + "package-manager-detector": "^0.2.0", + "picocolors": "^1.1.0", + "resolve-from": "^5.0.0", + "semver": "^7.5.3", + "spawndamnit": "^3.0.1", + "term-size": "^2.1.0" }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", "bin": { - "semver": "bin/semver.js" + "changeset": "bin.js" } }, - "node_modules/@babel/helper-globals": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", - "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "node_modules/@changesets/config": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@changesets/config/-/config-3.1.1.tgz", + "integrity": "sha512-bd+3Ap2TKXxljCggI0mKPfzCQKeV/TU4yO2h2C6vAihIo8tzseAn2e7klSuiyYYXvgu53zMN1OeYMIQkaQoWnA==", "dev": true, "license": "MIT", - "engines": { - "node": ">=6.9.0" + "dependencies": { + "@changesets/errors": "^0.2.0", + "@changesets/get-dependents-graph": "^2.1.3", + "@changesets/logger": "^0.1.1", + "@changesets/types": "^6.1.0", + "@manypkg/get-packages": "^1.1.3", + "fs-extra": "^7.0.1", + "micromatch": "^4.0.8" } }, - "node_modules/@babel/helper-module-imports": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", - "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", + "node_modules/@changesets/errors": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@changesets/errors/-/errors-0.2.0.tgz", + "integrity": "sha512-6BLOQUscTpZeGljvyQXlWOItQyU71kCdGz7Pi8H8zdw6BI0g3m43iL4xKUVPWtG+qrrL9DTjpdn8eYuCQSRpow==", "dev": true, "license": "MIT", "dependencies": { - "@babel/traverse": "^7.27.1", - "@babel/types": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" + "extendable-error": "^0.1.5" } }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz", - "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==", + "node_modules/@changesets/get-dependents-graph": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@changesets/get-dependents-graph/-/get-dependents-graph-2.1.3.tgz", + "integrity": "sha512-gphr+v0mv2I3Oxt19VdWRRUxq3sseyUpX9DaHpTUmLj92Y10AGy+XOtV+kbM6L/fDcpx7/ISDFK6T8A/P3lOdQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1", - "@babel/traverse": "^7.28.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "@changesets/types": "^6.1.0", + "@manypkg/get-packages": "^1.1.3", + "picocolors": "^1.1.0", + "semver": "^7.5.3" } }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", - "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", + "node_modules/@changesets/get-github-info": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@changesets/get-github-info/-/get-github-info-0.6.0.tgz", + "integrity": "sha512-v/TSnFVXI8vzX9/w3DU2Ol+UlTZcu3m0kXTjTT4KlAdwSvwutcByYwyYn9hwerPWfPkT2JfpoX0KgvCEi8Q/SA==", "dev": true, "license": "MIT", - "engines": { - "node": ">=6.9.0" + "dependencies": { + "dataloader": "^1.4.0", + "node-fetch": "^2.5.0" } }, - "node_modules/@babel/helper-string-parser": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", - "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "node_modules/@changesets/get-release-plan": { + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/@changesets/get-release-plan/-/get-release-plan-4.0.13.tgz", + "integrity": "sha512-DWG1pus72FcNeXkM12tx+xtExyH/c9I1z+2aXlObH3i9YA7+WZEVaiHzHl03thpvAgWTRaH64MpfHxozfF7Dvg==", "dev": true, "license": "MIT", - "engines": { - "node": ">=6.9.0" + "dependencies": { + "@changesets/assemble-release-plan": "^6.0.9", + "@changesets/config": "^3.1.1", + "@changesets/pre": "^2.0.2", + "@changesets/read": "^0.6.5", + "@changesets/types": "^6.1.0", + "@manypkg/get-packages": "^1.1.3" } }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", - "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", + "node_modules/@changesets/get-version-range-type": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@changesets/get-version-range-type/-/get-version-range-type-0.4.0.tgz", + "integrity": "sha512-hwawtob9DryoGTpixy1D3ZXbGgJu1Rhr+ySH2PvTLHvkZuQ7sRT4oQwMh0hbqZH1weAooedEjRsbrWcGLCeyVQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@changesets/git": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@changesets/git/-/git-3.0.4.tgz", + "integrity": "sha512-BXANzRFkX+XcC1q/d27NKvlJ1yf7PSAgi8JG6dt8EfbHFHi4neau7mufcSca5zRhwOL8j9s6EqsxmT+s+/E6Sw==", "dev": true, "license": "MIT", - "engines": { - "node": ">=6.9.0" + "dependencies": { + "@changesets/errors": "^0.2.0", + "@manypkg/get-packages": "^1.1.3", + "is-subdir": "^1.1.1", + "micromatch": "^4.0.8", + "spawndamnit": "^3.0.1" } }, - "node_modules/@babel/helper-validator-option": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", - "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "node_modules/@changesets/logger": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@changesets/logger/-/logger-0.1.1.tgz", + "integrity": "sha512-OQtR36ZlnuTxKqoW4Sv6x5YIhOmClRd5pWsjZsddYxpWs517R0HkyiefQPIytCVh4ZcC5x9XaG8KTdd5iRQUfg==", "dev": true, "license": "MIT", - "engines": { - "node": ">=6.9.0" + "dependencies": { + "picocolors": "^1.1.0" } }, - "node_modules/@babel/helpers": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz", - "integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==", + "node_modules/@changesets/parse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@changesets/parse/-/parse-0.4.1.tgz", + "integrity": "sha512-iwksMs5Bf/wUItfcg+OXrEpravm5rEd9Bf4oyIPL4kVTmJQ7PNDSd6MDYkpSJR1pn7tz/k8Zf2DhTCqX08Ou+Q==", "dev": true, "license": "MIT", "dependencies": { - "@babel/template": "^7.27.2", - "@babel/types": "^7.28.4" - }, - "engines": { - "node": ">=6.9.0" + "@changesets/types": "^6.1.0", + "js-yaml": "^3.13.1" } }, - "node_modules/@babel/parser": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.4.tgz", - "integrity": "sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg==", + "node_modules/@changesets/pre": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@changesets/pre/-/pre-2.0.2.tgz", + "integrity": "sha512-HaL/gEyFVvkf9KFg6484wR9s0qjAXlZ8qWPDkTyKF6+zqjBe/I2mygg3MbpZ++hdi0ToqNUF8cjj7fBy0dg8Ug==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.28.4" - }, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" + "@changesets/errors": "^0.2.0", + "@changesets/types": "^6.1.0", + "@manypkg/get-packages": "^1.1.3", + "fs-extra": "^7.0.1" } }, - "node_modules/@babel/plugin-transform-react-jsx-self": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz", - "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==", + "node_modules/@changesets/read": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/@changesets/read/-/read-0.6.5.tgz", + "integrity": "sha512-UPzNGhsSjHD3Veb0xO/MwvasGe8eMyNrR/sT9gR8Q3DhOQZirgKhhXv/8hVsI0QpPjR004Z9iFxoJU6in3uGMg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@changesets/git": "^3.0.4", + "@changesets/logger": "^0.1.1", + "@changesets/parse": "^0.4.1", + "@changesets/types": "^6.1.0", + "fs-extra": "^7.0.1", + "p-filter": "^2.1.0", + "picocolors": "^1.1.0" } }, - "node_modules/@babel/plugin-transform-react-jsx-source": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz", - "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==", + "node_modules/@changesets/should-skip-package": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@changesets/should-skip-package/-/should-skip-package-0.1.2.tgz", + "integrity": "sha512-qAK/WrqWLNCP22UDdBTMPH5f41elVDlsNyat180A33dWxuUDyNpg6fPi/FyTZwRriVjg0L8gnjJn2F9XAoF0qw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@changesets/types": "^6.1.0", + "@manypkg/get-packages": "^1.1.3" } }, - "node_modules/@babel/runtime": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz", - "integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==", + "node_modules/@changesets/types": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@changesets/types/-/types-6.1.0.tgz", + "integrity": "sha512-rKQcJ+o1nKNgeoYRHKOS07tAMNd3YSN0uHaJOZYjBAgxfV7TUE7JE+z4BzZdQwb5hKaYbayKN5KrYV7ODb2rAA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@changesets/write": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@changesets/write/-/write-0.4.0.tgz", + "integrity": "sha512-CdTLvIOPiCNuH71pyDu3rA+Q0n65cmAbXnwWH84rKGiFumFzkmHNT8KHTMEchcxN+Kl8I54xGUhJ7l3E7X396Q==", "dev": true, "license": "MIT", - "engines": { - "node": ">=6.9.0" + "dependencies": { + "@changesets/types": "^6.1.0", + "fs-extra": "^7.0.1", + "human-id": "^4.1.1", + "prettier": "^2.7.1" } }, - "node_modules/@babel/template": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", - "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", + "node_modules/@cloudflare/containers": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@cloudflare/containers/-/containers-0.0.29.tgz", + "integrity": "sha512-tiVCbS7p2SBWNZd4Ym6zx2gMJdQqq7VhWStID0DkQ1iCyqmLis1hDUNmeVbHCYKSnsyZq/SUxFspRwrXNaA3Yg==", + "license": "ISC" + }, + "node_modules/@cloudflare/kv-asset-handler": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.4.0.tgz", + "integrity": "sha512-+tv3z+SPp+gqTIcImN9o0hqE9xyfQjI1XD9pL6NuKjua9B1y7mNYv0S9cP+QEbA4ppVgGZEmKOvHX5G5Ei1CVA==", "dev": true, - "license": "MIT", + "license": "MIT OR Apache-2.0", "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/parser": "^7.27.2", - "@babel/types": "^7.27.1" + "mime": "^3.0.0" }, "engines": { - "node": ">=6.9.0" + "node": ">=18.0.0" } }, - "node_modules/@babel/traverse": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.4.tgz", - "integrity": "sha512-YEzuboP2qvQavAcjgQNVgsvHIDv6ZpwXvcvjmyySP2DIMuByS/6ioU5G9pYrWHM6T2YDfc7xga9iNzYOs12CFQ==", + "node_modules/@cloudflare/sandbox": { + "resolved": "packages/sandbox", + "link": true + }, + "node_modules/@cloudflare/unenv-preset": { + "version": "2.7.7", + "resolved": "https://registry.npmjs.org/@cloudflare/unenv-preset/-/unenv-preset-2.7.7.tgz", + "integrity": "sha512-HtZuh166y0Olbj9bqqySckz0Rw9uHjggJeoGbDx5x+sgezBXlxO6tQSig2RZw5tgObF8mWI8zaPvQMkQZtAODw==", "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.3", - "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.28.4", - "@babel/template": "^7.27.2", - "@babel/types": "^7.28.4", - "debug": "^4.3.1" + "license": "MIT OR Apache-2.0", + "peerDependencies": { + "unenv": "2.0.0-rc.21", + "workerd": "^1.20250927.0" }, - "engines": { - "node": ">=6.9.0" + "peerDependenciesMeta": { + "workerd": { + "optional": true + } } }, - "node_modules/@babel/types": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.4.tgz", - "integrity": "sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==", + "node_modules/@cloudflare/vite-plugin": { + "version": "1.13.12", + "resolved": "https://registry.npmjs.org/@cloudflare/vite-plugin/-/vite-plugin-1.13.12.tgz", + "integrity": "sha512-JEcrUF1uXxMQfp+RcGw7ov5K8uOGX0arFYdyO3QfHrjWspHnsw0zOYL+4083itEInRVnZjS5LunpsNpxSVbCEw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1" + "@cloudflare/unenv-preset": "2.7.7", + "@remix-run/node-fetch-server": "^0.8.0", + "get-port": "^7.1.0", + "miniflare": "4.20251008.0", + "picocolors": "^1.1.1", + "tinyglobby": "^0.2.12", + "unenv": "2.0.0-rc.21", + "wrangler": "4.42.2", + "ws": "8.18.0" }, - "engines": { - "node": ">=6.9.0" + "peerDependencies": { + "vite": "^6.1.0 || ^7.0.0", + "wrangler": "^4.42.2" } }, - "node_modules/@biomejs/biome": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-2.2.5.tgz", - "integrity": "sha512-zcIi+163Rc3HtyHbEO7CjeHq8DjQRs40HsGbW6vx2WI0tg8mYQOPouhvHSyEnCBAorfYNnKdR64/IxO7xQ5faw==", + "node_modules/@cloudflare/vite-plugin/node_modules/ws": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", "dev": true, - "license": "MIT OR Apache-2.0", - "bin": { - "biome": "bin/biome" - }, + "license": "MIT", "engines": { - "node": ">=14.21.3" + "node": ">=10.0.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/biome" + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" }, - "optionalDependencies": { - "@biomejs/cli-darwin-arm64": "2.2.5", - "@biomejs/cli-darwin-x64": "2.2.5", - "@biomejs/cli-linux-arm64": "2.2.5", - "@biomejs/cli-linux-arm64-musl": "2.2.5", - "@biomejs/cli-linux-x64": "2.2.5", - "@biomejs/cli-linux-x64-musl": "2.2.5", - "@biomejs/cli-win32-arm64": "2.2.5", - "@biomejs/cli-win32-x64": "2.2.5" + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } } }, - "node_modules/@biomejs/cli-darwin-arm64": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-2.2.5.tgz", - "integrity": "sha512-MYT+nZ38wEIWVcL5xLyOhYQQ7nlWD0b/4mgATW2c8dvq7R4OQjt/XGXFkXrmtWmQofaIM14L7V8qIz/M+bx5QQ==", + "node_modules/@cloudflare/vitest-pool-workers": { + "version": "0.9.12", + "resolved": "https://registry.npmjs.org/@cloudflare/vitest-pool-workers/-/vitest-pool-workers-0.9.12.tgz", + "integrity": "sha512-MTHFgqyhji3VhdjNQX/CcKNYchAyaQMbjh23Hif8LFq2YaMCISSVoVAUBXoGMMS/+RblwqZOWfH2ZojTVhEr+Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "birpc": "0.2.14", + "cjs-module-lexer": "^1.2.3", + "devalue": "^5.3.2", + "miniflare": "4.20251008.0", + "semver": "^7.7.1", + "wrangler": "4.42.2", + "zod": "^3.22.3" + }, + "peerDependencies": { + "@vitest/runner": "2.0.x - 3.2.x", + "@vitest/snapshot": "2.0.x - 3.2.x", + "vitest": "2.0.x - 3.2.x" + } + }, + "node_modules/@cloudflare/workerd-darwin-64": { + "version": "1.20251008.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20251008.0.tgz", + "integrity": "sha512-yph0H+8mMOK5Z9oDwjb8rI96oTVt4no5lZ43aorcbzsWG9VUIaXSXlBBoB3von6p4YCRW+J3n36fBM9XZ6TLaA==", "cpu": [ - "arm64" + "x64" ], "dev": true, - "license": "MIT OR Apache-2.0", + "license": "Apache-2.0", "optional": true, "os": [ "darwin" ], "engines": { - "node": ">=14.21.3" + "node": ">=16" } }, - "node_modules/@biomejs/cli-darwin-x64": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-2.2.5.tgz", - "integrity": "sha512-FLIEl73fv0R7dI10EnEiZLw+IMz3mWLnF95ASDI0kbx6DDLJjWxE5JxxBfmG+udz1hIDd3fr5wsuP7nwuTRdAg==", + "node_modules/@cloudflare/workerd-darwin-arm64": { + "version": "1.20251008.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20251008.0.tgz", + "integrity": "sha512-Yc4lMGSbM4AEtYRpyDpmk77MsHb6X2BSwJgMgGsLVPmckM7ZHivZkJChfcNQjZ/MGR6nkhYc4iF6TcVS+UMEVw==", "cpu": [ - "x64" + "arm64" ], "dev": true, - "license": "MIT OR Apache-2.0", + "license": "Apache-2.0", "optional": true, "os": [ "darwin" ], "engines": { - "node": ">=14.21.3" + "node": ">=16" } }, - "node_modules/@biomejs/cli-linux-arm64": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-2.2.5.tgz", - "integrity": "sha512-5DjiiDfHqGgR2MS9D+AZ8kOfrzTGqLKywn8hoXpXXlJXIECGQ32t+gt/uiS2XyGBM2XQhR6ztUvbjZWeccFMoQ==", + "node_modules/@cloudflare/workerd-linux-64": { + "version": "1.20251008.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20251008.0.tgz", + "integrity": "sha512-AjoQnylw4/5G6SmfhZRsli7EuIK7ZMhmbxtU0jkpciTlVV8H01OsFOgS1d8zaTXMfkWamEfMouy8oH/L7B9YcQ==", "cpu": [ - "arm64" + "x64" ], "dev": true, - "license": "MIT OR Apache-2.0", + "license": "Apache-2.0", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=14.21.3" + "node": ">=16" } }, - "node_modules/@biomejs/cli-linux-arm64-musl": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.2.5.tgz", - "integrity": "sha512-5Ov2wgAFwqDvQiESnu7b9ufD1faRa+40uwrohgBopeY84El2TnBDoMNXx6iuQdreoFGjwW8vH6k68G21EpNERw==", + "node_modules/@cloudflare/workerd-linux-arm64": { + "version": "1.20251008.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20251008.0.tgz", + "integrity": "sha512-hRy9yyvzVq1HsqHZUmFkAr0C8JGjAD/PeeVEGCKL3jln3M9sNCKIrbDXiL+efe+EwajJNNlDxpO+s30uVWVaRg==", "cpu": [ "arm64" ], "dev": true, - "license": "MIT OR Apache-2.0", + "license": "Apache-2.0", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=14.21.3" + "node": ">=16" } }, - "node_modules/@biomejs/cli-linux-x64": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-2.2.5.tgz", - "integrity": "sha512-fq9meKm1AEXeAWan3uCg6XSP5ObA6F/Ovm89TwaMiy1DNIwdgxPkNwxlXJX8iM6oRbFysYeGnT0OG8diCWb9ew==", + "node_modules/@cloudflare/workerd-windows-64": { + "version": "1.20251008.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20251008.0.tgz", + "integrity": "sha512-Gm0RR+ehfNMsScn2pUcn3N9PDUpy7FyvV9ecHEyclKttvztyFOcmsF14bxEaSVv7iM4TxWEBn1rclmYHxDM4ow==", "cpu": [ "x64" ], "dev": true, - "license": "MIT OR Apache-2.0", + "license": "Apache-2.0", "optional": true, "os": [ - "linux" + "win32" ], "engines": { - "node": ">=14.21.3" + "node": ">=16" } }, - "node_modules/@biomejs/cli-linux-x64-musl": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-2.2.5.tgz", - "integrity": "sha512-AVqLCDb/6K7aPNIcxHaTQj01sl1m989CJIQFQEaiQkGr2EQwyOpaATJ473h+nXDUuAcREhccfRpe/tu+0wu0eQ==", + "node_modules/@cloudflare/workers-types": { + "version": "4.20251011.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workers-types/-/workers-types-4.20251011.0.tgz", + "integrity": "sha512-gQpih+pbq3sP4uXltUeCSbPgZxTNp2gQd8639SaIbQMwgA6oJNHLhIART1fWy6DQACngiRzDVULA2x0ohmkGTQ==", + "dev": true, + "license": "MIT OR Apache-2.0" + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.5.0.tgz", + "integrity": "sha512-97/BJ3iXHww3djw6hYIfErCZFee7qCtrneuLa20UXFCOTCfBM2cvQHjWJ2EG0s0MtdNwInarqCTz35i4wWXHsQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.10.tgz", + "integrity": "sha512-0NFWnA+7l41irNuaSVlLfgNT12caWJVLzp5eAVhZ0z1qpxbockccEt3s+149rE64VUI3Ml2zt8Nv5JVc4QXTsw==", "cpu": [ - "x64" + "ppc64" ], - "dev": true, - "license": "MIT OR Apache-2.0", + "license": "MIT", "optional": true, "os": [ - "linux" + "aix" ], "engines": { - "node": ">=14.21.3" + "node": ">=18" } }, - "node_modules/@biomejs/cli-win32-arm64": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-2.2.5.tgz", - "integrity": "sha512-xaOIad4wBambwJa6mdp1FigYSIF9i7PCqRbvBqtIi9y29QtPVQ13sDGtUnsRoe6SjL10auMzQ6YAe+B3RpZXVg==", + "node_modules/@esbuild/android-arm": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.10.tgz", + "integrity": "sha512-dQAxF1dW1C3zpeCDc5KqIYuZ1tgAdRXNoZP7vkBIRtKZPYe2xVr/d3SkirklCHudW1B45tGiUlz2pUWDfbDD4w==", "cpu": [ - "arm64" + "arm" ], - "dev": true, - "license": "MIT OR Apache-2.0", + "license": "MIT", "optional": true, "os": [ - "win32" + "android" ], "engines": { - "node": ">=14.21.3" + "node": ">=18" } }, - "node_modules/@biomejs/cli-win32-x64": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-2.2.5.tgz", - "integrity": "sha512-F/jhuXCssPFAuciMhHKk00xnCAxJRS/pUzVfXYmOMUp//XW7mO6QeCjsjvnm8L4AO/dG2VOB0O+fJPiJ2uXtIw==", + "node_modules/@esbuild/android-arm64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.10.tgz", + "integrity": "sha512-LSQa7eDahypv/VO6WKohZGPSJDq5OVOo3UoFR1E4t4Gj1W7zEQMUhI+lo81H+DtB+kP+tDgBp+M4oNCwp6kffg==", "cpu": [ - "x64" + "arm64" ], - "dev": true, - "license": "MIT OR Apache-2.0", + "license": "MIT", "optional": true, "os": [ - "win32" + "android" ], "engines": { - "node": ">=14.21.3" + "node": ">=18" } }, - "node_modules/@changesets/apply-release-plan": { - "version": "7.0.13", - "resolved": "https://registry.npmjs.org/@changesets/apply-release-plan/-/apply-release-plan-7.0.13.tgz", - "integrity": "sha512-BIW7bofD2yAWoE8H4V40FikC+1nNFEKBisMECccS16W1rt6qqhNTBDmIw5HaqmMgtLNz9e7oiALiEUuKrQ4oHg==", - "dev": true, + "node_modules/@esbuild/android-x64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.10.tgz", + "integrity": "sha512-MiC9CWdPrfhibcXwr39p9ha1x0lZJ9KaVfvzA0Wxwz9ETX4v5CHfF09bx935nHlhi+MxhA63dKRRQLiVgSUtEg==", + "cpu": [ + "x64" + ], "license": "MIT", - "dependencies": { - "@changesets/config": "^3.1.1", - "@changesets/get-version-range-type": "^0.4.0", - "@changesets/git": "^3.0.4", - "@changesets/should-skip-package": "^0.1.2", - "@changesets/types": "^6.1.0", - "@manypkg/get-packages": "^1.1.3", - "detect-indent": "^6.0.0", - "fs-extra": "^7.0.1", - "lodash.startcase": "^4.4.0", - "outdent": "^0.5.0", - "prettier": "^2.7.1", - "resolve-from": "^5.0.0", - "semver": "^7.5.3" + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@changesets/assemble-release-plan": { - "version": "6.0.9", - "resolved": "https://registry.npmjs.org/@changesets/assemble-release-plan/-/assemble-release-plan-6.0.9.tgz", - "integrity": "sha512-tPgeeqCHIwNo8sypKlS3gOPmsS3wP0zHt67JDuL20P4QcXiw/O4Hl7oXiuLnP9yg+rXLQ2sScdV1Kkzde61iSQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@changesets/errors": "^0.2.0", - "@changesets/get-dependents-graph": "^2.1.3", - "@changesets/should-skip-package": "^0.1.2", - "@changesets/types": "^6.1.0", - "@manypkg/get-packages": "^1.1.3", - "semver": "^7.5.3" - } - }, - "node_modules/@changesets/changelog-git": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/@changesets/changelog-git/-/changelog-git-0.2.1.tgz", - "integrity": "sha512-x/xEleCFLH28c3bQeQIyeZf8lFXyDFVn1SgcBiR2Tw/r4IAWlk1fzxCEZ6NxQAjF2Nwtczoen3OA2qR+UawQ8Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@changesets/types": "^6.1.0" - } - }, - "node_modules/@changesets/changelog-github": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/@changesets/changelog-github/-/changelog-github-0.5.1.tgz", - "integrity": "sha512-BVuHtF+hrhUScSoHnJwTELB4/INQxVFc+P/Qdt20BLiBFIHFJDDUaGsZw+8fQeJTRP5hJZrzpt3oZWh0G19rAQ==", - "dev": true, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.10.tgz", + "integrity": "sha512-JC74bdXcQEpW9KkV326WpZZjLguSZ3DfS8wrrvPMHgQOIEIG/sPXEN/V8IssoJhbefLRcRqw6RQH2NnpdprtMA==", + "cpu": [ + "arm64" + ], "license": "MIT", - "dependencies": { - "@changesets/get-github-info": "^0.6.0", - "@changesets/types": "^6.1.0", - "dotenv": "^8.1.0" + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@changesets/cli": { - "version": "2.29.7", - "resolved": "https://registry.npmjs.org/@changesets/cli/-/cli-2.29.7.tgz", - "integrity": "sha512-R7RqWoaksyyKXbKXBTbT4REdy22yH81mcFK6sWtqSanxUCbUi9Uf+6aqxZtDQouIqPdem2W56CdxXgsxdq7FLQ==", - "dev": true, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.10.tgz", + "integrity": "sha512-tguWg1olF6DGqzws97pKZ8G2L7Ig1vjDmGTwcTuYHbuU6TTjJe5FXbgs5C1BBzHbJ2bo1m3WkQDbWO2PvamRcg==", + "cpu": [ + "x64" + ], "license": "MIT", - "dependencies": { - "@changesets/apply-release-plan": "^7.0.13", - "@changesets/assemble-release-plan": "^6.0.9", - "@changesets/changelog-git": "^0.2.1", - "@changesets/config": "^3.1.1", - "@changesets/errors": "^0.2.0", - "@changesets/get-dependents-graph": "^2.1.3", - "@changesets/get-release-plan": "^4.0.13", - "@changesets/git": "^3.0.4", - "@changesets/logger": "^0.1.1", - "@changesets/pre": "^2.0.2", - "@changesets/read": "^0.6.5", - "@changesets/should-skip-package": "^0.1.2", - "@changesets/types": "^6.1.0", - "@changesets/write": "^0.4.0", - "@inquirer/external-editor": "^1.0.0", - "@manypkg/get-packages": "^1.1.3", - "ansi-colors": "^4.1.3", - "ci-info": "^3.7.0", - "enquirer": "^2.4.1", - "fs-extra": "^7.0.1", - "mri": "^1.2.0", - "p-limit": "^2.2.0", - "package-manager-detector": "^0.2.0", - "picocolors": "^1.1.0", - "resolve-from": "^5.0.0", - "semver": "^7.5.3", - "spawndamnit": "^3.0.1", - "term-size": "^2.1.0" - }, - "bin": { - "changeset": "bin.js" + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@changesets/config": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@changesets/config/-/config-3.1.1.tgz", - "integrity": "sha512-bd+3Ap2TKXxljCggI0mKPfzCQKeV/TU4yO2h2C6vAihIo8tzseAn2e7klSuiyYYXvgu53zMN1OeYMIQkaQoWnA==", - "dev": true, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.10.tgz", + "integrity": "sha512-3ZioSQSg1HT2N05YxeJWYR+Libe3bREVSdWhEEgExWaDtyFbbXWb49QgPvFH8u03vUPX10JhJPcz7s9t9+boWg==", + "cpu": [ + "arm64" + ], "license": "MIT", - "dependencies": { - "@changesets/errors": "^0.2.0", - "@changesets/get-dependents-graph": "^2.1.3", - "@changesets/logger": "^0.1.1", - "@changesets/types": "^6.1.0", - "@manypkg/get-packages": "^1.1.3", - "fs-extra": "^7.0.1", - "micromatch": "^4.0.8" + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@changesets/errors": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@changesets/errors/-/errors-0.2.0.tgz", - "integrity": "sha512-6BLOQUscTpZeGljvyQXlWOItQyU71kCdGz7Pi8H8zdw6BI0g3m43iL4xKUVPWtG+qrrL9DTjpdn8eYuCQSRpow==", - "dev": true, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.10.tgz", + "integrity": "sha512-LLgJfHJk014Aa4anGDbh8bmI5Lk+QidDmGzuC2D+vP7mv/GeSN+H39zOf7pN5N8p059FcOfs2bVlrRr4SK9WxA==", + "cpu": [ + "x64" + ], "license": "MIT", - "dependencies": { - "extendable-error": "^0.1.5" + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@changesets/get-dependents-graph": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@changesets/get-dependents-graph/-/get-dependents-graph-2.1.3.tgz", - "integrity": "sha512-gphr+v0mv2I3Oxt19VdWRRUxq3sseyUpX9DaHpTUmLj92Y10AGy+XOtV+kbM6L/fDcpx7/ISDFK6T8A/P3lOdQ==", - "dev": true, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.10.tgz", + "integrity": "sha512-oR31GtBTFYCqEBALI9r6WxoU/ZofZl962pouZRTEYECvNF/dtXKku8YXcJkhgK/beU+zedXfIzHijSRapJY3vg==", + "cpu": [ + "arm" + ], "license": "MIT", - "dependencies": { - "@changesets/types": "^6.1.0", - "@manypkg/get-packages": "^1.1.3", - "picocolors": "^1.1.0", - "semver": "^7.5.3" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@changesets/get-github-info": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@changesets/get-github-info/-/get-github-info-0.6.0.tgz", - "integrity": "sha512-v/TSnFVXI8vzX9/w3DU2Ol+UlTZcu3m0kXTjTT4KlAdwSvwutcByYwyYn9hwerPWfPkT2JfpoX0KgvCEi8Q/SA==", - "dev": true, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.10.tgz", + "integrity": "sha512-5luJWN6YKBsawd5f9i4+c+geYiVEw20FVW5x0v1kEMWNq8UctFjDiMATBxLvmmHA4bf7F6hTRaJgtghFr9iziQ==", + "cpu": [ + "arm64" + ], "license": "MIT", - "dependencies": { - "dataloader": "^1.4.0", - "node-fetch": "^2.5.0" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@changesets/get-release-plan": { - "version": "4.0.13", - "resolved": "https://registry.npmjs.org/@changesets/get-release-plan/-/get-release-plan-4.0.13.tgz", - "integrity": "sha512-DWG1pus72FcNeXkM12tx+xtExyH/c9I1z+2aXlObH3i9YA7+WZEVaiHzHl03thpvAgWTRaH64MpfHxozfF7Dvg==", - "dev": true, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.10.tgz", + "integrity": "sha512-NrSCx2Kim3EnnWgS4Txn0QGt0Xipoumb6z6sUtl5bOEZIVKhzfyp/Lyw4C1DIYvzeW/5mWYPBFJU3a/8Yr75DQ==", + "cpu": [ + "ia32" + ], "license": "MIT", - "dependencies": { - "@changesets/assemble-release-plan": "^6.0.9", - "@changesets/config": "^3.1.1", - "@changesets/pre": "^2.0.2", - "@changesets/read": "^0.6.5", - "@changesets/types": "^6.1.0", - "@manypkg/get-packages": "^1.1.3" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@changesets/get-version-range-type": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@changesets/get-version-range-type/-/get-version-range-type-0.4.0.tgz", - "integrity": "sha512-hwawtob9DryoGTpixy1D3ZXbGgJu1Rhr+ySH2PvTLHvkZuQ7sRT4oQwMh0hbqZH1weAooedEjRsbrWcGLCeyVQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@changesets/git": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@changesets/git/-/git-3.0.4.tgz", - "integrity": "sha512-BXANzRFkX+XcC1q/d27NKvlJ1yf7PSAgi8JG6dt8EfbHFHi4neau7mufcSca5zRhwOL8j9s6EqsxmT+s+/E6Sw==", - "dev": true, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.10.tgz", + "integrity": "sha512-xoSphrd4AZda8+rUDDfD9J6FUMjrkTz8itpTITM4/xgerAZZcFW7Dv+sun7333IfKxGG8gAq+3NbfEMJfiY+Eg==", + "cpu": [ + "loong64" + ], "license": "MIT", - "dependencies": { - "@changesets/errors": "^0.2.0", - "@manypkg/get-packages": "^1.1.3", - "is-subdir": "^1.1.1", - "micromatch": "^4.0.8", - "spawndamnit": "^3.0.1" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@changesets/logger": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@changesets/logger/-/logger-0.1.1.tgz", - "integrity": "sha512-OQtR36ZlnuTxKqoW4Sv6x5YIhOmClRd5pWsjZsddYxpWs517R0HkyiefQPIytCVh4ZcC5x9XaG8KTdd5iRQUfg==", - "dev": true, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.10.tgz", + "integrity": "sha512-ab6eiuCwoMmYDyTnyptoKkVS3k8fy/1Uvq7Dj5czXI6DF2GqD2ToInBI0SHOp5/X1BdZ26RKc5+qjQNGRBelRA==", + "cpu": [ + "mips64el" + ], "license": "MIT", - "dependencies": { - "picocolors": "^1.1.0" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@changesets/parse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@changesets/parse/-/parse-0.4.1.tgz", - "integrity": "sha512-iwksMs5Bf/wUItfcg+OXrEpravm5rEd9Bf4oyIPL4kVTmJQ7PNDSd6MDYkpSJR1pn7tz/k8Zf2DhTCqX08Ou+Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@changesets/types": "^6.1.0", - "js-yaml": "^3.13.1" - } - }, - "node_modules/@changesets/pre": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@changesets/pre/-/pre-2.0.2.tgz", - "integrity": "sha512-HaL/gEyFVvkf9KFg6484wR9s0qjAXlZ8qWPDkTyKF6+zqjBe/I2mygg3MbpZ++hdi0ToqNUF8cjj7fBy0dg8Ug==", - "dev": true, - "license": "MIT", - "dependencies": { - "@changesets/errors": "^0.2.0", - "@changesets/types": "^6.1.0", - "@manypkg/get-packages": "^1.1.3", - "fs-extra": "^7.0.1" - } - }, - "node_modules/@changesets/read": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/@changesets/read/-/read-0.6.5.tgz", - "integrity": "sha512-UPzNGhsSjHD3Veb0xO/MwvasGe8eMyNrR/sT9gR8Q3DhOQZirgKhhXv/8hVsI0QpPjR004Z9iFxoJU6in3uGMg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@changesets/git": "^3.0.4", - "@changesets/logger": "^0.1.1", - "@changesets/parse": "^0.4.1", - "@changesets/types": "^6.1.0", - "fs-extra": "^7.0.1", - "p-filter": "^2.1.0", - "picocolors": "^1.1.0" - } - }, - "node_modules/@changesets/should-skip-package": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@changesets/should-skip-package/-/should-skip-package-0.1.2.tgz", - "integrity": "sha512-qAK/WrqWLNCP22UDdBTMPH5f41elVDlsNyat180A33dWxuUDyNpg6fPi/FyTZwRriVjg0L8gnjJn2F9XAoF0qw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@changesets/types": "^6.1.0", - "@manypkg/get-packages": "^1.1.3" - } - }, - "node_modules/@changesets/types": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@changesets/types/-/types-6.1.0.tgz", - "integrity": "sha512-rKQcJ+o1nKNgeoYRHKOS07tAMNd3YSN0uHaJOZYjBAgxfV7TUE7JE+z4BzZdQwb5hKaYbayKN5KrYV7ODb2rAA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@changesets/write": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@changesets/write/-/write-0.4.0.tgz", - "integrity": "sha512-CdTLvIOPiCNuH71pyDu3rA+Q0n65cmAbXnwWH84rKGiFumFzkmHNT8KHTMEchcxN+Kl8I54xGUhJ7l3E7X396Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@changesets/types": "^6.1.0", - "fs-extra": "^7.0.1", - "human-id": "^4.1.1", - "prettier": "^2.7.1" - } - }, - "node_modules/@cloudflare/containers": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@cloudflare/containers/-/containers-0.0.29.tgz", - "integrity": "sha512-tiVCbS7p2SBWNZd4Ym6zx2gMJdQqq7VhWStID0DkQ1iCyqmLis1hDUNmeVbHCYKSnsyZq/SUxFspRwrXNaA3Yg==", - "license": "ISC" - }, - "node_modules/@cloudflare/kv-asset-handler": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.4.0.tgz", - "integrity": "sha512-+tv3z+SPp+gqTIcImN9o0hqE9xyfQjI1XD9pL6NuKjua9B1y7mNYv0S9cP+QEbA4ppVgGZEmKOvHX5G5Ei1CVA==", - "dev": true, - "license": "MIT OR Apache-2.0", - "dependencies": { - "mime": "^3.0.0" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@cloudflare/sandbox": { - "resolved": "packages/sandbox", - "link": true - }, - "node_modules/@cloudflare/sandbox-code-interpreter-example": { - "resolved": "examples/code-interpreter", - "link": true - }, - "node_modules/@cloudflare/sandbox-example": { - "resolved": "examples/basic", - "link": true - }, - "node_modules/@cloudflare/unenv-preset": { - "version": "2.7.7", - "resolved": "https://registry.npmjs.org/@cloudflare/unenv-preset/-/unenv-preset-2.7.7.tgz", - "integrity": "sha512-HtZuh166y0Olbj9bqqySckz0Rw9uHjggJeoGbDx5x+sgezBXlxO6tQSig2RZw5tgObF8mWI8zaPvQMkQZtAODw==", - "dev": true, - "license": "MIT OR Apache-2.0", - "peerDependencies": { - "unenv": "2.0.0-rc.21", - "workerd": "^1.20250927.0" - }, - "peerDependenciesMeta": { - "workerd": { - "optional": true - } - } - }, - "node_modules/@cloudflare/vite-plugin": { - "version": "1.13.12", - "resolved": "https://registry.npmjs.org/@cloudflare/vite-plugin/-/vite-plugin-1.13.12.tgz", - "integrity": "sha512-JEcrUF1uXxMQfp+RcGw7ov5K8uOGX0arFYdyO3QfHrjWspHnsw0zOYL+4083itEInRVnZjS5LunpsNpxSVbCEw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@cloudflare/unenv-preset": "2.7.7", - "@remix-run/node-fetch-server": "^0.8.0", - "get-port": "^7.1.0", - "miniflare": "4.20251008.0", - "picocolors": "^1.1.1", - "tinyglobby": "^0.2.12", - "unenv": "2.0.0-rc.21", - "wrangler": "4.42.2", - "ws": "8.18.0" - }, - "peerDependencies": { - "vite": "^6.1.0 || ^7.0.0", - "wrangler": "^4.42.2" - } - }, - "node_modules/@cloudflare/vite-plugin/node_modules/ws": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", - "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", - "dev": true, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.10.tgz", + "integrity": "sha512-NLinzzOgZQsGpsTkEbdJTCanwA5/wozN9dSgEl12haXJBzMTpssebuXR42bthOF3z7zXFWH1AmvWunUCkBE4EA==", + "cpu": [ + "ppc64" + ], "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/@cloudflare/vitest-pool-workers": { - "version": "0.9.12", - "resolved": "https://registry.npmjs.org/@cloudflare/vitest-pool-workers/-/vitest-pool-workers-0.9.12.tgz", - "integrity": "sha512-MTHFgqyhji3VhdjNQX/CcKNYchAyaQMbjh23Hif8LFq2YaMCISSVoVAUBXoGMMS/+RblwqZOWfH2ZojTVhEr+Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "birpc": "0.2.14", - "cjs-module-lexer": "^1.2.3", - "devalue": "^5.3.2", - "miniflare": "4.20251008.0", - "semver": "^7.7.1", - "wrangler": "4.42.2", - "zod": "^3.22.3" - }, - "peerDependencies": { - "@vitest/runner": "2.0.x - 3.2.x", - "@vitest/snapshot": "2.0.x - 3.2.x", - "vitest": "2.0.x - 3.2.x" + "node": ">=18" } }, - "node_modules/@cloudflare/workerd-darwin-64": { - "version": "1.20251008.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20251008.0.tgz", - "integrity": "sha512-yph0H+8mMOK5Z9oDwjb8rI96oTVt4no5lZ43aorcbzsWG9VUIaXSXlBBoB3von6p4YCRW+J3n36fBM9XZ6TLaA==", + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.10.tgz", + "integrity": "sha512-FE557XdZDrtX8NMIeA8LBJX3dC2M8VGXwfrQWU7LB5SLOajfJIxmSdyL/gU1m64Zs9CBKvm4UAuBp5aJ8OgnrA==", "cpu": [ - "x64" + "riscv64" ], - "dev": true, - "license": "Apache-2.0", + "license": "MIT", "optional": true, "os": [ - "darwin" + "linux" ], "engines": { - "node": ">=16" + "node": ">=18" } }, - "node_modules/@cloudflare/workerd-darwin-arm64": { - "version": "1.20251008.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20251008.0.tgz", - "integrity": "sha512-Yc4lMGSbM4AEtYRpyDpmk77MsHb6X2BSwJgMgGsLVPmckM7ZHivZkJChfcNQjZ/MGR6nkhYc4iF6TcVS+UMEVw==", + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.10.tgz", + "integrity": "sha512-3BBSbgzuB9ajLoVZk0mGu+EHlBwkusRmeNYdqmznmMc9zGASFjSsxgkNsqmXugpPk00gJ0JNKh/97nxmjctdew==", "cpu": [ - "arm64" + "s390x" ], - "dev": true, - "license": "Apache-2.0", + "license": "MIT", "optional": true, "os": [ - "darwin" + "linux" ], "engines": { - "node": ">=16" + "node": ">=18" } }, - "node_modules/@cloudflare/workerd-linux-64": { - "version": "1.20251008.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20251008.0.tgz", - "integrity": "sha512-AjoQnylw4/5G6SmfhZRsli7EuIK7ZMhmbxtU0jkpciTlVV8H01OsFOgS1d8zaTXMfkWamEfMouy8oH/L7B9YcQ==", + "node_modules/@esbuild/linux-x64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.10.tgz", + "integrity": "sha512-QSX81KhFoZGwenVyPoberggdW1nrQZSvfVDAIUXr3WqLRZGZqWk/P4T8p2SP+de2Sr5HPcvjhcJzEiulKgnxtA==", "cpu": [ "x64" ], - "dev": true, - "license": "Apache-2.0", + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=16" + "node": ">=18" } }, - "node_modules/@cloudflare/workerd-linux-arm64": { - "version": "1.20251008.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20251008.0.tgz", - "integrity": "sha512-hRy9yyvzVq1HsqHZUmFkAr0C8JGjAD/PeeVEGCKL3jln3M9sNCKIrbDXiL+efe+EwajJNNlDxpO+s30uVWVaRg==", + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.10.tgz", + "integrity": "sha512-AKQM3gfYfSW8XRk8DdMCzaLUFB15dTrZfnX8WXQoOUpUBQ+NaAFCP1kPS/ykbbGYz7rxn0WS48/81l9hFl3u4A==", "cpu": [ "arm64" ], - "dev": true, - "license": "Apache-2.0", + "license": "MIT", "optional": true, "os": [ - "linux" + "netbsd" ], "engines": { - "node": ">=16" + "node": ">=18" } }, - "node_modules/@cloudflare/workerd-windows-64": { - "version": "1.20251008.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20251008.0.tgz", - "integrity": "sha512-Gm0RR+ehfNMsScn2pUcn3N9PDUpy7FyvV9ecHEyclKttvztyFOcmsF14bxEaSVv7iM4TxWEBn1rclmYHxDM4ow==", + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.10.tgz", + "integrity": "sha512-7RTytDPGU6fek/hWuN9qQpeGPBZFfB4zZgcz2VK2Z5VpdUxEI8JKYsg3JfO0n/Z1E/6l05n0unDCNc4HnhQGig==", "cpu": [ "x64" ], - "dev": true, - "license": "Apache-2.0", + "license": "MIT", "optional": true, "os": [ - "win32" + "netbsd" ], "engines": { - "node": ">=16" - } - }, - "node_modules/@cloudflare/workers-types": { - "version": "4.20251011.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workers-types/-/workers-types-4.20251011.0.tgz", - "integrity": "sha512-gQpih+pbq3sP4uXltUeCSbPgZxTNp2gQd8639SaIbQMwgA6oJNHLhIART1fWy6DQACngiRzDVULA2x0ohmkGTQ==", - "dev": true, - "license": "MIT OR Apache-2.0", - "peer": true - }, - "node_modules/@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/trace-mapping": "0.3.9" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, - "node_modules/@emnapi/runtime": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.5.0.tgz", - "integrity": "sha512-97/BJ3iXHww3djw6hYIfErCZFee7qCtrneuLa20UXFCOTCfBM2cvQHjWJ2EG0s0MtdNwInarqCTz35i4wWXHsQ==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" + "node": ">=18" } }, - "node_modules/@esbuild/aix-ppc64": { + "node_modules/@esbuild/openbsd-arm64": { "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.10.tgz", - "integrity": "sha512-0NFWnA+7l41irNuaSVlLfgNT12caWJVLzp5eAVhZ0z1qpxbockccEt3s+149rE64VUI3Ml2zt8Nv5JVc4QXTsw==", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.10.tgz", + "integrity": "sha512-5Se0VM9Wtq797YFn+dLimf2Zx6McttsH2olUBsDml+lm0GOCRVebRWUvDtkY4BWYv/3NgzS8b/UM3jQNh5hYyw==", "cpu": [ - "ppc64" + "arm64" ], "license": "MIT", "optional": true, "os": [ - "aix" + "openbsd" ], "engines": { "node": ">=18" } }, - "node_modules/@esbuild/android-arm": { + "node_modules/@esbuild/openbsd-x64": { "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.10.tgz", - "integrity": "sha512-dQAxF1dW1C3zpeCDc5KqIYuZ1tgAdRXNoZP7vkBIRtKZPYe2xVr/d3SkirklCHudW1B45tGiUlz2pUWDfbDD4w==", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.10.tgz", + "integrity": "sha512-XkA4frq1TLj4bEMB+2HnI0+4RnjbuGZfet2gs/LNs5Hc7D89ZQBHQ0gL2ND6Lzu1+QVkjp3x1gIcPKzRNP8bXw==", "cpu": [ - "arm" + "x64" ], "license": "MIT", "optional": true, "os": [ - "android" + "openbsd" ], "engines": { "node": ">=18" } }, - "node_modules/@esbuild/android-arm64": { + "node_modules/@esbuild/openharmony-arm64": { "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.10.tgz", - "integrity": "sha512-LSQa7eDahypv/VO6WKohZGPSJDq5OVOo3UoFR1E4t4Gj1W7zEQMUhI+lo81H+DtB+kP+tDgBp+M4oNCwp6kffg==", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.10.tgz", + "integrity": "sha512-AVTSBhTX8Y/Fz6OmIVBip9tJzZEUcY8WLh7I59+upa5/GPhh2/aM6bvOMQySspnCCHvFi79kMtdJS1w0DXAeag==", "cpu": [ "arm64" ], "license": "MIT", "optional": true, "os": [ - "android" + "openharmony" ], "engines": { "node": ">=18" } }, - "node_modules/@esbuild/android-x64": { + "node_modules/@esbuild/sunos-x64": { "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.10.tgz", - "integrity": "sha512-MiC9CWdPrfhibcXwr39p9ha1x0lZJ9KaVfvzA0Wxwz9ETX4v5CHfF09bx935nHlhi+MxhA63dKRRQLiVgSUtEg==", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.10.tgz", + "integrity": "sha512-fswk3XT0Uf2pGJmOpDB7yknqhVkJQkAQOcW/ccVOtfx05LkbWOaRAtn5SaqXypeKQra1QaEa841PgrSL9ubSPQ==", "cpu": [ "x64" ], "license": "MIT", "optional": true, "os": [ - "android" + "sunos" ], "engines": { "node": ">=18" } }, - "node_modules/@esbuild/darwin-arm64": { + "node_modules/@esbuild/win32-arm64": { "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.10.tgz", - "integrity": "sha512-JC74bdXcQEpW9KkV326WpZZjLguSZ3DfS8wrrvPMHgQOIEIG/sPXEN/V8IssoJhbefLRcRqw6RQH2NnpdprtMA==", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.10.tgz", + "integrity": "sha512-ah+9b59KDTSfpaCg6VdJoOQvKjI33nTaQr4UluQwW7aEwZQsbMCfTmfEO4VyewOxx4RaDT/xCy9ra2GPWmO7Kw==", "cpu": [ "arm64" ], "license": "MIT", "optional": true, "os": [ - "darwin" + "win32" ], "engines": { "node": ">=18" } }, - "node_modules/@esbuild/darwin-x64": { + "node_modules/@esbuild/win32-ia32": { "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.10.tgz", - "integrity": "sha512-tguWg1olF6DGqzws97pKZ8G2L7Ig1vjDmGTwcTuYHbuU6TTjJe5FXbgs5C1BBzHbJ2bo1m3WkQDbWO2PvamRcg==", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.10.tgz", + "integrity": "sha512-QHPDbKkrGO8/cz9LKVnJU22HOi4pxZnZhhA2HYHez5Pz4JeffhDjf85E57Oyco163GnzNCVkZK0b/n4Y0UHcSw==", "cpu": [ - "x64" + "ia32" ], "license": "MIT", "optional": true, "os": [ - "darwin" + "win32" ], "engines": { "node": ">=18" } }, - "node_modules/@esbuild/freebsd-arm64": { + "node_modules/@esbuild/win32-x64": { "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.10.tgz", - "integrity": "sha512-3ZioSQSg1HT2N05YxeJWYR+Libe3bREVSdWhEEgExWaDtyFbbXWb49QgPvFH8u03vUPX10JhJPcz7s9t9+boWg==", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.10.tgz", + "integrity": "sha512-9KpxSVFCu0iK1owoez6aC/s/EdUQLDN3adTxGCqxMVhrPDj6bt5dbrHDXUuq+Bs2vATFBBrQS5vdQ/Ed2P+nbw==", "cpu": [ - "arm64" + "x64" ], "license": "MIT", "optional": true, "os": [ - "freebsd" + "win32" ], "engines": { "node": ">=18" } }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.10.tgz", - "integrity": "sha512-LLgJfHJk014Aa4anGDbh8bmI5Lk+QidDmGzuC2D+vP7mv/GeSN+H39zOf7pN5N8p059FcOfs2bVlrRr4SK9WxA==", + "node_modules/@fastify/busboy": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", + "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz", + "integrity": "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==", "cpu": [ - "x64" + "arm64" ], - "license": "MIT", + "dev": true, + "license": "Apache-2.0", "optional": true, "os": [ - "freebsd" + "darwin" ], "engines": { - "node": ">=18" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.0.4" } }, - "node_modules/@esbuild/linux-arm": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.10.tgz", - "integrity": "sha512-oR31GtBTFYCqEBALI9r6WxoU/ZofZl962pouZRTEYECvNF/dtXKku8YXcJkhgK/beU+zedXfIzHijSRapJY3vg==", + "node_modules/@img/sharp-darwin-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.5.tgz", + "integrity": "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==", "cpu": [ - "arm" + "x64" ], - "license": "MIT", + "dev": true, + "license": "Apache-2.0", "optional": true, "os": [ - "linux" + "darwin" ], "engines": { - "node": ">=18" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.0.4" } }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.10.tgz", - "integrity": "sha512-5luJWN6YKBsawd5f9i4+c+geYiVEw20FVW5x0v1kEMWNq8UctFjDiMATBxLvmmHA4bf7F6hTRaJgtghFr9iziQ==", + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.4.tgz", + "integrity": "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==", "cpu": [ "arm64" ], - "license": "MIT", + "dev": true, + "license": "LGPL-3.0-or-later", "optional": true, "os": [ - "linux" + "darwin" ], - "engines": { - "node": ">=18" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.10.tgz", - "integrity": "sha512-NrSCx2Kim3EnnWgS4Txn0QGt0Xipoumb6z6sUtl5bOEZIVKhzfyp/Lyw4C1DIYvzeW/5mWYPBFJU3a/8Yr75DQ==", + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.4.tgz", + "integrity": "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==", "cpu": [ - "ia32" + "x64" ], - "license": "MIT", + "dev": true, + "license": "LGPL-3.0-or-later", "optional": true, "os": [ - "linux" + "darwin" ], - "engines": { - "node": ">=18" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.10.tgz", - "integrity": "sha512-xoSphrd4AZda8+rUDDfD9J6FUMjrkTz8itpTITM4/xgerAZZcFW7Dv+sun7333IfKxGG8gAq+3NbfEMJfiY+Eg==", + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz", + "integrity": "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==", "cpu": [ - "loong64" + "arm" ], - "license": "MIT", + "dev": true, + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" ], - "engines": { - "node": ">=18" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.10.tgz", - "integrity": "sha512-ab6eiuCwoMmYDyTnyptoKkVS3k8fy/1Uvq7Dj5czXI6DF2GqD2ToInBI0SHOp5/X1BdZ26RKc5+qjQNGRBelRA==", + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz", + "integrity": "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==", "cpu": [ - "mips64el" + "arm64" ], - "license": "MIT", + "dev": true, + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" ], - "engines": { - "node": ">=18" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.10.tgz", - "integrity": "sha512-NLinzzOgZQsGpsTkEbdJTCanwA5/wozN9dSgEl12haXJBzMTpssebuXR42bthOF3z7zXFWH1AmvWunUCkBE4EA==", + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.4.tgz", + "integrity": "sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==", "cpu": [ - "ppc64" + "s390x" ], - "license": "MIT", + "dev": true, + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" ], - "engines": { - "node": ">=18" - } + "funding": { + "url": "https://opencollective.com/libvips" + } }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.10.tgz", - "integrity": "sha512-FE557XdZDrtX8NMIeA8LBJX3dC2M8VGXwfrQWU7LB5SLOajfJIxmSdyL/gU1m64Zs9CBKvm4UAuBp5aJ8OgnrA==", + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz", + "integrity": "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==", "cpu": [ - "riscv64" + "x64" ], - "license": "MIT", + "dev": true, + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" ], - "engines": { - "node": ">=18" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.10.tgz", - "integrity": "sha512-3BBSbgzuB9ajLoVZk0mGu+EHlBwkusRmeNYdqmznmMc9zGASFjSsxgkNsqmXugpPk00gJ0JNKh/97nxmjctdew==", + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.4.tgz", + "integrity": "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==", "cpu": [ - "s390x" + "arm64" ], - "license": "MIT", + "dev": true, + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" ], - "engines": { - "node": ">=18" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@esbuild/linux-x64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.10.tgz", - "integrity": "sha512-QSX81KhFoZGwenVyPoberggdW1nrQZSvfVDAIUXr3WqLRZGZqWk/P4T8p2SP+de2Sr5HPcvjhcJzEiulKgnxtA==", + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.4.tgz", + "integrity": "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==", "cpu": [ "x64" ], - "license": "MIT", + "dev": true, + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" ], - "engines": { - "node": ">=18" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.10.tgz", - "integrity": "sha512-AKQM3gfYfSW8XRk8DdMCzaLUFB15dTrZfnX8WXQoOUpUBQ+NaAFCP1kPS/ykbbGYz7rxn0WS48/81l9hFl3u4A==", + "node_modules/@img/sharp-linux-arm": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz", + "integrity": "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==", "cpu": [ - "arm64" + "arm" ], - "license": "MIT", + "dev": true, + "license": "Apache-2.0", "optional": true, "os": [ - "netbsd" + "linux" ], "engines": { - "node": ">=18" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.0.5" } }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.10.tgz", - "integrity": "sha512-7RTytDPGU6fek/hWuN9qQpeGPBZFfB4zZgcz2VK2Z5VpdUxEI8JKYsg3JfO0n/Z1E/6l05n0unDCNc4HnhQGig==", + "node_modules/@img/sharp-linux-arm64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz", + "integrity": "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==", "cpu": [ - "x64" + "arm64" ], - "license": "MIT", + "dev": true, + "license": "Apache-2.0", "optional": true, "os": [ - "netbsd" + "linux" ], "engines": { - "node": ">=18" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.0.4" } }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.10.tgz", - "integrity": "sha512-5Se0VM9Wtq797YFn+dLimf2Zx6McttsH2olUBsDml+lm0GOCRVebRWUvDtkY4BWYv/3NgzS8b/UM3jQNh5hYyw==", + "node_modules/@img/sharp-linux-s390x": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.5.tgz", + "integrity": "sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==", "cpu": [ - "arm64" + "s390x" ], - "license": "MIT", + "dev": true, + "license": "Apache-2.0", "optional": true, "os": [ - "openbsd" + "linux" ], "engines": { - "node": ">=18" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.0.4" } }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.10.tgz", - "integrity": "sha512-XkA4frq1TLj4bEMB+2HnI0+4RnjbuGZfet2gs/LNs5Hc7D89ZQBHQ0gL2ND6Lzu1+QVkjp3x1gIcPKzRNP8bXw==", + "node_modules/@img/sharp-linux-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz", + "integrity": "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==", "cpu": [ "x64" ], - "license": "MIT", + "dev": true, + "license": "Apache-2.0", "optional": true, "os": [ - "openbsd" + "linux" ], "engines": { - "node": ">=18" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.0.4" } }, - "node_modules/@esbuild/openharmony-arm64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.10.tgz", - "integrity": "sha512-AVTSBhTX8Y/Fz6OmIVBip9tJzZEUcY8WLh7I59+upa5/GPhh2/aM6bvOMQySspnCCHvFi79kMtdJS1w0DXAeag==", + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.5.tgz", + "integrity": "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==", "cpu": [ "arm64" ], - "license": "MIT", + "dev": true, + "license": "Apache-2.0", "optional": true, "os": [ - "openharmony" + "linux" ], "engines": { - "node": ">=18" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.0.4" } }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.10.tgz", - "integrity": "sha512-fswk3XT0Uf2pGJmOpDB7yknqhVkJQkAQOcW/ccVOtfx05LkbWOaRAtn5SaqXypeKQra1QaEa841PgrSL9ubSPQ==", + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.5.tgz", + "integrity": "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==", "cpu": [ "x64" ], - "license": "MIT", + "dev": true, + "license": "Apache-2.0", "optional": true, "os": [ - "sunos" + "linux" ], "engines": { - "node": ">=18" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.0.4" } }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.10.tgz", - "integrity": "sha512-ah+9b59KDTSfpaCg6VdJoOQvKjI33nTaQr4UluQwW7aEwZQsbMCfTmfEO4VyewOxx4RaDT/xCy9ra2GPWmO7Kw==", + "node_modules/@img/sharp-wasm32": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.33.5.tgz", + "integrity": "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==", "cpu": [ - "arm64" + "wasm32" ], - "license": "MIT", + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", "optional": true, - "os": [ - "win32" - ], + "dependencies": { + "@emnapi/runtime": "^1.2.0" + }, "engines": { - "node": ">=18" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.10.tgz", - "integrity": "sha512-QHPDbKkrGO8/cz9LKVnJU22HOi4pxZnZhhA2HYHez5Pz4JeffhDjf85E57Oyco163GnzNCVkZK0b/n4Y0UHcSw==", + "node_modules/@img/sharp-win32-ia32": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.5.tgz", + "integrity": "sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==", "cpu": [ "ia32" ], - "license": "MIT", + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later", "optional": true, "os": [ "win32" ], "engines": { - "node": ">=18" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@esbuild/win32-x64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.10.tgz", - "integrity": "sha512-9KpxSVFCu0iK1owoez6aC/s/EdUQLDN3adTxGCqxMVhrPDj6bt5dbrHDXUuq+Bs2vATFBBrQS5vdQ/Ed2P+nbw==", + "node_modules/@img/sharp-win32-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz", + "integrity": "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==", "cpu": [ "x64" ], - "license": "MIT", + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later", "optional": true, "os": [ "win32" ], "engines": { - "node": ">=18" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@fastify/busboy": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", - "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", + "node_modules/@inquirer/external-editor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@inquirer/external-editor/-/external-editor-1.0.2.tgz", + "integrity": "sha512-yy9cOoBnx58TlsPrIxauKIFQTiyH+0MK4e97y4sV9ERbI+zDxw7i2hxHLCIEGIE/8PPvDxGhgzIOTSOWcs6/MQ==", "dev": true, "license": "MIT", + "dependencies": { + "chardet": "^2.1.0", + "iconv-lite": "^0.7.0" + }, "engines": { - "node": ">=14" - } - }, - "node_modules/@img/sharp-darwin-arm64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz", - "integrity": "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": ">=18" }, - "funding": { - "url": "https://opencollective.com/libvips" + "peerDependencies": { + "@types/node": ">=18" }, - "optionalDependencies": { - "@img/sharp-libvips-darwin-arm64": "1.0.4" + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@img/sharp-darwin-x64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.5.tgz", - "integrity": "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==", - "cpu": [ - "x64" - ], + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" }, - "optionalDependencies": { - "@img/sharp-libvips-darwin-x64": "1.0.4" + "engines": { + "node": ">=12" } }, - "node_modules/@img/sharp-libvips-darwin-arm64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.4.tgz", - "integrity": "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==", - "cpu": [ - "arm64" - ], + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", "dev": true, - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "darwin" - ], + "license": "MIT", + "engines": { + "node": ">=12" + }, "funding": { - "url": "https://opencollective.com/libvips" + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/@img/sharp-libvips-darwin-x64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.4.tgz", - "integrity": "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==", - "cpu": [ - "x64" - ], + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", "dev": true, - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "darwin" - ], + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, "funding": { - "url": "https://opencollective.com/libvips" + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/@img/sharp-libvips-linux-arm": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz", - "integrity": "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==", - "cpu": [ - "arm" - ], + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", "dev": true, - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" } }, - "node_modules/@img/sharp-libvips-linux-arm64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz", - "integrity": "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==", - "cpu": [ - "arm64" - ], + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", "dev": true, - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" } }, - "node_modules/@img/sharp-libvips-linux-s390x": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.4.tgz", - "integrity": "sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==", - "cpu": [ - "s390x" - ], + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "dev": true, - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" + "license": "MIT", + "engines": { + "node": ">=6.0.0" } }, - "node_modules/@img/sharp-libvips-linux-x64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz", - "integrity": "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==", - "cpu": [ - "x64" - ], + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", "dev": true, - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } + "license": "MIT" }, - "node_modules/@img/sharp-libvips-linuxmusl-arm64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.4.tgz", - "integrity": "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==", - "cpu": [ - "arm64" - ], + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", "dev": true, - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@img/sharp-libvips-linuxmusl-x64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.4.tgz", - "integrity": "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==", - "cpu": [ - "x64" - ], + "node_modules/@jsdevtools/ez-spawn": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@jsdevtools/ez-spawn/-/ez-spawn-3.0.4.tgz", + "integrity": "sha512-f5DRIOZf7wxogefH03RjMPMdBF7ADTWUMoOs9kaJo06EfwF+aFhMZMDZxHg/Xe12hptN9xoZjGso2fdjapBRIA==", "dev": true, - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" + "license": "MIT", + "dependencies": { + "call-me-maybe": "^1.0.1", + "cross-spawn": "^7.0.3", + "string-argv": "^0.3.1", + "type-detect": "^4.0.8" + }, + "engines": { + "node": ">=10" } }, - "node_modules/@img/sharp-linux-arm": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz", - "integrity": "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==", - "cpu": [ - "arm" - ], + "node_modules/@manypkg/find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@manypkg/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==", "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-arm": "1.0.5" + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.5.5", + "@types/node": "^12.7.1", + "find-up": "^4.1.0", + "fs-extra": "^8.1.0" } }, - "node_modules/@img/sharp-linux-arm64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz", - "integrity": "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==", - "cpu": [ - "arm64" - ], + "node_modules/@manypkg/find-root/node_modules/@types/node": { + "version": "12.20.55", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz", + "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==", "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-arm64": "1.0.4" - } + "license": "MIT" }, - "node_modules/@img/sharp-linux-s390x": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.5.tgz", - "integrity": "sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==", - "cpu": [ - "s390x" - ], + "node_modules/@manypkg/find-root/node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" }, - "optionalDependencies": { - "@img/sharp-libvips-linux-s390x": "1.0.4" + "engines": { + "node": ">=6 <7 || >=8" } }, - "node_modules/@img/sharp-linux-x64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz", - "integrity": "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==", - "cpu": [ - "x64" - ], + "node_modules/@manypkg/get-packages": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@manypkg/get-packages/-/get-packages-1.1.3.tgz", + "integrity": "sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A==", "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-x64": "1.0.4" + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.5.5", + "@changesets/types": "^4.0.1", + "@manypkg/find-root": "^1.1.0", + "fs-extra": "^8.1.0", + "globby": "^11.0.0", + "read-yaml-file": "^1.1.0" } }, - "node_modules/@img/sharp-linuxmusl-arm64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.5.tgz", - "integrity": "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==", - "cpu": [ - "arm64" - ], + "node_modules/@manypkg/get-packages/node_modules/@changesets/types": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@changesets/types/-/types-4.1.0.tgz", + "integrity": "sha512-LDQvVDv5Kb50ny2s25Fhm3d9QSZimsoUGBsUioj6MC3qbMUCuC8GPIvk/M6IvXx3lYhAs0lwWUQLb+VIEUCECw==", "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-arm64": "1.0.4" - } + "license": "MIT" }, - "node_modules/@img/sharp-linuxmusl-x64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.5.tgz", - "integrity": "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==", - "cpu": [ - "x64" - ], + "node_modules/@manypkg/get-packages/node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" }, - "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-x64": "1.0.4" + "engines": { + "node": ">=6 <7 || >=8" } }, - "node_modules/@img/sharp-wasm32": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.33.5.tgz", - "integrity": "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==", - "cpu": [ - "wasm32" - ], + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, - "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", - "optional": true, + "license": "MIT", "dependencies": { - "@emnapi/runtime": "^1.2.0" + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" }, "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" + "node": ">= 8" } }, - "node_modules/@img/sharp-win32-ia32": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.5.tgz", - "integrity": "sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==", - "cpu": [ - "ia32" - ], + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, - "license": "Apache-2.0 AND LGPL-3.0-or-later", - "optional": true, - "os": [ - "win32" - ], + "license": "MIT", "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" + "node": ">= 8" } }, - "node_modules/@img/sharp-win32-x64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz", - "integrity": "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==", - "cpu": [ - "x64" - ], + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, - "license": "Apache-2.0 AND LGPL-3.0-or-later", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" }, - "funding": { - "url": "https://opencollective.com/libvips" + "engines": { + "node": ">= 8" } }, - "node_modules/@inquirer/external-editor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@inquirer/external-editor/-/external-editor-1.0.2.tgz", - "integrity": "sha512-yy9cOoBnx58TlsPrIxauKIFQTiyH+0MK4e97y4sV9ERbI+zDxw7i2hxHLCIEGIE/8PPvDxGhgzIOTSOWcs6/MQ==", + "node_modules/@octokit/action": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@octokit/action/-/action-6.1.0.tgz", + "integrity": "sha512-lo+nHx8kAV86bxvOVOI3vFjX3gXPd/L7guAUbvs3pUvnR2KC+R7yjBkA1uACt4gYhs4LcWP3AXSGQzsbeN2XXw==", "dev": true, "license": "MIT", "dependencies": { - "chardet": "^2.1.0", - "iconv-lite": "^0.7.0" + "@octokit/auth-action": "^4.0.0", + "@octokit/core": "^5.0.0", + "@octokit/plugin-paginate-rest": "^9.0.0", + "@octokit/plugin-rest-endpoint-methods": "^10.0.0", + "@octokit/types": "^12.0.0", + "undici": "^6.0.0" }, "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", - "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.13", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", - "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/remapping": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", - "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "dev": true, - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.31", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", - "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@jsdevtools/ez-spawn": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@jsdevtools/ez-spawn/-/ez-spawn-3.0.4.tgz", - "integrity": "sha512-f5DRIOZf7wxogefH03RjMPMdBF7ADTWUMoOs9kaJo06EfwF+aFhMZMDZxHg/Xe12hptN9xoZjGso2fdjapBRIA==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-me-maybe": "^1.0.1", - "cross-spawn": "^7.0.3", - "string-argv": "^0.3.1", - "type-detect": "^4.0.8" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@manypkg/find-root": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@manypkg/find-root/-/find-root-1.1.0.tgz", - "integrity": "sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.5.5", - "@types/node": "^12.7.1", - "find-up": "^4.1.0", - "fs-extra": "^8.1.0" - } - }, - "node_modules/@manypkg/find-root/node_modules/@types/node": { - "version": "12.20.55", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz", - "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@manypkg/find-root/node_modules/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, - "node_modules/@manypkg/get-packages": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@manypkg/get-packages/-/get-packages-1.1.3.tgz", - "integrity": "sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.5.5", - "@changesets/types": "^4.0.1", - "@manypkg/find-root": "^1.1.0", - "fs-extra": "^8.1.0", - "globby": "^11.0.0", - "read-yaml-file": "^1.1.0" - } - }, - "node_modules/@manypkg/get-packages/node_modules/@changesets/types": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@changesets/types/-/types-4.1.0.tgz", - "integrity": "sha512-LDQvVDv5Kb50ny2s25Fhm3d9QSZimsoUGBsUioj6MC3qbMUCuC8GPIvk/M6IvXx3lYhAs0lwWUQLb+VIEUCECw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@manypkg/get-packages/node_modules/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@octokit/action": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@octokit/action/-/action-6.1.0.tgz", - "integrity": "sha512-lo+nHx8kAV86bxvOVOI3vFjX3gXPd/L7guAUbvs3pUvnR2KC+R7yjBkA1uACt4gYhs4LcWP3AXSGQzsbeN2XXw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@octokit/auth-action": "^4.0.0", - "@octokit/core": "^5.0.0", - "@octokit/plugin-paginate-rest": "^9.0.0", - "@octokit/plugin-rest-endpoint-methods": "^10.0.0", - "@octokit/types": "^12.0.0", - "undici": "^6.0.0" - }, - "engines": { - "node": ">= 18" + "node": ">= 18" } }, "node_modules/@octokit/action/node_modules/undici": { @@ -2758,7 +2235,6 @@ "integrity": "sha512-/g2d4sW9nUDJOMz3mabVQvOGhVa4e/BN/Um7yca9Bb2XTzPPnfTWHWQg+IsEYO7M3Vx+EXvaM/I2pJWIMun1bg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@octokit/auth-token": "^4.0.0", "@octokit/graphql": "^7.1.0", @@ -3020,6 +2496,10 @@ "dev": true, "license": "MIT" }, + "node_modules/@repo/integration": { + "resolved": "tests/integration", + "link": true + }, "node_modules/@repo/sandbox-container": { "resolved": "packages/sandbox-container", "link": true @@ -3472,6 +2952,15 @@ "@types/unist": "*" } }, + "node_modules/@types/mdast": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", + "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, "node_modules/@types/ms": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", @@ -3493,7 +2982,6 @@ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.0.tgz", "integrity": "sha512-1LOH8xovvsKsCBq1wnT4ntDUdCJKmnEakhsuoUSy6ExlHCkGP2hqnatagYTgFk6oeL0VU31u7SNjunPN+GchtA==", "license": "MIT", - "peer": true, "dependencies": { "csstype": "^3.0.2" } @@ -3519,9 +3007,9 @@ } }, "node_modules/@types/unist": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", - "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", "license": "MIT" }, "node_modules/@types/whatwg-mimetype": { @@ -3631,7 +3119,6 @@ "integrity": "sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@vitest/utils": "3.2.4", "pathe": "^2.0.3", @@ -3647,7 +3134,6 @@ "integrity": "sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@vitest/pretty-format": "3.2.4", "magic-string": "^0.30.17", @@ -3676,7 +3162,6 @@ "integrity": "sha512-hGISOaP18plkzbWEcP/QvtRW1xDXF2+96HbEX6byqQhAUbiS5oH6/9JwW+QsQCIYON2bI6QZBF+2PvOmrRZ9wA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@vitest/utils": "3.2.4", "fflate": "^0.8.2", @@ -3801,6 +3286,16 @@ "node": ">=12" } }, + "node_modules/bail": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", + "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -3898,7 +3393,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "baseline-browser-mapping": "^2.8.9", "caniuse-lite": "^1.0.30001746", @@ -3980,6 +3474,16 @@ ], "license": "CC-BY-4.0" }, + "node_modules/ccount": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/chai": { "version": "5.3.3", "resolved": "https://registry.npmjs.org/chai/-/chai-5.3.3.tgz", @@ -4387,7 +3891,6 @@ "integrity": "sha512-9RiGKvCwaqxO2owP61uQ4BgNborAQskMR6QusfWzQqv7AZOg5oGehdY2pRJMTKuwxd1IDBP4rSbI5lHzU7SMsQ==", "hasInstallScript": true, "license": "MIT", - "peer": true, "bin": { "esbuild": "bin/esbuild" }, @@ -4433,6 +3936,18 @@ "node": ">=6" } }, + "node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", @@ -4814,39 +4329,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/hast-util-to-jsx-runtime/node_modules/@types/unist": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", - "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", - "license": "MIT" - }, - "node_modules/hast-util-to-jsx-runtime/node_modules/unist-util-stringify-position": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", - "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-to-jsx-runtime/node_modules/vfile-message": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz", - "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-stringify-position": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/hast-util-whitespace": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", @@ -4963,6 +4445,18 @@ "node": ">=0.12.0" } }, + "node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-subdir": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/is-subdir/-/is-subdir-1.2.0.tgz", @@ -5180,11 +4674,22 @@ "dev": true, "license": "MIT" }, + "node_modules/longest-streak": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", + "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", "license": "MIT", + "peer": true, "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" }, @@ -5219,49 +4724,33 @@ "@jridgewell/sourcemap-codec": "^1.5.5" } }, - "node_modules/mdast-util-gfm-footnote": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.1.0.tgz", - "integrity": "sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==", + "node_modules/markdown-table": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz", + "integrity": "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==", "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "devlop": "^1.1.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0" - }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/mdast-util-gfm-footnote/node_modules/@types/mdast": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", - "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", + "node_modules/mdast-util-find-and-replace": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.2.tgz", + "integrity": "sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==", "license": "MIT", "dependencies": { - "@types/unist": "*" - } - }, - "node_modules/mdast-util-gfm-footnote/node_modules/@types/unist": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", - "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", - "license": "MIT" - }, - "node_modules/mdast-util-gfm-footnote/node_modules/longest-streak": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", - "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", - "license": "MIT", + "@types/mdast": "^4.0.0", + "escape-string-regexp": "^5.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/mdast-util-gfm-footnote/node_modules/mdast-util-from-markdown": { + "node_modules/mdast-util-from-markdown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz", "integrity": "sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==", @@ -5285,96 +4774,105 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/mdast-util-gfm-footnote/node_modules/mdast-util-to-markdown": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz", - "integrity": "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==", + "node_modules/mdast-util-gfm": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-3.1.0.tgz", + "integrity": "sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==", + "license": "MIT", + "dependencies": { + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-gfm-autolink-literal": "^2.0.0", + "mdast-util-gfm-footnote": "^2.0.0", + "mdast-util-gfm-strikethrough": "^2.0.0", + "mdast-util-gfm-table": "^2.0.0", + "mdast-util-gfm-task-list-item": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-autolink-literal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-2.0.1.tgz", + "integrity": "sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==", "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "longest-streak": "^3.0.0", - "mdast-util-phrasing": "^4.0.0", - "mdast-util-to-string": "^4.0.0", - "micromark-util-classify-character": "^2.0.0", - "micromark-util-decode-string": "^2.0.0", - "unist-util-visit": "^5.0.0", - "zwitch": "^2.0.0" + "ccount": "^2.0.0", + "devlop": "^1.0.0", + "mdast-util-find-and-replace": "^3.0.0", + "micromark-util-character": "^2.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/mdast-util-gfm-footnote/node_modules/mdast-util-to-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", - "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", + "node_modules/mdast-util-gfm-footnote": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.1.0.tgz", + "integrity": "sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==", "license": "MIT", "dependencies": { - "@types/mdast": "^4.0.0" + "@types/mdast": "^4.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/mdast-util-gfm-footnote/node_modules/micromark": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz", - "integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], + "node_modules/mdast-util-gfm-strikethrough": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-2.0.0.tgz", + "integrity": "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==", "license": "MIT", "dependencies": { - "@types/debug": "^4.0.0", - "debug": "^4.0.0", - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "micromark-core-commonmark": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-combine-extensions": "^2.0.0", - "micromark-util-decode-numeric-character-reference": "^2.0.0", - "micromark-util-encode": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-resolve-all": "^2.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "micromark-util-subtokenize": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/mdast-util-gfm-footnote/node_modules/unist-util-stringify-position": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", - "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "node_modules/mdast-util-gfm-table": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-2.0.0.tgz", + "integrity": "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==", "license": "MIT", "dependencies": { - "@types/unist": "^3.0.0" + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "markdown-table": "^3.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/mdast-util-gfm-footnote/node_modules/zwitch": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", - "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", + "node_modules/mdast-util-gfm-task-list-item": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.0.tgz", + "integrity": "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==", "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, "node_modules/mdast-util-mdx-expression": { @@ -5395,151 +4893,10 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/mdast-util-mdx-expression/node_modules/@types/mdast": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", - "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", - "license": "MIT", - "dependencies": { - "@types/unist": "*" - } - }, - "node_modules/mdast-util-mdx-expression/node_modules/@types/unist": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", - "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", - "license": "MIT" - }, - "node_modules/mdast-util-mdx-expression/node_modules/longest-streak": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", - "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/mdast-util-mdx-expression/node_modules/mdast-util-from-markdown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz", - "integrity": "sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "mdast-util-to-string": "^4.0.0", - "micromark": "^4.0.0", - "micromark-util-decode-numeric-character-reference": "^2.0.0", - "micromark-util-decode-string": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0", - "unist-util-stringify-position": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-mdx-expression/node_modules/mdast-util-to-markdown": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz", - "integrity": "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "longest-streak": "^3.0.0", - "mdast-util-phrasing": "^4.0.0", - "mdast-util-to-string": "^4.0.0", - "micromark-util-classify-character": "^2.0.0", - "micromark-util-decode-string": "^2.0.0", - "unist-util-visit": "^5.0.0", - "zwitch": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-mdx-expression/node_modules/mdast-util-to-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", - "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-mdx-expression/node_modules/micromark": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz", - "integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "@types/debug": "^4.0.0", - "debug": "^4.0.0", - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "micromark-core-commonmark": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-combine-extensions": "^2.0.0", - "micromark-util-decode-numeric-character-reference": "^2.0.0", - "micromark-util-encode": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-resolve-all": "^2.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "micromark-util-subtokenize": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/mdast-util-mdx-expression/node_modules/unist-util-stringify-position": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", - "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-mdx-expression/node_modules/zwitch": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", - "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/mdast-util-mdx-jsx": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.2.0.tgz", - "integrity": "sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==", + "node_modules/mdast-util-mdx-jsx": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.2.0.tgz", + "integrity": "sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==", "license": "MIT", "dependencies": { "@types/estree-jsx": "^1.0.0", @@ -5560,31 +4917,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/mdast-util-mdx-jsx/node_modules/@types/mdast": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", - "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", - "license": "MIT", - "dependencies": { - "@types/unist": "*" - } - }, - "node_modules/mdast-util-mdx-jsx/node_modules/@types/unist": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", - "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", - "license": "MIT" - }, - "node_modules/mdast-util-mdx-jsx/node_modules/ccount": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", - "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, "node_modules/mdast-util-mdx-jsx/node_modules/character-entities-legacy": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", @@ -5649,41 +4981,85 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/mdast-util-mdx-jsx/node_modules/longest-streak": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", - "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", + "node_modules/mdast-util-mdx-jsx/node_modules/parse-entities": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz", + "integrity": "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==", "license": "MIT", + "dependencies": { + "@types/unist": "^2.0.0", + "character-entities-legacy": "^3.0.0", + "character-reference-invalid": "^2.0.0", + "decode-named-character-reference": "^1.0.0", + "is-alphanumerical": "^2.0.0", + "is-decimal": "^2.0.0", + "is-hexadecimal": "^2.0.0" + }, "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/mdast-util-mdx-jsx/node_modules/mdast-util-from-markdown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz", - "integrity": "sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==", + "node_modules/mdast-util-mdx-jsx/node_modules/parse-entities/node_modules/@types/unist": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", + "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", + "license": "MIT" + }, + "node_modules/mdast-util-mdxjs-esm": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz", + "integrity": "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==", "license": "MIT", "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "decode-named-character-reference": "^1.0.0", "devlop": "^1.0.0", - "mdast-util-to-string": "^4.0.0", - "micromark": "^4.0.0", - "micromark-util-decode-numeric-character-reference": "^2.0.0", - "micromark-util-decode-string": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0", - "unist-util-stringify-position": "^4.0.0" + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-phrasing": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", + "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-hast": { + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz", + "integrity": "sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@ungap/structured-clone": "^1.0.0", + "devlop": "^1.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "trim-lines": "^3.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/mdast-util-mdx-jsx/node_modules/mdast-util-to-markdown": { + "node_modules/mdast-util-to-markdown": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz", "integrity": "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==", @@ -5704,7 +5080,7 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/mdast-util-mdx-jsx/node_modules/mdast-util-to-string": { + "node_modules/mdast-util-to-string": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", @@ -5717,7 +5093,17 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/mdast-util-mdx-jsx/node_modules/micromark": { + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromark": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz", "integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==", @@ -5752,173 +5138,165 @@ "micromark-util-types": "^2.0.0" } }, - "node_modules/mdast-util-mdx-jsx/node_modules/parse-entities": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz", - "integrity": "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==", - "license": "MIT", - "dependencies": { - "@types/unist": "^2.0.0", - "character-entities-legacy": "^3.0.0", - "character-reference-invalid": "^2.0.0", - "decode-named-character-reference": "^1.0.0", - "is-alphanumerical": "^2.0.0", - "is-decimal": "^2.0.0", - "is-hexadecimal": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "node_modules/micromark-core-commonmark": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.3.tgz", + "integrity": "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-destination": "^2.0.0", + "micromark-factory-label": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-factory-title": "^2.0.0", + "micromark-factory-whitespace": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-html-tag-name": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" } }, - "node_modules/mdast-util-mdx-jsx/node_modules/parse-entities/node_modules/@types/unist": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", - "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", - "license": "MIT" - }, - "node_modules/mdast-util-mdx-jsx/node_modules/unist-util-stringify-position": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", - "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "node_modules/micromark-extension-gfm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz", + "integrity": "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==", "license": "MIT", "dependencies": { - "@types/unist": "^3.0.0" + "micromark-extension-gfm-autolink-literal": "^2.0.0", + "micromark-extension-gfm-footnote": "^2.0.0", + "micromark-extension-gfm-strikethrough": "^2.0.0", + "micromark-extension-gfm-table": "^2.0.0", + "micromark-extension-gfm-tagfilter": "^2.0.0", + "micromark-extension-gfm-task-list-item": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-types": "^2.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/mdast-util-mdx-jsx/node_modules/vfile-message": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz", - "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", + "node_modules/micromark-extension-gfm-autolink-literal": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz", + "integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==", "license": "MIT", "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-stringify-position": "^4.0.0" + "micromark-util-character": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/mdast-util-mdx-jsx/node_modules/zwitch": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", - "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/mdast-util-mdxjs-esm": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz", - "integrity": "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==", + "node_modules/micromark-extension-gfm-footnote": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz", + "integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==", "license": "MIT", "dependencies": { - "@types/estree-jsx": "^1.0.0", - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", "devlop": "^1.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/mdast-util-mdxjs-esm/node_modules/@types/mdast": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", - "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", + "node_modules/micromark-extension-gfm-strikethrough": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.1.0.tgz", + "integrity": "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==", "license": "MIT", "dependencies": { - "@types/unist": "*" - } - }, - "node_modules/mdast-util-mdxjs-esm/node_modules/@types/unist": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", - "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", - "license": "MIT" - }, - "node_modules/mdast-util-mdxjs-esm/node_modules/longest-streak": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", - "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", - "license": "MIT", + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/mdast-util-mdxjs-esm/node_modules/mdast-util-from-markdown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz", - "integrity": "sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==", + "node_modules/micromark-extension-gfm-table": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.1.tgz", + "integrity": "sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==", "license": "MIT", "dependencies": { - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "decode-named-character-reference": "^1.0.0", "devlop": "^1.0.0", - "mdast-util-to-string": "^4.0.0", - "micromark": "^4.0.0", - "micromark-util-decode-numeric-character-reference": "^2.0.0", - "micromark-util-decode-string": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0", - "unist-util-stringify-position": "^4.0.0" + "micromark-util-types": "^2.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/mdast-util-mdxjs-esm/node_modules/mdast-util-to-markdown": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz", - "integrity": "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==", + "node_modules/micromark-extension-gfm-tagfilter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz", + "integrity": "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==", "license": "MIT", "dependencies": { - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "longest-streak": "^3.0.0", - "mdast-util-phrasing": "^4.0.0", - "mdast-util-to-string": "^4.0.0", - "micromark-util-classify-character": "^2.0.0", - "micromark-util-decode-string": "^2.0.0", - "unist-util-visit": "^5.0.0", - "zwitch": "^2.0.0" + "micromark-util-types": "^2.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/mdast-util-mdxjs-esm/node_modules/mdast-util-to-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", - "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", + "node_modules/micromark-extension-gfm-task-list-item": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.1.0.tgz", + "integrity": "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==", "license": "MIT", "dependencies": { - "@types/mdast": "^4.0.0" + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/mdast-util-mdxjs-esm/node_modules/micromark": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz", - "integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==", + "node_modules/micromark-factory-destination": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz", + "integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==", "funding": [ { "type": "GitHub Sponsors", @@ -5931,292 +5309,51 @@ ], "license": "MIT", "dependencies": { - "@types/debug": "^4.0.0", - "debug": "^4.0.0", - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "micromark-core-commonmark": "^2.0.0", - "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-combine-extensions": "^2.0.0", - "micromark-util-decode-numeric-character-reference": "^2.0.0", - "micromark-util-encode": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-resolve-all": "^2.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "micromark-util-subtokenize": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, - "node_modules/mdast-util-mdxjs-esm/node_modules/unist-util-stringify-position": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", - "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "node_modules/micromark-factory-label": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz", + "integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], "license": "MIT", "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-mdxjs-esm/node_modules/zwitch": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", - "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "devlop": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" } }, - "node_modules/mdast-util-phrasing": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", - "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", + "node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], "license": "MIT", "dependencies": { - "@types/mdast": "^4.0.0", - "unist-util-is": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-phrasing/node_modules/@types/mdast": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", - "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", - "license": "MIT", - "dependencies": { - "@types/unist": "*" - } - }, - "node_modules/mdast-util-phrasing/node_modules/@types/unist": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", - "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", - "license": "MIT" - }, - "node_modules/mdast-util-phrasing/node_modules/unist-util-is": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", - "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-to-hast": { - "version": "13.2.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz", - "integrity": "sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "@ungap/structured-clone": "^1.0.0", - "devlop": "^1.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "trim-lines": "^3.0.0", - "unist-util-position": "^5.0.0", - "unist-util-visit": "^5.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-to-hast/node_modules/@types/mdast": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", - "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", - "license": "MIT", - "dependencies": { - "@types/unist": "*" - } - }, - "node_modules/mdast-util-to-hast/node_modules/@types/unist": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", - "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", - "license": "MIT" - }, - "node_modules/mdast-util-to-hast/node_modules/unist-util-stringify-position": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", - "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-to-hast/node_modules/vfile": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", - "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "vfile-message": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-to-hast/node_modules/vfile-message": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz", - "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-stringify-position": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromark-core-commonmark": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.3.tgz", - "integrity": "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "micromark-factory-destination": "^2.0.0", - "micromark-factory-label": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-factory-title": "^2.0.0", - "micromark-factory-whitespace": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-classify-character": "^2.0.0", - "micromark-util-html-tag-name": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-resolve-all": "^2.0.0", - "micromark-util-subtokenize": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-extension-gfm-footnote": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz", - "integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==", - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-core-commonmark": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-factory-destination": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz", - "integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-label": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz", - "integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-space": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", - "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-types": "^2.0.0" + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" } }, "node_modules/micromark-factory-title": { @@ -6510,1343 +5647,892 @@ "type": "OpenCollective", "url": "https://opencollective.com/unified" } - ], - "license": "MIT" - }, - "node_modules/micromark-util-types": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz", - "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dev": true, - "license": "MIT", - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mime": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", - "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", - "dev": true, - "license": "MIT", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/miniflare": { - "version": "4.20251008.0", - "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-4.20251008.0.tgz", - "integrity": "sha512-sKCNYNzXG6l8qg0Oo7y8WcDKcpbgw0qwZsxNpdZilFTR4EavRow2TlcwuPSVN99jqAjhz0M4VXvTdSGdtJ2VfQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@cspotcode/source-map-support": "0.8.1", - "acorn": "8.14.0", - "acorn-walk": "8.3.2", - "exit-hook": "2.2.1", - "glob-to-regexp": "0.4.1", - "sharp": "^0.33.5", - "stoppable": "1.1.0", - "undici": "7.14.0", - "workerd": "1.20251008.0", - "ws": "8.18.0", - "youch": "4.1.0-beta.10", - "zod": "3.22.3" - }, - "bin": { - "miniflare": "bootstrap.js" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/miniflare/node_modules/ws": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", - "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/miniflare/node_modules/zod": { - "version": "3.22.3", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.3.tgz", - "integrity": "sha512-EjIevzuJRiRPbVH4mGc8nApb/lVLKVpmUhAaR5R5doKGfAnGJ6Gr3CViAVjP+4FWSxCsybeWQdcgCtbX+7oZug==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - }, - "node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/mlly": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.8.0.tgz", - "integrity": "sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "acorn": "^8.15.0", - "pathe": "^2.0.3", - "pkg-types": "^1.3.1", - "ufo": "^1.6.1" - } - }, - "node_modules/mlly/node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", - "dev": true, - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/mri": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", - "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/mrmime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", - "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "license": "MIT" - }, - "node_modules/mz": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", - "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "any-promise": "^1.0.0", - "object-assign": "^4.0.1", - "thenify-all": "^1.0.0" - } - }, - "node_modules/nanoid": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "dev": true, - "license": "MIT", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/node-releases": { - "version": "2.0.23", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.23.tgz", - "integrity": "sha512-cCmFDMSm26S6tQSDpBCg/NR8NENrVPhAJSf+XbxBG4rPFaaonlEoE9wHQmun+cls499TQGSb7ZyPBRlzgKfpeg==", - "dev": true, - "license": "MIT" - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ohash": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz", - "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "license": "ISC", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/openai": { - "version": "5.23.2", - "resolved": "https://registry.npmjs.org/openai/-/openai-5.23.2.tgz", - "integrity": "sha512-MQBzmTulj+MM5O8SKEk/gL8a7s5mktS9zUtAkU257WjvobGc9nKcBuVwjyEEcb9SI8a8Y2G/mzn3vm9n1Jlleg==", - "license": "Apache-2.0", - "bin": { - "openai": "bin/cli" - }, - "peerDependencies": { - "ws": "^8.18.0", - "zod": "^3.23.8" - }, - "peerDependenciesMeta": { - "ws": { - "optional": true - }, - "zod": { - "optional": true - } - } - }, - "node_modules/outdent": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/outdent/-/outdent-0.5.0.tgz", - "integrity": "sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/p-filter": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-filter/-/p-filter-2.1.0.tgz", - "integrity": "sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-map": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-map": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", - "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/package-json-from-dist": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", - "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", - "dev": true, - "license": "BlueOak-1.0.0" - }, - "node_modules/package-manager-detector": { - "version": "0.2.11", - "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-0.2.11.tgz", - "integrity": "sha512-BEnLolu+yuz22S56CU1SUKq3XC3PkwD5wv4ikR4MfGvnRVcmzXR9DwSlW2fEamyTPyXHomBJRzgapeuBvRNzJQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "quansync": "^0.2.7" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-scurry": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", - "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "engines": { - "node": ">=16 || 14 >=14.18" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/path-scurry/node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/path-to-regexp": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz", - "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/pathe": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", - "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", - "dev": true, - "license": "MIT" - }, - "node_modules/pathval": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.1.tgz", - "integrity": "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 14.16" - } - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, - "license": "ISC" - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/pirates": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", - "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, - "node_modules/pkg-pr-new": { - "version": "0.0.60", - "resolved": "https://registry.npmjs.org/pkg-pr-new/-/pkg-pr-new-0.0.60.tgz", - "integrity": "sha512-eblxPNSgv0AO18OrfpHq+YrNHfEqeePWWvlKkPvcHByddGsGDOK25z41C1RDjZ+K8zUHDk5IGN+6n0WZa4T2Pg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@actions/core": "^1.11.1", - "@jsdevtools/ez-spawn": "^3.0.4", - "@octokit/action": "^6.1.0", - "ignore": "^5.3.1", - "isbinaryfile": "^5.0.2", - "pkg-types": "^1.1.1", - "query-registry": "^3.0.1", - "tinyglobby": "^0.2.9" - }, - "bin": { - "pkg-pr-new": "bin/cli.js" - } - }, - "node_modules/pkg-types": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz", - "integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "confbox": "^0.1.8", - "mlly": "^1.7.4", - "pathe": "^2.0.1" - } - }, - "node_modules/postcss": { - "version": "8.5.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", - "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", - "dev": true, + ], + "license": "MIT" + }, + "node_modules/micromark-util-types": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz", + "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", "funding": [ { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" }, { - "type": "github", - "url": "https://github.com/sponsors/ai" + "type": "OpenCollective", + "url": "https://opencollective.com/unified" } ], + "license": "MIT" + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "nanoid": "^3.3.11", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" + "braces": "^3.0.3", + "picomatch": "^2.3.1" }, "engines": { - "node": "^10 || ^12 || >=14" + "node": ">=8.6" } }, - "node_modules/postcss-load-config": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-6.0.1.tgz", - "integrity": "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==", + "node_modules/mime": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", + "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", + "dev": true, + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/miniflare": { + "version": "4.20251008.0", + "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-4.20251008.0.tgz", + "integrity": "sha512-sKCNYNzXG6l8qg0Oo7y8WcDKcpbgw0qwZsxNpdZilFTR4EavRow2TlcwuPSVN99jqAjhz0M4VXvTdSGdtJ2VfQ==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], "license": "MIT", "dependencies": { - "lilconfig": "^3.1.1" + "@cspotcode/source-map-support": "0.8.1", + "acorn": "8.14.0", + "acorn-walk": "8.3.2", + "exit-hook": "2.2.1", + "glob-to-regexp": "0.4.1", + "sharp": "^0.33.5", + "stoppable": "1.1.0", + "undici": "7.14.0", + "workerd": "1.20251008.0", + "ws": "8.18.0", + "youch": "4.1.0-beta.10", + "zod": "3.22.3" + }, + "bin": { + "miniflare": "bootstrap.js" }, "engines": { - "node": ">= 18" + "node": ">=18.0.0" + } + }, + "node_modules/miniflare/node_modules/ws": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" }, "peerDependencies": { - "jiti": ">=1.21.0", - "postcss": ">=8.0.9", - "tsx": "^4.8.1", - "yaml": "^2.4.2" + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" }, "peerDependenciesMeta": { - "jiti": { - "optional": true - }, - "postcss": { - "optional": true - }, - "tsx": { + "bufferutil": { "optional": true }, - "yaml": { + "utf-8-validate": { "optional": true } } }, - "node_modules/prettier": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", - "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "node_modules/miniflare/node_modules/zod": { + "version": "3.22.3", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.3.tgz", + "integrity": "sha512-EjIevzuJRiRPbVH4mGc8nApb/lVLKVpmUhAaR5R5doKGfAnGJ6Gr3CViAVjP+4FWSxCsybeWQdcgCtbX+7oZug==", "dev": true, "license": "MIT", - "bin": { - "prettier": "bin-prettier.js" + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=10.13.0" + "node": ">=16 || 14 >=14.17" }, "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/prop-types": { - "version": "15.8.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "license": "MIT", - "peer": true, - "dependencies": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.13.1" + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" } }, - "node_modules/property-information": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz", - "integrity": "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==", + "node_modules/mlly": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.8.0.tgz", + "integrity": "sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==", + "dev": true, "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "dependencies": { + "acorn": "^8.15.0", + "pathe": "^2.0.3", + "pkg-types": "^1.3.1", + "ufo": "^1.6.1" } }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "node_modules/mlly/node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, "engines": { - "node": ">=6" + "node": ">=0.4.0" } }, - "node_modules/quansync": { - "version": "0.2.11", - "resolved": "https://registry.npmjs.org/quansync/-/quansync-0.2.11.tgz", - "integrity": "sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/antfu" - }, - { - "type": "individual", - "url": "https://github.com/sponsors/sxzz" - } - ], - "license": "MIT" - }, - "node_modules/query-registry": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/query-registry/-/query-registry-3.0.1.tgz", - "integrity": "sha512-M9RxRITi2mHMVPU5zysNjctUT8bAPx6ltEXo/ir9+qmiM47Y7f0Ir3+OxUO5OjYAWdicBQRew7RtHtqUXydqlg==", + "node_modules/mri": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", + "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", "dev": true, "license": "MIT", - "dependencies": { - "query-string": "^9.0.0", - "quick-lru": "^7.0.0", - "url-join": "^5.0.0", - "validate-npm-package-name": "^5.0.1", - "zod": "^3.23.8", - "zod-package-json": "^1.0.3" - }, "engines": { - "node": ">=20" + "node": ">=4" } }, - "node_modules/query-string": { - "version": "9.3.1", - "resolved": "https://registry.npmjs.org/query-string/-/query-string-9.3.1.tgz", - "integrity": "sha512-5fBfMOcDi5SA9qj5jZhWAcTtDfKF5WFdd2uD9nVNlbxVv1baq65aALy6qofpNEGELHvisjjasxQp7BlM9gvMzw==", + "node_modules/mrmime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", + "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==", "dev": true, "license": "MIT", - "dependencies": { - "decode-uri-component": "^0.4.1", - "filter-obj": "^5.1.0", - "split-on-first": "^3.0.0" - }, "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=10" } }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", "dev": true, "funding": [ { "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" + "url": "https://github.com/sponsors/ai" } ], - "license": "MIT" - }, - "node_modules/quick-lru": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-7.3.0.tgz", - "integrity": "sha512-k9lSsjl36EJdK7I06v7APZCbyGT2vMTsYSRX1Q2nbYmnkBqgUhRkAuzH08Ciotteu/PLJmIF2+tti7o3C/ts2g==", - "dev": true, "license": "MIT", - "engines": { - "node": ">=18" + "bin": { + "nanoid": "bin/nanoid.cjs" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/react": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/react/-/react-19.2.0.tgz", - "integrity": "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==", - "license": "MIT", - "peer": true, "engines": { - "node": ">=0.10.0" + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "node_modules/react-dom": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.0.tgz", - "integrity": "sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ==", + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", "dev": true, "license": "MIT", "dependencies": { - "scheduler": "^0.27.0" + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" }, "peerDependencies": { - "react": "^19.2.0" + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } } }, - "node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "node_modules/node-releases": { + "version": "2.0.23", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.23.tgz", + "integrity": "sha512-cCmFDMSm26S6tQSDpBCg/NR8NENrVPhAJSf+XbxBG4rPFaaonlEoE9wHQmun+cls499TQGSb7ZyPBRlzgKfpeg==", + "dev": true, "license": "MIT" }, - "node_modules/react-katex": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/react-katex/-/react-katex-3.1.0.tgz", - "integrity": "sha512-At9uLOkC75gwn2N+ZXc5HD8TlATsB+3Hkp9OGs6uA8tM3dwZ3Wljn74Bk3JyHFPgSnesY/EMrIAB1WJwqZqejA==", + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", "license": "MIT", - "dependencies": { - "katex": "^0.16.0" - }, - "peerDependencies": { - "prop-types": "^15.8.1", - "react": ">=15.3.2 <20" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/react-markdown": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-10.1.0.tgz", - "integrity": "sha512-qKxVopLT/TyA6BX3Ue5NwabOsAzm0Q7kAPwq6L+wWDwisYs7R8vZ0nRXqq6rkueboxpkjvLGU9fWifiX/ZZFxQ==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "devlop": "^1.0.0", - "hast-util-to-jsx-runtime": "^2.0.0", - "html-url-attributes": "^3.0.0", - "mdast-util-to-hast": "^13.0.0", - "remark-parse": "^11.0.0", - "remark-rehype": "^11.0.0", - "unified": "^11.0.0", - "unist-util-visit": "^5.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - }, - "peerDependencies": { - "@types/react": ">=18", - "react": ">=18" - } + "node_modules/ohash": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz", + "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==", + "dev": true, + "license": "MIT" }, - "node_modules/react-markdown/node_modules/@types/mdast": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", - "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", - "license": "MIT", + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", "dependencies": { - "@types/unist": "*" + "wrappy": "1" } }, - "node_modules/react-markdown/node_modules/@types/unist": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", - "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "node_modules/outdent": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/outdent/-/outdent-0.5.0.tgz", + "integrity": "sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==", + "dev": true, "license": "MIT" }, - "node_modules/react-markdown/node_modules/bail": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", - "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==", + "node_modules/p-filter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-filter/-/p-filter-2.1.0.tgz", + "integrity": "sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==", + "dev": true, "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "dependencies": { + "p-map": "^2.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/react-markdown/node_modules/is-plain-obj": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", - "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, "engines": { - "node": ">=12" + "node": ">=6" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/react-markdown/node_modules/mdast-util-from-markdown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz", - "integrity": "sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==", + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, "license": "MIT", "dependencies": { - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "mdast-util-to-string": "^4.0.0", - "micromark": "^4.0.0", - "micromark-util-decode-numeric-character-reference": "^2.0.0", - "micromark-util-decode-string": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0", - "unist-util-stringify-position": "^4.0.0" + "p-limit": "^2.2.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">=8" } }, - "node_modules/react-markdown/node_modules/mdast-util-to-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", - "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", + "node_modules/p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "dev": true, "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">=6" } }, - "node_modules/react-markdown/node_modules/micromark": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz", - "integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, "license": "MIT", - "dependencies": { - "@types/debug": "^4.0.0", - "debug": "^4.0.0", - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "micromark-core-commonmark": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-combine-extensions": "^2.0.0", - "micromark-util-decode-numeric-character-reference": "^2.0.0", - "micromark-util-encode": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-resolve-all": "^2.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "micromark-util-subtokenize": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" + "engines": { + "node": ">=6" } }, - "node_modules/react-markdown/node_modules/remark-parse": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", - "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==", + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, + "license": "BlueOak-1.0.0" + }, + "node_modules/package-manager-detector": { + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-0.2.11.tgz", + "integrity": "sha512-BEnLolu+yuz22S56CU1SUKq3XC3PkwD5wv4ikR4MfGvnRVcmzXR9DwSlW2fEamyTPyXHomBJRzgapeuBvRNzJQ==", + "dev": true, "license": "MIT", "dependencies": { - "@types/mdast": "^4.0.0", - "mdast-util-from-markdown": "^2.0.0", - "micromark-util-types": "^2.0.0", - "unified": "^11.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "quansync": "^0.2.7" } }, - "node_modules/react-markdown/node_modules/trough": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", - "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==", + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "engines": { + "node": ">=8" } }, - "node_modules/react-markdown/node_modules/unified": { - "version": "11.0.5", - "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", - "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==", + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "license": "BlueOak-1.0.0", "dependencies": { - "@types/unist": "^3.0.0", - "bail": "^2.0.0", - "devlop": "^1.0.0", - "extend": "^3.0.0", - "is-plain-obj": "^4.0.0", - "trough": "^2.0.0", - "vfile": "^6.0.0" + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/react-markdown/node_modules/unist-util-stringify-position": { + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/path-to-regexp": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz", + "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-type": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", - "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">=8" } }, - "node_modules/react-markdown/node_modules/vfile": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", - "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, + "node_modules/pathval": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.1.tgz", + "integrity": "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==", + "dev": true, "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "vfile-message": "^4.0.0" + "engines": { + "node": ">= 14.16" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/react-markdown/node_modules/vfile-message": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz", - "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", + "node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/pirates": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-pr-new": { + "version": "0.0.60", + "resolved": "https://registry.npmjs.org/pkg-pr-new/-/pkg-pr-new-0.0.60.tgz", + "integrity": "sha512-eblxPNSgv0AO18OrfpHq+YrNHfEqeePWWvlKkPvcHByddGsGDOK25z41C1RDjZ+K8zUHDk5IGN+6n0WZa4T2Pg==", + "dev": true, "license": "MIT", "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-stringify-position": "^4.0.0" + "@actions/core": "^1.11.1", + "@jsdevtools/ez-spawn": "^3.0.4", + "@octokit/action": "^6.1.0", + "ignore": "^5.3.1", + "isbinaryfile": "^5.0.2", + "pkg-types": "^1.1.1", + "query-registry": "^3.0.1", + "tinyglobby": "^0.2.9" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "bin": { + "pkg-pr-new": "bin/cli.js" } }, - "node_modules/react-refresh": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz", - "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==", + "node_modules/pkg-types": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz", + "integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==", "dev": true, "license": "MIT", - "engines": { - "node": ">=0.10.0" + "dependencies": { + "confbox": "^0.1.8", + "mlly": "^1.7.4", + "pathe": "^2.0.1" } }, - "node_modules/read-yaml-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-yaml-file/-/read-yaml-file-1.1.0.tgz", - "integrity": "sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA==", + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "license": "MIT", "dependencies": { - "graceful-fs": "^4.1.5", - "js-yaml": "^3.6.1", - "pify": "^4.0.1", - "strip-bom": "^3.0.0" + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" }, "engines": { - "node": ">=6" + "node": "^10 || ^12 || >=14" } }, - "node_modules/readdirp": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", - "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "node_modules/postcss-load-config": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-6.0.1.tgz", + "integrity": "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "license": "MIT", + "dependencies": { + "lilconfig": "^3.1.1" + }, "engines": { - "node": ">= 14.18.0" + "node": ">= 18" }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" + "peerDependencies": { + "jiti": ">=1.21.0", + "postcss": ">=8.0.9", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + }, + "postcss": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } } }, - "node_modules/remark-rehype": { - "version": "11.1.2", - "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.2.tgz", - "integrity": "sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==", + "node_modules/prettier": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "dev": true, "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "mdast-util-to-hast": "^13.0.0", - "unified": "^11.0.0", - "vfile": "^6.0.0" + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://github.com/prettier/prettier?sponsor=1" } }, - "node_modules/remark-rehype/node_modules/@types/mdast": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", - "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", "license": "MIT", + "peer": true, "dependencies": { - "@types/unist": "*" + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" } }, - "node_modules/remark-rehype/node_modules/@types/unist": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", - "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", - "license": "MIT" - }, - "node_modules/remark-rehype/node_modules/bail": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", - "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==", + "node_modules/property-information": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz", + "integrity": "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==", "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/remark-rehype/node_modules/is-plain-obj": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", - "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, "license": "MIT", "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=6" } }, - "node_modules/remark-rehype/node_modules/trough": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", - "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } + "node_modules/quansync": { + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/quansync/-/quansync-0.2.11.tgz", + "integrity": "sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/antfu" + }, + { + "type": "individual", + "url": "https://github.com/sponsors/sxzz" + } + ], + "license": "MIT" }, - "node_modules/remark-rehype/node_modules/unified": { - "version": "11.0.5", - "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", - "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==", + "node_modules/query-registry": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/query-registry/-/query-registry-3.0.1.tgz", + "integrity": "sha512-M9RxRITi2mHMVPU5zysNjctUT8bAPx6ltEXo/ir9+qmiM47Y7f0Ir3+OxUO5OjYAWdicBQRew7RtHtqUXydqlg==", + "dev": true, "license": "MIT", "dependencies": { - "@types/unist": "^3.0.0", - "bail": "^2.0.0", - "devlop": "^1.0.0", - "extend": "^3.0.0", - "is-plain-obj": "^4.0.0", - "trough": "^2.0.0", - "vfile": "^6.0.0" + "query-string": "^9.0.0", + "quick-lru": "^7.0.0", + "url-join": "^5.0.0", + "validate-npm-package-name": "^5.0.1", + "zod": "^3.23.8", + "zod-package-json": "^1.0.3" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">=20" } }, - "node_modules/remark-rehype/node_modules/unist-util-stringify-position": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", - "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "node_modules/query-string": { + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-9.3.1.tgz", + "integrity": "sha512-5fBfMOcDi5SA9qj5jZhWAcTtDfKF5WFdd2uD9nVNlbxVv1baq65aALy6qofpNEGELHvisjjasxQp7BlM9gvMzw==", + "dev": true, "license": "MIT", "dependencies": { - "@types/unist": "^3.0.0" + "decode-uri-component": "^0.4.1", + "filter-obj": "^5.1.0", + "split-on-first": "^3.0.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-rehype/node_modules/vfile": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", - "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "vfile-message": "^4.0.0" + "engines": { + "node": ">=18" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/remark-rehype/node_modules/vfile-message": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz", - "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-stringify-position": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" }, - "node_modules/remark-stringify": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-11.0.0.tgz", - "integrity": "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==", + "node_modules/quick-lru": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-7.3.0.tgz", + "integrity": "sha512-k9lSsjl36EJdK7I06v7APZCbyGT2vMTsYSRX1Q2nbYmnkBqgUhRkAuzH08Ciotteu/PLJmIF2+tti7o3C/ts2g==", + "dev": true, "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "mdast-util-to-markdown": "^2.0.0", - "unified": "^11.0.0" + "engines": { + "node": ">=18" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/remark-stringify/node_modules/@types/mdast": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", - "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", + "node_modules/react": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.0.tgz", + "integrity": "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==", "license": "MIT", - "dependencies": { - "@types/unist": "*" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/remark-stringify/node_modules/@types/unist": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", - "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", - "license": "MIT" - }, - "node_modules/remark-stringify/node_modules/bail": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", - "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==", + "node_modules/react-dom": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.0.tgz", + "integrity": "sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ==", + "dev": true, "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "dependencies": { + "scheduler": "^0.27.0" + }, + "peerDependencies": { + "react": "^19.2.0" } }, - "node_modules/remark-stringify/node_modules/is-plain-obj": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", - "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + "peer": true }, - "node_modules/remark-stringify/node_modules/longest-streak": { + "node_modules/react-katex": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", - "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", + "resolved": "https://registry.npmjs.org/react-katex/-/react-katex-3.1.0.tgz", + "integrity": "sha512-At9uLOkC75gwn2N+ZXc5HD8TlATsB+3Hkp9OGs6uA8tM3dwZ3Wljn74Bk3JyHFPgSnesY/EMrIAB1WJwqZqejA==", "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "dependencies": { + "katex": "^0.16.0" + }, + "peerDependencies": { + "prop-types": "^15.8.1", + "react": ">=15.3.2 <20" } }, - "node_modules/remark-stringify/node_modules/mdast-util-to-markdown": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz", - "integrity": "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==", + "node_modules/react-markdown": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-10.1.0.tgz", + "integrity": "sha512-qKxVopLT/TyA6BX3Ue5NwabOsAzm0Q7kAPwq6L+wWDwisYs7R8vZ0nRXqq6rkueboxpkjvLGU9fWifiX/ZZFxQ==", "license": "MIT", "dependencies": { + "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "longest-streak": "^3.0.0", - "mdast-util-phrasing": "^4.0.0", - "mdast-util-to-string": "^4.0.0", - "micromark-util-classify-character": "^2.0.0", - "micromark-util-decode-string": "^2.0.0", + "devlop": "^1.0.0", + "hast-util-to-jsx-runtime": "^2.0.0", + "html-url-attributes": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "remark-parse": "^11.0.0", + "remark-rehype": "^11.0.0", + "unified": "^11.0.0", "unist-util-visit": "^5.0.0", - "zwitch": "^2.0.0" + "vfile": "^6.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" + }, + "peerDependencies": { + "@types/react": ">=18", + "react": ">=18" } }, - "node_modules/remark-stringify/node_modules/mdast-util-to-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", - "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", + "node_modules/react-refresh": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz", + "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/read-yaml-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-yaml-file/-/read-yaml-file-1.1.0.tgz", + "integrity": "sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA==", + "dev": true, "license": "MIT", "dependencies": { - "@types/mdast": "^4.0.0" + "graceful-fs": "^4.1.5", + "js-yaml": "^3.6.1", + "pify": "^4.0.1", + "strip-bom": "^3.0.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">=6" } }, - "node_modules/remark-stringify/node_modules/trough": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", - "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==", + "node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "dev": true, "license": "MIT", + "engines": { + "node": ">= 14.18.0" + }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "type": "individual", + "url": "https://paulmillr.com/funding/" } }, - "node_modules/remark-stringify/node_modules/unified": { - "version": "11.0.5", - "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", - "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==", + "node_modules/remark-gfm": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.1.tgz", + "integrity": "sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==", "license": "MIT", "dependencies": { - "@types/unist": "^3.0.0", - "bail": "^2.0.0", - "devlop": "^1.0.0", - "extend": "^3.0.0", - "is-plain-obj": "^4.0.0", - "trough": "^2.0.0", - "vfile": "^6.0.0" + "@types/mdast": "^4.0.0", + "mdast-util-gfm": "^3.0.0", + "micromark-extension-gfm": "^3.0.0", + "remark-parse": "^11.0.0", + "remark-stringify": "^11.0.0", + "unified": "^11.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/remark-stringify/node_modules/unist-util-stringify-position": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", - "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "node_modules/remark-parse": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", + "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==", "license": "MIT", "dependencies": { - "@types/unist": "^3.0.0" + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unified": "^11.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/remark-stringify/node_modules/vfile": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", - "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", + "node_modules/remark-rehype": { + "version": "11.1.2", + "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.2.tgz", + "integrity": "sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==", "license": "MIT", "dependencies": { - "@types/unist": "^3.0.0", - "vfile-message": "^4.0.0" + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "mdast-util-to-hast": "^13.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/remark-stringify/node_modules/vfile-message": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz", - "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", + "node_modules/remark-stringify": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-11.0.0.tgz", + "integrity": "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==", "license": "MIT", "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-stringify-position": "^4.0.0" + "@types/mdast": "^4.0.0", + "mdast-util-to-markdown": "^2.0.0", + "unified": "^11.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/remark-stringify/node_modules/zwitch": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", - "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, "node_modules/resolve-from": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", @@ -8521,7 +7207,6 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -8609,6 +7294,16 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/trough": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", + "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/ts-interface-checker": { "version": "0.1.13", "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", @@ -8683,7 +7378,6 @@ "integrity": "sha512-ytQKuwgmrrkDTFP4LjR0ToE2nqgy886GpvRSpU0JAnrdBYppuY5rLkRUYPU1yCryb24SsKBTL/hlDQAEFVwtZg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "esbuild": "~0.25.0", "get-tsconfig": "^4.7.5" @@ -8864,7 +7558,6 @@ "integrity": "sha512-Wj7/AMtE9MRnAXa6Su3Lk0LNCfqDYgfwVjwRFVum9U7wsto1imuHqk4kTm7Jni+5A0Hn7dttL6O/zjvUvoo+8A==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "defu": "^6.1.4", "exsolve": "^1.0.7", @@ -8873,6 +7566,38 @@ "ufo": "^1.6.1" } }, + "node_modules/unified": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", + "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "bail": "^2.0.0", + "devlop": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^4.0.0", + "trough": "^2.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-is": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", + "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/unist-util-position": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", @@ -8886,50 +7611,38 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/unist-util-position/node_modules/@types/unist": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", - "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", - "license": "MIT" - }, - "node_modules/unist-util-visit": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", - "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", "license": "MIT", "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0", - "unist-util-visit-parents": "^6.0.0" + "@types/unist": "^3.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/unist-util-visit/node_modules/@types/unist": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", - "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", - "license": "MIT" - }, - "node_modules/unist-util-visit/node_modules/unist-util-is": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", - "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", + "node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", "license": "MIT", "dependencies": { - "@types/unist": "^3.0.0" + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/unist-util-visit/node_modules/unist-util-visit-parents": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", - "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", + "node_modules/unist-util-visit-parents": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", + "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", "license": "MIT", "dependencies": { "@types/unist": "^3.0.0", @@ -9008,13 +7721,40 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/vfile": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-message": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz", + "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/vite": { "version": "7.1.11", "resolved": "https://registry.npmjs.org/vite/-/vite-7.1.11.tgz", "integrity": "sha512-uzcxnSDVjAopEUjljkWh8EIrg6tlzrjFUfMcR1EVsRDGwf/ccef0qQPRyOrROwhrTDaApueq+ja+KLPlzR/zdg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", @@ -9131,7 +7871,6 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -9145,7 +7884,6 @@ "integrity": "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@types/chai": "^5.2.2", "@vitest/expect": "3.2.4", @@ -9294,7 +8032,6 @@ "dev": true, "hasInstallScript": true, "license": "Apache-2.0", - "peer": true, "bin": { "workerd": "bin/workerd" }, @@ -9925,9 +8662,8 @@ "version": "8.18.3", "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", - "devOptional": true, + "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=10.0.0" }, @@ -9998,6 +8734,16 @@ "node": ">=20" } }, + "node_modules/zwitch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "packages/sandbox": { "name": "@cloudflare/sandbox", "version": "0.4.12", @@ -10031,6 +8777,21 @@ "typescript": "^5.7.2" } }, + "tests/integration": { + "name": "@repo/integration", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "@cloudflare/sandbox": "*", + "katex": "^0.16.22", + "react-katex": "^3.1.0", + "react-markdown": "^10.1.0", + "remark-gfm": "^4.0.1" + }, + "devDependencies": { + "@types/react-katex": "^3.0.4" + } + }, "tooling/typescript-config": { "name": "@repo/typescript-config", "version": "0.0.0" diff --git a/package.json b/package.json index fb42707f..ec86657d 100644 --- a/package.json +++ b/package.json @@ -19,8 +19,7 @@ "workspaces": [ "packages/*", "tooling/*", - "examples/basic", - "examples/code-interpreter" + "tests/integration" ], "devDependencies": { "@biomejs/biome": "^2.1.2", diff --git a/packages/sandbox/README.md b/packages/sandbox/README.md index 4656896c..b396911a 100644 --- a/packages/sandbox/README.md +++ b/packages/sandbox/README.md @@ -144,7 +144,6 @@ See the [examples directory](./examples) for complete working examples: - [Minimal](./examples/minimal) - Basic sandbox setup - [Code Interpreter](./examples/code-interpreter) - Use sandbox as an interpreter tool with gpt-oss -- [Complete](./examples/basic) - Huge example integrated with every sandbox feature ## Status diff --git a/packages/sandbox/src/sandbox.ts b/packages/sandbox/src/sandbox.ts index 263f9cce..345fba56 100644 --- a/packages/sandbox/src/sandbox.ts +++ b/packages/sandbox/src/sandbox.ts @@ -59,11 +59,20 @@ export function getSandbox( /** * Connect an incoming WebSocket request to a specific port inside the container. * - * @param sandbox - The sandbox instance (stub) to connect to - * @param request - The incoming WebSocket upgrade request from the client - * @param port - The port number to connect to inside the container (1024-65535) - * @returns Promise - The WebSocket upgrade response + * Note: This is a standalone function (not a Sandbox method) because WebSocket + * connections cannot be serialized over Durable Object RPC. + * + * @param sandbox - The Sandbox instance to route the request through + * @param request - The incoming WebSocket upgrade request + * @param port - The port number to connect to (1024-65535) + * @returns The WebSocket upgrade response * @throws {SecurityError} - If port is invalid or in restricted range + * + * @example + * const sandbox = getSandbox(env.Sandbox, 'sandbox-id'); + * if (request.headers.get('Upgrade')?.toLowerCase() === 'websocket') { + * return await connect(sandbox, request, 8080); + * } */ export async function connect( sandbox: Sandbox, @@ -890,6 +899,7 @@ export class Sandbox extends Container implements ISandbox { return storedToken === token; } + private generatePortToken(): string { // Generate cryptographically secure 16-character token using Web Crypto API // Available in Cloudflare Workers runtime diff --git a/packages/sandbox/tests/connect.test.ts b/packages/sandbox/tests/connect.test.ts deleted file mode 100644 index 1b36ba3c..00000000 --- a/packages/sandbox/tests/connect.test.ts +++ /dev/null @@ -1,356 +0,0 @@ -import type { DurableObjectState } from '@cloudflare/workers-types'; -import { beforeEach, describe, expect, it, vi } from 'vitest'; -import { connect, Sandbox } from '../src/sandbox'; - -// Mock @cloudflare/containers before importing -vi.mock('@cloudflare/containers', () => { - const mockSwitchPort = vi.fn((request: Request, port: number) => { - // Create a new request with the port in the URL path - const url = new URL(request.url); - url.pathname = `/proxy/${port}${url.pathname}`; - return new Request(url, request); - }); - - const MockContainer = class Container { - ctx: any; - env: any; - constructor(ctx: any, env: any) { - this.ctx = ctx; - this.env = env; - } - async fetch(request: Request): Promise { - // Mock WebSocket upgrade response - // Note: In Workers runtime, WebSocket upgrades don't return status 101 - // Instead, the runtime handles the upgrade internally - const upgradeHeader = request.headers.get('Upgrade'); - if (upgradeHeader?.toLowerCase() === 'websocket') { - return new Response('WebSocket Upgraded', { - status: 200, - headers: { - 'X-WebSocket-Upgraded': 'true', - 'Upgrade': 'websocket', - 'Connection': 'Upgrade', - }, - }); - } - return new Response('Mock fetch'); - } - }; - - return { - Container: MockContainer, - getContainer: vi.fn(), - switchPort: mockSwitchPort, - }; -}); - -describe('connect() - WebSocket Routing', () => { - let sandbox: Sandbox; - let mockCtx: Partial; - let mockEnv: any; - - beforeEach(async () => { - vi.clearAllMocks(); - - // Mock DurableObjectState - mockCtx = { - storage: { - get: vi.fn().mockResolvedValue(null), - put: vi.fn().mockResolvedValue(undefined), - delete: vi.fn().mockResolvedValue(undefined), - list: vi.fn().mockResolvedValue(new Map()), - } as any, - blockConcurrencyWhile: vi.fn((fn: () => Promise) => fn()), - id: { - toString: () => 'test-sandbox-id', - equals: vi.fn(), - name: 'test-sandbox', - } as any, - }; - - mockEnv = {}; - - // Create Sandbox instance - sandbox = new Sandbox(mockCtx as DurableObjectState, mockEnv); - - // Wait for initialization - await vi.waitFor(() => { - expect(mockCtx.blockConcurrencyWhile).toHaveBeenCalled(); - }); - }); - - describe('basic functionality', () => { - it('should route WebSocket request to specified port', async () => { - // Create a WebSocket upgrade request (RFC 6455 compliant) - const request = new Request('http://localhost/ws/echo', { - headers: { - 'Upgrade': 'websocket', - 'Connection': 'Upgrade', - 'Sec-WebSocket-Version': '13', - 'Sec-WebSocket-Key': 'dGhlIHNhbXBsZSBub25jZQ==', - }, - }); - - // Spy on sandbox.fetch to verify it's called - const fetchSpy = vi.spyOn(sandbox, 'fetch'); - - // Call connect() - const response = await connect(sandbox, request, 8080); - - // Verify sandbox.fetch was called - expect(fetchSpy).toHaveBeenCalledOnce(); - - // Verify response indicates WebSocket upgrade - expect(response.status).toBe(200); - expect(response.headers.get('X-WebSocket-Upgraded')).toBe('true'); - expect(response.headers.get('Upgrade')).toBe('websocket'); - }); - - it('should pass port number through switchPort', async () => { - const request = new Request('http://localhost/ws/terminal', { - headers: { - 'Upgrade': 'websocket', - 'Connection': 'Upgrade', - }, - }); - - const { switchPort } = await import('@cloudflare/containers'); - const switchPortMock = vi.mocked(switchPort); - - await connect(sandbox, request, 8082); - - // Verify switchPort was called with correct port - expect(switchPortMock).toHaveBeenCalledWith(request, 8082); - }); - - it('should preserve request headers when routing', async () => { - const request = new Request('http://localhost/ws/code', { - headers: { - 'Upgrade': 'websocket', - 'Connection': 'Upgrade', - 'X-Sandbox-Id': 'test-sandbox-123', - 'X-Custom-Header': 'custom-value', - }, - }); - - const fetchSpy = vi.spyOn(sandbox, 'fetch'); - - await connect(sandbox, request, 8081); - - // Get the request that was passed to fetch - const calledRequest = fetchSpy.mock.calls[0][0]; - - // Verify headers are preserved - expect(calledRequest.headers.get('Upgrade')).toBe('websocket'); - expect(calledRequest.headers.get('X-Sandbox-Id')).toBe('test-sandbox-123'); - expect(calledRequest.headers.get('X-Custom-Header')).toBe('custom-value'); - }); - }); - - describe('port routing', () => { - it('should route to port 8080 for echo server', async () => { - const request = new Request('http://localhost/ws/echo', { - headers: { 'Upgrade': 'websocket', 'Connection': 'Upgrade' }, - }); - - const { switchPort } = await import('@cloudflare/containers'); - const switchPortMock = vi.mocked(switchPort); - - await connect(sandbox, request, 8080); - - expect(switchPortMock).toHaveBeenCalledWith(request, 8080); - }); - - it('should route to port 8081 for code server', async () => { - const request = new Request('http://localhost/ws/code', { - headers: { 'Upgrade': 'websocket', 'Connection': 'Upgrade' }, - }); - - const { switchPort } = await import('@cloudflare/containers'); - const switchPortMock = vi.mocked(switchPort); - - await connect(sandbox, request, 8081); - - expect(switchPortMock).toHaveBeenCalledWith(request, 8081); - }); - - it('should route to port 8082 for terminal server', async () => { - const request = new Request('http://localhost/ws/terminal', { - headers: { 'Upgrade': 'websocket', 'Connection': 'Upgrade' }, - }); - - const { switchPort } = await import('@cloudflare/containers'); - const switchPortMock = vi.mocked(switchPort); - - await connect(sandbox, request, 8082); - - expect(switchPortMock).toHaveBeenCalledWith(request, 8082); - }); - - it('should support custom ports', async () => { - const request = new Request('http://localhost/ws/custom', { - headers: { 'Upgrade': 'websocket', 'Connection': 'Upgrade' }, - }); - - const { switchPort } = await import('@cloudflare/containers'); - const switchPortMock = vi.mocked(switchPort); - - await connect(sandbox, request, 9000); - - expect(switchPortMock).toHaveBeenCalledWith(request, 9000); - }); - }); - - describe('error handling', () => { - it('should propagate errors from sandbox.fetch', async () => { - const request = new Request('http://localhost/ws/error', { - headers: { 'Upgrade': 'websocket', 'Connection': 'Upgrade' }, - }); - - // Mock fetch to throw an error - vi.spyOn(sandbox, 'fetch').mockRejectedValueOnce( - new Error('Container connection failed') - ); - - await expect(connect(sandbox, request, 8080)).rejects.toThrow( - 'Container connection failed' - ); - }); - - it('should reject invalid port numbers', async () => { - const request = new Request('http://localhost/ws/test', { - headers: { 'Upgrade': 'websocket', 'Connection': 'Upgrade' }, - }); - - // Test with negative port - await expect(connect(sandbox, request, -1)).rejects.toThrow('Invalid or restricted port'); - - // Test with port 0 - await expect(connect(sandbox, request, 0)).rejects.toThrow('Invalid or restricted port'); - - // Test with port > 65535 - await expect(connect(sandbox, request, 70000)).rejects.toThrow('Invalid or restricted port'); - }); - - it('should reject privileged ports (< 1024)', async () => { - const request = new Request('http://localhost/ws/test', { - headers: { 'Upgrade': 'websocket', 'Connection': 'Upgrade' }, - }); - - // Test with port 80 (privileged) - await expect(connect(sandbox, request, 80)).rejects.toThrow('Invalid or restricted port'); - - // Test with port 443 (privileged) - await expect(connect(sandbox, request, 443)).rejects.toThrow('Invalid or restricted port'); - - // Test with port 22 (privileged) - await expect(connect(sandbox, request, 22)).rejects.toThrow('Invalid or restricted port'); - }); - - it('should allow valid user ports (1024-65535)', async () => { - const request = new Request('http://localhost/ws/test', { - headers: { 'Upgrade': 'websocket', 'Connection': 'Upgrade' }, - }); - - // Test boundary: port 1024 (first valid user port) - await expect(connect(sandbox, request, 1024)).resolves.toBeDefined(); - - // Test boundary: port 65535 (last valid port) - await expect(connect(sandbox, request, 65535)).resolves.toBeDefined(); - - // Test common ports - await expect(connect(sandbox, request, 8080)).resolves.toBeDefined(); - await expect(connect(sandbox, request, 3001)).resolves.toBeDefined(); - }); - }); - - describe('WebSocket upgrade scenarios', () => { - it('should handle standard WebSocket headers', async () => { - const request = new Request('http://localhost/ws/test', { - headers: { - 'Upgrade': 'websocket', - 'Connection': 'Upgrade', - 'Sec-WebSocket-Version': '13', - 'Sec-WebSocket-Key': 'dGhlIHNhbXBsZSBub25jZQ==', - 'Sec-WebSocket-Protocol': 'chat', - }, - }); - - const response = await connect(sandbox, request, 8080); - - expect(response.status).toBe(200); - expect(response.headers.get('X-WebSocket-Upgraded')).toBe('true'); - }); - - it('should handle WebSocket with query parameters', async () => { - const request = new Request('http://localhost/ws/test?token=abc123&room=lobby', { - headers: { 'Upgrade': 'websocket', 'Connection': 'Upgrade' }, - }); - - const fetchSpy = vi.spyOn(sandbox, 'fetch'); - - await connect(sandbox, request, 8080); - - const calledRequest = fetchSpy.mock.calls[0][0]; - const url = new URL(calledRequest.url); - - // Verify query parameters are preserved - expect(url.searchParams.get('token')).toBe('abc123'); - expect(url.searchParams.get('room')).toBe('lobby'); - }); - - it('should handle WebSocket with path segments', async () => { - const request = new Request('http://localhost/ws/rooms/123/chat', { - headers: { 'Upgrade': 'websocket', 'Connection': 'Upgrade' }, - }); - - const fetchSpy = vi.spyOn(sandbox, 'fetch'); - - await connect(sandbox, request, 8080); - - const calledRequest = fetchSpy.mock.calls[0][0]; - const url = new URL(calledRequest.url); - - // Verify path is preserved in proxied request - expect(url.pathname).toContain('rooms/123/chat'); - }); - - it('should handle case-insensitive Upgrade header', async () => { - const request = new Request('http://localhost/ws/test', { - headers: { - 'Upgrade': 'WebSocket', // Mixed case - 'Connection': 'upgrade', - }, - }); - - const response = await connect(sandbox, request, 8080); - - // Should still work with non-lowercase Upgrade header - expect(response.status).toBe(200); - expect(response.headers.get('X-WebSocket-Upgraded')).toBe('true'); - }); - }); - - describe('integration with Sandbox', () => { - it('should work with getSandbox helper', async () => { - // This tests the typical usage pattern - const { getSandbox } = await import('../src/sandbox'); - const { getContainer } = await import('@cloudflare/containers'); - - const mockNamespace = {} as any; - const getContainerMock = vi.mocked(getContainer); - getContainerMock.mockReturnValue(sandbox as any); - - const sandboxStub = getSandbox(mockNamespace, 'test-id'); - - const request = new Request('http://localhost/ws/echo', { - headers: { 'Upgrade': 'websocket', 'Connection': 'Upgrade' }, - }); - - const response = await connect(sandboxStub, request, 8080); - - expect(response.status).toBe(200); - expect(response.headers.get('X-WebSocket-Upgraded')).toBe('true'); - }); - }); -}); diff --git a/packages/sandbox/tests/sandbox.test.ts b/packages/sandbox/tests/sandbox.test.ts index 1b820f51..279597c5 100644 --- a/packages/sandbox/tests/sandbox.test.ts +++ b/packages/sandbox/tests/sandbox.test.ts @@ -1,7 +1,7 @@ import { Container } from '@cloudflare/containers'; import type { DurableObjectState } from '@cloudflare/workers-types'; import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; -import { Sandbox } from '../src/sandbox'; +import { Sandbox, connect } from '../src/sandbox'; // Mock dependencies before imports vi.mock('./interpreter', () => ({ @@ -9,6 +9,13 @@ vi.mock('./interpreter', () => ({ })); vi.mock('@cloudflare/containers', () => { + const mockSwitchPort = vi.fn((request: Request, port: number) => { + // Create a new request with the port in the URL path + const url = new URL(request.url); + url.pathname = `/proxy/${port}${url.pathname}`; + return new Request(url, request); + }); + const MockContainer = class Container { ctx: any; env: any; @@ -18,6 +25,17 @@ vi.mock('@cloudflare/containers', () => { } async fetch(request: Request): Promise { // Mock implementation - will be spied on in tests + const upgradeHeader = request.headers.get('Upgrade'); + if (upgradeHeader?.toLowerCase() === 'websocket') { + return new Response('WebSocket Upgraded', { + status: 200, + headers: { + 'X-WebSocket-Upgraded': 'true', + 'Upgrade': 'websocket', + 'Connection': 'Upgrade', + }, + }); + } return new Response('Mock Container fetch'); } async containerFetch(request: Request, port: number): Promise { @@ -29,6 +47,7 @@ vi.mock('@cloudflare/containers', () => { return { Container: MockContainer, getContainer: vi.fn(), + switchPort: mockSwitchPort, }; }); @@ -553,4 +572,70 @@ describe('Sandbox - Automatic Session Management', () => { expect(passedRequest.headers.get('Sec-WebSocket-Version')).toBe('13'); }); }); + + describe('connect() function', () => { + it('should route WebSocket request through switchPort to sandbox.fetch', async () => { + const { switchPort } = await import('@cloudflare/containers'); + const switchPortMock = vi.mocked(switchPort); + + const request = new Request('http://localhost/ws/echo', { + headers: { + 'Upgrade': 'websocket', + 'Connection': 'Upgrade', + }, + }); + + const fetchSpy = vi.spyOn(sandbox, 'fetch'); + const response = await connect(sandbox, request, 8080); + + // Verify switchPort was called with correct port + expect(switchPortMock).toHaveBeenCalledWith(request, 8080); + + // Verify fetch was called with the switched request + expect(fetchSpy).toHaveBeenCalledOnce(); + + // Verify response indicates WebSocket upgrade + expect(response.status).toBe(200); + expect(response.headers.get('X-WebSocket-Upgraded')).toBe('true'); + }); + + it('should reject invalid ports with SecurityError', async () => { + const request = new Request('http://localhost/ws/test', { + headers: { 'Upgrade': 'websocket', 'Connection': 'Upgrade' }, + }); + + // Invalid port values + await expect(connect(sandbox, request, -1)).rejects.toThrow('Invalid or restricted port'); + await expect(connect(sandbox, request, 0)).rejects.toThrow('Invalid or restricted port'); + await expect(connect(sandbox, request, 70000)).rejects.toThrow('Invalid or restricted port'); + + // Privileged ports + await expect(connect(sandbox, request, 80)).rejects.toThrow('Invalid or restricted port'); + await expect(connect(sandbox, request, 443)).rejects.toThrow('Invalid or restricted port'); + }); + + it('should preserve request properties through routing', async () => { + const request = new Request('http://localhost/ws/test?token=abc&room=lobby', { + headers: { + 'Upgrade': 'websocket', + 'Connection': 'Upgrade', + 'X-Custom-Header': 'custom-value', + }, + }); + + const fetchSpy = vi.spyOn(sandbox, 'fetch'); + await connect(sandbox, request, 8080); + + const calledRequest = fetchSpy.mock.calls[0][0]; + + // Verify headers are preserved + expect(calledRequest.headers.get('Upgrade')).toBe('websocket'); + expect(calledRequest.headers.get('X-Custom-Header')).toBe('custom-value'); + + // Verify query parameters are preserved + const url = new URL(calledRequest.url); + expect(url.searchParams.get('token')).toBe('abc'); + expect(url.searchParams.get('room')).toBe('lobby'); + }); + }); }); diff --git a/tests/e2e/test-worker/index.ts b/tests/e2e/test-worker/index.ts index 0f89b35d..19ad1522 100644 --- a/tests/e2e/test-worker/index.ts +++ b/tests/e2e/test-worker/index.ts @@ -202,7 +202,7 @@ console.log('Terminal server on port ' + port); // WebSocket endpoints const upgradeHeader = request.headers.get('Upgrade'); - if (upgradeHeader === 'websocket') { + if (upgradeHeader?.toLowerCase() === 'websocket') { if (url.pathname === '/ws/echo') { return await connect(sandbox, request, 8080); } diff --git a/tests/e2e/websocket-connect.test.ts b/tests/e2e/websocket-connect.test.ts index 2624cc73..6d536dda 100644 --- a/tests/e2e/websocket-connect.test.ts +++ b/tests/e2e/websocket-connect.test.ts @@ -6,18 +6,10 @@ import { createSandboxId, createTestHeaders, cleanupSandbox } from './helpers/te /** * WebSocket connect() Integration Tests * - * Tests the new connect() pattern for routing WebSocket requests directly to - * container services, plus the /api/init endpoint for pre-initializing servers. - * - * COVERAGE: - * - /api/init endpoint functionality - * - Direct WebSocket routing via connect() - * - Python code streaming with real-time output - * - Terminal command execution - * - Server persistence across connections - * - Multiple concurrent connections + * Tests the connect() method for routing WebSocket requests to container services. + * Focuses on transport-level functionality, not application-level server implementations. */ -describe('WebSocket connect() Pattern', () => { +describe('WebSocket Connections', () => { let runner: WranglerDevRunner | null = null; let workerUrl: string; let currentSandboxId: string | null = null; @@ -41,55 +33,20 @@ describe('WebSocket connect() Pattern', () => { } }); - test('should initialize all servers via /api/init endpoint', async () => { + test('should establish WebSocket connection to container service', async () => { currentSandboxId = createSandboxId(); const headers = createTestHeaders(currentSandboxId); - // Call /api/init to start all servers - const response = await fetch(`${workerUrl}/api/init`, { + // Start a simple echo server in the container + await fetch(`${workerUrl}/api/init`, { method: 'POST', headers, }); - expect(response.status).toBe(200); - const data = await response.json(); - - expect(data.success).toBe(true); - expect(data.serversStarted).toBeGreaterThanOrEqual(0); // May be 0 if already running - expect(data.serversFailed).toBe(0); // No failures - - // Verify all three server processes exist - const processesResponse = await fetch(`${workerUrl}/api/process/list`, { - method: 'GET', - headers, - }); - - expect(processesResponse.status).toBe(200); - const processes = await processesResponse.json(); - - const processIds = processes.map((p: any) => p.id); - expect(processIds).toContain('ws-echo-8080'); - expect(processIds).toContain('ws-code-8081'); - expect(processIds).toContain('ws-terminal-8082'); - - // Verify all are running - const runningProcesses = processes.filter((p: any) => p.status === 'running'); - expect(runningProcesses.length).toBeGreaterThanOrEqual(3); - }, 30000); - - test('should connect to echo server directly using connect()', async () => { - currentSandboxId = createSandboxId(); - const headers = createTestHeaders(currentSandboxId); - - // Initialize servers - const initResponse = await fetch(`${workerUrl}/api/init`, { - method: 'POST', - headers, - }); - const initData = await initResponse.json(); - expect(initData.success).toBe(true); + // Wait for server to be ready (generous timeout for first startup) + await new Promise(resolve => setTimeout(resolve, 2000)); - // Connect via WebSocket using connect() pattern (no port exposure API) + // Connect via WebSocket using connect() routing const wsUrl = workerUrl.replace(/^http/, 'ws') + '/ws/echo'; const ws = new WebSocket(wsUrl, { headers: { @@ -104,8 +61,8 @@ describe('WebSocket connect() Pattern', () => { setTimeout(() => reject(new Error('Connection timeout')), 10000); }); - // Send message and verify echo - const testMessage = 'Hello from connect() test!'; + // Send message and verify echo back + const testMessage = 'Hello WebSocket'; const messagePromise = new Promise((resolve, reject) => { ws.on('message', (data) => resolve(data.toString())); setTimeout(() => reject(new Error('Echo timeout')), 5000); @@ -116,7 +73,7 @@ describe('WebSocket connect() Pattern', () => { expect(echoedMessage).toBe(testMessage); - // Close connection + // Clean close ws.close(); await new Promise((resolve) => { ws.on('close', () => resolve()); @@ -124,393 +81,26 @@ describe('WebSocket connect() Pattern', () => { }); }, 30000); - test('should stream Python code execution output in real-time', async () => { - currentSandboxId = createSandboxId(); - const headers = createTestHeaders(currentSandboxId); - - // Initialize servers - const initResponse = await fetch(`${workerUrl}/api/init`, { - method: 'POST', - headers, - }); - const initData = await initResponse.json(); - expect(initData.success).toBe(true); - - // Connect to code streaming server - const wsUrl = workerUrl.replace(/^http/, 'ws') + '/ws/code'; - const ws = new WebSocket(wsUrl, { - headers: { - 'X-Sandbox-Id': currentSandboxId, - }, - }); - - await new Promise((resolve, reject) => { - ws.on('open', () => resolve()); - ws.on('error', (error) => reject(error)); - setTimeout(() => reject(new Error('Connection timeout')), 10000); - }); - - // Collect all messages - const messages: any[] = []; - ws.on('message', (data) => { - try { - messages.push(JSON.parse(data.toString())); - } catch (e) { - console.error('Failed to parse message:', data.toString()); - } - }); - - // Send Python code with multiple print statements and delays - const pythonCode = ` -import time -for i in range(3): - print(f'Count: {i}') - time.sleep(0.3) -print('Done!') -`; - - ws.send(JSON.stringify({ - type: 'execute', - code: pythonCode, - })); - - // Wait for completion - await new Promise((resolve, reject) => { - const checkComplete = () => { - const completed = messages.find(m => m.type === 'completed'); - if (completed) { - resolve(); - } else { - setTimeout(checkComplete, 100); - } - }; - checkComplete(); - setTimeout(() => reject(new Error('Execution timeout')), 10000); - }); - - // Verify message sequence - expect(messages.some(m => m.type === 'ready')).toBe(true); - expect(messages.some(m => m.type === 'executing')).toBe(true); - - // Verify we got stdout messages (streaming) - const stdoutMessages = messages.filter(m => m.type === 'stdout'); - expect(stdoutMessages.length).toBeGreaterThan(0); - - // Verify output contains our print statements - const fullOutput = stdoutMessages.map(m => m.data).join(''); - expect(fullOutput).toContain('Count: 0'); - expect(fullOutput).toContain('Count: 1'); - expect(fullOutput).toContain('Count: 2'); - expect(fullOutput).toContain('Done!'); - - // Verify completion with exit code 0 - const completedMsg = messages.find(m => m.type === 'completed'); - expect(completedMsg).toBeDefined(); - expect(completedMsg.exitCode).toBe(0); - - ws.close(); - }, 30000); - - test('should handle Python code execution errors with non-zero exit code', async () => { + test('should handle multiple concurrent connections', async () => { currentSandboxId = createSandboxId(); const headers = createTestHeaders(currentSandboxId); - const initResponse = await fetch(`${workerUrl}/api/init`, { + // Initialize echo server + await fetch(`${workerUrl}/api/init`, { method: 'POST', headers, }); - const initData = await initResponse.json(); - expect(initData.success).toBe(true); - - const wsUrl = workerUrl.replace(/^http/, 'ws') + '/ws/code'; - const ws = new WebSocket(wsUrl, { - headers: { - 'X-Sandbox-Id': currentSandboxId, - }, - }); - - await new Promise((resolve, reject) => { - ws.on('open', () => resolve()); - ws.on('error', (error) => reject(error)); - setTimeout(() => reject(new Error('Connection timeout')), 10000); - }); - - const messages: any[] = []; - ws.on('message', (data) => { - try { - messages.push(JSON.parse(data.toString())); - } catch (e) {} - }); - - // Send Python code that raises an error - const pythonCode = ` -print('Starting...') -raise ValueError('This is a test error') -print('This should not print') -`; - - ws.send(JSON.stringify({ - type: 'execute', - code: pythonCode, - })); - // Wait for completion - await new Promise((resolve, reject) => { - const checkComplete = () => { - const completed = messages.find(m => m.type === 'completed'); - if (completed) { - resolve(); - } else { - setTimeout(checkComplete, 100); - } - }; - checkComplete(); - setTimeout(() => reject(new Error('Execution timeout')), 10000); - }); - - // Verify we got stderr with error message - const stderrMessages = messages.filter(m => m.type === 'stderr'); - expect(stderrMessages.length).toBeGreaterThan(0); - - const stderrOutput = stderrMessages.map(m => m.data).join(''); - expect(stderrOutput).toContain('ValueError'); - expect(stderrOutput).toContain('This is a test error'); - - // Verify non-zero exit code - const completedMsg = messages.find(m => m.type === 'completed'); - expect(completedMsg).toBeDefined(); - expect(completedMsg.exitCode).not.toBe(0); - - ws.close(); - }, 30000); - - test('should execute terminal commands and return results', async () => { - currentSandboxId = createSandboxId(); - const headers = createTestHeaders(currentSandboxId); - - const initResponse = await fetch(`${workerUrl}/api/init`, { - method: 'POST', - headers, - }); - const initData = await initResponse.json(); - expect(initData.success).toBe(true); - - const wsUrl = workerUrl.replace(/^http/, 'ws') + '/ws/terminal'; - const ws = new WebSocket(wsUrl, { - headers: { - 'X-Sandbox-Id': currentSandboxId, - }, - }); + // Wait for server to be ready + await new Promise(resolve => setTimeout(resolve, 2000)); - await new Promise((resolve, reject) => { - ws.on('open', () => resolve()); - ws.on('error', (error) => reject(error)); - setTimeout(() => reject(new Error('Connection timeout')), 10000); - }); - - const messages: any[] = []; - ws.on('message', (data) => { - try { - messages.push(JSON.parse(data.toString())); - } catch (e) {} - }); - - // Wait for ready message - await new Promise((resolve) => { - const checkReady = () => { - if (messages.some(m => m.type === 'ready')) { - resolve(); - } else { - setTimeout(checkReady, 100); - } - }; - checkReady(); - }); - - const readyMsg = messages.find(m => m.type === 'ready'); - expect(readyMsg).toBeDefined(); - expect(readyMsg.cwd).toBeDefined(); - - // Execute echo command - ws.send(JSON.stringify({ - type: 'command', - command: 'echo "Hello Terminal"', - })); - - // Wait for result - await new Promise((resolve) => { - const checkResult = () => { - if (messages.some(m => m.type === 'result')) { - resolve(); - } else { - setTimeout(checkResult, 100); - } - }; - checkResult(); - }); - - const resultMsg = messages.find(m => m.type === 'result'); - expect(resultMsg).toBeDefined(); - expect(resultMsg.stdout).toContain('Hello Terminal'); - expect(resultMsg.exitCode).toBe(0); - - ws.close(); - }, 30000); - - test('should handle terminal command errors with non-zero exit code', async () => { - currentSandboxId = createSandboxId(); - const headers = createTestHeaders(currentSandboxId); - - const initResponse = await fetch(`${workerUrl}/api/init`, { - method: 'POST', - headers, - }); - const initData = await initResponse.json(); - expect(initData.success).toBe(true); - - const wsUrl = workerUrl.replace(/^http/, 'ws') + '/ws/terminal'; - const ws = new WebSocket(wsUrl, { - headers: { - 'X-Sandbox-Id': currentSandboxId, - }, - }); - - await new Promise((resolve, reject) => { - ws.on('open', () => resolve()); - ws.on('error', (error) => reject(error)); - setTimeout(() => reject(new Error('Connection timeout')), 10000); - }); - - const messages: any[] = []; - ws.on('message', (data) => { - try { - messages.push(JSON.parse(data.toString())); - } catch (e) {} - }); - - // Wait for ready - await new Promise((resolve) => { - const checkReady = () => { - if (messages.some(m => m.type === 'ready')) resolve(); - else setTimeout(checkReady, 100); - }; - checkReady(); - }); - - // Execute command that fails - ws.send(JSON.stringify({ - type: 'command', - command: 'ls /nonexistent-directory', - })); - - // Wait for result - await new Promise((resolve) => { - const checkResult = () => { - if (messages.some(m => m.type === 'result')) resolve(); - else setTimeout(checkResult, 100); - }; - checkResult(); - }); - - const resultMsg = messages.find(m => m.type === 'result'); - expect(resultMsg).toBeDefined(); - expect(resultMsg.stderr).toContain('No such file or directory'); - expect(resultMsg.exitCode).not.toBe(0); - - ws.close(); - }, 30000); - - test('should reuse running servers across multiple connections', async () => { - currentSandboxId = createSandboxId(); - const headers = createTestHeaders(currentSandboxId); - - // Initialize servers once - const initResponse = await fetch(`${workerUrl}/api/init`, { - method: 'POST', - headers, - }); - const initData = await initResponse.json(); - expect(initData.success).toBe(true); - - // Get initial process list - const initialProcesses = await fetch(`${workerUrl}/api/process/list`, { - method: 'GET', - headers, - }).then(r => r.json()); - - const echoProcess = initialProcesses.find((p: any) => p.id === 'ws-echo-8080'); - expect(echoProcess).toBeDefined(); - - // Connect, disconnect, reconnect multiple times - for (let i = 0; i < 3; i++) { - const wsUrl = workerUrl.replace(/^http/, 'ws') + '/ws/echo'; - const ws = new WebSocket(wsUrl, { - headers: { - 'X-Sandbox-Id': currentSandboxId, - }, - }); - - await new Promise((resolve, reject) => { - ws.on('open', () => resolve()); - ws.on('error', (error) => reject(error)); - setTimeout(() => reject(new Error('Connection timeout')), 10000); - }); - - // Send a message - const messagePromise = new Promise((resolve) => { - ws.on('message', (data) => resolve(data.toString())); - }); - - ws.send(`Test ${i}`); - const echo = await messagePromise; - expect(echo).toBe(`Test ${i}`); - - // Close - ws.close(); - await new Promise((resolve) => { - ws.on('close', () => resolve()); - setTimeout(() => resolve(), 500); - }); - - // Small delay between connections - await new Promise(resolve => setTimeout(resolve, 100)); - } - - // Verify same process is still running (not restarted) - const finalProcesses = await fetch(`${workerUrl}/api/process/list`, { - method: 'GET', - headers, - }).then(r => r.json()); - - const finalEchoProcess = finalProcesses.find((p: any) => p.id === 'ws-echo-8080'); - expect(finalEchoProcess).toBeDefined(); - expect(finalEchoProcess.status).toBe('running'); - - // Process ID should be the same (server wasn't restarted) - expect(finalEchoProcess.id).toBe(echoProcess.id); - }, 30000); - - test('should handle multiple concurrent WebSocket connections', async () => { - currentSandboxId = createSandboxId(); - const headers = createTestHeaders(currentSandboxId); - - const initResponse = await fetch(`${workerUrl}/api/init`, { - method: 'POST', - headers, - }); - const initData = await initResponse.json(); - expect(initData.success).toBe(true); - - // Open 3 concurrent connections to different servers - const wsUrl1 = workerUrl.replace(/^http/, 'ws') + '/ws/echo'; - const wsUrl2 = workerUrl.replace(/^http/, 'ws') + '/ws/code'; - const wsUrl3 = workerUrl.replace(/^http/, 'ws') + '/ws/terminal'; - - const ws1 = new WebSocket(wsUrl1, { headers: { 'X-Sandbox-Id': currentSandboxId } }); - const ws2 = new WebSocket(wsUrl2, { headers: { 'X-Sandbox-Id': currentSandboxId } }); - const ws3 = new WebSocket(wsUrl3, { headers: { 'X-Sandbox-Id': currentSandboxId } }); + // Open 3 concurrent connections to echo server + const wsUrl = workerUrl.replace(/^http/, 'ws') + '/ws/echo'; + const ws1 = new WebSocket(wsUrl, { headers: { 'X-Sandbox-Id': currentSandboxId } }); + const ws2 = new WebSocket(wsUrl, { headers: { 'X-Sandbox-Id': currentSandboxId } }); + const ws3 = new WebSocket(wsUrl, { headers: { 'X-Sandbox-Id': currentSandboxId } }); - // Wait for all connections + // Wait for all connections to open await Promise.all([ new Promise((resolve, reject) => { ws1.on('open', () => resolve()); @@ -529,45 +119,28 @@ print('This should not print') }), ]); - // Send messages on all connections simultaneously + // Send different messages on each connection simultaneously const results = await Promise.all([ new Promise((resolve) => { ws1.on('message', (data) => resolve(data.toString())); - ws1.send('Echo test'); + ws1.send('Message 1'); }), - new Promise((resolve) => { - const messages: any[] = []; - ws2.on('message', (data) => { - try { - const msg = JSON.parse(data.toString()); - messages.push(msg); - if (msg.type === 'completed') resolve(messages); - } catch (e) {} - }); - ws2.send(JSON.stringify({ type: 'execute', code: 'print("Code test")' })); + new Promise((resolve) => { + ws2.on('message', (data) => resolve(data.toString())); + ws2.send('Message 2'); }), - new Promise((resolve) => { - const messages: any[] = []; - ws3.on('message', (data) => { - try { - const msg = JSON.parse(data.toString()); - messages.push(msg); - if (msg.type === 'result') resolve(messages); - } catch (e) {} - }); - // Wait for ready first - setTimeout(() => { - ws3.send(JSON.stringify({ type: 'command', command: 'echo "Terminal test"' })); - }, 500); + new Promise((resolve) => { + ws3.on('message', (data) => resolve(data.toString())); + ws3.send('Message 3'); }), ]); - // Verify all worked independently - expect(results[0]).toBe('Echo test'); - expect(results[1].some((m: any) => m.type === 'stdout')).toBe(true); - expect(results[2].some((m: any) => m.type === 'result')).toBe(true); + // Verify each connection received its own message (no interference) + expect(results[0]).toBe('Message 1'); + expect(results[1]).toBe('Message 2'); + expect(results[2]).toBe('Message 3'); - // Close all + // Close all connections ws1.close(); ws2.close(); ws3.close(); diff --git a/examples/basic/.gitignore b/tests/integration/.gitignore similarity index 100% rename from examples/basic/.gitignore rename to tests/integration/.gitignore diff --git a/examples/basic/Dockerfile b/tests/integration/Dockerfile similarity index 100% rename from examples/basic/Dockerfile rename to tests/integration/Dockerfile diff --git a/examples/basic/README.md b/tests/integration/README.md similarity index 100% rename from examples/basic/README.md rename to tests/integration/README.md diff --git a/examples/basic/app/components/LaTeXRenderer.tsx b/tests/integration/app/components/LaTeXRenderer.tsx similarity index 100% rename from examples/basic/app/components/LaTeXRenderer.tsx rename to tests/integration/app/components/LaTeXRenderer.tsx diff --git a/examples/basic/app/components/MarkdownRenderer.tsx b/tests/integration/app/components/MarkdownRenderer.tsx similarity index 100% rename from examples/basic/app/components/MarkdownRenderer.tsx rename to tests/integration/app/components/MarkdownRenderer.tsx diff --git a/examples/basic/app/index.tsx b/tests/integration/app/index.tsx similarity index 94% rename from examples/basic/app/index.tsx rename to tests/integration/app/index.tsx index 1d9c312b..3e73aba0 100644 --- a/examples/basic/app/index.tsx +++ b/tests/integration/app/index.tsx @@ -628,7 +628,8 @@ type TabType = | "streaming" | "files" | "notebook" - | "examples"; + | "examples" + | "websocket"; interface ProcessInfo { id: string; @@ -3618,6 +3619,218 @@ function ExamplesTab({ ); } +function WebSocketTab() { + const [serverInitialized, setServerInitialized] = useState(false); + const [isInitializing, setIsInitializing] = useState(false); + const [connectionStatus, setConnectionStatus] = useState<"disconnected" | "connecting" | "connected">("disconnected"); + const [messages, setMessages] = useState>([]); + const [messageInput, setMessageInput] = useState(""); + const wsRef = useRef(null); + const messagesEndRef = useRef(null); + + const scrollToBottom = () => { + messagesEndRef.current?.scrollIntoView({ behavior: "smooth" }); + }; + + useEffect(() => { + scrollToBottom(); + }, [messages]); + + const initializeServer = async () => { + setIsInitializing(true); + try { + const response = await fetch("/api/websocket/init", { + method: "POST", + headers: { + "Content-Type": "application/json", + "X-Sandbox-Client-Id": getClientSandboxId(), + }, + }); + + if (!response.ok) { + throw new Error(`Failed to initialize server: ${response.statusText}`); + } + + const data = await response.json(); + setServerInitialized(true); + addMessage("received", `Server initialized: ${data.message}`); + } catch (error: any) { + addMessage("received", `Error initializing server: ${error.message}`); + } finally { + setIsInitializing(false); + } + }; + + const addMessage = (type: "sent" | "received", text: string) => { + setMessages((prev) => [...prev, { type, text, timestamp: new Date() }]); + }; + + const connectWebSocket = () => { + if (wsRef.current) return; + + setConnectionStatus("connecting"); + const protocol = window.location.protocol === "https:" ? "wss:" : "ws:"; + const sandboxId = getClientSandboxId(); + const ws = new WebSocket(`${protocol}//${window.location.host}/ws/echo?sandboxId=${sandboxId}`); + + ws.onopen = () => { + setConnectionStatus("connected"); + addMessage("received", "WebSocket connected"); + }; + + ws.onmessage = (event) => { + addMessage("received", event.data); + }; + + ws.onerror = (error) => { + addMessage("received", "WebSocket error occurred"); + }; + + ws.onclose = () => { + setConnectionStatus("disconnected"); + addMessage("received", "WebSocket disconnected"); + wsRef.current = null; + }; + + wsRef.current = ws; + }; + + const disconnectWebSocket = () => { + if (wsRef.current) { + wsRef.current.close(); + wsRef.current = null; + } + }; + + const sendMessage = () => { + if (!messageInput.trim() || !wsRef.current || connectionStatus !== "connected") return; + + wsRef.current.send(messageInput); + addMessage("sent", messageInput); + setMessageInput(""); + }; + + const handleKeyPress = (e: React.KeyboardEvent) => { + if (e.key === "Enter" && !e.shiftKey) { + e.preventDefault(); + sendMessage(); + } + }; + + const clearMessages = () => { + setMessages([]); + }; + + // Cleanup on unmount + useEffect(() => { + return () => { + disconnectWebSocket(); + }; + }, []); + + return ( +
+
+

WebSocket Echo Server

+

+ Test the connect() method by sending messages to a WebSocket echo server running in the sandbox. +

+
+ +
+
+ + + + + + + + {connectionStatus === "connected" ? "🟢 Connected" : connectionStatus === "connecting" ? "🟡 Connecting..." : "🔴 Disconnected"} + +
+
+ +
+
+ {messages.length === 0 ? ( +
+

No messages yet. Initialize the server and connect to start sending messages.

+
+ ) : ( + <> + {messages.map((msg, idx) => ( +
+ + {msg.timestamp.toLocaleTimeString()} + + + {msg.type === "sent" ? "→ Sent:" : "← Received:"} + + {msg.text} +
+ ))} +
+ + )} +
+ +
+ setMessageInput(e.target.value)} + onKeyPress={handleKeyPress} + placeholder="Type a message to echo..." + disabled={connectionStatus !== "connected"} + className="message-input" + /> + + +
+
+ +
+

How it works:

+
    +
  1. Initialize: Starts a Bun WebSocket echo server on port 8080 in the sandbox
  2. +
  3. Connect: Uses connect(sandbox, request, 8080) to route WebSocket to the server
  4. +
  5. Echo: Any message you send will be echoed back by the server
  6. +
+

+ This demonstrates the connect() method, which is syntactic sugar for fetch(switchPort()) to make WebSocket routing clear and simple. +

+
+
+ ); +} + function SandboxTester() { const [activeTab, setActiveTab] = useState("commands"); const [client, setClient] = useState(null); @@ -4047,6 +4260,12 @@ function SandboxTester() { > 🧪 Examples +
@@ -4243,6 +4462,8 @@ function SandboxTester() { {activeTab === "examples" && ( )} + + {activeTab === "websocket" && }
); diff --git a/examples/basic/app/style.css b/tests/integration/app/style.css similarity index 93% rename from examples/basic/app/style.css rename to tests/integration/app/style.css index 45ab1560..f9e17e17 100644 --- a/examples/basic/app/style.css +++ b/tests/integration/app/style.css @@ -3025,3 +3025,213 @@ button:focus { grid-template-columns: 1fr; } } + +/* WebSocket Tab Styles */ +.websocket-tab { + padding: 1.5rem; + background-color: #0d1117; +} + +.websocket-header { + margin-bottom: 1.5rem; +} + +.websocket-header h3 { + margin: 0 0 0.5rem 0; + color: #58a6ff; + font-size: 1.3rem; +} + +.websocket-header p { + margin: 0; + color: #8b949e; + font-size: 0.95rem; +} + +.websocket-header code { + background-color: #161b22; + padding: 0.2rem 0.4rem; + border-radius: 3px; + font-family: "Fira Code", monospace; + font-size: 0.9rem; + color: #79c0ff; +} + +.websocket-controls { + background-color: #161b22; + border: 1px solid #30363d; + border-radius: 6px; + padding: 1rem; + margin-bottom: 1.5rem; +} + +.websocket-controls .control-group { + display: flex; + align-items: center; + gap: 0.75rem; + flex-wrap: wrap; +} + +.status-indicator { + padding: 0.4rem 0.8rem; + border-radius: 4px; + font-size: 0.9rem; + font-weight: 500; + margin-left: auto; +} + +.status-connected { + background-color: rgba(46, 160, 67, 0.15); + color: #3fb950; +} + +.status-connecting { + background-color: rgba(201, 209, 217, 0.15); + color: #c9d1d9; +} + +.status-disconnected { + background-color: rgba(248, 81, 73, 0.15); + color: #f85149; +} + +.websocket-message-area { + background-color: #161b22; + border: 1px solid #30363d; + border-radius: 6px; + padding: 1rem; + margin-bottom: 1.5rem; +} + +.messages-container { + background-color: #0d1117; + border: 1px solid #30363d; + border-radius: 4px; + padding: 1rem; + min-height: 300px; + max-height: 400px; + overflow-y: auto; + margin-bottom: 1rem; +} + +.no-messages { + display: flex; + align-items: center; + justify-content: center; + height: 300px; + color: #8b949e; + font-style: italic; +} + +.message { + display: flex; + align-items: baseline; + gap: 0.5rem; + padding: 0.5rem; + margin-bottom: 0.5rem; + border-radius: 4px; + font-family: "Fira Code", monospace; + font-size: 0.9rem; +} + +.message-sent { + background-color: rgba(88, 166, 255, 0.1); + border-left: 3px solid #58a6ff; +} + +.message-received { + background-color: rgba(63, 185, 80, 0.1); + border-left: 3px solid #3fb950; +} + +.message-time { + color: #6e7681; + font-size: 0.8rem; + white-space: nowrap; +} + +.message-label { + color: #8b949e; + font-weight: 500; + white-space: nowrap; +} + +.message-text { + color: #c9d1d9; + word-break: break-word; +} + +.message-input-area { + display: flex; + gap: 0.75rem; + align-items: center; +} + +.message-input { + flex: 1; + padding: 0.6rem; + background-color: #0d1117; + border: 1px solid #30363d; + border-radius: 6px; + color: #c9d1d9; + font-family: "Fira Code", monospace; + font-size: 0.95rem; +} + +.message-input:focus { + outline: none; + border-color: #58a6ff; + box-shadow: 0 0 0 3px rgba(88, 166, 255, 0.1); +} + +.message-input:disabled { + opacity: 0.5; + cursor: not-allowed; +} + +.btn-send { + background-color: #238636; + color: white; +} + +.btn-send:hover:not(:disabled) { + background-color: #2ea043; +} + +.websocket-info { + background-color: rgba(56, 139, 253, 0.1); + border: 1px solid rgba(56, 139, 253, 0.3); + border-radius: 6px; + padding: 1rem; +} + +.websocket-info h4 { + margin: 0 0 0.75rem 0; + color: #58a6ff; + font-size: 1rem; +} + +.websocket-info ol { + margin: 0.5rem 0; + padding-left: 1.5rem; + color: #c9d1d9; +} + +.websocket-info li { + margin-bottom: 0.5rem; +} + +.websocket-info p { + margin: 0.75rem 0 0 0; + color: #8b949e; + font-size: 0.9rem; +} + +.websocket-info code { + background-color: #161b22; + padding: 0.2rem 0.4rem; + border-radius: 3px; + font-family: "Fira Code", monospace; + font-size: 0.85rem; + color: #79c0ff; +} diff --git a/examples/basic/index.html b/tests/integration/index.html similarity index 100% rename from examples/basic/index.html rename to tests/integration/index.html diff --git a/examples/basic/package.json b/tests/integration/package.json similarity index 80% rename from examples/basic/package.json rename to tests/integration/package.json index fce77872..21c95b95 100644 --- a/examples/basic/package.json +++ b/tests/integration/package.json @@ -1,9 +1,9 @@ { - "name": "@cloudflare/sandbox-example", + "name": "@repo/integration", "version": "1.0.0", "type": "module", "private": true, - "description": "An example of using the sandbox package", + "description": "Integration testing app for the Sandbox SDK", "scripts": { "start": "vite dev", "deploy": "vite build && wrangler deploy" diff --git a/examples/basic/public/favicon.ico b/tests/integration/public/favicon.ico similarity index 100% rename from examples/basic/public/favicon.ico rename to tests/integration/public/favicon.ico diff --git a/examples/basic/shared/examples.ts b/tests/integration/shared/examples.ts similarity index 100% rename from examples/basic/shared/examples.ts rename to tests/integration/shared/examples.ts diff --git a/examples/basic/src/endpoints/createTestBinary.ts b/tests/integration/src/endpoints/createTestBinary.ts similarity index 100% rename from examples/basic/src/endpoints/createTestBinary.ts rename to tests/integration/src/endpoints/createTestBinary.ts diff --git a/examples/basic/src/endpoints/execute.ts b/tests/integration/src/endpoints/execute.ts similarity index 100% rename from examples/basic/src/endpoints/execute.ts rename to tests/integration/src/endpoints/execute.ts diff --git a/examples/basic/src/endpoints/executeStream.ts b/tests/integration/src/endpoints/executeStream.ts similarity index 100% rename from examples/basic/src/endpoints/executeStream.ts rename to tests/integration/src/endpoints/executeStream.ts diff --git a/examples/basic/src/endpoints/fileDelete.ts b/tests/integration/src/endpoints/fileDelete.ts similarity index 100% rename from examples/basic/src/endpoints/fileDelete.ts rename to tests/integration/src/endpoints/fileDelete.ts diff --git a/examples/basic/src/endpoints/fileList.ts b/tests/integration/src/endpoints/fileList.ts similarity index 100% rename from examples/basic/src/endpoints/fileList.ts rename to tests/integration/src/endpoints/fileList.ts diff --git a/examples/basic/src/endpoints/fileMove.ts b/tests/integration/src/endpoints/fileMove.ts similarity index 100% rename from examples/basic/src/endpoints/fileMove.ts rename to tests/integration/src/endpoints/fileMove.ts diff --git a/examples/basic/src/endpoints/fileRead.ts b/tests/integration/src/endpoints/fileRead.ts similarity index 100% rename from examples/basic/src/endpoints/fileRead.ts rename to tests/integration/src/endpoints/fileRead.ts diff --git a/examples/basic/src/endpoints/fileReadStream.ts b/tests/integration/src/endpoints/fileReadStream.ts similarity index 100% rename from examples/basic/src/endpoints/fileReadStream.ts rename to tests/integration/src/endpoints/fileReadStream.ts diff --git a/examples/basic/src/endpoints/fileRename.ts b/tests/integration/src/endpoints/fileRename.ts similarity index 100% rename from examples/basic/src/endpoints/fileRename.ts rename to tests/integration/src/endpoints/fileRename.ts diff --git a/examples/basic/src/endpoints/gitCheckout.ts b/tests/integration/src/endpoints/gitCheckout.ts similarity index 100% rename from examples/basic/src/endpoints/gitCheckout.ts rename to tests/integration/src/endpoints/gitCheckout.ts diff --git a/examples/basic/src/endpoints/index.ts b/tests/integration/src/endpoints/index.ts similarity index 93% rename from examples/basic/src/endpoints/index.ts rename to tests/integration/src/endpoints/index.ts index 0896cdb7..bceee96b 100644 --- a/examples/basic/src/endpoints/index.ts +++ b/tests/integration/src/endpoints/index.ts @@ -16,3 +16,4 @@ export { createDirectory } from "./mkdir"; export { gitCheckout } from "./gitCheckout"; export { setupNextjs, setupReact, setupVue, setupStatic } from "./templates"; export { createTestBinaryFile } from "./createTestBinary"; +export { initializeWebSocketServer } from "./websocketInit"; diff --git a/examples/basic/src/endpoints/mkdir.ts b/tests/integration/src/endpoints/mkdir.ts similarity index 100% rename from examples/basic/src/endpoints/mkdir.ts rename to tests/integration/src/endpoints/mkdir.ts diff --git a/examples/basic/src/endpoints/notebook.ts b/tests/integration/src/endpoints/notebook.ts similarity index 100% rename from examples/basic/src/endpoints/notebook.ts rename to tests/integration/src/endpoints/notebook.ts diff --git a/examples/basic/src/endpoints/ports.ts b/tests/integration/src/endpoints/ports.ts similarity index 100% rename from examples/basic/src/endpoints/ports.ts rename to tests/integration/src/endpoints/ports.ts diff --git a/examples/basic/src/endpoints/processGet.ts b/tests/integration/src/endpoints/processGet.ts similarity index 100% rename from examples/basic/src/endpoints/processGet.ts rename to tests/integration/src/endpoints/processGet.ts diff --git a/examples/basic/src/endpoints/processKill.ts b/tests/integration/src/endpoints/processKill.ts similarity index 100% rename from examples/basic/src/endpoints/processKill.ts rename to tests/integration/src/endpoints/processKill.ts diff --git a/examples/basic/src/endpoints/processList.ts b/tests/integration/src/endpoints/processList.ts similarity index 100% rename from examples/basic/src/endpoints/processList.ts rename to tests/integration/src/endpoints/processList.ts diff --git a/examples/basic/src/endpoints/processLogs.ts b/tests/integration/src/endpoints/processLogs.ts similarity index 100% rename from examples/basic/src/endpoints/processLogs.ts rename to tests/integration/src/endpoints/processLogs.ts diff --git a/examples/basic/src/endpoints/processStart.ts b/tests/integration/src/endpoints/processStart.ts similarity index 100% rename from examples/basic/src/endpoints/processStart.ts rename to tests/integration/src/endpoints/processStart.ts diff --git a/examples/basic/src/endpoints/templates.ts b/tests/integration/src/endpoints/templates.ts similarity index 100% rename from examples/basic/src/endpoints/templates.ts rename to tests/integration/src/endpoints/templates.ts diff --git a/tests/integration/src/endpoints/websocketInit.ts b/tests/integration/src/endpoints/websocketInit.ts new file mode 100644 index 00000000..1bcb912f --- /dev/null +++ b/tests/integration/src/endpoints/websocketInit.ts @@ -0,0 +1,77 @@ +import type { Sandbox } from "@cloudflare/sandbox"; +import { jsonResponse, errorResponse } from "../http"; + +// Minimal WebSocket echo server script using Bun +const ECHO_SERVER_SCRIPT = ` +const port = 8080; + +Bun.serve({ + port, + fetch(req, server) { + const upgradeHeader = req.headers.get("Upgrade"); + if (upgradeHeader === "websocket") { + const upgraded = server.upgrade(req); + if (!upgraded) { + return new Response("WebSocket upgrade failed", { status: 400 }); + } + return undefined; + } + return new Response("WebSocket server running on port " + port, { status: 200 }); + }, + websocket: { + open(ws) { + console.log("WebSocket connection opened"); + }, + message(ws, message) { + // Echo the message back + ws.send(message); + }, + close(ws) { + console.log("WebSocket connection closed"); + }, + }, +}); + +console.log("WebSocket echo server listening on port " + port); +`.trim(); + +export async function initializeWebSocketServer(sandbox: Sandbox) { + try { + const processId = "ws-echo-8080"; + + // Check if server is already running + const processes = await sandbox.listProcesses(); + const existingProcess = processes.find(p => p.id === processId); + + if (existingProcess) { + return jsonResponse({ + message: "WebSocket server already running", + port: 8080, + processId + }); + } + + // Write the echo server script + await sandbox.writeFile("/tmp/ws-echo.ts", ECHO_SERVER_SCRIPT); + + // Start the server as a background process + await sandbox.startProcess("bun run /tmp/ws-echo.ts", { + processId, + cwd: "/tmp" + }); + + // Give the server a moment to start + await new Promise(resolve => setTimeout(resolve, 500)); + + return jsonResponse({ + message: "WebSocket echo server initialized", + port: 8080, + processId, + endpoint: "/ws/echo" + }); + + } catch (error: any) { + console.error("Failed to initialize WebSocket server:", error); + return errorResponse(`Failed to initialize WebSocket server: ${error.message}`, 500); + } +} diff --git a/examples/basic/src/http.ts b/tests/integration/src/http.ts similarity index 100% rename from examples/basic/src/http.ts rename to tests/integration/src/http.ts diff --git a/examples/basic/src/index.ts b/tests/integration/src/index.ts similarity index 92% rename from examples/basic/src/index.ts rename to tests/integration/src/index.ts index d548cc34..d60f07af 100644 --- a/examples/basic/src/index.ts +++ b/tests/integration/src/index.ts @@ -1,4 +1,4 @@ -import { getSandbox, proxyToSandbox, type Sandbox } from "@cloudflare/sandbox"; +import { getSandbox, proxyToSandbox, connect, type Sandbox } from "@cloudflare/sandbox"; import { codeExamples } from "../shared/examples"; import { executeCommand, @@ -24,6 +24,7 @@ import { setupVue, setupStatic, createTestBinaryFile, + initializeWebSocketServer, } from "./endpoints"; import { createSession, executeCell, deleteSession } from "./endpoints/notebook"; import { corsHeaders, errorResponse, jsonResponse, parseJsonBody } from "./http"; @@ -72,6 +73,17 @@ export default { const pathname = url.pathname; try { + // WebSocket routing - detect upgrade requests and route to container + const upgradeHeader = request.headers.get("Upgrade"); + if (upgradeHeader?.toLowerCase() === "websocket" && pathname === "/ws/echo") { + // For WebSocket connections, get sandbox ID from query parameter + // (browsers don't support custom headers in WebSocket constructor) + const sandboxId = url.searchParams.get("sandboxId") || `sandbox-${Date.now()}-${generateSecureRandomString()}`; + const sandbox = getSandbox(env.Sandbox, sandboxId) as unknown as Sandbox; + // Route WebSocket connection to echo server on port 8080 + return await connect(sandbox, request, 8080); + } + const sandbox = getUserSandbox(env, request) as unknown as Sandbox; // Notebook API endpoints @@ -87,6 +99,11 @@ export default { return await deleteSession(sandbox, request); } + // WebSocket Server Initialization API + if (pathname === "/api/websocket/init" && request.method === "POST") { + return await initializeWebSocketServer(sandbox); + } + // Command Execution API if (pathname === "/api/execute" && request.method === "POST") { return await executeCommand(sandbox, request); @@ -338,6 +355,8 @@ export default { "POST /api/notebook/session - Create notebook session", "POST /api/notebook/execute - Execute notebook cell", "DELETE /api/notebook/session - Delete notebook session", + "POST /api/websocket/init - Initialize WebSocket echo server", + "WS /ws/echo - WebSocket echo endpoint", "GET /api/examples/basic-python - Basic Python example", "GET /api/examples/chart - Chart generation example", "GET /api/examples/javascript - JavaScript execution example", diff --git a/examples/basic/tsconfig.json b/tests/integration/tsconfig.json similarity index 100% rename from examples/basic/tsconfig.json rename to tests/integration/tsconfig.json diff --git a/examples/basic/vite.config.ts b/tests/integration/vite.config.ts similarity index 100% rename from examples/basic/vite.config.ts rename to tests/integration/vite.config.ts diff --git a/examples/basic/wrangler.jsonc b/tests/integration/wrangler.jsonc similarity index 100% rename from examples/basic/wrangler.jsonc rename to tests/integration/wrangler.jsonc From b915e8509aa5b97e2b02ec6db73bdf0ca67daf4e Mon Sep 17 00:00:00 2001 From: katereznykova Date: Wed, 29 Oct 2025 16:16:19 +0000 Subject: [PATCH 13/16] fix the build --- package-lock.json | 74 ++++++++++++++++++++++++++++++++++- packages/sandbox/src/index.ts | 61 +++++++++++++++++++++++++++-- 2 files changed, 129 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3bb697c4..038ce5de 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,8 @@ "workspaces": [ "packages/*", "tooling/*", - "tests/integration" + "tests/integration", + "examples/*" ], "devDependencies": { "@biomejs/biome": "^2.1.2", @@ -42,6 +43,42 @@ "ws": "^8.18.3" } }, + "examples/claude-code": { + "name": "@cloudflare/sandbox-claude-code-example", + "version": "1.0.0", + "license": "MIT", + "devDependencies": { + "@cloudflare/sandbox": "*", + "@types/node": "^24.9.1", + "typescript": "^5.8.3", + "wrangler": "^4.44.0" + } + }, + "examples/code-interpreter": { + "name": "@cloudflare/sandbox-code-interpreter-example", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "@cloudflare/sandbox": "*", + "openai": "^5.12.0" + }, + "devDependencies": { + "@types/node": "^24.9.1", + "typescript": "^5.8.3", + "wrangler": "^4.44.0" + } + }, + "examples/minimal": { + "name": "@cloudflare/sandbox-minimal-example", + "version": "1.0.0", + "license": "MIT", + "devDependencies": { + "@cloudflare/sandbox": "*", + "@types/node": "^24.9.1", + "typescript": "^5.8.3", + "wrangler": "^4.44.0" + } + }, "node_modules/@actions/core": { "version": "1.11.1", "dev": true, @@ -647,6 +684,18 @@ "resolved": "packages/sandbox", "link": true }, + "node_modules/@cloudflare/sandbox-claude-code-example": { + "resolved": "examples/claude-code", + "link": true + }, + "node_modules/@cloudflare/sandbox-code-interpreter-example": { + "resolved": "examples/code-interpreter", + "link": true + }, + "node_modules/@cloudflare/sandbox-minimal-example": { + "resolved": "examples/minimal", + "link": true + }, "node_modules/@cloudflare/unenv-preset": { "version": "2.7.7", "dev": true, @@ -5188,6 +5237,27 @@ "wrappy": "1" } }, + "node_modules/openai": { + "version": "5.23.2", + "resolved": "https://registry.npmjs.org/openai/-/openai-5.23.2.tgz", + "integrity": "sha512-MQBzmTulj+MM5O8SKEk/gL8a7s5mktS9zUtAkU257WjvobGc9nKcBuVwjyEEcb9SI8a8Y2G/mzn3vm9n1Jlleg==", + "license": "Apache-2.0", + "bin": { + "openai": "bin/cli" + }, + "peerDependencies": { + "ws": "^8.18.0", + "zod": "^3.23.8" + }, + "peerDependenciesMeta": { + "ws": { + "optional": true + }, + "zod": { + "optional": true + } + } + }, "node_modules/outdent": { "version": "0.5.0", "dev": true, @@ -7162,7 +7232,7 @@ }, "node_modules/ws": { "version": "8.18.3", - "dev": true, + "devOptional": true, "license": "MIT", "engines": { "node": ">=10.0.0" diff --git a/packages/sandbox/src/index.ts b/packages/sandbox/src/index.ts index 5ea896ae..2577ad99 100644 --- a/packages/sandbox/src/index.ts +++ b/packages/sandbox/src/index.ts @@ -20,17 +20,70 @@ export type { BaseExecOptions, ExecEvent, ExecOptions, - ExecResult,FileChunk, FileMetadata, FileStreamEvent, + ExecResult, + FileChunk, + FileMetadata, + FileStreamEvent, ISandbox, LogEvent, Process, ProcessOptions, ProcessStatus, - StreamOptions + StreamOptions } from "@repo/shared"; -export * from '@repo/shared'; -// Export type guards for runtime validation + +// Export additional shared types needed by SDK consumers +export type { + // Interpreter types + ChartData, + CodeContext, + CreateContextOptions, + ExecutionError, + ExecutionResult, + OutputMessage, + Result, + RunCodeOptions, + // Result types + ContextCreateResult, + ContextDeleteResult, + ContextListResult, + DeleteFileResult, + EnvSetResult, + FileExistsResult, + FileInfo, + HealthCheckResult, + InterpreterHealthResult, + ListFilesOptions, + ListFilesResult, + MkdirResult, + MoveFileResult, + ReadFileResult, + RenameFileResult, + SandboxOptions, + SessionCreateResult, + SessionDeleteResult, + SessionOptions, + ShutdownResult, + WriteFileResult, + // Execution session type + ExecutionSession, + PortStatusResult, + // Logger types + LogContext, + Logger, + LogLevel +} from "@repo/shared"; + +// Export runtime values from shared export { + Execution, + ResultImpl, + createLogger, + createNoOpLogger, + getLogger, + LogLevelEnum, + runWithLogger, + TraceContext, isExecResult, isProcess, isProcessStatus From 2f8a3d230cbae36ec80e518b045c22fd7f1bdeaf Mon Sep 17 00:00:00 2001 From: Naresh Date: Wed, 29 Oct 2025 16:39:19 +0000 Subject: [PATCH 14/16] Revert "fix the build" This reverts commit b915e8509aa5b97e2b02ec6db73bdf0ca67daf4e. --- package-lock.json | 74 +---------------------------------- packages/sandbox/src/index.ts | 61 ++--------------------------- 2 files changed, 6 insertions(+), 129 deletions(-) diff --git a/package-lock.json b/package-lock.json index 038ce5de..3bb697c4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,8 +11,7 @@ "workspaces": [ "packages/*", "tooling/*", - "tests/integration", - "examples/*" + "tests/integration" ], "devDependencies": { "@biomejs/biome": "^2.1.2", @@ -43,42 +42,6 @@ "ws": "^8.18.3" } }, - "examples/claude-code": { - "name": "@cloudflare/sandbox-claude-code-example", - "version": "1.0.0", - "license": "MIT", - "devDependencies": { - "@cloudflare/sandbox": "*", - "@types/node": "^24.9.1", - "typescript": "^5.8.3", - "wrangler": "^4.44.0" - } - }, - "examples/code-interpreter": { - "name": "@cloudflare/sandbox-code-interpreter-example", - "version": "1.0.0", - "license": "MIT", - "dependencies": { - "@cloudflare/sandbox": "*", - "openai": "^5.12.0" - }, - "devDependencies": { - "@types/node": "^24.9.1", - "typescript": "^5.8.3", - "wrangler": "^4.44.0" - } - }, - "examples/minimal": { - "name": "@cloudflare/sandbox-minimal-example", - "version": "1.0.0", - "license": "MIT", - "devDependencies": { - "@cloudflare/sandbox": "*", - "@types/node": "^24.9.1", - "typescript": "^5.8.3", - "wrangler": "^4.44.0" - } - }, "node_modules/@actions/core": { "version": "1.11.1", "dev": true, @@ -684,18 +647,6 @@ "resolved": "packages/sandbox", "link": true }, - "node_modules/@cloudflare/sandbox-claude-code-example": { - "resolved": "examples/claude-code", - "link": true - }, - "node_modules/@cloudflare/sandbox-code-interpreter-example": { - "resolved": "examples/code-interpreter", - "link": true - }, - "node_modules/@cloudflare/sandbox-minimal-example": { - "resolved": "examples/minimal", - "link": true - }, "node_modules/@cloudflare/unenv-preset": { "version": "2.7.7", "dev": true, @@ -5237,27 +5188,6 @@ "wrappy": "1" } }, - "node_modules/openai": { - "version": "5.23.2", - "resolved": "https://registry.npmjs.org/openai/-/openai-5.23.2.tgz", - "integrity": "sha512-MQBzmTulj+MM5O8SKEk/gL8a7s5mktS9zUtAkU257WjvobGc9nKcBuVwjyEEcb9SI8a8Y2G/mzn3vm9n1Jlleg==", - "license": "Apache-2.0", - "bin": { - "openai": "bin/cli" - }, - "peerDependencies": { - "ws": "^8.18.0", - "zod": "^3.23.8" - }, - "peerDependenciesMeta": { - "ws": { - "optional": true - }, - "zod": { - "optional": true - } - } - }, "node_modules/outdent": { "version": "0.5.0", "dev": true, @@ -7232,7 +7162,7 @@ }, "node_modules/ws": { "version": "8.18.3", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">=10.0.0" diff --git a/packages/sandbox/src/index.ts b/packages/sandbox/src/index.ts index 2577ad99..5ea896ae 100644 --- a/packages/sandbox/src/index.ts +++ b/packages/sandbox/src/index.ts @@ -20,70 +20,17 @@ export type { BaseExecOptions, ExecEvent, ExecOptions, - ExecResult, - FileChunk, - FileMetadata, - FileStreamEvent, + ExecResult,FileChunk, FileMetadata, FileStreamEvent, ISandbox, LogEvent, Process, ProcessOptions, ProcessStatus, - StreamOptions + StreamOptions } from "@repo/shared"; - -// Export additional shared types needed by SDK consumers -export type { - // Interpreter types - ChartData, - CodeContext, - CreateContextOptions, - ExecutionError, - ExecutionResult, - OutputMessage, - Result, - RunCodeOptions, - // Result types - ContextCreateResult, - ContextDeleteResult, - ContextListResult, - DeleteFileResult, - EnvSetResult, - FileExistsResult, - FileInfo, - HealthCheckResult, - InterpreterHealthResult, - ListFilesOptions, - ListFilesResult, - MkdirResult, - MoveFileResult, - ReadFileResult, - RenameFileResult, - SandboxOptions, - SessionCreateResult, - SessionDeleteResult, - SessionOptions, - ShutdownResult, - WriteFileResult, - // Execution session type - ExecutionSession, - PortStatusResult, - // Logger types - LogContext, - Logger, - LogLevel -} from "@repo/shared"; - -// Export runtime values from shared +export * from '@repo/shared'; +// Export type guards for runtime validation export { - Execution, - ResultImpl, - createLogger, - createNoOpLogger, - getLogger, - LogLevelEnum, - runWithLogger, - TraceContext, isExecResult, isProcess, isProcessStatus From c673ca2d71fc2b15d847c0f89d84ebf1db11d61f Mon Sep 17 00:00:00 2001 From: Naresh Date: Wed, 29 Oct 2025 16:39:31 +0000 Subject: [PATCH 15/16] update lockfile --- package-lock.json | 74 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 72 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3bb697c4..038ce5de 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,8 @@ "workspaces": [ "packages/*", "tooling/*", - "tests/integration" + "tests/integration", + "examples/*" ], "devDependencies": { "@biomejs/biome": "^2.1.2", @@ -42,6 +43,42 @@ "ws": "^8.18.3" } }, + "examples/claude-code": { + "name": "@cloudflare/sandbox-claude-code-example", + "version": "1.0.0", + "license": "MIT", + "devDependencies": { + "@cloudflare/sandbox": "*", + "@types/node": "^24.9.1", + "typescript": "^5.8.3", + "wrangler": "^4.44.0" + } + }, + "examples/code-interpreter": { + "name": "@cloudflare/sandbox-code-interpreter-example", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "@cloudflare/sandbox": "*", + "openai": "^5.12.0" + }, + "devDependencies": { + "@types/node": "^24.9.1", + "typescript": "^5.8.3", + "wrangler": "^4.44.0" + } + }, + "examples/minimal": { + "name": "@cloudflare/sandbox-minimal-example", + "version": "1.0.0", + "license": "MIT", + "devDependencies": { + "@cloudflare/sandbox": "*", + "@types/node": "^24.9.1", + "typescript": "^5.8.3", + "wrangler": "^4.44.0" + } + }, "node_modules/@actions/core": { "version": "1.11.1", "dev": true, @@ -647,6 +684,18 @@ "resolved": "packages/sandbox", "link": true }, + "node_modules/@cloudflare/sandbox-claude-code-example": { + "resolved": "examples/claude-code", + "link": true + }, + "node_modules/@cloudflare/sandbox-code-interpreter-example": { + "resolved": "examples/code-interpreter", + "link": true + }, + "node_modules/@cloudflare/sandbox-minimal-example": { + "resolved": "examples/minimal", + "link": true + }, "node_modules/@cloudflare/unenv-preset": { "version": "2.7.7", "dev": true, @@ -5188,6 +5237,27 @@ "wrappy": "1" } }, + "node_modules/openai": { + "version": "5.23.2", + "resolved": "https://registry.npmjs.org/openai/-/openai-5.23.2.tgz", + "integrity": "sha512-MQBzmTulj+MM5O8SKEk/gL8a7s5mktS9zUtAkU257WjvobGc9nKcBuVwjyEEcb9SI8a8Y2G/mzn3vm9n1Jlleg==", + "license": "Apache-2.0", + "bin": { + "openai": "bin/cli" + }, + "peerDependencies": { + "ws": "^8.18.0", + "zod": "^3.23.8" + }, + "peerDependenciesMeta": { + "ws": { + "optional": true + }, + "zod": { + "optional": true + } + } + }, "node_modules/outdent": { "version": "0.5.0", "dev": true, @@ -7162,7 +7232,7 @@ }, "node_modules/ws": { "version": "8.18.3", - "dev": true, + "devOptional": true, "license": "MIT", "engines": { "node": ">=10.0.0" From 39f6dd80b4b82e12c8333fdd9205e350e9e33310 Mon Sep 17 00:00:00 2001 From: Naresh Date: Wed, 29 Oct 2025 16:43:57 +0000 Subject: [PATCH 16/16] Update lockfile --- package-lock.json | 8138 ++++++++++++++++++++++++++++----------------- 1 file changed, 5025 insertions(+), 3113 deletions(-) diff --git a/package-lock.json b/package-lock.json index 038ce5de..e1bcc46c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -81,6 +81,8 @@ }, "node_modules/@actions/core": { "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.11.1.tgz", + "integrity": "sha512-hXJCSrkwfA46Vd9Z3q4cpEpHB1rL5NG04+/rbqW9d3+CSvtB1tYe8UTpAlixa1vj0m/ULglfEK2UKxMGxCxv5A==", "dev": true, "license": "MIT", "dependencies": { @@ -90,6 +92,8 @@ }, "node_modules/@actions/exec": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.1.1.tgz", + "integrity": "sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==", "dev": true, "license": "MIT", "dependencies": { @@ -98,6 +102,8 @@ }, "node_modules/@actions/http-client": { "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.2.3.tgz", + "integrity": "sha512-mx8hyJi/hjFvbPokCg4uRd4ZX78t+YyRPtnKWwIl+RzNaVuFpQHfmlGVfsKEJN8LwTCvL+DfVgAM04XaHkm6bA==", "dev": true, "license": "MIT", "dependencies": { @@ -107,6 +113,8 @@ }, "node_modules/@actions/http-client/node_modules/undici": { "version": "5.29.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.29.0.tgz", + "integrity": "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==", "dev": true, "license": "MIT", "dependencies": { @@ -118,11 +126,15 @@ }, "node_modules/@actions/io": { "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@actions/io/-/io-1.1.3.tgz", + "integrity": "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q==", "dev": true, "license": "MIT" }, "node_modules/@babel/code-frame": { "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", "dev": true, "license": "MIT", "dependencies": { @@ -135,7 +147,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.28.4", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.5.tgz", + "integrity": "sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==", "dev": true, "license": "MIT", "engines": { @@ -143,19 +157,21 @@ } }, "node_modules/@babel/core": { - "version": "7.28.4", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.5.tgz", + "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.3", + "@babel/generator": "^7.28.5", "@babel/helper-compilation-targets": "^7.27.2", "@babel/helper-module-transforms": "^7.28.3", "@babel/helpers": "^7.28.4", - "@babel/parser": "^7.28.4", + "@babel/parser": "^7.28.5", "@babel/template": "^7.27.2", - "@babel/traverse": "^7.28.4", - "@babel/types": "^7.28.4", + "@babel/traverse": "^7.28.5", + "@babel/types": "^7.28.5", "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", @@ -173,6 +189,8 @@ }, "node_modules/@babel/core/node_modules/semver": { "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "license": "ISC", "bin": { @@ -198,6 +216,8 @@ }, "node_modules/@babel/helper-compilation-targets": { "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", + "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", "dev": true, "license": "MIT", "dependencies": { @@ -213,6 +233,8 @@ }, "node_modules/@babel/helper-compilation-targets/node_modules/semver": { "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "license": "ISC", "bin": { @@ -221,6 +243,8 @@ }, "node_modules/@babel/helper-globals": { "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", "dev": true, "license": "MIT", "engines": { @@ -229,6 +253,8 @@ }, "node_modules/@babel/helper-module-imports": { "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", + "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", "dev": true, "license": "MIT", "dependencies": { @@ -241,6 +267,8 @@ }, "node_modules/@babel/helper-module-transforms": { "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz", + "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==", "dev": true, "license": "MIT", "dependencies": { @@ -257,6 +285,8 @@ }, "node_modules/@babel/helper-plugin-utils": { "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", + "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", "dev": true, "license": "MIT", "engines": { @@ -265,6 +295,8 @@ }, "node_modules/@babel/helper-string-parser": { "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", "dev": true, "license": "MIT", "engines": { @@ -283,6 +315,8 @@ }, "node_modules/@babel/helper-validator-option": { "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", "dev": true, "license": "MIT", "engines": { @@ -291,6 +325,8 @@ }, "node_modules/@babel/helpers": { "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz", + "integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==", "dev": true, "license": "MIT", "dependencies": { @@ -319,6 +355,8 @@ }, "node_modules/@babel/plugin-transform-react-jsx-self": { "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz", + "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==", "dev": true, "license": "MIT", "dependencies": { @@ -333,6 +371,8 @@ }, "node_modules/@babel/plugin-transform-react-jsx-source": { "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz", + "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==", "dev": true, "license": "MIT", "dependencies": { @@ -347,6 +387,8 @@ }, "node_modules/@babel/runtime": { "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz", + "integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==", "dev": true, "license": "MIT", "engines": { @@ -355,6 +397,8 @@ }, "node_modules/@babel/template": { "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", "dev": true, "license": "MIT", "dependencies": { @@ -367,16 +411,18 @@ } }, "node_modules/@babel/traverse": { - "version": "7.28.4", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.5.tgz", + "integrity": "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==", "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.3", + "@babel/generator": "^7.28.5", "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.28.4", + "@babel/parser": "^7.28.5", "@babel/template": "^7.27.2", - "@babel/types": "^7.28.4", + "@babel/types": "^7.28.5", "debug": "^4.3.1" }, "engines": { @@ -398,7 +444,9 @@ } }, "node_modules/@biomejs/biome": { - "version": "2.2.5", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-2.3.2.tgz", + "integrity": "sha512-8e9tzamuDycx7fdrcJ/F/GDZ8SYukc5ud6tDicjjFqURKYFSWMl0H0iXNXZEGmcmNUmABgGuHThPykcM41INgg==", "dev": true, "license": "MIT OR Apache-2.0", "bin": { @@ -412,18 +460,20 @@ "url": "https://opencollective.com/biome" }, "optionalDependencies": { - "@biomejs/cli-darwin-arm64": "2.2.5", - "@biomejs/cli-darwin-x64": "2.2.5", - "@biomejs/cli-linux-arm64": "2.2.5", - "@biomejs/cli-linux-arm64-musl": "2.2.5", - "@biomejs/cli-linux-x64": "2.2.5", - "@biomejs/cli-linux-x64-musl": "2.2.5", - "@biomejs/cli-win32-arm64": "2.2.5", - "@biomejs/cli-win32-x64": "2.2.5" + "@biomejs/cli-darwin-arm64": "2.3.2", + "@biomejs/cli-darwin-x64": "2.3.2", + "@biomejs/cli-linux-arm64": "2.3.2", + "@biomejs/cli-linux-arm64-musl": "2.3.2", + "@biomejs/cli-linux-x64": "2.3.2", + "@biomejs/cli-linux-x64-musl": "2.3.2", + "@biomejs/cli-win32-arm64": "2.3.2", + "@biomejs/cli-win32-x64": "2.3.2" } }, "node_modules/@biomejs/cli-darwin-arm64": { - "version": "2.2.5", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-2.3.2.tgz", + "integrity": "sha512-4LECm4kc3If0JISai4c3KWQzukoUdpxy4fRzlrPcrdMSRFksR9ZoXK7JBcPuLBmd2SoT4/d7CQS33VnZpgBjew==", "cpu": [ "arm64" ], @@ -437,8 +487,129 @@ "node": ">=14.21.3" } }, + "node_modules/@biomejs/cli-darwin-x64": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-2.3.2.tgz", + "integrity": "sha512-jNMnfwHT4N3wi+ypRfMTjLGnDmKYGzxVr1EYAPBcauRcDnICFXN81wD6wxJcSUrLynoyyYCdfW6vJHS/IAoTDA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-arm64": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-2.3.2.tgz", + "integrity": "sha512-amnqvk+gWybbQleRRq8TMe0rIv7GHss8mFJEaGuEZYWg1Tw14YKOkeo8h6pf1c+d3qR+JU4iT9KXnBKGON4klw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-arm64-musl": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.3.2.tgz", + "integrity": "sha512-2Zz4usDG1GTTPQnliIeNx6eVGGP2ry5vE/v39nT73a3cKN6t5H5XxjcEoZZh62uVZvED7hXXikclvI64vZkYqw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-x64": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-2.3.2.tgz", + "integrity": "sha512-8BG/vRAhFz1pmuyd24FQPhNeueLqPtwvZk6yblABY2gzL2H8fLQAF/Z2OPIc+BPIVPld+8cSiKY/KFh6k81xfA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-x64-musl": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-2.3.2.tgz", + "integrity": "sha512-gzB19MpRdTuOuLtPpFBGrV3Lq424gHyq2lFj8wfX9tvLMLdmA/R9C7k/mqBp/spcbWuHeIEKgEs3RviOPcWGBA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-win32-arm64": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-2.3.2.tgz", + "integrity": "sha512-lCruqQlfWjhMlOdyf5pDHOxoNm4WoyY2vZ4YN33/nuZBRstVDuqPPjS0yBkbUlLEte11FbpW+wWSlfnZfSIZvg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-win32-x64": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-2.3.2.tgz", + "integrity": "sha512-6Ee9P26DTb4D8sN9nXxgbi9Dw5vSOfH98M7UlmkjKB2vtUbrRqCbZiNfryGiwnPIpd6YUoTl7rLVD2/x1CyEHQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.21.3" + } + }, "node_modules/@changesets/apply-release-plan": { "version": "7.0.13", + "resolved": "https://registry.npmjs.org/@changesets/apply-release-plan/-/apply-release-plan-7.0.13.tgz", + "integrity": "sha512-BIW7bofD2yAWoE8H4V40FikC+1nNFEKBisMECccS16W1rt6qqhNTBDmIw5HaqmMgtLNz9e7oiALiEUuKrQ4oHg==", "dev": true, "license": "MIT", "dependencies": { @@ -459,6 +630,8 @@ }, "node_modules/@changesets/assemble-release-plan": { "version": "6.0.9", + "resolved": "https://registry.npmjs.org/@changesets/assemble-release-plan/-/assemble-release-plan-6.0.9.tgz", + "integrity": "sha512-tPgeeqCHIwNo8sypKlS3gOPmsS3wP0zHt67JDuL20P4QcXiw/O4Hl7oXiuLnP9yg+rXLQ2sScdV1Kkzde61iSQ==", "dev": true, "license": "MIT", "dependencies": { @@ -472,6 +645,8 @@ }, "node_modules/@changesets/changelog-git": { "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@changesets/changelog-git/-/changelog-git-0.2.1.tgz", + "integrity": "sha512-x/xEleCFLH28c3bQeQIyeZf8lFXyDFVn1SgcBiR2Tw/r4IAWlk1fzxCEZ6NxQAjF2Nwtczoen3OA2qR+UawQ8Q==", "dev": true, "license": "MIT", "dependencies": { @@ -480,6 +655,8 @@ }, "node_modules/@changesets/changelog-github": { "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@changesets/changelog-github/-/changelog-github-0.5.1.tgz", + "integrity": "sha512-BVuHtF+hrhUScSoHnJwTELB4/INQxVFc+P/Qdt20BLiBFIHFJDDUaGsZw+8fQeJTRP5hJZrzpt3oZWh0G19rAQ==", "dev": true, "license": "MIT", "dependencies": { @@ -490,6 +667,8 @@ }, "node_modules/@changesets/cli": { "version": "2.29.7", + "resolved": "https://registry.npmjs.org/@changesets/cli/-/cli-2.29.7.tgz", + "integrity": "sha512-R7RqWoaksyyKXbKXBTbT4REdy22yH81mcFK6sWtqSanxUCbUi9Uf+6aqxZtDQouIqPdem2W56CdxXgsxdq7FLQ==", "dev": true, "license": "MIT", "dependencies": { @@ -528,6 +707,8 @@ }, "node_modules/@changesets/config": { "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@changesets/config/-/config-3.1.1.tgz", + "integrity": "sha512-bd+3Ap2TKXxljCggI0mKPfzCQKeV/TU4yO2h2C6vAihIo8tzseAn2e7klSuiyYYXvgu53zMN1OeYMIQkaQoWnA==", "dev": true, "license": "MIT", "dependencies": { @@ -542,6 +723,8 @@ }, "node_modules/@changesets/errors": { "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@changesets/errors/-/errors-0.2.0.tgz", + "integrity": "sha512-6BLOQUscTpZeGljvyQXlWOItQyU71kCdGz7Pi8H8zdw6BI0g3m43iL4xKUVPWtG+qrrL9DTjpdn8eYuCQSRpow==", "dev": true, "license": "MIT", "dependencies": { @@ -550,6 +733,8 @@ }, "node_modules/@changesets/get-dependents-graph": { "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@changesets/get-dependents-graph/-/get-dependents-graph-2.1.3.tgz", + "integrity": "sha512-gphr+v0mv2I3Oxt19VdWRRUxq3sseyUpX9DaHpTUmLj92Y10AGy+XOtV+kbM6L/fDcpx7/ISDFK6T8A/P3lOdQ==", "dev": true, "license": "MIT", "dependencies": { @@ -561,6 +746,8 @@ }, "node_modules/@changesets/get-github-info": { "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@changesets/get-github-info/-/get-github-info-0.6.0.tgz", + "integrity": "sha512-v/TSnFVXI8vzX9/w3DU2Ol+UlTZcu3m0kXTjTT4KlAdwSvwutcByYwyYn9hwerPWfPkT2JfpoX0KgvCEi8Q/SA==", "dev": true, "license": "MIT", "dependencies": { @@ -570,6 +757,8 @@ }, "node_modules/@changesets/get-release-plan": { "version": "4.0.13", + "resolved": "https://registry.npmjs.org/@changesets/get-release-plan/-/get-release-plan-4.0.13.tgz", + "integrity": "sha512-DWG1pus72FcNeXkM12tx+xtExyH/c9I1z+2aXlObH3i9YA7+WZEVaiHzHl03thpvAgWTRaH64MpfHxozfF7Dvg==", "dev": true, "license": "MIT", "dependencies": { @@ -583,11 +772,15 @@ }, "node_modules/@changesets/get-version-range-type": { "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@changesets/get-version-range-type/-/get-version-range-type-0.4.0.tgz", + "integrity": "sha512-hwawtob9DryoGTpixy1D3ZXbGgJu1Rhr+ySH2PvTLHvkZuQ7sRT4oQwMh0hbqZH1weAooedEjRsbrWcGLCeyVQ==", "dev": true, "license": "MIT" }, "node_modules/@changesets/git": { "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@changesets/git/-/git-3.0.4.tgz", + "integrity": "sha512-BXANzRFkX+XcC1q/d27NKvlJ1yf7PSAgi8JG6dt8EfbHFHi4neau7mufcSca5zRhwOL8j9s6EqsxmT+s+/E6Sw==", "dev": true, "license": "MIT", "dependencies": { @@ -600,6 +793,8 @@ }, "node_modules/@changesets/logger": { "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@changesets/logger/-/logger-0.1.1.tgz", + "integrity": "sha512-OQtR36ZlnuTxKqoW4Sv6x5YIhOmClRd5pWsjZsddYxpWs517R0HkyiefQPIytCVh4ZcC5x9XaG8KTdd5iRQUfg==", "dev": true, "license": "MIT", "dependencies": { @@ -608,6 +803,8 @@ }, "node_modules/@changesets/parse": { "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@changesets/parse/-/parse-0.4.1.tgz", + "integrity": "sha512-iwksMs5Bf/wUItfcg+OXrEpravm5rEd9Bf4oyIPL4kVTmJQ7PNDSd6MDYkpSJR1pn7tz/k8Zf2DhTCqX08Ou+Q==", "dev": true, "license": "MIT", "dependencies": { @@ -617,6 +814,8 @@ }, "node_modules/@changesets/pre": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@changesets/pre/-/pre-2.0.2.tgz", + "integrity": "sha512-HaL/gEyFVvkf9KFg6484wR9s0qjAXlZ8qWPDkTyKF6+zqjBe/I2mygg3MbpZ++hdi0ToqNUF8cjj7fBy0dg8Ug==", "dev": true, "license": "MIT", "dependencies": { @@ -628,6 +827,8 @@ }, "node_modules/@changesets/read": { "version": "0.6.5", + "resolved": "https://registry.npmjs.org/@changesets/read/-/read-0.6.5.tgz", + "integrity": "sha512-UPzNGhsSjHD3Veb0xO/MwvasGe8eMyNrR/sT9gR8Q3DhOQZirgKhhXv/8hVsI0QpPjR004Z9iFxoJU6in3uGMg==", "dev": true, "license": "MIT", "dependencies": { @@ -642,6 +843,8 @@ }, "node_modules/@changesets/should-skip-package": { "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@changesets/should-skip-package/-/should-skip-package-0.1.2.tgz", + "integrity": "sha512-qAK/WrqWLNCP22UDdBTMPH5f41elVDlsNyat180A33dWxuUDyNpg6fPi/FyTZwRriVjg0L8gnjJn2F9XAoF0qw==", "dev": true, "license": "MIT", "dependencies": { @@ -651,11 +854,15 @@ }, "node_modules/@changesets/types": { "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@changesets/types/-/types-6.1.0.tgz", + "integrity": "sha512-rKQcJ+o1nKNgeoYRHKOS07tAMNd3YSN0uHaJOZYjBAgxfV7TUE7JE+z4BzZdQwb5hKaYbayKN5KrYV7ODb2rAA==", "dev": true, "license": "MIT" }, "node_modules/@changesets/write": { "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@changesets/write/-/write-0.4.0.tgz", + "integrity": "sha512-CdTLvIOPiCNuH71pyDu3rA+Q0n65cmAbXnwWH84rKGiFumFzkmHNT8KHTMEchcxN+Kl8I54xGUhJ7l3E7X396Q==", "dev": true, "license": "MIT", "dependencies": { @@ -667,10 +874,14 @@ }, "node_modules/@cloudflare/containers": { "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@cloudflare/containers/-/containers-0.0.29.tgz", + "integrity": "sha512-tiVCbS7p2SBWNZd4Ym6zx2gMJdQqq7VhWStID0DkQ1iCyqmLis1hDUNmeVbHCYKSnsyZq/SUxFspRwrXNaA3Yg==", "license": "ISC" }, "node_modules/@cloudflare/kv-asset-handler": { "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.4.0.tgz", + "integrity": "sha512-+tv3z+SPp+gqTIcImN9o0hqE9xyfQjI1XD9pL6NuKjua9B1y7mNYv0S9cP+QEbA4ppVgGZEmKOvHX5G5Ei1CVA==", "dev": true, "license": "MIT OR Apache-2.0", "dependencies": { @@ -697,7 +908,9 @@ "link": true }, "node_modules/@cloudflare/unenv-preset": { - "version": "2.7.7", + "version": "2.7.8", + "resolved": "https://registry.npmjs.org/@cloudflare/unenv-preset/-/unenv-preset-2.7.8.tgz", + "integrity": "sha512-Ky929MfHh+qPhwCapYrRPwPVHtA2Ioex/DbGZyskGyNRDe9Ru3WThYZivyNVaPy5ergQSgMs9OKrM9Ajtz9F6w==", "dev": true, "license": "MIT OR Apache-2.0", "peerDependencies": { @@ -711,120 +924,31 @@ } }, "node_modules/@cloudflare/vite-plugin": { - "version": "1.13.12", + "version": "1.13.17", + "resolved": "https://registry.npmjs.org/@cloudflare/vite-plugin/-/vite-plugin-1.13.17.tgz", + "integrity": "sha512-JYBs+KwN/fcqcOwa4hZ5SPLUAZ2idksZ4umeja4TWPPUWvO2f0Lm0bOjVHI+rFuq72b2vixx2coNJSyntEBUsA==", "dev": true, "license": "MIT", "dependencies": { - "@cloudflare/unenv-preset": "2.7.7", + "@cloudflare/unenv-preset": "2.7.8", "@remix-run/node-fetch-server": "^0.8.0", "get-port": "^7.1.0", - "miniflare": "4.20251008.0", + "miniflare": "4.20251011.1", "picocolors": "^1.1.1", "tinyglobby": "^0.2.12", "unenv": "2.0.0-rc.21", - "wrangler": "4.42.2", + "wrangler": "4.45.2", "ws": "8.18.0" }, "peerDependencies": { "vite": "^6.1.0 || ^7.0.0", - "wrangler": "^4.42.2" - } - }, - "node_modules/@cloudflare/vite-plugin/node_modules/@esbuild/darwin-arm64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.4.tgz", - "integrity": "sha512-Y1giCfM4nlHDWEfSckMzeWNdQS31BQGs9/rouw6Ub91tkK79aIMTH3q9xHvzH8d0wDru5Ci0kWB8b3up/nl16g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@cloudflare/vite-plugin/node_modules/esbuild": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.4.tgz", - "integrity": "sha512-8pgjLUcUjcgDg+2Q4NYXnPbo/vncAY4UmyaCm0jZevERqCHZIaWwdJHkf8XQtu4AxSKCdvrUbT0XUr1IdZzI8Q==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.4", - "@esbuild/android-arm": "0.25.4", - "@esbuild/android-arm64": "0.25.4", - "@esbuild/android-x64": "0.25.4", - "@esbuild/darwin-arm64": "0.25.4", - "@esbuild/darwin-x64": "0.25.4", - "@esbuild/freebsd-arm64": "0.25.4", - "@esbuild/freebsd-x64": "0.25.4", - "@esbuild/linux-arm": "0.25.4", - "@esbuild/linux-arm64": "0.25.4", - "@esbuild/linux-ia32": "0.25.4", - "@esbuild/linux-loong64": "0.25.4", - "@esbuild/linux-mips64el": "0.25.4", - "@esbuild/linux-ppc64": "0.25.4", - "@esbuild/linux-riscv64": "0.25.4", - "@esbuild/linux-s390x": "0.25.4", - "@esbuild/linux-x64": "0.25.4", - "@esbuild/netbsd-arm64": "0.25.4", - "@esbuild/netbsd-x64": "0.25.4", - "@esbuild/openbsd-arm64": "0.25.4", - "@esbuild/openbsd-x64": "0.25.4", - "@esbuild/sunos-x64": "0.25.4", - "@esbuild/win32-arm64": "0.25.4", - "@esbuild/win32-ia32": "0.25.4", - "@esbuild/win32-x64": "0.25.4" - } - }, - "node_modules/@cloudflare/vite-plugin/node_modules/wrangler": { - "version": "4.42.2", - "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-4.42.2.tgz", - "integrity": "sha512-1iTnbjB4F12KSP1zbfxQL495xarS+vdrZnulQP2SEcAxDTUGn7N9zk1O2WtFOc+Fhcgl+9/sdz/4AL9pF34Pwg==", - "dev": true, - "license": "MIT OR Apache-2.0", - "dependencies": { - "@cloudflare/kv-asset-handler": "0.4.0", - "@cloudflare/unenv-preset": "2.7.7", - "blake3-wasm": "2.1.5", - "esbuild": "0.25.4", - "miniflare": "4.20251008.0", - "path-to-regexp": "6.3.0", - "unenv": "2.0.0-rc.21", - "workerd": "1.20251008.0" - }, - "bin": { - "wrangler": "bin/wrangler.js", - "wrangler2": "bin/wrangler.js" - }, - "engines": { - "node": ">=18.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - }, - "peerDependencies": { - "@cloudflare/workers-types": "^4.20251008.0" - }, - "peerDependenciesMeta": { - "@cloudflare/workers-types": { - "optional": true - } + "wrangler": "^4.45.2" } }, "node_modules/@cloudflare/vite-plugin/node_modules/ws": { "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", "dev": true, "license": "MIT", "engines": { @@ -844,16 +968,18 @@ } }, "node_modules/@cloudflare/vitest-pool-workers": { - "version": "0.9.12", + "version": "0.9.14", + "resolved": "https://registry.npmjs.org/@cloudflare/vitest-pool-workers/-/vitest-pool-workers-0.9.14.tgz", + "integrity": "sha512-1D/1KFa32EymaYDojWcrmUyMbHJwewn/mZSxsAqXdybvKMrHVaoaqGpLoH9bgWSfbrGs4af4RrmIXMINOqc4Lw==", "dev": true, "license": "MIT", "dependencies": { "birpc": "0.2.14", "cjs-module-lexer": "^1.2.3", "devalue": "^5.3.2", - "miniflare": "4.20251008.0", + "miniflare": "4.20251011.0", "semver": "^7.7.1", - "wrangler": "4.42.2", + "wrangler": "4.44.0", "zod": "^3.22.3" }, "peerDependencies": { @@ -862,282 +988,47 @@ "vitest": "2.0.x - 3.2.x" } }, - "node_modules/@cloudflare/vitest-pool-workers/node_modules/@esbuild/darwin-arm64": { + "node_modules/@cloudflare/vitest-pool-workers/node_modules/@esbuild/aix-ppc64": { "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.4.tgz", - "integrity": "sha512-Y1giCfM4nlHDWEfSckMzeWNdQS31BQGs9/rouw6Ub91tkK79aIMTH3q9xHvzH8d0wDru5Ci0kWB8b3up/nl16g==", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.4.tgz", + "integrity": "sha512-1VCICWypeQKhVbE9oW/sJaAmjLxhVqacdkvPLEjwlttjfwENRSClS8EjBz0KzRyFSCPDIkuXW34Je/vk7zdB7Q==", "cpu": [ - "arm64" + "ppc64" ], "dev": true, "license": "MIT", "optional": true, "os": [ - "darwin" + "aix" ], "engines": { "node": ">=18" } }, - "node_modules/@cloudflare/vitest-pool-workers/node_modules/esbuild": { + "node_modules/@cloudflare/vitest-pool-workers/node_modules/@esbuild/android-arm": { "version": "0.25.4", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.4.tgz", - "integrity": "sha512-8pgjLUcUjcgDg+2Q4NYXnPbo/vncAY4UmyaCm0jZevERqCHZIaWwdJHkf8XQtu4AxSKCdvrUbT0XUr1IdZzI8Q==", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.4.tgz", + "integrity": "sha512-QNdQEps7DfFwE3hXiU4BZeOV68HHzYwGd0Nthhd3uCkkEKK7/R6MTgM0P7H7FAs5pU/DIWsviMmEGxEoxIZ+ZQ==", + "cpu": [ + "arm" + ], "dev": true, - "hasInstallScript": true, "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, + "optional": true, + "os": [ + "android" + ], "engines": { "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.4", - "@esbuild/android-arm": "0.25.4", - "@esbuild/android-arm64": "0.25.4", - "@esbuild/android-x64": "0.25.4", - "@esbuild/darwin-arm64": "0.25.4", - "@esbuild/darwin-x64": "0.25.4", - "@esbuild/freebsd-arm64": "0.25.4", - "@esbuild/freebsd-x64": "0.25.4", - "@esbuild/linux-arm": "0.25.4", - "@esbuild/linux-arm64": "0.25.4", - "@esbuild/linux-ia32": "0.25.4", - "@esbuild/linux-loong64": "0.25.4", - "@esbuild/linux-mips64el": "0.25.4", - "@esbuild/linux-ppc64": "0.25.4", - "@esbuild/linux-riscv64": "0.25.4", - "@esbuild/linux-s390x": "0.25.4", - "@esbuild/linux-x64": "0.25.4", - "@esbuild/netbsd-arm64": "0.25.4", - "@esbuild/netbsd-x64": "0.25.4", - "@esbuild/openbsd-arm64": "0.25.4", - "@esbuild/openbsd-x64": "0.25.4", - "@esbuild/sunos-x64": "0.25.4", - "@esbuild/win32-arm64": "0.25.4", - "@esbuild/win32-ia32": "0.25.4", - "@esbuild/win32-x64": "0.25.4" } }, - "node_modules/@cloudflare/vitest-pool-workers/node_modules/wrangler": { - "version": "4.42.2", - "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-4.42.2.tgz", - "integrity": "sha512-1iTnbjB4F12KSP1zbfxQL495xarS+vdrZnulQP2SEcAxDTUGn7N9zk1O2WtFOc+Fhcgl+9/sdz/4AL9pF34Pwg==", - "dev": true, - "license": "MIT OR Apache-2.0", - "dependencies": { - "@cloudflare/kv-asset-handler": "0.4.0", - "@cloudflare/unenv-preset": "2.7.7", - "blake3-wasm": "2.1.5", - "esbuild": "0.25.4", - "miniflare": "4.20251008.0", - "path-to-regexp": "6.3.0", - "unenv": "2.0.0-rc.21", - "workerd": "1.20251008.0" - }, - "bin": { - "wrangler": "bin/wrangler.js", - "wrangler2": "bin/wrangler.js" - }, - "engines": { - "node": ">=18.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - }, - "peerDependencies": { - "@cloudflare/workers-types": "^4.20251008.0" - }, - "peerDependenciesMeta": { - "@cloudflare/workers-types": { - "optional": true - } - } - }, - "node_modules/@cloudflare/workerd-darwin-64": { - "version": "1.20251011.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20251011.0.tgz", - "integrity": "sha512-0DirVP+Z82RtZLlK2B+VhLOkk+ShBqDYO/jhcRw4oVlp0TOvk3cOVZChrt3+y3NV8Y/PYgTEywzLKFSziK4wCg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=16" - } - }, - "node_modules/@cloudflare/workerd-darwin-arm64": { - "version": "1.20251008.0", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=16" - } - }, - "node_modules/@cloudflare/workerd-linux-64": { - "version": "1.20251011.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20251011.0.tgz", - "integrity": "sha512-BccMiBzFlWZyFghIw2szanmYJrJGBGHomw2y/GV6pYXChFzMGZkeCEMfmCyJj29xczZXxcZmUVJxNy4eJxO8QA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=16" - } - }, - "node_modules/@cloudflare/workerd-linux-arm64": { - "version": "1.20251011.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20251011.0.tgz", - "integrity": "sha512-79o/216lsbAbKEVDZYXR24ivEIE2ysDL9jvo0rDTkViLWju9dAp3CpyetglpJatbSi3uWBPKZBEOqN68zIjVsQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=16" - } - }, - "node_modules/@cloudflare/workerd-windows-64": { - "version": "1.20251011.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20251011.0.tgz", - "integrity": "sha512-RIXUQRchFdqEvaUqn1cXZXSKjpqMaSaVAkI5jNZ8XzAw/bw2bcdOVUtakrflgxDprltjFb0PTNtuss1FKtH9Jg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=16" - } - }, - "node_modules/@cloudflare/workers-types": { - "version": "4.20251011.0", - "dev": true, - "license": "MIT OR Apache-2.0" - }, - "node_modules/@cspotcode/source-map-support": { - "version": "0.8.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/trace-mapping": "0.3.9" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { - "version": "0.3.9", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, - "node_modules/@emnapi/core": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.6.0.tgz", - "integrity": "sha512-zq/ay+9fNIJJtJiZxdTnXS20PllcYMX3OE23ESc4HK/bdYu3cOWYVhsOhVnXALfU/uqJIxn5NBPd9z4v+SfoSg==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/wasi-threads": "1.1.0", - "tslib": "^2.4.0" - } - }, - "node_modules/@emnapi/runtime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.6.0.tgz", - "integrity": "sha512-obtUmAHTMjll499P+D9A3axeJFlhdjOWdKUNs/U6QIGT7V5RjcUW1xToAzjvmgTSQhDbYn/NwfTRoJcQ2rNBxA==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@emnapi/wasi-threads": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz", - "integrity": "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.4.tgz", - "integrity": "sha512-1VCICWypeQKhVbE9oW/sJaAmjLxhVqacdkvPLEjwlttjfwENRSClS8EjBz0KzRyFSCPDIkuXW34Je/vk7zdB7Q==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.4.tgz", - "integrity": "sha512-QNdQEps7DfFwE3hXiU4BZeOV68HHzYwGd0Nthhd3uCkkEKK7/R6MTgM0P7H7FAs5pU/DIWsviMmEGxEoxIZ+ZQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.4.tgz", - "integrity": "sha512-bBy69pgfhMGtCnwpC/x5QhfxAz/cBgQ9enbtwjf6V9lnPI/hMyT9iWpR1arm0l3kttTr4L0KSLpKmLp/ilKS9A==", - "cpu": [ - "arm64" - ], + "node_modules/@cloudflare/vitest-pool-workers/node_modules/@esbuild/android-arm64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.4.tgz", + "integrity": "sha512-bBy69pgfhMGtCnwpC/x5QhfxAz/cBgQ9enbtwjf6V9lnPI/hMyT9iWpR1arm0l3kttTr4L0KSLpKmLp/ilKS9A==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", "optional": true, @@ -1148,7 +1039,7 @@ "node": ">=18" } }, - "node_modules/@esbuild/android-x64": { + "node_modules/@cloudflare/vitest-pool-workers/node_modules/@esbuild/android-x64": { "version": "0.25.4", "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.4.tgz", "integrity": "sha512-TVhdVtQIFuVpIIR282btcGC2oGQoSfZfmBdTip2anCaVYcqWlZXGcdcKIUklfX2wj0JklNYgz39OBqh2cqXvcQ==", @@ -1165,11 +1056,14 @@ "node": ">=18" } }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.10", + "node_modules/@cloudflare/vitest-pool-workers/node_modules/@esbuild/darwin-arm64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.4.tgz", + "integrity": "sha512-Y1giCfM4nlHDWEfSckMzeWNdQS31BQGs9/rouw6Ub91tkK79aIMTH3q9xHvzH8d0wDru5Ci0kWB8b3up/nl16g==", "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1179,7 +1073,7 @@ "node": ">=18" } }, - "node_modules/@esbuild/darwin-x64": { + "node_modules/@cloudflare/vitest-pool-workers/node_modules/@esbuild/darwin-x64": { "version": "0.25.4", "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.4.tgz", "integrity": "sha512-CJsry8ZGM5VFVeyUYB3cdKpd/H69PYez4eJh1W/t38vzutdjEjtP7hB6eLKBoOdxcAlCtEYHzQ/PJ/oU9I4u0A==", @@ -1196,7 +1090,7 @@ "node": ">=18" } }, - "node_modules/@esbuild/freebsd-arm64": { + "node_modules/@cloudflare/vitest-pool-workers/node_modules/@esbuild/freebsd-arm64": { "version": "0.25.4", "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.4.tgz", "integrity": "sha512-yYq+39NlTRzU2XmoPW4l5Ifpl9fqSk0nAJYM/V/WUGPEFfek1epLHJIkTQM6bBs1swApjO5nWgvr843g6TjxuQ==", @@ -1213,7 +1107,7 @@ "node": ">=18" } }, - "node_modules/@esbuild/freebsd-x64": { + "node_modules/@cloudflare/vitest-pool-workers/node_modules/@esbuild/freebsd-x64": { "version": "0.25.4", "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.4.tgz", "integrity": "sha512-0FgvOJ6UUMflsHSPLzdfDnnBBVoCDtBTVyn/MrWloUNvq/5SFmh13l3dvgRPkDihRxb77Y17MbqbCAa2strMQQ==", @@ -1230,7 +1124,7 @@ "node": ">=18" } }, - "node_modules/@esbuild/linux-arm": { + "node_modules/@cloudflare/vitest-pool-workers/node_modules/@esbuild/linux-arm": { "version": "0.25.4", "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.4.tgz", "integrity": "sha512-kro4c0P85GMfFYqW4TWOpvmF8rFShbWGnrLqlzp4X1TNWjRY3JMYUfDCtOxPKOIY8B0WC8HN51hGP4I4hz4AaQ==", @@ -1247,7 +1141,7 @@ "node": ">=18" } }, - "node_modules/@esbuild/linux-arm64": { + "node_modules/@cloudflare/vitest-pool-workers/node_modules/@esbuild/linux-arm64": { "version": "0.25.4", "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.4.tgz", "integrity": "sha512-+89UsQTfXdmjIvZS6nUnOOLoXnkUTB9hR5QAeLrQdzOSWZvNSAXAtcRDHWtqAUtAmv7ZM1WPOOeSxDzzzMogiQ==", @@ -1264,7 +1158,7 @@ "node": ">=18" } }, - "node_modules/@esbuild/linux-ia32": { + "node_modules/@cloudflare/vitest-pool-workers/node_modules/@esbuild/linux-ia32": { "version": "0.25.4", "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.4.tgz", "integrity": "sha512-yTEjoapy8UP3rv8dB0ip3AfMpRbyhSN3+hY8mo/i4QXFeDxmiYbEKp3ZRjBKcOP862Ua4b1PDfwlvbuwY7hIGQ==", @@ -1281,7 +1175,7 @@ "node": ">=18" } }, - "node_modules/@esbuild/linux-loong64": { + "node_modules/@cloudflare/vitest-pool-workers/node_modules/@esbuild/linux-loong64": { "version": "0.25.4", "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.4.tgz", "integrity": "sha512-NeqqYkrcGzFwi6CGRGNMOjWGGSYOpqwCjS9fvaUlX5s3zwOtn1qwg1s2iE2svBe4Q/YOG1q6875lcAoQK/F4VA==", @@ -1298,7 +1192,7 @@ "node": ">=18" } }, - "node_modules/@esbuild/linux-mips64el": { + "node_modules/@cloudflare/vitest-pool-workers/node_modules/@esbuild/linux-mips64el": { "version": "0.25.4", "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.4.tgz", "integrity": "sha512-IcvTlF9dtLrfL/M8WgNI/qJYBENP3ekgsHbYUIzEzq5XJzzVEV/fXY9WFPfEEXmu3ck2qJP8LG/p3Q8f7Zc2Xg==", @@ -1315,7 +1209,7 @@ "node": ">=18" } }, - "node_modules/@esbuild/linux-ppc64": { + "node_modules/@cloudflare/vitest-pool-workers/node_modules/@esbuild/linux-ppc64": { "version": "0.25.4", "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.4.tgz", "integrity": "sha512-HOy0aLTJTVtoTeGZh4HSXaO6M95qu4k5lJcH4gxv56iaycfz1S8GO/5Jh6X4Y1YiI0h7cRyLi+HixMR+88swag==", @@ -1332,7 +1226,7 @@ "node": ">=18" } }, - "node_modules/@esbuild/linux-riscv64": { + "node_modules/@cloudflare/vitest-pool-workers/node_modules/@esbuild/linux-riscv64": { "version": "0.25.4", "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.4.tgz", "integrity": "sha512-i8JUDAufpz9jOzo4yIShCTcXzS07vEgWzyX3NH2G7LEFVgrLEhjwL3ajFE4fZI3I4ZgiM7JH3GQ7ReObROvSUA==", @@ -1349,7 +1243,7 @@ "node": ">=18" } }, - "node_modules/@esbuild/linux-s390x": { + "node_modules/@cloudflare/vitest-pool-workers/node_modules/@esbuild/linux-s390x": { "version": "0.25.4", "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.4.tgz", "integrity": "sha512-jFnu+6UbLlzIjPQpWCNh5QtrcNfMLjgIavnwPQAfoGx4q17ocOU9MsQ2QVvFxwQoWpZT8DvTLooTvmOQXkO51g==", @@ -1366,7 +1260,7 @@ "node": ">=18" } }, - "node_modules/@esbuild/linux-x64": { + "node_modules/@cloudflare/vitest-pool-workers/node_modules/@esbuild/linux-x64": { "version": "0.25.4", "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.4.tgz", "integrity": "sha512-6e0cvXwzOnVWJHq+mskP8DNSrKBr1bULBvnFLpc1KY+d+irZSgZ02TGse5FsafKS5jg2e4pbvK6TPXaF/A6+CA==", @@ -1383,7 +1277,7 @@ "node": ">=18" } }, - "node_modules/@esbuild/netbsd-arm64": { + "node_modules/@cloudflare/vitest-pool-workers/node_modules/@esbuild/netbsd-arm64": { "version": "0.25.4", "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.4.tgz", "integrity": "sha512-vUnkBYxZW4hL/ie91hSqaSNjulOnYXE1VSLusnvHg2u3jewJBz3YzB9+oCw8DABeVqZGg94t9tyZFoHma8gWZQ==", @@ -1400,7 +1294,7 @@ "node": ">=18" } }, - "node_modules/@esbuild/netbsd-x64": { + "node_modules/@cloudflare/vitest-pool-workers/node_modules/@esbuild/netbsd-x64": { "version": "0.25.4", "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.4.tgz", "integrity": "sha512-XAg8pIQn5CzhOB8odIcAm42QsOfa98SBeKUdo4xa8OvX8LbMZqEtgeWE9P/Wxt7MlG2QqvjGths+nq48TrUiKw==", @@ -1417,7 +1311,7 @@ "node": ">=18" } }, - "node_modules/@esbuild/openbsd-arm64": { + "node_modules/@cloudflare/vitest-pool-workers/node_modules/@esbuild/openbsd-arm64": { "version": "0.25.4", "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.4.tgz", "integrity": "sha512-Ct2WcFEANlFDtp1nVAXSNBPDxyU+j7+tId//iHXU2f/lN5AmO4zLyhDcpR5Cz1r08mVxzt3Jpyt4PmXQ1O6+7A==", @@ -1434,7 +1328,7 @@ "node": ">=18" } }, - "node_modules/@esbuild/openbsd-x64": { + "node_modules/@cloudflare/vitest-pool-workers/node_modules/@esbuild/openbsd-x64": { "version": "0.25.4", "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.4.tgz", "integrity": "sha512-xAGGhyOQ9Otm1Xu8NT1ifGLnA6M3sJxZ6ixylb+vIUVzvvd6GOALpwQrYrtlPouMqd/vSbgehz6HaVk4+7Afhw==", @@ -1451,23 +1345,7 @@ "node": ">=18" } }, - "node_modules/@esbuild/openharmony-arm64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.10.tgz", - "integrity": "sha512-AVTSBhTX8Y/Fz6OmIVBip9tJzZEUcY8WLh7I59+upa5/GPhh2/aM6bvOMQySspnCCHvFi79kMtdJS1w0DXAeag==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { + "node_modules/@cloudflare/vitest-pool-workers/node_modules/@esbuild/sunos-x64": { "version": "0.25.4", "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.4.tgz", "integrity": "sha512-Mw+tzy4pp6wZEK0+Lwr76pWLjrtjmJyUB23tHKqEDP74R3q95luY/bXqXZeYl4NYlvwOqoRKlInQialgCKy67Q==", @@ -1484,7 +1362,7 @@ "node": ">=18" } }, - "node_modules/@esbuild/win32-arm64": { + "node_modules/@cloudflare/vitest-pool-workers/node_modules/@esbuild/win32-arm64": { "version": "0.25.4", "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.4.tgz", "integrity": "sha512-AVUP428VQTSddguz9dO9ngb+E5aScyg7nOeJDrF1HPYu555gmza3bDGMPhmVXL8svDSoqPCsCPjb265yG/kLKQ==", @@ -1501,7 +1379,7 @@ "node": ">=18" } }, - "node_modules/@esbuild/win32-ia32": { + "node_modules/@cloudflare/vitest-pool-workers/node_modules/@esbuild/win32-ia32": { "version": "0.25.4", "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.4.tgz", "integrity": "sha512-i1sW+1i+oWvQzSgfRcxxG2k4I9n3O9NRqy8U+uugaT2Dy7kLO9Y7wI72haOahxceMX8hZAzgGou1FhndRldxRg==", @@ -1518,7 +1396,7 @@ "node": ">=18" } }, - "node_modules/@esbuild/win32-x64": { + "node_modules/@cloudflare/vitest-pool-workers/node_modules/@esbuild/win32-x64": { "version": "0.25.4", "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.4.tgz", "integrity": "sha512-nOT2vZNw6hJ+z43oP1SPea/G/6AbN6X+bGNhNuq8NtRHy4wsMhw765IKLNmnjek7GvjWBYQ8Q5VBoYTFg9y1UQ==", @@ -1535,3313 +1413,4717 @@ "node": ">=18" } }, - "node_modules/@fastify/busboy": { - "version": "2.1.1", + "node_modules/@cloudflare/vitest-pool-workers/node_modules/esbuild": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.4.tgz", + "integrity": "sha512-8pgjLUcUjcgDg+2Q4NYXnPbo/vncAY4UmyaCm0jZevERqCHZIaWwdJHkf8XQtu4AxSKCdvrUbT0XUr1IdZzI8Q==", "dev": true, + "hasInstallScript": true, "license": "MIT", - "engines": { - "node": ">=14" - } - }, - "node_modules/@img/sharp-darwin-arm64": { - "version": "0.33.5", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "bin": { + "esbuild": "bin/esbuild" }, - "funding": { - "url": "https://opencollective.com/libvips" + "engines": { + "node": ">=18" }, "optionalDependencies": { - "@img/sharp-libvips-darwin-arm64": "1.0.4" + "@esbuild/aix-ppc64": "0.25.4", + "@esbuild/android-arm": "0.25.4", + "@esbuild/android-arm64": "0.25.4", + "@esbuild/android-x64": "0.25.4", + "@esbuild/darwin-arm64": "0.25.4", + "@esbuild/darwin-x64": "0.25.4", + "@esbuild/freebsd-arm64": "0.25.4", + "@esbuild/freebsd-x64": "0.25.4", + "@esbuild/linux-arm": "0.25.4", + "@esbuild/linux-arm64": "0.25.4", + "@esbuild/linux-ia32": "0.25.4", + "@esbuild/linux-loong64": "0.25.4", + "@esbuild/linux-mips64el": "0.25.4", + "@esbuild/linux-ppc64": "0.25.4", + "@esbuild/linux-riscv64": "0.25.4", + "@esbuild/linux-s390x": "0.25.4", + "@esbuild/linux-x64": "0.25.4", + "@esbuild/netbsd-arm64": "0.25.4", + "@esbuild/netbsd-x64": "0.25.4", + "@esbuild/openbsd-arm64": "0.25.4", + "@esbuild/openbsd-x64": "0.25.4", + "@esbuild/sunos-x64": "0.25.4", + "@esbuild/win32-arm64": "0.25.4", + "@esbuild/win32-ia32": "0.25.4", + "@esbuild/win32-x64": "0.25.4" } }, - "node_modules/@img/sharp-libvips-darwin-arm64": { - "version": "1.0.4", - "cpu": [ - "arm64" - ], + "node_modules/@cloudflare/vitest-pool-workers/node_modules/miniflare": { + "version": "4.20251011.0", + "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-4.20251011.0.tgz", + "integrity": "sha512-DlZ7vR5q/RE9eLsxsrXzfSZIF2f6O5k0YsFrSKhWUtdefyGtJt4sSpR6V+Af/waaZ6+zIFy9lsknHBCm49sEYA==", "dev": true, - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "darwin" - ], - "funding": { - "url": "https://opencollective.com/libvips" + "license": "MIT", + "dependencies": { + "@cspotcode/source-map-support": "0.8.1", + "acorn": "8.14.0", + "acorn-walk": "8.3.2", + "exit-hook": "2.2.1", + "glob-to-regexp": "0.4.1", + "sharp": "^0.33.5", + "stoppable": "1.1.0", + "undici": "7.14.0", + "workerd": "1.20251011.0", + "ws": "8.18.0", + "youch": "4.1.0-beta.10", + "zod": "3.22.3" + }, + "bin": { + "miniflare": "bootstrap.js" + }, + "engines": { + "node": ">=18.0.0" } }, - "node_modules/@inquirer/external-editor": { - "version": "1.0.2", + "node_modules/@cloudflare/vitest-pool-workers/node_modules/wrangler": { + "version": "4.44.0", + "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-4.44.0.tgz", + "integrity": "sha512-BLOUigckcWZ0r4rm7b5PuaTpb9KP9as0XeCRSJ8kqcNgXcKoUD3Ij8FlPvN25KybLnFnetaO0ZdfRYUPWle4qw==", "dev": true, - "license": "MIT", + "license": "MIT OR Apache-2.0", "dependencies": { - "chardet": "^2.1.0", - "iconv-lite": "^0.7.0" + "@cloudflare/kv-asset-handler": "0.4.0", + "@cloudflare/unenv-preset": "2.7.8", + "blake3-wasm": "2.1.5", + "esbuild": "0.25.4", + "miniflare": "4.20251011.0", + "path-to-regexp": "6.3.0", + "unenv": "2.0.0-rc.21", + "workerd": "1.20251011.0" + }, + "bin": { + "wrangler": "bin/wrangler.js", + "wrangler2": "bin/wrangler.js" }, "engines": { - "node": ">=18" + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" }, "peerDependencies": { - "@types/node": ">=18" + "@cloudflare/workers-types": "^4.20251011.0" }, "peerDependenciesMeta": { - "@types/node": { + "@cloudflare/workers-types": { "optional": true } } }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.13", + "node_modules/@cloudflare/vitest-pool-workers/node_modules/ws": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", "dev": true, "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0", - "@jridgewell/trace-mapping": "^0.3.24" + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } } }, - "node_modules/@jridgewell/remapping": { - "version": "2.3.5", + "node_modules/@cloudflare/vitest-pool-workers/node_modules/zod": { + "version": "3.22.3", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.3.tgz", + "integrity": "sha512-EjIevzuJRiRPbVH4mGc8nApb/lVLKVpmUhAaR5R5doKGfAnGJ6Gr3CViAVjP+4FWSxCsybeWQdcgCtbX+7oZug==", "dev": true, "license": "MIT", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" + "funding": { + "url": "https://github.com/sponsors/colinhacks" } }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", + "node_modules/@cloudflare/workerd-darwin-64": { + "version": "1.20251011.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20251011.0.tgz", + "integrity": "sha512-0DirVP+Z82RtZLlK2B+VhLOkk+ShBqDYO/jhcRw4oVlp0TOvk3cOVZChrt3+y3NV8Y/PYgTEywzLKFSziK4wCg==", + "cpu": [ + "x64" + ], "dev": true, - "license": "MIT", + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=6.0.0" + "node": ">=16" } }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", + "node_modules/@cloudflare/workerd-darwin-arm64": { + "version": "1.20251011.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20251011.0.tgz", + "integrity": "sha512-1WuFBGwZd15p4xssGN/48OE2oqokIuc51YvHvyNivyV8IYnAs3G9bJNGWth1X7iMDPe4g44pZrKhRnISS2+5dA==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "MIT" + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=16" + } }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.31", + "node_modules/@cloudflare/workerd-linux-64": { + "version": "1.20251011.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20251011.0.tgz", + "integrity": "sha512-BccMiBzFlWZyFghIw2szanmYJrJGBGHomw2y/GV6pYXChFzMGZkeCEMfmCyJj29xczZXxcZmUVJxNy4eJxO8QA==", + "cpu": [ + "x64" + ], "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16" } }, - "node_modules/@jsdevtools/ez-spawn": { - "version": "3.0.4", + "node_modules/@cloudflare/workerd-linux-arm64": { + "version": "1.20251011.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20251011.0.tgz", + "integrity": "sha512-79o/216lsbAbKEVDZYXR24ivEIE2ysDL9jvo0rDTkViLWju9dAp3CpyetglpJatbSi3uWBPKZBEOqN68zIjVsQ==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "MIT", - "dependencies": { - "call-me-maybe": "^1.0.1", - "cross-spawn": "^7.0.3", - "string-argv": "^0.3.1", - "type-detect": "^4.0.8" - }, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=10" + "node": ">=16" } }, - "node_modules/@manypkg/find-root": { - "version": "1.1.0", + "node_modules/@cloudflare/workerd-windows-64": { + "version": "1.20251011.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20251011.0.tgz", + "integrity": "sha512-RIXUQRchFdqEvaUqn1cXZXSKjpqMaSaVAkI5jNZ8XzAw/bw2bcdOVUtakrflgxDprltjFb0PTNtuss1FKtH9Jg==", + "cpu": [ + "x64" + ], "dev": true, - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.5.5", - "@types/node": "^12.7.1", - "find-up": "^4.1.0", - "fs-extra": "^8.1.0" + "license": "Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=16" } }, - "node_modules/@manypkg/find-root/node_modules/@types/node": { - "version": "12.20.55", + "node_modules/@cloudflare/workers-types": { + "version": "4.20251014.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workers-types/-/workers-types-4.20251014.0.tgz", + "integrity": "sha512-tEW98J/kOa0TdylIUOrLKRdwkUw0rvvYVlo+Ce0mqRH3c8kSoxLzUH9gfCvwLe0M89z1RkzFovSKAW2Nwtyn3w==", "dev": true, - "license": "MIT" + "license": "MIT OR Apache-2.0" }, - "node_modules/@manypkg/find-root/node_modules/fs-extra": { - "version": "8.1.0", + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", "dev": true, "license": "MIT", "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" + "@jridgewell/trace-mapping": "0.3.9" }, "engines": { - "node": ">=6 <7 || >=8" + "node": ">=12" } }, - "node_modules/@manypkg/get-packages": { - "version": "1.1.3", + "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/runtime": "^7.5.5", - "@changesets/types": "^4.0.1", - "@manypkg/find-root": "^1.1.0", - "fs-extra": "^8.1.0", - "globby": "^11.0.0", - "read-yaml-file": "^1.1.0" + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" } }, - "node_modules/@manypkg/get-packages/node_modules/@changesets/types": { - "version": "4.1.0", - "dev": true, - "license": "MIT" - }, - "node_modules/@manypkg/get-packages/node_modules/fs-extra": { - "version": "8.1.0", + "node_modules/@emnapi/core": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.6.0.tgz", + "integrity": "sha512-zq/ay+9fNIJJtJiZxdTnXS20PllcYMX3OE23ESc4HK/bdYu3cOWYVhsOhVnXALfU/uqJIxn5NBPd9z4v+SfoSg==", "dev": true, "license": "MIT", + "optional": true, "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" + "@emnapi/wasi-threads": "1.1.0", + "tslib": "^2.4.0" } }, - "node_modules/@napi-rs/wasm-runtime": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.0.7.tgz", - "integrity": "sha512-SeDnOO0Tk7Okiq6DbXmmBODgOAb9dp9gjlphokTUxmt8U3liIP1ZsozBahH69j/RJv+Rfs6IwUKHTgQYJ/HBAw==", + "node_modules/@emnapi/runtime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.6.0.tgz", + "integrity": "sha512-obtUmAHTMjll499P+D9A3axeJFlhdjOWdKUNs/U6QIGT7V5RjcUW1xToAzjvmgTSQhDbYn/NwfTRoJcQ2rNBxA==", "dev": true, "license": "MIT", "optional": true, "dependencies": { - "@emnapi/core": "^1.5.0", - "@emnapi/runtime": "^1.5.0", - "@tybys/wasm-util": "^0.10.1" + "tslib": "^2.4.0" } }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", + "node_modules/@emnapi/wasi-threads": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz", + "integrity": "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==", "dev": true, "license": "MIT", + "optional": true, "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" + "tslib": "^2.4.0" } }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "dev": true, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.11.tgz", + "integrity": "sha512-Xt1dOL13m8u0WE8iplx9Ibbm+hFAO0GsU2P34UNoDGvZYkY8ifSiy6Zuc1lYxfG7svWE2fzqCUmFp5HCn51gJg==", + "cpu": [ + "ppc64" + ], "license": "MIT", + "optional": true, + "os": [ + "aix" + ], "engines": { - "node": ">= 8" + "node": ">=18" } }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "dev": true, + "node_modules/@esbuild/android-arm": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.11.tgz", + "integrity": "sha512-uoa7dU+Dt3HYsethkJ1k6Z9YdcHjTrSb5NUy66ZfZaSV8hEYGD5ZHbEMXnqLFlbBflLsl89Zke7CAdDJ4JI+Gg==", + "cpu": [ + "arm" + ], "license": "MIT", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">= 8" + "node": ">=18" } }, - "node_modules/@octokit/action": { - "version": "6.1.0", - "dev": true, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.11.tgz", + "integrity": "sha512-9slpyFBc4FPPz48+f6jyiXOx/Y4v34TUeDDXJpZqAWQn/08lKGeD8aDp9TMn9jDz2CiEuHwfhRmGBvpnd/PWIQ==", + "cpu": [ + "arm64" + ], "license": "MIT", - "dependencies": { - "@octokit/auth-action": "^4.0.0", - "@octokit/core": "^5.0.0", - "@octokit/plugin-paginate-rest": "^9.0.0", - "@octokit/plugin-rest-endpoint-methods": "^10.0.0", - "@octokit/types": "^12.0.0", - "undici": "^6.0.0" - }, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">= 18" + "node": ">=18" } }, - "node_modules/@octokit/action/node_modules/undici": { - "version": "6.22.0", - "dev": true, + "node_modules/@esbuild/android-x64": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.11.tgz", + "integrity": "sha512-Sgiab4xBjPU1QoPEIqS3Xx+R2lezu0LKIEcYe6pftr56PqPygbB7+szVnzoShbx64MUupqoE0KyRlN7gezbl8g==", + "cpu": [ + "x64" + ], "license": "MIT", + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=18.17" + "node": ">=18" } }, - "node_modules/@octokit/auth-action": { - "version": "4.1.0", - "dev": true, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.11.tgz", + "integrity": "sha512-VekY0PBCukppoQrycFxUqkCojnTQhdec0vevUL/EDOCnXd9LKWqD/bHwMPzigIJXPhC59Vd1WFIL57SKs2mg4w==", + "cpu": [ + "arm64" + ], "license": "MIT", - "dependencies": { - "@octokit/auth-token": "^4.0.0", - "@octokit/types": "^13.0.0" - }, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">= 18" + "node": ">=18" } }, - "node_modules/@octokit/auth-action/node_modules/@octokit/openapi-types": { - "version": "24.2.0", - "dev": true, - "license": "MIT" - }, - "node_modules/@octokit/auth-action/node_modules/@octokit/types": { - "version": "13.10.0", - "dev": true, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.11.tgz", + "integrity": "sha512-+hfp3yfBalNEpTGp9loYgbknjR695HkqtY3d3/JjSRUyPg/xd6q+mQqIb5qdywnDxRZykIHs3axEqU6l1+oWEQ==", + "cpu": [ + "x64" + ], "license": "MIT", - "dependencies": { - "@octokit/openapi-types": "^24.2.0" + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@octokit/auth-token": { - "version": "4.0.0", - "dev": true, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.11.tgz", + "integrity": "sha512-CmKjrnayyTJF2eVuO//uSjl/K3KsMIeYeyN7FyDBjsR3lnSJHaXlVoAK8DZa7lXWChbuOk7NjAc7ygAwrnPBhA==", + "cpu": [ + "arm64" + ], "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">= 18" + "node": ">=18" } }, - "node_modules/@octokit/core": { - "version": "5.2.2", - "dev": true, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.11.tgz", + "integrity": "sha512-Dyq+5oscTJvMaYPvW3x3FLpi2+gSZTCE/1ffdwuM6G1ARang/mb3jvjxs0mw6n3Lsw84ocfo9CrNMqc5lTfGOw==", + "cpu": [ + "x64" + ], "license": "MIT", - "dependencies": { - "@octokit/auth-token": "^4.0.0", - "@octokit/graphql": "^7.1.0", - "@octokit/request": "^8.4.1", - "@octokit/request-error": "^5.1.1", - "@octokit/types": "^13.0.0", - "before-after-hook": "^2.2.0", - "universal-user-agent": "^6.0.0" - }, + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">= 18" + "node": ">=18" } }, - "node_modules/@octokit/core/node_modules/@octokit/openapi-types": { - "version": "24.2.0", - "dev": true, - "license": "MIT" - }, - "node_modules/@octokit/core/node_modules/@octokit/types": { - "version": "13.10.0", - "dev": true, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.11.tgz", + "integrity": "sha512-TBMv6B4kCfrGJ8cUPo7vd6NECZH/8hPpBHHlYI3qzoYFvWu2AdTvZNuU/7hsbKWqu/COU7NIK12dHAAqBLLXgw==", + "cpu": [ + "arm" + ], "license": "MIT", - "dependencies": { - "@octokit/openapi-types": "^24.2.0" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@octokit/endpoint": { - "version": "9.0.6", - "dev": true, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.11.tgz", + "integrity": "sha512-Qr8AzcplUhGvdyUF08A1kHU3Vr2O88xxP0Tm8GcdVOUm25XYcMPp2YqSVHbLuXzYQMf9Bh/iKx7YPqECs6ffLA==", + "cpu": [ + "arm64" + ], "license": "MIT", - "dependencies": { - "@octokit/types": "^13.1.0", - "universal-user-agent": "^6.0.0" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 18" + "node": ">=18" } }, - "node_modules/@octokit/endpoint/node_modules/@octokit/openapi-types": { - "version": "24.2.0", - "dev": true, - "license": "MIT" - }, - "node_modules/@octokit/endpoint/node_modules/@octokit/types": { - "version": "13.10.0", - "dev": true, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.11.tgz", + "integrity": "sha512-TmnJg8BMGPehs5JKrCLqyWTVAvielc615jbkOirATQvWWB1NMXY77oLMzsUjRLa0+ngecEmDGqt5jiDC6bfvOw==", + "cpu": [ + "ia32" + ], "license": "MIT", - "dependencies": { - "@octokit/openapi-types": "^24.2.0" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@octokit/graphql": { - "version": "7.1.1", - "dev": true, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.11.tgz", + "integrity": "sha512-DIGXL2+gvDaXlaq8xruNXUJdT5tF+SBbJQKbWy/0J7OhU8gOHOzKmGIlfTTl6nHaCOoipxQbuJi7O++ldrxgMw==", + "cpu": [ + "loong64" + ], "license": "MIT", - "dependencies": { - "@octokit/request": "^8.4.1", - "@octokit/types": "^13.0.0", - "universal-user-agent": "^6.0.0" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 18" + "node": ">=18" } }, - "node_modules/@octokit/graphql/node_modules/@octokit/openapi-types": { - "version": "24.2.0", - "dev": true, - "license": "MIT" - }, - "node_modules/@octokit/graphql/node_modules/@octokit/types": { - "version": "13.10.0", - "dev": true, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.11.tgz", + "integrity": "sha512-Osx1nALUJu4pU43o9OyjSCXokFkFbyzjXb6VhGIJZQ5JZi8ylCQ9/LFagolPsHtgw6himDSyb5ETSfmp4rpiKQ==", + "cpu": [ + "mips64el" + ], "license": "MIT", - "dependencies": { - "@octokit/openapi-types": "^24.2.0" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@octokit/openapi-types": { - "version": "20.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/@octokit/plugin-paginate-rest": { - "version": "9.2.2", - "dev": true, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.11.tgz", + "integrity": "sha512-nbLFgsQQEsBa8XSgSTSlrnBSrpoWh7ioFDUmwo158gIm5NNP+17IYmNWzaIzWmgCxq56vfr34xGkOcZ7jX6CPw==", + "cpu": [ + "ppc64" + ], "license": "MIT", - "dependencies": { - "@octokit/types": "^12.6.0" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 18" - }, - "peerDependencies": { - "@octokit/core": "5" + "node": ">=18" } }, - "node_modules/@octokit/plugin-rest-endpoint-methods": { - "version": "10.4.1", - "dev": true, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.11.tgz", + "integrity": "sha512-HfyAmqZi9uBAbgKYP1yGuI7tSREXwIb438q0nqvlpxAOs3XnZ8RsisRfmVsgV486NdjD7Mw2UrFSw51lzUk1ww==", + "cpu": [ + "riscv64" + ], "license": "MIT", - "dependencies": { - "@octokit/types": "^12.6.0" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 18" - }, - "peerDependencies": { - "@octokit/core": "5" + "node": ">=18" } }, - "node_modules/@octokit/request": { - "version": "8.4.1", - "dev": true, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.11.tgz", + "integrity": "sha512-HjLqVgSSYnVXRisyfmzsH6mXqyvj0SA7pG5g+9W7ESgwA70AXYNpfKBqh1KbTxmQVaYxpzA/SvlB9oclGPbApw==", + "cpu": [ + "s390x" + ], "license": "MIT", - "dependencies": { - "@octokit/endpoint": "^9.0.6", - "@octokit/request-error": "^5.1.1", - "@octokit/types": "^13.1.0", - "universal-user-agent": "^6.0.0" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 18" + "node": ">=18" } }, - "node_modules/@octokit/request-error": { - "version": "5.1.1", - "dev": true, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.11.tgz", + "integrity": "sha512-HSFAT4+WYjIhrHxKBwGmOOSpphjYkcswF449j6EjsjbinTZbp8PJtjsVK1XFJStdzXdy/jaddAep2FGY+wyFAQ==", + "cpu": [ + "x64" + ], "license": "MIT", - "dependencies": { - "@octokit/types": "^13.1.0", - "deprecation": "^2.0.0", - "once": "^1.4.0" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 18" + "node": ">=18" } }, - "node_modules/@octokit/request-error/node_modules/@octokit/openapi-types": { - "version": "24.2.0", - "dev": true, - "license": "MIT" - }, - "node_modules/@octokit/request-error/node_modules/@octokit/types": { - "version": "13.10.0", - "dev": true, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.11.tgz", + "integrity": "sha512-hr9Oxj1Fa4r04dNpWr3P8QKVVsjQhqrMSUzZzf+LZcYjZNqhA3IAfPQdEh1FLVUJSiu6sgAwp3OmwBfbFgG2Xg==", + "cpu": [ + "arm64" + ], "license": "MIT", - "dependencies": { - "@octokit/openapi-types": "^24.2.0" + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@octokit/request/node_modules/@octokit/openapi-types": { - "version": "24.2.0", - "dev": true, - "license": "MIT" - }, - "node_modules/@octokit/request/node_modules/@octokit/types": { - "version": "13.10.0", - "dev": true, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.11.tgz", + "integrity": "sha512-u7tKA+qbzBydyj0vgpu+5h5AeudxOAGncb8N6C9Kh1N4n7wU1Xw1JDApsRjpShRpXRQlJLb9wY28ELpwdPcZ7A==", + "cpu": [ + "x64" + ], "license": "MIT", - "dependencies": { - "@octokit/openapi-types": "^24.2.0" + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@octokit/types": { - "version": "12.6.0", - "dev": true, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.11.tgz", + "integrity": "sha512-Qq6YHhayieor3DxFOoYM1q0q1uMFYb7cSpLD2qzDSvK1NAvqFi8Xgivv0cFC6J+hWVw2teCYltyy9/m/14ryHg==", + "cpu": [ + "arm64" + ], "license": "MIT", - "dependencies": { - "@octokit/openapi-types": "^20.0.0" + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@oxc-project/runtime": { - "version": "0.95.0", - "resolved": "https://registry.npmjs.org/@oxc-project/runtime/-/runtime-0.95.0.tgz", - "integrity": "sha512-qJS5pNepwMGnafO9ayKGz7rfPQgUBuunHpnP1//9Qa0zK3oT3t1EhT+I+pV9MUA+ZKez//OFqxCxf1vijCKb2Q==", - "dev": true, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.11.tgz", + "integrity": "sha512-CN+7c++kkbrckTOz5hrehxWN7uIhFFlmS/hqziSFVWpAzpWrQoAG4chH+nN3Be+Kzv/uuo7zhX716x3Sn2Jduw==", + "cpu": [ + "x64" + ], "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], "engines": { - "node": "^20.19.0 || >=22.12.0" + "node": ">=18" } }, - "node_modules/@oxc-project/types": { - "version": "0.95.0", - "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.95.0.tgz", - "integrity": "sha512-vACy7vhpMPhjEJhULNxrdR0D943TkA/MigMpJCHmBHvMXxRStRi/dPtTlfQ3uDwWSzRpT8z+7ImjZVf8JWBocQ==", - "dev": true, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.11.tgz", + "integrity": "sha512-rOREuNIQgaiR+9QuNkbkxubbp8MSO9rONmwP5nKncnWJ9v5jQ4JxFnLu4zDSRPf3x4u+2VN4pM4RdyIzDty/wQ==", + "cpu": [ + "arm64" + ], "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/Boshen" + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@pkgr/core": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz", - "integrity": "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==", - "dev": true, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.11.tgz", + "integrity": "sha512-nq2xdYaWxyg9DcIyXkZhcYulC6pQ2FuCgem3LI92IwMgIZ69KHeY8T4Y88pcwoLIjbed8n36CyKoYRDygNSGhA==", + "cpu": [ + "x64" + ], "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], "engines": { - "node": "^12.20.0 || ^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/pkgr" + "node": ">=18" } }, - "node_modules/@polka/url": { - "version": "1.0.0-next.29", - "dev": true, - "license": "MIT" - }, - "node_modules/@poppinss/colors": { - "version": "4.1.5", - "dev": true, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.11.tgz", + "integrity": "sha512-3XxECOWJq1qMZ3MN8srCJ/QfoLpL+VaxD/WfNRm1O3B4+AZ/BnLVgFbUV3eiRYDMXetciH16dwPbbHqwe1uU0Q==", + "cpu": [ + "arm64" + ], "license": "MIT", - "dependencies": { - "kleur": "^4.1.5" + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@poppinss/dumper": { - "version": "0.6.4", - "dev": true, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.11.tgz", + "integrity": "sha512-3ukss6gb9XZ8TlRyJlgLn17ecsK4NSQTmdIXRASVsiS2sQ6zPPZklNJT5GR5tE/MUarymmy8kCEf5xPCNCqVOA==", + "cpu": [ + "ia32" + ], "license": "MIT", - "dependencies": { - "@poppinss/colors": "^4.1.5", - "@sindresorhus/is": "^7.0.2", - "supports-color": "^10.0.0" + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@poppinss/exception": { - "version": "1.2.2", - "dev": true, - "license": "MIT" - }, - "node_modules/@quansync/fs": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/@quansync/fs/-/fs-0.1.5.tgz", - "integrity": "sha512-lNS9hL2aS2NZgNW7BBj+6EBl4rOf8l+tQ0eRY6JWCI8jI2kc53gSoqbjojU0OnAWhzoXiOjFyGsHcDGePB3lhA==", - "dev": true, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.11.tgz", + "integrity": "sha512-D7Hpz6A2L4hzsRpPaCYkQnGOotdUpDzSGRIv9I+1ITdHROSFUWW95ZPZWQmGka1Fg7W3zFJowyn9WGwMJ0+KPA==", + "cpu": [ + "x64" + ], "license": "MIT", - "dependencies": { - "quansync": "^0.2.11" - }, - "funding": { - "url": "https://github.com/sponsors/sxzz" + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@remix-run/node-fetch-server": { - "version": "0.8.1", + "node_modules/@fastify/busboy": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", + "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", "dev": true, - "license": "MIT" - }, - "node_modules/@repo/integration": { - "resolved": "tests/integration", - "link": true - }, - "node_modules/@repo/sandbox-container": { - "resolved": "packages/sandbox-container", - "link": true - }, - "node_modules/@repo/shared": { - "resolved": "packages/shared", - "link": true - }, - "node_modules/@repo/typescript-config": { - "resolved": "tooling/typescript-config", - "link": true + "license": "MIT", + "engines": { + "node": ">=14" + } }, - "node_modules/@rolldown/binding-android-arm64": { - "version": "1.0.0-beta.45", - "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-beta.45.tgz", - "integrity": "sha512-bfgKYhFiXJALeA/riil908+2vlyWGdwa7Ju5S+JgWZYdR4jtiPOGdM6WLfso1dojCh+4ZWeiTwPeV9IKQEX+4g==", + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz", + "integrity": "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==", "cpu": [ "arm64" ], "dev": true, - "license": "MIT", + "license": "Apache-2.0", "optional": true, "os": [ - "android" + "darwin" ], "engines": { - "node": "^20.19.0 || >=22.12.0" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.0.4" } }, - "node_modules/@rolldown/binding-darwin-arm64": { - "version": "1.0.0-beta.45", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-beta.45.tgz", - "integrity": "sha512-xjCv4CRVsSnnIxTuyH1RDJl5OEQ1c9JYOwfDAHddjJDxCw46ZX9q80+xq7Eok7KC4bRSZudMJllkvOKv0T9SeA==", + "node_modules/@img/sharp-darwin-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.5.tgz", + "integrity": "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==", "cpu": [ - "arm64" + "x64" ], "dev": true, - "license": "MIT", + "license": "Apache-2.0", "optional": true, "os": [ "darwin" ], "engines": { - "node": "^20.19.0 || >=22.12.0" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.0.4" } }, - "node_modules/@rolldown/binding-darwin-x64": { - "version": "1.0.0-beta.45", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-beta.45.tgz", - "integrity": "sha512-ddcO9TD3D/CLUa/l8GO8LHzBOaZqWg5ClMy3jICoxwCuoz47h9dtqPsIeTiB6yR501LQTeDsjA4lIFd7u3Ljfw==", + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.4.tgz", + "integrity": "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==", "cpu": [ - "x64" + "arm64" ], "dev": true, - "license": "MIT", + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "darwin" ], - "engines": { - "node": "^20.19.0 || >=22.12.0" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@rolldown/binding-freebsd-x64": { - "version": "1.0.0-beta.45", - "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-beta.45.tgz", - "integrity": "sha512-MBTWdrzW9w+UMYDUvnEuh0pQvLENkl2Sis15fHTfHVW7ClbGuez+RWopZudIDEGkpZXdeI4CkRXk+vdIIebrmg==", + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.4.tgz", + "integrity": "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==", "cpu": [ "x64" ], "dev": true, - "license": "MIT", + "license": "LGPL-3.0-or-later", "optional": true, "os": [ - "freebsd" + "darwin" ], - "engines": { - "node": "^20.19.0 || >=22.12.0" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@rolldown/binding-linux-arm-gnueabihf": { - "version": "1.0.0-beta.45", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-beta.45.tgz", - "integrity": "sha512-4YgoCFiki1HR6oSg+GxxfzfnVCesQxLF1LEnw9uXS/MpBmuog0EOO2rYfy69rWP4tFZL9IWp6KEfGZLrZ7aUog==", + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz", + "integrity": "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==", "cpu": [ "arm" ], "dev": true, - "license": "MIT", + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" ], - "engines": { - "node": "^20.19.0 || >=22.12.0" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@rolldown/binding-linux-arm64-gnu": { - "version": "1.0.0-beta.45", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-beta.45.tgz", - "integrity": "sha512-LE1gjAwQRrbCOorJJ7LFr10s5vqYf5a00V5Ea9wXcT2+56n5YosJkcp8eQ12FxRBv2YX8dsdQJb+ZTtYJwb6XQ==", + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz", + "integrity": "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==", "cpu": [ "arm64" ], "dev": true, - "license": "MIT", + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" ], - "engines": { - "node": "^20.19.0 || >=22.12.0" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@rolldown/binding-linux-arm64-musl": { - "version": "1.0.0-beta.45", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-beta.45.tgz", - "integrity": "sha512-tdy8ThO/fPp40B81v0YK3QC+KODOmzJzSUOO37DinQxzlTJ026gqUSOM8tzlVixRbQJltgVDCTYF8HNPRErQTA==", + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.4.tgz", + "integrity": "sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==", "cpu": [ - "arm64" + "s390x" ], "dev": true, - "license": "MIT", + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" ], - "engines": { - "node": "^20.19.0 || >=22.12.0" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@rolldown/binding-linux-x64-gnu": { - "version": "1.0.0-beta.45", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-beta.45.tgz", - "integrity": "sha512-lS082ROBWdmOyVY/0YB3JmsiClaWoxvC+dA8/rbhyB9VLkvVEaihLEOr4CYmrMse151C4+S6hCw6oa1iewox7g==", + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz", + "integrity": "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==", "cpu": [ "x64" ], "dev": true, - "license": "MIT", + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" ], - "engines": { - "node": "^20.19.0 || >=22.12.0" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@rolldown/binding-linux-x64-musl": { - "version": "1.0.0-beta.45", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-beta.45.tgz", - "integrity": "sha512-Hi73aYY0cBkr1/SvNQqH8Cd+rSV6S9RB5izCv0ySBcRnd/Wfn5plguUoGYwBnhHgFbh6cPw9m2dUVBR6BG1gxA==", + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.4.tgz", + "integrity": "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==", "cpu": [ - "x64" + "arm64" ], "dev": true, - "license": "MIT", + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" ], - "engines": { - "node": "^20.19.0 || >=22.12.0" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@rolldown/binding-openharmony-arm64": { - "version": "1.0.0-beta.45", - "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-beta.45.tgz", - "integrity": "sha512-fljEqbO7RHHogNDxYtTzr+GNjlfOx21RUyGmF+NrkebZ8emYYiIqzPxsaMZuRx0rgZmVmliOzEp86/CQFDKhJQ==", + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.4.tgz", + "integrity": "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==", "cpu": [ - "arm64" + "x64" ], "dev": true, - "license": "MIT", + "license": "LGPL-3.0-or-later", "optional": true, "os": [ - "openharmony" + "linux" ], - "engines": { - "node": "^20.19.0 || >=22.12.0" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@rolldown/binding-wasm32-wasi": { - "version": "1.0.0-beta.45", - "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-beta.45.tgz", - "integrity": "sha512-ZJDB7lkuZE9XUnWQSYrBObZxczut+8FZ5pdanm8nNS1DAo8zsrPuvGwn+U3fwU98WaiFsNrA4XHngesCGr8tEQ==", + "node_modules/@img/sharp-linux-arm": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz", + "integrity": "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==", "cpu": [ - "wasm32" + "arm" ], "dev": true, - "license": "MIT", + "license": "Apache-2.0", "optional": true, - "dependencies": { - "@napi-rs/wasm-runtime": "^1.0.7" - }, + "os": [ + "linux" + ], "engines": { - "node": ">=14.0.0" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.0.5" } }, - "node_modules/@rolldown/binding-win32-arm64-msvc": { - "version": "1.0.0-beta.45", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-beta.45.tgz", - "integrity": "sha512-zyzAjItHPUmxg6Z8SyRhLdXlJn3/D9KL5b9mObUrBHhWS/GwRH4665xCiFqeuktAhhWutqfc+rOV2LjK4VYQGQ==", + "node_modules/@img/sharp-linux-arm64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz", + "integrity": "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==", "cpu": [ "arm64" ], "dev": true, - "license": "MIT", + "license": "Apache-2.0", "optional": true, "os": [ - "win32" + "linux" ], "engines": { - "node": "^20.19.0 || >=22.12.0" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.0.4" } }, - "node_modules/@rolldown/binding-win32-ia32-msvc": { - "version": "1.0.0-beta.45", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.0.0-beta.45.tgz", - "integrity": "sha512-wODcGzlfxqS6D7BR0srkJk3drPwXYLu7jPHN27ce2c4PUnVVmJnp9mJzUQGT4LpmHmmVdMZ+P6hKvyTGBzc1CA==", + "node_modules/@img/sharp-linux-s390x": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.5.tgz", + "integrity": "sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==", "cpu": [ - "ia32" + "s390x" ], "dev": true, - "license": "MIT", + "license": "Apache-2.0", "optional": true, "os": [ - "win32" + "linux" ], "engines": { - "node": "^20.19.0 || >=22.12.0" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.0.4" } }, - "node_modules/@rolldown/binding-win32-x64-msvc": { - "version": "1.0.0-beta.45", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-beta.45.tgz", - "integrity": "sha512-wiU40G1nQo9rtfvF9jLbl79lUgjfaD/LTyUEw2Wg/gdF5OhjzpKMVugZQngO+RNdwYaNj+Fs+kWBWfp4VXPMHA==", + "node_modules/@img/sharp-linux-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz", + "integrity": "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==", "cpu": [ "x64" ], "dev": true, - "license": "MIT", + "license": "Apache-2.0", "optional": true, "os": [ - "win32" + "linux" ], "engines": { - "node": "^20.19.0 || >=22.12.0" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.0.4" } }, - "node_modules/@rolldown/pluginutils": { - "version": "1.0.0-beta.27", - "dev": true, - "license": "MIT" - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.52.4", + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.5.tgz", + "integrity": "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==", "cpu": [ "arm64" ], "dev": true, - "license": "MIT", + "license": "Apache-2.0", "optional": true, "os": [ - "darwin" - ] - }, - "node_modules/@sindresorhus/is": { - "version": "7.1.0", - "dev": true, - "license": "MIT", + "linux" + ], "engines": { - "node": ">=18" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" }, "funding": { - "url": "https://github.com/sindresorhus/is?sponsor=1" + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.0.4" } }, - "node_modules/@speed-highlight/core": { - "version": "1.2.7", - "dev": true, - "license": "CC0-1.0" - }, - "node_modules/@tybys/wasm-util": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", - "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==", + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.5.tgz", + "integrity": "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==", + "cpu": [ + "x64" + ], "dev": true, - "license": "MIT", + "license": "Apache-2.0", "optional": true, - "dependencies": { - "tslib": "^2.4.0" + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.0.4" } }, - "node_modules/@types/babel__core": { - "version": "7.20.5", + "node_modules/@img/sharp-wasm32": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.33.5.tgz", + "integrity": "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==", + "cpu": [ + "wasm32" + ], "dev": true, - "license": "MIT", + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" + "@emnapi/runtime": "^1.2.0" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@types/babel__generator": { - "version": "7.27.0", + "node_modules/@img/sharp-win32-ia32": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.5.tgz", + "integrity": "sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==", + "cpu": [ + "ia32" + ], "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.0.0" + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@types/babel__template": { - "version": "7.4.4", + "node_modules/@img/sharp-win32-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz", + "integrity": "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==", + "cpu": [ + "x64" + ], "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@types/babel__traverse": { - "version": "7.28.0", + "node_modules/@inquirer/external-editor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@inquirer/external-editor/-/external-editor-1.0.2.tgz", + "integrity": "sha512-yy9cOoBnx58TlsPrIxauKIFQTiyH+0MK4e97y4sV9ERbI+zDxw7i2hxHLCIEGIE/8PPvDxGhgzIOTSOWcs6/MQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.28.2" + "chardet": "^2.1.0", + "iconv-lite": "^0.7.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@types/bun": { - "version": "1.2.23", + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", "dev": true, "license": "MIT", "dependencies": { - "bun-types": "1.2.23" + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" } }, - "node_modules/@types/chai": { - "version": "5.2.2", + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", "dev": true, "license": "MIT", "dependencies": { - "@types/deep-eql": "*" + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" } }, - "node_modules/@types/debug": { - "version": "4.1.12", + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, "license": "MIT", - "dependencies": { - "@types/ms": "*" + "engines": { + "node": ">=6.0.0" } }, - "node_modules/@types/deep-eql": { - "version": "4.0.2", + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", "dev": true, "license": "MIT" }, - "node_modules/@types/estree": { - "version": "1.0.8", - "license": "MIT" - }, - "node_modules/@types/estree-jsx": { - "version": "1.0.5", + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, "license": "MIT", "dependencies": { - "@types/estree": "*" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@types/hast": { + "node_modules/@jsdevtools/ez-spawn": { "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@jsdevtools/ez-spawn/-/ez-spawn-3.0.4.tgz", + "integrity": "sha512-f5DRIOZf7wxogefH03RjMPMdBF7ADTWUMoOs9kaJo06EfwF+aFhMZMDZxHg/Xe12hptN9xoZjGso2fdjapBRIA==", + "dev": true, "license": "MIT", "dependencies": { - "@types/unist": "*" + "call-me-maybe": "^1.0.1", + "cross-spawn": "^7.0.3", + "string-argv": "^0.3.1", + "type-detect": "^4.0.8" + }, + "engines": { + "node": ">=10" } }, - "node_modules/@types/mdast": { - "version": "4.0.4", + "node_modules/@manypkg/find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@manypkg/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==", + "dev": true, "license": "MIT", "dependencies": { - "@types/unist": "*" + "@babel/runtime": "^7.5.5", + "@types/node": "^12.7.1", + "find-up": "^4.1.0", + "fs-extra": "^8.1.0" } }, - "node_modules/@types/ms": { - "version": "2.1.0", + "node_modules/@manypkg/find-root/node_modules/@types/node": { + "version": "12.20.55", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz", + "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==", + "dev": true, "license": "MIT" }, - "node_modules/@types/node": { - "version": "24.9.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.9.2.tgz", - "integrity": "sha512-uWN8YqxXxqFMX2RqGOrumsKeti4LlmIMIyV0lgut4jx7KQBcBiW6vkDtIBvHnHIquwNfJhk8v2OtmO8zXWHfPA==", + "node_modules/@manypkg/find-root/node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~7.16.0" + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" } }, - "node_modules/@types/react": { - "version": "19.2.0", + "node_modules/@manypkg/get-packages": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@manypkg/get-packages/-/get-packages-1.1.3.tgz", + "integrity": "sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A==", + "dev": true, "license": "MIT", "dependencies": { - "csstype": "^3.0.2" + "@babel/runtime": "^7.5.5", + "@changesets/types": "^4.0.1", + "@manypkg/find-root": "^1.1.0", + "fs-extra": "^8.1.0", + "globby": "^11.0.0", + "read-yaml-file": "^1.1.0" } }, - "node_modules/@types/react-dom": { - "version": "19.2.0", + "node_modules/@manypkg/get-packages/node_modules/@changesets/types": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@changesets/types/-/types-4.1.0.tgz", + "integrity": "sha512-LDQvVDv5Kb50ny2s25Fhm3d9QSZimsoUGBsUioj6MC3qbMUCuC8GPIvk/M6IvXx3lYhAs0lwWUQLb+VIEUCECw==", "dev": true, - "license": "MIT", - "peerDependencies": { - "@types/react": "^19.2.0" - } + "license": "MIT" }, - "node_modules/@types/react-katex": { - "version": "3.0.4", + "node_modules/@manypkg/get-packages/node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", "dev": true, "license": "MIT", "dependencies": { - "@types/react": "*" + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" } }, - "node_modules/@types/unist": { - "version": "3.0.3", - "license": "MIT" - }, - "node_modules/@types/whatwg-mimetype": { - "version": "3.0.2", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/ws": { - "version": "8.18.1", + "node_modules/@napi-rs/wasm-runtime": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.0.7.tgz", + "integrity": "sha512-SeDnOO0Tk7Okiq6DbXmmBODgOAb9dp9gjlphokTUxmt8U3liIP1ZsozBahH69j/RJv+Rfs6IwUKHTgQYJ/HBAw==", "dev": true, "license": "MIT", + "optional": true, "dependencies": { - "@types/node": "*" + "@emnapi/core": "^1.5.0", + "@emnapi/runtime": "^1.5.0", + "@tybys/wasm-util": "^0.10.1" } }, - "node_modules/@ungap/structured-clone": { - "version": "1.3.0", - "license": "ISC" - }, - "node_modules/@vitejs/plugin-react": { - "version": "4.7.0", + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/core": "^7.28.0", - "@babel/plugin-transform-react-jsx-self": "^7.27.1", - "@babel/plugin-transform-react-jsx-source": "^7.27.1", - "@rolldown/pluginutils": "1.0.0-beta.27", - "@types/babel__core": "^7.20.5", - "react-refresh": "^0.17.0" + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" }, "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "peerDependencies": { - "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" + "node": ">= 8" } }, - "node_modules/@vitest/expect": { - "version": "3.2.4", + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, "license": "MIT", - "dependencies": { - "@types/chai": "^5.2.2", - "@vitest/spy": "3.2.4", - "@vitest/utils": "3.2.4", - "chai": "^5.2.0", - "tinyrainbow": "^2.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" + "engines": { + "node": ">= 8" } }, - "node_modules/@vitest/mocker": { - "version": "3.2.4", + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "3.2.4", - "estree-walker": "^3.0.3", - "magic-string": "^0.30.17" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "msw": "^2.4.9", - "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" }, - "peerDependenciesMeta": { - "msw": { - "optional": true - }, - "vite": { - "optional": true - } + "engines": { + "node": ">= 8" } }, - "node_modules/@vitest/pretty-format": { - "version": "3.2.4", + "node_modules/@octokit/action": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@octokit/action/-/action-6.1.0.tgz", + "integrity": "sha512-lo+nHx8kAV86bxvOVOI3vFjX3gXPd/L7guAUbvs3pUvnR2KC+R7yjBkA1uACt4gYhs4LcWP3AXSGQzsbeN2XXw==", "dev": true, "license": "MIT", "dependencies": { - "tinyrainbow": "^2.0.0" + "@octokit/auth-action": "^4.0.0", + "@octokit/core": "^5.0.0", + "@octokit/plugin-paginate-rest": "^9.0.0", + "@octokit/plugin-rest-endpoint-methods": "^10.0.0", + "@octokit/types": "^12.0.0", + "undici": "^6.0.0" }, - "funding": { - "url": "https://opencollective.com/vitest" + "engines": { + "node": ">= 18" } }, - "node_modules/@vitest/runner": { - "version": "3.2.4", + "node_modules/@octokit/action/node_modules/undici": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.22.0.tgz", + "integrity": "sha512-hU/10obOIu62MGYjdskASR3CUAiYaFTtC9Pa6vHyf//mAipSvSQg6od2CnJswq7fvzNS3zJhxoRkgNVaHurWKw==", "dev": true, "license": "MIT", - "dependencies": { - "@vitest/utils": "3.2.4", - "pathe": "^2.0.3", - "strip-literal": "^3.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" + "engines": { + "node": ">=18.17" } }, - "node_modules/@vitest/snapshot": { - "version": "3.2.4", + "node_modules/@octokit/auth-action": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-action/-/auth-action-4.1.0.tgz", + "integrity": "sha512-m+3t7K46IYyMk7Bl6/lF4Rv09GqDZjYmNg8IWycJ2Fa3YE3DE7vQcV6G2hUPmR9NDqenefNJwVtlisMjzymPiQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "3.2.4", - "magic-string": "^0.30.17", - "pathe": "^2.0.3" + "@octokit/auth-token": "^4.0.0", + "@octokit/types": "^13.0.0" }, - "funding": { - "url": "https://opencollective.com/vitest" + "engines": { + "node": ">= 18" } }, - "node_modules/@vitest/spy": { - "version": "3.2.4", + "node_modules/@octokit/auth-action/node_modules/@octokit/openapi-types": { + "version": "24.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", + "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@octokit/auth-action/node_modules/@octokit/types": { + "version": "13.10.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", + "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", "dev": true, "license": "MIT", "dependencies": { - "tinyspy": "^4.0.3" - }, - "funding": { - "url": "https://opencollective.com/vitest" + "@octokit/openapi-types": "^24.2.0" } }, - "node_modules/@vitest/ui": { - "version": "3.2.4", + "node_modules/@octokit/auth-token": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-4.0.0.tgz", + "integrity": "sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==", "dev": true, "license": "MIT", - "dependencies": { - "@vitest/utils": "3.2.4", - "fflate": "^0.8.2", - "flatted": "^3.3.3", - "pathe": "^2.0.3", - "sirv": "^3.0.1", - "tinyglobby": "^0.2.14", - "tinyrainbow": "^2.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "vitest": "3.2.4" + "engines": { + "node": ">= 18" } }, - "node_modules/@vitest/utils": { - "version": "3.2.4", + "node_modules/@octokit/core": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.2.2.tgz", + "integrity": "sha512-/g2d4sW9nUDJOMz3mabVQvOGhVa4e/BN/Um7yca9Bb2XTzPPnfTWHWQg+IsEYO7M3Vx+EXvaM/I2pJWIMun1bg==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "3.2.4", - "loupe": "^3.1.4", - "tinyrainbow": "^2.0.0" + "@octokit/auth-token": "^4.0.0", + "@octokit/graphql": "^7.1.0", + "@octokit/request": "^8.4.1", + "@octokit/request-error": "^5.1.1", + "@octokit/types": "^13.0.0", + "before-after-hook": "^2.2.0", + "universal-user-agent": "^6.0.0" }, - "funding": { - "url": "https://opencollective.com/vitest" + "engines": { + "node": ">= 18" } }, - "node_modules/acorn": { - "version": "8.14.0", + "node_modules/@octokit/core/node_modules/@octokit/openapi-types": { + "version": "24.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", + "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@octokit/core/node_modules/@octokit/types": { + "version": "13.10.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", + "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", "dev": true, "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" + "dependencies": { + "@octokit/openapi-types": "^24.2.0" } }, - "node_modules/acorn-walk": { - "version": "8.3.2", + "node_modules/@octokit/endpoint": { + "version": "9.0.6", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.6.tgz", + "integrity": "sha512-H1fNTMA57HbkFESSt3Y9+FBICv+0jFceJFPWDePYlR/iMGrwM5ph+Dd4XRQs+8X+PUFURLQgX9ChPfhJ/1uNQw==", "dev": true, "license": "MIT", + "dependencies": { + "@octokit/types": "^13.1.0", + "universal-user-agent": "^6.0.0" + }, "engines": { - "node": ">=0.4.0" + "node": ">= 18" } }, - "node_modules/ansi-colors": { - "version": "4.1.3", + "node_modules/@octokit/endpoint/node_modules/@octokit/openapi-types": { + "version": "24.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", + "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@octokit/endpoint/node_modules/@octokit/types": { + "version": "13.10.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", + "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", "dev": true, "license": "MIT", - "engines": { - "node": ">=6" + "dependencies": { + "@octokit/openapi-types": "^24.2.0" } }, - "node_modules/ansi-regex": { - "version": "5.0.1", + "node_modules/@octokit/graphql": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.1.1.tgz", + "integrity": "sha512-3mkDltSfcDUoa176nlGoA32RGjeWjl3K7F/BwHwRMJUW/IteSa4bnSV8p2ThNkcIcZU2umkZWxwETSSCJf2Q7g==", "dev": true, "license": "MIT", + "dependencies": { + "@octokit/request": "^8.4.1", + "@octokit/types": "^13.0.0", + "universal-user-agent": "^6.0.0" + }, "engines": { - "node": ">=8" + "node": ">= 18" } }, - "node_modules/ansis": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/ansis/-/ansis-4.2.0.tgz", - "integrity": "sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig==", + "node_modules/@octokit/graphql/node_modules/@octokit/openapi-types": { + "version": "24.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", + "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==", "dev": true, - "license": "ISC", - "engines": { - "node": ">=14" - } + "license": "MIT" }, - "node_modules/argparse": { - "version": "1.0.10", + "node_modules/@octokit/graphql/node_modules/@octokit/types": { + "version": "13.10.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", + "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", "dev": true, "license": "MIT", "dependencies": { - "sprintf-js": "~1.0.2" + "@octokit/openapi-types": "^24.2.0" } }, - "node_modules/array-union": { - "version": "2.1.0", + "node_modules/@octokit/openapi-types": { + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz", + "integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } + "license": "MIT" }, - "node_modules/assertion-error": { - "version": "2.0.1", + "node_modules/@octokit/plugin-paginate-rest": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.2.2.tgz", + "integrity": "sha512-u3KYkGF7GcZnSD/3UP0S7K5XUFT2FkOQdcfXZGZQPGv3lm4F2Xbf71lvjldr8c1H3nNbF+33cLEkWYbokGWqiQ==", "dev": true, "license": "MIT", + "dependencies": { + "@octokit/types": "^12.6.0" + }, "engines": { - "node": ">=12" + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": "5" } }, - "node_modules/ast-kit": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ast-kit/-/ast-kit-2.1.3.tgz", - "integrity": "sha512-TH+b3Lv6pUjy/Nu0m6A2JULtdzLpmqF9x1Dhj00ZoEiML8qvVA9j1flkzTKNYgdEhWrjDwtWNpyyCUbfQe514g==", + "node_modules/@octokit/plugin-rest-endpoint-methods": { + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-10.4.1.tgz", + "integrity": "sha512-xV1b+ceKV9KytQe3zCVqjg+8GTGfDYwaT1ATU5isiUyVtlVAO3HNdzpS4sr4GBx4hxQ46s7ITtZrAsxG22+rVg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.28.4", - "pathe": "^2.0.3" + "@octokit/types": "^12.6.0" }, "engines": { - "node": ">=20.19.0" + "node": ">= 18" }, - "funding": { - "url": "https://github.com/sponsors/sxzz" + "peerDependencies": { + "@octokit/core": "5" } }, - "node_modules/bail": { - "version": "2.0.2", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/baseline-browser-mapping": { - "version": "2.8.12", - "dev": true, - "license": "Apache-2.0", - "bin": { - "baseline-browser-mapping": "dist/cli.js" - } - }, - "node_modules/before-after-hook": { - "version": "2.2.3", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/better-path-resolve": { - "version": "1.0.0", - "dev": true, + "node_modules/@octokit/request": { + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.4.1.tgz", + "integrity": "sha512-qnB2+SY3hkCmBxZsR/MPCybNmbJe4KAlfWErXq+rBKkQJlbjdJeS85VI9r8UqeLYLvnAenU8Q1okM/0MBsAGXw==", + "dev": true, "license": "MIT", "dependencies": { - "is-windows": "^1.0.0" + "@octokit/endpoint": "^9.0.6", + "@octokit/request-error": "^5.1.1", + "@octokit/types": "^13.1.0", + "universal-user-agent": "^6.0.0" }, "engines": { - "node": ">=4" - } - }, - "node_modules/birpc": { - "version": "0.2.14", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/antfu" + "node": ">= 18" } }, - "node_modules/blake3-wasm": { - "version": "2.1.5", - "dev": true, - "license": "MIT" - }, - "node_modules/braces": { - "version": "3.0.3", + "node_modules/@octokit/request-error": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.1.1.tgz", + "integrity": "sha512-v9iyEQJH6ZntoENr9/yXxjuezh4My67CBSu9r6Ve/05Iu5gNgnisNWOsoJHTP6k0Rr0+HQIpnH+kyammu90q/g==", "dev": true, "license": "MIT", "dependencies": { - "fill-range": "^7.1.1" + "@octokit/types": "^13.1.0", + "deprecation": "^2.0.0", + "once": "^1.4.0" }, "engines": { - "node": ">=8" + "node": ">= 18" } }, - "node_modules/browserslist": { - "version": "4.26.3", + "node_modules/@octokit/request-error/node_modules/@octokit/openapi-types": { + "version": "24.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", + "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "baseline-browser-mapping": "^2.8.9", - "caniuse-lite": "^1.0.30001746", - "electron-to-chromium": "^1.5.227", - "node-releases": "^2.0.21", - "update-browserslist-db": "^1.1.3" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } + "license": "MIT" }, - "node_modules/bun-types": { - "version": "1.2.23", + "node_modules/@octokit/request-error/node_modules/@octokit/types": { + "version": "13.10.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", + "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", "dev": true, "license": "MIT", "dependencies": { - "@types/node": "*" - }, - "peerDependencies": { - "@types/react": "^19" - } - }, - "node_modules/cac": { - "version": "6.7.14", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" + "@octokit/openapi-types": "^24.2.0" } }, - "node_modules/call-me-maybe": { - "version": "1.0.2", + "node_modules/@octokit/request/node_modules/@octokit/openapi-types": { + "version": "24.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", + "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==", "dev": true, "license": "MIT" }, - "node_modules/caniuse-lite": { - "version": "1.0.30001748", + "node_modules/@octokit/request/node_modules/@octokit/types": { + "version": "13.10.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", + "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "CC-BY-4.0" - }, - "node_modules/ccount": { - "version": "2.0.1", "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "dependencies": { + "@octokit/openapi-types": "^24.2.0" } }, - "node_modules/chai": { - "version": "5.3.3", + "node_modules/@octokit/types": { + "version": "12.6.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz", + "integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==", "dev": true, "license": "MIT", "dependencies": { - "assertion-error": "^2.0.1", - "check-error": "^2.1.1", - "deep-eql": "^5.0.1", - "loupe": "^3.1.0", - "pathval": "^2.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/character-entities-html4": { - "version": "2.1.0", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "@octokit/openapi-types": "^20.0.0" } }, - "node_modules/chardet": { - "version": "2.1.0", - "dev": true, - "license": "MIT" - }, - "node_modules/check-error": { - "version": "2.1.1", + "node_modules/@oxc-project/runtime": { + "version": "0.95.0", + "resolved": "https://registry.npmjs.org/@oxc-project/runtime/-/runtime-0.95.0.tgz", + "integrity": "sha512-qJS5pNepwMGnafO9ayKGz7rfPQgUBuunHpnP1//9Qa0zK3oT3t1EhT+I+pV9MUA+ZKez//OFqxCxf1vijCKb2Q==", "dev": true, "license": "MIT", "engines": { - "node": ">= 16" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/chokidar": { - "version": "4.0.3", + "node_modules/@oxc-project/types": { + "version": "0.95.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.95.0.tgz", + "integrity": "sha512-vACy7vhpMPhjEJhULNxrdR0D943TkA/MigMpJCHmBHvMXxRStRi/dPtTlfQ3uDwWSzRpT8z+7ImjZVf8JWBocQ==", "dev": true, "license": "MIT", - "dependencies": { - "readdirp": "^4.0.1" - }, - "engines": { - "node": ">= 14.16.0" - }, "funding": { - "url": "https://paulmillr.com/funding/" + "url": "https://github.com/sponsors/Boshen" } }, - "node_modules/ci-info": { - "version": "3.9.0", + "node_modules/@pkgr/core": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz", + "integrity": "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], "license": "MIT", "engines": { - "node": ">=8" + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/pkgr" } }, - "node_modules/cjs-module-lexer": { - "version": "1.4.3", + "node_modules/@polka/url": { + "version": "1.0.0-next.29", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz", + "integrity": "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==", "dev": true, "license": "MIT" }, - "node_modules/color": { - "version": "4.2.3", + "node_modules/@poppinss/colors": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@poppinss/colors/-/colors-4.1.5.tgz", + "integrity": "sha512-FvdDqtcRCtz6hThExcFOgW0cWX+xwSMWcRuQe5ZEb2m7cVQOAVZOIMt+/v9RxGiD9/OY16qJBXK4CVKWAPalBw==", "dev": true, "license": "MIT", "dependencies": { - "color-convert": "^2.0.1", - "color-string": "^1.9.0" - }, - "engines": { - "node": ">=12.5.0" + "kleur": "^4.1.5" } }, - "node_modules/color-convert": { - "version": "2.0.1", + "node_modules/@poppinss/dumper": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/@poppinss/dumper/-/dumper-0.6.4.tgz", + "integrity": "sha512-iG0TIdqv8xJ3Lt9O8DrPRxw1MRLjNpoqiSGU03P/wNLP/s0ra0udPJ1J2Tx5M0J3H/cVyEgpbn8xUKRY9j59kQ==", "dev": true, "license": "MIT", "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" + "@poppinss/colors": "^4.1.5", + "@sindresorhus/is": "^7.0.2", + "supports-color": "^10.0.0" } }, - "node_modules/color-name": { - "version": "1.1.4", + "node_modules/@poppinss/exception": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@poppinss/exception/-/exception-1.2.2.tgz", + "integrity": "sha512-m7bpKCD4QMlFCjA/nKTs23fuvoVFoA83brRKmObCUNmi/9tVu8Ve3w4YQAnJu4q3Tjf5fr685HYIC/IA2zHRSg==", "dev": true, "license": "MIT" }, - "node_modules/color-string": { - "version": "1.9.1", + "node_modules/@quansync/fs": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/@quansync/fs/-/fs-0.1.5.tgz", + "integrity": "sha512-lNS9hL2aS2NZgNW7BBj+6EBl4rOf8l+tQ0eRY6JWCI8jI2kc53gSoqbjojU0OnAWhzoXiOjFyGsHcDGePB3lhA==", "dev": true, "license": "MIT", "dependencies": { - "color-name": "^1.0.0", - "simple-swizzle": "^0.2.2" - } - }, - "node_modules/comma-separated-tokens": { - "version": "2.0.3", - "license": "MIT", + "quansync": "^0.2.11" + }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "url": "https://github.com/sponsors/sxzz" } }, - "node_modules/confbox": { - "version": "0.1.8", + "node_modules/@remix-run/node-fetch-server": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@remix-run/node-fetch-server/-/node-fetch-server-0.8.1.tgz", + "integrity": "sha512-J1dev372wtJqmqn9U/qbpbZxbJSQrogNN2+Qv1lKlpATpe/WQ9aCZfl/xSb9d2Rgh1IyLSvNxZAXPZxruO6Xig==", "dev": true, "license": "MIT" }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "dev": true, - "license": "MIT" + "node_modules/@repo/integration": { + "resolved": "tests/integration", + "link": true }, - "node_modules/cookie": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - } + "node_modules/@repo/sandbox-container": { + "resolved": "packages/sandbox-container", + "link": true }, - "node_modules/cross-spawn": { - "version": "7.0.6", + "node_modules/@repo/shared": { + "resolved": "packages/shared", + "link": true + }, + "node_modules/@repo/typescript-config": { + "resolved": "tooling/typescript-config", + "link": true + }, + "node_modules/@rolldown/binding-android-arm64": { + "version": "1.0.0-beta.45", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-beta.45.tgz", + "integrity": "sha512-bfgKYhFiXJALeA/riil908+2vlyWGdwa7Ju5S+JgWZYdR4jtiPOGdM6WLfso1dojCh+4ZWeiTwPeV9IKQEX+4g==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">= 8" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/csstype": { - "version": "3.1.3", - "license": "MIT" - }, - "node_modules/dataloader": { - "version": "1.4.0", + "node_modules/@rolldown/binding-darwin-arm64": { + "version": "1.0.0-beta.45", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-beta.45.tgz", + "integrity": "sha512-xjCv4CRVsSnnIxTuyH1RDJl5OEQ1c9JYOwfDAHddjJDxCw46ZX9q80+xq7Eok7KC4bRSZudMJllkvOKv0T9SeA==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/debug": { - "version": "4.4.3", "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/decode-named-character-reference": { - "version": "1.2.0", + "node_modules/@rolldown/binding-darwin-x64": { + "version": "1.0.0-beta.45", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-beta.45.tgz", + "integrity": "sha512-ddcO9TD3D/CLUa/l8GO8LHzBOaZqWg5ClMy3jICoxwCuoz47h9dtqPsIeTiB6yR501LQTeDsjA4lIFd7u3Ljfw==", + "cpu": [ + "x64" + ], + "dev": true, "license": "MIT", - "dependencies": { - "character-entities": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/decode-named-character-reference/node_modules/character-entities": { - "version": "2.0.2", + "node_modules/@rolldown/binding-freebsd-x64": { + "version": "1.0.0-beta.45", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-beta.45.tgz", + "integrity": "sha512-MBTWdrzW9w+UMYDUvnEuh0pQvLENkl2Sis15fHTfHVW7ClbGuez+RWopZudIDEGkpZXdeI4CkRXk+vdIIebrmg==", + "cpu": [ + "x64" + ], + "dev": true, "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/decode-uri-component": { - "version": "0.4.1", + "node_modules/@rolldown/binding-linux-arm-gnueabihf": { + "version": "1.0.0-beta.45", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-beta.45.tgz", + "integrity": "sha512-4YgoCFiki1HR6oSg+GxxfzfnVCesQxLF1LEnw9uXS/MpBmuog0EOO2rYfy69rWP4tFZL9IWp6KEfGZLrZ7aUog==", + "cpu": [ + "arm" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=14.16" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/deep-eql": { - "version": "5.0.2", + "node_modules/@rolldown/binding-linux-arm64-gnu": { + "version": "1.0.0-beta.45", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-beta.45.tgz", + "integrity": "sha512-LE1gjAwQRrbCOorJJ7LFr10s5vqYf5a00V5Ea9wXcT2+56n5YosJkcp8eQ12FxRBv2YX8dsdQJb+ZTtYJwb6XQ==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/defu": { - "version": "6.1.4", + "node_modules/@rolldown/binding-linux-arm64-musl": { + "version": "1.0.0-beta.45", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-beta.45.tgz", + "integrity": "sha512-tdy8ThO/fPp40B81v0YK3QC+KODOmzJzSUOO37DinQxzlTJ026gqUSOM8tzlVixRbQJltgVDCTYF8HNPRErQTA==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "MIT" + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/deprecation": { - "version": "2.3.1", + "node_modules/@rolldown/binding-linux-x64-gnu": { + "version": "1.0.0-beta.45", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-beta.45.tgz", + "integrity": "sha512-lS082ROBWdmOyVY/0YB3JmsiClaWoxvC+dA8/rbhyB9VLkvVEaihLEOr4CYmrMse151C4+S6hCw6oa1iewox7g==", + "cpu": [ + "x64" + ], "dev": true, - "license": "ISC" - }, - "node_modules/dequal": { - "version": "2.0.3", "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/detect-indent": { - "version": "6.1.0", + "node_modules/@rolldown/binding-linux-x64-musl": { + "version": "1.0.0-beta.45", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-beta.45.tgz", + "integrity": "sha512-Hi73aYY0cBkr1/SvNQqH8Cd+rSV6S9RB5izCv0ySBcRnd/Wfn5plguUoGYwBnhHgFbh6cPw9m2dUVBR6BG1gxA==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=8" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/detect-libc": { - "version": "2.1.2", + "node_modules/@rolldown/binding-openharmony-arm64": { + "version": "1.0.0-beta.45", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-beta.45.tgz", + "integrity": "sha512-fljEqbO7RHHogNDxYtTzr+GNjlfOx21RUyGmF+NrkebZ8emYYiIqzPxsaMZuRx0rgZmVmliOzEp86/CQFDKhJQ==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "Apache-2.0", + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], "engines": { - "node": ">=8" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/devalue": { - "version": "5.3.2", + "node_modules/@rolldown/binding-wasm32-wasi": { + "version": "1.0.0-beta.45", + "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-beta.45.tgz", + "integrity": "sha512-ZJDB7lkuZE9XUnWQSYrBObZxczut+8FZ5pdanm8nNS1DAo8zsrPuvGwn+U3fwU98WaiFsNrA4XHngesCGr8tEQ==", + "cpu": [ + "wasm32" + ], "dev": true, - "license": "MIT" - }, - "node_modules/devlop": { - "version": "1.1.0", "license": "MIT", + "optional": true, "dependencies": { - "dequal": "^2.0.0" + "@napi-rs/wasm-runtime": "^1.0.7" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "engines": { + "node": ">=14.0.0" } }, - "node_modules/diff": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-8.0.2.tgz", - "integrity": "sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg==", + "node_modules/@rolldown/binding-win32-arm64-msvc": { + "version": "1.0.0-beta.45", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-beta.45.tgz", + "integrity": "sha512-zyzAjItHPUmxg6Z8SyRhLdXlJn3/D9KL5b9mObUrBHhWS/GwRH4665xCiFqeuktAhhWutqfc+rOV2LjK4VYQGQ==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=0.3.1" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/dir-glob": { - "version": "3.0.1", + "node_modules/@rolldown/binding-win32-ia32-msvc": { + "version": "1.0.0-beta.45", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.0.0-beta.45.tgz", + "integrity": "sha512-wODcGzlfxqS6D7BR0srkJk3drPwXYLu7jPHN27ce2c4PUnVVmJnp9mJzUQGT4LpmHmmVdMZ+P6hKvyTGBzc1CA==", + "cpu": [ + "ia32" + ], "dev": true, "license": "MIT", - "dependencies": { - "path-type": "^4.0.0" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=8" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/dotenv": { - "version": "8.6.0", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=10" - } - }, - "node_modules/dts-resolver": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/dts-resolver/-/dts-resolver-2.1.2.tgz", - "integrity": "sha512-xeXHBQkn2ISSXxbJWD828PFjtyg+/UrMDo7W4Ffcs7+YWCquxU8YjV1KoxuiL+eJ5pg3ll+bC6flVv61L3LKZg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=20.18.0" - }, - "funding": { - "url": "https://github.com/sponsors/sxzz" - }, - "peerDependencies": { - "oxc-resolver": ">=11.0.0" - }, - "peerDependenciesMeta": { - "oxc-resolver": { - "optional": true - } - } - }, - "node_modules/electron-to-chromium": { - "version": "1.5.230", - "dev": true, - "license": "ISC" - }, - "node_modules/empathic": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/empathic/-/empathic-2.0.0.tgz", - "integrity": "sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14" - } - }, - "node_modules/enquirer": { - "version": "2.4.1", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-colors": "^4.1.1", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/error-stack-parser-es": { - "version": "1.0.5", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, - "node_modules/es-module-lexer": { - "version": "1.7.0", - "dev": true, - "license": "MIT" - }, - "node_modules/esbuild": { - "version": "0.25.10", - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.10", - "@esbuild/android-arm": "0.25.10", - "@esbuild/android-arm64": "0.25.10", - "@esbuild/android-x64": "0.25.10", - "@esbuild/darwin-arm64": "0.25.10", - "@esbuild/darwin-x64": "0.25.10", - "@esbuild/freebsd-arm64": "0.25.10", - "@esbuild/freebsd-x64": "0.25.10", - "@esbuild/linux-arm": "0.25.10", - "@esbuild/linux-arm64": "0.25.10", - "@esbuild/linux-ia32": "0.25.10", - "@esbuild/linux-loong64": "0.25.10", - "@esbuild/linux-mips64el": "0.25.10", - "@esbuild/linux-ppc64": "0.25.10", - "@esbuild/linux-riscv64": "0.25.10", - "@esbuild/linux-s390x": "0.25.10", - "@esbuild/linux-x64": "0.25.10", - "@esbuild/netbsd-arm64": "0.25.10", - "@esbuild/netbsd-x64": "0.25.10", - "@esbuild/openbsd-arm64": "0.25.10", - "@esbuild/openbsd-x64": "0.25.10", - "@esbuild/openharmony-arm64": "0.25.10", - "@esbuild/sunos-x64": "0.25.10", - "@esbuild/win32-arm64": "0.25.10", - "@esbuild/win32-ia32": "0.25.10", - "@esbuild/win32-x64": "0.25.10" - } - }, - "node_modules/esbuild/node_modules/@esbuild/aix-ppc64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.10.tgz", - "integrity": "sha512-0NFWnA+7l41irNuaSVlLfgNT12caWJVLzp5eAVhZ0z1qpxbockccEt3s+149rE64VUI3Ml2zt8Nv5JVc4QXTsw==", + "node_modules/@rolldown/binding-win32-x64-msvc": { + "version": "1.0.0-beta.45", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-beta.45.tgz", + "integrity": "sha512-wiU40G1nQo9rtfvF9jLbl79lUgjfaD/LTyUEw2Wg/gdF5OhjzpKMVugZQngO+RNdwYaNj+Fs+kWBWfp4VXPMHA==", "cpu": [ - "ppc64" + "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ - "aix" + "win32" ], "engines": { - "node": ">=18" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/esbuild/node_modules/@esbuild/android-arm": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.10.tgz", - "integrity": "sha512-dQAxF1dW1C3zpeCDc5KqIYuZ1tgAdRXNoZP7vkBIRtKZPYe2xVr/d3SkirklCHudW1B45tGiUlz2pUWDfbDD4w==", + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-beta.27", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz", + "integrity": "sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.52.5.tgz", + "integrity": "sha512-8c1vW4ocv3UOMp9K+gToY5zL2XiiVw3k7f1ksf4yO1FlDFQ1C2u72iACFnSOceJFsWskc2WZNqeRhFRPzv+wtQ==", "cpu": [ "arm" ], + "dev": true, "license": "MIT", "optional": true, "os": [ "android" - ], - "engines": { - "node": ">=18" - } + ] }, - "node_modules/esbuild/node_modules/@esbuild/android-arm64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.10.tgz", - "integrity": "sha512-LSQa7eDahypv/VO6WKohZGPSJDq5OVOo3UoFR1E4t4Gj1W7zEQMUhI+lo81H+DtB+kP+tDgBp+M4oNCwp6kffg==", + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.52.5.tgz", + "integrity": "sha512-mQGfsIEFcu21mvqkEKKu2dYmtuSZOBMmAl5CFlPGLY94Vlcm+zWApK7F/eocsNzp8tKmbeBP8yXyAbx0XHsFNA==", "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ "android" - ], - "engines": { - "node": ">=18" - } + ] }, - "node_modules/esbuild/node_modules/@esbuild/android-x64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.10.tgz", - "integrity": "sha512-MiC9CWdPrfhibcXwr39p9ha1x0lZJ9KaVfvzA0Wxwz9ETX4v5CHfF09bx935nHlhi+MxhA63dKRRQLiVgSUtEg==", + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.52.5.tgz", + "integrity": "sha512-takF3CR71mCAGA+v794QUZ0b6ZSrgJkArC+gUiG6LB6TQty9T0Mqh3m2ImRBOxS2IeYBo4lKWIieSvnEk2OQWA==", "cpu": [ - "x64" + "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ - "android" - ], - "engines": { - "node": ">=18" - } + "darwin" + ] }, - "node_modules/esbuild/node_modules/@esbuild/darwin-x64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.10.tgz", - "integrity": "sha512-tguWg1olF6DGqzws97pKZ8G2L7Ig1vjDmGTwcTuYHbuU6TTjJe5FXbgs5C1BBzHbJ2bo1m3WkQDbWO2PvamRcg==", + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.52.5.tgz", + "integrity": "sha512-W901Pla8Ya95WpxDn//VF9K9u2JbocwV/v75TE0YIHNTbhqUTv9w4VuQ9MaWlNOkkEfFwkdNhXgcLqPSmHy0fA==", "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ "darwin" - ], - "engines": { - "node": ">=18" - } + ] }, - "node_modules/esbuild/node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.10.tgz", - "integrity": "sha512-3ZioSQSg1HT2N05YxeJWYR+Libe3bREVSdWhEEgExWaDtyFbbXWb49QgPvFH8u03vUPX10JhJPcz7s9t9+boWg==", + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.52.5.tgz", + "integrity": "sha512-QofO7i7JycsYOWxe0GFqhLmF6l1TqBswJMvICnRUjqCx8b47MTo46W8AoeQwiokAx3zVryVnxtBMcGcnX12LvA==", "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ "freebsd" - ], - "engines": { - "node": ">=18" - } + ] }, - "node_modules/esbuild/node_modules/@esbuild/freebsd-x64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.10.tgz", - "integrity": "sha512-LLgJfHJk014Aa4anGDbh8bmI5Lk+QidDmGzuC2D+vP7mv/GeSN+H39zOf7pN5N8p059FcOfs2bVlrRr4SK9WxA==", + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.52.5.tgz", + "integrity": "sha512-jr21b/99ew8ujZubPo9skbrItHEIE50WdV86cdSoRkKtmWa+DDr6fu2c/xyRT0F/WazZpam6kk7IHBerSL7LDQ==", "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ "freebsd" - ], - "engines": { - "node": ">=18" - } + ] }, - "node_modules/esbuild/node_modules/@esbuild/linux-arm": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.10.tgz", - "integrity": "sha512-oR31GtBTFYCqEBALI9r6WxoU/ZofZl962pouZRTEYECvNF/dtXKku8YXcJkhgK/beU+zedXfIzHijSRapJY3vg==", + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.52.5.tgz", + "integrity": "sha512-PsNAbcyv9CcecAUagQefwX8fQn9LQ4nZkpDboBOttmyffnInRy8R8dSg6hxxl2Re5QhHBf6FYIDhIj5v982ATQ==", "cpu": [ "arm" ], + "dev": true, "license": "MIT", "optional": true, "os": [ "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.52.5.tgz", + "integrity": "sha512-Fw4tysRutyQc/wwkmcyoqFtJhh0u31K+Q6jYjeicsGJJ7bbEq8LwPWV/w0cnzOqR2m694/Af6hpFayLJZkG2VQ==", + "cpu": [ + "arm" ], - "engines": { - "node": ">=18" - } + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/esbuild/node_modules/@esbuild/linux-arm64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.10.tgz", - "integrity": "sha512-5luJWN6YKBsawd5f9i4+c+geYiVEw20FVW5x0v1kEMWNq8UctFjDiMATBxLvmmHA4bf7F6hTRaJgtghFr9iziQ==", + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.52.5.tgz", + "integrity": "sha512-a+3wVnAYdQClOTlyapKmyI6BLPAFYs0JM8HRpgYZQO02rMR09ZcV9LbQB+NL6sljzG38869YqThrRnfPMCDtZg==", "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ "linux" - ], - "engines": { - "node": ">=18" - } + ] }, - "node_modules/esbuild/node_modules/@esbuild/linux-ia32": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.10.tgz", - "integrity": "sha512-NrSCx2Kim3EnnWgS4Txn0QGt0Xipoumb6z6sUtl5bOEZIVKhzfyp/Lyw4C1DIYvzeW/5mWYPBFJU3a/8Yr75DQ==", + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.52.5.tgz", + "integrity": "sha512-AvttBOMwO9Pcuuf7m9PkC1PUIKsfaAJ4AYhy944qeTJgQOqJYJ9oVl2nYgY7Rk0mkbsuOpCAYSs6wLYB2Xiw0Q==", "cpu": [ - "ia32" + "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ "linux" - ], - "engines": { - "node": ">=18" - } + ] }, - "node_modules/esbuild/node_modules/@esbuild/linux-loong64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.10.tgz", - "integrity": "sha512-xoSphrd4AZda8+rUDDfD9J6FUMjrkTz8itpTITM4/xgerAZZcFW7Dv+sun7333IfKxGG8gAq+3NbfEMJfiY+Eg==", + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.52.5.tgz", + "integrity": "sha512-DkDk8pmXQV2wVrF6oq5tONK6UHLz/XcEVow4JTTerdeV1uqPeHxwcg7aFsfnSm9L+OO8WJsWotKM2JJPMWrQtA==", "cpu": [ "loong64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ "linux" - ], - "engines": { - "node": ">=18" - } + ] }, - "node_modules/esbuild/node_modules/@esbuild/linux-mips64el": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.10.tgz", - "integrity": "sha512-ab6eiuCwoMmYDyTnyptoKkVS3k8fy/1Uvq7Dj5czXI6DF2GqD2ToInBI0SHOp5/X1BdZ26RKc5+qjQNGRBelRA==", + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.52.5.tgz", + "integrity": "sha512-W/b9ZN/U9+hPQVvlGwjzi+Wy4xdoH2I8EjaCkMvzpI7wJUs8sWJ03Rq96jRnHkSrcHTpQe8h5Tg3ZzUPGauvAw==", "cpu": [ - "mips64el" + "ppc64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ "linux" - ], - "engines": { - "node": ">=18" - } + ] }, - "node_modules/esbuild/node_modules/@esbuild/linux-ppc64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.10.tgz", - "integrity": "sha512-NLinzzOgZQsGpsTkEbdJTCanwA5/wozN9dSgEl12haXJBzMTpssebuXR42bthOF3z7zXFWH1AmvWunUCkBE4EA==", + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.52.5.tgz", + "integrity": "sha512-sjQLr9BW7R/ZiXnQiWPkErNfLMkkWIoCz7YMn27HldKsADEKa5WYdobaa1hmN6slu9oWQbB6/jFpJ+P2IkVrmw==", "cpu": [ - "ppc64" + "riscv64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ "linux" - ], - "engines": { - "node": ">=18" - } + ] }, - "node_modules/esbuild/node_modules/@esbuild/linux-riscv64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.10.tgz", - "integrity": "sha512-FE557XdZDrtX8NMIeA8LBJX3dC2M8VGXwfrQWU7LB5SLOajfJIxmSdyL/gU1m64Zs9CBKvm4UAuBp5aJ8OgnrA==", + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.52.5.tgz", + "integrity": "sha512-hq3jU/kGyjXWTvAh2awn8oHroCbrPm8JqM7RUpKjalIRWWXE01CQOf/tUNWNHjmbMHg/hmNCwc/Pz3k1T/j/Lg==", "cpu": [ "riscv64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ "linux" - ], - "engines": { - "node": ">=18" - } + ] }, - "node_modules/esbuild/node_modules/@esbuild/linux-s390x": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.10.tgz", - "integrity": "sha512-3BBSbgzuB9ajLoVZk0mGu+EHlBwkusRmeNYdqmznmMc9zGASFjSsxgkNsqmXugpPk00gJ0JNKh/97nxmjctdew==", + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.52.5.tgz", + "integrity": "sha512-gn8kHOrku8D4NGHMK1Y7NA7INQTRdVOntt1OCYypZPRt6skGbddska44K8iocdpxHTMMNui5oH4elPH4QOLrFQ==", "cpu": [ "s390x" ], + "dev": true, "license": "MIT", "optional": true, "os": [ "linux" - ], - "engines": { - "node": ">=18" - } + ] }, - "node_modules/esbuild/node_modules/@esbuild/linux-x64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.10.tgz", - "integrity": "sha512-QSX81KhFoZGwenVyPoberggdW1nrQZSvfVDAIUXr3WqLRZGZqWk/P4T8p2SP+de2Sr5HPcvjhcJzEiulKgnxtA==", + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.52.5.tgz", + "integrity": "sha512-hXGLYpdhiNElzN770+H2nlx+jRog8TyynpTVzdlc6bndktjKWyZyiCsuDAlpd+j+W+WNqfcyAWz9HxxIGfZm1Q==", "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ "linux" - ], - "engines": { - "node": ">=18" - } + ] }, - "node_modules/esbuild/node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.10.tgz", - "integrity": "sha512-AKQM3gfYfSW8XRk8DdMCzaLUFB15dTrZfnX8WXQoOUpUBQ+NaAFCP1kPS/ykbbGYz7rxn0WS48/81l9hFl3u4A==", + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.52.5.tgz", + "integrity": "sha512-arCGIcuNKjBoKAXD+y7XomR9gY6Mw7HnFBv5Rw7wQRvwYLR7gBAgV7Mb2QTyjXfTveBNFAtPt46/36vV9STLNg==", "cpu": [ - "arm64" + "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } + "linux" + ] }, - "node_modules/esbuild/node_modules/@esbuild/netbsd-x64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.10.tgz", - "integrity": "sha512-7RTytDPGU6fek/hWuN9qQpeGPBZFfB4zZgcz2VK2Z5VpdUxEI8JKYsg3JfO0n/Z1E/6l05n0unDCNc4HnhQGig==", + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.52.5.tgz", + "integrity": "sha512-QoFqB6+/9Rly/RiPjaomPLmR/13cgkIGfA40LHly9zcH1S0bN2HVFYk3a1eAyHQyjs3ZJYlXvIGtcCs5tko9Cw==", "cpu": [ - "x64" + "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } + "openharmony" + ] }, - "node_modules/esbuild/node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.10.tgz", - "integrity": "sha512-5Se0VM9Wtq797YFn+dLimf2Zx6McttsH2olUBsDml+lm0GOCRVebRWUvDtkY4BWYv/3NgzS8b/UM3jQNh5hYyw==", + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.52.5.tgz", + "integrity": "sha512-w0cDWVR6MlTstla1cIfOGyl8+qb93FlAVutcor14Gf5Md5ap5ySfQ7R9S/NjNaMLSFdUnKGEasmVnu3lCMqB7w==", "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } + "win32" + ] }, - "node_modules/esbuild/node_modules/@esbuild/openbsd-x64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.10.tgz", - "integrity": "sha512-XkA4frq1TLj4bEMB+2HnI0+4RnjbuGZfet2gs/LNs5Hc7D89ZQBHQ0gL2ND6Lzu1+QVkjp3x1gIcPKzRNP8bXw==", + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.52.5.tgz", + "integrity": "sha512-Aufdpzp7DpOTULJCuvzqcItSGDH73pF3ko/f+ckJhxQyHtp67rHw3HMNxoIdDMUITJESNE6a8uh4Lo4SLouOUg==", "cpu": [ - "x64" + "ia32" ], + "dev": true, "license": "MIT", "optional": true, "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } + "win32" + ] }, - "node_modules/esbuild/node_modules/@esbuild/sunos-x64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.10.tgz", - "integrity": "sha512-fswk3XT0Uf2pGJmOpDB7yknqhVkJQkAQOcW/ccVOtfx05LkbWOaRAtn5SaqXypeKQra1QaEa841PgrSL9ubSPQ==", + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.52.5.tgz", + "integrity": "sha512-UGBUGPFp1vkj6p8wCRraqNhqwX/4kNQPS57BCFc8wYh0g94iVIW33wJtQAx3G7vrjjNtRaxiMUylM0ktp/TRSQ==", "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } + "win32" + ] }, - "node_modules/esbuild/node_modules/@esbuild/win32-arm64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.10.tgz", - "integrity": "sha512-ah+9b59KDTSfpaCg6VdJoOQvKjI33nTaQr4UluQwW7aEwZQsbMCfTmfEO4VyewOxx4RaDT/xCy9ra2GPWmO7Kw==", + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.52.5.tgz", + "integrity": "sha512-TAcgQh2sSkykPRWLrdyy2AiceMckNf5loITqXxFI5VuQjS5tSuw3WlwdN8qv8vzjLAUTvYaH/mVjSFpbkFbpTg==", "cpu": [ - "arm64" + "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ "win32" - ], - "engines": { - "node": ">=18" - } + ] }, - "node_modules/esbuild/node_modules/@esbuild/win32-ia32": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.10.tgz", - "integrity": "sha512-QHPDbKkrGO8/cz9LKVnJU22HOi4pxZnZhhA2HYHez5Pz4JeffhDjf85E57Oyco163GnzNCVkZK0b/n4Y0UHcSw==", - "cpu": [ - "ia32" - ], + "node_modules/@sindresorhus/is": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-7.1.0.tgz", + "integrity": "sha512-7F/yz2IphV39hiS2zB4QYVkivrptHHh0K8qJJd9HhuWSdvf8AN7NpebW3CcDZDBQsUPMoDKWsY2WWgW7bqOcfA==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ], "engines": { "node": ">=18" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" } }, - "node_modules/esbuild/node_modules/@esbuild/win32-x64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.10.tgz", - "integrity": "sha512-9KpxSVFCu0iK1owoez6aC/s/EdUQLDN3adTxGCqxMVhrPDj6bt5dbrHDXUuq+Bs2vATFBBrQS5vdQ/Ed2P+nbw==", - "cpu": [ - "x64" - ], + "node_modules/@speed-highlight/core": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@speed-highlight/core/-/core-1.2.8.tgz", + "integrity": "sha512-IGytNtnUnPIobIbOq5Y6LIlqiHNX+vnToQIS7lj6L5819C+rA8TXRDkkG8vePsiBOGcoW9R6i+dp2YBUKdB09Q==", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", + "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==", + "dev": true, "license": "MIT", "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" + "dependencies": { + "tslib": "^2.4.0" } }, - "node_modules/escalade": { - "version": "3.2.0", + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", "dev": true, "license": "MIT", - "engines": { - "node": ">=6" + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" } }, - "node_modules/escape-string-regexp": { - "version": "5.0.0", + "node_modules/@types/babel__generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "dev": true, "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "dependencies": { + "@babel/types": "^7.0.0" } }, - "node_modules/esprima": { - "version": "4.0.1", + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", "dev": true, - "license": "BSD-2-Clause", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" } }, - "node_modules/estree-util-is-identifier-name": { - "version": "3.0.0", + "node_modules/@types/babel__traverse": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", + "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", + "dev": true, "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "dependencies": { + "@babel/types": "^7.28.2" } }, - "node_modules/estree-walker": { - "version": "3.0.3", + "node_modules/@types/bun": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@types/bun/-/bun-1.3.1.tgz", + "integrity": "sha512-4jNMk2/K9YJtfqwoAa28c8wK+T7nvJFOjxI4h/7sORWcypRNxBpr+TPNaCfVWq70tLCJsqoFwcf0oI0JU/fvMQ==", "dev": true, "license": "MIT", "dependencies": { - "@types/estree": "^1.0.0" + "bun-types": "1.3.1" } }, - "node_modules/exit-hook": { - "version": "2.2.1", + "node_modules/@types/chai": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", + "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", "dev": true, "license": "MIT", - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "dependencies": { + "@types/deep-eql": "*", + "assertion-error": "^2.0.1" } }, - "node_modules/expect-type": { - "version": "1.2.2", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=12.0.0" + "node_modules/@types/debug": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "license": "MIT", + "dependencies": { + "@types/ms": "*" } }, - "node_modules/exsolve": { - "version": "1.0.7", + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", "dev": true, "license": "MIT" }, - "node_modules/extend": { - "version": "3.0.2", + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", "license": "MIT" }, - "node_modules/extendable-error": { - "version": "0.1.7", - "dev": true, - "license": "MIT" + "node_modules/@types/estree-jsx": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.5.tgz", + "integrity": "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==", + "license": "MIT", + "dependencies": { + "@types/estree": "*" + } }, - "node_modules/fast-glob": { - "version": "3.3.3", - "dev": true, + "node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", "license": "MIT", "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.8" - }, - "engines": { - "node": ">=8.6.0" + "@types/unist": "*" } }, - "node_modules/fastq": { - "version": "1.19.1", - "dev": true, - "license": "ISC", + "node_modules/@types/mdast": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", + "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", + "license": "MIT", "dependencies": { - "reusify": "^1.0.4" + "@types/unist": "*" } }, - "node_modules/fflate": { - "version": "0.8.2", - "dev": true, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", "license": "MIT" }, - "node_modules/fill-range": { - "version": "7.1.1", + "node_modules/@types/node": { + "version": "24.9.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.9.2.tgz", + "integrity": "sha512-uWN8YqxXxqFMX2RqGOrumsKeti4LlmIMIyV0lgut4jx7KQBcBiW6vkDtIBvHnHIquwNfJhk8v2OtmO8zXWHfPA==", "dev": true, "license": "MIT", "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" + "undici-types": "~7.16.0" } }, - "node_modules/filter-obj": { - "version": "5.1.0", + "node_modules/@types/react": { + "version": "19.2.2", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.2.tgz", + "integrity": "sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA==", + "license": "MIT", + "dependencies": { + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "19.2.2", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.2.tgz", + "integrity": "sha512-9KQPoO6mZCi7jcIStSnlOWn2nEF3mNmyr3rIAsGnAbQKYbRLyqmeSc39EVgtxXVia+LMT8j3knZLAZAh+xLmrw==", "dev": true, "license": "MIT", - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "@types/react": "^19.2.0" } }, - "node_modules/find-up": { - "version": "4.1.0", + "node_modules/@types/react-katex": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/react-katex/-/react-katex-3.0.4.tgz", + "integrity": "sha512-aLkykKzSKLpXI6REJ3uClao6P47HAFfR1gcHOZwDeTuALsyjgMhz+oynLV4gX0kiJVnvHrBKF/TLXqyNTpHDUg==", "dev": true, "license": "MIT", "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" + "@types/react": "*" } }, - "node_modules/flatted": { - "version": "3.3.3", + "node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "license": "MIT" + }, + "node_modules/@types/whatwg-mimetype": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/whatwg-mimetype/-/whatwg-mimetype-3.0.2.tgz", + "integrity": "sha512-c2AKvDT8ToxLIOUlN51gTiHXflsfIFisS4pO7pDPoKouJCESkhZnEy623gwP9laCy5lnLDAw1vAzu2vM2YLOrA==", "dev": true, - "license": "ISC" + "license": "MIT" }, - "node_modules/fs-extra": { - "version": "7.0.1", + "node_modules/@types/ws": { + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", "dev": true, "license": "MIT", "dependencies": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" + "@types/node": "*" } }, - "node_modules/fsevents": { - "version": "2.3.3", - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "license": "ISC" }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", + "node_modules/@vitejs/plugin-react": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.7.0.tgz", + "integrity": "sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==", "dev": true, "license": "MIT", + "dependencies": { + "@babel/core": "^7.28.0", + "@babel/plugin-transform-react-jsx-self": "^7.27.1", + "@babel/plugin-transform-react-jsx-source": "^7.27.1", + "@rolldown/pluginutils": "1.0.0-beta.27", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.17.0" + }, "engines": { - "node": ">=6.9.0" + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" } }, - "node_modules/get-port": { - "version": "7.1.0", + "node_modules/@vitest/expect": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.2.4.tgz", + "integrity": "sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==", "dev": true, "license": "MIT", - "engines": { - "node": ">=16" + "dependencies": { + "@types/chai": "^5.2.2", + "@vitest/spy": "3.2.4", + "@vitest/utils": "3.2.4", + "chai": "^5.2.0", + "tinyrainbow": "^2.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://opencollective.com/vitest" } }, - "node_modules/get-tsconfig": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.0.tgz", - "integrity": "sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==", + "node_modules/@vitest/mocker": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.2.4.tgz", + "integrity": "sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==", "dev": true, "license": "MIT", "dependencies": { - "resolve-pkg-maps": "^1.0.0" + "@vitest/spy": "3.2.4", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.17" }, "funding": { - "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" - } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" + "url": "https://opencollective.com/vitest" }, - "engines": { - "node": ">= 6" + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } } }, - "node_modules/glob-to-regexp": { - "version": "0.4.1", - "dev": true, - "license": "BSD-2-Clause" - }, - "node_modules/globby": { - "version": "11.1.0", + "node_modules/@vitest/pretty-format": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.4.tgz", + "integrity": "sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==", "dev": true, "license": "MIT", "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" + "tinyrainbow": "^2.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://opencollective.com/vitest" } }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "dev": true, - "license": "ISC" - }, - "node_modules/happy-dom": { - "version": "20.0.5", + "node_modules/@vitest/runner": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.2.4.tgz", + "integrity": "sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==", "dev": true, "license": "MIT", "dependencies": { - "@types/node": "^20.0.0", - "@types/whatwg-mimetype": "^3.0.2", - "whatwg-mimetype": "^3.0.0" + "@vitest/utils": "3.2.4", + "pathe": "^2.0.3", + "strip-literal": "^3.0.0" }, - "engines": { - "node": ">=20.0.0" + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/happy-dom/node_modules/@types/node": { - "version": "20.19.19", + "node_modules/@vitest/snapshot": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.2.4.tgz", + "integrity": "sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==", "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~6.21.0" + "@vitest/pretty-format": "3.2.4", + "magic-string": "^0.30.17", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/happy-dom/node_modules/undici-types": { - "version": "6.21.0", + "node_modules/@vitest/spy": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.2.4.tgz", + "integrity": "sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==", "dev": true, - "license": "MIT" - }, - "node_modules/hast-util-to-jsx-runtime": { - "version": "2.3.6", "license": "MIT", "dependencies": { - "@types/estree": "^1.0.0", - "@types/hast": "^3.0.0", - "@types/unist": "^3.0.0", - "comma-separated-tokens": "^2.0.0", - "devlop": "^1.0.0", - "estree-util-is-identifier-name": "^3.0.0", - "hast-util-whitespace": "^3.0.0", - "mdast-util-mdx-expression": "^2.0.0", - "mdast-util-mdx-jsx": "^3.0.0", - "mdast-util-mdxjs-esm": "^2.0.0", - "property-information": "^7.0.0", - "space-separated-tokens": "^2.0.0", - "style-to-js": "^1.0.0", - "unist-util-position": "^5.0.0", - "vfile-message": "^4.0.0" + "tinyspy": "^4.0.3" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://opencollective.com/vitest" } }, - "node_modules/hast-util-whitespace": { - "version": "3.0.0", + "node_modules/@vitest/ui": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/ui/-/ui-3.2.4.tgz", + "integrity": "sha512-hGISOaP18plkzbWEcP/QvtRW1xDXF2+96HbEX6byqQhAUbiS5oH6/9JwW+QsQCIYON2bI6QZBF+2PvOmrRZ9wA==", + "dev": true, "license": "MIT", "dependencies": { - "@types/hast": "^3.0.0" + "@vitest/utils": "3.2.4", + "fflate": "^0.8.2", + "flatted": "^3.3.3", + "pathe": "^2.0.3", + "sirv": "^3.0.1", + "tinyglobby": "^0.2.14", + "tinyrainbow": "^2.0.0" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "vitest": "3.2.4" } }, - "node_modules/hookable": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz", - "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==", + "node_modules/@vitest/utils": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.2.4.tgz", + "integrity": "sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==", "dev": true, - "license": "MIT" - }, - "node_modules/html-url-attributes": { - "version": "3.0.1", "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "3.2.4", + "loupe": "^3.1.4", + "tinyrainbow": "^2.0.0" + }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://opencollective.com/vitest" } }, - "node_modules/human-id": { - "version": "4.1.1", + "node_modules/acorn": { + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", "dev": true, "license": "MIT", "bin": { - "human-id": "dist/cli.js" + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" } }, - "node_modules/iconv-lite": { - "version": "0.7.0", + "node_modules/acorn-walk": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", + "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", "dev": true, "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, "engines": { - "node": ">=0.10.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" + "node": ">=0.4.0" } }, - "node_modules/ignore": { - "version": "5.3.2", + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", "dev": true, "license": "MIT", "engines": { - "node": ">= 4" + "node": ">=6" } }, - "node_modules/inline-style-parser": { - "version": "0.2.4", - "license": "MIT" - }, - "node_modules/is-arrayish": { - "version": "0.3.4", + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=8" + } }, - "node_modules/is-extglob": { - "version": "2.1.1", + "node_modules/ansis": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/ansis/-/ansis-4.2.0.tgz", + "integrity": "sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig==", "dev": true, - "license": "MIT", + "license": "ISC", "engines": { - "node": ">=0.10.0" + "node": ">=14" } }, - "node_modules/is-glob": { - "version": "4.0.3", + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, "license": "MIT", "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" + "sprintf-js": "~1.0.2" } }, - "node_modules/is-number": { - "version": "7.0.0", + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true, "license": "MIT", "engines": { - "node": ">=0.12.0" + "node": ">=8" } }, - "node_modules/is-plain-obj": { - "version": "4.1.0", + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "dev": true, "license": "MIT", "engines": { "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-subdir": { - "version": "1.2.0", + "node_modules/ast-kit": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ast-kit/-/ast-kit-2.1.3.tgz", + "integrity": "sha512-TH+b3Lv6pUjy/Nu0m6A2JULtdzLpmqF9x1Dhj00ZoEiML8qvVA9j1flkzTKNYgdEhWrjDwtWNpyyCUbfQe514g==", "dev": true, "license": "MIT", "dependencies": { - "better-path-resolve": "1.0.0" + "@babel/parser": "^7.28.4", + "pathe": "^2.0.3" }, "engines": { - "node": ">=4" + "node": ">=20.19.0" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" } }, - "node_modules/is-windows": { - "version": "1.0.2", - "dev": true, + "node_modules/bail": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", + "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==", "license": "MIT", - "engines": { - "node": ">=0.10.0" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/isbinaryfile": { - "version": "5.0.6", + "node_modules/baseline-browser-mapping": { + "version": "2.8.21", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.21.tgz", + "integrity": "sha512-JU0h5APyQNsHOlAM7HnQnPToSDQoEBZqzu/YBlqDnEeymPnZDREeXJA3KBMQee+dKteAxZ2AtvQEvVYdZf241Q==", "dev": true, - "license": "MIT", - "engines": { - "node": ">= 18.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/gjtorikian/" + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.js" } }, - "node_modules/isexe": { - "version": "2.0.0", + "node_modules/before-after-hook": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", + "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==", "dev": true, - "license": "ISC" + "license": "Apache-2.0" }, - "node_modules/jiti": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", - "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", + "node_modules/better-path-resolve": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/better-path-resolve/-/better-path-resolve-1.0.0.tgz", + "integrity": "sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==", "dev": true, "license": "MIT", - "bin": { - "jiti": "lib/jiti-cli.mjs" + "dependencies": { + "is-windows": "^1.0.0" + }, + "engines": { + "node": ">=4" } }, - "node_modules/js-tokens": { - "version": "4.0.0", + "node_modules/birpc": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/birpc/-/birpc-0.2.14.tgz", + "integrity": "sha512-37FHE8rqsYM5JEKCnXFyHpBCzvgHEExwVVTq+nUmloInU7l8ezD1TpOhKpS8oe1DTYFqEK27rFZVKG43oTqXRA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/blake3-wasm": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/blake3-wasm/-/blake3-wasm-2.1.5.tgz", + "integrity": "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==", + "dev": true, "license": "MIT" }, - "node_modules/js-yaml": { - "version": "3.14.1", + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, "license": "MIT", "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "fill-range": "^7.1.1" }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "engines": { + "node": ">=8" } }, - "node_modules/jsesc": { - "version": "3.1.0", + "node_modules/browserslist": { + "version": "4.27.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.27.0.tgz", + "integrity": "sha512-AXVQwdhot1eqLihwasPElhX2tAZiBjWdJ9i/Zcj2S6QYIjkx62OKSfnobkriB81C3l4w0rVy3Nt4jaTBltYEpw==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.8.19", + "caniuse-lite": "^1.0.30001751", + "electron-to-chromium": "^1.5.238", + "node-releases": "^2.0.26", + "update-browserslist-db": "^1.1.4" + }, "bin": { - "jsesc": "bin/jsesc" + "browserslist": "cli.js" }, "engines": { - "node": ">=6" + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, - "node_modules/json5": { - "version": "2.2.3", + "node_modules/bun-types": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/bun-types/-/bun-types-1.3.1.tgz", + "integrity": "sha512-NMrcy7smratanWJ2mMXdpatalovtxVggkj11bScuWuiOoXTiKIu2eVS1/7qbyI/4yHedtsn175n4Sm4JcdHLXw==", "dev": true, "license": "MIT", - "bin": { - "json5": "lib/cli.js" + "dependencies": { + "@types/node": "*" }, - "engines": { - "node": ">=6" + "peerDependencies": { + "@types/react": "^19" } }, - "node_modules/jsonfile": { - "version": "4.0.0", + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", "dev": true, "license": "MIT", - "optionalDependencies": { - "graceful-fs": "^4.1.6" + "engines": { + "node": ">=8" } }, - "node_modules/katex": { - "version": "0.16.23", + "node_modules/call-me-maybe": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz", + "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001751", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001751.tgz", + "integrity": "sha512-A0QJhug0Ly64Ii3eIqHu5X51ebln3k4yTUkY1j8drqpWHVreg/VLijN48cZ1bYPiqOQuqpkIKnzr/Ul8V+p6Cw==", + "dev": true, "funding": [ - "https://opencollective.com/katex", - "https://github.com/sponsors/katex" + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } ], + "license": "CC-BY-4.0" + }, + "node_modules/ccount": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/chai": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/chai/-/chai-5.3.3.tgz", + "integrity": "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==", + "dev": true, "license": "MIT", "dependencies": { - "commander": "^8.3.0" + "assertion-error": "^2.0.1", + "check-error": "^2.1.1", + "deep-eql": "^5.0.1", + "loupe": "^3.1.0", + "pathval": "^2.0.0" }, - "bin": { - "katex": "cli.js" + "engines": { + "node": ">=18" } }, - "node_modules/katex/node_modules/commander": { - "version": "8.3.0", + "node_modules/character-entities": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", + "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", "license": "MIT", - "engines": { - "node": ">= 12" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/kleur": { - "version": "4.1.5", + "node_modules/character-entities-html4": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", + "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-legacy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", + "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-reference-invalid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz", + "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/chardet": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-2.1.0.tgz", + "integrity": "sha512-bNFETTG/pM5ryzQ9Ad0lJOTa6HWD/YsScAR3EnCPZRPlQh77JocYktSHOUHelyhm8IARL+o4c4F1bP5KVOjiRA==", + "dev": true, + "license": "MIT" + }, + "node_modules/check-error": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", + "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", "dev": true, "license": "MIT", "engines": { - "node": ">=6" + "node": ">= 16" } }, - "node_modules/locate-path": { - "version": "5.0.0", + "node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", "dev": true, "license": "MIT", "dependencies": { - "p-locate": "^4.1.0" + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/lodash.startcase": { - "version": "4.4.0", + "node_modules/cjs-module-lexer": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", + "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==", "dev": true, "license": "MIT" }, - "node_modules/longest-streak": { - "version": "3.1.0", + "node_modules/color": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", + "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", + "dev": true, "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "dependencies": { + "color-convert": "^2.0.1", + "color-string": "^1.9.0" + }, + "engines": { + "node": ">=12.5.0" } }, - "node_modules/loose-envify": { - "version": "1.4.0", + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" + "color-name": "~1.1.4" }, - "bin": { - "loose-envify": "cli.js" + "engines": { + "node": ">=7.0.0" } }, - "node_modules/loupe": { - "version": "3.2.1", + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true, "license": "MIT" }, - "node_modules/lru-cache": { - "version": "5.1.1", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/magic-string": { - "version": "0.30.21", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", - "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.5" + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" } }, - "node_modules/markdown-table": { - "version": "3.0.4", + "node_modules/comma-separated-tokens": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", + "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/mdast-util-find-and-replace": { - "version": "3.0.2", + "node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "escape-string-regexp": "^5.0.0", - "unist-util-is": "^6.0.0", - "unist-util-visit-parents": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">= 12" } }, - "node_modules/mdast-util-from-markdown": { - "version": "2.0.2", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "mdast-util-to-string": "^4.0.0", - "micromark": "^4.0.0", - "micromark-util-decode-numeric-character-reference": "^2.0.0", - "micromark-util-decode-string": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0", - "unist-util-stringify-position": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } + "node_modules/confbox": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz", + "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==", + "dev": true, + "license": "MIT" }, - "node_modules/mdast-util-gfm": { - "version": "3.1.0", - "license": "MIT", - "dependencies": { - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-gfm-autolink-literal": "^2.0.0", - "mdast-util-gfm-footnote": "^2.0.0", - "mdast-util-gfm-strikethrough": "^2.0.0", - "mdast-util-gfm-table": "^2.0.0", - "mdast-util-gfm-task-list-item": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" }, - "node_modules/mdast-util-gfm-autolink-literal": { - "version": "2.0.1", + "node_modules/cookie": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz", + "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==", + "dev": true, "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "ccount": "^2.0.0", - "devlop": "^1.0.0", - "mdast-util-find-and-replace": "^3.0.0", - "micromark-util-character": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">=18" } }, - "node_modules/mdast-util-gfm-footnote": { - "version": "2.1.0", + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, "license": "MIT", "dependencies": { - "@types/mdast": "^4.0.0", - "devlop": "^1.1.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0" + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">= 8" } }, - "node_modules/mdast-util-gfm-strikethrough": { - "version": "2.0.0", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "license": "MIT" }, - "node_modules/mdast-util-gfm-table": { - "version": "2.0.0", + "node_modules/dataloader": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/dataloader/-/dataloader-1.4.0.tgz", + "integrity": "sha512-68s5jYdlvasItOJnCuI2Q9s4q98g0pCyL3HrcKJu8KNugUl8ahgmZYg38ysLTgQjjXX3H8CJLkAvWrclWfcalw==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "license": "MIT", "dependencies": { - "@types/mdast": "^4.0.0", - "devlop": "^1.0.0", - "markdown-table": "^3.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" + "ms": "^2.1.3" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/mdast-util-gfm-task-list-item": { - "version": "2.0.0", + "node_modules/decode-named-character-reference": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.2.0.tgz", + "integrity": "sha512-c6fcElNV6ShtZXmsgNgFFV5tVX2PaV4g+MOAkb8eXHvn6sryJBrZa9r0zV6+dtTyoCKxtDy5tyQ5ZwQuidtd+Q==", "license": "MIT", "dependencies": { - "@types/mdast": "^4.0.0", - "devlop": "^1.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" + "character-entities": "^2.0.0" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/mdast-util-mdx-expression": { - "version": "2.0.1", + "node_modules/decode-uri-component": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.4.1.tgz", + "integrity": "sha512-+8VxcR21HhTy8nOt6jf20w0c9CADrw1O8d+VZ/YzzCt4bJ3uBjw+D1q2osAB8RnpwwaeYBxy0HyKQxD5JBMuuQ==", + "dev": true, "license": "MIT", - "dependencies": { - "@types/estree-jsx": "^1.0.0", - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "devlop": "^1.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">=14.16" } }, - "node_modules/mdast-util-mdx-jsx": { - "version": "3.2.0", + "node_modules/deep-eql": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", + "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", + "dev": true, "license": "MIT", - "dependencies": { - "@types/estree-jsx": "^1.0.0", - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "ccount": "^2.0.0", - "devlop": "^1.1.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0", - "parse-entities": "^4.0.0", - "stringify-entities": "^4.0.0", - "unist-util-stringify-position": "^4.0.0", - "vfile-message": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">=6" } }, - "node_modules/mdast-util-mdx-jsx/node_modules/character-entities-legacy": { - "version": "3.0.0", + "node_modules/defu": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", + "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", + "dev": true, + "license": "MIT" + }, + "node_modules/deprecation": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", + "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "engines": { + "node": ">=6" } }, - "node_modules/mdast-util-mdx-jsx/node_modules/character-reference-invalid": { - "version": "2.0.1", + "node_modules/detect-indent": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", + "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", + "dev": true, "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "engines": { + "node": ">=8" } }, - "node_modules/mdast-util-mdx-jsx/node_modules/is-alphabetical": { - "version": "2.0.1", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" } }, - "node_modules/mdast-util-mdx-jsx/node_modules/is-alphanumerical": { - "version": "2.0.1", + "node_modules/devalue": { + "version": "5.4.2", + "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.4.2.tgz", + "integrity": "sha512-MwPZTKEPK2k8Qgfmqrd48ZKVvzSQjgW0lXLxiIBA8dQjtf/6mw6pggHNLcyDKyf+fI6eXxlQwPsfaCMTU5U+Bw==", + "dev": true, + "license": "MIT" + }, + "node_modules/devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", "license": "MIT", "dependencies": { - "is-alphabetical": "^2.0.0", - "is-decimal": "^2.0.0" + "dequal": "^2.0.0" }, "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/mdast-util-mdx-jsx/node_modules/is-decimal": { - "version": "2.0.1", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "node_modules/diff": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-8.0.2.tgz", + "integrity": "sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" } }, - "node_modules/mdast-util-mdx-jsx/node_modules/is-hexadecimal": { - "version": "2.0.1", + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/mdast-util-mdx-jsx/node_modules/parse-entities": { - "version": "4.0.2", - "license": "MIT", - "dependencies": { - "@types/unist": "^2.0.0", - "character-entities-legacy": "^3.0.0", - "character-reference-invalid": "^2.0.0", - "decode-named-character-reference": "^1.0.0", - "is-alphanumerical": "^2.0.0", - "is-decimal": "^2.0.0", - "is-hexadecimal": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "node_modules/dotenv": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz", + "integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=10" } }, - "node_modules/mdast-util-mdx-jsx/node_modules/parse-entities/node_modules/@types/unist": { - "version": "2.0.11", - "license": "MIT" - }, - "node_modules/mdast-util-mdxjs-esm": { - "version": "2.0.1", + "node_modules/dts-resolver": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/dts-resolver/-/dts-resolver-2.1.2.tgz", + "integrity": "sha512-xeXHBQkn2ISSXxbJWD828PFjtyg+/UrMDo7W4Ffcs7+YWCquxU8YjV1KoxuiL+eJ5pg3ll+bC6flVv61L3LKZg==", + "dev": true, "license": "MIT", - "dependencies": { - "@types/estree-jsx": "^1.0.0", - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "devlop": "^1.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" + "engines": { + "node": ">=20.18.0" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://github.com/sponsors/sxzz" + }, + "peerDependencies": { + "oxc-resolver": ">=11.0.0" + }, + "peerDependenciesMeta": { + "oxc-resolver": { + "optional": true + } } }, - "node_modules/mdast-util-phrasing": { - "version": "4.1.0", + "node_modules/electron-to-chromium": { + "version": "1.5.243", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.243.tgz", + "integrity": "sha512-ZCphxFW3Q1TVhcgS9blfut1PX8lusVi2SvXQgmEEnK4TCmE1JhH2JkjJN+DNt0pJJwfBri5AROBnz2b/C+YU9g==", + "dev": true, + "license": "ISC" + }, + "node_modules/empathic": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/empathic/-/empathic-2.0.0.tgz", + "integrity": "sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA==", + "dev": true, "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "unist-util-is": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">=14" } }, - "node_modules/mdast-util-to-hast": { - "version": "13.2.0", + "node_modules/enquirer": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz", + "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==", + "dev": true, "license": "MIT", "dependencies": { - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "@ungap/structured-clone": "^1.0.0", - "devlop": "^1.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "trim-lines": "^3.0.0", - "unist-util-position": "^5.0.0", - "unist-util-visit": "^5.0.0", - "vfile": "^6.0.0" + "ansi-colors": "^4.1.1", + "strip-ansi": "^6.0.1" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">=8.6" } }, - "node_modules/mdast-util-to-markdown": { - "version": "2.1.2", + "node_modules/error-stack-parser-es": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/error-stack-parser-es/-/error-stack-parser-es-1.0.5.tgz", + "integrity": "sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA==", + "dev": true, "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "longest-streak": "^3.0.0", - "mdast-util-phrasing": "^4.0.0", - "mdast-util-to-string": "^4.0.0", - "micromark-util-classify-character": "^2.0.0", - "micromark-util-decode-string": "^2.0.0", - "unist-util-visit": "^5.0.0", - "zwitch": "^2.0.0" - }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://github.com/sponsors/antfu" } }, - "node_modules/mdast-util-to-string": { - "version": "4.0.0", + "node_modules/es-module-lexer": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", + "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", + "dev": true, + "license": "MIT" + }, + "node_modules/esbuild": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.11.tgz", + "integrity": "sha512-KohQwyzrKTQmhXDW1PjCv3Tyspn9n5GcY2RTDqeORIdIJY8yKIF7sTSopFmn/wpMPW4rdPXI0UE5LJLuq3bx0Q==", + "hasInstallScript": true, "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0" + "bin": { + "esbuild": "bin/esbuild" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.11", + "@esbuild/android-arm": "0.25.11", + "@esbuild/android-arm64": "0.25.11", + "@esbuild/android-x64": "0.25.11", + "@esbuild/darwin-arm64": "0.25.11", + "@esbuild/darwin-x64": "0.25.11", + "@esbuild/freebsd-arm64": "0.25.11", + "@esbuild/freebsd-x64": "0.25.11", + "@esbuild/linux-arm": "0.25.11", + "@esbuild/linux-arm64": "0.25.11", + "@esbuild/linux-ia32": "0.25.11", + "@esbuild/linux-loong64": "0.25.11", + "@esbuild/linux-mips64el": "0.25.11", + "@esbuild/linux-ppc64": "0.25.11", + "@esbuild/linux-riscv64": "0.25.11", + "@esbuild/linux-s390x": "0.25.11", + "@esbuild/linux-x64": "0.25.11", + "@esbuild/netbsd-arm64": "0.25.11", + "@esbuild/netbsd-x64": "0.25.11", + "@esbuild/openbsd-arm64": "0.25.11", + "@esbuild/openbsd-x64": "0.25.11", + "@esbuild/openharmony-arm64": "0.25.11", + "@esbuild/sunos-x64": "0.25.11", + "@esbuild/win32-arm64": "0.25.11", + "@esbuild/win32-ia32": "0.25.11", + "@esbuild/win32-x64": "0.25.11" } }, - "node_modules/merge2": { - "version": "1.4.1", + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, "license": "MIT", "engines": { - "node": ">= 8" + "node": ">=6" } }, - "node_modules/micromark": { - "version": "4.0.2", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], + "node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", "license": "MIT", - "dependencies": { - "@types/debug": "^4.0.0", - "debug": "^4.0.0", - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "micromark-core-commonmark": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-combine-extensions": "^2.0.0", - "micromark-util-decode-numeric-character-reference": "^2.0.0", - "micromark-util-encode": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-resolve-all": "^2.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "micromark-util-subtokenize": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/micromark-core-commonmark": { - "version": "2.0.3", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "micromark-factory-destination": "^2.0.0", - "micromark-factory-label": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-factory-title": "^2.0.0", - "micromark-factory-whitespace": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-classify-character": "^2.0.0", - "micromark-util-html-tag-name": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-resolve-all": "^2.0.0", - "micromark-util-subtokenize": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" } }, - "node_modules/micromark-extension-gfm": { + "node_modules/estree-util-is-identifier-name": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz", + "integrity": "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==", "license": "MIT", - "dependencies": { - "micromark-extension-gfm-autolink-literal": "^2.0.0", - "micromark-extension-gfm-footnote": "^2.0.0", - "micromark-extension-gfm-strikethrough": "^2.0.0", - "micromark-extension-gfm-table": "^2.0.0", - "micromark-extension-gfm-tagfilter": "^2.0.0", - "micromark-extension-gfm-task-list-item": "^2.0.0", - "micromark-util-combine-extensions": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/micromark-extension-gfm-autolink-literal": { - "version": "2.1.0", + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, "license": "MIT", "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "@types/estree": "^1.0.0" } }, - "node_modules/micromark-extension-gfm-footnote": { - "version": "2.1.0", + "node_modules/exit-hook": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-2.2.1.tgz", + "integrity": "sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw==", + "dev": true, "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-core-commonmark": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" + "engines": { + "node": ">=6" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/micromark-extension-gfm-strikethrough": { - "version": "2.1.0", + "node_modules/expect-type": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.2.2.tgz", + "integrity": "sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/exsolve": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.7.tgz", + "integrity": "sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw==", + "dev": true, + "license": "MIT" + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "license": "MIT" + }, + "node_modules/extendable-error": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/extendable-error/-/extendable-error-0.1.7.tgz", + "integrity": "sha512-UOiS2in6/Q0FK0R0q6UY9vYpQ21mr/Qn1KOnte7vsACuNJf514WvCCUHSRCPcgjPT2bAhNIJdlE6bVap1GKmeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, "license": "MIT", "dependencies": { - "devlop": "^1.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-classify-character": "^2.0.0", - "micromark-util-resolve-all": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">=8.6.0" } }, - "node_modules/micromark-extension-gfm-table": { - "version": "2.1.1", - "license": "MIT", + "node_modules/fastq": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "dev": true, + "license": "ISC", "dependencies": { - "devlop": "^1.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "reusify": "^1.0.4" } }, - "node_modules/micromark-extension-gfm-tagfilter": { - "version": "2.0.0", + "node_modules/fflate": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", + "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==", + "dev": true, + "license": "MIT" + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, "license": "MIT", "dependencies": { - "micromark-util-types": "^2.0.0" + "to-regex-range": "^5.0.1" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">=8" } }, - "node_modules/micromark-extension-gfm-task-list-item": { - "version": "2.1.0", + "node_modules/filter-obj": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-5.1.0.tgz", + "integrity": "sha512-qWeTREPoT7I0bifpPUXtxkZJ1XJzxWtfoWWkdVGqa+eCr3SHW/Ocp89o8vLvbUuQnadybJpjOKu4V+RwO6sGng==", + "dev": true, "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" + "engines": { + "node": ">=14.16" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/micromark-factory-destination": { - "version": "2.0.1", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, "license": "MIT", "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/micromark-factory-label": { - "version": "2.0.1", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "dev": true, + "license": "ISC" + }, + "node_modules/fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, "license": "MIT", "dependencies": { - "devlop": "^1.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" } }, - "node_modules/micromark-factory-space": { - "version": "2.0.1", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-types": "^2.0.0" + "engines": { + "node": ">=6.9.0" } }, - "node_modules/micromark-factory-title": { - "version": "2.0.1", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], + "node_modules/get-port": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/get-port/-/get-port-7.1.0.tgz", + "integrity": "sha512-QB9NKEeDg3xxVwCCwJQ9+xycaz6pBB6iQ76wiWMl1927n0Kir6alPiP+yuiICLLU4jpMe08dXfpebuQppFA2zw==", + "dev": true, "license": "MIT", - "dependencies": { - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/micromark-factory-whitespace": { - "version": "2.0.1", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], + "node_modules/get-tsconfig": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.0.tgz", + "integrity": "sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==", + "dev": true, "license": "MIT", "dependencies": { - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" } }, - "node_modules/micromark-util-character": { - "version": "2.1.1", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", "dependencies": { - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" } }, - "node_modules/micromark-util-chunked": { - "version": "2.0.1", - "funding": [ - { - "type": "GitHub Sponsors", + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/happy-dom": { + "version": "20.0.10", + "resolved": "https://registry.npmjs.org/happy-dom/-/happy-dom-20.0.10.tgz", + "integrity": "sha512-6umCCHcjQrhP5oXhrHQQvLB0bwb1UzHAHdsXy+FjtKoYjUhmNZsQL8NivwM1vDvNEChJabVrUYxUnp/ZdYmy2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "^20.0.0", + "@types/whatwg-mimetype": "^3.0.2", + "whatwg-mimetype": "^3.0.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/happy-dom/node_modules/@types/node": { + "version": "20.19.24", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.24.tgz", + "integrity": "sha512-FE5u0ezmi6y9OZEzlJfg37mqqf6ZDSF2V/NLjUyGrR9uTZ7Sb9F7bLNZ03S4XVUNRWGA7Ck4c1kK+YnuWjl+DA==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/happy-dom/node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/hast-util-to-jsx-runtime": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.6.tgz", + "integrity": "sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "style-to-js": "^1.0.0", + "unist-util-position": "^5.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-whitespace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", + "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hookable": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz", + "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/html-url-attributes": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/html-url-attributes/-/html-url-attributes-3.0.1.tgz", + "integrity": "sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/human-id": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/human-id/-/human-id-4.1.2.tgz", + "integrity": "sha512-v/J+4Z/1eIJovEBdlV5TYj1IR+ZiohcYGRY+qN/oC9dAfKzVT023N/Bgw37hrKCoVRBvk3bqyzpr2PP5YeTMSg==", + "dev": true, + "license": "MIT", + "bin": { + "human-id": "dist/cli.js" + } + }, + "node_modules/iconv-lite": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.0.tgz", + "integrity": "sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/inline-style-parser": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.4.tgz", + "integrity": "sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q==", + "license": "MIT" + }, + "node_modules/is-alphabetical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", + "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-alphanumerical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", + "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", + "license": "MIT", + "dependencies": { + "is-alphabetical": "^2.0.0", + "is-decimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-arrayish": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.4.tgz", + "integrity": "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-decimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", + "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-hexadecimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", + "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-subdir": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-subdir/-/is-subdir-1.2.0.tgz", + "integrity": "sha512-2AT6j+gXe/1ueqbW6fLZJiIw3F8iXGJtt0yDrZaBhAZEG1raiTxKWU+IPqMCzQAXOUCKdA4UDMgacKH25XG2Cw==", + "dev": true, + "license": "MIT", + "dependencies": { + "better-path-resolve": "1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isbinaryfile": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-5.0.6.tgz", + "integrity": "sha512-I+NmIfBHUl+r2wcDd6JwE9yWje/PIVY/R5/CmV8dXLZd5K+L9X2klAOwfAHNnondLXkbHyTAleQAWonpTJBTtw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 18.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/gjtorikian/" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/jiti": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", + "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "license": "MIT", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/katex": { + "version": "0.16.25", + "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.25.tgz", + "integrity": "sha512-woHRUZ/iF23GBP1dkDQMh1QBad9dmr8/PAwNA54VrSOVYgI12MAcE14TqnDdQOdzyEonGzMepYnqBMYdsoAr8Q==", + "funding": [ + "https://opencollective.com/katex", + "https://github.com/sponsors/katex" + ], + "license": "MIT", + "dependencies": { + "commander": "^8.3.0" + }, + "bin": { + "katex": "cli.js" + } + }, + "node_modules/kleur": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", + "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash.startcase": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.startcase/-/lodash.startcase-4.4.0.tgz", + "integrity": "sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==", + "dev": true, + "license": "MIT" + }, + "node_modules/longest-streak": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", + "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "license": "MIT", + "peer": true, + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/loupe": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.1.tgz", + "integrity": "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/markdown-table": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz", + "integrity": "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/mdast-util-find-and-replace": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.2.tgz", + "integrity": "sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "escape-string-regexp": "^5.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-from-markdown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz", + "integrity": "sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark": "^4.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-3.1.0.tgz", + "integrity": "sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==", + "license": "MIT", + "dependencies": { + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-gfm-autolink-literal": "^2.0.0", + "mdast-util-gfm-footnote": "^2.0.0", + "mdast-util-gfm-strikethrough": "^2.0.0", + "mdast-util-gfm-table": "^2.0.0", + "mdast-util-gfm-task-list-item": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-autolink-literal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-2.0.1.tgz", + "integrity": "sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "ccount": "^2.0.0", + "devlop": "^1.0.0", + "mdast-util-find-and-replace": "^3.0.0", + "micromark-util-character": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-footnote": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.1.0.tgz", + "integrity": "sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-strikethrough": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-2.0.0.tgz", + "integrity": "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-table": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-2.0.0.tgz", + "integrity": "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "markdown-table": "^3.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-task-list-item": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.0.tgz", + "integrity": "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-expression": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.1.tgz", + "integrity": "sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-jsx": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.2.0.tgz", + "integrity": "sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "parse-entities": "^4.0.0", + "stringify-entities": "^4.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdxjs-esm": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz", + "integrity": "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-phrasing": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", + "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-hast": { + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz", + "integrity": "sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@ungap/structured-clone": "^1.0.0", + "devlop": "^1.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "trim-lines": "^3.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-markdown": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz", + "integrity": "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "longest-streak": "^3.0.0", + "mdast-util-phrasing": "^4.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "unist-util-visit": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", + "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromark": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz", + "integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/debug": "^4.0.0", + "debug": "^4.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-core-commonmark": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.3.tgz", + "integrity": "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-destination": "^2.0.0", + "micromark-factory-label": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-factory-title": "^2.0.0", + "micromark-factory-whitespace": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-html-tag-name": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz", + "integrity": "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==", + "license": "MIT", + "dependencies": { + "micromark-extension-gfm-autolink-literal": "^2.0.0", + "micromark-extension-gfm-footnote": "^2.0.0", + "micromark-extension-gfm-strikethrough": "^2.0.0", + "micromark-extension-gfm-table": "^2.0.0", + "micromark-extension-gfm-tagfilter": "^2.0.0", + "micromark-extension-gfm-task-list-item": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-autolink-literal": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz", + "integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==", + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-footnote": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz", + "integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-strikethrough": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.1.0.tgz", + "integrity": "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-table": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.1.tgz", + "integrity": "sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-tagfilter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz", + "integrity": "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==", + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-task-list-item": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.1.0.tgz", + "integrity": "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-factory-destination": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz", + "integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-label": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz", + "integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-title": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz", + "integrity": "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-whitespace": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz", + "integrity": "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-chunked": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz", + "integrity": "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==", + "funding": [ + { + "type": "GitHub Sponsors", "url": "https://github.com/sponsors/unifiedjs" }, { @@ -4856,6 +6138,8 @@ }, "node_modules/micromark-util-classify-character": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz", + "integrity": "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==", "funding": [ { "type": "GitHub Sponsors", @@ -4875,6 +6159,8 @@ }, "node_modules/micromark-util-combine-extensions": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz", + "integrity": "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==", "funding": [ { "type": "GitHub Sponsors", @@ -4893,6 +6179,8 @@ }, "node_modules/micromark-util-decode-numeric-character-reference": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz", + "integrity": "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==", "funding": [ { "type": "GitHub Sponsors", @@ -4910,6 +6198,8 @@ }, "node_modules/micromark-util-decode-string": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.1.tgz", + "integrity": "sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==", "funding": [ { "type": "GitHub Sponsors", @@ -4930,6 +6220,8 @@ }, "node_modules/micromark-util-encode": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", + "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", "funding": [ { "type": "GitHub Sponsors", @@ -4944,6 +6236,8 @@ }, "node_modules/micromark-util-html-tag-name": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz", + "integrity": "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==", "funding": [ { "type": "GitHub Sponsors", @@ -4958,6 +6252,8 @@ }, "node_modules/micromark-util-normalize-identifier": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz", + "integrity": "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==", "funding": [ { "type": "GitHub Sponsors", @@ -4975,6 +6271,8 @@ }, "node_modules/micromark-util-resolve-all": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz", + "integrity": "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==", "funding": [ { "type": "GitHub Sponsors", @@ -4992,6 +6290,8 @@ }, "node_modules/micromark-util-sanitize-uri": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", + "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", "funding": [ { "type": "GitHub Sponsors", @@ -5011,6 +6311,8 @@ }, "node_modules/micromark-util-subtokenize": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz", + "integrity": "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==", "funding": [ { "type": "GitHub Sponsors", @@ -5031,6 +6333,8 @@ }, "node_modules/micromark-util-symbol": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", "funding": [ { "type": "GitHub Sponsors", @@ -5045,6 +6349,8 @@ }, "node_modules/micromark-util-types": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz", + "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", "funding": [ { "type": "GitHub Sponsors", @@ -5059,6 +6365,8 @@ }, "node_modules/micromatch": { "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, "license": "MIT", "dependencies": { @@ -5071,6 +6379,8 @@ }, "node_modules/mime": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", + "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", "dev": true, "license": "MIT", "bin": { @@ -5081,7 +6391,9 @@ } }, "node_modules/miniflare": { - "version": "4.20251008.0", + "version": "4.20251011.1", + "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-4.20251011.1.tgz", + "integrity": "sha512-Qbw1Z8HTYM1adWl6FAtzhrj34/6dPRDPwdYOx21dkae8a/EaxbMzRIPbb4HKVGMVvtqbK1FaRCgDLVLolNzGHg==", "dev": true, "license": "MIT", "dependencies": { @@ -5093,7 +6405,7 @@ "sharp": "^0.33.5", "stoppable": "1.1.0", "undici": "7.14.0", - "workerd": "1.20251008.0", + "workerd": "1.20251011.0", "ws": "8.18.0", "youch": "4.1.0-beta.10", "zod": "3.22.3" @@ -5107,6 +6419,8 @@ }, "node_modules/miniflare/node_modules/ws": { "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", "dev": true, "license": "MIT", "engines": { @@ -5127,6 +6441,8 @@ }, "node_modules/miniflare/node_modules/zod": { "version": "3.22.3", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.3.tgz", + "integrity": "sha512-EjIevzuJRiRPbVH4mGc8nApb/lVLKVpmUhAaR5R5doKGfAnGJ6Gr3CViAVjP+4FWSxCsybeWQdcgCtbX+7oZug==", "dev": true, "license": "MIT", "funding": { @@ -5135,6 +6451,8 @@ }, "node_modules/mlly": { "version": "1.8.0", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.8.0.tgz", + "integrity": "sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==", "dev": true, "license": "MIT", "dependencies": { @@ -5146,6 +6464,8 @@ }, "node_modules/mlly/node_modules/acorn": { "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", "bin": { @@ -5157,6 +6477,8 @@ }, "node_modules/mri": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", + "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", "dev": true, "license": "MIT", "engines": { @@ -5165,6 +6487,8 @@ }, "node_modules/mrmime": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", + "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==", "dev": true, "license": "MIT", "engines": { @@ -5173,10 +6497,14 @@ }, "node_modules/ms": { "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "license": "MIT" }, "node_modules/nanoid": { "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", "dev": true, "funding": [ { @@ -5194,6 +6522,8 @@ }, "node_modules/node-fetch": { "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", "dev": true, "license": "MIT", "dependencies": { @@ -5212,12 +6542,16 @@ } }, "node_modules/node-releases": { - "version": "2.0.23", + "version": "2.0.27", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", + "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", "dev": true, "license": "MIT" }, "node_modules/object-assign": { "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", "license": "MIT", "peer": true, "engines": { @@ -5226,11 +6560,15 @@ }, "node_modules/ohash": { "version": "2.0.11", + "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz", + "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==", "dev": true, "license": "MIT" }, "node_modules/once": { "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dev": true, "license": "ISC", "dependencies": { @@ -5260,11 +6598,15 @@ }, "node_modules/outdent": { "version": "0.5.0", + "resolved": "https://registry.npmjs.org/outdent/-/outdent-0.5.0.tgz", + "integrity": "sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==", "dev": true, "license": "MIT" }, "node_modules/p-filter": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-filter/-/p-filter-2.1.0.tgz", + "integrity": "sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==", "dev": true, "license": "MIT", "dependencies": { @@ -5276,6 +6618,8 @@ }, "node_modules/p-limit": { "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "license": "MIT", "dependencies": { @@ -5290,6 +6634,8 @@ }, "node_modules/p-locate": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, "license": "MIT", "dependencies": { @@ -5301,6 +6647,8 @@ }, "node_modules/p-map": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", "dev": true, "license": "MIT", "engines": { @@ -5309,6 +6657,8 @@ }, "node_modules/p-try": { "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true, "license": "MIT", "engines": { @@ -5317,14 +6667,43 @@ }, "node_modules/package-manager-detector": { "version": "0.2.11", + "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-0.2.11.tgz", + "integrity": "sha512-BEnLolu+yuz22S56CU1SUKq3XC3PkwD5wv4ikR4MfGvnRVcmzXR9DwSlW2fEamyTPyXHomBJRzgapeuBvRNzJQ==", "dev": true, "license": "MIT", "dependencies": { "quansync": "^0.2.7" } }, + "node_modules/parse-entities": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz", + "integrity": "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^2.0.0", + "character-entities-legacy": "^3.0.0", + "character-reference-invalid": "^2.0.0", + "decode-named-character-reference": "^1.0.0", + "is-alphanumerical": "^2.0.0", + "is-decimal": "^2.0.0", + "is-hexadecimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/parse-entities/node_modules/@types/unist": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", + "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", + "license": "MIT" + }, "node_modules/path-exists": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, "license": "MIT", "engines": { @@ -5333,6 +6712,8 @@ }, "node_modules/path-key": { "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, "license": "MIT", "engines": { @@ -5341,11 +6722,15 @@ }, "node_modules/path-to-regexp": { "version": "6.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz", + "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==", "dev": true, "license": "MIT" }, "node_modules/path-type": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "dev": true, "license": "MIT", "engines": { @@ -5354,11 +6739,15 @@ }, "node_modules/pathe": { "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", "dev": true, "license": "MIT" }, "node_modules/pathval": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.1.tgz", + "integrity": "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==", "dev": true, "license": "MIT", "engines": { @@ -5367,11 +6756,15 @@ }, "node_modules/picocolors": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "dev": true, "license": "ISC" }, "node_modules/picomatch": { "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, "license": "MIT", "engines": { @@ -5383,6 +6776,8 @@ }, "node_modules/pify": { "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", "dev": true, "license": "MIT", "engines": { @@ -5391,6 +6786,8 @@ }, "node_modules/pkg-pr-new": { "version": "0.0.60", + "resolved": "https://registry.npmjs.org/pkg-pr-new/-/pkg-pr-new-0.0.60.tgz", + "integrity": "sha512-eblxPNSgv0AO18OrfpHq+YrNHfEqeePWWvlKkPvcHByddGsGDOK25z41C1RDjZ+K8zUHDk5IGN+6n0WZa4T2Pg==", "dev": true, "license": "MIT", "dependencies": { @@ -5409,6 +6806,8 @@ }, "node_modules/pkg-types": { "version": "1.3.1", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz", + "integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==", "dev": true, "license": "MIT", "dependencies": { @@ -5419,6 +6818,8 @@ }, "node_modules/postcss": { "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", "dev": true, "funding": [ { @@ -5446,6 +6847,8 @@ }, "node_modules/prettier": { "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", "dev": true, "license": "MIT", "bin": { @@ -5460,6 +6863,8 @@ }, "node_modules/prop-types": { "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", "license": "MIT", "peer": true, "dependencies": { @@ -5470,6 +6875,8 @@ }, "node_modules/property-information": { "version": "7.1.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz", + "integrity": "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==", "license": "MIT", "funding": { "type": "github", @@ -5478,6 +6885,8 @@ }, "node_modules/quansync": { "version": "0.2.11", + "resolved": "https://registry.npmjs.org/quansync/-/quansync-0.2.11.tgz", + "integrity": "sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==", "dev": true, "funding": [ { @@ -5493,6 +6902,8 @@ }, "node_modules/query-registry": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/query-registry/-/query-registry-3.0.1.tgz", + "integrity": "sha512-M9RxRITi2mHMVPU5zysNjctUT8bAPx6ltEXo/ir9+qmiM47Y7f0Ir3+OxUO5OjYAWdicBQRew7RtHtqUXydqlg==", "dev": true, "license": "MIT", "dependencies": { @@ -5509,6 +6920,8 @@ }, "node_modules/query-string": { "version": "9.3.1", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-9.3.1.tgz", + "integrity": "sha512-5fBfMOcDi5SA9qj5jZhWAcTtDfKF5WFdd2uD9nVNlbxVv1baq65aALy6qofpNEGELHvisjjasxQp7BlM9gvMzw==", "dev": true, "license": "MIT", "dependencies": { @@ -5525,6 +6938,8 @@ }, "node_modules/queue-microtask": { "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", "dev": true, "funding": [ { @@ -5544,6 +6959,8 @@ }, "node_modules/quick-lru": { "version": "7.3.0", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-7.3.0.tgz", + "integrity": "sha512-k9lSsjl36EJdK7I06v7APZCbyGT2vMTsYSRX1Q2nbYmnkBqgUhRkAuzH08Ciotteu/PLJmIF2+tti7o3C/ts2g==", "dev": true, "license": "MIT", "engines": { @@ -5555,6 +6972,8 @@ }, "node_modules/react": { "version": "19.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.0.tgz", + "integrity": "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==", "license": "MIT", "engines": { "node": ">=0.10.0" @@ -5562,6 +6981,8 @@ }, "node_modules/react-dom": { "version": "19.2.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.0.tgz", + "integrity": "sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ==", "dev": true, "license": "MIT", "dependencies": { @@ -5573,11 +6994,15 @@ }, "node_modules/react-is": { "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", "license": "MIT", "peer": true }, "node_modules/react-katex": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/react-katex/-/react-katex-3.1.0.tgz", + "integrity": "sha512-At9uLOkC75gwn2N+ZXc5HD8TlATsB+3Hkp9OGs6uA8tM3dwZ3Wljn74Bk3JyHFPgSnesY/EMrIAB1WJwqZqejA==", "license": "MIT", "dependencies": { "katex": "^0.16.0" @@ -5589,6 +7014,8 @@ }, "node_modules/react-markdown": { "version": "10.1.0", + "resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-10.1.0.tgz", + "integrity": "sha512-qKxVopLT/TyA6BX3Ue5NwabOsAzm0Q7kAPwq6L+wWDwisYs7R8vZ0nRXqq6rkueboxpkjvLGU9fWifiX/ZZFxQ==", "license": "MIT", "dependencies": { "@types/hast": "^3.0.0", @@ -5614,6 +7041,8 @@ }, "node_modules/react-refresh": { "version": "0.17.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz", + "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==", "dev": true, "license": "MIT", "engines": { @@ -5622,6 +7051,8 @@ }, "node_modules/read-yaml-file": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-yaml-file/-/read-yaml-file-1.1.0.tgz", + "integrity": "sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA==", "dev": true, "license": "MIT", "dependencies": { @@ -5636,6 +7067,8 @@ }, "node_modules/readdirp": { "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", "dev": true, "license": "MIT", "engines": { @@ -5648,6 +7081,8 @@ }, "node_modules/remark-gfm": { "version": "4.0.1", + "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.1.tgz", + "integrity": "sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==", "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0", @@ -5664,6 +7099,8 @@ }, "node_modules/remark-parse": { "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", + "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==", "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0", @@ -5678,6 +7115,8 @@ }, "node_modules/remark-rehype": { "version": "11.1.2", + "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.2.tgz", + "integrity": "sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==", "license": "MIT", "dependencies": { "@types/hast": "^3.0.0", @@ -5693,6 +7132,8 @@ }, "node_modules/remark-stringify": { "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-11.0.0.tgz", + "integrity": "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==", "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0", @@ -5706,6 +7147,8 @@ }, "node_modules/resolve-from": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, "license": "MIT", "engines": { @@ -5714,6 +7157,8 @@ }, "node_modules/resolve-pkg-maps": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", "dev": true, "license": "MIT", "funding": { @@ -5722,6 +7167,8 @@ }, "node_modules/reusify": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", "dev": true, "license": "MIT", "engines": { @@ -5825,7 +7272,9 @@ "license": "MIT" }, "node_modules/rollup": { - "version": "4.52.4", + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.52.5.tgz", + "integrity": "sha512-3GuObel8h7Kqdjt0gxkEzaifHTqLVW56Y/bjN7PSQtkKr0w3V/QYSdt6QWYtd7A1xUtYQigtdUfgj1RvWVtorw==", "dev": true, "license": "MIT", "dependencies": { @@ -5839,33 +7288,35 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.52.4", - "@rollup/rollup-android-arm64": "4.52.4", - "@rollup/rollup-darwin-arm64": "4.52.4", - "@rollup/rollup-darwin-x64": "4.52.4", - "@rollup/rollup-freebsd-arm64": "4.52.4", - "@rollup/rollup-freebsd-x64": "4.52.4", - "@rollup/rollup-linux-arm-gnueabihf": "4.52.4", - "@rollup/rollup-linux-arm-musleabihf": "4.52.4", - "@rollup/rollup-linux-arm64-gnu": "4.52.4", - "@rollup/rollup-linux-arm64-musl": "4.52.4", - "@rollup/rollup-linux-loong64-gnu": "4.52.4", - "@rollup/rollup-linux-ppc64-gnu": "4.52.4", - "@rollup/rollup-linux-riscv64-gnu": "4.52.4", - "@rollup/rollup-linux-riscv64-musl": "4.52.4", - "@rollup/rollup-linux-s390x-gnu": "4.52.4", - "@rollup/rollup-linux-x64-gnu": "4.52.4", - "@rollup/rollup-linux-x64-musl": "4.52.4", - "@rollup/rollup-openharmony-arm64": "4.52.4", - "@rollup/rollup-win32-arm64-msvc": "4.52.4", - "@rollup/rollup-win32-ia32-msvc": "4.52.4", - "@rollup/rollup-win32-x64-gnu": "4.52.4", - "@rollup/rollup-win32-x64-msvc": "4.52.4", + "@rollup/rollup-android-arm-eabi": "4.52.5", + "@rollup/rollup-android-arm64": "4.52.5", + "@rollup/rollup-darwin-arm64": "4.52.5", + "@rollup/rollup-darwin-x64": "4.52.5", + "@rollup/rollup-freebsd-arm64": "4.52.5", + "@rollup/rollup-freebsd-x64": "4.52.5", + "@rollup/rollup-linux-arm-gnueabihf": "4.52.5", + "@rollup/rollup-linux-arm-musleabihf": "4.52.5", + "@rollup/rollup-linux-arm64-gnu": "4.52.5", + "@rollup/rollup-linux-arm64-musl": "4.52.5", + "@rollup/rollup-linux-loong64-gnu": "4.52.5", + "@rollup/rollup-linux-ppc64-gnu": "4.52.5", + "@rollup/rollup-linux-riscv64-gnu": "4.52.5", + "@rollup/rollup-linux-riscv64-musl": "4.52.5", + "@rollup/rollup-linux-s390x-gnu": "4.52.5", + "@rollup/rollup-linux-x64-gnu": "4.52.5", + "@rollup/rollup-linux-x64-musl": "4.52.5", + "@rollup/rollup-openharmony-arm64": "4.52.5", + "@rollup/rollup-win32-arm64-msvc": "4.52.5", + "@rollup/rollup-win32-ia32-msvc": "4.52.5", + "@rollup/rollup-win32-x64-gnu": "4.52.5", + "@rollup/rollup-win32-x64-msvc": "4.52.5", "fsevents": "~2.3.2" } }, "node_modules/run-parallel": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", "dev": true, "funding": [ { @@ -5888,11 +7339,15 @@ }, "node_modules/safer-buffer": { "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true, "license": "MIT" }, "node_modules/scheduler": { "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", "dev": true, "license": "MIT" }, @@ -5911,6 +7366,8 @@ }, "node_modules/sharp": { "version": "0.33.5", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz", + "integrity": "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==", "dev": true, "hasInstallScript": true, "license": "Apache-2.0", @@ -5949,6 +7406,8 @@ }, "node_modules/shebang-command": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, "license": "MIT", "dependencies": { @@ -5960,6 +7419,8 @@ }, "node_modules/shebang-regex": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, "license": "MIT", "engines": { @@ -5968,11 +7429,15 @@ }, "node_modules/siginfo": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", "dev": true, "license": "ISC" }, "node_modules/signal-exit": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, "license": "ISC", "engines": { @@ -5984,6 +7449,8 @@ }, "node_modules/simple-swizzle": { "version": "0.2.4", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.4.tgz", + "integrity": "sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw==", "dev": true, "license": "MIT", "dependencies": { @@ -5992,6 +7459,8 @@ }, "node_modules/sirv": { "version": "3.0.2", + "resolved": "https://registry.npmjs.org/sirv/-/sirv-3.0.2.tgz", + "integrity": "sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==", "dev": true, "license": "MIT", "dependencies": { @@ -6005,6 +7474,8 @@ }, "node_modules/slash": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true, "license": "MIT", "engines": { @@ -6013,6 +7484,8 @@ }, "node_modules/source-map-js": { "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -6021,6 +7494,8 @@ }, "node_modules/space-separated-tokens": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", "license": "MIT", "funding": { "type": "github", @@ -6029,6 +7504,8 @@ }, "node_modules/spawndamnit": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spawndamnit/-/spawndamnit-3.0.1.tgz", + "integrity": "sha512-MmnduQUuHCoFckZoWnXsTg7JaiLBJrKFj9UI2MbRPGaJeVpsLcVBu6P/IGZovziM/YBsellCmsprgNA+w0CzVg==", "dev": true, "license": "SEE LICENSE IN LICENSE", "dependencies": { @@ -6038,6 +7515,8 @@ }, "node_modules/split-on-first": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-3.0.0.tgz", + "integrity": "sha512-qxQJTx2ryR0Dw0ITYyekNQWpz6f8dGd7vffGNflQQ3Iqj9NJ6qiZ7ELpZsJ/QBhIVAiDfXdag3+Gp8RvWa62AA==", "dev": true, "license": "MIT", "engines": { @@ -6049,21 +7528,29 @@ }, "node_modules/sprintf-js": { "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", "dev": true, "license": "BSD-3-Clause" }, "node_modules/stackback": { "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", "dev": true, "license": "MIT" }, "node_modules/std-env": { - "version": "3.9.0", + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", + "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", "dev": true, "license": "MIT" }, "node_modules/stoppable": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stoppable/-/stoppable-1.1.0.tgz", + "integrity": "sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==", "dev": true, "license": "MIT", "engines": { @@ -6073,6 +7560,8 @@ }, "node_modules/string-argv": { "version": "0.3.2", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", + "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", "dev": true, "license": "MIT", "engines": { @@ -6081,6 +7570,8 @@ }, "node_modules/stringify-entities": { "version": "4.0.4", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", + "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", "license": "MIT", "dependencies": { "character-entities-html4": "^2.0.0", @@ -6091,16 +7582,10 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/stringify-entities/node_modules/character-entities-legacy": { - "version": "3.0.0", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, "node_modules/strip-ansi": { "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "license": "MIT", "dependencies": { @@ -6112,6 +7597,8 @@ }, "node_modules/strip-bom": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", "dev": true, "license": "MIT", "engines": { @@ -6120,6 +7607,8 @@ }, "node_modules/strip-literal": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-3.1.0.tgz", + "integrity": "sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==", "dev": true, "license": "MIT", "dependencies": { @@ -6131,18 +7620,24 @@ }, "node_modules/strip-literal/node_modules/js-tokens": { "version": "9.0.1", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.1.tgz", + "integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==", "dev": true, "license": "MIT" }, "node_modules/style-to-js": { - "version": "1.1.17", + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.18.tgz", + "integrity": "sha512-JFPn62D4kJaPTnhFUI244MThx+FEGbi+9dw1b9yBBQ+1CZpV7QAT8kUtJ7b7EUNdHajjF/0x8fT+16oLJoojLg==", "license": "MIT", "dependencies": { - "style-to-object": "1.0.9" + "style-to-object": "1.0.11" } }, "node_modules/style-to-object": { - "version": "1.0.9", + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.11.tgz", + "integrity": "sha512-5A560JmXr7wDyGLK12Nq/EYS38VkGlglVzkis1JEdbGWSnbQIEhZzTJhzURXN5/8WwwFCs/f/VVcmkTppbXLow==", "license": "MIT", "dependencies": { "inline-style-parser": "0.2.4" @@ -6150,6 +7645,8 @@ }, "node_modules/supports-color": { "version": "10.2.2", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-10.2.2.tgz", + "integrity": "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==", "dev": true, "license": "MIT", "engines": { @@ -6177,6 +7674,8 @@ }, "node_modules/term-size": { "version": "2.2.1", + "resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.1.tgz", + "integrity": "sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==", "dev": true, "license": "MIT", "engines": { @@ -6188,16 +7687,22 @@ }, "node_modules/tinybench": { "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", "dev": true, "license": "MIT" }, "node_modules/tinyexec": { - "version": "0.3.2", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.1.tgz", + "integrity": "sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw==", "dev": true, "license": "MIT" }, "node_modules/tinyglobby": { "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6213,6 +7718,8 @@ }, "node_modules/tinyglobby/node_modules/fdir": { "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", "dev": true, "license": "MIT", "engines": { @@ -6229,6 +7736,8 @@ }, "node_modules/tinyglobby/node_modules/picomatch": { "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", "engines": { @@ -6240,6 +7749,8 @@ }, "node_modules/tinypool": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.1.tgz", + "integrity": "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==", "dev": true, "license": "MIT", "engines": { @@ -6248,6 +7759,8 @@ }, "node_modules/tinyrainbow": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-2.0.0.tgz", + "integrity": "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==", "dev": true, "license": "MIT", "engines": { @@ -6256,6 +7769,8 @@ }, "node_modules/tinyspy": { "version": "4.0.4", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-4.0.4.tgz", + "integrity": "sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==", "dev": true, "license": "MIT", "engines": { @@ -6264,6 +7779,8 @@ }, "node_modules/to-regex-range": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6275,6 +7792,8 @@ }, "node_modules/totalist": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", + "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", "dev": true, "license": "MIT", "engines": { @@ -6283,11 +7802,15 @@ }, "node_modules/tr46": { "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", "dev": true, "license": "MIT" }, "node_modules/tree-kill": { "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", "dev": true, "license": "MIT", "bin": { @@ -6296,6 +7819,8 @@ }, "node_modules/trim-lines": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", + "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", "license": "MIT", "funding": { "type": "github", @@ -6304,6 +7829,8 @@ }, "node_modules/trough": { "version": "2.2.0", + "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", + "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==", "license": "MIT", "funding": { "type": "github", @@ -6367,13 +7894,6 @@ } } }, - "node_modules/tsdown/node_modules/tinyexec": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.1.tgz", - "integrity": "sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw==", - "dev": true, - "license": "MIT" - }, "node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", @@ -6384,6 +7904,8 @@ }, "node_modules/tsx": { "version": "4.20.6", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.20.6.tgz", + "integrity": "sha512-ytQKuwgmrrkDTFP4LjR0ToE2nqgy886GpvRSpU0JAnrdBYppuY5rLkRUYPU1yCryb24SsKBTL/hlDQAEFVwtZg==", "dev": true, "license": "MIT", "dependencies": { @@ -6402,6 +7924,8 @@ }, "node_modules/tunnel": { "version": "0.0.6", + "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", + "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", "dev": true, "license": "MIT", "engines": { @@ -6410,6 +7934,8 @@ }, "node_modules/turbo": { "version": "2.5.8", + "resolved": "https://registry.npmjs.org/turbo/-/turbo-2.5.8.tgz", + "integrity": "sha512-5c9Fdsr9qfpT3hA0EyYSFRZj1dVVsb6KIWubA9JBYZ/9ZEAijgUEae0BBR/Xl/wekt4w65/lYLTFaP3JmwSO8w==", "dev": true, "license": "MIT", "bin": { @@ -6424,8 +7950,24 @@ "turbo-windows-arm64": "2.5.8" } }, + "node_modules/turbo-darwin-64": { + "version": "2.5.8", + "resolved": "https://registry.npmjs.org/turbo-darwin-64/-/turbo-darwin-64-2.5.8.tgz", + "integrity": "sha512-Dh5bCACiHO8rUXZLpKw+m3FiHtAp2CkanSyJre+SInEvEr5kIxjGvCK/8MFX8SFRjQuhjtvpIvYYZJB4AGCxNQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, "node_modules/turbo-darwin-arm64": { "version": "2.5.8", + "resolved": "https://registry.npmjs.org/turbo-darwin-arm64/-/turbo-darwin-arm64-2.5.8.tgz", + "integrity": "sha512-f1H/tQC9px7+hmXn6Kx/w8Jd/FneIUnvLlcI/7RGHunxfOkKJKvsoiNzySkoHQ8uq1pJnhJ0xNGTlYM48ZaJOQ==", "cpu": [ "arm64" ], @@ -6436,8 +7978,66 @@ "darwin" ] }, + "node_modules/turbo-linux-64": { + "version": "2.5.8", + "resolved": "https://registry.npmjs.org/turbo-linux-64/-/turbo-linux-64-2.5.8.tgz", + "integrity": "sha512-hMyvc7w7yadBlZBGl/bnR6O+dJTx3XkTeyTTH4zEjERO6ChEs0SrN8jTFj1lueNXKIHh1SnALmy6VctKMGnWfw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/turbo-linux-arm64": { + "version": "2.5.8", + "resolved": "https://registry.npmjs.org/turbo-linux-arm64/-/turbo-linux-arm64-2.5.8.tgz", + "integrity": "sha512-LQELGa7bAqV2f+3rTMRPnj5G/OHAe2U+0N9BwsZvfMvHSUbsQ3bBMWdSQaYNicok7wOZcHjz2TkESn1hYK6xIQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/turbo-windows-64": { + "version": "2.5.8", + "resolved": "https://registry.npmjs.org/turbo-windows-64/-/turbo-windows-64-2.5.8.tgz", + "integrity": "sha512-3YdcaW34TrN1AWwqgYL9gUqmZsMT4T7g8Y5Azz+uwwEJW+4sgcJkIi9pYFyU4ZBSjBvkfuPZkGgfStir5BBDJQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/turbo-windows-arm64": { + "version": "2.5.8", + "resolved": "https://registry.npmjs.org/turbo-windows-arm64/-/turbo-windows-arm64-2.5.8.tgz", + "integrity": "sha512-eFC5XzLmgXJfnAK3UMTmVECCwuBcORrWdewoiXBnUm934DY6QN8YowC/srhNnROMpaKaqNeRpoB5FxCww3eteQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/type-detect": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz", + "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==", "dev": true, "license": "MIT", "engines": { @@ -6446,6 +8046,8 @@ }, "node_modules/typescript": { "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", "bin": { @@ -6458,6 +8060,8 @@ }, "node_modules/ufo": { "version": "1.6.1", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.1.tgz", + "integrity": "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==", "dev": true, "license": "MIT" }, @@ -6473,634 +8077,1004 @@ "jiti": "^2.5.1", "quansync": "^0.2.11" }, - "funding": { - "url": "https://github.com/sponsors/antfu" + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/undici": { + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.14.0.tgz", + "integrity": "sha512-Vqs8HTzjpQXZeXdpsfChQTlafcMQaaIwnGwLam1wudSSjlJeQ3bw1j+TLPePgrCnCpUXx7Ba5Pdpf5OBih62NQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.18.1" + } + }, + "node_modules/undici-types": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", + "dev": true, + "license": "MIT" + }, + "node_modules/unenv": { + "version": "2.0.0-rc.21", + "resolved": "https://registry.npmjs.org/unenv/-/unenv-2.0.0-rc.21.tgz", + "integrity": "sha512-Wj7/AMtE9MRnAXa6Su3Lk0LNCfqDYgfwVjwRFVum9U7wsto1imuHqk4kTm7Jni+5A0Hn7dttL6O/zjvUvoo+8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "defu": "^6.1.4", + "exsolve": "^1.0.7", + "ohash": "^2.0.11", + "pathe": "^2.0.3", + "ufo": "^1.6.1" + } + }, + "node_modules/unified": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", + "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "bail": "^2.0.0", + "devlop": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^4.0.0", + "trough": "^2.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-is": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", + "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", + "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", + "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/universal-user-agent": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.1.tgz", + "integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/unrun": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/unrun/-/unrun-0.2.1.tgz", + "integrity": "sha512-1HpwmlCKrAOP3jPxFisPR0sYpPuiNtyYKJbmKu9iugIdvCte3DH1uJ1p1DBxUWkxW2pjvkUguJoK9aduK8ak3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@oxc-project/runtime": "^0.95.0", + "rolldown": "1.0.0-beta.45", + "synckit": "^0.11.11" + }, + "bin": { + "unrun": "dist/cli.js" + }, + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "url": "https://github.com/sponsors/Gugustinette" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.4.tgz", + "integrity": "sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" } }, - "node_modules/undici": { - "version": "7.14.0", + "node_modules/url-join": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-5.0.0.tgz", + "integrity": "sha512-n2huDr9h9yzd6exQVnH/jU5mr+Pfx08LRXXZhkLLetAMESRj+anQsTAh940iMrIetKAmry9coFuZQ2jY8/p3WA==", "dev": true, "license": "MIT", "engines": { - "node": ">=20.18.1" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" } }, - "node_modules/undici-types": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", - "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", - "dev": true, - "license": "MIT" - }, - "node_modules/unenv": { - "version": "2.0.0-rc.21", + "node_modules/validate-npm-package-name": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz", + "integrity": "sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==", "dev": true, - "license": "MIT", - "dependencies": { - "defu": "^6.1.4", - "exsolve": "^1.0.7", - "ohash": "^2.0.11", - "pathe": "^2.0.3", - "ufo": "^1.6.1" + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/unified": { - "version": "11.0.5", + "node_modules/vfile": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", "license": "MIT", "dependencies": { "@types/unist": "^3.0.0", - "bail": "^2.0.0", - "devlop": "^1.0.0", - "extend": "^3.0.0", - "is-plain-obj": "^4.0.0", - "trough": "^2.0.0", - "vfile": "^6.0.0" + "vfile-message": "^4.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/unist-util-is": { - "version": "6.0.1", + "node_modules/vfile-message": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz", + "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", "license": "MIT", "dependencies": { - "@types/unist": "^3.0.0" + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/unist-util-position": { - "version": "5.0.0", + "node_modules/vite": { + "version": "7.1.12", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.1.12.tgz", + "integrity": "sha512-ZWyE8YXEXqJrrSLvYgrRP7p62OziLW7xI5HYGWFzOvupfAlrLvURSzv/FyGyy0eidogEM3ujU+kUG1zuHgb6Ug==", + "dev": true, "license": "MIT", "dependencies": { - "@types/unist": "^3.0.0" + "esbuild": "^0.25.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "lightningcss": "^1.21.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } } }, - "node_modules/unist-util-stringify-position": { - "version": "4.0.0", + "node_modules/vite-node": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.2.4.tgz", + "integrity": "sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==", + "dev": true, "license": "MIT", "dependencies": { - "@types/unist": "^3.0.0" + "cac": "^6.7.14", + "debug": "^4.4.1", + "es-module-lexer": "^1.7.0", + "pathe": "^2.0.3", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" + }, + "bin": { + "vite-node": "vite-node.mjs" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://opencollective.com/vitest" } }, - "node_modules/unist-util-visit": { - "version": "5.0.0", + "node_modules/vite/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0", - "unist-util-visit-parents": "^6.0.0" + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/vite/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/unist-util-visit-parents": { - "version": "6.0.2", + "node_modules/vitest": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.2.4.tgz", + "integrity": "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==", + "dev": true, "license": "MIT", "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0" + "@types/chai": "^5.2.2", + "@vitest/expect": "3.2.4", + "@vitest/mocker": "3.2.4", + "@vitest/pretty-format": "^3.2.4", + "@vitest/runner": "3.2.4", + "@vitest/snapshot": "3.2.4", + "@vitest/spy": "3.2.4", + "@vitest/utils": "3.2.4", + "chai": "^5.2.0", + "debug": "^4.4.1", + "expect-type": "^1.2.1", + "magic-string": "^0.30.17", + "pathe": "^2.0.3", + "picomatch": "^4.0.2", + "std-env": "^3.9.0", + "tinybench": "^2.9.0", + "tinyexec": "^0.3.2", + "tinyglobby": "^0.2.14", + "tinypool": "^1.1.1", + "tinyrainbow": "^2.0.0", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0", + "vite-node": "3.2.4", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@types/debug": "^4.1.12", + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "@vitest/browser": "3.2.4", + "@vitest/ui": "3.2.4", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@types/debug": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } + } + }, + "node_modules/vitest/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/universal-user-agent": { - "version": "6.0.1", + "node_modules/vitest/node_modules/tinyexec": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", + "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", "dev": true, - "license": "ISC" + "license": "MIT" }, - "node_modules/universalify": { - "version": "0.1.2", + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/whatwg-mimetype": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", + "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", "dev": true, "license": "MIT", "engines": { - "node": ">= 4.0.0" + "node": ">=12" } }, - "node_modules/unrun": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/unrun/-/unrun-0.2.1.tgz", - "integrity": "sha512-1HpwmlCKrAOP3jPxFisPR0sYpPuiNtyYKJbmKu9iugIdvCte3DH1uJ1p1DBxUWkxW2pjvkUguJoK9aduK8ak3Q==", + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", "dev": true, "license": "MIT", "dependencies": { - "@oxc-project/runtime": "^0.95.0", - "rolldown": "1.0.0-beta.45", - "synckit": "^0.11.11" + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" }, "bin": { - "unrun": "dist/cli.js" + "node-which": "bin/node-which" }, "engines": { - "node": ">=20.19.0" - }, - "funding": { - "url": "https://github.com/sponsors/Gugustinette" + "node": ">= 8" } }, - "node_modules/update-browserslist-db": { - "version": "1.1.3", + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], "license": "MIT", "dependencies": { - "escalade": "^3.2.0", - "picocolors": "^1.1.1" + "siginfo": "^2.0.0", + "stackback": "0.0.2" }, "bin": { - "update-browserslist-db": "cli.js" + "why-is-node-running": "cli.js" }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/url-join": { - "version": "5.0.0", - "dev": true, - "license": "MIT", "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=8" } }, - "node_modules/validate-npm-package-name": { - "version": "5.0.1", + "node_modules/workerd": { + "version": "1.20251011.0", + "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20251011.0.tgz", + "integrity": "sha512-Dq35TLPEJAw7BuYQMkN3p9rge34zWMU2Gnd4DSJFeVqld4+DAO2aPG7+We2dNIAyM97S8Y9BmHulbQ00E0HC7Q==", "dev": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/vfile": { - "version": "6.0.3", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "vfile-message": "^4.0.0" + "hasInstallScript": true, + "license": "Apache-2.0", + "bin": { + "workerd": "bin/workerd" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/vfile-message": { - "version": "4.0.3", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-stringify-position": "^4.0.0" + "engines": { + "node": ">=16" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "optionalDependencies": { + "@cloudflare/workerd-darwin-64": "1.20251011.0", + "@cloudflare/workerd-darwin-arm64": "1.20251011.0", + "@cloudflare/workerd-linux-64": "1.20251011.0", + "@cloudflare/workerd-linux-arm64": "1.20251011.0", + "@cloudflare/workerd-windows-64": "1.20251011.0" } }, - "node_modules/vite": { - "version": "7.1.11", + "node_modules/wrangler": { + "version": "4.45.2", + "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-4.45.2.tgz", + "integrity": "sha512-+G24gD+Rh7iBus5QiVBhNgSLzyAiyuZSm+3Ih5li8+PEA+gosAXfDSZlNZwsVmXd8VJTjq+BR4vhUiruQRWgTw==", "dev": true, - "license": "MIT", + "license": "MIT OR Apache-2.0", "dependencies": { - "esbuild": "^0.25.0", - "fdir": "^6.5.0", - "picomatch": "^4.0.3", - "postcss": "^8.5.6", - "rollup": "^4.43.0", - "tinyglobby": "^0.2.15" + "@cloudflare/kv-asset-handler": "0.4.0", + "@cloudflare/unenv-preset": "2.7.8", + "blake3-wasm": "2.1.5", + "esbuild": "0.25.4", + "miniflare": "4.20251011.1", + "path-to-regexp": "6.3.0", + "unenv": "2.0.0-rc.21", + "workerd": "1.20251011.0" }, "bin": { - "vite": "bin/vite.js" + "wrangler": "bin/wrangler.js", + "wrangler2": "bin/wrangler.js" }, "engines": { - "node": "^20.19.0 || >=22.12.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" + "node": ">=18.0.0" }, "optionalDependencies": { - "fsevents": "~2.3.3" + "fsevents": "~2.3.2" }, "peerDependencies": { - "@types/node": "^20.19.0 || >=22.12.0", - "jiti": ">=1.21.0", - "less": "^4.0.0", - "lightningcss": "^1.21.0", - "sass": "^1.70.0", - "sass-embedded": "^1.70.0", - "stylus": ">=0.54.8", - "sugarss": "^5.0.0", - "terser": "^5.16.0", - "tsx": "^4.8.1", - "yaml": "^2.4.2" + "@cloudflare/workers-types": "^4.20251011.0" }, "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "jiti": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - }, - "tsx": { - "optional": true - }, - "yaml": { + "@cloudflare/workers-types": { "optional": true } } }, - "node_modules/vite-node": { - "version": "3.2.4", + "node_modules/wrangler/node_modules/@esbuild/aix-ppc64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.4.tgz", + "integrity": "sha512-1VCICWypeQKhVbE9oW/sJaAmjLxhVqacdkvPLEjwlttjfwENRSClS8EjBz0KzRyFSCPDIkuXW34Je/vk7zdB7Q==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/android-arm": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.4.tgz", + "integrity": "sha512-QNdQEps7DfFwE3hXiU4BZeOV68HHzYwGd0Nthhd3uCkkEKK7/R6MTgM0P7H7FAs5pU/DIWsviMmEGxEoxIZ+ZQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/android-arm64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.4.tgz", + "integrity": "sha512-bBy69pgfhMGtCnwpC/x5QhfxAz/cBgQ9enbtwjf6V9lnPI/hMyT9iWpR1arm0l3kttTr4L0KSLpKmLp/ilKS9A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/android-x64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.4.tgz", + "integrity": "sha512-TVhdVtQIFuVpIIR282btcGC2oGQoSfZfmBdTip2anCaVYcqWlZXGcdcKIUklfX2wj0JklNYgz39OBqh2cqXvcQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/darwin-arm64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.4.tgz", + "integrity": "sha512-Y1giCfM4nlHDWEfSckMzeWNdQS31BQGs9/rouw6Ub91tkK79aIMTH3q9xHvzH8d0wDru5Ci0kWB8b3up/nl16g==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "cac": "^6.7.14", - "debug": "^4.4.1", - "es-module-lexer": "^1.7.0", - "pathe": "^2.0.3", - "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" - }, - "bin": { - "vite-node": "vite-node.mjs" - }, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": "^18.0.0 || ^20.0.0 || >=22.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" + "node": ">=18" } }, - "node_modules/vite/node_modules/fdir": { - "version": "6.5.0", + "node_modules/wrangler/node_modules/@esbuild/darwin-x64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.4.tgz", + "integrity": "sha512-CJsry8ZGM5VFVeyUYB3cdKpd/H69PYez4eJh1W/t38vzutdjEjtP7hB6eLKBoOdxcAlCtEYHzQ/PJ/oU9I4u0A==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } + "node": ">=18" } }, - "node_modules/vite/node_modules/picomatch": { - "version": "4.0.3", + "node_modules/wrangler/node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.4.tgz", + "integrity": "sha512-yYq+39NlTRzU2XmoPW4l5Ifpl9fqSk0nAJYM/V/WUGPEFfek1epLHJIkTQM6bBs1swApjO5nWgvr843g6TjxuQ==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "node": ">=18" } }, - "node_modules/vitest": { - "version": "3.2.4", + "node_modules/wrangler/node_modules/@esbuild/freebsd-x64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.4.tgz", + "integrity": "sha512-0FgvOJ6UUMflsHSPLzdfDnnBBVoCDtBTVyn/MrWloUNvq/5SFmh13l3dvgRPkDihRxb77Y17MbqbCAa2strMQQ==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@types/chai": "^5.2.2", - "@vitest/expect": "3.2.4", - "@vitest/mocker": "3.2.4", - "@vitest/pretty-format": "^3.2.4", - "@vitest/runner": "3.2.4", - "@vitest/snapshot": "3.2.4", - "@vitest/spy": "3.2.4", - "@vitest/utils": "3.2.4", - "chai": "^5.2.0", - "debug": "^4.4.1", - "expect-type": "^1.2.1", - "magic-string": "^0.30.17", - "pathe": "^2.0.3", - "picomatch": "^4.0.2", - "std-env": "^3.9.0", - "tinybench": "^2.9.0", - "tinyexec": "^0.3.2", - "tinyglobby": "^0.2.14", - "tinypool": "^1.1.1", - "tinyrainbow": "^2.0.0", - "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0", - "vite-node": "3.2.4", - "why-is-node-running": "^2.3.0" - }, - "bin": { - "vitest": "vitest.mjs" - }, + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": "^18.0.0 || ^20.0.0 || >=22.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "@edge-runtime/vm": "*", - "@types/debug": "^4.1.12", - "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", - "@vitest/browser": "3.2.4", - "@vitest/ui": "3.2.4", - "happy-dom": "*", - "jsdom": "*" - }, - "peerDependenciesMeta": { - "@edge-runtime/vm": { - "optional": true - }, - "@types/debug": { - "optional": true - }, - "@types/node": { - "optional": true - }, - "@vitest/browser": { - "optional": true - }, - "@vitest/ui": { - "optional": true - }, - "happy-dom": { - "optional": true - }, - "jsdom": { - "optional": true - } + "node": ">=18" } }, - "node_modules/vitest/node_modules/picomatch": { - "version": "4.0.3", + "node_modules/wrangler/node_modules/@esbuild/linux-arm": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.4.tgz", + "integrity": "sha512-kro4c0P85GMfFYqW4TWOpvmF8rFShbWGnrLqlzp4X1TNWjRY3JMYUfDCtOxPKOIY8B0WC8HN51hGP4I4hz4AaQ==", + "cpu": [ + "arm" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "node": ">=18" } }, - "node_modules/webidl-conversions": { - "version": "3.0.1", + "node_modules/wrangler/node_modules/@esbuild/linux-arm64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.4.tgz", + "integrity": "sha512-+89UsQTfXdmjIvZS6nUnOOLoXnkUTB9hR5QAeLrQdzOSWZvNSAXAtcRDHWtqAUtAmv7ZM1WPOOeSxDzzzMogiQ==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "BSD-2-Clause" + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } }, - "node_modules/whatwg-mimetype": { - "version": "3.0.0", + "node_modules/wrangler/node_modules/@esbuild/linux-ia32": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.4.tgz", + "integrity": "sha512-yTEjoapy8UP3rv8dB0ip3AfMpRbyhSN3+hY8mo/i4QXFeDxmiYbEKp3ZRjBKcOP862Ua4b1PDfwlvbuwY7hIGQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/linux-loong64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.4.tgz", + "integrity": "sha512-NeqqYkrcGzFwi6CGRGNMOjWGGSYOpqwCjS9fvaUlX5s3zwOtn1qwg1s2iE2svBe4Q/YOG1q6875lcAoQK/F4VA==", + "cpu": [ + "loong64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/whatwg-url": { - "version": "5.0.0", + "node_modules/wrangler/node_modules/@esbuild/linux-mips64el": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.4.tgz", + "integrity": "sha512-IcvTlF9dtLrfL/M8WgNI/qJYBENP3ekgsHbYUIzEzq5XJzzVEV/fXY9WFPfEEXmu3ck2qJP8LG/p3Q8f7Zc2Xg==", + "cpu": [ + "mips64el" + ], "dev": true, "license": "MIT", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, - "node_modules/which": { - "version": "2.0.2", + "node_modules/wrangler/node_modules/@esbuild/linux-ppc64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.4.tgz", + "integrity": "sha512-HOy0aLTJTVtoTeGZh4HSXaO6M95qu4k5lJcH4gxv56iaycfz1S8GO/5Jh6X4Y1YiI0h7cRyLi+HixMR+88swag==", + "cpu": [ + "ppc64" + ], "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/linux-riscv64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.4.tgz", + "integrity": "sha512-i8JUDAufpz9jOzo4yIShCTcXzS07vEgWzyX3NH2G7LEFVgrLEhjwL3ajFE4fZI3I4ZgiM7JH3GQ7ReObROvSUA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 8" + "node": ">=18" } }, - "node_modules/why-is-node-running": { - "version": "2.3.0", + "node_modules/wrangler/node_modules/@esbuild/linux-s390x": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.4.tgz", + "integrity": "sha512-jFnu+6UbLlzIjPQpWCNh5QtrcNfMLjgIavnwPQAfoGx4q17ocOU9MsQ2QVvFxwQoWpZT8DvTLooTvmOQXkO51g==", + "cpu": [ + "s390x" + ], "dev": true, "license": "MIT", - "dependencies": { - "siginfo": "^2.0.0", - "stackback": "0.0.2" - }, - "bin": { - "why-is-node-running": "cli.js" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=8" + "node": ">=18" } }, - "node_modules/workerd": { - "version": "1.20251008.0", + "node_modules/wrangler/node_modules/@esbuild/linux-x64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.4.tgz", + "integrity": "sha512-6e0cvXwzOnVWJHq+mskP8DNSrKBr1bULBvnFLpc1KY+d+irZSgZ02TGse5FsafKS5jg2e4pbvK6TPXaF/A6+CA==", + "cpu": [ + "x64" + ], "dev": true, - "hasInstallScript": true, - "license": "Apache-2.0", - "bin": { - "workerd": "bin/workerd" - }, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=16" - }, - "optionalDependencies": { - "@cloudflare/workerd-darwin-64": "1.20251008.0", - "@cloudflare/workerd-darwin-arm64": "1.20251008.0", - "@cloudflare/workerd-linux-64": "1.20251008.0", - "@cloudflare/workerd-linux-arm64": "1.20251008.0", - "@cloudflare/workerd-windows-64": "1.20251008.0" + "node": ">=18" } }, - "node_modules/workerd/node_modules/@cloudflare/workerd-darwin-64": { - "version": "1.20251008.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20251008.0.tgz", - "integrity": "sha512-yph0H+8mMOK5Z9oDwjb8rI96oTVt4no5lZ43aorcbzsWG9VUIaXSXlBBoB3von6p4YCRW+J3n36fBM9XZ6TLaA==", + "node_modules/wrangler/node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.4.tgz", + "integrity": "sha512-vUnkBYxZW4hL/ie91hSqaSNjulOnYXE1VSLusnvHg2u3jewJBz3YzB9+oCw8DABeVqZGg94t9tyZFoHma8gWZQ==", "cpu": [ - "x64" + "arm64" ], "dev": true, - "license": "Apache-2.0", + "license": "MIT", "optional": true, "os": [ - "darwin" + "netbsd" ], "engines": { - "node": ">=16" + "node": ">=18" } }, - "node_modules/workerd/node_modules/@cloudflare/workerd-linux-64": { - "version": "1.20251008.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20251008.0.tgz", - "integrity": "sha512-AjoQnylw4/5G6SmfhZRsli7EuIK7ZMhmbxtU0jkpciTlVV8H01OsFOgS1d8zaTXMfkWamEfMouy8oH/L7B9YcQ==", + "node_modules/wrangler/node_modules/@esbuild/netbsd-x64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.4.tgz", + "integrity": "sha512-XAg8pIQn5CzhOB8odIcAm42QsOfa98SBeKUdo4xa8OvX8LbMZqEtgeWE9P/Wxt7MlG2QqvjGths+nq48TrUiKw==", "cpu": [ "x64" ], "dev": true, - "license": "Apache-2.0", + "license": "MIT", "optional": true, "os": [ - "linux" + "netbsd" ], "engines": { - "node": ">=16" + "node": ">=18" } }, - "node_modules/workerd/node_modules/@cloudflare/workerd-linux-arm64": { - "version": "1.20251008.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20251008.0.tgz", - "integrity": "sha512-hRy9yyvzVq1HsqHZUmFkAr0C8JGjAD/PeeVEGCKL3jln3M9sNCKIrbDXiL+efe+EwajJNNlDxpO+s30uVWVaRg==", + "node_modules/wrangler/node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.4.tgz", + "integrity": "sha512-Ct2WcFEANlFDtp1nVAXSNBPDxyU+j7+tId//iHXU2f/lN5AmO4zLyhDcpR5Cz1r08mVxzt3Jpyt4PmXQ1O6+7A==", "cpu": [ "arm64" ], "dev": true, - "license": "Apache-2.0", + "license": "MIT", "optional": true, "os": [ - "linux" + "openbsd" ], "engines": { - "node": ">=16" + "node": ">=18" } }, - "node_modules/workerd/node_modules/@cloudflare/workerd-windows-64": { - "version": "1.20251008.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20251008.0.tgz", - "integrity": "sha512-Gm0RR+ehfNMsScn2pUcn3N9PDUpy7FyvV9ecHEyclKttvztyFOcmsF14bxEaSVv7iM4TxWEBn1rclmYHxDM4ow==", + "node_modules/wrangler/node_modules/@esbuild/openbsd-x64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.4.tgz", + "integrity": "sha512-xAGGhyOQ9Otm1Xu8NT1ifGLnA6M3sJxZ6ixylb+vIUVzvvd6GOALpwQrYrtlPouMqd/vSbgehz6HaVk4+7Afhw==", "cpu": [ "x64" ], "dev": true, - "license": "Apache-2.0", + "license": "MIT", "optional": true, "os": [ - "win32" + "openbsd" ], "engines": { - "node": ">=16" + "node": ">=18" } }, - "node_modules/wrangler": { - "version": "4.45.2", - "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-4.45.2.tgz", - "integrity": "sha512-+G24gD+Rh7iBus5QiVBhNgSLzyAiyuZSm+3Ih5li8+PEA+gosAXfDSZlNZwsVmXd8VJTjq+BR4vhUiruQRWgTw==", + "node_modules/wrangler/node_modules/@esbuild/sunos-x64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.4.tgz", + "integrity": "sha512-Mw+tzy4pp6wZEK0+Lwr76pWLjrtjmJyUB23tHKqEDP74R3q95luY/bXqXZeYl4NYlvwOqoRKlInQialgCKy67Q==", + "cpu": [ + "x64" + ], "dev": true, - "license": "MIT OR Apache-2.0", - "dependencies": { - "@cloudflare/kv-asset-handler": "0.4.0", - "@cloudflare/unenv-preset": "2.7.8", - "blake3-wasm": "2.1.5", - "esbuild": "0.25.4", - "miniflare": "4.20251011.1", - "path-to-regexp": "6.3.0", - "unenv": "2.0.0-rc.21", - "workerd": "1.20251011.0" - }, - "bin": { - "wrangler": "bin/wrangler.js", - "wrangler2": "bin/wrangler.js" - }, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], "engines": { - "node": ">=18.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - }, - "peerDependencies": { - "@cloudflare/workers-types": "^4.20251011.0" - }, - "peerDependenciesMeta": { - "@cloudflare/workers-types": { - "optional": true - } + "node": ">=18" } }, - "node_modules/wrangler/node_modules/@cloudflare/unenv-preset": { - "version": "2.7.8", - "resolved": "https://registry.npmjs.org/@cloudflare/unenv-preset/-/unenv-preset-2.7.8.tgz", - "integrity": "sha512-Ky929MfHh+qPhwCapYrRPwPVHtA2Ioex/DbGZyskGyNRDe9Ru3WThYZivyNVaPy5ergQSgMs9OKrM9Ajtz9F6w==", + "node_modules/wrangler/node_modules/@esbuild/win32-arm64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.4.tgz", + "integrity": "sha512-AVUP428VQTSddguz9dO9ngb+E5aScyg7nOeJDrF1HPYu555gmza3bDGMPhmVXL8svDSoqPCsCPjb265yG/kLKQ==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "MIT OR Apache-2.0", - "peerDependencies": { - "unenv": "2.0.0-rc.21", - "workerd": "^1.20250927.0" - }, - "peerDependenciesMeta": { - "workerd": { - "optional": true - } + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" } }, - "node_modules/wrangler/node_modules/@cloudflare/workerd-darwin-arm64": { - "version": "1.20251011.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20251011.0.tgz", - "integrity": "sha512-1WuFBGwZd15p4xssGN/48OE2oqokIuc51YvHvyNivyV8IYnAs3G9bJNGWth1X7iMDPe4g44pZrKhRnISS2+5dA==", + "node_modules/wrangler/node_modules/@esbuild/win32-ia32": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.4.tgz", + "integrity": "sha512-i1sW+1i+oWvQzSgfRcxxG2k4I9n3O9NRqy8U+uugaT2Dy7kLO9Y7wI72haOahxceMX8hZAzgGou1FhndRldxRg==", "cpu": [ - "arm64" + "ia32" ], "dev": true, - "license": "Apache-2.0", + "license": "MIT", "optional": true, "os": [ - "darwin" + "win32" ], "engines": { - "node": ">=16" + "node": ">=18" } }, - "node_modules/wrangler/node_modules/@esbuild/darwin-arm64": { + "node_modules/wrangler/node_modules/@esbuild/win32-x64": { "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.4.tgz", + "integrity": "sha512-nOT2vZNw6hJ+z43oP1SPea/G/6AbN6X+bGNhNuq8NtRHy4wsMhw765IKLNmnjek7GvjWBYQ8Q5VBoYTFg9y1UQ==", "cpu": [ - "arm64" + "x64" ], "dev": true, "license": "MIT", "optional": true, "os": [ - "darwin" + "win32" ], "engines": { "node": ">=18" @@ -7108,6 +9082,8 @@ }, "node_modules/wrangler/node_modules/esbuild": { "version": "0.25.4", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.4.tgz", + "integrity": "sha512-8pgjLUcUjcgDg+2Q4NYXnPbo/vncAY4UmyaCm0jZevERqCHZIaWwdJHkf8XQtu4AxSKCdvrUbT0XUr1IdZzI8Q==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -7145,93 +9121,17 @@ "@esbuild/win32-x64": "0.25.4" } }, - "node_modules/wrangler/node_modules/miniflare": { - "version": "4.20251011.1", - "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-4.20251011.1.tgz", - "integrity": "sha512-Qbw1Z8HTYM1adWl6FAtzhrj34/6dPRDPwdYOx21dkae8a/EaxbMzRIPbb4HKVGMVvtqbK1FaRCgDLVLolNzGHg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@cspotcode/source-map-support": "0.8.1", - "acorn": "8.14.0", - "acorn-walk": "8.3.2", - "exit-hook": "2.2.1", - "glob-to-regexp": "0.4.1", - "sharp": "^0.33.5", - "stoppable": "1.1.0", - "undici": "7.14.0", - "workerd": "1.20251011.0", - "ws": "8.18.0", - "youch": "4.1.0-beta.10", - "zod": "3.22.3" - }, - "bin": { - "miniflare": "bootstrap.js" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/wrangler/node_modules/workerd": { - "version": "1.20251011.0", - "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20251011.0.tgz", - "integrity": "sha512-Dq35TLPEJAw7BuYQMkN3p9rge34zWMU2Gnd4DSJFeVqld4+DAO2aPG7+We2dNIAyM97S8Y9BmHulbQ00E0HC7Q==", - "dev": true, - "hasInstallScript": true, - "license": "Apache-2.0", - "bin": { - "workerd": "bin/workerd" - }, - "engines": { - "node": ">=16" - }, - "optionalDependencies": { - "@cloudflare/workerd-darwin-64": "1.20251011.0", - "@cloudflare/workerd-darwin-arm64": "1.20251011.0", - "@cloudflare/workerd-linux-64": "1.20251011.0", - "@cloudflare/workerd-linux-arm64": "1.20251011.0", - "@cloudflare/workerd-windows-64": "1.20251011.0" - } - }, - "node_modules/wrangler/node_modules/ws": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", - "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/wrangler/node_modules/zod": { - "version": "3.22.3", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.3.tgz", - "integrity": "sha512-EjIevzuJRiRPbVH4mGc8nApb/lVLKVpmUhAaR5R5doKGfAnGJ6Gr3CViAVjP+4FWSxCsybeWQdcgCtbX+7oZug==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - }, "node_modules/wrappy": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true, "license": "ISC" }, "node_modules/ws": { "version": "8.18.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", + "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", "devOptional": true, "license": "MIT", "engines": { @@ -7252,11 +9152,15 @@ }, "node_modules/yallist": { "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "dev": true, "license": "ISC" }, "node_modules/youch": { "version": "4.1.0-beta.10", + "resolved": "https://registry.npmjs.org/youch/-/youch-4.1.0-beta.10.tgz", + "integrity": "sha512-rLfVLB4FgQneDr0dv1oddCVZmKjcJ6yX6mS4pU82Mq/Dt9a3cLZQ62pDBL4AUO+uVrCvtWz3ZFUL2HFAFJ/BXQ==", "dev": true, "license": "MIT", "dependencies": { @@ -7269,6 +9173,8 @@ }, "node_modules/youch-core": { "version": "0.3.3", + "resolved": "https://registry.npmjs.org/youch-core/-/youch-core-0.3.3.tgz", + "integrity": "sha512-ho7XuGjLaJ2hWHoK8yFnsUGy2Y5uDpqSTq1FkHLK4/oqKtyUU1AFbOOxY4IpC9f0fTLjwYbslUz0Po5BpD1wrA==", "dev": true, "license": "MIT", "dependencies": { @@ -7278,6 +9184,8 @@ }, "node_modules/zod": { "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/colinhacks" @@ -7285,6 +9193,8 @@ }, "node_modules/zod-package-json": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/zod-package-json/-/zod-package-json-1.2.0.tgz", + "integrity": "sha512-tamtgPM3MkP+obfO2dLr/G+nYoYkpJKmuHdYEy6IXRKfLybruoJ5NUj0lM0LxwOpC9PpoGLbll1ecoeyj43Wsg==", "dev": true, "license": "MIT", "dependencies": { @@ -7296,6 +9206,8 @@ }, "node_modules/zwitch": { "version": "2.0.4", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", "license": "MIT", "funding": { "type": "github",