diff --git a/.gitignore b/.gitignore index 9a5aced..d7e1ba2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,139 +1,44 @@ -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -lerna-debug.log* - -# Diagnostic reports (https://nodejs.org/api/report.html) -report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json - -# Runtime data -pids -*.pid -*.seed -*.pid.lock - -# Directory for instrumented libs generated by jscoverage/JSCover -lib-cov +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. -# Coverage directory used by tools like istanbul -coverage -*.lcov +# dependencies +/node_modules +/.pnp +.pnp.* +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/versions -# nyc test coverage -.nyc_output +# testing +/coverage -# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) -.grunt +# next.js +/.next/ +/out/ -# Bower dependency directory (https://bower.io/) -bower_components +# production +/build -# node-waf configuration -.lock-wscript +# misc +.DS_Store +*.pem -# Compiled binary addons (https://nodejs.org/api/addons.html) -build/Release +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.pnpm-debug.log* -# Dependency directories -node_modules/ -jspm_packages/ +# env files (can opt-in for committing if needed) +.env* -# Snowpack dependency directory (https://snowpack.dev/) -web_modules/ +# vercel +.vercel -# TypeScript cache +# typescript *.tsbuildinfo +next-env.d.ts -# Optional npm cache directory -.npm - -# Optional eslint cache -.eslintcache - -# Optional stylelint cache -.stylelintcache - -# Optional REPL history -.node_repl_history - -# Output of 'npm pack' -*.tgz - -# Yarn Integrity file -.yarn-integrity - -# dotenv environment variable files -.env -.env.* -!.env.example - -# parcel-bundler cache (https://parceljs.org/) -.cache -.parcel-cache - -# Next.js build output -.next -out - -# Nuxt.js build / generate output -.nuxt -dist - -# Gatsby files -.cache/ -# Comment in the public line in if your project uses Gatsby and not Next.js -# https://nextjs.org/blog/next-9-1#public-directory-support -# public - -# vuepress build output -.vuepress/dist - -# vuepress v2.x temp and cache directory -.temp -.cache - -# Sveltekit cache directory -.svelte-kit/ - -# vitepress build output -**/.vitepress/dist - -# vitepress cache directory -**/.vitepress/cache - -# Docusaurus cache and generated files -.docusaurus - -# Serverless directories -.serverless/ - -# FuseBox cache -.fusebox/ - -# DynamoDB Local files -.dynamodb/ - -# Firebase cache directory -.firebase/ - -# TernJS port file -.tern-port - -# Stores VSCode versions used for testing VSCode extensions -.vscode-test - -# yarn v3 -.pnp.* -.yarn/* -!.yarn/patches -!.yarn/plugins -!.yarn/releases -!.yarn/sdks -!.yarn/versions - -# Vite logs files -vite.config.js.timestamp-* -vite.config.ts.timestamp-* +# data persistence +/data/ diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..2b4b973 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,60 @@ +# CodeSandbox SDK Usage + +This project integrates with the CodeSandbox SDK to automatically create sandboxes when creating new projects. + +## Documentation Reference + +For comprehensive documentation on the CodeSandbox SDK, visit: https://codesandbox.io/docs/sdk + +## How It Works + +When a new project is created via the `/api/projects` endpoint, the system will: + +1. Create the project record with the provided name +2. Attempt to create a new sandbox using the `sandbox-template@latest` template +3. Store the sandbox ID with the project for future reference + +## Environment Setup + +To enable sandbox creation, you need to set up your CodeSandbox API key: + +1. Create a CodeSandbox account at https://codesandbox.io +2. Generate an API key at https://codesandbox.io/t/api +3. Set the environment variable: `CSB_API_KEY=your_api_key_here` + +### GitHub Token Requirements + +If using GitHub integration features, you'll need a GitHub token with the following permissions: +- Repository creation access +- Push access to repositories + +Set the environment variable: `GITHUB_TOKEN=your_github_token_here` + +## Template Configuration + +The system uses `sandbox-template@latest` as the default template for creating new sandboxes. This template is defined in the `sandbox-template/` directory and contains a basic Vite + React setup. + +## Error Handling + +If sandbox creation fails (due to missing API key, network issues, or other errors), the project will still be created successfully, but without an associated sandbox ID. The error is logged for debugging purposes. + +## Data Structure + +Projects now include an optional `sandboxId` field: + +```typescript +interface Project { + id: string; + name: string; + createdAt: string; + sandboxId?: string; // CodeSandbox ID when successfully created +} +``` + +## Implementation Details + +- **File**: `app/api/projects/route.ts:16-18` - Sandbox creation logic +- **File**: `app/api/projects/store.ts:5` - Project interface with sandboxId +- **File**: `app/api/projects/store.ts:11` - Updated addProject function + +The integration is designed to be non-blocking - if CodeSandbox is unavailable, project creation will still succeed. \ No newline at end of file diff --git a/CODESANDBOX_SDK_GUIDE.md b/CODESANDBOX_SDK_GUIDE.md new file mode 100644 index 0000000..5d28a07 --- /dev/null +++ b/CODESANDBOX_SDK_GUIDE.md @@ -0,0 +1,584 @@ +# CodeSandbox SDK Integration Guide + +This document provides comprehensive information about the CodeSandbox SDK integration in this Next.js application, including the React hooks-based architecture for managing sandbox operations. + +## Table of Contents + +1. [Overview](#overview) +2. [SDK Installation & Setup](#sdk-installation--setup) +3. [Architecture](#architecture) +4. [Custom React Hooks](#custom-react-hooks) +5. [Server-Side Integration](#server-side-integration) +6. [Client-Side Integration](#client-side-integration) +7. [Usage Examples](#usage-examples) +8. [Environment Configuration](#environment-configuration) +9. [Error Handling](#error-handling) +10. [Best Practices](#best-practices) + +## Overview + +This application integrates with the CodeSandbox SDK to provide seamless sandbox creation and management capabilities. The integration features: + +- **Server-side sandbox creation** using the CodeSandbox API +- **Client-side sandbox connection** and real-time interaction +- **React hooks-based architecture** for clean state management +- **Real-time project creation** with streaming progress updates +- **Integrated development environment** with VSCode and live preview + +## SDK Installation & Setup + +### Package Installation + +```bash +npm install @codesandbox/sdk +``` + +### Package Information + +- **Version**: `^2.0.6-rc.1` +- **Components Used**: + - Server SDK: `CodeSandbox`, `HostToken` + - Browser SDK: `connectToSandbox`, `createPreview` + +## Architecture + +The application provides two architectural approaches for managing CodeSandbox operations: + +### Approach 1: Composable Hooks Architecture (Current Implementation) + +``` +┌─────────────────────────────────────────────────────────────┐ +│ Client Architecture │ +├─────────────────────────────────────────────────────────────┤ +│ Components (UI Layer) │ +│ ├── HomePage │ +│ ├── ProjectPage │ +│ ├── LoginForm │ +│ └── CreateProjectModal │ +├─────────────────────────────────────────────────────────────┤ +│ Custom Hooks (Business Logic) │ +│ ├── useAuth - Authentication management │ +│ ├── useProjects - Project CRUD operations │ +│ ├── useProject - Individual project management │ +│ ├── useProjectCreation - Project creation with streaming │ +│ ├── useCodeSandbox - Sandbox connection & management │ +│ ├── useSandboxTasks - Task management (dev server, etc) │ +│ ├── useSandboxPreview - Preview iframe management │ +│ └── useSandboxManager - Comprehensive sandbox management │ +├─────────────────────────────────────────────────────────────┤ +│ CodeSandbox SDK Integration │ +│ ├── @codesandbox/sdk/browser (connectToSandbox, etc) │ +│ └── API calls to server endpoints │ +└─────────────────────────────────────────────────────────────┘ +``` + +### Approach 2: Context-Based Architecture (Recommended) + +``` +┌─────────────────────────────────────────────────────────────┐ +│ Context-Based Architecture │ +├─────────────────────────────────────────────────────────────┤ +│ Components (UI Layer) │ +│ ├── HomePage │ +│ ├── ProjectPageV2 (Context-aware) │ +│ ├── LoginForm │ +│ └── CreateProjectModal │ +├─────────────────────────────────────────────────────────────┤ +│ React Context (Shared State) │ +│ └── SandboxProvider │ +│ ├── Sandbox Client Instance │ +│ ├── Connection State │ +│ ├── Setup State │ +│ └── Event Management (Port listeners, etc) │ +├─────────────────────────────────────────────────────────────┤ +│ Context-Aware Hooks (Business Logic) │ +│ ├── useSandboxContext - Core sandbox access │ +│ ├── useSandboxTasks.v2 - Task management with context │ +│ ├── useSandboxPreview.v2 - Preview management │ +│ └── Other hooks (useAuth, useProjects, etc) │ +├─────────────────────────────────────────────────────────────┤ +│ CodeSandbox SDK Integration │ +│ ├── @codesandbox/sdk/browser (connectToSandbox, etc) │ +│ └── API calls to server endpoints │ +└─────────────────────────────────────────────────────────────┘ +``` + +## Architecture Comparison + +| Aspect | Composable Hooks | Context-Based | +|--------|------------------|---------------| +| **State Management** | Each hook manages own state | Centralized in context | +| **Event Handling** | Duplicated across hooks | Centralized event management | +| **Performance** | More re-renders | Optimized with context | +| **Testing** | Easy to test individual hooks | Requires provider wrapper | +| **Complexity** | Simple for small apps | Better for large apps | +| **Prop Drilling** | Props passed between hooks | Eliminated | +| **Memory Usage** | Higher (multiple instances) | Lower (shared instances) | + +## Custom React Hooks + +### 1. `useAuth` - Authentication Management + +Manages user authentication state and operations. + +```typescript +interface UseAuthReturn { + user: User | null; + loading: boolean; + login: (username: string, password: string) => Promise; + logout: () => Promise; + error: string | null; +} + +// Usage +const { user, loading, login, logout, error } = useAuth(); +``` + +### 2. `useProjects` - Project Management + +Handles project listing and basic operations. + +```typescript +interface UseProjectsReturn { + projects: Project[]; + loading: boolean; + error: string | null; + fetchProjects: () => Promise; + createProject: (name: string) => Promise; +} + +// Usage +const { projects, loading, fetchProjects, createProject } = useProjects(); +``` + +### 3. `useProjectCreation` - Streaming Project Creation + +Manages project creation with real-time progress updates via Server-Sent Events. + +```typescript +interface UseProjectCreationReturn { + isCreating: boolean; + progress: ProgressStep[]; + error: string | null; + createProjectWithStream: (name: string) => Promise; + resetCreation: () => void; +} + +// Usage +const { isCreating, progress, createProjectWithStream } = useProjectCreation(); +``` + +### 4. `useCodeSandbox` - Sandbox Connection + +Core hook for connecting to and managing CodeSandbox instances. + +```typescript +interface UseCodeSandboxReturn { + sandbox: any; + sandboxSession: SandboxSession | null; + loading: boolean; + error: string | null; + setupState: SetupState; + connectToSandboxInstance: (projectId: string, sandboxId: string) => Promise; + disconnect: () => Promise; + checkSetupStatus: () => Promise; +} + +// Usage +const { sandbox, connectToSandboxInstance, setupState } = useCodeSandbox(); +``` + +### 5. `useSandboxTasks` - Task Management + +Manages sandbox tasks like development server and VSCode server. + +```typescript +interface UseSandboxTasksReturn { + devServerTask: TaskState; + vscodeTask: TaskState; + taskLoading: boolean; + vscodeTaskLoading: boolean; + startDevServer: () => Promise; + restartDevServer: () => Promise; + stopDevServer: () => Promise; + startVscode: () => Promise; + restartVscode: () => Promise; + stopVscode: () => Promise; +} + +// Usage +const { devServerTask, startDevServer, vscodeTask, startVscode } = useSandboxTasks(sandbox, setupFinished); +``` + +### 6. `useSandboxPreview` - Preview Management + +Handles creation and management of preview iframes for development server and VSCode. + +```typescript +interface UseSandboxPreviewReturn { + previewState: PreviewState; + vscodeState: PreviewState; + previewContainerRef: React.RefObject; + vscodeContainerRef: React.RefObject; + createSandboxPreview: () => Promise; + createVscodePreview: () => Promise; + destroyPreview: () => void; + destroyVscodePreview: () => void; +} + +// Usage +const { previewState, previewContainerRef, createSandboxPreview } = useSandboxPreview(sandbox); +``` + +### 7. `useSandboxManager` - Comprehensive Management + +High-level hook that combines all sandbox functionality with automatic lifecycle management. + +```typescript +// Usage +const { + sandbox, + setupState, + devServerTask, + vscodeTask, + previewState, + vscodeState, + startDevServer, + startVscode, + previewContainerRef, + vscodeContainerRef, +} = useSandboxManager(); +``` + +## Context-Based Hooks (Recommended Approach) + +### 8. `SandboxProvider` - Context Provider + +Provides centralized sandbox state management across the component tree. + +```typescript +// Setup in layout or page +function ProjectLayout({ children }: { children: React.ReactNode }) { + return ( + + {children} + + ); +} +``` + +### 9. `useSandboxContext` - Core Sandbox Access + +Provides access to the sandbox instance and core functionality through React Context. + +```typescript +interface SandboxContextValue { + sandbox: any; + sandboxSession: SandboxSession | null; + loading: boolean; + error: string | null; + setupState: SetupState; + connectToSandboxInstance: (projectId: string, sandboxId: string) => Promise; + disconnect: () => Promise; + checkSetupStatus: () => Promise; + onPortOpen: (callback: (portInfo: any) => void) => () => void; + onPortClose: (callback: (port: number) => void) => () => void; +} + +// Usage +const { sandbox, setupState, connectToSandboxInstance } = useSandboxContext(); +``` + +### 10. Context-Based Task Management + +Updated hooks that consume the sandbox context for better performance and centralized state. + +```typescript +// useSandboxTasks.v2.ts - Context-aware task management +const { + devServerTask, + vscodeTask, + startDevServer, + startVscode, +} = useSandboxTasks(); // No parameters needed - uses context + +// useSandboxPreview.v2.ts - Context-aware preview management +const { + previewState, + vscodeState, + previewContainerRef, + vscodeContainerRef, +} = useSandboxPreview(); // No parameters needed - uses context +``` + +## Server-Side Integration + +### CodeSandbox Service + +The server uses a singleton service pattern for CodeSandbox operations: + +```typescript +// app/api/services/codesandbox.ts +export class CodeSandboxService { + private sdk: CodeSandbox; + private static instance: CodeSandboxService; + + static getInstance(): CodeSandboxService { + if (!process.env.CSB_API_KEY) { + throw new Error('CSB_API_KEY environment variable is required'); + } + if (!CodeSandboxService.instance) { + CodeSandboxService.instance = new CodeSandboxService(process.env.CSB_API_KEY); + } + return CodeSandboxService.instance; + } + + async createSandbox(templateId: string = 'sdk-example@latest', privacy: 'public' | 'private' = 'private') { + return await this.sdk.sandboxes.create({ + id: templateId, + privacy, + }); + } + + async resumeSandbox(sandboxId: string) { + return await this.sdk.sandboxes.resume(sandboxId); + } + + // ... other methods +} +``` + +### Key Server Endpoints + +1. **POST /api/projects** - Create new project with sandbox +2. **GET /api/projects/create-stream** - Stream project creation progress +3. **POST /api/projects/[id]/resume** - Resume/connect to sandbox +4. **GET /api/projects/[id]** - Get project details + +## Client-Side Integration + +### Sandbox Connection Flow + +```typescript +// 1. Connect to sandbox using the browser SDK +const connectedSandbox = await connectToSandbox({ + session: initialData.sandboxSession, + getSession: async (id: string) => { + const response = await fetch(`/api/projects/${projectId}/resume`, { + method: 'POST' + }); + const result = await response.json(); + return result.data.sandboxSession; + } +}); + +// 2. Monitor sandbox tasks and ports +const tasks = await sandbox.tasks.getAll(); +const devTask = tasks.find((task: any) => task.id === 'dev-server'); + +// 3. Create previews for active ports +const previewUrl = sandbox.hosts.getUrl(5173); +const preview = createPreview(previewUrl); +``` + +### Event-Driven Architecture + +The client uses event listeners for real-time updates: + +```typescript +// Port monitoring +const portOpenListener = sandbox.ports.onDidPortOpen((portInfo: any) => { + if (portInfo.port === 5173) { + // Handle dev server port opened + } +}); + +const portCloseListener = sandbox.ports.onDidPortClose((port: number) => { + if (port === 5173) { + // Handle dev server port closed + } +}); +``` + +## Usage Examples + +### Basic Project Creation + +```typescript +function CreateProject() { + const { createProjectWithStream, isCreating, progress } = useProjectCreation(); + + const handleCreate = async (name: string) => { + try { + const projectId = await createProjectWithStream(name); + router.push(`/projects/${projectId}`); + } catch (error) { + console.error('Failed to create project:', error); + } + }; + + return ( +
+ {isCreating && ( +
+ {progress.map(step => ( +
+ {step.status === 'completed' ? '✓' : '⋯'} {step.message} +
+ ))} +
+ )} +
+ ); +} +``` + +### Sandbox Management + +```typescript +function ProjectDashboard({ projectId }: { projectId: string }) { + const { project } = useProject(projectId); + const { + sandbox, + setupState, + devServerTask, + startDevServer, + previewState, + previewContainerRef, + } = useSandboxManager(); + + useEffect(() => { + if (project?.sandboxId && !sandbox) { + connectToSandboxInstance(project.id, project.sandboxId); + } + }, [project, sandbox]); + + return ( +
+
Setup Status: {setupState.status}
+
Dev Server: {devServerTask.status}
+ + {!devServerTask.portActive && ( + + )} + +
+ {/* Preview iframe will be automatically inserted here */} +
+
+ ); +} +``` + +## Environment Configuration + +### Required Environment Variables + +```env +# CodeSandbox API Key - Required for sandbox operations +CSB_API_KEY=your_codesandbox_api_key_here + +# GitHub Token - Required for Git operations in sandboxes +GITHUB_TOKEN=your_github_token_here +``` + +### Getting API Keys + +1. **CodeSandbox API Key**: + - Visit [CodeSandbox API Settings](https://codesandbox.io/t/api) + - Generate a new API key + - Set `CSB_API_KEY` environment variable + +2. **GitHub Token**: + - Visit [GitHub Personal Access Tokens](https://github.com/settings/tokens) + - Generate token with appropriate repository permissions + - Set `GITHUB_TOKEN` environment variable + +## Error Handling + +### Server-Side Error Handling + +```typescript +export class CodeSandboxService { + async createSandbox(templateId: string) { + try { + return await this.sdk.sandboxes.create({ + id: templateId, + privacy: 'private', + }); + } catch (error) { + throw new Error(`Failed to create sandbox: ${error instanceof Error ? error.message : 'Unknown error'}`); + } + } +} +``` + +### Client-Side Error Handling + +```typescript +// Hooks handle errors internally and expose them via error state +const { error } = useAuth(); +const { error: projectError } = useProjects(); +const { error: sandboxError } = useCodeSandbox(); + +// Components can display errors appropriately +{error && ( +
+ {error} +
+)} +``` + +## Best Practices + +### 1. Hook Usage Guidelines + +- **Single Responsibility**: Each hook handles one specific concern +- **Composition**: Use `useSandboxManager` for complex scenarios that need multiple hooks +- **Error Handling**: Always check error states from hooks +- **Cleanup**: Hooks automatically handle cleanup in `useEffect` return functions + +### 2. Performance Optimization + +- **Memoization**: Hooks use `useCallback` for stable function references +- **Conditional Effects**: Effects only run when necessary dependencies change +- **Resource Cleanup**: Preview iframes and event listeners are properly cleaned up + +### 3. State Management + +- **Local State**: Component-specific state stays in components +- **Shared State**: Cross-component state is managed in custom hooks +- **Server State**: API data is managed by data-fetching hooks + +### 4. CodeSandbox Best Practices + +- **Template Management**: Use versioned templates (`sdk-example@latest`) +- **Resource Cleanup**: Always disconnect from sandboxes when unmounting +- **Port Monitoring**: Use event listeners instead of polling for port status +- **Error Recovery**: Implement retry logic for network failures + +### 5. Security Considerations + +- **API Key Protection**: Never expose CodeSandbox API keys on the client +- **Session Management**: Use secure session handling for sandbox connections +- **Input Validation**: Validate all user inputs before API calls + +## API Reference + +### Server Endpoints + +| Endpoint | Method | Description | +|----------|--------|-------------| +| `/api/projects` | GET | List all projects | +| `/api/projects` | POST | Create new project with sandbox | +| `/api/projects/create-stream` | GET | Stream project creation progress | +| `/api/projects/[id]` | GET | Get project details | +| `/api/projects/[id]/resume` | POST | Resume/connect to sandbox | + +### Hook APIs + +Refer to the individual hook sections above for detailed API documentation. + +--- + +This guide provides a comprehensive overview of the CodeSandbox SDK integration. For more specific implementation details, refer to the source code in the `app/hooks/` directory and the API routes in `app/api/`. \ No newline at end of file diff --git a/README.md b/README.md index 9df56f1..e94a69a 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,96 @@ -# codesandbox-sdk-example -Example app for using the CodeSandbox SDK +# CodeSandbox Clone + +A full-featured CodeSandbox clone built with Next.js and the [@codesandbox/sdk](https://codesandbox.io/docs/sdk). This application provides a complete online code editing experience with automated project creation, sandbox management, and real-time development environments. + +## 🖥️ User-Facing Features + +### Project Dashboard +- **Project Creation**: Real-time project creation with GitHub integration using `app/components/CreateProjectModal.tsx:160` +- **Project Listing**: Dynamic project grid with sandbox status indicators at `app/page.tsx:108` +- **Authentication**: Session-based login system with GitHub token validation via `app/components/LoginForm.tsx` + +### Sandbox Development Environment +- **VS Code Integration**: Browser-based VS Code editor with automatic startup at `app/projects/[id]/page.tsx:154` +- **Live Development Preview**: Real-time preview iframe with automatic reload functionality at `app/projects/[id]/page.tsx:324` +- **Task Management**: Start/stop/restart controls for dev servers and VS Code instances +- **Port Monitoring**: Real-time status monitoring for development ports (5173 for dev server, 8080 for VS Code) +- **Setup Progress**: Visual feedback for sandbox initialization with step-by-step progress + +### Real-Time Features +- **Server-Sent Events**: Live project creation updates via streaming API at `app/api/projects/create-stream/route.ts:27` +- **Port Listeners**: Automatic detection of service availability using sandbox port events at `app/hooks/useSandboxManager.ts:88` +- **Auto-Preview**: Automatic preview creation when development server becomes available at `app/hooks/useSandboxManager.ts:129` + +### React Hooks Architecture +- **`useSandboxManager`**: Comprehensive hook orchestrating all sandbox operations at `app/hooks/useSandboxManager.ts:37` +- **`useCodeSandbox`**: Core sandbox connection and lifecycle management at `app/hooks/useCodeSandbox.ts` +- **`useSandboxTasks`**: Dev server and VS Code task management at `app/hooks/useSandboxTasks.ts` +- **`useSandboxPreview`**: Preview iframe management with error handling at `app/hooks/useSandboxPreview.ts` +- **`SandboxProvider`**: Context-based state management for performance optimization at `app/contexts/SandboxContext.tsx` + +## 🔧 Internal API Features + +### CodeSandbox SDK Service Layer +- **Singleton Service**: Centralized SDK wrapper with consistent configuration at `app/api/services/codesandbox.ts:7` +- **Sandbox Lifecycle Management**: + - Create sandboxes from templates at `app/api/services/codesandbox.ts:34` + - Resume hibernated sandboxes at `app/api/services/codesandbox.ts:60` + - Restart out-of-date sandboxes at `app/api/services/codesandbox.ts:71` + - Hibernate for resource management at `app/api/services/codesandbox.ts:82` + +### Authentication & Session Management +- **Host Token Generation**: Long-lived access tokens (10 years) for sandbox browser sessions at `app/api/services/codesandbox.ts:93` +- **Sandbox Connection**: User authentication with Git provider integration at `app/api/services/codesandbox.ts:105` +- **Session Creation**: Browser session establishment with host token authentication at `app/api/services/codesandbox.ts:129` + +### Project Management API +- **`GET /api/projects`**: List all projects with sandbox health status at `app/api/projects/route.ts` +- **`GET /api/projects/create-stream`**: Streaming project creation with 8-step process: + 1. User authentication validation at `app/api/projects/create-stream/route.ts:96` + 2. GitHub repository creation at `app/api/projects/create-stream/route.ts:133` + 3. CodeSandbox sandbox provisioning at `app/api/projects/create-stream/route.ts:154` + 4. Sandbox connection establishment at `app/api/projects/create-stream/route.ts:169` + 5. Git repository initialization at `app/api/projects/create-stream/route.ts:189` + 6. Code push to GitHub at `app/api/projects/create-stream/route.ts:212` + 7. Host token generation at `app/api/projects/create-stream/route.ts:237` + 8. Project persistence at `app/api/projects/create-stream/route.ts:252` + +- **`POST /api/projects/[id]/resume`**: Resume hibernated sandbox with session creation at `app/api/projects/[id]/resume/route.ts` + +### Monitoring & Health Management +- **Sandbox Monitor Service**: Automated health checking and maintenance at `app/api/sandbox-monitor/service.ts` +- **Automatic Restart**: Out-of-date sandbox detection and restart functionality +- **Resource Optimization**: Automatic hibernation after restart operations +- **Batch Processing**: Efficient handling of multiple sandbox health checks + +### Template System +- **Template Management**: Pre-configured project blueprints in `sandbox-template/` +- **Vite + React Setup**: Default template with TypeScript, ESLint, and development server +- **Custom Templates**: Support for multiple project types via `npm run template` deployment + +### Error Handling & Responses +- **Standardized API Responses**: Consistent error formatting via `app/api/utils/responses.ts` +- **Environment Validation**: Runtime checks for required API keys and configuration +- **Comprehensive Error Messages**: Detailed error context for debugging and user feedback +- **Graceful Degradation**: Non-blocking failures for optional features + +### Data Models +```typescript +// Project with CodeSandbox integration +interface Project { + id: string; + name: string; + createdAt: string; + sandboxId: string; // CodeSandbox sandbox ID + githubRepoUrl?: string; // GitHub repository URL + hostToken: HostToken; // Long-lived access token + isUpToDate?: boolean; // Sandbox health status +} +``` + +### Key Integration Points +- **`@codesandbox/sdk`**: Core SDK integration for sandbox operations +- **GitHub API**: Repository creation via Octokit at `app/api/projects/create-stream/route.ts:129` +- **Server-Sent Events**: Real-time progress updates using ReadableStream at `app/api/projects/create-stream/route.ts:54` +- **File System Storage**: JSON-based data persistence in `data/` directory +- **Environment Configuration**: CSB_API_KEY and GitHub token validation \ No newline at end of file diff --git a/app/api/auth/auto-login/route.ts b/app/api/auth/auto-login/route.ts new file mode 100644 index 0000000..5400b67 --- /dev/null +++ b/app/api/auth/auto-login/route.ts @@ -0,0 +1,43 @@ +import { NextResponse } from 'next/server'; +import { users, createSession } from '../store'; + +export async function POST() { + try { + // Get the default user (first user in the array) + const defaultUser = users[0]; + + if (!defaultUser) { + return NextResponse.json( + { error: 'No default user available' }, + { status: 500 } + ); + } + + // Create a session for the default user + const session = createSession(defaultUser.id); + + const response = NextResponse.json({ + user: { + id: defaultUser.id, + username: defaultUser.username, + role: defaultUser.role + } + }); + + // Set the session cookie + response.cookies.set('sessionId', session.id, { + httpOnly: true, + secure: process.env.NODE_ENV === 'production', + sameSite: 'lax', + maxAge: 24 * 60 * 60 // 24 hours + }); + + return response; + } catch (error) { + console.error('Auto-login error:', error); + return NextResponse.json( + { error: 'Auto-login failed' }, + { status: 500 } + ); + } +} \ No newline at end of file diff --git a/app/api/auth/github-status/route.ts b/app/api/auth/github-status/route.ts new file mode 100644 index 0000000..9d84da3 --- /dev/null +++ b/app/api/auth/github-status/route.ts @@ -0,0 +1,11 @@ +import { NextResponse } from 'next/server'; +import { users } from '../store'; + +export async function GET() { + const defaultUser = users[0]; + + return NextResponse.json({ + hasGitHubToken: !!(defaultUser?.githubToken), + username: defaultUser?.username || 'user' + }); +} \ No newline at end of file diff --git a/app/api/auth/login/route.ts b/app/api/auth/login/route.ts new file mode 100644 index 0000000..b92b381 --- /dev/null +++ b/app/api/auth/login/route.ts @@ -0,0 +1,49 @@ +import { NextRequest, NextResponse } from 'next/server'; +import { findUser, createSession } from '../store'; + +export async function POST(request: NextRequest) { + try { + const { username, password } = await request.json(); + + if (!username || !password) { + return NextResponse.json( + { error: 'Username and password are required' }, + { status: 400 } + ); + } + + const user = findUser(username, password); + if (!user) { + return NextResponse.json( + { error: 'Invalid username or password' }, + { status: 401 } + ); + } + + // GitHub token is optional for basic functionality + + const session = createSession(user.id); + + const response = NextResponse.json({ + user: { + id: user.id, + username: user.username, + role: user.role + } + }); + + response.cookies.set('sessionId', session.id, { + httpOnly: true, + secure: process.env.NODE_ENV === 'production', + sameSite: 'lax', + maxAge: 24 * 60 * 60 // 24 hours + }); + + return response; + } catch (error) { + return NextResponse.json( + { error: 'Internal server error' }, + { status: 500 } + ); + } +} \ No newline at end of file diff --git a/app/api/auth/logout/route.ts b/app/api/auth/logout/route.ts new file mode 100644 index 0000000..ce073fc --- /dev/null +++ b/app/api/auth/logout/route.ts @@ -0,0 +1,21 @@ +import { NextRequest, NextResponse } from 'next/server'; +import { removeSession } from '../store'; + +export async function POST(request: NextRequest) { + const sessionId = request.cookies.get('sessionId')?.value; + + if (sessionId) { + removeSession(sessionId); + } + + const response = NextResponse.json({ message: 'Logged out successfully' }); + + response.cookies.set('sessionId', '', { + httpOnly: true, + secure: process.env.NODE_ENV === 'production', + sameSite: 'lax', + maxAge: 0 + }); + + return response; +} \ No newline at end of file diff --git a/app/api/auth/me/route.ts b/app/api/auth/me/route.ts new file mode 100644 index 0000000..6fdd5f8 --- /dev/null +++ b/app/api/auth/me/route.ts @@ -0,0 +1,15 @@ +import { NextRequest, NextResponse } from 'next/server'; +import { getAuthenticatedUser } from '../middleware'; + +export async function GET(request: NextRequest) { + const user = await getAuthenticatedUser(request); + + if (!user) { + return NextResponse.json( + { error: 'Not authenticated' }, + { status: 401 } + ); + } + + return NextResponse.json({ user }); +} \ No newline at end of file diff --git a/app/api/auth/middleware.ts b/app/api/auth/middleware.ts new file mode 100644 index 0000000..a65f5c2 --- /dev/null +++ b/app/api/auth/middleware.ts @@ -0,0 +1,48 @@ +import { NextRequest } from 'next/server'; +import { findSession, getUserById, User } from './store'; + +export interface AuthenticatedUser { + id: string; + username: string; + role: 'user'; +} + +export async function getAuthenticatedUser(request: NextRequest): Promise { + const sessionId = request.cookies.get('sessionId')?.value; + + if (!sessionId) { + return null; + } + + const session = findSession(sessionId); + if (!session) { + return null; + } + + const user = getUserById(session.userId); + if (!user) { + return null; + } + + return { + id: user.id, + username: user.username, + role: user.role + }; +} + +export function requireAuth(handler: (request: NextRequest, user: AuthenticatedUser) => Promise) { + return async (request: NextRequest) => { + const user = await getAuthenticatedUser(request); + + if (!user) { + return new Response(JSON.stringify({ error: 'Authentication required' }), { + status: 401, + headers: { 'Content-Type': 'application/json' } + }); + } + + return handler(request, user); + }; +} + diff --git a/app/api/auth/store.ts b/app/api/auth/store.ts new file mode 100644 index 0000000..1de2cfc --- /dev/null +++ b/app/api/auth/store.ts @@ -0,0 +1,104 @@ +import { readFileSync, writeFileSync, existsSync } from 'fs'; +import { join } from 'path'; + +export interface User { + id: string; + username: string; + password: string; + role: 'user'; + email: string; + githubToken?: string; +} + +export interface Session { + id: string; + userId: string; + createdAt: string; + expiresAt: string; +} + +export const users: User[] = [ + { + id: '1', + username: process.env.GITHUB_USERNAME || 'user', + password: 'password', + role: 'user', + email: 'user@example.com', + githubToken: process.env.GITHUB_TOKEN + } +]; + +const SESSION_FILE_PATH = join(process.cwd(), 'data', 'sessions.json'); + +function loadSessions(): Session[] { + try { + if (existsSync(SESSION_FILE_PATH)) { + const data = readFileSync(SESSION_FILE_PATH, 'utf8'); + return JSON.parse(data); + } + } catch (error) { + console.error('Error loading sessions:', error); + } + return []; +} + +function saveSessions(sessions: Session[]): void { + try { + const dataDir = join(process.cwd(), 'data'); + if (!existsSync(dataDir)) { + require('fs').mkdirSync(dataDir, { recursive: true }); + } + writeFileSync(SESSION_FILE_PATH, JSON.stringify(sessions, null, 2)); + } catch (error) { + console.error('Error saving sessions:', error); + } +} + +export function findUser(username: string, password: string): User | undefined { + return users.find(u => u.username === username && u.password === password); +} + +export function createSession(userId: string): Session { + const sessionId = Math.random().toString(36).substr(2, 9); + const now = new Date(); + const expiresAt = new Date(now.getTime() + 24 * 60 * 60 * 1000); // 24 hours + + const session: Session = { + id: sessionId, + userId, + createdAt: now.toISOString(), + expiresAt: expiresAt.toISOString() + }; + + const sessions = loadSessions(); + sessions.push(session); + saveSessions(sessions); + return session; +} + +export function findSession(sessionId: string): Session | undefined { + const sessions = loadSessions(); + const session = sessions.find(s => s.id === sessionId); + if (!session) return undefined; + + // Check if session is expired + if (new Date() > new Date(session.expiresAt)) { + removeSession(sessionId); + return undefined; + } + + return session; +} + +export function removeSession(sessionId: string): void { + const sessions = loadSessions(); + const index = sessions.findIndex(s => s.id === sessionId); + if (index > -1) { + sessions.splice(index, 1); + saveSessions(sessions); + } +} + +export function getUserById(userId: string): User | undefined { + return users.find(u => u.id === userId); +} \ No newline at end of file diff --git a/app/api/projects/[id]/resume/route.ts b/app/api/projects/[id]/resume/route.ts new file mode 100644 index 0000000..479759d --- /dev/null +++ b/app/api/projects/[id]/resume/route.ts @@ -0,0 +1,78 @@ +import { getProject, updateProject } from "../../store"; +import { NextRequest } from "next/server"; +import { getAuthenticatedUser } from "../../../auth/middleware"; +import { getUserById } from "../../../auth/store"; +import { getCodeSandboxService } from "../../../services/codesandbox"; +import { createSuccessResponse, createErrorResponse, handleApiError, validateEnvironment } from "../../../utils/responses"; + +/** + * POST /api/projects/[id]/resume + * Resume a hibernated sandbox and create a new browser session + */ +export async function POST( + request: NextRequest, + { params }: { params: { id: string } } +) { + try { + const { id } = params; + + if (!id) { + return createErrorResponse("Project ID is required", undefined, 400, "MISSING_ID"); + } + + // Validate environment + validateEnvironment(['CSB_API_KEY']); + + const project = await getProject(id); + if (!project) { + return createErrorResponse("Project not found", `No project found with ID: ${id}`, 404, "PROJECT_NOT_FOUND"); + } + + // Get authenticated user + const authUser = await getAuthenticatedUser(request); + if (!authUser) { + return createErrorResponse("Authentication required", undefined, 401, "UNAUTHORIZED"); + } + + const user = getUserById(authUser.id); + if (!user || !user.githubToken) { + return createErrorResponse( + "GitHub token not found for user", + "User must have a valid GitHub token to resume sandboxes", + 400, + "MISSING_GITHUB_TOKEN" + ); + } + + // Resume the sandbox using the centralized service + const csbService = getCodeSandboxService(); + const sandbox = await csbService.resumeSandbox(project.sandboxId); + + // Update project with current isUpToDate status + await updateProject(id, { isUpToDate: sandbox.isUpToDate }); + + // Create new browser session + const sandboxSession = await csbService.createSandboxSession( + sandbox, + { + id: user.username, + email: user.email, + username: user.username, + githubToken: user.githubToken, + }, + project.hostToken + ); + + return createSuccessResponse( + { + sandboxSession, + isUpToDate: sandbox.isUpToDate, + projectName: project.name, + sandboxId: project.sandboxId + }, + `Successfully resumed sandbox for ${project.name}` + ); + } catch (error) { + return handleApiError(error, 'Resume sandbox'); + } +} \ No newline at end of file diff --git a/app/api/projects/[id]/route.ts b/app/api/projects/[id]/route.ts new file mode 100644 index 0000000..ff1b7ea --- /dev/null +++ b/app/api/projects/[id]/route.ts @@ -0,0 +1,29 @@ +import { getProject } from "../store"; +import { createSuccessResponse, createErrorResponse, handleApiError } from "../../utils/responses"; + +/** + * GET /api/projects/[id] + * Retrieve a specific project by ID with sandbox information + */ +export async function GET( + _request: Request, + { params }: { params: { id: string } } +) { + try { + const { id } = params; + + if (!id) { + return createErrorResponse("Project ID is required", undefined, 400, "MISSING_ID"); + } + + const project = await getProject(id); + + if (!project) { + return createErrorResponse("Project not found", `No project found with ID: ${id}`, 404, "PROJECT_NOT_FOUND"); + } + + return createSuccessResponse(project, `Retrieved project ${project.name}`); + } catch (error) { + return handleApiError(error, 'Get project'); + } +} diff --git a/app/api/projects/create-stream/route.ts b/app/api/projects/create-stream/route.ts new file mode 100644 index 0000000..1bb893d --- /dev/null +++ b/app/api/projects/create-stream/route.ts @@ -0,0 +1,279 @@ +import { addProject } from "../store"; +import { Octokit } from "@octokit/rest"; +import { NextRequest } from "next/server"; +import { getAuthenticatedUser } from "../../auth/middleware"; +import { getUserById } from "../../auth/store"; +import { getCodeSandboxService } from "../../services/codesandbox"; +import { validateEnvironment, validateRequiredParams } from "../../utils/responses"; + +interface ProgressStep { + id: string; + message: string; + status: "pending" | "in_progress" | "completed" | "error"; +} + +function createProgressMessage( + type: "progress" | "success" | "error", + data: any +): string { + return `data: ${JSON.stringify({ type, ...data })}\n\n`; +} + +/** + * GET /api/projects/create-stream + * Create a new project with GitHub repository and CodeSandbox integration + * Returns a Server-Sent Events stream for real-time progress updates + */ +export async function GET(request: NextRequest) { + const { searchParams } = new URL(request.url); + const name = searchParams.get("name"); + + if (!name || typeof name !== "string") { + return new Response( + createProgressMessage("error", { message: "Project name is required and must be a non-empty string" }), + { + status: 400, + headers: { + "Content-Type": "text/plain", + }, + } + ); + } + + // Set up SSE headers + const headers = new Headers({ + "Content-Type": "text/event-stream", + "Cache-Control": "no-cache", + Connection: "keep-alive", + "Access-Control-Allow-Origin": "*", + "Access-Control-Allow-Headers": "Cache-Control", + }); + + const encoder = new TextEncoder(); + + const stream = new ReadableStream({ + async start(controller) { + let currentStepId: string | undefined; + + const sendProgress = (step: ProgressStep) => { + currentStepId = step.status === "in_progress" ? step.id : currentStepId; + controller.enqueue( + encoder.encode(createProgressMessage("progress", { step })) + ); + }; + + const sendSuccess = (projectId: string) => { + controller.enqueue( + encoder.encode(createProgressMessage("success", { projectId })) + ); + controller.close(); + }; + + const sendError = (message: string, stepId?: string) => { + const errorStepId = stepId || currentStepId; + // If we have a current step that was in progress, mark it as failed + if (errorStepId) { + sendProgress({ + id: errorStepId, + message: `Failed: ${message}`, + status: "error", + }); + } + controller.enqueue( + encoder.encode(createProgressMessage("error", { message })) + ); + controller.close(); + }; + + try { + // Step 1: Authentication + sendProgress({ + id: "auth", + message: "Authenticating user...", + status: "in_progress", + }); + + const authUser = await getAuthenticatedUser(request); + if (!authUser) { + sendError("Authentication required", "auth"); + return; + } + + const user = getUserById(authUser.id); + if (!user || !user.githubToken) { + sendError("GitHub token not found for user", "auth"); + return; + } + + // Validate environment variables + try { + validateEnvironment(['CSB_API_KEY']); + } catch (error) { + sendError(error instanceof Error ? error.message : "Environment validation failed", "auth"); + return; + } + + sendProgress({ + id: "auth", + message: "User authenticated successfully", + status: "completed", + }); + + // Step 2: Create GitHub repository + sendProgress({ + id: "github-repo", + message: "Creating GitHub repository...", + status: "in_progress", + }); + + const octokit = new Octokit({ + auth: user.githubToken, + }); + + const repo = await octokit.rest.repos.createForAuthenticatedUser({ + name: name, + private: false, + auto_init: false, + description: `Project repository for ${name}`, + }); + + sendProgress({ + id: "github-repo", + message: `GitHub repository created: ${repo.data.html_url}`, + status: "completed", + }); + + // Step 3: Create CodeSandbox sandbox + sendProgress({ + id: "sandbox-create", + message: "Creating CodeSandbox sandbox...", + status: "in_progress", + }); + + const csbService = getCodeSandboxService(); + const sandbox = await csbService.createSandbox("sdk-example@latest", "private"); + + sendProgress({ + id: "sandbox-create", + message: `Sandbox created: ${sandbox.id}`, + status: "completed", + }); + + // Step 4: Connect to sandbox + sendProgress({ + id: "sandbox-connect", + message: "Connecting to sandbox...", + status: "in_progress", + }); + + const client = await csbService.connectToSandbox(sandbox, { + id: user.username, + email: user.email, + username: user.username, + githubToken: user.githubToken, + }); + + sendProgress({ + id: "sandbox-connect", + message: "Connected to sandbox successfully", + status: "completed", + }); + + // Step 5: Setting up Git repository + sendProgress({ + id: "git-setup", + message: "Initializing Git repository...", + status: "in_progress", + }); + + await client.commands.run( + "git init", + `git remote add origin https://github.com/${user.username}/${repo.data.name}.git`, + { + cwd: "/project/workspace/app", + } + ); + + sendProgress({ + id: "git-setup", + message: "Git repository initialized", + status: "completed", + }); + + // Step 6: Committing and pushing code + sendProgress({ + id: "git-push", + message: "Committing and pushing initial code...", + status: "in_progress", + }); + + await client.commands.run( + [ + "git add .", + `git commit -m "Initial commit"`, + "git branch -M main", + "git push -u origin main", + ], + { + cwd: "/project/workspace/app", + } + ); + + sendProgress({ + id: "git-push", + message: "Code pushed to GitHub successfully", + status: "completed", + }); + + // Step 7: Generate host token + sendProgress({ + id: "host-token", + message: "Generating host token...", + status: "in_progress", + }); + + const hostToken = await csbService.createHostToken(sandbox.id, 10); // 10 years expiration + + sendProgress({ + id: "host-token", + message: "Host token generated", + status: "completed", + }); + + // Step 8: Save project + sendProgress({ + id: "save-project", + message: "Saving project...", + status: "in_progress", + }); + + const project = await addProject( + name, + sandbox.id, + hostToken, + repo.data.html_url + ); + + sendProgress({ + id: "save-project", + message: "Project saved successfully", + status: "completed", + }); + + // Success! + sendSuccess(project.id); + } catch (error) { + console.error("Project creation failed:", error); + let errorMessage = "Failed to create project"; + + if (error instanceof Error) { + errorMessage = error.message; + } + + sendError(errorMessage); + } + }, + }); + + return new Response(stream, { headers }); +} diff --git a/app/api/projects/route.ts b/app/api/projects/route.ts new file mode 100644 index 0000000..c7d1d7b --- /dev/null +++ b/app/api/projects/route.ts @@ -0,0 +1,15 @@ +import { getAllProjects } from "./store"; +import { createSuccessResponse, handleApiError } from "../utils/responses"; + +/** + * GET /api/projects + * Retrieve all projects with their associated sandbox information + */ +export async function GET() { + try { + const projects = await getAllProjects(); + return createSuccessResponse(projects, `Retrieved ${projects.length} projects`); + } catch (error) { + return handleApiError(error, 'Get projects'); + } +} diff --git a/app/api/projects/store.ts b/app/api/projects/store.ts new file mode 100644 index 0000000..c407be9 --- /dev/null +++ b/app/api/projects/store.ts @@ -0,0 +1,87 @@ +import { HostToken } from '@codesandbox/sdk'; +import { promises as fs } from 'fs'; +import path from 'path'; + +export interface Project { + id: string; + name: string; + createdAt: string; + sandboxId: string; + githubRepoUrl?: string; + hostToken: HostToken; + isUpToDate?: boolean; +} + +interface StoreData { + projects: Project[]; + nextId: number; +} + +const STORE_FILE = path.join(process.cwd(), 'data', 'projects.json'); + +async function ensureDataDir(): Promise { + const dataDir = path.dirname(STORE_FILE); + try { + await fs.access(dataDir); + } catch { + await fs.mkdir(dataDir, { recursive: true }); + } +} + +async function loadStore(): Promise { + try { + await ensureDataDir(); + const data = await fs.readFile(STORE_FILE, 'utf-8'); + return JSON.parse(data); + } catch { + return { projects: [], nextId: 1 }; + } +} + +async function saveStore(data: StoreData): Promise { + await ensureDataDir(); + await fs.writeFile(STORE_FILE, JSON.stringify(data, null, 2)); +} + +export async function addProject(name: string, sandboxId: string, hostToken: HostToken, githubRepoUrl?: string): Promise { + const store = await loadStore(); + + const project: Project = { + id: store.nextId.toString(), + name, + createdAt: new Date().toISOString(), + sandboxId, + githubRepoUrl, + hostToken, + isUpToDate: true + }; + + store.projects.push(project); + store.nextId++; + + await saveStore(store); + return project; +} + +export async function getProject(id: string): Promise { + const store = await loadStore(); + return store.projects.find(p => p.id === id); +} + +export async function getAllProjects(): Promise { + const store = await loadStore(); + return store.projects; +} + +export async function updateProject(id: string, updates: Partial): Promise { + const store = await loadStore(); + const projectIndex = store.projects.findIndex(p => p.id === id); + + if (projectIndex === -1) { + return undefined; + } + + store.projects[projectIndex] = { ...store.projects[projectIndex], ...updates }; + await saveStore(store); + return store.projects[projectIndex]; +} \ No newline at end of file diff --git a/app/api/sandbox-monitor/route.ts b/app/api/sandbox-monitor/route.ts new file mode 100644 index 0000000..e59bfe5 --- /dev/null +++ b/app/api/sandbox-monitor/route.ts @@ -0,0 +1,74 @@ +import { NextRequest } from "next/server"; +import { sandboxMonitorService } from "./service"; +import { createSuccessResponse, createErrorResponse, handleApiError } from "../utils/responses"; + +/** + * GET /api/sandbox-monitor + * Get the current status of the sandbox monitoring service + */ +export async function GET() { + try { + const status = sandboxMonitorService.getStatus(); + return createSuccessResponse(status, "Retrieved sandbox monitor status"); + } catch (error) { + return handleApiError(error, 'Get sandbox monitor status'); + } +} + +/** + * POST /api/sandbox-monitor + * Control the sandbox monitoring service (start, stop, check) + */ +export async function POST(request: NextRequest) { + try { + const body = await request.json(); + const { action } = body; + + if (!action) { + return createErrorResponse( + "Action is required", + 'Valid actions are: "start", "stop", "check"', + 400, + "MISSING_ACTION" + ); + } + + switch (action) { + case 'start': + sandboxMonitorService.start(); + const startStatus = sandboxMonitorService.getStatus(); + return createSuccessResponse( + startStatus, + startStatus.isRunning + ? 'Sandbox monitor service started successfully' + : 'Sandbox monitor service was already running' + ); + + case 'stop': + sandboxMonitorService.stop(); + const stopStatus = sandboxMonitorService.getStatus(); + return createSuccessResponse( + stopStatus, + 'Sandbox monitor service stopped' + ); + + case 'check': + await sandboxMonitorService.manualCheck(); + const checkStatus = sandboxMonitorService.getStatus(); + return createSuccessResponse( + checkStatus, + 'Manual sandbox check completed' + ); + + default: + return createErrorResponse( + "Invalid action", + 'Valid actions are: "start", "stop", "check"', + 400, + "INVALID_ACTION" + ); + } + } catch (error) { + return handleApiError(error, 'Manage sandbox monitor'); + } +} \ No newline at end of file diff --git a/app/api/sandbox-monitor/service.ts b/app/api/sandbox-monitor/service.ts new file mode 100644 index 0000000..0556ec1 --- /dev/null +++ b/app/api/sandbox-monitor/service.ts @@ -0,0 +1,152 @@ +import { getAllProjects, updateProject } from "../projects/store"; +import { getCodeSandboxService } from "../services/codesandbox"; + +/** + * Service to monitor and maintain CodeSandbox sandbox health + * Automatically restarts out-of-date sandboxes and hibernates them to save resources + */ +class SandboxMonitorService { + private intervalId: NodeJS.Timeout | null = null; + private readonly CHECK_INTERVAL = 5 * 60 * 1000; // 5 minutes + private isRunning = false; + + /** + * Start the monitoring service + */ + start() { + if (this.intervalId || this.isRunning) { + console.log('Sandbox monitor service is already running'); + return; + } + + // Validate environment before starting + if (!process.env.CSB_API_KEY) { + console.warn('CodeSandbox API key not found, cannot start monitor service'); + return; + } + + this.isRunning = true; + this.intervalId = setInterval(async () => { + await this.checkOutOfDateProjects(); + }, this.CHECK_INTERVAL); + + console.log(`Sandbox monitor service started (checking every ${this.CHECK_INTERVAL / 1000 / 60} minutes)`); + } + + /** + * Stop the monitoring service + */ + stop() { + if (this.intervalId) { + clearInterval(this.intervalId); + this.intervalId = null; + this.isRunning = false; + console.log('Sandbox monitor service stopped'); + } + } + + /** + * Get the current status of the monitor service + */ + getStatus() { + return { + isRunning: this.isRunning, + checkInterval: this.CHECK_INTERVAL, + nextCheckIn: this.intervalId ? this.CHECK_INTERVAL : null + }; + } + + /** + * Manually trigger a check for out-of-date projects + */ + async manualCheck() { + console.log('Manual sandbox monitor check triggered'); + await this.checkOutOfDateProjects(); + } + + /** + * Check all projects for out-of-date sandboxes and handle them + */ + private async checkOutOfDateProjects() { + try { + if (!process.env.CSB_API_KEY) { + console.warn('CodeSandbox API key not found, skipping monitor check'); + return; + } + + const projects = await getAllProjects(); + + const outOfDateProjects = projects.filter(project => + project.isUpToDate === false || project.isUpToDate === undefined + ); + + console.log(`Monitor check: Found ${outOfDateProjects.length} potentially out-of-date projects out of ${projects.length} total`); + + if (outOfDateProjects.length === 0) { + return; + } + + const csbService = getCodeSandboxService(); + + // Process projects in batches to avoid overwhelming the API + const batchSize = 3; + for (let i = 0; i < outOfDateProjects.length; i += batchSize) { + const batch = outOfDateProjects.slice(i, i + batchSize); + + await Promise.allSettled( + batch.map(project => + this.handleOutOfDateProject(csbService, project.id, project.sandboxId, project.name) + ) + ); + + // Small delay between batches + if (i + batchSize < outOfDateProjects.length) { + await new Promise(resolve => setTimeout(resolve, 1000)); + } + } + } catch (error) { + console.error('Error in sandbox monitor check:', error); + } + } + + /** + * Handle a single out-of-date project + */ + private async handleOutOfDateProject( + csbService: any, + projectId: string, + sandboxId: string, + projectName: string + ) { + try { + console.log(`Checking sandbox ${sandboxId} for project "${projectName}" (${projectId})`); + + // Check current status + const sandbox = await csbService.getSandbox(sandboxId); + + if (!sandbox.isUpToDate) { + console.log(`Restarting out-of-date sandbox ${sandboxId} for project "${projectName}"`); + + // Restart the sandbox + await csbService.restartSandbox(sandboxId); + + // Hibernate after restart to save resources + await csbService.hibernateSandbox(sandboxId); + + // Update project status + await updateProject(projectId, { isUpToDate: true }); + + console.log(`Successfully restarted and hibernated sandbox ${sandboxId} for "${projectName}"`); + } else { + // Update project status if it's now up to date + await updateProject(projectId, { isUpToDate: true }); + console.log(`Sandbox ${sandboxId} for "${projectName}" is up to date`); + } + } catch (error) { + console.error(`Failed to handle sandbox ${sandboxId} for project "${projectName}":`, error); + // Don't throw to avoid stopping the entire batch + } + } +} + +export const sandboxMonitorService = new SandboxMonitorService(); \ No newline at end of file diff --git a/app/api/services/codesandbox.ts b/app/api/services/codesandbox.ts new file mode 100644 index 0000000..70430fd --- /dev/null +++ b/app/api/services/codesandbox.ts @@ -0,0 +1,157 @@ +import { CodeSandbox, HostToken } from '@codesandbox/sdk'; + +/** + * Centralized CodeSandbox SDK service + * Handles all CodeSandbox API interactions with consistent error handling and configuration + */ +export class CodeSandboxService { + private sdk: CodeSandbox; + private static instance: CodeSandboxService; + + private constructor(apiKey: string) { + this.sdk = new CodeSandbox(apiKey); + } + + /** + * Get singleton instance of CodeSandboxService + * Ensures consistent SDK configuration across the application + */ + static getInstance(): CodeSandboxService { + if (!process.env.CSB_API_KEY) { + throw new Error('CSB_API_KEY environment variable is required'); + } + + if (!CodeSandboxService.instance) { + CodeSandboxService.instance = new CodeSandboxService(process.env.CSB_API_KEY); + } + + return CodeSandboxService.instance; + } + + /** + * Create a new sandbox from template + */ + async createSandbox(templateId: string = 'sdk-example@latest', privacy: 'public' | 'private' = 'private') { + try { + return await this.sdk.sandboxes.create({ + id: templateId, + privacy, + }); + } catch (error) { + throw new Error(`Failed to create sandbox: ${error instanceof Error ? error.message : 'Unknown error'}`); + } + } + + /** + * Get sandbox information + */ + async getSandbox(sandboxId: string) { + try { + // Note: Using any type as the SDK types may not be perfectly aligned + return await (this.sdk.sandboxes as any).get(sandboxId); + } catch (error) { + throw new Error(`Failed to get sandbox ${sandboxId}: ${error instanceof Error ? error.message : 'Unknown error'}`); + } + } + + /** + * Resume a hibernated sandbox + */ + async resumeSandbox(sandboxId: string) { + try { + return await this.sdk.sandboxes.resume(sandboxId); + } catch (error) { + throw new Error(`Failed to resume sandbox ${sandboxId}: ${error instanceof Error ? error.message : 'Unknown error'}`); + } + } + + /** + * Restart a sandbox + */ + async restartSandbox(sandboxId: string) { + try { + return await this.sdk.sandboxes.restart(sandboxId); + } catch (error) { + throw new Error(`Failed to restart sandbox ${sandboxId}: ${error instanceof Error ? error.message : 'Unknown error'}`); + } + } + + /** + * Hibernate a sandbox to save resources + */ + async hibernateSandbox(sandboxId: string) { + try { + return await this.sdk.sandboxes.hibernate(sandboxId); + } catch (error) { + throw new Error(`Failed to hibernate sandbox ${sandboxId}: ${error instanceof Error ? error.message : 'Unknown error'}`); + } + } + + /** + * Create a host token for sandbox access + */ + async createHostToken(sandboxId: string, expirationYears: number = 10): Promise { + try { + const expiresAt = new Date(Date.now() + expirationYears * 365 * 24 * 60 * 60 * 1000); + return await this.sdk.hosts.createToken(sandboxId, { expiresAt }); + } catch (error) { + throw new Error(`Failed to create host token for sandbox ${sandboxId}: ${error instanceof Error ? error.message : 'Unknown error'}`); + } + } + + /** + * Connect to a sandbox and return a client + */ + async connectToSandbox(sandbox: any, userConfig: { + id: string; + email: string; + username: string; + githubToken: string; + }) { + try { + return await sandbox.connect({ + id: userConfig.id, + git: { + email: userConfig.email, + username: userConfig.username, + provider: "github.com", + accessToken: userConfig.githubToken, + }, + }); + } catch (error) { + throw new Error(`Failed to connect to sandbox: ${error instanceof Error ? error.message : 'Unknown error'}`); + } + } + + /** + * Create a browser session for a sandbox + */ + async createSandboxSession(sandbox: any, userConfig: { + id: string; + email: string; + username: string; + githubToken: string; + }, hostToken: HostToken) { + try { + return await sandbox.createSession({ + id: userConfig.id, + git: { + email: userConfig.email, + username: userConfig.username, + provider: "github.com", + accessToken: userConfig.githubToken, + }, + hostToken, + }); + } catch (error) { + throw new Error(`Failed to create sandbox session: ${error instanceof Error ? error.message : 'Unknown error'}`); + } + } +} + +/** + * Convenience function to get CodeSandbox service instance + */ +export function getCodeSandboxService(): CodeSandboxService { + return CodeSandboxService.getInstance(); +} \ No newline at end of file diff --git a/app/api/startup/route.ts b/app/api/startup/route.ts new file mode 100644 index 0000000..2eb6b3d --- /dev/null +++ b/app/api/startup/route.ts @@ -0,0 +1,19 @@ +import { sandboxMonitorService } from "../sandbox-monitor/service"; + +export async function GET() { + try { + // Start the sandbox monitor service + sandboxMonitorService.start(); + + return Response.json({ + message: 'Application initialized successfully', + services: ['sandbox-monitor'] + }); + } catch (error) { + console.error('Error during application startup:', error); + return Response.json( + { error: 'Failed to initialize application services' }, + { status: 500 } + ); + } +} \ No newline at end of file diff --git a/app/api/utils/responses.ts b/app/api/utils/responses.ts new file mode 100644 index 0000000..7d0dcd4 --- /dev/null +++ b/app/api/utils/responses.ts @@ -0,0 +1,121 @@ +/** + * Standardized API response utilities + * Provides consistent error handling and response formatting across all endpoints + */ + +export interface ApiError { + error: string; + details?: string; + code?: string; +} + +export interface ApiSuccess { + data: T; + message?: string; +} + +/** + * Create a standardized success response + */ +export function createSuccessResponse(data: T, message?: string, status: number = 200): Response { + const response: ApiSuccess = { data }; + if (message) response.message = message; + + return Response.json(response, { status }); +} + +/** + * Create a standardized error response + */ +export function createErrorResponse( + error: string, + details?: string, + status: number = 500, + code?: string +): Response { + const response: ApiError = { error }; + if (details) response.details = details; + if (code) response.code = code; + + return Response.json(response, { status }); +} + +/** + * Handle and format caught errors consistently + */ +export function handleApiError(error: unknown, context: string): Response { + console.error(`API Error in ${context}:`, error); + + if (error instanceof Error) { + // Check for specific error types that should return different status codes + if (error.message.includes('not found')) { + return createErrorResponse( + `${context} failed`, + error.message, + 404, + 'NOT_FOUND' + ); + } + + if (error.message.includes('Authentication') || error.message.includes('Unauthorized')) { + return createErrorResponse( + `${context} failed`, + error.message, + 401, + 'UNAUTHORIZED' + ); + } + + if (error.message.includes('required') || error.message.includes('invalid')) { + return createErrorResponse( + `${context} failed`, + error.message, + 400, + 'BAD_REQUEST' + ); + } + + return createErrorResponse( + `${context} failed`, + error.message, + 500, + 'INTERNAL_ERROR' + ); + } + + return createErrorResponse( + `${context} failed`, + 'An unexpected error occurred', + 500, + 'UNKNOWN_ERROR' + ); +} + +/** + * Validate required environment variables + */ +export function validateEnvironment(requiredVars: string[]): void { + const missing = requiredVars.filter(varName => !process.env[varName]); + + if (missing.length > 0) { + throw new Error( + `Missing required environment variables: ${missing.join(', ')}` + ); + } +} + +/** + * Validate required request parameters + */ +export function validateRequiredParams( + params: Record, + required: string[] +): void { + const missing = required.filter(param => !params[param] || params[param] === ''); + + if (missing.length > 0) { + throw new Error( + `Missing required parameters: ${missing.join(', ')}` + ); + } +} \ No newline at end of file diff --git a/app/components/CreateProjectModal.tsx b/app/components/CreateProjectModal.tsx new file mode 100644 index 0000000..aede209 --- /dev/null +++ b/app/components/CreateProjectModal.tsx @@ -0,0 +1,249 @@ +'use client'; + +import { useState } from 'react'; +import { useProjectCreation } from '../hooks/useProjectCreation'; + +interface CreateProjectModalProps { + isOpen: boolean; + onClose: () => void; + onProjectCreated: (projectId: string) => void; +} + +export default function CreateProjectModal({ isOpen, onClose, onProjectCreated }: CreateProjectModalProps) { + const [projectName, setProjectName] = useState(''); + const { isCreating, progress, error, createProjectWithStream, resetCreation } = useProjectCreation(); + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + + try { + const projectId = await createProjectWithStream(projectName); + onProjectCreated(projectId); + } catch (err) { + // Error is handled by the useProjectCreation hook + } + }; + + const handleClose = () => { + if (!isCreating) { + setProjectName(''); + resetCreation(); + onClose(); + } + }; + + if (!isOpen) return null; + + return ( +
+
+

Create New Project

+ + {!isCreating && progress.length === 0 ? ( +
+
+ + setProjectName(e.target.value)} + placeholder="Enter project name..." + style={{ + width: '100%', + padding: '8px 12px', + border: '1px solid #d1d5db', + borderRadius: '6px', + fontSize: '16px', + color: '#1f2937', + backgroundColor: '#ffffff' + }} + autoFocus + /> +
+ +
+ ℹ️ + This will create a public repository on your GitHub account. +
+ + {error && ( +
+ {error} +
+ )} + +
+ + +
+
+ ) : ( +
+

+ {isCreating ? `Creating "${projectName}"...` : `Project Creation ${error ? 'Failed' : 'Completed'}`} +

+
+ {progress.map((step) => ( +
+
+ {step.status === 'completed' && } + {step.status === 'in_progress' && } + {step.status === 'error' && } + {step.status === 'pending' && } +
+
+ + {step.message} + +
+
+ ))} +
+ + {error && ( +
+ {error} +
+ )} + + {!isCreating && ( +
+ + {error && ( + + )} +
+ )} +
+ )} +
+
+ ); +} \ No newline at end of file diff --git a/app/components/GitHubTokenError.tsx b/app/components/GitHubTokenError.tsx new file mode 100644 index 0000000..d47c87c --- /dev/null +++ b/app/components/GitHubTokenError.tsx @@ -0,0 +1,68 @@ +'use client'; + +interface GitHubTokenErrorProps { + onRetry?: () => void; +} + +export default function GitHubTokenError({ onRetry }: GitHubTokenErrorProps) { + return ( +
+
+
+
+ + + +
+

Missing GitHub Token

+

+ A GitHub token is required to create projects and integrate with CodeSandbox. +

+
+ +
+

Setup Instructions:

+
    +
  1. + 1 + Go to GitHub Settings → Developer settings → Personal access tokens +
  2. +
  3. + 2 + Create a new token with repo permissions +
  4. +
  5. + 3 + Set the environment variable: +
  6. +
+ +
+ GITHUB_TOKEN=your_token_here +
+ +

+ Add this to your .env.local file or environment variables +

+
+ + {onRetry && ( +
+ +
+ )} + +
+

+ Restart your development server after setting the token +

+
+
+
+ ); +} \ No newline at end of file diff --git a/app/components/LoginForm.tsx b/app/components/LoginForm.tsx new file mode 100644 index 0000000..a43ccfd --- /dev/null +++ b/app/components/LoginForm.tsx @@ -0,0 +1,93 @@ +"use client"; + +import { useState } from "react"; +import { useAuth } from "../hooks/useAuth"; + +export default function LoginForm() { + const [username, setUsername] = useState(""); + const [password, setPassword] = useState(""); + const { login, loading, error } = useAuth(); + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + + try { + await login(username, password); + } catch (err) { + // Error is handled by the useAuth hook + } + }; + + return ( +
+
+
+

+ Welcome Back +

+

Sign in to your account

+
+ + {error && ( +
+ {error} +
+ )} + +
+
+ + setUsername(e.target.value)} + className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-transparent text-gray-900 bg-white" + required + /> +
+ +
+ + setPassword(e.target.value)} + className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-transparent text-gray-900 bg-white" + required + /> +
+ + +
+ +
+

+ Demo Account: +

+
+
User: GITHUB_USERNAME, Password: "password"
+
Requires GITHUB_TOKEN env var to be set
+
+
+
+
+ ); +} diff --git a/app/contexts/SandboxContext.tsx b/app/contexts/SandboxContext.tsx new file mode 100644 index 0000000..7dd17b0 --- /dev/null +++ b/app/contexts/SandboxContext.tsx @@ -0,0 +1,275 @@ +'use client'; + +import React, { createContext, useContext, useCallback, useState, useEffect } from 'react'; +import { connectToSandbox } from '@codesandbox/sdk/browser'; + +interface SandboxSession { + url: string; +} + +interface SetupState { + status: 'NOT_STARTED' | 'RUNNING' | 'FINISHED' | 'ERROR'; + currentStepIndex: number; + totalSteps: number; + currentStepName: string; +} + +interface SandboxContextValue { + // Core sandbox state + sandbox: any; + sandboxSession: SandboxSession | null; + loading: boolean; + error: string | null; + setupState: SetupState; + + // Connection methods + connectToSandboxInstance: (projectId: string, sandboxId: string) => Promise; + disconnect: () => Promise; + + // Setup monitoring + checkSetupStatus: () => Promise; + + // Event handlers (for port monitoring, etc.) + onPortOpen: (callback: (portInfo: any) => void) => () => void; + onPortClose: (callback: (port: number) => void) => () => void; +} + +const SandboxContext = createContext(null); + +export function useSandboxContext(): SandboxContextValue { + const context = useContext(SandboxContext); + if (!context) { + throw new Error('useSandboxContext must be used within a SandboxProvider'); + } + return context; +} + +interface SandboxProviderProps { + children: React.ReactNode; +} + +export function SandboxProvider({ children }: SandboxProviderProps) { + const [sandbox, setSandbox] = useState(null); + const [sandboxSession, setSandboxSession] = useState(null); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(null); + const [setupState, setSetupState] = useState({ + status: 'NOT_STARTED', + currentStepIndex: 0, + totalSteps: 0, + currentStepName: '' + }); + + // Port event listeners registry + const [portOpenListeners, setPortOpenListeners] = useState void>>(new Set()); + const [portCloseListeners, setPortCloseListeners] = useState void>>(new Set()); + + const checkSetupStatus = useCallback(async () => { + if (!sandbox) return; + + try { + console.log('🔍 Checking setup status...'); + + const steps = sandbox.setup ? await sandbox.setup.getSteps() : null; + + if (steps && steps.length > 0) { + console.log('📊 Setup steps:', steps); + + let currentStepIndex = 0; + let status = 'FINISHED'; + let currentStepName = ''; + + for (let i = 0; i < steps.length; i++) { + const step = steps[i]; + if (step.status === 'RUNNING') { + currentStepIndex = i; + status = 'RUNNING'; + currentStepName = step.name || `Step ${i + 1}`; + break; + } else if (step.status === 'ERROR') { + currentStepIndex = i; + status = 'ERROR'; + currentStepName = step.name || `Step ${i + 1} (Error)`; + break; + } else if (step.status === 'PENDING') { + if (status === 'FINISHED') { + status = 'NOT_STARTED'; + currentStepIndex = 0; + currentStepName = ''; + } + } + } + + setSetupState({ + status: status as 'RUNNING' | 'FINISHED' | 'ERROR' | 'NOT_STARTED', + currentStepIndex, + totalSteps: steps.length, + currentStepName + }); + } else { + console.log('No setup steps found, assuming setup is finished'); + setSetupState({ + status: 'FINISHED', + currentStepIndex: 0, + totalSteps: 0, + currentStepName: '' + }); + } + } catch (err) { + console.error('💥 Failed to check setup status:', err); + setSetupState({ + status: 'ERROR', + currentStepIndex: 0, + totalSteps: 0, + currentStepName: 'Setup check failed' + }); + } + }, [sandbox]); + + const connectToSandboxInstance = useCallback(async (projectId: string, sandboxId: string) => { + setLoading(true); + setError(null); + + try { + const initialResponse = await fetch(`/api/projects/${projectId}/resume`, { + method: 'POST' + }); + + if (!initialResponse.ok) { + throw new Error('Failed to get initial session'); + } + + const initialResult = await initialResponse.json(); + const initialData = initialResult.data || initialResult; + + const connectedSandbox = await connectToSandbox({ + session: initialData.sandboxSession, + getSession: async (id: string) => { + const response = await fetch(`/api/projects/${projectId}/resume`, { + method: 'POST' + }); + const result = await response.json(); + const data = result.data || result; + return data.sandboxSession; + } + }); + + console.log('🎉 Successfully connected to sandbox:', connectedSandbox); + setSandbox(connectedSandbox); + setSandboxSession(initialData.sandboxSession); + } catch (err) { + console.error('Failed to connect to sandbox:', err); + setError('Failed to connect to sandbox'); + throw err; + } finally { + setLoading(false); + } + }, []); + + const disconnect = useCallback(async () => { + if (sandbox) { + try { + await sandbox.disconnect(); + setSandbox(null); + setSandboxSession(null); + setSetupState({ + status: 'NOT_STARTED', + currentStepIndex: 0, + totalSteps: 0, + currentStepName: '' + }); + setError(null); + + // Clear all listeners + setPortOpenListeners(new Set()); + setPortCloseListeners(new Set()); + } catch (err) { + console.error('Failed to disconnect from sandbox:', err); + throw err; + } + } + }, [sandbox]); + + // Event handler registration + const onPortOpen = useCallback((callback: (portInfo: any) => void) => { + setPortOpenListeners(prev => new Set([...prev, callback])); + + // Return cleanup function + return () => { + setPortOpenListeners(prev => { + const newSet = new Set(prev); + newSet.delete(callback); + return newSet; + }); + }; + }, []); + + const onPortClose = useCallback((callback: (port: number) => void) => { + setPortCloseListeners(prev => new Set([...prev, callback])); + + // Return cleanup function + return () => { + setPortCloseListeners(prev => { + const newSet = new Set(prev); + newSet.delete(callback); + return newSet; + }); + }; + }, []); + + // Set up sandbox event listeners when sandbox is available + useEffect(() => { + if (!sandbox) return; + + console.log('🔗 Setting up sandbox event listeners...'); + + // Set up port listeners + const portOpenListener = sandbox.ports.onDidPortOpen((portInfo: any) => { + console.log('🔌 Port opened:', portInfo); + portOpenListeners.forEach(callback => callback(portInfo)); + }); + + const portCloseListener = sandbox.ports.onDidPortClose((port: number) => { + console.log('🔌 Port closed:', port); + portCloseListeners.forEach(callback => callback(port)); + }); + + // Initial setup check + checkSetupStatus(); + + // Setup monitoring interval + let setupInterval: NodeJS.Timeout | null = null; + if (setupState.status === 'RUNNING' || setupState.status === 'NOT_STARTED') { + setupInterval = setInterval(() => { + console.log('⏰ Checking setup status...'); + checkSetupStatus(); + }, 2000); + } + + return () => { + console.log('🛑 Cleaning up sandbox event listeners'); + if (portOpenListener) portOpenListener.dispose?.(); + if (portCloseListener) portCloseListener.dispose?.(); + if (setupInterval) clearInterval(setupInterval); + }; + }, [sandbox, setupState.status, checkSetupStatus, portOpenListeners, portCloseListeners]); + + const contextValue: SandboxContextValue = { + sandbox, + sandboxSession, + loading, + error, + setupState, + connectToSandboxInstance, + disconnect, + checkSetupStatus, + onPortOpen, + onPortClose, + }; + + return ( + + {children} + + ); +} \ No newline at end of file diff --git a/app/favicon.ico b/app/favicon.ico new file mode 100644 index 0000000..718d6fe Binary files /dev/null and b/app/favicon.ico differ diff --git a/app/globals.css b/app/globals.css new file mode 100644 index 0000000..a2dc41e --- /dev/null +++ b/app/globals.css @@ -0,0 +1,26 @@ +@import "tailwindcss"; + +:root { + --background: #ffffff; + --foreground: #171717; +} + +@theme inline { + --color-background: var(--background); + --color-foreground: var(--foreground); + --font-sans: var(--font-geist-sans); + --font-mono: var(--font-geist-mono); +} + +@media (prefers-color-scheme: dark) { + :root { + --background: #0a0a0a; + --foreground: #ededed; + } +} + +body { + background: var(--background); + color: var(--foreground); + font-family: Arial, Helvetica, sans-serif; +} diff --git a/app/hooks/useAuth.ts b/app/hooks/useAuth.ts new file mode 100644 index 0000000..981422c --- /dev/null +++ b/app/hooks/useAuth.ts @@ -0,0 +1,120 @@ +'use client'; + +import { useState, useEffect } from 'react'; + +interface User { + id: string; + username: string; + role: string; +} + +interface UseAuthReturn { + user: User | null; + loading: boolean; + login: (username: string, password: string) => Promise; + logout: () => Promise; + error: string | null; +} + +export function useAuth(): UseAuthReturn { + const [user, setUser] = useState(null); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + + useEffect(() => { + checkAuth(); + }, []); + + const checkAuth = async () => { + try { + const response = await fetch('/api/auth/me'); + if (response.ok) { + const userData = await response.json(); + setUser(userData.user); + } else if (response.status === 401) { + // Expected: no session exists, trigger auto-login + await autoLogin(); + } else { + console.error('Unexpected auth check error:', response.status); + await autoLogin(); + } + } catch (err) { + console.error('Auth check failed:', err); + // Attempt auto-login on network errors too + await autoLogin(); + } finally { + setLoading(false); + } + }; + + const autoLogin = async () => { + try { + const response = await fetch('/api/auth/auto-login', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + }); + + if (response.ok) { + const data = await response.json(); + setUser(data.user); + } else { + console.error('Auto-login failed with status:', response.status); + const errorData = await response.json(); + console.error('Error details:', errorData); + } + } catch (err) { + console.error('Auto-login failed:', err); + } + }; + + const login = async (username: string, password: string) => { + setLoading(true); + setError(null); + + try { + const response = await fetch('/api/auth/login', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ username, password }), + }); + + const data = await response.json(); + + if (response.ok) { + setUser(data.user); + } else { + setError(data.error || 'Login failed'); + throw new Error(data.error || 'Login failed'); + } + } catch (err) { + if (err instanceof Error && err.message !== 'Login failed') { + setError('Network error occurred'); + } + throw err; + } finally { + setLoading(false); + } + }; + + const logout = async () => { + try { + await fetch('/api/auth/logout', { method: 'POST' }); + setUser(null); + } catch (err) { + console.error('Logout failed:', err); + throw err; + } + }; + + return { + user, + loading, + login, + logout, + error, + }; +} \ No newline at end of file diff --git a/app/hooks/useCodeSandbox.ts b/app/hooks/useCodeSandbox.ts new file mode 100644 index 0000000..00ee992 --- /dev/null +++ b/app/hooks/useCodeSandbox.ts @@ -0,0 +1,177 @@ +'use client'; + +import { useState, useEffect, useCallback } from 'react'; +import { connectToSandbox } from '@codesandbox/sdk/browser'; + +interface SandboxSession { + url: string; +} + +interface TaskState { + status: 'RUNNING' | 'FINISHED' | 'ERROR' | 'STOPPED' | 'UNKNOWN' | 'LOADING'; + portActive: boolean; +} + +interface SetupState { + status: 'NOT_STARTED' | 'RUNNING' | 'FINISHED' | 'ERROR'; + currentStepIndex: number; + totalSteps: number; + currentStepName: string; +} + +interface UseCodeSandboxReturn { + sandbox: any; + sandboxSession: SandboxSession | null; + loading: boolean; + error: string | null; + setupState: SetupState; + connectToSandboxInstance: (projectId: string, sandboxId: string) => Promise; + disconnect: () => Promise; + checkSetupStatus: () => Promise; +} + +export function useCodeSandbox(): UseCodeSandboxReturn { + const [sandbox, setSandbox] = useState(null); + const [sandboxSession, setSandboxSession] = useState(null); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(null); + const [setupState, setSetupState] = useState({ + status: 'NOT_STARTED', + currentStepIndex: 0, + totalSteps: 0, + currentStepName: '' + }); + + const checkSetupStatus = useCallback(async () => { + if (!sandbox) return; + + try { + console.log('🔍 Checking setup status...'); + + const steps = sandbox.setup ? await sandbox.setup.getSteps() : null; + + if (steps && steps.length > 0) { + console.log('📊 Setup steps:', steps); + + let currentStepIndex = 0; + let status = 'FINISHED'; + let currentStepName = ''; + + for (let i = 0; i < steps.length; i++) { + const step = steps[i]; + if (step.status === 'RUNNING') { + currentStepIndex = i; + status = 'RUNNING'; + currentStepName = step.name || `Step ${i + 1}`; + break; + } else if (step.status === 'ERROR') { + currentStepIndex = i; + status = 'ERROR'; + currentStepName = step.name || `Step ${i + 1} (Error)`; + break; + } else if (step.status === 'PENDING') { + if (status === 'FINISHED') { + status = 'NOT_STARTED'; + currentStepIndex = 0; + currentStepName = ''; + } + } + } + + setSetupState({ + status: status as 'RUNNING' | 'FINISHED' | 'ERROR' | 'NOT_STARTED', + currentStepIndex, + totalSteps: steps.length, + currentStepName + }); + } else { + console.log('No setup steps found, assuming setup is finished'); + setSetupState({ + status: 'FINISHED', + currentStepIndex: 0, + totalSteps: 0, + currentStepName: '' + }); + } + } catch (err) { + console.error('💥 Failed to check setup status:', err); + setSetupState({ + status: 'ERROR', + currentStepIndex: 0, + totalSteps: 0, + currentStepName: 'Setup check failed' + }); + } + }, [sandbox]); + + const connectToSandboxInstance = useCallback(async (projectId: string, sandboxId: string) => { + setLoading(true); + setError(null); + + try { + const initialResponse = await fetch(`/api/projects/${projectId}/resume`, { + method: 'POST' + }); + + if (!initialResponse.ok) { + throw new Error('Failed to get initial session'); + } + + const initialResult = await initialResponse.json(); + const initialData = initialResult.data || initialResult; + + const connectedSandbox = await connectToSandbox({ + session: initialData.sandboxSession, + getSession: async (id: string) => { + const response = await fetch(`/api/projects/${projectId}/resume`, { + method: 'POST' + }); + const result = await response.json(); + const data = result.data || result; + return data.sandboxSession; + } + }); + + console.log('🎉 Successfully connected to sandbox:', connectedSandbox); + setSandbox(connectedSandbox); + setSandboxSession(initialData.sandboxSession); + } catch (err) { + console.error('Failed to connect to sandbox:', err); + setError('Failed to connect to sandbox'); + throw err; + } finally { + setLoading(false); + } + }, []); + + const disconnect = useCallback(async () => { + if (sandbox) { + try { + await sandbox.disconnect(); + setSandbox(null); + setSandboxSession(null); + setSetupState({ + status: 'NOT_STARTED', + currentStepIndex: 0, + totalSteps: 0, + currentStepName: '' + }); + setError(null); + } catch (err) { + console.error('Failed to disconnect from sandbox:', err); + throw err; + } + } + }, [sandbox]); + + return { + sandbox, + sandboxSession, + loading, + error, + setupState, + connectToSandboxInstance, + disconnect, + checkSetupStatus, + }; +} \ No newline at end of file diff --git a/app/hooks/useProject.ts b/app/hooks/useProject.ts new file mode 100644 index 0000000..69fb1e9 --- /dev/null +++ b/app/hooks/useProject.ts @@ -0,0 +1,69 @@ +'use client'; + +import { useState, useEffect } from 'react'; + +interface Project { + id: string; + name: string; + createdAt: string; + sandboxId: string; + githubRepoUrl?: string; +} + +interface UseProjectReturn { + project: Project | null; + loading: boolean; + error: string | null; + fetchProject: (id: string) => Promise; +} + +export function useProject(projectId?: string): UseProjectReturn { + const [project, setProject] = useState(null); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + + const fetchProject = async (id: string) => { + try { + setLoading(true); + setError(null); + + const response = await fetch(`/api/projects/${id}`); + if (!response.ok) { + if (response.status === 404) { + setError('Project not found'); + } else if (response.status === 401) { + setError('Authentication required'); + } else { + setError('Failed to load project'); + } + return; + } + + const result = await response.json(); + + if (result.data) { + setProject(result.data); + } else { + setProject(result); + } + } catch (err) { + setError('Failed to load project'); + console.error('Failed to fetch project:', err); + } finally { + setLoading(false); + } + }; + + useEffect(() => { + if (projectId) { + fetchProject(projectId); + } + }, [projectId]); + + return { + project, + loading, + error, + fetchProject, + }; +} \ No newline at end of file diff --git a/app/hooks/useProjectCreation.ts b/app/hooks/useProjectCreation.ts new file mode 100644 index 0000000..8268954 --- /dev/null +++ b/app/hooks/useProjectCreation.ts @@ -0,0 +1,87 @@ +'use client'; + +import { useState, useCallback } from 'react'; + +interface ProgressStep { + id: string; + message: string; + status: 'pending' | 'in_progress' | 'completed' | 'error'; +} + +interface UseProjectCreationReturn { + isCreating: boolean; + progress: ProgressStep[]; + error: string | null; + createProjectWithStream: (name: string) => Promise; + resetCreation: () => void; +} + +export function useProjectCreation(): UseProjectCreationReturn { + const [isCreating, setIsCreating] = useState(false); + const [progress, setProgress] = useState([]); + const [error, setError] = useState(null); + + const createProjectWithStream = useCallback(async (name: string): Promise => { + if (!name.trim()) { + throw new Error('Project name is required'); + } + + setIsCreating(true); + setError(null); + setProgress([]); + + return new Promise((resolve, reject) => { + const eventSource = new EventSource(`/api/projects/create-stream?name=${encodeURIComponent(name.trim())}`); + + eventSource.onmessage = (event) => { + const data = JSON.parse(event.data); + + if (data.type === 'progress') { + setProgress(prev => { + const newProgress = [...prev]; + const existingIndex = newProgress.findIndex(step => step.id === data.step.id); + + if (existingIndex >= 0) { + newProgress[existingIndex] = data.step; + } else { + newProgress.push(data.step); + } + + return newProgress; + }); + } else if (data.type === 'success') { + eventSource.close(); + setIsCreating(false); + resolve(data.projectId); + } else if (data.type === 'error') { + eventSource.close(); + setIsCreating(false); + setError(data.message); + reject(new Error(data.message)); + } + }; + + eventSource.onerror = () => { + eventSource.close(); + setIsCreating(false); + const errorMessage = 'Connection to server lost. Please try again.'; + setError(errorMessage); + reject(new Error(errorMessage)); + }; + }); + }, []); + + const resetCreation = useCallback(() => { + setProgress([]); + setError(null); + setIsCreating(false); + }, []); + + return { + isCreating, + progress, + error, + createProjectWithStream, + resetCreation, + }; +} \ No newline at end of file diff --git a/app/hooks/useProjects.ts b/app/hooks/useProjects.ts new file mode 100644 index 0000000..3e8599a --- /dev/null +++ b/app/hooks/useProjects.ts @@ -0,0 +1,84 @@ +'use client'; + +import { useState, useEffect } from 'react'; + +interface Project { + id: string; + name: string; + createdAt: string; + sandboxId?: string; + githubRepoUrl?: string; +} + +interface UseProjectsReturn { + projects: Project[]; + loading: boolean; + error: string | null; + fetchProjects: () => Promise; + createProject: (name: string) => Promise; +} + +export function useProjects(): UseProjectsReturn { + const [projects, setProjects] = useState([]); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + + const fetchProjects = async () => { + try { + setError(null); + const response = await fetch('/api/projects'); + const result = await response.json(); + + if (result.data) { + setProjects(result.data); + } else { + setProjects(Array.isArray(result) ? result : []); + } + } catch (err) { + console.error('Failed to fetch projects:', err); + setError('Failed to fetch projects'); + setProjects([]); + } finally { + setLoading(false); + } + }; + + const createProject = async (name: string): Promise => { + if (!name.trim()) { + throw new Error('Project name is required'); + } + + const response = await fetch('/api/projects', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ name: name.trim() }), + }); + + if (!response.ok) { + const error = await response.json(); + throw new Error(error.message || 'Failed to create project'); + } + + const result = await response.json(); + const projectId = result.data?.id || result.id; + + // Refresh projects list after creation + await fetchProjects(); + + return projectId; + }; + + useEffect(() => { + fetchProjects(); + }, []); + + return { + projects, + loading, + error, + fetchProjects, + createProject, + }; +} \ No newline at end of file diff --git a/app/hooks/useSandboxManager.ts b/app/hooks/useSandboxManager.ts new file mode 100644 index 0000000..f3a094a --- /dev/null +++ b/app/hooks/useSandboxManager.ts @@ -0,0 +1,202 @@ +'use client'; + +import { useEffect, useState } from 'react'; +import { useCodeSandbox } from './useCodeSandbox'; +import { useSandboxTasks } from './useSandboxTasks'; +import { useSandboxPreview } from './useSandboxPreview'; + +interface UseSandboxManagerReturn { + // CodeSandbox connection + sandbox: any; + sandboxSession: any; + sandboxLoading: boolean; + sandboxError: string | null; + setupState: any; + connectToSandboxInstance: (projectId: string, sandboxId: string) => Promise; + disconnectFromSandbox: () => Promise; + + // Tasks + devServerTask: any; + vscodeTask: any; + taskLoading: boolean; + vscodeTaskLoading: boolean; + startDevServer: () => Promise; + restartDevServer: () => Promise; + stopDevServer: () => Promise; + startVscode: () => Promise; + restartVscode: () => Promise; + stopVscode: () => Promise; + + // Previews + previewState: any; + vscodeState: any; + previewContainerRef: React.RefObject; + vscodeContainerRef: React.RefObject; +} + +export function useSandboxManager(): UseSandboxManagerReturn { + const [vscodeUserInteracted, setVscodeUserInteracted] = useState(false); + + const { + sandbox, + sandboxSession, + loading: sandboxLoading, + error: sandboxError, + setupState, + connectToSandboxInstance, + disconnect, + checkSetupStatus, + } = useCodeSandbox(); + + const setupFinished = setupState.status === 'FINISHED'; + + const { + devServerTask, + vscodeTask, + taskLoading, + vscodeTaskLoading, + checkDevServerStatus, + checkVscodeStatus, + startDevServer: _startDevServer, + restartDevServer, + stopDevServer, + startVscode: _startVscode, + restartVscode, + stopVscode, + } = useSandboxTasks(sandbox, setupFinished); + + const { + previewState, + vscodeState, + previewContainerRef, + vscodeContainerRef, + createSandboxPreview, + createVscodePreview, + destroyPreview, + destroyVscodePreview, + } = useSandboxPreview(sandbox); + + // Auto-monitor setup and tasks when sandbox is connected + useEffect(() => { + if (sandbox) { + console.log('🔗 Sandbox connected, starting setup and task monitoring...'); + checkSetupStatus(); + checkDevServerStatus(); + checkVscodeStatus(); + + // Set up port listeners + const portOpenListener = sandbox.ports.onDidPortOpen((portInfo: any) => { + console.log('🔌 Port opened:', portInfo); + if (portInfo.port === 5173) { + console.log('✅ Dev server port 5173 opened'); + checkDevServerStatus(); + } else if (portInfo.port === 8080) { + console.log('✅ VSCode port 8080 opened'); + checkVscodeStatus(); + } + }); + + const portCloseListener = sandbox.ports.onDidPortClose((port: number) => { + console.log('🔌 Port closed:', port); + if (port === 5173) { + console.log('❌ Dev server port 5173 closed'); + checkDevServerStatus(); + } else if (port === 8080) { + console.log('❌ VSCode port 8080 closed'); + checkVscodeStatus(); + } + }); + + // Setup monitoring + let setupInterval: NodeJS.Timeout | null = null; + if (setupState.status === 'RUNNING' || setupState.status === 'NOT_STARTED') { + setupInterval = setInterval(() => { + console.log('⏰ Checking setup status...'); + checkSetupStatus(); + }, 2000); + } + + return () => { + console.log('🛑 Cleaning up port listeners and setup monitoring'); + if (portOpenListener) portOpenListener.dispose?.(); + if (portCloseListener) portCloseListener.dispose?.(); + if (setupInterval) clearInterval(setupInterval); + }; + } + }, [sandbox, setupState.status, checkSetupStatus, checkDevServerStatus, checkVscodeStatus]); + + // Auto-create preview when dev server port becomes active and setup is finished + useEffect(() => { + if (sandbox && devServerTask.portActive && !previewState.preview && !previewState.loading && setupFinished) { + console.log('🎬 Port is active and setup finished, creating preview...'); + createSandboxPreview(); + } else if (!devServerTask.portActive && previewState.preview) { + console.log('🛑 Port is inactive, destroying preview...'); + destroyPreview(); + } + }, [sandbox, devServerTask.portActive, previewState.preview, previewState.loading, setupFinished, createSandboxPreview, destroyPreview]); + + // Auto-create VSCode when port becomes active and setup is finished + useEffect(() => { + if (sandbox && vscodeTask.portActive && !vscodeState.preview && !vscodeState.loading && setupFinished) { + console.log('🎬 VSCode port is active and setup finished, creating VSCode preview...'); + createVscodePreview(); + } else if (!vscodeTask.portActive && vscodeState.preview) { + console.log('🛑 VSCode port is inactive, destroying VSCode preview...'); + destroyVscodePreview(); + } + }, [sandbox, vscodeTask.portActive, vscodeState.preview, vscodeState.loading, setupFinished, createVscodePreview, destroyVscodePreview]); + + // Auto-start VSCode on initial load if not user-interacted + useEffect(() => { + if (sandbox && !vscodeTask.portActive && setupFinished && !vscodeTaskLoading && !vscodeUserInteracted) { + console.log('🚀 Auto-starting VSCode server...'); + _startVscode(); + } + }, [sandbox, vscodeTask.portActive, setupFinished, vscodeTaskLoading, vscodeUserInteracted, _startVscode]); + + const disconnectFromSandbox = async () => { + destroyPreview(); + destroyVscodePreview(); + await disconnect(); + setVscodeUserInteracted(false); + }; + + const startDevServer = async () => { + await _startDevServer(); + }; + + const startVscode = async () => { + setVscodeUserInteracted(true); + await _startVscode(); + }; + + return { + // CodeSandbox connection + sandbox, + sandboxSession, + sandboxLoading, + sandboxError, + setupState, + connectToSandboxInstance, + disconnectFromSandbox, + + // Tasks + devServerTask, + vscodeTask, + taskLoading, + vscodeTaskLoading, + startDevServer, + restartDevServer, + stopDevServer, + startVscode, + restartVscode, + stopVscode, + + // Previews + previewState, + vscodeState, + previewContainerRef, + vscodeContainerRef, + }; +} \ No newline at end of file diff --git a/app/hooks/useSandboxPreview.ts b/app/hooks/useSandboxPreview.ts new file mode 100644 index 0000000..d9e7054 --- /dev/null +++ b/app/hooks/useSandboxPreview.ts @@ -0,0 +1,223 @@ +'use client'; + +import { useState, useCallback, useRef, useEffect } from 'react'; +import { createPreview } from '@codesandbox/sdk/browser'; + +interface PreviewState { + loading: boolean; + connected: boolean; + portClosed: boolean; + preview: any | null; +} + +interface UseSandboxPreviewReturn { + previewState: PreviewState; + vscodeState: PreviewState; + previewContainerRef: React.RefObject; + vscodeContainerRef: React.RefObject; + createSandboxPreview: () => Promise; + createVscodePreview: () => Promise; + destroyPreview: () => void; + destroyVscodePreview: () => void; +} + +export function useSandboxPreview(sandbox: any): UseSandboxPreviewReturn { + const [previewState, setPreviewState] = useState({ + loading: false, + connected: false, + portClosed: false, + preview: null + }); + + const [vscodeState, setVscodeState] = useState({ + loading: false, + connected: false, + portClosed: false, + preview: null + }); + + const previewContainerRef = useRef(null); + const vscodeContainerRef = useRef(null); + + // Manage preview iframe insertion + useEffect(() => { + const container = previewContainerRef.current; + if (!container || !previewState.preview?.iframe) return; + + if (!container.contains(previewState.preview.iframe)) { + container.appendChild(previewState.preview.iframe); + } + }, [previewState.preview]); + + // Manage VSCode iframe insertion + useEffect(() => { + const container = vscodeContainerRef.current; + if (!container || !vscodeState.preview?.iframe) return; + + if (!container.contains(vscodeState.preview.iframe)) { + container.appendChild(vscodeState.preview.iframe); + } + }, [vscodeState.preview]); + + const createSandboxPreview = useCallback(async () => { + if (!sandbox) return; + + setPreviewState(prev => ({ ...prev, loading: true })); + + try { + console.log('🎬 Creating preview for port 5173...'); + + const previewUrl = sandbox.hosts.getUrl(5173); + console.log('🔗 Preview URL:', previewUrl); + + const preview = createPreview(previewUrl); + console.log('✅ Preview created:', preview); + + preview.onMessage((message: any) => { + console.log('📨 Preview message:', message); + switch (message.type) { + case 'SET_URL': + console.log('🔗 URL changed:', message.url); + break; + case 'RELOAD': + console.log('🔄 Preview reloaded'); + break; + case 'PREVIEW_UNLOADING': + console.log('📤 Preview unloading'); + break; + } + }); + + setPreviewState({ + loading: false, + connected: true, + portClosed: false, + preview: preview + }); + + if (preview.iframe) { + preview.iframe.style.width = '100%'; + preview.iframe.style.height = '100%'; + preview.iframe.style.border = 'none'; + preview.iframe.style.borderRadius = '0.5rem'; + } + + } catch (err) { + console.error('💥 Failed to create preview:', err); + setPreviewState(prev => ({ + ...prev, + loading: false, + connected: false + })); + } + }, [sandbox]); + + const createVscodePreview = useCallback(async () => { + if (!sandbox) return; + + setVscodeState(prev => ({ ...prev, loading: true })); + + try { + console.log('🎬 Creating VSCode preview for port 8080...'); + + const baseUrl = sandbox.hosts.getUrl(8080); + const previewUrl = `${baseUrl}&folder=${encodeURIComponent("/project/workspace/app")}`; + console.log('🔗 VSCode Preview URL:', previewUrl); + + const preview = createPreview(previewUrl); + console.log('✅ VSCode Preview created:', preview); + + preview.onMessage((message: any) => { + console.log('📨 VSCode Preview message:', message); + switch (message.type) { + case 'SET_URL': + console.log('🔗 VSCode URL changed:', message.url); + break; + case 'RELOAD': + console.log('🔄 VSCode Preview reloaded'); + break; + case 'PREVIEW_UNLOADING': + console.log('📤 VSCode Preview unloading'); + break; + } + }); + + setVscodeState({ + loading: false, + connected: true, + portClosed: false, + preview: preview + }); + + if (preview.iframe) { + preview.iframe.style.width = '100%'; + preview.iframe.style.height = '100%'; + preview.iframe.style.border = 'none'; + preview.iframe.style.borderRadius = '0.5rem'; + } + + } catch (err) { + console.error('💥 Failed to create VSCode preview:', err); + setVscodeState(prev => ({ + ...prev, + loading: false, + connected: false + })); + } + }, [sandbox]); + + const destroyPreview = useCallback(() => { + if (previewState.preview) { + try { + if (typeof previewState.preview.destroy === 'function') { + previewState.preview.destroy(); + } + if (previewState.preview.iframe && previewState.preview.iframe.parentNode) { + previewState.preview.iframe.parentNode.removeChild(previewState.preview.iframe); + } + } catch (error) { + console.warn('Error cleaning up preview:', error); + } + } + + setPreviewState({ + loading: false, + connected: false, + portClosed: false, + preview: null + }); + }, [previewState.preview]); + + const destroyVscodePreview = useCallback(() => { + if (vscodeState.preview) { + try { + if (typeof vscodeState.preview.destroy === 'function') { + vscodeState.preview.destroy(); + } + if (vscodeState.preview.iframe && vscodeState.preview.iframe.parentNode) { + vscodeState.preview.iframe.parentNode.removeChild(vscodeState.preview.iframe); + } + } catch (error) { + console.warn('Error cleaning up VSCode preview:', error); + } + } + + setVscodeState({ + loading: false, + connected: false, + portClosed: false, + preview: null + }); + }, [vscodeState.preview]); + + return { + previewState, + vscodeState, + previewContainerRef, + vscodeContainerRef, + createSandboxPreview, + createVscodePreview, + destroyPreview, + destroyVscodePreview, + }; +} \ No newline at end of file diff --git a/app/hooks/useSandboxPreview.v2.ts b/app/hooks/useSandboxPreview.v2.ts new file mode 100644 index 0000000..3498455 --- /dev/null +++ b/app/hooks/useSandboxPreview.v2.ts @@ -0,0 +1,272 @@ +'use client'; + +import { useState, useCallback, useRef, useEffect } from 'react'; +import { createPreview } from '@codesandbox/sdk/browser'; +import { useSandboxContext } from '../contexts/SandboxContext'; + +interface PreviewState { + loading: boolean; + connected: boolean; + portClosed: boolean; + preview: any | null; +} + +interface UseSandboxPreviewReturn { + previewState: PreviewState; + vscodeState: PreviewState; + previewContainerRef: React.RefObject; + vscodeContainerRef: React.RefObject; + createSandboxPreview: () => Promise; + createVscodePreview: () => Promise; + destroyPreview: () => void; + destroyVscodePreview: () => void; +} + +export function useSandboxPreview(): UseSandboxPreviewReturn { + const { sandbox, onPortOpen, onPortClose } = useSandboxContext(); + + const [previewState, setPreviewState] = useState({ + loading: false, + connected: false, + portClosed: false, + preview: null + }); + + const [vscodeState, setVscodeState] = useState({ + loading: false, + connected: false, + portClosed: false, + preview: null + }); + + const previewContainerRef = useRef(null); + const vscodeContainerRef = useRef(null); + + // Set up port event listeners for preview state management + useEffect(() => { + if (!sandbox) return; + + const cleanupPortOpen = onPortOpen((portInfo: any) => { + if (portInfo.port === 5173) { + console.log('✅ Dev server port 5173 opened'); + setPreviewState(prev => ({ + ...prev, + portClosed: false, + connected: true + })); + } else if (portInfo.port === 8080) { + console.log('✅ VSCode port 8080 opened'); + setVscodeState(prev => ({ + ...prev, + portClosed: false, + connected: true + })); + } + }); + + const cleanupPortClose = onPortClose((port: number) => { + if (port === 5173) { + console.log('❌ Dev server port 5173 closed'); + setPreviewState(prev => ({ + ...prev, + portClosed: true, + connected: false + })); + } else if (port === 8080) { + console.log('❌ VSCode port 8080 closed'); + setVscodeState(prev => ({ + ...prev, + portClosed: true, + connected: false + })); + } + }); + + return () => { + cleanupPortOpen(); + cleanupPortClose(); + }; + }, [sandbox, onPortOpen, onPortClose]); + + // Manage preview iframe insertion + useEffect(() => { + const container = previewContainerRef.current; + if (!container || !previewState.preview?.iframe) return; + + if (!container.contains(previewState.preview.iframe)) { + container.appendChild(previewState.preview.iframe); + } + }, [previewState.preview]); + + // Manage VSCode iframe insertion + useEffect(() => { + const container = vscodeContainerRef.current; + if (!container || !vscodeState.preview?.iframe) return; + + if (!container.contains(vscodeState.preview.iframe)) { + container.appendChild(vscodeState.preview.iframe); + } + }, [vscodeState.preview]); + + const createSandboxPreview = useCallback(async () => { + if (!sandbox) return; + + setPreviewState(prev => ({ ...prev, loading: true })); + + try { + console.log('🎬 Creating preview for port 5173...'); + + const previewUrl = sandbox.hosts.getUrl(5173); + console.log('🔗 Preview URL:', previewUrl); + + const preview = createPreview(previewUrl); + console.log('✅ Preview created:', preview); + + preview.onMessage((message: any) => { + console.log('📨 Preview message:', message); + switch (message.type) { + case 'SET_URL': + console.log('🔗 URL changed:', message.url); + break; + case 'RELOAD': + console.log('🔄 Preview reloaded'); + break; + case 'PREVIEW_UNLOADING': + console.log('📤 Preview unloading'); + break; + } + }); + + setPreviewState({ + loading: false, + connected: true, + portClosed: false, + preview: preview + }); + + if (preview.iframe) { + preview.iframe.style.width = '100%'; + preview.iframe.style.height = '100%'; + preview.iframe.style.border = 'none'; + preview.iframe.style.borderRadius = '0.5rem'; + } + + } catch (err) { + console.error('💥 Failed to create preview:', err); + setPreviewState(prev => ({ + ...prev, + loading: false, + connected: false + })); + } + }, [sandbox]); + + const createVscodePreview = useCallback(async () => { + if (!sandbox) return; + + setVscodeState(prev => ({ ...prev, loading: true })); + + try { + console.log('🎬 Creating VSCode preview for port 8080...'); + + const baseUrl = sandbox.hosts.getUrl(8080); + const previewUrl = `${baseUrl}&folder=${encodeURIComponent("/project/workspace/app")}`; + console.log('🔗 VSCode Preview URL:', previewUrl); + + const preview = createPreview(previewUrl); + console.log('✅ VSCode Preview created:', preview); + + preview.onMessage((message: any) => { + console.log('📨 VSCode Preview message:', message); + switch (message.type) { + case 'SET_URL': + console.log('🔗 VSCode URL changed:', message.url); + break; + case 'RELOAD': + console.log('🔄 VSCode Preview reloaded'); + break; + case 'PREVIEW_UNLOADING': + console.log('📤 VSCode Preview unloading'); + break; + } + }); + + setVscodeState({ + loading: false, + connected: true, + portClosed: false, + preview: preview + }); + + if (preview.iframe) { + preview.iframe.style.width = '100%'; + preview.iframe.style.height = '100%'; + preview.iframe.style.border = 'none'; + preview.iframe.style.borderRadius = '0.5rem'; + } + + } catch (err) { + console.error('💥 Failed to create VSCode preview:', err); + setVscodeState(prev => ({ + ...prev, + loading: false, + connected: false + })); + } + }, [sandbox]); + + const destroyPreview = useCallback(() => { + if (previewState.preview) { + try { + if (typeof previewState.preview.destroy === 'function') { + previewState.preview.destroy(); + } + if (previewState.preview.iframe && previewState.preview.iframe.parentNode) { + previewState.preview.iframe.parentNode.removeChild(previewState.preview.iframe); + } + } catch (error) { + console.warn('Error cleaning up preview:', error); + } + } + + setPreviewState({ + loading: false, + connected: false, + portClosed: false, + preview: null + }); + }, [previewState.preview]); + + const destroyVscodePreview = useCallback(() => { + if (vscodeState.preview) { + try { + if (typeof vscodeState.preview.destroy === 'function') { + vscodeState.preview.destroy(); + } + if (vscodeState.preview.iframe && vscodeState.preview.iframe.parentNode) { + vscodeState.preview.iframe.parentNode.removeChild(vscodeState.preview.iframe); + } + } catch (error) { + console.warn('Error cleaning up VSCode preview:', error); + } + } + + setVscodeState({ + loading: false, + connected: false, + portClosed: false, + preview: null + }); + }, [vscodeState.preview]); + + return { + previewState, + vscodeState, + previewContainerRef, + vscodeContainerRef, + createSandboxPreview, + createVscodePreview, + destroyPreview, + destroyVscodePreview, + }; +} \ No newline at end of file diff --git a/app/hooks/useSandboxTasks.ts b/app/hooks/useSandboxTasks.ts new file mode 100644 index 0000000..1000c5f --- /dev/null +++ b/app/hooks/useSandboxTasks.ts @@ -0,0 +1,357 @@ +'use client'; + +import { useState, useCallback } from 'react'; + +interface TaskState { + status: 'RUNNING' | 'FINISHED' | 'ERROR' | 'STOPPED' | 'UNKNOWN' | 'LOADING'; + portActive: boolean; +} + +interface UseSandboxTasksReturn { + devServerTask: TaskState; + vscodeTask: TaskState; + vscodeCommand: any; + taskLoading: boolean; + vscodeTaskLoading: boolean; + checkDevServerStatus: () => Promise; + checkVscodeStatus: () => Promise; + startDevServer: () => Promise; + restartDevServer: () => Promise; + stopDevServer: () => Promise; + startVscode: () => Promise; + restartVscode: () => Promise; + stopVscode: () => Promise; +} + +export function useSandboxTasks(sandbox: any, setupFinished: boolean): UseSandboxTasksReturn { + const [devServerTask, setDevServerTask] = useState({ status: 'UNKNOWN', portActive: false }); + const [vscodeTask, setVscodeTask] = useState({ status: 'LOADING', portActive: false }); + const [vscodeCommand, setVscodeCommand] = useState(null); + const [taskLoading, setTaskLoading] = useState(false); + const [vscodeTaskLoading, setVscodeTaskLoading] = useState(false); + + const findExistingVscodeCommand = useCallback(async () => { + if (!sandbox) return null; + + try { + console.log('🔍 Looking for existing VSCode commands...'); + const allCommands = await sandbox.commands.getAll(); + console.log('📋 All commands:', allCommands); + + const vscodeCmd = allCommands.find((cmd: any) => + cmd.command && cmd.command.includes('code-server') && cmd.command.includes('8080') + ); + + if (vscodeCmd) { + console.log('✅ Found existing VSCode command:', vscodeCmd); + return vscodeCmd; + } else { + console.log('❌ No existing VSCode command found'); + return null; + } + } catch (err) { + console.error('💥 Failed to get commands:', err); + return null; + } + }, [sandbox]); + + const checkDevServerStatus = useCallback(async () => { + if (!sandbox) return; + + try { + console.log('🔍 Checking dev server status...'); + const tasks = await sandbox.tasks.getAll(); + console.log('📋 All tasks:', tasks); + + const devTask = tasks.find((task: any) => task.id === 'dev-server'); + console.log('🎯 Found dev-server task:', devTask); + + if (devTask) { + console.log('📊 Task status:', devTask.status); + + let portActive = false; + try { + console.log('🔌 Checking port availability...'); + const portResult = await Promise.race([ + devTask.waitForPort(), + new Promise((_, reject) => setTimeout(() => reject(new Error('timeout')), 2000)) + ]); + console.log('✅ Port check result:', portResult); + portActive = true; + } catch (portError) { + console.log('❌ Port check failed:', portError instanceof Error ? portError.message : 'Unknown error'); + portActive = false; + } + + console.log('📈 Final task state:', { status: devTask.status, portActive }); + setDevServerTask({ + status: devTask.status || 'UNKNOWN', + portActive + }); + } else { + console.log('❌ No dev-server task found'); + setDevServerTask({ status: 'UNKNOWN', portActive: false }); + } + } catch (err) { + console.error('💥 Failed to check dev server status:', err); + setDevServerTask({ status: 'ERROR', portActive: false }); + } + }, [sandbox]); + + const checkVscodeStatus = useCallback(async () => { + if (!sandbox) return; + + try { + console.log('🔍 Checking VSCode port status...'); + + let portActive = false; + try { + console.log('🔌 Checking port 8080 availability...'); + const portResult = await Promise.race([ + sandbox.ports.waitForPort(8080), + new Promise((_, reject) => setTimeout(() => reject(new Error('timeout')), 2000)) + ]); + console.log('✅ Port 8080 check result:', portResult); + portActive = true; + } catch (portError) { + console.log('❌ Port 8080 check failed:', portError instanceof Error ? portError.message : 'Unknown error'); + portActive = false; + } + + console.log('📈 VSCode port state:', { portActive }); + setVscodeTask({ + status: portActive ? 'RUNNING' : 'STOPPED', + portActive + }); + + if (portActive && !vscodeCommand) { + console.log('🔍 Port is active but no command reference, looking for existing command...'); + const existingCommand = await findExistingVscodeCommand(); + if (existingCommand) { + setVscodeCommand(existingCommand); + console.log('✅ Found and stored existing VSCode command reference'); + } + } + } catch (err) { + console.error('💥 Failed to check VSCode port status:', err); + setVscodeTask({ status: 'ERROR', portActive: false }); + } + }, [sandbox, vscodeCommand, findExistingVscodeCommand]); + + const startDevServer = useCallback(async () => { + if (!sandbox || !setupFinished) { + console.log('❌ Cannot start dev server: setup is still running'); + return; + } + + console.log('🚀 Starting dev server...'); + setTaskLoading(true); + try { + const tasks = await sandbox.tasks.getAll(); + const devTask = tasks.find((task: any) => task.id === 'dev-server'); + console.log('🎯 Task to start:', devTask); + + if (devTask) { + console.log('▶️ Running task...'); + await devTask.run(); + console.log('✅ Task started, checking status...'); + await checkDevServerStatus(); + } else { + console.log('❌ No dev-server task found to start'); + } + } catch (err) { + console.error('💥 Failed to start dev server:', err); + } finally { + setTaskLoading(false); + } + }, [sandbox, setupFinished, checkDevServerStatus]); + + const restartDevServer = useCallback(async () => { + if (!sandbox || !setupFinished) { + console.log('❌ Cannot restart dev server: setup is still running'); + return; + } + + setTaskLoading(true); + try { + const tasks = await sandbox.tasks.getAll(); + const devTask = tasks.find((task: any) => task.id === 'dev-server'); + + if (devTask) { + await devTask.restart(); + await checkDevServerStatus(); + } + } catch (err) { + console.error('Failed to restart dev server:', err); + } finally { + setTaskLoading(false); + } + }, [sandbox, setupFinished, checkDevServerStatus]); + + const stopDevServer = useCallback(async () => { + if (!sandbox || !setupFinished) { + console.log('❌ Cannot stop dev server: setup is still running'); + return; + } + + setTaskLoading(true); + try { + const tasks = await sandbox.tasks.getAll(); + const devTask = tasks.find((task: any) => task.id === 'dev-server'); + + if (devTask) { + await devTask.stop(); + await checkDevServerStatus(); + } + } catch (err) { + console.error('Failed to stop dev server:', err); + } finally { + setTaskLoading(false); + } + }, [sandbox, setupFinished, checkDevServerStatus]); + + const startVscode = useCallback(async () => { + if (!sandbox) return; + + console.log('🚀 Starting VSCode server...'); + setVscodeTaskLoading(true); + try { + let portAlreadyOpen = false; + try { + console.log('🔍 Checking if port 8080 is already open...'); + await Promise.race([ + sandbox.ports.waitForPort(8080), + new Promise((_, reject) => setTimeout(() => reject(new Error('timeout')), 1000)) + ]); + portAlreadyOpen = true; + console.log('✅ Port 8080 is already open, skipping command execution'); + } catch (portError) { + console.log('📝 Port 8080 is not open, will start VSCode server'); + portAlreadyOpen = false; + } + + if (!portAlreadyOpen) { + console.log('▶️ Running code-server command...'); + const command = 'code-server /project/workspace/app --host 0.0.0.0 --port 8080 --auth none --disable-telemetry --user-data-dir /project/workspace/.vscode'; + const cmdInstance = await sandbox.commands.runBackground(command, { + name: 'VSCode Server' + }); + setVscodeCommand(cmdInstance); + console.log('✅ Code-server command started'); + + console.log('⏳ Waiting for port 8080 to open...'); + try { + await sandbox.ports.waitForPort(8080); + console.log('✅ Port 8080 is now open'); + } catch (waitError) { + console.error('❌ Timeout waiting for port 8080:', waitError); + } + } + + await checkVscodeStatus(); + } catch (err) { + console.error('💥 Failed to start VSCode server:', err); + } finally { + setVscodeTaskLoading(false); + } + }, [sandbox, checkVscodeStatus]); + + const restartVscode = useCallback(async () => { + if (!sandbox || !setupFinished) { + console.log('❌ Cannot restart VSCode: setup is still running'); + return; + } + + setVscodeTaskLoading(true); + try { + console.log('🔄 Restarting VSCode server...'); + + const existingCommand = vscodeCommand || await findExistingVscodeCommand(); + if (existingCommand) { + console.log('🛑 Stopping existing VSCode command...'); + try { + await existingCommand.kill(); + console.log('✅ VSCode command stopped'); + } catch (killError) { + console.log('⚠️ Error stopping VSCode command, will continue:', killError); + } + } else { + console.log('ℹ️ No existing VSCode command found to stop'); + } + + await new Promise(resolve => setTimeout(resolve, 1000)); + + console.log('▶️ Starting code-server command...'); + const command = 'code-server /project/workspace/app --host 0.0.0.0 --port 8080 --auth none --disable-telemetry --user-data-dir /project/workspace/.vscode'; + const cmdInstance = await sandbox.commands.runBackground(command, { + name: 'VSCode Server' + }); + setVscodeCommand(cmdInstance); + console.log('✅ Code-server command restarted'); + + console.log('⏳ Waiting for port 8080 to open...'); + try { + await sandbox.ports.waitForPort(8080); + console.log('✅ Port 8080 is now open'); + } catch (waitError) { + console.error('❌ Timeout waiting for port 8080:', waitError); + } + + await checkVscodeStatus(); + } catch (err) { + console.error('💥 Failed to restart VSCode:', err); + } finally { + setVscodeTaskLoading(false); + } + }, [sandbox, setupFinished, vscodeCommand, findExistingVscodeCommand, checkVscodeStatus]); + + const stopVscode = useCallback(async () => { + if (!sandbox || !setupFinished) { + console.log('❌ Cannot stop VSCode: setup is still running'); + return; + } + + setVscodeTaskLoading(true); + try { + console.log('🛑 Stopping VSCode server...'); + + const existingCommand = vscodeCommand || await findExistingVscodeCommand(); + if (existingCommand) { + console.log('🛑 Killing VSCode command...'); + try { + await existingCommand.kill(); + setVscodeCommand(null); + console.log('✅ VSCode command stopped'); + } catch (killError) { + console.log('⚠️ Error stopping VSCode command:', killError); + } + } else { + console.log('ℹ️ No VSCode command found to stop'); + } + + await new Promise(resolve => setTimeout(resolve, 1000)); + + await checkVscodeStatus(); + } catch (err) { + console.error('💥 Failed to stop VSCode:', err); + } finally { + setVscodeTaskLoading(false); + } + }, [sandbox, setupFinished, vscodeCommand, findExistingVscodeCommand, checkVscodeStatus]); + + return { + devServerTask, + vscodeTask, + vscodeCommand, + taskLoading, + vscodeTaskLoading, + checkDevServerStatus, + checkVscodeStatus, + startDevServer, + restartDevServer, + stopDevServer, + startVscode, + restartVscode, + stopVscode, + }; +} \ No newline at end of file diff --git a/app/hooks/useSandboxTasks.v2.ts b/app/hooks/useSandboxTasks.v2.ts new file mode 100644 index 0000000..9def8e0 --- /dev/null +++ b/app/hooks/useSandboxTasks.v2.ts @@ -0,0 +1,397 @@ +'use client'; + +import { useState, useCallback, useEffect } from 'react'; +import { useSandboxContext } from '../contexts/SandboxContext'; + +interface TaskState { + status: 'RUNNING' | 'FINISHED' | 'ERROR' | 'STOPPED' | 'UNKNOWN' | 'LOADING'; + portActive: boolean; +} + +interface UseSandboxTasksReturn { + devServerTask: TaskState; + vscodeTask: TaskState; + vscodeCommand: any; + taskLoading: boolean; + vscodeTaskLoading: boolean; + checkDevServerStatus: () => Promise; + checkVscodeStatus: () => Promise; + startDevServer: () => Promise; + restartDevServer: () => Promise; + stopDevServer: () => Promise; + startVscode: () => Promise; + restartVscode: () => Promise; + stopVscode: () => Promise; +} + +export function useSandboxTasks(): UseSandboxTasksReturn { + const { sandbox, setupState, onPortOpen, onPortClose } = useSandboxContext(); + + const [devServerTask, setDevServerTask] = useState({ status: 'UNKNOWN', portActive: false }); + const [vscodeTask, setVscodeTask] = useState({ status: 'LOADING', portActive: false }); + const [vscodeCommand, setVscodeCommand] = useState(null); + const [taskLoading, setTaskLoading] = useState(false); + const [vscodeTaskLoading, setVscodeTaskLoading] = useState(false); + + const setupFinished = setupState.status === 'FINISHED'; + + const findExistingVscodeCommand = useCallback(async () => { + if (!sandbox) return null; + + try { + console.log('🔍 Looking for existing VSCode commands...'); + const allCommands = await sandbox.commands.getAll(); + console.log('📋 All commands:', allCommands); + + const vscodeCmd = allCommands.find((cmd: any) => + cmd.command && cmd.command.includes('code-server') && cmd.command.includes('8080') + ); + + if (vscodeCmd) { + console.log('✅ Found existing VSCode command:', vscodeCmd); + return vscodeCmd; + } else { + console.log('❌ No existing VSCode command found'); + return null; + } + } catch (err) { + console.error('💥 Failed to get commands:', err); + return null; + } + }, [sandbox]); + + const checkDevServerStatus = useCallback(async () => { + if (!sandbox) return; + + try { + console.log('🔍 Checking dev server status...'); + const tasks = await sandbox.tasks.getAll(); + console.log('📋 All tasks:', tasks); + + const devTask = tasks.find((task: any) => task.id === 'dev-server'); + console.log('🎯 Found dev-server task:', devTask); + + if (devTask) { + console.log('📊 Task status:', devTask.status); + + let portActive = false; + try { + console.log('🔌 Checking port availability...'); + const portResult = await Promise.race([ + devTask.waitForPort(), + new Promise((_, reject) => setTimeout(() => reject(new Error('timeout')), 2000)) + ]); + console.log('✅ Port check result:', portResult); + portActive = true; + } catch (portError) { + console.log('❌ Port check failed:', portError instanceof Error ? portError.message : 'Unknown error'); + portActive = false; + } + + console.log('📈 Final task state:', { status: devTask.status, portActive }); + setDevServerTask({ + status: devTask.status || 'UNKNOWN', + portActive + }); + } else { + console.log('❌ No dev-server task found'); + setDevServerTask({ status: 'UNKNOWN', portActive: false }); + } + } catch (err) { + console.error('💥 Failed to check dev server status:', err); + setDevServerTask({ status: 'ERROR', portActive: false }); + } + }, [sandbox]); + + const checkVscodeStatus = useCallback(async () => { + if (!sandbox) return; + + try { + console.log('🔍 Checking VSCode port status...'); + + let portActive = false; + try { + console.log('🔌 Checking port 8080 availability...'); + const portResult = await Promise.race([ + sandbox.ports.waitForPort(8080), + new Promise((_, reject) => setTimeout(() => reject(new Error('timeout')), 2000)) + ]); + console.log('✅ Port 8080 check result:', portResult); + portActive = true; + } catch (portError) { + console.log('❌ Port 8080 check failed:', portError instanceof Error ? portError.message : 'Unknown error'); + portActive = false; + } + + console.log('📈 VSCode port state:', { portActive }); + setVscodeTask({ + status: portActive ? 'RUNNING' : 'STOPPED', + portActive + }); + + if (portActive && !vscodeCommand) { + console.log('🔍 Port is active but no command reference, looking for existing command...'); + const existingCommand = await findExistingVscodeCommand(); + if (existingCommand) { + setVscodeCommand(existingCommand); + console.log('✅ Found and stored existing VSCode command reference'); + } + } + } catch (err) { + console.error('💥 Failed to check VSCode port status:', err); + setVscodeTask({ status: 'ERROR', portActive: false }); + } + }, [sandbox, vscodeCommand, findExistingVscodeCommand]); + + // Set up port event listeners + useEffect(() => { + if (!sandbox) return; + + // Listen for port events from the context + const cleanupPortOpen = onPortOpen((portInfo: any) => { + if (portInfo.port === 5173) { + console.log('✅ Dev server port 5173 opened'); + checkDevServerStatus(); + } else if (portInfo.port === 8080) { + console.log('✅ VSCode port 8080 opened'); + checkVscodeStatus(); + } + }); + + const cleanupPortClose = onPortClose((port: number) => { + if (port === 5173) { + console.log('❌ Dev server port 5173 closed'); + checkDevServerStatus(); + } else if (port === 8080) { + console.log('❌ VSCode port 8080 closed'); + checkVscodeStatus(); + } + }); + + // Initial status checks + checkDevServerStatus(); + checkVscodeStatus(); + + return () => { + cleanupPortOpen(); + cleanupPortClose(); + }; + }, [sandbox, onPortOpen, onPortClose, checkDevServerStatus, checkVscodeStatus]); + + const startDevServer = useCallback(async () => { + if (!sandbox || !setupFinished) { + console.log('❌ Cannot start dev server: setup is still running'); + return; + } + + console.log('🚀 Starting dev server...'); + setTaskLoading(true); + try { + const tasks = await sandbox.tasks.getAll(); + const devTask = tasks.find((task: any) => task.id === 'dev-server'); + console.log('🎯 Task to start:', devTask); + + if (devTask) { + console.log('▶️ Running task...'); + await devTask.run(); + console.log('✅ Task started, checking status...'); + await checkDevServerStatus(); + } else { + console.log('❌ No dev-server task found to start'); + } + } catch (err) { + console.error('💥 Failed to start dev server:', err); + } finally { + setTaskLoading(false); + } + }, [sandbox, setupFinished, checkDevServerStatus]); + + const restartDevServer = useCallback(async () => { + if (!sandbox || !setupFinished) { + console.log('❌ Cannot restart dev server: setup is still running'); + return; + } + + setTaskLoading(true); + try { + const tasks = await sandbox.tasks.getAll(); + const devTask = tasks.find((task: any) => task.id === 'dev-server'); + + if (devTask) { + await devTask.restart(); + await checkDevServerStatus(); + } + } catch (err) { + console.error('Failed to restart dev server:', err); + } finally { + setTaskLoading(false); + } + }, [sandbox, setupFinished, checkDevServerStatus]); + + const stopDevServer = useCallback(async () => { + if (!sandbox || !setupFinished) { + console.log('❌ Cannot stop dev server: setup is still running'); + return; + } + + setTaskLoading(true); + try { + const tasks = await sandbox.tasks.getAll(); + const devTask = tasks.find((task: any) => task.id === 'dev-server'); + + if (devTask) { + await devTask.stop(); + await checkDevServerStatus(); + } + } catch (err) { + console.error('Failed to stop dev server:', err); + } finally { + setTaskLoading(false); + } + }, [sandbox, setupFinished, checkDevServerStatus]); + + const startVscode = useCallback(async () => { + if (!sandbox) return; + + console.log('🚀 Starting VSCode server...'); + setVscodeTaskLoading(true); + try { + let portAlreadyOpen = false; + try { + console.log('🔍 Checking if port 8080 is already open...'); + await Promise.race([ + sandbox.ports.waitForPort(8080), + new Promise((_, reject) => setTimeout(() => reject(new Error('timeout')), 1000)) + ]); + portAlreadyOpen = true; + console.log('✅ Port 8080 is already open, skipping command execution'); + } catch (portError) { + console.log('📝 Port 8080 is not open, will start VSCode server'); + portAlreadyOpen = false; + } + + if (!portAlreadyOpen) { + console.log('▶️ Running code-server command...'); + const command = 'code-server /project/workspace/app --host 0.0.0.0 --port 8080 --auth none --disable-telemetry --user-data-dir /project/workspace/.vscode'; + const cmdInstance = await sandbox.commands.runBackground(command, { + name: 'VSCode Server' + }); + setVscodeCommand(cmdInstance); + console.log('✅ Code-server command started'); + + console.log('⏳ Waiting for port 8080 to open...'); + try { + await sandbox.ports.waitForPort(8080); + console.log('✅ Port 8080 is now open'); + } catch (waitError) { + console.error('❌ Timeout waiting for port 8080:', waitError); + } + } + + await checkVscodeStatus(); + } catch (err) { + console.error('💥 Failed to start VSCode server:', err); + } finally { + setVscodeTaskLoading(false); + } + }, [sandbox, checkVscodeStatus]); + + const restartVscode = useCallback(async () => { + if (!sandbox || !setupFinished) { + console.log('❌ Cannot restart VSCode: setup is still running'); + return; + } + + setVscodeTaskLoading(true); + try { + console.log('🔄 Restarting VSCode server...'); + + const existingCommand = vscodeCommand || await findExistingVscodeCommand(); + if (existingCommand) { + console.log('🛑 Stopping existing VSCode command...'); + try { + await existingCommand.kill(); + console.log('✅ VSCode command stopped'); + } catch (killError) { + console.log('⚠️ Error stopping VSCode command, will continue:', killError); + } + } else { + console.log('ℹ️ No existing VSCode command found to stop'); + } + + await new Promise(resolve => setTimeout(resolve, 1000)); + + console.log('▶️ Starting code-server command...'); + const command = 'code-server /project/workspace/app --host 0.0.0.0 --port 8080 --auth none --disable-telemetry --user-data-dir /project/workspace/.vscode'; + const cmdInstance = await sandbox.commands.runBackground(command, { + name: 'VSCode Server' + }); + setVscodeCommand(cmdInstance); + console.log('✅ Code-server command restarted'); + + console.log('⏳ Waiting for port 8080 to open...'); + try { + await sandbox.ports.waitForPort(8080); + console.log('✅ Port 8080 is now open'); + } catch (waitError) { + console.error('❌ Timeout waiting for port 8080:', waitError); + } + + await checkVscodeStatus(); + } catch (err) { + console.error('💥 Failed to restart VSCode:', err); + } finally { + setVscodeTaskLoading(false); + } + }, [sandbox, setupFinished, vscodeCommand, findExistingVscodeCommand, checkVscodeStatus]); + + const stopVscode = useCallback(async () => { + if (!sandbox || !setupFinished) { + console.log('❌ Cannot stop VSCode: setup is still running'); + return; + } + + setVscodeTaskLoading(true); + try { + console.log('🛑 Stopping VSCode server...'); + + const existingCommand = vscodeCommand || await findExistingVscodeCommand(); + if (existingCommand) { + console.log('🛑 Killing VSCode command...'); + try { + await existingCommand.kill(); + setVscodeCommand(null); + console.log('✅ VSCode command stopped'); + } catch (killError) { + console.log('⚠️ Error stopping VSCode command:', killError); + } + } else { + console.log('ℹ️ No VSCode command found to stop'); + } + + await new Promise(resolve => setTimeout(resolve, 1000)); + + await checkVscodeStatus(); + } catch (err) { + console.error('💥 Failed to stop VSCode:', err); + } finally { + setVscodeTaskLoading(false); + } + }, [sandbox, setupFinished, vscodeCommand, findExistingVscodeCommand, checkVscodeStatus]); + + return { + devServerTask, + vscodeTask, + vscodeCommand, + taskLoading, + vscodeTaskLoading, + checkDevServerStatus, + checkVscodeStatus, + startDevServer, + restartDevServer, + stopDevServer, + startVscode, + restartVscode, + stopVscode, + }; +} \ No newline at end of file diff --git a/app/layout.tsx b/app/layout.tsx new file mode 100644 index 0000000..14b4baa --- /dev/null +++ b/app/layout.tsx @@ -0,0 +1,34 @@ +import type { Metadata } from "next"; +import { Geist, Geist_Mono } from "next/font/google"; +import "./globals.css"; + +const geistSans = Geist({ + variable: "--font-geist-sans", + subsets: ["latin"], +}); + +const geistMono = Geist_Mono({ + variable: "--font-geist-mono", + subsets: ["latin"], +}); + +export const metadata: Metadata = { + title: "CodeSandbox Clone", + description: "A full-featured CodeSandbox clone built with Next.js and the CodeSandbox SDK", +}; + +export default function RootLayout({ + children, +}: Readonly<{ + children: React.ReactNode; +}>) { + return ( + + + {children} + + + ); +} diff --git a/app/page.tsx b/app/page.tsx new file mode 100644 index 0000000..273a802 --- /dev/null +++ b/app/page.tsx @@ -0,0 +1,200 @@ +'use client'; + +import { useState, useEffect } from 'react'; +import Link from 'next/link'; +import { useRouter } from 'next/navigation'; +import CreateProjectModal from './components/CreateProjectModal'; +import GitHubTokenError from './components/GitHubTokenError'; +import { useAuth } from './hooks/useAuth'; +import { useProjects } from './hooks/useProjects'; + +export default function Home() { + const [isModalOpen, setIsModalOpen] = useState(false); + const [hasGitHubToken, setHasGitHubToken] = useState(null); + const router = useRouter(); + + const { user, loading: authLoading, logout } = useAuth(); + const { projects, loading: projectsLoading, fetchProjects } = useProjects(); + + const loading = authLoading || (user && projectsLoading); + + useEffect(() => { + const checkGitHubToken = async () => { + try { + const response = await fetch('/api/auth/github-status'); + if (response.ok) { + const data = await response.json(); + setHasGitHubToken(data.hasGitHubToken); + } + } catch (err) { + console.error('Failed to check GitHub token status:', err); + setHasGitHubToken(false); + } + }; + + if (user) { + checkGitHubToken(); + } + }, [user]); + + const handleLogout = async () => { + try { + await logout(); + } catch (err) { + console.error('Logout failed:', err); + } + }; + + const handleProjectCreated = (projectId: string) => { + setIsModalOpen(false); + fetchProjects(); + router.push(`/projects/${projectId}`); + }; + + const handleRetryGitHubCheck = async () => { + setHasGitHubToken(null); + try { + const response = await fetch('/api/auth/github-status'); + if (response.ok) { + const data = await response.json(); + setHasGitHubToken(data.hasGitHubToken); + } + } catch (err) { + console.error('Failed to check GitHub token status:', err); + setHasGitHubToken(false); + } + }; + + if (loading || !user || hasGitHubToken === null) { + return ( +
+
+
+

Loading...

+
+
+ ); + } + + if (hasGitHubToken === false) { + return ; + } + + return ( +
+ {/* Header */} +
+
+
+
+

CodeSandbox Clone

+

Create and manage your coding projects

+
+
+
+ {projects.length} Projects +
+ +
+
+ Welcome, + {user.username} + + {user.role} + +
+ +
+
+
+
+
+ + {/* Main Content */} +
+ {projects.length === 0 ? ( +
+
+ + + +
+

No projects yet

+

Get started by creating your first project

+ +
+ ) : ( +
+ {projects.map(project => ( + +
+
+
+ + + +
+
+ + + +
+
+ +

+ {project.name} +

+ +
+ + + + Created {new Date(project.createdAt).toLocaleDateString('en-US', { + month: 'short', + day: 'numeric', + year: 'numeric' + })} +
+ +
+
+ + ID: {project.id} + +
+
+
+
+ + ))} +
+ )} +
+ + setIsModalOpen(false)} + onProjectCreated={handleProjectCreated} + /> +
+ ); +} diff --git a/app/projects/[id]/layout.tsx b/app/projects/[id]/layout.tsx new file mode 100644 index 0000000..e2126d9 --- /dev/null +++ b/app/projects/[id]/layout.tsx @@ -0,0 +1,13 @@ +import { SandboxProvider } from '../../contexts/SandboxContext'; + +export default function ProjectLayout({ + children, +}: { + children: React.ReactNode; +}) { + return ( + + {children} + + ); +} \ No newline at end of file diff --git a/app/projects/[id]/page.tsx b/app/projects/[id]/page.tsx new file mode 100644 index 0000000..1d935fc --- /dev/null +++ b/app/projects/[id]/page.tsx @@ -0,0 +1,504 @@ +'use client'; + +import { useEffect } from 'react'; +import { useParams } from 'next/navigation'; +import Link from 'next/link'; +import { useProject } from '../../hooks/useProject'; +import { useSandboxManager } from '../../hooks/useSandboxManager'; + +export default function ProjectPage() { + const params = useParams(); + const projectId = params.id as string; + + const { project, loading, error } = useProject(projectId); + const { + sandbox, + sandboxLoading, + setupState, + connectToSandboxInstance, + devServerTask, + vscodeTask, + taskLoading, + vscodeTaskLoading, + startDevServer, + restartDevServer, + stopDevServer, + startVscode, + restartVscode, + stopVscode, + previewState, + vscodeState, + previewContainerRef, + vscodeContainerRef, + } = useSandboxManager(); + + useEffect(() => { + if (project?.sandboxId && !sandbox) { + connectToSandboxInstance(project.id, project.sandboxId); + } + }, [project, sandbox, connectToSandboxInstance]); + + if (loading) { + return ( +
+
+
+

Loading project...

+
+
+ ); + } + + if (error) { + return ( +
+
+
+ + + +
+

{error}

+ + Back to Dashboard + +
+
+ ); + } + + if (!project) { + return null; + } + + return ( +
+ {/* Header */} +
+
+
+
+ + + + + +
+

{project.name}

+ {project.githubRepoUrl && ( + + {project.githubRepoUrl} + + + + + )} +
+
+
+ {/* Sandbox Status */} +
+ Sandbox: +
+ + {sandbox ? 'Connected' : sandboxLoading ? 'Connecting...' : 'Disconnected'} + +
+ + {/* Setup Status */} + {sandbox && ( +
+ Setup: +
+ + {setupState.status === 'FINISHED' ? 'Complete' : + setupState.status === 'RUNNING' ? 'Running' : + setupState.status === 'ERROR' ? 'Error' : + 'Not Started'} + +
+ )} + +
+ ID: {project.id} +
+
+
+
+
+ + {/* Main Content */} +
+ {/* Two Column Layout */} + {sandbox && ( +
+ {/* VSCode Column */} +
+
+

VSCode

+
+ {/* VSCode Task Status */} +
+ Server: +
+ + {vscodeTask.status === 'LOADING' ? 'Loading...' : vscodeTask.status.toLowerCase()} + +
+
+
+ + {/* VSCode Controls */} +
+
+
+
+ Port 8080: +
+ + {vscodeTask.portActive ? 'Active' : 'Inactive'} + +
+
+ +
+ {!vscodeTask.portActive ? ( + + ) : ( + <> + + + + )} +
+
+
+ +
+
+ {/* Loading state */} + {vscodeState.loading && ( +
+
+
+

Loading VSCode...

+
+
+ )} + + {/* Port closed message */} + {vscodeState.portClosed && !vscodeState.loading && ( +
+
+ + + +

Port Disconnected

+

The VSCode server port has closed.

+

VSCode will reload automatically when the port reopens.

+
+
+ )} + + {/* Setup running */} + {setupState.status === 'RUNNING' && !vscodeState.loading && ( +
+
+
+

Setting up Sandbox

+

Please wait while the sandbox is being configured...

+ {setupState.currentStepName && ( +

+ Current step: {setupState.currentStepName} +

+ )} + {setupState.totalSteps > 0 && ( +

+ Step {setupState.currentStepIndex + 1} of {setupState.totalSteps} +

+ )} +
+
+ )} + + {/* VSCode initial loading state */} + {vscodeTask.status === 'LOADING' && !vscodeState.loading && ( +
+
+
+

Checking VSCode Status

+

Please wait while we check the VSCode server status...

+
+
+ )} + + {/* VSCode task not running */} + {setupState.status !== 'RUNNING' && !vscodeTask.portActive && !vscodeState.loading && !vscodeState.portClosed && vscodeTask.status !== 'LOADING' && ( +
+
+ + + +

No VSCode Available

+

Start the VSCode server to access the editor.

+
+
+ )} +
+
+
+ + {/* Development Preview Column */} +
+
+

Development Preview

+
+ {/* Dev Server Status */} +
+ Server: +
+ + {devServerTask.status.toLowerCase()} + +
+
+
+ + {/* Dev Server Controls */} +
+
+
+
+ Port 5173: +
+ + {devServerTask.portActive ? 'Active' : 'Inactive'} + +
+
+ +
+ {!devServerTask.portActive ? ( + + ) : ( + <> + + + {previewState.connected && previewState.preview && ( + + )} + + )} +
+
+
+ +
+
+ {/* Loading state */} + {previewState.loading && ( +
+
+
+

Loading preview...

+
+
+ )} + + {/* Port closed message */} + {previewState.portClosed && !previewState.loading && ( +
+
+ + + +

Port Disconnected

+

The development server port has closed.

+

Preview will reload automatically when the port reopens.

+
+
+ )} + + {/* Setup running */} + {setupState.status === 'RUNNING' && !previewState.loading && ( +
+
+
+

Setting up Sandbox

+

Please wait while the sandbox is being configured...

+ {setupState.currentStepName && ( +

+ Current step: {setupState.currentStepName} +

+ )} + {setupState.totalSteps > 0 && ( +

+ Step {setupState.currentStepIndex + 1} of {setupState.totalSteps} +

+ )} +
+
+ )} + + {/* Dev server not running */} + {setupState.status !== 'RUNNING' && !devServerTask.portActive && !previewState.loading && !previewState.portClosed && ( +
+
+ + + +

No Preview Available

+

Start the development server to see a preview.

+
+
+ )} +
+
+
+
+ )} +
+
+ ); +} \ No newline at end of file diff --git a/app/projects/[id]/page.v2.tsx b/app/projects/[id]/page.v2.tsx new file mode 100644 index 0000000..97016b6 --- /dev/null +++ b/app/projects/[id]/page.v2.tsx @@ -0,0 +1,408 @@ +'use client'; + +import { useEffect } from 'react'; +import { useParams } from 'next/navigation'; +import Link from 'next/link'; +import { useProject } from '../../hooks/useProject'; +import { useSandboxContext } from '../../contexts/SandboxContext'; +import { useSandboxTasks } from '../../hooks/useSandboxTasks.v2'; +import { useSandboxPreview } from '../../hooks/useSandboxPreview.v2'; + +export default function ProjectPageV2() { + const params = useParams(); + const projectId = params.id as string; + + const { project, loading, error } = useProject(projectId); + const { + sandbox, + loading: sandboxLoading, + setupState, + connectToSandboxInstance, + } = useSandboxContext(); + + const { + devServerTask, + vscodeTask, + taskLoading, + vscodeTaskLoading, + startDevServer, + restartDevServer, + stopDevServer, + startVscode, + restartVscode, + stopVscode, + } = useSandboxTasks(); + + const { + previewState, + vscodeState, + previewContainerRef, + vscodeContainerRef, + createSandboxPreview, + createVscodePreview, + destroyPreview, + destroyVscodePreview, + } = useSandboxPreview(); + + // Connect to sandbox when project is loaded + useEffect(() => { + if (project?.sandboxId && !sandbox) { + connectToSandboxInstance(project.id, project.sandboxId); + } + }, [project, sandbox, connectToSandboxInstance]); + + // Auto-create preview when dev server port becomes active and setup is finished + useEffect(() => { + if (sandbox && devServerTask.portActive && !previewState.preview && !previewState.loading && setupState.status === 'FINISHED') { + console.log('🎬 Port is active and setup finished, creating preview...'); + createSandboxPreview(); + } else if (!devServerTask.portActive && previewState.preview) { + console.log('🛑 Port is inactive, destroying preview...'); + destroyPreview(); + } + }, [sandbox, devServerTask.portActive, previewState.preview, previewState.loading, setupState.status, createSandboxPreview, destroyPreview]); + + // Auto-create VSCode when port becomes active and setup is finished + useEffect(() => { + if (sandbox && vscodeTask.portActive && !vscodeState.preview && !vscodeState.loading && setupState.status === 'FINISHED') { + console.log('🎬 VSCode port is active and setup finished, creating VSCode preview...'); + createVscodePreview(); + } else if (!vscodeTask.portActive && vscodeState.preview) { + console.log('🛑 VSCode port is inactive, destroying VSCode preview...'); + destroyVscodePreview(); + } + }, [sandbox, vscodeTask.portActive, vscodeState.preview, vscodeState.loading, setupState.status, createVscodePreview, destroyVscodePreview]); + + if (loading) { + return ( +
+
+
+

Loading project...

+
+
+ ); + } + + if (error) { + return ( +
+
+
+ + + +
+

{error}

+ + Back to Dashboard + +
+
+ ); + } + + if (!project) { + return null; + } + + return ( +
+ {/* Header */} +
+
+
+
+ + + + + +
+

{project.name}

+ {project.githubRepoUrl && ( + + {project.githubRepoUrl} + + + + + )} +
+
+
+ {/* Sandbox Status */} +
+ Sandbox: +
+ + {sandbox ? 'Connected' : sandboxLoading ? 'Connecting...' : 'Disconnected'} + +
+ + {/* Setup Status */} + {sandbox && ( +
+ Setup: +
+ + {setupState.status === 'FINISHED' ? 'Complete' : + setupState.status === 'RUNNING' ? 'Running' : + setupState.status === 'ERROR' ? 'Error' : + 'Not Started'} + +
+ )} + +
+ ID: {project.id} +
+
+
+
+
+ + {/* Main Content */} +
+ {/* Context-Based Architecture Benefits Display */} +
+

🔄 Context-Based Architecture

+

+ This page now uses a Context-based architecture where the Sandbox Client instance is shared across hooks through SandboxProvider. + Benefits include centralized state management, reduced prop drilling, and efficient event handling. +

+
+ + {/* Two Column Layout */} + {sandbox && ( +
+ {/* VSCode Column */} +
+
+

VSCode

+
+ {/* VSCode Task Status */} +
+ Server: +
+ + {vscodeTask.status === 'LOADING' ? 'Loading...' : vscodeTask.status.toLowerCase()} + +
+
+
+ + {/* VSCode Controls */} +
+
+
+
+ Port 8080: +
+ + {vscodeTask.portActive ? 'Active' : 'Inactive'} + +
+
+ +
+ {!vscodeTask.portActive ? ( + + ) : ( + <> + + + + )} +
+
+
+ +
+
+ {/* Loading and status messages similar to original */} + {vscodeState.loading && ( +
+
+
+

Loading VSCode...

+
+
+ )} + + {!vscodeTask.portActive && !vscodeState.loading && setupState.status === 'FINISHED' && ( +
+
+ + + +

No VSCode Available

+

Start the VSCode server to access the editor.

+
+
+ )} +
+
+
+ + {/* Development Preview Column */} +
+
+

Development Preview

+
+
+ Server: +
+ + {devServerTask.status.toLowerCase()} + +
+
+
+ + {/* Dev Server Controls */} +
+
+
+
+ Port 5173: +
+ + {devServerTask.portActive ? 'Active' : 'Inactive'} + +
+
+ +
+ {!devServerTask.portActive ? ( + + ) : ( + <> + + + + )} +
+
+
+ +
+
+ {previewState.loading && ( +
+
+
+

Loading preview...

+
+
+ )} + + {!devServerTask.portActive && !previewState.loading && setupState.status === 'FINISHED' && ( +
+
+ + + +

No Preview Available

+

Start the development server to see a preview.

+
+
+ )} +
+
+
+
+ )} +
+
+ ); +} \ No newline at end of file diff --git a/next.config.ts b/next.config.ts new file mode 100644 index 0000000..e9ffa30 --- /dev/null +++ b/next.config.ts @@ -0,0 +1,7 @@ +import type { NextConfig } from "next"; + +const nextConfig: NextConfig = { + /* config options here */ +}; + +export default nextConfig; diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..27eef76 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,6167 @@ +{ + "name": "app", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "app", + "version": "0.1.0", + "dependencies": { + "@codesandbox/sdk": "^2.0.6-rc.1", + "@octokit/rest": "^22.0.0", + "next": "15.4.5", + "react": "19.1.0", + "react-dom": "19.1.0" + }, + "devDependencies": { + "@tailwindcss/postcss": "^4", + "@types/node": "^20", + "@types/react": "^19", + "@types/react-dom": "^19", + "tailwindcss": "^4", + "typescript": "^5" + } + }, + "node_modules/@absinthe/socket": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@absinthe/socket/-/socket-0.2.1.tgz", + "integrity": "sha512-rCuMRG4WndooGR+QfU5v+xL6U8YKEXFyvjqYt0qTHupAh+k+tpD6a5dlxcLO0g38p/hb1I12OzKvl+0G1XYCkA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "7.2.0", + "@jumpn/utils-array": "0.3.4", + "@jumpn/utils-composite": "0.7.0", + "@jumpn/utils-graphql": "0.6.0", + "core-js": "2.6.0", + "zen-observable": "0.8.11" + }, + "peerDependencies": { + "phoenix": "^1.4.0" + } + }, + "node_modules/@alcalzone/ansi-tokenize": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@alcalzone/ansi-tokenize/-/ansi-tokenize-0.1.3.tgz", + "integrity": "sha512-3yWxPTq3UQ/FY9p1ErPxIyfT64elWaMvM9lIHnaqpyft63tkxodF5aUElYHrdisWve5cETkh1+KBw1yJuW0aRw==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^4.0.0" + }, + "engines": { + "node": ">=14.13.1" + } + }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.2.0.tgz", + "integrity": "sha512-oouEibCbHMVdZSDlJBO6bZmID/zA/G/Qx3H1d3rSNPTD+L8UNKvCat7aKWSJ74zYbm5zWGh0GQN0hKj8zYFTCg==", + "license": "MIT", + "dependencies": { + "regenerator-runtime": "^0.12.0" + } + }, + "node_modules/@codesandbox/api": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@codesandbox/api/-/api-1.1.3.tgz", + "integrity": "sha512-GHrxd/tL4CHy/+42Qx0RC65EHUH6jjzuRm+JcBgAlRcMCJPvSTANpoNgI6fQKofvEJIVc4ghqR7X87j6emEZyg==", + "license": "MIT", + "dependencies": { + "@absinthe/socket": "^0.2.1", + "@codesandbox/create-gql-api": "^1.0.1", + "class-states": "1.0.15", + "humps": "^2.0.1", + "phoenix": "^1.6.6", + "preact": "^10.22.0", + "universal-cookie": "^4.0.4" + } + }, + "node_modules/@codesandbox/api/node_modules/class-states": { + "version": "1.0.15", + "resolved": "https://registry.npmjs.org/class-states/-/class-states-1.0.15.tgz", + "integrity": "sha512-ReR0LKl1C3tK+Wwe2zlAtXEjLavuR3+m+oFFNELdJmywEoh00iDYCWLxWJof83YSpqIBK/iegy0blUuktJ7+6A==", + "license": "ISC" + }, + "node_modules/@codesandbox/create-gql-api": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@codesandbox/create-gql-api/-/create-gql-api-1.0.1.tgz", + "integrity": "sha512-k+C8OS2wYdakIoYEtHjW+pvwb7uq+emHQX5W1tqJQ9gDEYYy2dHItQNulY/8H0ymudhW3b6zcKTVNTMl9QgGWQ==", + "license": "ISC", + "dependencies": { + "get-graphql-schema": "^2.1.2", + "graphql": "^16.8.1" + }, + "bin": { + "create-gql-api": "bin/index.js" + } + }, + "node_modules/@codesandbox/nodebox": { + "version": "0.1.9", + "resolved": "https://registry.npmjs.org/@codesandbox/nodebox/-/nodebox-0.1.9.tgz", + "integrity": "sha512-h/SCSA5iasmEUlxWWQf2ecv1WgGoI5KLV5iZoN9YA1Hhz4DIacE3vwwD24Vn+1qczny4TEr8zwMQYZ1K8TbvzQ==", + "license": "SEE LICENSE IN ./LICENSE", + "dependencies": { + "outvariant": "^1.4.0", + "strict-event-emitter": "^0.4.3" + } + }, + "node_modules/@codesandbox/pitcher-client": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@codesandbox/pitcher-client/-/pitcher-client-1.1.7.tgz", + "integrity": "sha512-D3KkU+nDUR6kXCsnsEFaYMjkWhsum7imD6aduG44cxYmZi1jlqnUb1FCoDW2Sj4+6LmhFOnpUdSE1nnkJ2eoFQ==", + "license": "GPL-3.0", + "dependencies": { + "@codesandbox/api": "^1.1.3", + "@codesandbox/nodebox": "^0.1.8", + "@codesandbox/pitcher-common": "^0.360.2", + "@codesandbox/pitcher-protocol": "^0.360.4", + "@codesandbox/sandpack-client": "^2.18.0", + "@types/ws": "^7.4.7", + "class-states": "1.0.16", + "debug": "^4.3.4", + "isomorphic-ws": "^5.0.0", + "js-untar": "^2.0.0", + "jszip": "^3.10.1", + "minimatch": "^10.0.1", + "semver": "^7.3.5", + "vscode-jsonrpc": "^8.2.0" + } + }, + "node_modules/@codesandbox/pitcher-common": { + "version": "0.360.2", + "resolved": "https://registry.npmjs.org/@codesandbox/pitcher-common/-/pitcher-common-0.360.2.tgz", + "integrity": "sha512-FWy4YgDh0LFZRo9N8j7mTSoKyIftWJVs/9LR5rwzAta0lFUAV2X8hsGMzt0u16Ng5Wpbi92svMZQy6WygC93gg==", + "license": "GPL-3.0", + "dependencies": { + "@emotion/hash": "^0.8.0", + "@types/micromatch": "^4.0.2", + "@types/retry": "^0.12.2", + "cross-fetch": "^4.0.0", + "lru_map": "^0.4.1", + "micromatch": "^4.0.4", + "oo-ascii-tree": "^1.34.0", + "p-queue": "^6.6.2", + "retry": "^0.13.1", + "strip-json-comments": "^3.1.1", + "tiny-invariant": "^1.2.0", + "ts-mixer": "^6.0.0", + "type-fest": "^2.11.1", + "uuid": "^11.0.2", + "vscode-diff": "^2.0.1" + } + }, + "node_modules/@codesandbox/pitcher-protocol": { + "version": "0.360.4", + "resolved": "https://registry.npmjs.org/@codesandbox/pitcher-protocol/-/pitcher-protocol-0.360.4.tgz", + "integrity": "sha512-oPxA2/F/ywyR73elJwdFOsw3D+rOId2UTNAXnRrTGjh66Ujyx/IFGVqfTlibGaQUg2HENkRoiRsvRJa5qphITA==", + "license": "GPL-3.0", + "dependencies": { + "@codesandbox/pitcher-common": "0.360.2", + "@msgpack/msgpack": "^2.7.1" + } + }, + "node_modules/@codesandbox/pitcher-protocol/node_modules/@msgpack/msgpack": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@msgpack/msgpack/-/msgpack-2.8.0.tgz", + "integrity": "sha512-h9u4u/jiIRKbq25PM+zymTyW6bhTzELvOoUd+AvYriWOAKpLGnIamaET3pnHYoI5iYphAHBI4ayx0MehR+VVPQ==", + "license": "ISC", + "engines": { + "node": ">= 10" + } + }, + "node_modules/@codesandbox/sandpack-client": { + "version": "2.19.8", + "resolved": "https://registry.npmjs.org/@codesandbox/sandpack-client/-/sandpack-client-2.19.8.tgz", + "integrity": "sha512-CMV4nr1zgKzVpx4I3FYvGRM5YT0VaQhALMW9vy4wZRhEyWAtJITQIqZzrTGWqB1JvV7V72dVEUCUPLfYz5hgJQ==", + "license": "Apache-2.0", + "dependencies": { + "@codesandbox/nodebox": "0.1.8", + "buffer": "^6.0.3", + "dequal": "^2.0.2", + "mime-db": "^1.52.0", + "outvariant": "1.4.0", + "static-browser-server": "1.0.3" + } + }, + "node_modules/@codesandbox/sandpack-client/node_modules/@codesandbox/nodebox": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/@codesandbox/nodebox/-/nodebox-0.1.8.tgz", + "integrity": "sha512-2VRS6JDSk+M+pg56GA6CryyUSGPjBEe8Pnae0QL3jJF1mJZJVMDKr93gJRtBbLkfZN6LD/DwMtf+2L0bpWrjqg==", + "license": "SEE LICENSE IN ./LICENSE", + "dependencies": { + "outvariant": "^1.4.0", + "strict-event-emitter": "^0.4.3" + } + }, + "node_modules/@codesandbox/sandpack-client/node_modules/outvariant": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/outvariant/-/outvariant-1.4.0.tgz", + "integrity": "sha512-AlWY719RF02ujitly7Kk/0QlV+pXGFDHrHf9O2OKqyqgBieaPOIeuSkL8sRK6j2WK+/ZAURq2kZsY0d8JapUiw==", + "license": "MIT" + }, + "node_modules/@codesandbox/sdk": { + "version": "2.0.6-rc.1", + "resolved": "https://registry.npmjs.org/@codesandbox/sdk/-/sdk-2.0.6-rc.1.tgz", + "integrity": "sha512-BaOQ4Jhrgfn/3GD5/cEgGPqmH7iIOI+1qBi7PFT+tnpZ6O78E16jUBA1yOXtrVWHwAtQEABxufv9GZSoN0K73A==", + "license": "MIT", + "dependencies": { + "@codesandbox/pitcher-client": "1.1.7", + "@hey-api/client-fetch": "^0.7.3", + "@inkjs/ui": "^2.0.0", + "@msgpack/msgpack": "^3.1.0", + "@tanstack/react-query": "^5.76.1", + "blessed": "^0.1.81", + "blessed-contrib": "^4.11.0", + "cli-table3": "^0.6.3", + "ink": "^6.1.0", + "isbinaryfile": "^5.0.4", + "isomorphic-ws": "^5.0.0", + "ora": "^8.2.0", + "path": "^0.12.7", + "react": "^19.1.1", + "readline": "^1.3.0", + "util": "^0.12.5", + "yargs": "^17.7.2" + }, + "bin": { + "csb": "dist/bin/codesandbox.mjs" + }, + "optionalDependencies": { + "@sentry/node": "^9.29.0" + } + }, + "node_modules/@codesandbox/sdk/node_modules/react": { + "version": "19.1.1", + "resolved": "https://registry.npmjs.org/react/-/react-19.1.1.tgz", + "integrity": "sha512-w8nqGImo45dmMIfljjMwOGtbmC/mk4CMYhWIicdSflH91J9TyCyczcPFXJzrZ/ZXcgGRFeP6BU0BEJTw6tZdfQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.4.5.tgz", + "integrity": "sha512-++LApOtY0pEEz1zrd9vy1/zXVaVJJ/EbAF3u0fXIzPJEDtnITsBGbbK0EkM72amhl/R5b+5xx0Y/QhcVOpuulg==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emotion/hash": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz", + "integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==", + "license": "MIT" + }, + "node_modules/@hey-api/client-fetch": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/@hey-api/client-fetch/-/client-fetch-0.7.3.tgz", + "integrity": "sha512-nysIXMag9nr5ENy+47G0AYsegdT7vT6S4KLfY7NVgM6HsyZ0DrhCZvz5nP70M16x9i860SrnXhjpcuHx0g5sDQ==", + "deprecated": "Starting with v0.73.0, this package is bundled directly inside @hey-api/openapi-ts.", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/hey-api" + } + }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.3.tgz", + "integrity": "sha512-ryFMfvxxpQRsgZJqBd4wsttYQbCxsJksrv9Lw/v798JcQ8+w84mBWuXwl+TT0WJ/WrYOLaYpwQXi3sA9nTIaIg==", + "cpu": [ + "arm64" + ], + "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.2.0" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.3.tgz", + "integrity": "sha512-yHpJYynROAj12TA6qil58hmPmAwxKKC7reUqtGLzsOHfP7/rniNGTL8tjWX6L3CTV4+5P4ypcS7Pp+7OB+8ihA==", + "cpu": [ + "x64" + ], + "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.2.0" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.0.tgz", + "integrity": "sha512-sBZmpwmxqwlqG9ueWFXtockhsxefaV6O84BMOrhtg/YqbTaRdqDE7hxraVE3y6gVM4eExmfzW4a8el9ArLeEiQ==", + "cpu": [ + "arm64" + ], + "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.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.0.tgz", + "integrity": "sha512-M64XVuL94OgiNHa5/m2YvEQI5q2cl9d/wk0qFTDVXcYzi43lxuiFTftMR1tOnFQovVXNZJ5TURSDK2pNe9Yzqg==", + "cpu": [ + "x64" + ], + "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.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.0.tgz", + "integrity": "sha512-mWd2uWvDtL/nvIzThLq3fr2nnGfyr/XMXlq8ZJ9WMR6PXijHlC3ksp0IpuhK6bougvQrchUAfzRLnbsen0Cqvw==", + "cpu": [ + "arm" + ], + "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.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.0.tgz", + "integrity": "sha512-RXwd0CgG+uPRX5YYrkzKyalt2OJYRiJQ8ED/fi1tq9WQW2jsQIn0tqrlR5l5dr/rjqq6AHAxURhj2DVjyQWSOA==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.0.tgz", + "integrity": "sha512-Xod/7KaDDHkYu2phxxfeEPXfVXFKx70EAFZ0qyUdOjCcxbjqyJOEUpDe6RIyaunGxT34Anf9ue/wuWOqBW2WcQ==", + "cpu": [ + "ppc64" + ], + "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.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.0.tgz", + "integrity": "sha512-eMKfzDxLGT8mnmPJTNMcjfO33fLiTDsrMlUVcp6b96ETbnJmd4uvZxVJSKPQfS+odwfVaGifhsB07J1LynFehw==", + "cpu": [ + "s390x" + ], + "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.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.0.tgz", + "integrity": "sha512-ZW3FPWIc7K1sH9E3nxIGB3y3dZkpJlMnkk7z5tu1nSkBoCgw2nSRTFHI5pB/3CQaJM0pdzMF3paf9ckKMSE9Tg==", + "cpu": [ + "x64" + ], + "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.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.0.tgz", + "integrity": "sha512-UG+LqQJbf5VJ8NWJ5Z3tdIe/HXjuIdo4JeVNADXBFuG7z9zjoegpzzGIyV5zQKi4zaJjnAd2+g2nna8TZvuW9Q==", + "cpu": [ + "arm64" + ], + "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.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.0.tgz", + "integrity": "sha512-SRYOLR7CXPgNze8akZwjoGBoN1ThNZoqpOgfnOxmWsklTGVfJiGJoC/Lod7aNMGA1jSsKWM1+HRX43OP6p9+6Q==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.3.tgz", + "integrity": "sha512-oBK9l+h6KBN0i3dC8rYntLiVfW8D8wH+NPNT3O/WBHeW0OQWCjfWksLUaPidsrDKpJgXp3G3/hkmhptAW0I3+A==", + "cpu": [ + "arm" + ], + "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.2.0" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.3.tgz", + "integrity": "sha512-QdrKe3EvQrqwkDrtuTIjI0bu6YEJHTgEeqdzI3uWJOH6G1O8Nl1iEeVYRGdj1h5I21CqxSvQp1Yv7xeU3ZewbA==", + "cpu": [ + "arm64" + ], + "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.2.0" + } + }, + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.3.tgz", + "integrity": "sha512-GLtbLQMCNC5nxuImPR2+RgrviwKwVql28FWZIW1zWruy6zLgA5/x2ZXk3mxj58X/tszVF69KK0Is83V8YgWhLA==", + "cpu": [ + "ppc64" + ], + "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-ppc64": "1.2.0" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.3.tgz", + "integrity": "sha512-3gahT+A6c4cdc2edhsLHmIOXMb17ltffJlxR0aC2VPZfwKoTGZec6u5GrFgdR7ciJSsHT27BD3TIuGcuRT0KmQ==", + "cpu": [ + "s390x" + ], + "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.2.0" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.3.tgz", + "integrity": "sha512-8kYso8d806ypnSq3/Ly0QEw90V5ZoHh10yH0HnrzOCr6DKAPI6QVHvwleqMkVQ0m+fc7EH8ah0BB0QPuWY6zJQ==", + "cpu": [ + "x64" + ], + "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.2.0" + } + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.3.tgz", + "integrity": "sha512-vAjbHDlr4izEiXM1OTggpCcPg9tn4YriK5vAjowJsHwdBIdx0fYRsURkxLG2RLm9gyBq66gwtWI8Gx0/ov+JKQ==", + "cpu": [ + "arm64" + ], + "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.2.0" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.3.tgz", + "integrity": "sha512-gCWUn9547K5bwvOn9l5XGAEjVTTRji4aPTqLzGXHvIr6bIDZKNTA34seMPgM0WmSf+RYBH411VavCejp3PkOeQ==", + "cpu": [ + "x64" + ], + "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.2.0" + } + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.3.tgz", + "integrity": "sha512-+CyRcpagHMGteySaWos8IbnXcHgfDn7pO2fiC2slJxvNq9gDipYBN42/RagzctVRKgxATmfqOSulgZv5e1RdMg==", + "cpu": [ + "wasm32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.4.4" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-arm64": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.3.tgz", + "integrity": "sha512-MjnHPnbqMXNC2UgeLJtX4XqoVHHlZNd+nPt1kRPmj63wURegwBhZlApELdtxM2OIZDRv/DFtLcNhVbd1z8GYXQ==", + "cpu": [ + "arm64" + ], + "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-ia32": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.3.tgz", + "integrity": "sha512-xuCdhH44WxuXgOM714hn4amodJMZl3OEvf0GVTm0BEyMeA2to+8HEdRPShH0SLYptJY1uBw+SCFP9WVQi1Q/cw==", + "cpu": [ + "ia32" + ], + "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.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.3.tgz", + "integrity": "sha512-OWwz05d++TxzLEv4VnsTz5CmZ6mI6S05sfQGEMrNrQcOEERbX46332IvE7pO/EUiw7jUrrS40z/M7kPyjfl04g==", + "cpu": [ + "x64" + ], + "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/@inkjs/ui": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@inkjs/ui/-/ui-2.0.0.tgz", + "integrity": "sha512-5+8fJmwtF9UvikzLfph9sA+LS+l37Ij/szQltkuXLOAXwNkBX9innfzh4pLGXIB59vKEQUtc6D4qGvhD7h3pAg==", + "license": "MIT", + "dependencies": { + "chalk": "^5.3.0", + "cli-spinners": "^3.0.0", + "deepmerge": "^4.3.1", + "figures": "^6.1.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "ink": ">=5" + } + }, + "node_modules/@isaacs/balanced-match": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz", + "integrity": "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==", + "license": "MIT", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@isaacs/brace-expansion": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.0.tgz", + "integrity": "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==", + "license": "MIT", + "dependencies": { + "@isaacs/balanced-match": "^4.0.1" + }, + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@isaacs/fs-minipass": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", + "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^7.0.4" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.12", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.12.tgz", + "integrity": "sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@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.4", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.4.tgz", + "integrity": "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.29", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.29.tgz", + "integrity": "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jumpn/utils-array": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@jumpn/utils-array/-/utils-array-0.3.4.tgz", + "integrity": "sha512-ExRwf0b0NMyMn6HLStMeqEEtmblV0BKVZ4YT3FhEJ5ErZSPN4Vv6xYUJQGNG0b7QGZJIN2KetxEoOm4MYmXygw==", + "license": "MIT", + "dependencies": { + "babel-polyfill": "6.26.0", + "babel-runtime": "6.26.0", + "flow-static-land": "0.2.7" + } + }, + "node_modules/@jumpn/utils-composite": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@jumpn/utils-composite/-/utils-composite-0.7.0.tgz", + "integrity": "sha512-kamRVYJLNvjMrnKKeu2RSFQHLUO/IYFo05gLI7GQcCk063mJzsjCCfRycCievIBI+5Sg8C7A5gwRYxkBA5jY8w==", + "license": "MIT", + "dependencies": { + "@jumpn/utils-array": "0.3.4", + "babel-polyfill": "6.26.0", + "babel-runtime": "6.26.0", + "fast-deep-equal": "1.0.0", + "flow-static-land": "0.2.8" + } + }, + "node_modules/@jumpn/utils-composite/node_modules/flow-static-land": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/flow-static-land/-/flow-static-land-0.2.8.tgz", + "integrity": "sha512-pOZFExu2rbscCgcEo7nL7FNhBubMi18dn1Un4lm8LOmQkYhgsHLsrBGMWmuJXRWcYMrOC7I/bPsiqqVjdD3K1g==", + "license": "MIT" + }, + "node_modules/@jumpn/utils-graphql": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@jumpn/utils-graphql/-/utils-graphql-0.6.0.tgz", + "integrity": "sha512-I5OSEh8Ed4FdLIcUTYzWdpO9noQOoWptdgF8yOZ0xhDD7h7E9IgPYxfy36qbC6v9xlpGTwQMu3Wn8ulkinG/MQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "7.2.0", + "core-js": "2.6.0", + "graphql": "14.0.2" + } + }, + "node_modules/@jumpn/utils-graphql/node_modules/graphql": { + "version": "14.0.2", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-14.0.2.tgz", + "integrity": "sha512-gUC4YYsaiSJT1h40krG3J+USGlwhzNTXSb4IOZljn9ag5Tj+RkoXrWp+Kh7WyE3t1NCfab5kzCuxBIvOMERMXw==", + "deprecated": "No longer supported; please update to a newer version. Details: https://github.com/graphql/graphql-js#version-support", + "license": "MIT", + "dependencies": { + "iterall": "^1.2.2" + }, + "engines": { + "node": ">= 6.x" + } + }, + "node_modules/@msgpack/msgpack": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@msgpack/msgpack/-/msgpack-3.1.2.tgz", + "integrity": "sha512-JEW4DEtBzfe8HvUYecLU9e6+XJnKDlUAIve8FvPzF3Kzs6Xo/KuZkZJsDH0wJXl/qEZbeeE7edxDNY3kMs39hQ==", + "license": "ISC", + "engines": { + "node": ">= 18" + } + }, + "node_modules/@next/env": { + "version": "15.4.5", + "resolved": "https://registry.npmjs.org/@next/env/-/env-15.4.5.tgz", + "integrity": "sha512-ruM+q2SCOVCepUiERoxOmZY9ZVoecR3gcXNwCYZRvQQWRjhOiPJGmQ2fAiLR6YKWXcSAh7G79KEFxN3rwhs4LQ==", + "license": "MIT" + }, + "node_modules/@next/swc-darwin-arm64": { + "version": "15.4.5", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.4.5.tgz", + "integrity": "sha512-84dAN4fkfdC7nX6udDLz9GzQlMUwEMKD7zsseXrl7FTeIItF8vpk1lhLEnsotiiDt+QFu3O1FVWnqwcRD2U3KA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-darwin-x64": { + "version": "15.4.5", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.4.5.tgz", + "integrity": "sha512-CL6mfGsKuFSyQjx36p2ftwMNSb8PQog8y0HO/ONLdQqDql7x3aJb/wB+LA651r4we2pp/Ck+qoRVUeZZEvSurA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "15.4.5", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.4.5.tgz", + "integrity": "sha512-1hTVd9n6jpM/thnDc5kYHD1OjjWYpUJrJxY4DlEacT7L5SEOXIifIdTye6SQNNn8JDZrcN+n8AWOmeJ8u3KlvQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-musl": { + "version": "15.4.5", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.4.5.tgz", + "integrity": "sha512-4W+D/nw3RpIwGrqpFi7greZ0hjrCaioGErI7XHgkcTeWdZd146NNu1s4HnaHonLeNTguKnL2Urqvj28UJj6Gqw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-gnu": { + "version": "15.4.5", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.4.5.tgz", + "integrity": "sha512-N6Mgdxe/Cn2K1yMHge6pclffkxzbSGOydXVKYOjYqQXZYjLCfN/CuFkaYDeDHY2VBwSHyM2fUjYBiQCIlxIKDA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-musl": { + "version": "15.4.5", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.4.5.tgz", + "integrity": "sha512-YZ3bNDrS8v5KiqgWE0xZQgtXgCTUacgFtnEgI4ccotAASwSvcMPDLua7BWLuTfucoRv6mPidXkITJLd8IdJplQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "15.4.5", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.4.5.tgz", + "integrity": "sha512-9Wr4t9GkZmMNcTVvSloFtjzbH4vtT4a8+UHqDoVnxA5QyfWe6c5flTH1BIWPGNWSUlofc8dVJAE7j84FQgskvQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-x64-msvc": { + "version": "15.4.5", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.4.5.tgz", + "integrity": "sha512-voWk7XtGvlsP+w8VBz7lqp8Y+dYw/MTI4KeS0gTVtfdhdJ5QwhXLmNrndFOin/MDoCvUaLWMkYKATaCoUkt2/A==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@octokit/auth-token": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-6.0.0.tgz", + "integrity": "sha512-P4YJBPdPSpWTQ1NU4XYdvHvXJJDxM6YwpS0FZHRgP7YFkdVxsWcpWGy/NVqlAA7PcPCnMacXlRm1y2PFZRWL/w==", + "license": "MIT", + "engines": { + "node": ">= 20" + } + }, + "node_modules/@octokit/core": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-7.0.3.tgz", + "integrity": "sha512-oNXsh2ywth5aowwIa7RKtawnkdH6LgU1ztfP9AIUCQCvzysB+WeU8o2kyyosDPwBZutPpjZDKPQGIzzrfTWweQ==", + "license": "MIT", + "dependencies": { + "@octokit/auth-token": "^6.0.0", + "@octokit/graphql": "^9.0.1", + "@octokit/request": "^10.0.2", + "@octokit/request-error": "^7.0.0", + "@octokit/types": "^14.0.0", + "before-after-hook": "^4.0.0", + "universal-user-agent": "^7.0.0" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/@octokit/endpoint": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-11.0.0.tgz", + "integrity": "sha512-hoYicJZaqISMAI3JfaDr1qMNi48OctWuOih1m80bkYow/ayPw6Jj52tqWJ6GEoFTk1gBqfanSoI1iY99Z5+ekQ==", + "license": "MIT", + "dependencies": { + "@octokit/types": "^14.0.0", + "universal-user-agent": "^7.0.2" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/@octokit/graphql": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-9.0.1.tgz", + "integrity": "sha512-j1nQNU1ZxNFx2ZtKmL4sMrs4egy5h65OMDmSbVyuCzjOcwsHq6EaYjOTGXPQxgfiN8dJ4CriYHk6zF050WEULg==", + "license": "MIT", + "dependencies": { + "@octokit/request": "^10.0.2", + "@octokit/types": "^14.0.0", + "universal-user-agent": "^7.0.0" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/@octokit/openapi-types": { + "version": "25.1.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-25.1.0.tgz", + "integrity": "sha512-idsIggNXUKkk0+BExUn1dQ92sfysJrje03Q0bv0e+KPLrvyqZF8MnBpFz8UNfYDwB3Ie7Z0TByjWfzxt7vseaA==", + "license": "MIT" + }, + "node_modules/@octokit/plugin-paginate-rest": { + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-13.1.1.tgz", + "integrity": "sha512-q9iQGlZlxAVNRN2jDNskJW/Cafy7/XE52wjZ5TTvyhyOD904Cvx//DNyoO3J/MXJ0ve3rPoNWKEg5iZrisQSuw==", + "license": "MIT", + "dependencies": { + "@octokit/types": "^14.1.0" + }, + "engines": { + "node": ">= 20" + }, + "peerDependencies": { + "@octokit/core": ">=6" + } + }, + "node_modules/@octokit/plugin-request-log": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-6.0.0.tgz", + "integrity": "sha512-UkOzeEN3W91/eBq9sPZNQ7sUBvYCqYbrrD8gTbBuGtHEuycE4/awMXcYvx6sVYo7LypPhmQwwpUe4Yyu4QZN5Q==", + "license": "MIT", + "engines": { + "node": ">= 20" + }, + "peerDependencies": { + "@octokit/core": ">=6" + } + }, + "node_modules/@octokit/plugin-rest-endpoint-methods": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-16.0.0.tgz", + "integrity": "sha512-kJVUQk6/dx/gRNLWUnAWKFs1kVPn5O5CYZyssyEoNYaFedqZxsfYs7DwI3d67hGz4qOwaJ1dpm07hOAD1BXx6g==", + "license": "MIT", + "dependencies": { + "@octokit/types": "^14.1.0" + }, + "engines": { + "node": ">= 20" + }, + "peerDependencies": { + "@octokit/core": ">=6" + } + }, + "node_modules/@octokit/request": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-10.0.3.tgz", + "integrity": "sha512-V6jhKokg35vk098iBqp2FBKunk3kMTXlmq+PtbV9Gl3TfskWlebSofU9uunVKhUN7xl+0+i5vt0TGTG8/p/7HA==", + "license": "MIT", + "dependencies": { + "@octokit/endpoint": "^11.0.0", + "@octokit/request-error": "^7.0.0", + "@octokit/types": "^14.0.0", + "fast-content-type-parse": "^3.0.0", + "universal-user-agent": "^7.0.2" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/@octokit/request-error": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-7.0.0.tgz", + "integrity": "sha512-KRA7VTGdVyJlh0cP5Tf94hTiYVVqmt2f3I6mnimmaVz4UG3gQV/k4mDJlJv3X67iX6rmN7gSHCF8ssqeMnmhZg==", + "license": "MIT", + "dependencies": { + "@octokit/types": "^14.0.0" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/@octokit/rest": { + "version": "22.0.0", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-22.0.0.tgz", + "integrity": "sha512-z6tmTu9BTnw51jYGulxrlernpsQYXpui1RK21vmXn8yF5bp6iX16yfTtJYGK5Mh1qDkvDOmp2n8sRMcQmR8jiA==", + "license": "MIT", + "dependencies": { + "@octokit/core": "^7.0.2", + "@octokit/plugin-paginate-rest": "^13.0.1", + "@octokit/plugin-request-log": "^6.0.0", + "@octokit/plugin-rest-endpoint-methods": "^16.0.0" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/@octokit/types": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-14.1.0.tgz", + "integrity": "sha512-1y6DgTy8Jomcpu33N+p5w58l6xyt55Ar2I91RPiIA0xCJBXyUAhXCcmZaDWSANiha7R9a6qJJ2CRomGPZ6f46g==", + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^25.1.0" + } + }, + "node_modules/@open-draft/deferred-promise": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@open-draft/deferred-promise/-/deferred-promise-2.2.0.tgz", + "integrity": "sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==", + "license": "MIT" + }, + "node_modules/@opentelemetry/api": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", + "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@opentelemetry/api-logs": { + "version": "0.57.2", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.57.2.tgz", + "integrity": "sha512-uIX52NnTM0iBh84MShlpouI7UKqkZ7MrUszTmaypHBu4r7NofznSnQRfJ+uUeDtQDj6w8eFGg5KBLDAwAPz1+A==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@opentelemetry/api": "^1.3.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/context-async-hooks": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/context-async-hooks/-/context-async-hooks-1.30.1.tgz", + "integrity": "sha512-s5vvxXPVdjqS3kTLKMeBMvop9hbWkwzBpu+mUO2M7sZtlkyDJGwFe33wRKnbaYDo8ExRVBIIdwIGrqpxHuKttA==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/core": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.30.1.tgz", + "integrity": "sha512-OOCM2C/QIURhJMuKaekP3TRBxBKxG/TWWA0TL2J6nXUtDnuCtccy49LUJF8xPFXMX+0LMcxFpCo8M9cGY1W6rQ==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@opentelemetry/semantic-conventions": "1.28.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/core/node_modules/@opentelemetry/semantic-conventions": { + "version": "1.28.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.28.0.tgz", + "integrity": "sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/instrumentation": { + "version": "0.57.2", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.57.2.tgz", + "integrity": "sha512-BdBGhQBh8IjZ2oIIX6F2/Q3LKm/FDDKi6ccYKcBTeilh6SNdNKveDOLk73BkSJjQLJk6qe4Yh+hHw1UPhCDdrg==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@opentelemetry/api-logs": "0.57.2", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-amqplib": { + "version": "0.46.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-amqplib/-/instrumentation-amqplib-0.46.1.tgz", + "integrity": "sha512-AyXVnlCf/xV3K/rNumzKxZqsULyITJH6OVLiW6730JPRqWA7Zc9bvYoVNpN6iOpTU8CasH34SU/ksVJmObFibQ==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.57.1", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-connect": { + "version": "0.43.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-connect/-/instrumentation-connect-0.43.1.tgz", + "integrity": "sha512-ht7YGWQuV5BopMcw5Q2hXn3I8eG8TH0J/kc/GMcW4CuNTgiP6wCu44BOnucJWL3CmFWaRHI//vWyAhaC8BwePw==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.57.1", + "@opentelemetry/semantic-conventions": "^1.27.0", + "@types/connect": "3.4.38" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-dataloader": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-dataloader/-/instrumentation-dataloader-0.16.1.tgz", + "integrity": "sha512-K/qU4CjnzOpNkkKO4DfCLSQshejRNAJtd4esgigo/50nxCB6XCyi1dhAblUHM9jG5dRm8eu0FB+t87nIo99LYQ==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@opentelemetry/instrumentation": "^0.57.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-express": { + "version": "0.47.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-express/-/instrumentation-express-0.47.1.tgz", + "integrity": "sha512-QNXPTWteDclR2B4pDFpz0TNghgB33UMjUt14B+BZPmtH1MwUFAfLHBaP5If0Z5NZC+jaH8oF2glgYjrmhZWmSw==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.57.1", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-fs": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-fs/-/instrumentation-fs-0.19.1.tgz", + "integrity": "sha512-6g0FhB3B9UobAR60BGTcXg4IHZ6aaYJzp0Ki5FhnxyAPt8Ns+9SSvgcrnsN2eGmk3RWG5vYycUGOEApycQL24A==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.57.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-generic-pool": { + "version": "0.43.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-generic-pool/-/instrumentation-generic-pool-0.43.1.tgz", + "integrity": "sha512-M6qGYsp1cURtvVLGDrPPZemMFEbuMmCXgQYTReC/IbimV5sGrLBjB+/hANUpRZjX67nGLdKSVLZuQQAiNz+sww==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@opentelemetry/instrumentation": "^0.57.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-graphql": { + "version": "0.47.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-graphql/-/instrumentation-graphql-0.47.1.tgz", + "integrity": "sha512-EGQRWMGqwiuVma8ZLAZnExQ7sBvbOx0N/AE/nlafISPs8S+QtXX+Viy6dcQwVWwYHQPAcuY3bFt3xgoAwb4ZNQ==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@opentelemetry/instrumentation": "^0.57.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-hapi": { + "version": "0.45.2", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-hapi/-/instrumentation-hapi-0.45.2.tgz", + "integrity": "sha512-7Ehow/7Wp3aoyCrZwQpU7a2CnoMq0XhIcioFuKjBb0PLYfBfmTsFTUyatlHu0fRxhwcRsSQRTvEhmZu8CppBpQ==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.57.1", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-http": { + "version": "0.57.2", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-http/-/instrumentation-http-0.57.2.tgz", + "integrity": "sha512-1Uz5iJ9ZAlFOiPuwYg29Bf7bJJc/GeoeJIFKJYQf67nTVKFe8RHbEtxgkOmK4UGZNHKXcpW4P8cWBYzBn1USpg==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@opentelemetry/core": "1.30.1", + "@opentelemetry/instrumentation": "0.57.2", + "@opentelemetry/semantic-conventions": "1.28.0", + "forwarded-parse": "2.1.2", + "semver": "^7.5.2" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-http/node_modules/@opentelemetry/semantic-conventions": { + "version": "1.28.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.28.0.tgz", + "integrity": "sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/instrumentation-ioredis": { + "version": "0.47.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-ioredis/-/instrumentation-ioredis-0.47.1.tgz", + "integrity": "sha512-OtFGSN+kgk/aoKgdkKQnBsQFDiG8WdCxu+UrHr0bXScdAmtSzLSraLo7wFIb25RVHfRWvzI5kZomqJYEg/l1iA==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@opentelemetry/instrumentation": "^0.57.1", + "@opentelemetry/redis-common": "^0.36.2", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-kafkajs": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-kafkajs/-/instrumentation-kafkajs-0.7.1.tgz", + "integrity": "sha512-OtjaKs8H7oysfErajdYr1yuWSjMAectT7Dwr+axIoZqT9lmEOkD/H/3rgAs8h/NIuEi2imSXD+vL4MZtOuJfqQ==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@opentelemetry/instrumentation": "^0.57.1", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-knex": { + "version": "0.44.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-knex/-/instrumentation-knex-0.44.1.tgz", + "integrity": "sha512-U4dQxkNhvPexffjEmGwCq68FuftFK15JgUF05y/HlK3M6W/G2iEaACIfXdSnwVNe9Qh0sPfw8LbOPxrWzGWGMQ==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@opentelemetry/instrumentation": "^0.57.1", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-koa": { + "version": "0.47.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-koa/-/instrumentation-koa-0.47.1.tgz", + "integrity": "sha512-l/c+Z9F86cOiPJUllUCt09v+kICKvT+Vg1vOAJHtHPsJIzurGayucfCMq2acd/A/yxeNWunl9d9eqZ0G+XiI6A==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.57.1", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-lru-memoizer": { + "version": "0.44.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-lru-memoizer/-/instrumentation-lru-memoizer-0.44.1.tgz", + "integrity": "sha512-5MPkYCvG2yw7WONEjYj5lr5JFehTobW7wX+ZUFy81oF2lr9IPfZk9qO+FTaM0bGEiymwfLwKe6jE15nHn1nmHg==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@opentelemetry/instrumentation": "^0.57.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-mongodb": { + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mongodb/-/instrumentation-mongodb-0.52.0.tgz", + "integrity": "sha512-1xmAqOtRUQGR7QfJFfGV/M2kC7wmI2WgZdpru8hJl3S0r4hW0n3OQpEHlSGXJAaNFyvT+ilnwkT+g5L4ljHR6g==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@opentelemetry/instrumentation": "^0.57.1", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-mongoose": { + "version": "0.46.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mongoose/-/instrumentation-mongoose-0.46.1.tgz", + "integrity": "sha512-3kINtW1LUTPkiXFRSSBmva1SXzS/72we/jL22N+BnF3DFcoewkdkHPYOIdAAk9gSicJ4d5Ojtt1/HeibEc5OQg==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.57.1", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-mysql": { + "version": "0.45.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mysql/-/instrumentation-mysql-0.45.1.tgz", + "integrity": "sha512-TKp4hQ8iKQsY7vnp/j0yJJ4ZsP109Ht6l4RHTj0lNEG1TfgTrIH5vJMbgmoYXWzNHAqBH2e7fncN12p3BP8LFg==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@opentelemetry/instrumentation": "^0.57.1", + "@opentelemetry/semantic-conventions": "^1.27.0", + "@types/mysql": "2.15.26" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-mysql2": { + "version": "0.45.2", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mysql2/-/instrumentation-mysql2-0.45.2.tgz", + "integrity": "sha512-h6Ad60FjCYdJZ5DTz1Lk2VmQsShiViKe0G7sYikb0GHI0NVvApp2XQNRHNjEMz87roFttGPLHOYVPlfy+yVIhQ==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@opentelemetry/instrumentation": "^0.57.1", + "@opentelemetry/semantic-conventions": "^1.27.0", + "@opentelemetry/sql-common": "^0.40.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-pg": { + "version": "0.51.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-pg/-/instrumentation-pg-0.51.1.tgz", + "integrity": "sha512-QxgjSrxyWZc7Vk+qGSfsejPVFL1AgAJdSBMYZdDUbwg730D09ub3PXScB9d04vIqPriZ+0dqzjmQx0yWKiCi2Q==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@opentelemetry/core": "^1.26.0", + "@opentelemetry/instrumentation": "^0.57.1", + "@opentelemetry/semantic-conventions": "^1.27.0", + "@opentelemetry/sql-common": "^0.40.1", + "@types/pg": "8.6.1", + "@types/pg-pool": "2.0.6" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-redis-4": { + "version": "0.46.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-redis-4/-/instrumentation-redis-4-0.46.1.tgz", + "integrity": "sha512-UMqleEoabYMsWoTkqyt9WAzXwZ4BlFZHO40wr3d5ZvtjKCHlD4YXLm+6OLCeIi/HkX7EXvQaz8gtAwkwwSEvcQ==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@opentelemetry/instrumentation": "^0.57.1", + "@opentelemetry/redis-common": "^0.36.2", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-tedious": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-tedious/-/instrumentation-tedious-0.18.1.tgz", + "integrity": "sha512-5Cuy/nj0HBaH+ZJ4leuD7RjgvA844aY2WW+B5uLcWtxGjRZl3MNLuxnNg5DYWZNPO+NafSSnra0q49KWAHsKBg==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@opentelemetry/instrumentation": "^0.57.1", + "@opentelemetry/semantic-conventions": "^1.27.0", + "@types/tedious": "^4.0.14" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-undici": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-undici/-/instrumentation-undici-0.10.1.tgz", + "integrity": "sha512-rkOGikPEyRpMCmNu9AQuV5dtRlDmJp2dK5sw8roVshAGoB6hH/3QjDtRhdwd75SsJwgynWUNRUYe0wAkTo16tQ==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.57.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.7.0" + } + }, + "node_modules/@opentelemetry/redis-common": { + "version": "0.36.2", + "resolved": "https://registry.npmjs.org/@opentelemetry/redis-common/-/redis-common-0.36.2.tgz", + "integrity": "sha512-faYX1N0gpLhej/6nyp6bgRjzAKXn5GOEMYY7YhciSfCoITAktLUtQ36d24QEWNA1/WA1y6qQunCe0OhHRkVl9g==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/resources": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.30.1.tgz", + "integrity": "sha512-5UxZqiAgLYGFjS4s9qm5mBVo433u+dSPUFWVWXmLAD4wB65oMCoXaJP1KJa9DIYYMeHu3z4BZcStG3LC593cWA==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@opentelemetry/core": "1.30.1", + "@opentelemetry/semantic-conventions": "1.28.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/resources/node_modules/@opentelemetry/semantic-conventions": { + "version": "1.28.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.28.0.tgz", + "integrity": "sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/sdk-trace-base": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.30.1.tgz", + "integrity": "sha512-jVPgBbH1gCy2Lb7X0AVQ8XAfgg0pJ4nvl8/IiQA6nxOsPvS+0zMJaFSs2ltXe0J6C8dqjcnpyqINDJmU30+uOg==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@opentelemetry/core": "1.30.1", + "@opentelemetry/resources": "1.30.1", + "@opentelemetry/semantic-conventions": "1.28.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/sdk-trace-base/node_modules/@opentelemetry/semantic-conventions": { + "version": "1.28.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.28.0.tgz", + "integrity": "sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/semantic-conventions": { + "version": "1.36.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.36.0.tgz", + "integrity": "sha512-TtxJSRD8Ohxp6bKkhrm27JRHAxPczQA7idtcTOMYI+wQRRrfgqxHv1cFbCApcSnNjtXkmzFozn6jQtFrOmbjPQ==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/sql-common": { + "version": "0.40.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sql-common/-/sql-common-0.40.1.tgz", + "integrity": "sha512-nSDlnHSqzC3pXn/wZEZVLuAuJ1MYMXPBwtv2qAbCa3847SaHItdE7SzUq/Jtb0KZmh1zfAbNi3AAMjztTT4Ugg==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@opentelemetry/core": "^1.1.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.1.0" + } + }, + "node_modules/@prisma/instrumentation": { + "version": "6.11.1", + "resolved": "https://registry.npmjs.org/@prisma/instrumentation/-/instrumentation-6.11.1.tgz", + "integrity": "sha512-mrZOev24EDhnefmnZX7WVVT7v+r9LttPRqf54ONvj6re4XMF7wFTpK2tLJi4XHB7fFp/6xhYbgRel8YV7gQiyA==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@opentelemetry/instrumentation": "^0.52.0 || ^0.53.0 || ^0.54.0 || ^0.55.0 || ^0.56.0 || ^0.57.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.8" + } + }, + "node_modules/@sentry/core": { + "version": "9.44.1", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-9.44.1.tgz", + "integrity": "sha512-F+90dYxTRLOmkEWieArDHn4kiS3ZY48hNiBpt+GBqe7ooAHMaS4AlBWUuJZZ7fTbRpfoWVwDgGKDAoX5CSAIHg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry/node": { + "version": "9.44.1", + "resolved": "https://registry.npmjs.org/@sentry/node/-/node-9.44.1.tgz", + "integrity": "sha512-uarPyFRN7Gwo/X/NTPFRTFhv/VfDfu3TTCLgK/nyetEpIejHbjLVDt7zjTvLsxLeZJO923v2d6NCldTokiI8fQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "@opentelemetry/api": "^1.9.0", + "@opentelemetry/context-async-hooks": "^1.30.1", + "@opentelemetry/core": "^1.30.1", + "@opentelemetry/instrumentation": "^0.57.2", + "@opentelemetry/instrumentation-amqplib": "^0.46.1", + "@opentelemetry/instrumentation-connect": "0.43.1", + "@opentelemetry/instrumentation-dataloader": "0.16.1", + "@opentelemetry/instrumentation-express": "0.47.1", + "@opentelemetry/instrumentation-fs": "0.19.1", + "@opentelemetry/instrumentation-generic-pool": "0.43.1", + "@opentelemetry/instrumentation-graphql": "0.47.1", + "@opentelemetry/instrumentation-hapi": "0.45.2", + "@opentelemetry/instrumentation-http": "0.57.2", + "@opentelemetry/instrumentation-ioredis": "0.47.1", + "@opentelemetry/instrumentation-kafkajs": "0.7.1", + "@opentelemetry/instrumentation-knex": "0.44.1", + "@opentelemetry/instrumentation-koa": "0.47.1", + "@opentelemetry/instrumentation-lru-memoizer": "0.44.1", + "@opentelemetry/instrumentation-mongodb": "0.52.0", + "@opentelemetry/instrumentation-mongoose": "0.46.1", + "@opentelemetry/instrumentation-mysql": "0.45.1", + "@opentelemetry/instrumentation-mysql2": "0.45.2", + "@opentelemetry/instrumentation-pg": "0.51.1", + "@opentelemetry/instrumentation-redis-4": "0.46.1", + "@opentelemetry/instrumentation-tedious": "0.18.1", + "@opentelemetry/instrumentation-undici": "0.10.1", + "@opentelemetry/resources": "^1.30.1", + "@opentelemetry/sdk-trace-base": "^1.30.1", + "@opentelemetry/semantic-conventions": "^1.34.0", + "@prisma/instrumentation": "6.11.1", + "@sentry/core": "9.44.1", + "@sentry/node-core": "9.44.1", + "@sentry/opentelemetry": "9.44.1", + "import-in-the-middle": "^1.14.2", + "minimatch": "^9.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry/node-core": { + "version": "9.44.1", + "resolved": "https://registry.npmjs.org/@sentry/node-core/-/node-core-9.44.1.tgz", + "integrity": "sha512-2L+sucAsdDDQwjlvhiAaM+Tk+5gJIwJ7u5JU+Lr8z0fAd9ddbV6ExTY51U/UYCqjzYCZ6z/+GHspyIlSHbJGsw==", + "license": "MIT", + "optional": true, + "dependencies": { + "@sentry/core": "9.44.1", + "@sentry/opentelemetry": "9.44.1", + "import-in-the-middle": "^1.14.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.9.0", + "@opentelemetry/context-async-hooks": "^1.30.1 || ^2.0.0", + "@opentelemetry/core": "^1.30.1 || ^2.0.0", + "@opentelemetry/instrumentation": ">=0.57.1 <1", + "@opentelemetry/resources": "^1.30.1 || ^2.0.0", + "@opentelemetry/sdk-trace-base": "^1.30.1 || ^2.0.0", + "@opentelemetry/semantic-conventions": "^1.34.0" + } + }, + "node_modules/@sentry/node/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "license": "ISC", + "optional": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@sentry/opentelemetry": { + "version": "9.44.1", + "resolved": "https://registry.npmjs.org/@sentry/opentelemetry/-/opentelemetry-9.44.1.tgz", + "integrity": "sha512-+sQn/3+Il4aYehhruxfru0inkqsVZX78AZ8Lb3zj/YfH4G9WPiLOEn/ZgYgTgwYf/c4emY62XVdNejXgSP12cA==", + "license": "MIT", + "optional": true, + "dependencies": { + "@sentry/core": "9.44.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.9.0", + "@opentelemetry/context-async-hooks": "^1.30.1 || ^2.0.0", + "@opentelemetry/core": "^1.30.1 || ^2.0.0", + "@opentelemetry/sdk-trace-base": "^1.30.1 || ^2.0.0", + "@opentelemetry/semantic-conventions": "^1.34.0" + } + }, + "node_modules/@swc/helpers": { + "version": "0.5.15", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz", + "integrity": "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.8.0" + } + }, + "node_modules/@tailwindcss/node": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.11.tgz", + "integrity": "sha512-yzhzuGRmv5QyU9qLNg4GTlYI6STedBWRE7NjxP45CsFYYq9taI0zJXZBMqIC/c8fViNLhmrbpSFS57EoxUmD6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@ampproject/remapping": "^2.3.0", + "enhanced-resolve": "^5.18.1", + "jiti": "^2.4.2", + "lightningcss": "1.30.1", + "magic-string": "^0.30.17", + "source-map-js": "^1.2.1", + "tailwindcss": "4.1.11" + } + }, + "node_modules/@tailwindcss/oxide": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.11.tgz", + "integrity": "sha512-Q69XzrtAhuyfHo+5/HMgr1lAiPP/G40OMFAnws7xcFEYqcypZmdW8eGXaOUIeOl1dzPJBPENXgbjsOyhg2nkrg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "detect-libc": "^2.0.4", + "tar": "^7.4.3" + }, + "engines": { + "node": ">= 10" + }, + "optionalDependencies": { + "@tailwindcss/oxide-android-arm64": "4.1.11", + "@tailwindcss/oxide-darwin-arm64": "4.1.11", + "@tailwindcss/oxide-darwin-x64": "4.1.11", + "@tailwindcss/oxide-freebsd-x64": "4.1.11", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.11", + "@tailwindcss/oxide-linux-arm64-gnu": "4.1.11", + "@tailwindcss/oxide-linux-arm64-musl": "4.1.11", + "@tailwindcss/oxide-linux-x64-gnu": "4.1.11", + "@tailwindcss/oxide-linux-x64-musl": "4.1.11", + "@tailwindcss/oxide-wasm32-wasi": "4.1.11", + "@tailwindcss/oxide-win32-arm64-msvc": "4.1.11", + "@tailwindcss/oxide-win32-x64-msvc": "4.1.11" + } + }, + "node_modules/@tailwindcss/oxide-android-arm64": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.11.tgz", + "integrity": "sha512-3IfFuATVRUMZZprEIx9OGDjG3Ou3jG4xQzNTvjDoKmU9JdmoCohQJ83MYd0GPnQIu89YoJqvMM0G3uqLRFtetg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-darwin-arm64": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.11.tgz", + "integrity": "sha512-ESgStEOEsyg8J5YcMb1xl8WFOXfeBmrhAwGsFxxB2CxY9evy63+AtpbDLAyRkJnxLy2WsD1qF13E97uQyP1lfQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-darwin-x64": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.11.tgz", + "integrity": "sha512-EgnK8kRchgmgzG6jE10UQNaH9Mwi2n+yw1jWmof9Vyg2lpKNX2ioe7CJdf9M5f8V9uaQxInenZkOxnTVL3fhAw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-freebsd-x64": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.11.tgz", + "integrity": "sha512-xdqKtbpHs7pQhIKmqVpxStnY1skuNh4CtbcyOHeX1YBE0hArj2romsFGb6yUmzkq/6M24nkxDqU8GYrKrz+UcA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.11.tgz", + "integrity": "sha512-ryHQK2eyDYYMwB5wZL46uoxz2zzDZsFBwfjssgB7pzytAeCCa6glsiJGjhTEddq/4OsIjsLNMAiMlHNYnkEEeg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.11.tgz", + "integrity": "sha512-mYwqheq4BXF83j/w75ewkPJmPZIqqP1nhoghS9D57CLjsh3Nfq0m4ftTotRYtGnZd3eCztgbSPJ9QhfC91gDZQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-musl": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.11.tgz", + "integrity": "sha512-m/NVRFNGlEHJrNVk3O6I9ggVuNjXHIPoD6bqay/pubtYC9QIdAMpS+cswZQPBLvVvEF6GtSNONbDkZrjWZXYNQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-gnu": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.11.tgz", + "integrity": "sha512-YW6sblI7xukSD2TdbbaeQVDysIm/UPJtObHJHKxDEcW2exAtY47j52f8jZXkqE1krdnkhCMGqP3dbniu1Te2Fg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-musl": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.11.tgz", + "integrity": "sha512-e3C/RRhGunWYNC3aSF7exsQkdXzQ/M+aYuZHKnw4U7KQwTJotnWsGOIVih0s2qQzmEzOFIJ3+xt7iq67K/p56Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.11.tgz", + "integrity": "sha512-Xo1+/GU0JEN/C/dvcammKHzeM6NqKovG+6921MR6oadee5XPBaKOumrJCXvopJ/Qb5TH7LX/UAywbqrP4lax0g==", + "bundleDependencies": [ + "@napi-rs/wasm-runtime", + "@emnapi/core", + "@emnapi/runtime", + "@tybys/wasm-util", + "@emnapi/wasi-threads", + "tslib" + ], + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.4.3", + "@emnapi/runtime": "^1.4.3", + "@emnapi/wasi-threads": "^1.0.2", + "@napi-rs/wasm-runtime": "^0.2.11", + "@tybys/wasm-util": "^0.9.0", + "tslib": "^2.8.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.11.tgz", + "integrity": "sha512-UgKYx5PwEKrac3GPNPf6HVMNhUIGuUh4wlDFR2jYYdkX6pL/rn73zTq/4pzUm8fOjAn5L8zDeHp9iXmUGOXZ+w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-win32-x64-msvc": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.11.tgz", + "integrity": "sha512-YfHoggn1j0LK7wR82TOucWc5LDCguHnoS879idHekmmiR7g9HUtMw9MI0NHatS28u/Xlkfi9w5RJWgz2Dl+5Qg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/postcss": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.1.11.tgz", + "integrity": "sha512-q/EAIIpF6WpLhKEuQSEVMZNMIY8KhWoAemZ9eylNAih9jxMGAYPPWBn3I9QL/2jZ+e7OEz/tZkX5HwbBR4HohA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "@tailwindcss/node": "4.1.11", + "@tailwindcss/oxide": "4.1.11", + "postcss": "^8.4.41", + "tailwindcss": "4.1.11" + } + }, + "node_modules/@tanstack/query-core": { + "version": "5.83.1", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.83.1.tgz", + "integrity": "sha512-OG69LQgT7jSp+5pPuCfzltq/+7l2xoweggjme9vlbCPa/d7D7zaqv5vN/S82SzSYZ4EDLTxNO1PWrv49RAS64Q==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/react-query": { + "version": "5.84.1", + "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.84.1.tgz", + "integrity": "sha512-zo7EUygcWJMQfFNWDSG7CBhy8irje/XY0RDVKKV4IQJAysb+ZJkkJPcnQi+KboyGUgT+SQebRFoTqLuTtfoDLw==", + "license": "MIT", + "dependencies": { + "@tanstack/query-core": "5.83.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": "^18 || ^19" + } + }, + "node_modules/@types/braces": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/braces/-/braces-3.0.5.tgz", + "integrity": "sha512-SQFof9H+LXeWNz8wDe7oN5zu7ket0qwMu5vZubW4GCJ8Kkeh6nBWUz87+KTz/G3Kqsrp0j/W253XJb3KMEeg3w==", + "license": "MIT" + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "license": "MIT", + "optional": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/cookie": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.3.3.tgz", + "integrity": "sha512-LKVP3cgXBT9RYj+t+9FDKwS5tdI+rPBXaNSkma7hvqy35lc7mAokC2zsqWJH0LaqIt3B962nuYI77hsJoT1gow==", + "license": "MIT" + }, + "node_modules/@types/micromatch": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@types/micromatch/-/micromatch-4.0.9.tgz", + "integrity": "sha512-7V+8ncr22h4UoYRLnLXSpTxjQrNUXtWHGeMPRJt1nULXI57G9bIcpyrHlmrQ7QK24EyyuXvYcSSWAM8GA9nqCg==", + "license": "MIT", + "dependencies": { + "@types/braces": "*" + } + }, + "node_modules/@types/mysql": { + "version": "2.15.26", + "resolved": "https://registry.npmjs.org/@types/mysql/-/mysql-2.15.26.tgz", + "integrity": "sha512-DSLCOXhkvfS5WNNPbfn2KdICAmk8lLc+/PNvnPnF7gOdMZCxopXduqv0OQ13y/yA/zXTSikZZqVgybUxOEg6YQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/node": { + "version": "20.19.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.9.tgz", + "integrity": "sha512-cuVNgarYWZqxRJDQHEB58GEONhOK79QVR/qYx4S7kcUObQvUwvFnYxJuuHUKm2aieN9X3yZB4LZsuYNU1Qphsw==", + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/pg": { + "version": "8.6.1", + "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.6.1.tgz", + "integrity": "sha512-1Kc4oAGzAl7uqUStZCDvaLFqZrW9qWSjXOmBfdgyBP5La7Us6Mg4GBvRlSoaZMhQF/zSj1C8CtKMBkoiT8eL8w==", + "license": "MIT", + "optional": true, + "dependencies": { + "@types/node": "*", + "pg-protocol": "*", + "pg-types": "^2.2.0" + } + }, + "node_modules/@types/pg-pool": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/pg-pool/-/pg-pool-2.0.6.tgz", + "integrity": "sha512-TaAUE5rq2VQYxab5Ts7WZhKNmuN78Q6PiFonTDdpbx8a1H0M1vhy3rhiMjl+e2iHmogyMw7jZF4FrE6eJUy5HQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "@types/pg": "*" + } + }, + "node_modules/@types/react": { + "version": "19.1.9", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.9.tgz", + "integrity": "sha512-WmdoynAX8Stew/36uTSVMcLJJ1KRh6L3IZRx1PZ7qJtBqT3dYTgyDTx8H1qoRghErydW7xw9mSJ3wS//tCRpFA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "19.1.7", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.1.7.tgz", + "integrity": "sha512-i5ZzwYpqjmrKenzkoLM2Ibzt6mAsM7pxB6BCIouEVVmgiqaMj1TjaK7hnA36hbW5aZv20kx7Lw6hWzPWg0Rurw==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^19.0.0" + } + }, + "node_modules/@types/retry": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.5.tgz", + "integrity": "sha512-3xSjTp3v03X/lSQLkczaN9UIEwJMoMCA1+Nb5HfbJEQWogdeQIyVtTvxPXDQjZ5zws8rFQfVfRdz03ARihPJgw==", + "license": "MIT" + }, + "node_modules/@types/shimmer": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@types/shimmer/-/shimmer-1.2.0.tgz", + "integrity": "sha512-UE7oxhQLLd9gub6JKIAhDq06T0F6FnztwMNRvYgjeQSBeMc1ZG/tA47EwfduvkuQS8apbkM/lpLpWsaCeYsXVg==", + "license": "MIT", + "optional": true + }, + "node_modules/@types/tedious": { + "version": "4.0.14", + "resolved": "https://registry.npmjs.org/@types/tedious/-/tedious-4.0.14.tgz", + "integrity": "sha512-KHPsfX/FoVbUGbyYvk1q9MMQHLPeRZhRJZdO45Q4YjvFkv4hMNghCWTvy7rdKessBsmtz4euWCWAB6/tVpI1Iw==", + "license": "MIT", + "optional": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/ws": { + "version": "7.4.7", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.4.7.tgz", + "integrity": "sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "license": "ISC" + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "license": "MIT", + "optional": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-import-attributes": { + "version": "1.9.5", + "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", + "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", + "license": "MIT", + "optional": true, + "peerDependencies": { + "acorn": "^8" + } + }, + "node_modules/ansi-escapes": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.0.0.tgz", + "integrity": "sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==", + "license": "MIT", + "dependencies": { + "environment": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/ansi-term": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/ansi-term/-/ansi-term-0.0.2.tgz", + "integrity": "sha512-jLnGE+n8uAjksTJxiWZf/kcUmXq+cRWSl550B9NmQ8YiqaTM+lILcSe5dHdp8QkJPhaOghDjnMKwyYSMjosgAA==", + "license": "ISC", + "dependencies": { + "x256": ">=0.0.1" + } + }, + "node_modules/ansicolors": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/ansicolors/-/ansicolors-0.3.2.tgz", + "integrity": "sha512-QXu7BPrP29VllRxH8GwB7x5iX5qWKAAMLqKQGWTeLWVlNHNOpVMJ91dsxQAIWXpjuW5wqvxu3Jd/nRjrJ+0pqg==", + "license": "MIT" + }, + "node_modules/auto-bind": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/auto-bind/-/auto-bind-5.0.1.tgz", + "integrity": "sha512-ooviqdwwgfIfNmDwo94wlshcdzfO64XV0Cg6oDsDYBJfITDz1EngD2z7DkbvCWn+XIMsIqW27sEVF6qcpJrRcg==", + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/babel-polyfill": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz", + "integrity": "sha512-F2rZGQnAdaHWQ8YAoeRbukc7HS9QgdgeyJ0rQDd485v9opwuPvjpPFcOOT/WmkKTdgy9ESgSPXDcTNpzrGr6iQ==", + "license": "MIT", + "dependencies": { + "babel-runtime": "^6.26.0", + "core-js": "^2.5.0", + "regenerator-runtime": "^0.10.5" + } + }, + "node_modules/babel-polyfill/node_modules/regenerator-runtime": { + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", + "integrity": "sha512-02YopEIhAgiBHWeoTiA8aitHDt8z6w+rQqNuIftlM+ZtvSl/brTouaU7DW6GO/cHtvxJvS4Hwv2ibKdxIRi24w==", + "license": "MIT" + }, + "node_modules/babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==", + "license": "MIT", + "dependencies": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + } + }, + "node_modules/babel-runtime/node_modules/regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", + "license": "MIT" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT", + "optional": true + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "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/before-after-hook": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-4.0.0.tgz", + "integrity": "sha512-q6tR3RPqIB1pMiTRMFcZwuG5T8vwp+vUvEG0vuI6B+Rikh5BfPp2fQ82c925FOs+b0lcFQ8CFrL+KbilfZFhOQ==", + "license": "Apache-2.0" + }, + "node_modules/blessed": { + "version": "0.1.81", + "resolved": "https://registry.npmjs.org/blessed/-/blessed-0.1.81.tgz", + "integrity": "sha512-LoF5gae+hlmfORcG1M5+5XZi4LBmvlXTzwJWzUlPryN/SJdSflZvROM2TwkT0GMpq7oqT48NRd4GS7BiVBc5OQ==", + "license": "MIT", + "bin": { + "blessed": "bin/tput.js" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/blessed-contrib": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/blessed-contrib/-/blessed-contrib-4.11.0.tgz", + "integrity": "sha512-P00Xji3xPp53+FdU9f74WpvnOAn/SS0CKLy4vLAf5Ps7FGDOTY711ruJPZb3/7dpFuP+4i7f4a/ZTZdLlKG9WA==", + "license": "MIT", + "dependencies": { + "ansi-term": ">=0.0.2", + "chalk": "^1.1.0", + "drawille-canvas-blessed-contrib": ">=0.1.3", + "lodash": "~>=4.17.21", + "map-canvas": ">=0.1.5", + "marked": "^4.0.12", + "marked-terminal": "^5.1.1", + "memory-streams": "^0.1.0", + "memorystream": "^0.3.1", + "picture-tuber": "^1.0.1", + "sparkline": "^0.1.1", + "strip-ansi": "^3.0.0", + "term-canvas": "0.0.5", + "x256": ">=0.0.1" + } + }, + "node_modules/blessed-contrib/node_modules/ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/blessed-contrib/node_modules/chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/blessed-contrib/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/blessed-contrib/node_modules/supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/bresenham": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/bresenham/-/bresenham-0.0.3.tgz", + "integrity": "sha512-wbMxoJJM1p3+6G7xEFXYNCJ30h2qkwmVxebkbwIl4OcnWtno5R3UT9VuYLfStlVNAQCmRjkGwjPFdfaPd4iNXw==", + "license": "MIT" + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "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", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/buffers": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", + "integrity": "sha512-9q/rDEGSb/Qsvv2qvzIzdluL5k7AaJOTrw23z9reQthrbF7is4CtlT0DXyO1oei2DCp4uojjzQ7igaSHp1kAEQ==", + "engines": { + "node": ">=0.2.0" + } + }, + "node_modules/call-bind": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.0", + "es-define-property": "^1.0.0", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001731", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001731.tgz", + "integrity": "sha512-lDdp2/wrOmTRWuoB5DpfNkC0rJDU8DqRa6nYL6HK6sytw70QMopt/NIc/9SM7ylItlBWfACXk0tEn37UWM/+mg==", + "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/cardinal": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/cardinal/-/cardinal-2.1.1.tgz", + "integrity": "sha512-JSr5eOgoEymtYHBjNWyjrMqet9Am2miJhlfKNdqLp6zoeAh0KN5dRAcxlecj5mAJrmQomgiOBj35xHLrFjqBpw==", + "license": "MIT", + "dependencies": { + "ansicolors": "~0.3.2", + "redeyed": "~2.1.0" + }, + "bin": { + "cdl": "bin/cdl.js" + } + }, + "node_modules/chalk": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.5.0.tgz", + "integrity": "sha512-1tm8DTaJhPBG3bIkVeZt1iZM9GfSX2lzOeDVZH9R9ffRHpmHvxZ/QhgQH/aDTkswQVt+YHdXAdS/In/30OjCbg==", + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/charm": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/charm/-/charm-0.1.2.tgz", + "integrity": "sha512-syedaZ9cPe7r3hoQA9twWYKu5AIyCswN5+szkmPBe9ccdLrj4bYaCnLVPTLd2kgVRc7+zoX4tyPgRnFKCj5YjQ==", + "license": "MIT/X11" + }, + "node_modules/chownr": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "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==", + "license": "MIT", + "optional": true + }, + "node_modules/class-states": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/class-states/-/class-states-1.0.16.tgz", + "integrity": "sha512-DhQHga7pUo3LRfZawNIw+4yHBx9AncBAjXv4YXjwOLf06ZnxCR/hi2hPqMhZr//NhwhLlq9EmmWXM0o7BZgnNw==", + "license": "ISC" + }, + "node_modules/cli-boxes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", + "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", + "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", + "license": "MIT", + "dependencies": { + "restore-cursor": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-spinners": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-3.2.0.tgz", + "integrity": "sha512-pXftdQloMZzjCr3pCTIRniDcys6dDzgpgVhAHHk6TKBDbRuP1MkuetTF5KSv4YUutbOPa7+7ZrAJ2kVtbMqyXA==", + "license": "MIT", + "engines": { + "node": ">=18.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-table3": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz", + "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==", + "license": "MIT", + "dependencies": { + "string-width": "^4.2.0" + }, + "engines": { + "node": "10.* || >= 12.*" + }, + "optionalDependencies": { + "@colors/colors": "1.5.0" + } + }, + "node_modules/cli-truncate": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", + "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", + "license": "MIT", + "dependencies": { + "slice-ansi": "^5.0.0", + "string-width": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/cli-truncate/node_modules/emoji-regex": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", + "license": "MIT" + }, + "node_modules/cli-truncate/node_modules/slice-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", + "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.0.0", + "is-fullwidth-code-point": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/cli-truncate/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/client-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", + "license": "MIT" + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cliui/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==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/cliui/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==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/code-excerpt": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/code-excerpt/-/code-excerpt-4.0.0.tgz", + "integrity": "sha512-xxodCmBen3iy2i0WtAK8FlFNrRzjUqjRsMfho58xT/wvZU1YTM3fCnRjcy1gJPMepaRlgm/0e6w8SpWHpn3/cA==", + "license": "MIT", + "dependencies": { + "convert-to-spaces": "^2.0.1" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.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==", + "license": "MIT", + "optional": true, + "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==", + "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==", + "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==", + "license": "MIT", + "optional": true, + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "node_modules/convert-to-spaces": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/convert-to-spaces/-/convert-to-spaces-2.0.1.tgz", + "integrity": "sha512-rcQ1bsQO9799wq24uE5AM2tAILy4gXGIK/njFWcVQkGNZ96edlpY+A7bjwvzjYvLDyzmG1MmMLZhpcsb+klNMQ==", + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/core-js": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.0.tgz", + "integrity": "sha512-kLRC6ncVpuEW/1kwrOXYX6KQASCVtrh1gQr/UiaVgFlf9WE5Vp+lNe5+h3LuMr5PAucWnnEXwH0nQHRH/gpGtw==", + "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.", + "license": "MIT" + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "license": "MIT" + }, + "node_modules/cross-fetch": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.1.0.tgz", + "integrity": "sha512-uKm5PU+MHTootlWEY+mZ4vvXoCn4fLQxT9dSc1sXVMSFkINTJVN8cAQROpwcKm8bJ/c7rgZVIBWzH5T78sNZZw==", + "license": "MIT", + "dependencies": { + "node-fetch": "^2.7.0" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/detect-libc": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz", + "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==", + "devOptional": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/dotenv": { + "version": "16.6.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", + "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/drawille-blessed-contrib": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/drawille-blessed-contrib/-/drawille-blessed-contrib-1.0.0.tgz", + "integrity": "sha512-WnHMgf5en/hVOsFhxLI8ZX0qTJmerOsVjIMQmn4cR1eI8nLGu+L7w5ENbul+lZ6w827A3JakCuernES5xbHLzQ==", + "license": "MIT" + }, + "node_modules/drawille-canvas-blessed-contrib": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/drawille-canvas-blessed-contrib/-/drawille-canvas-blessed-contrib-0.1.3.tgz", + "integrity": "sha512-bdDvVJOxlrEoPLifGDPaxIzFh3cD7QH05ePoQ4fwnqfi08ZSxzEhOUpI5Z0/SQMlWgcCQOEtuw0zrwezacXglw==", + "license": "MIT", + "dependencies": { + "ansi-term": ">=0.0.2", + "bresenham": "0.0.3", + "drawille-blessed-contrib": ">=0.0.1", + "gl-matrix": "^2.1.0", + "x256": ">=0.0.1" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/enhanced-resolve": { + "version": "5.18.2", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.2.tgz", + "integrity": "sha512-6Jw4sE1maoRJo3q8MsSIn2onJFbLTOjY9hlx4DZXmOKvLRd1Ok2kXmAGXaafL2+ijsJZ1ClYbl/pmqr9+k4iUQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/environment": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", + "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-toolkit": { + "version": "1.39.8", + "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.39.8.tgz", + "integrity": "sha512-A8QO9TfF+rltS8BXpdu8OS+rpGgEdnRhqIVxO/ZmNvnXBYgOdSsxukT55ELyP94gZIntWJ+Li9QRrT2u1Kitpg==", + "license": "MIT", + "workspaces": [ + "docs", + "benchmarks" + ] + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "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==", + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/event-stream": { + "version": "0.9.8", + "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-0.9.8.tgz", + "integrity": "sha512-o5h0Mp1bkoR6B0i7pTCAzRy+VzdsRWH997KQD4Psb0EOPoKEIiaRx/EsOdUl7p1Ktjw7aIWvweI/OY1R9XrlUg==", + "dependencies": { + "optimist": "0.2" + }, + "engines": { + "node": "*" + } + }, + "node_modules/event-stream/node_modules/optimist": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.2.8.tgz", + "integrity": "sha512-Wy7E3cQDpqsTIFyW7m22hSevyTLxw850ahYv7FWsw4G6MIKVTZ8NSA95KBrQ95a4SMsMr1UGUUnwEFKhVaSzIg==", + "license": "MIT/X11", + "dependencies": { + "wordwrap": ">=0.0.1 <0.1.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "license": "MIT" + }, + "node_modules/fast-content-type-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/fast-content-type-parse/-/fast-content-type-parse-3.0.0.tgz", + "integrity": "sha512-ZvLdcY8P+N8mGQJahJV5G4U88CSvT1rP8ApL6uETe88MBXrBHAkZlSEySdUlyztF7ccb+Znos3TFqaepHxdhBg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT" + }, + "node_modules/fast-deep-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz", + "integrity": "sha512-46+Jxk9Yj/nQY+3a1KTnpbBTemcAbPySTKya8iM9D7EsiONpSWbvzesalcCJ6tmJrCUITT2fmAQfNHFG+OHM6Q==", + "license": "MIT" + }, + "node_modules/figures": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-6.1.0.tgz", + "integrity": "sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==", + "license": "MIT", + "dependencies": { + "is-unicode-supported": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/flow-static-land": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/flow-static-land/-/flow-static-land-0.2.7.tgz", + "integrity": "sha512-SmGgln4qcqLAysXM5BF8EQS+clj0TUf9+KlZUJgwuzNHvwbput+opz3CMyee9sDuLf4J/3sJbYGjdNsd2jSurA==", + "license": "MIT" + }, + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/forwarded-parse": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/forwarded-parse/-/forwarded-parse-2.1.2.tgz", + "integrity": "sha512-alTFZZQDKMporBH77856pXgzhEzaUVmLCDk+egLgIgHst3Tpndzz8MnKe+GzRJRfvVdn69HhpW7cmXzvtLvJAw==", + "license": "MIT", + "optional": true + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-east-asian-width": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.3.0.tgz", + "integrity": "sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-graphql-schema": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/get-graphql-schema/-/get-graphql-schema-2.1.2.tgz", + "integrity": "sha512-1z5Hw91VrE3GrpCZE6lE8Dy+jz4kXWesLS7rCSjwOxf5BOcIedAZeTUJRIeIzmmR+PA9CKOkPTYFRJbdgUtrxA==", + "license": "MIT", + "dependencies": { + "chalk": "^2.4.1", + "graphql": "^14.0.2", + "minimist": "^1.2.0", + "node-fetch": "^2.2.0" + }, + "bin": { + "get-graphql-schema": "dist/index.js" + } + }, + "node_modules/get-graphql-schema/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/get-graphql-schema/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/get-graphql-schema/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/get-graphql-schema/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "license": "MIT" + }, + "node_modules/get-graphql-schema/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/get-graphql-schema/node_modules/graphql": { + "version": "14.7.0", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-14.7.0.tgz", + "integrity": "sha512-l0xWZpoPKpppFzMfvVyFmp9vLN7w/ZZJPefUicMCepfJeQ8sMcztloGYY9DfjVPo6tIUDzU5Hw3MUbIjj9AVVA==", + "deprecated": "No longer supported; please update to a newer version. Details: https://github.com/graphql/graphql-js#version-support", + "license": "MIT", + "dependencies": { + "iterall": "^1.2.2" + }, + "engines": { + "node": ">= 6.x" + } + }, + "node_modules/get-graphql-schema/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/get-graphql-schema/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gl-matrix": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/gl-matrix/-/gl-matrix-2.8.1.tgz", + "integrity": "sha512-0YCjVpE3pS5XWlN3J4X7AiAx65+nqAI54LndtVFnQZB6G/FVLkZH8y8V6R3cIoOQR4pUdfwQGd1iwyoXHJ4Qfw==", + "license": "MIT" + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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/graphql": { + "version": "16.11.0", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.11.0.tgz", + "integrity": "sha512-mS1lbMsxgQj6hge1XZ6p7GPhbrtFwUFYi3wRzXAC/FmYnyXMTvvI3td3rjmQ2u8ewXueaSvRPWaEcgVVOT9Jnw==", + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" + } + }, + "node_modules/has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/here": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/here/-/here-0.0.2.tgz", + "integrity": "sha512-U7VYImCTcPoY27TSmzoiFsmWLEqQFaYNdpsPb9K0dXJhE6kufUqycaz51oR09CW85dDU9iWyy7At8M+p7hb3NQ==", + "license": "MIT" + }, + "node_modules/humps": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/humps/-/humps-2.0.1.tgz", + "integrity": "sha512-E0eIbrFWUhwfXJmsbdjRQFQPrl5pTEoKlz163j1mTqqUnU9PgR4AgB8AIITzuB3vLBdxZXyZ9TDIrwB2OASz4g==", + "license": "MIT" + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "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": "BSD-3-Clause" + }, + "node_modules/immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", + "license": "MIT" + }, + "node_modules/import-in-the-middle": { + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.14.2.tgz", + "integrity": "sha512-5tCuY9BV8ujfOpwtAGgsTx9CGUapcFMEEyByLv1B+v2+6DhAcw+Zr0nhQT7uwaZ7DiourxFEscghOR8e1aPLQw==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "acorn": "^8.14.0", + "acorn-import-attributes": "^1.9.5", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" + } + }, + "node_modules/indent-string": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", + "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ink": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ink/-/ink-6.1.0.tgz", + "integrity": "sha512-YQ+lbMD79y3FBAJXXZnuRajLEgaMFp102361eY5NrBIEVCi9oFo7gNZU4z2LBWlcjZFiTt7jetlkIbKCCH4KJA==", + "license": "MIT", + "dependencies": { + "@alcalzone/ansi-tokenize": "^0.1.3", + "ansi-escapes": "^7.0.0", + "ansi-styles": "^6.2.1", + "auto-bind": "^5.0.1", + "chalk": "^5.3.0", + "cli-boxes": "^3.0.0", + "cli-cursor": "^4.0.0", + "cli-truncate": "^4.0.0", + "code-excerpt": "^4.0.0", + "es-toolkit": "^1.22.0", + "indent-string": "^5.0.0", + "is-in-ci": "^1.0.0", + "patch-console": "^2.0.0", + "react-reconciler": "^0.32.0", + "scheduler": "^0.23.0", + "signal-exit": "^3.0.7", + "slice-ansi": "^7.1.0", + "stack-utils": "^2.0.6", + "string-width": "^7.2.0", + "type-fest": "^4.27.0", + "widest-line": "^5.0.0", + "wrap-ansi": "^9.0.0", + "ws": "^8.18.0", + "yoga-layout": "~3.2.1" + }, + "engines": { + "node": ">=20" + }, + "peerDependencies": { + "@types/react": ">=19.0.0", + "react": ">=19.0.0", + "react-devtools-core": "^4.19.1" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "react-devtools-core": { + "optional": true + } + } + }, + "node_modules/ink/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ink/node_modules/emoji-regex": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", + "license": "MIT" + }, + "node_modules/ink/node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/ink/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ink/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/ink/node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-arguments": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz", + "integrity": "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", + "license": "MIT", + "optional": true + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "license": "MIT", + "optional": true, + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", + "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-generator-function": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz", + "integrity": "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "get-proto": "^1.0.0", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-in-ci": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-in-ci/-/is-in-ci-1.0.0.tgz", + "integrity": "sha512-eUuAjybVTHMYWm/U+vBO1sY/JOCgoPCXRxzdju0K+K0BiGW0SChEL1MLC0PoCIR1OlPo5YAp8HuQoUlsWEICwg==", + "license": "MIT", + "bin": { + "is-in-ci": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-interactive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz", + "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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==", + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "license": "MIT", + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-unicode-supported": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz", + "integrity": "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "license": "MIT" + }, + "node_modules/isbinaryfile": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-5.0.4.tgz", + "integrity": "sha512-YKBKVkKhty7s8rxddb40oOkuP0NbaeXrQvLin6QMHL7Ypiy2RW9LwOVrVgZRyOrhQlayMd9t+D8yDy8MKFTSDQ==", + "license": "MIT", + "engines": { + "node": ">= 18.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/gjtorikian/" + } + }, + "node_modules/isomorphic-ws": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz", + "integrity": "sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==", + "license": "MIT", + "peerDependencies": { + "ws": "*" + } + }, + "node_modules/iterall": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/iterall/-/iterall-1.3.0.tgz", + "integrity": "sha512-QZ9qOMdF+QLHxy1QIpUHUU1D5pS2CG2P69LF6L6CPjPYA/XMOmKV3PZpawHoAjHNyB0swdVTRxdYT4tbBbxqwg==", + "license": "MIT" + }, + "node_modules/jiti": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.5.1.tgz", + "integrity": "sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w==", + "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-untar": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/js-untar/-/js-untar-2.0.0.tgz", + "integrity": "sha512-7CsDLrYQMbLxDt2zl9uKaPZSdmJMvGGQ7wo9hoB3J+z/VcO2w63bXFgHVnjF1+S9wD3zAu8FBVj7EYWjTQ3Z7g==", + "license": "MIT" + }, + "node_modules/jszip": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", + "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", + "license": "(MIT OR GPL-3.0-or-later)", + "dependencies": { + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "setimmediate": "^1.0.5" + } + }, + "node_modules/lie": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "license": "MIT", + "dependencies": { + "immediate": "~3.0.5" + } + }, + "node_modules/lightningcss": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.1.tgz", + "integrity": "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-darwin-arm64": "1.30.1", + "lightningcss-darwin-x64": "1.30.1", + "lightningcss-freebsd-x64": "1.30.1", + "lightningcss-linux-arm-gnueabihf": "1.30.1", + "lightningcss-linux-arm64-gnu": "1.30.1", + "lightningcss-linux-arm64-musl": "1.30.1", + "lightningcss-linux-x64-gnu": "1.30.1", + "lightningcss-linux-x64-musl": "1.30.1", + "lightningcss-win32-arm64-msvc": "1.30.1", + "lightningcss-win32-x64-msvc": "1.30.1" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.1.tgz", + "integrity": "sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.1.tgz", + "integrity": "sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.1.tgz", + "integrity": "sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.1.tgz", + "integrity": "sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.1.tgz", + "integrity": "sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.1.tgz", + "integrity": "sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.1.tgz", + "integrity": "sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.1.tgz", + "integrity": "sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.1.tgz", + "integrity": "sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.1.tgz", + "integrity": "sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "license": "MIT" + }, + "node_modules/log-symbols": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-6.0.0.tgz", + "integrity": "sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==", + "license": "MIT", + "dependencies": { + "chalk": "^5.3.0", + "is-unicode-supported": "^1.3.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-symbols/node_modules/is-unicode-supported": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", + "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lru_map": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/lru_map/-/lru_map-0.4.1.tgz", + "integrity": "sha512-I+lBvqMMFfqaV8CJCISjI3wbjmwVu/VyOoU7+qtu9d7ioW5klMgsTTiUOUp+DJvfTTzKXoPbyC6YfgkNcyPSOg==", + "license": "MIT" + }, + "node_modules/magic-string": { + "version": "0.30.17", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", + "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, + "node_modules/map-canvas": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/map-canvas/-/map-canvas-0.1.5.tgz", + "integrity": "sha512-f7M3sOuL9+up0NCOZbb1rQpWDLZwR/ftCiNbyscjl9LUUEwrRaoumH4sz6swgs58lF21DQ0hsYOCw5C6Zz7hbg==", + "license": "ISC", + "dependencies": { + "drawille-canvas-blessed-contrib": ">=0.0.1", + "xml2js": "^0.4.5" + } + }, + "node_modules/marked": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", + "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", + "license": "MIT", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/marked-terminal": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/marked-terminal/-/marked-terminal-5.2.0.tgz", + "integrity": "sha512-Piv6yNwAQXGFjZSaiNljyNFw7jKDdGrw70FSbtxEyldLsyeuV5ZHm/1wW++kWbrOF1VPnUgYOhB2oLL0ZpnekA==", + "license": "MIT", + "dependencies": { + "ansi-escapes": "^6.2.0", + "cardinal": "^2.1.1", + "chalk": "^5.2.0", + "cli-table3": "^0.6.3", + "node-emoji": "^1.11.0", + "supports-hyperlinks": "^2.3.0" + }, + "engines": { + "node": ">=14.13.1 || >=16.0.0" + }, + "peerDependencies": { + "marked": "^1.0.0 || ^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0" + } + }, + "node_modules/marked-terminal/node_modules/ansi-escapes": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.1.tgz", + "integrity": "sha512-4nJ3yixlEthEJ9Rk4vPcdBRkZvQZlYyu8j4/Mqz5sgIkddmEnH2Yj2ZrnP9S3tQOvSNRUIgVNF/1yPpRAGNRig==", + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/memory-streams": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/memory-streams/-/memory-streams-0.1.3.tgz", + "integrity": "sha512-qVQ/CjkMyMInPaaRMrwWNDvf6boRZXaT/DbQeMYcCWuXPEBf1v8qChOc9OlEVQp2uOvRXa1Qu30fLmKhY6NipA==", + "license": "MIT", + "dependencies": { + "readable-stream": "~1.0.2" + } + }, + "node_modules/memory-streams/node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", + "license": "MIT" + }, + "node_modules/memory-streams/node_modules/readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg==", + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/memory-streams/node_modules/string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==", + "license": "MIT" + }, + "node_modules/memorystream": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", + "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==", + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.3.tgz", + "integrity": "sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw==", + "license": "ISC", + "dependencies": { + "@isaacs/brace-expansion": "^5.0.0" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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/minizlib": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.2.tgz", + "integrity": "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==", + "dev": true, + "license": "MIT", + "dependencies": { + "minipass": "^7.1.2" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/mkdirp": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", + "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", + "dev": true, + "license": "MIT", + "bin": { + "mkdirp": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/module-details-from-path": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/module-details-from-path/-/module-details-from-path-1.0.4.tgz", + "integrity": "sha512-EGWKgxALGMgzvxYF1UyGTy0HXX/2vHLkw6+NvDKW2jypWbHpjQuj4UMcqQWXHERJhVGKikolT06G3bcKe4fi7w==", + "license": "MIT", + "optional": true + }, + "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==", + "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/next": { + "version": "15.4.5", + "resolved": "https://registry.npmjs.org/next/-/next-15.4.5.tgz", + "integrity": "sha512-nJ4v+IO9CPmbmcvsPebIoX3Q+S7f6Fu08/dEWu0Ttfa+wVwQRh9epcmsyCPjmL2b8MxC+CkBR97jgDhUUztI3g==", + "license": "MIT", + "dependencies": { + "@next/env": "15.4.5", + "@swc/helpers": "0.5.15", + "caniuse-lite": "^1.0.30001579", + "postcss": "8.4.31", + "styled-jsx": "5.1.6" + }, + "bin": { + "next": "dist/bin/next" + }, + "engines": { + "node": "^18.18.0 || ^19.8.0 || >= 20.0.0" + }, + "optionalDependencies": { + "@next/swc-darwin-arm64": "15.4.5", + "@next/swc-darwin-x64": "15.4.5", + "@next/swc-linux-arm64-gnu": "15.4.5", + "@next/swc-linux-arm64-musl": "15.4.5", + "@next/swc-linux-x64-gnu": "15.4.5", + "@next/swc-linux-x64-musl": "15.4.5", + "@next/swc-win32-arm64-msvc": "15.4.5", + "@next/swc-win32-x64-msvc": "15.4.5", + "sharp": "^0.34.3" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.1.0", + "@playwright/test": "^1.51.1", + "babel-plugin-react-compiler": "*", + "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", + "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", + "sass": "^1.3.0" + }, + "peerDependenciesMeta": { + "@opentelemetry/api": { + "optional": true + }, + "@playwright/test": { + "optional": true + }, + "babel-plugin-react-compiler": { + "optional": true + }, + "sass": { + "optional": true + } + } + }, + "node_modules/next/node_modules/postcss": { + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "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": { + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/node-emoji": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz", + "integrity": "sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==", + "license": "MIT", + "dependencies": { + "lodash": "^4.17.21" + } + }, + "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==", + "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/nopt": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-2.1.2.tgz", + "integrity": "sha512-x8vXm7BZ2jE1Txrxh/hO74HTuYZQEbo8edoRcANgdZ4+PCV+pbjd/xdummkmjjC7LU5EjPzlu8zEq/oxWylnKA==", + "license": "MIT", + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/oo-ascii-tree": { + "version": "1.113.0", + "resolved": "https://registry.npmjs.org/oo-ascii-tree/-/oo-ascii-tree-1.113.0.tgz", + "integrity": "sha512-9hGp+3S8qy0MSdBzp5pX2448Iv+w6QyXI6KBVihdt+Sb8nw1MxNu6ErMadTAXmyfCwZzZoEpn9hybTHEQuSJcQ==", + "license": "Apache-2.0", + "engines": { + "node": ">= 14.17.0" + } + }, + "node_modules/optimist": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.3.7.tgz", + "integrity": "sha512-TCx0dXQzVtSCg2OgY/bO9hjM9cV4XYx09TVK+s3+FhkjT6LovsLe+pPMzpWf+6yXK/hUizs2gUoTw3jHM0VaTQ==", + "license": "MIT/X11", + "dependencies": { + "wordwrap": "~0.0.2" + } + }, + "node_modules/ora": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/ora/-/ora-8.2.0.tgz", + "integrity": "sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw==", + "license": "MIT", + "dependencies": { + "chalk": "^5.3.0", + "cli-cursor": "^5.0.0", + "cli-spinners": "^2.9.2", + "is-interactive": "^2.0.0", + "is-unicode-supported": "^2.0.0", + "log-symbols": "^6.0.0", + "stdin-discarder": "^0.2.2", + "string-width": "^7.2.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ora/node_modules/cli-cursor": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", + "license": "MIT", + "dependencies": { + "restore-cursor": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/emoji-regex": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", + "license": "MIT" + }, + "node_modules/ora/node_modules/onetime": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", + "license": "MIT", + "dependencies": { + "mimic-function": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/restore-cursor": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", + "license": "MIT", + "dependencies": { + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/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==", + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/ora/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/outvariant": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/outvariant/-/outvariant-1.4.3.tgz", + "integrity": "sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA==", + "license": "MIT" + }, + "node_modules/p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/p-queue": { + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-6.6.2.tgz", + "integrity": "sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==", + "license": "MIT", + "dependencies": { + "eventemitter3": "^4.0.4", + "p-timeout": "^3.2.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-timeout": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz", + "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==", + "license": "MIT", + "dependencies": { + "p-finally": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "license": "(MIT AND Zlib)" + }, + "node_modules/patch-console": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/patch-console/-/patch-console-2.0.0.tgz", + "integrity": "sha512-0YNdUceMdaQwoKce1gatDScmMo5pu/tfABfnzEqeG0gtTmd7mh/WcwgUjtAeOU7N8nFFlbQBnFK2gXW5fGvmMA==", + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/path": { + "version": "0.12.7", + "resolved": "https://registry.npmjs.org/path/-/path-0.12.7.tgz", + "integrity": "sha512-aXXC6s+1w7otVF9UletFkFcDsJeO7lSZBPUQhtb5O0xJe8LtYhj/GxldoL09bBj9+ZmE2hNoHqQSFMN5fikh4Q==", + "license": "MIT", + "dependencies": { + "process": "^0.11.1", + "util": "^0.10.3" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "license": "MIT", + "optional": true + }, + "node_modules/path/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", + "license": "ISC" + }, + "node_modules/path/node_modules/util": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", + "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", + "license": "MIT", + "dependencies": { + "inherits": "2.0.3" + } + }, + "node_modules/pg-int8": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", + "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", + "license": "ISC", + "optional": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/pg-protocol": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.10.3.tgz", + "integrity": "sha512-6DIBgBQaTKDJyxnXaLiLR8wBpQQcGWuAESkRBX/t6OwA8YsqP+iVSiond2EDy6Y/dsGk8rh/jtax3js5NeV7JQ==", + "license": "MIT", + "optional": true + }, + "node_modules/pg-types": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", + "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", + "license": "MIT", + "optional": true, + "dependencies": { + "pg-int8": "1.0.1", + "postgres-array": "~2.0.0", + "postgres-bytea": "~1.0.0", + "postgres-date": "~1.0.4", + "postgres-interval": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/phoenix": { + "version": "1.7.21", + "resolved": "https://registry.npmjs.org/phoenix/-/phoenix-1.7.21.tgz", + "integrity": "sha512-8wOvJ8pQXRxNbyFlMI+wQhK3bvX4Ps3FtUX2+0cV6lkcebe9VTIl+xS60FLAeaPieFg80djor5z/AKofnwqAUw==", + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/picture-tuber": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/picture-tuber/-/picture-tuber-1.0.2.tgz", + "integrity": "sha512-49/xq+wzbwDeI32aPvwQJldM8pr7dKDRuR76IjztrkmiCkAQDaWFJzkmfVqCHmt/iFoPFhHmI9L0oKhthrTOQw==", + "license": "MIT", + "dependencies": { + "buffers": "~0.1.1", + "charm": "~0.1.0", + "event-stream": "~0.9.8", + "optimist": "~0.3.4", + "png-js": "~0.1.0", + "x256": "~0.0.1" + }, + "bin": { + "picture-tube": "bin/tube.js" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/png-js": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/png-js/-/png-js-0.1.1.tgz", + "integrity": "sha512-NTtk2SyfjBm+xYl2/VZJBhFnTQ4kU5qWC7VC4/iGbrgiU4FuB4xC+74erxADYJIqZICOR1HCvRA7EBHkpjTg9g==" + }, + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "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": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postgres-array": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", + "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/postgres-bytea": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", + "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-date": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", + "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-interval": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", + "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "xtend": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/preact": { + "version": "10.27.0", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.27.0.tgz", + "integrity": "sha512-/DTYoB6mwwgPytiqQTh/7SFRL98ZdiD8Sk8zIUVOxtwq4oWcwrcd1uno9fE/zZmUaUrFNYzbH14CPebOz9tZQw==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + } + }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "license": "MIT", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "license": "MIT" + }, + "node_modules/react": { + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz", + "integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz", + "integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==", + "license": "MIT", + "dependencies": { + "scheduler": "^0.26.0" + }, + "peerDependencies": { + "react": "^19.1.0" + } + }, + "node_modules/react-reconciler": { + "version": "0.32.0", + "resolved": "https://registry.npmjs.org/react-reconciler/-/react-reconciler-0.32.0.tgz", + "integrity": "sha512-2NPMOzgTlG0ZWdIf3qG+dcbLSoAc/uLfOwckc3ofy5sSK0pLJqnQLpUFxvGcN2rlXSjnVtGeeFLNimCQEj5gOQ==", + "license": "MIT", + "dependencies": { + "scheduler": "^0.26.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "peerDependencies": { + "react": "^19.1.0" + } + }, + "node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/readline": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/readline/-/readline-1.3.0.tgz", + "integrity": "sha512-k2d6ACCkiNYz222Fs/iNze30rRJ1iIicW7JuX/7/cozvih6YCkFZH+J6mAFDVgv0dRBaAyr4jDqC95R2y4IADg==", + "license": "BSD" + }, + "node_modules/redeyed": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/redeyed/-/redeyed-2.1.1.tgz", + "integrity": "sha512-FNpGGo1DycYAdnrKFxCMmKYgo/mILAqtRYbkdQD8Ep/Hk2PQ5+aEAEx+IU713RTDmuBaH0c8P5ZozurNu5ObRQ==", + "license": "MIT", + "dependencies": { + "esprima": "~4.0.0" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz", + "integrity": "sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg==", + "license": "MIT" + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-in-the-middle": { + "version": "7.5.2", + "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.5.2.tgz", + "integrity": "sha512-gAZ+kLqBdHarXB64XpAe2VCjB7rIRv+mU8tfRWziHRJ5umKsIHN2tLLv6EtMw7WCdP19S0ERVMldNvxYCHnhSQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "debug": "^4.3.5", + "module-details-from-path": "^1.0.3", + "resolve": "^1.22.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/resolve": { + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "license": "MIT", + "optional": true, + "dependencies": { + "is-core-module": "^2.16.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/restore-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", + "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", + "license": "MIT", + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, + "node_modules/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/sax": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", + "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==", + "license": "ISC" + }, + "node_modules/scheduler": { + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz", + "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "license": "MIT" + }, + "node_modules/sharp": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.3.tgz", + "integrity": "sha512-eX2IQ6nFohW4DbvHIOLRB3MHFpYqaqvXd3Tp5e/T/dSH83fxaNJQRvDMhASmkNTsNTVF2/OOopzRCt7xokgPfg==", + "hasInstallScript": true, + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "color": "^4.2.3", + "detect-libc": "^2.0.4", + "semver": "^7.7.2" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.34.3", + "@img/sharp-darwin-x64": "0.34.3", + "@img/sharp-libvips-darwin-arm64": "1.2.0", + "@img/sharp-libvips-darwin-x64": "1.2.0", + "@img/sharp-libvips-linux-arm": "1.2.0", + "@img/sharp-libvips-linux-arm64": "1.2.0", + "@img/sharp-libvips-linux-ppc64": "1.2.0", + "@img/sharp-libvips-linux-s390x": "1.2.0", + "@img/sharp-libvips-linux-x64": "1.2.0", + "@img/sharp-libvips-linuxmusl-arm64": "1.2.0", + "@img/sharp-libvips-linuxmusl-x64": "1.2.0", + "@img/sharp-linux-arm": "0.34.3", + "@img/sharp-linux-arm64": "0.34.3", + "@img/sharp-linux-ppc64": "0.34.3", + "@img/sharp-linux-s390x": "0.34.3", + "@img/sharp-linux-x64": "0.34.3", + "@img/sharp-linuxmusl-arm64": "0.34.3", + "@img/sharp-linuxmusl-x64": "0.34.3", + "@img/sharp-wasm32": "0.34.3", + "@img/sharp-win32-arm64": "0.34.3", + "@img/sharp-win32-ia32": "0.34.3", + "@img/sharp-win32-x64": "0.34.3" + } + }, + "node_modules/shimmer": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz", + "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==", + "license": "BSD-2-Clause", + "optional": true + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "license": "ISC" + }, + "node_modules/simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", + "license": "MIT", + "optional": true, + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, + "node_modules/slice-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz", + "integrity": "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/is-fullwidth-code-point": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz", + "integrity": "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==", + "license": "MIT", + "dependencies": { + "get-east-asian-width": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sparkline": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/sparkline/-/sparkline-0.1.2.tgz", + "integrity": "sha512-t//aVOiWt9fi/e22ea1vXVWBDX+gp18y+Ch9sKqmHl828bRfvP2VtfTJVEcgWFBQHd0yDPNQRiHdqzCvbcYSDA==", + "dependencies": { + "here": "0.0.2", + "nopt": "~2.1.2" + }, + "bin": { + "sparkline": "bin/sparkline" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/static-browser-server": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/static-browser-server/-/static-browser-server-1.0.3.tgz", + "integrity": "sha512-ZUyfgGDdFRbZGGJQ1YhiM930Yczz5VlbJObrQLlk24+qNHVQx4OlLcYswEUo3bIyNAbQUIUR9Yr5/Hqjzqb4zA==", + "license": "Apache-2.0", + "dependencies": { + "@open-draft/deferred-promise": "^2.1.0", + "dotenv": "^16.0.3", + "mime-db": "^1.52.0", + "outvariant": "^1.3.0" + } + }, + "node_modules/stdin-discarder": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.2.2.tgz", + "integrity": "sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strict-event-emitter": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/strict-event-emitter/-/strict-event-emitter-0.4.6.tgz", + "integrity": "sha512-12KWeb+wixJohmnwNFerbyiBrAlq5qJLwIt38etRtKtmmHyDSoGlIqFE9wx+4IwG0aDjI7GV8tc8ZccjWZZtTg==", + "license": "MIT" + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/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==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/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==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/styled-jsx": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz", + "integrity": "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==", + "license": "MIT", + "dependencies": { + "client-only": "0.0.1" + }, + "engines": { + "node": ">= 12.0.0" + }, + "peerDependencies": { + "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-hyperlinks": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", + "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tailwindcss": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.11.tgz", + "integrity": "sha512-2E9TBm6MDD/xKYe+dvJZAmg3yxIEDNRc0jwlNyDg/4Fil2QcSLjFKGVff0lAf1jjeaArlG/M75Ey/EYr/OJtBA==", + "dev": true, + "license": "MIT" + }, + "node_modules/tapable": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.2.tgz", + "integrity": "sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/tar": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz", + "integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==", + "dev": true, + "license": "ISC", + "dependencies": { + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.0.1", + "mkdirp": "^3.0.1", + "yallist": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/term-canvas": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/term-canvas/-/term-canvas-0.0.5.tgz", + "integrity": "sha512-eZ3rIWi5yLnKiUcsW8P79fKyooaLmyLWAGqBhFspqMxRNUiB4GmHHk5AzQ4LxvFbJILaXqQZLwbbATLOhCFwkw==" + }, + "node_modules/tiny-invariant": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", + "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", + "license": "MIT" + }, + "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==", + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" + }, + "node_modules/ts-mixer": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.4.tgz", + "integrity": "sha512-ufKpbmrugz5Aou4wcr5Wc1UUFWOLhq+Fm6qa6P0w0K5Qw2yhaUoiWszhCVuNQyNwrlGiscHOmqYoAox1PtvgjA==", + "license": "MIT" + }, + "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==", + "license": "0BSD" + }, + "node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "5.9.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz", + "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "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==", + "license": "MIT" + }, + "node_modules/universal-cookie": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/universal-cookie/-/universal-cookie-4.0.4.tgz", + "integrity": "sha512-lbRVHoOMtItjWbM7TwDLdl8wug7izB0tq3/YVKhT/ahB4VDvWMyvnADfnJI8y6fSvsjh51Ix7lTGC6Tn4rMPhw==", + "license": "MIT", + "dependencies": { + "@types/cookie": "^0.3.3", + "cookie": "^0.4.0" + } + }, + "node_modules/universal-user-agent": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.3.tgz", + "integrity": "sha512-TmnEAEAsBJVZM/AADELsK76llnwcf9vMKuPz8JflO1frO8Lchitr0fNaN9d+Ap0BjKtqWqd/J17qeDnXh8CL2A==", + "license": "ISC" + }, + "node_modules/util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, + "node_modules/uuid": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz", + "integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/esm/bin/uuid" + } + }, + "node_modules/vscode-diff": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/vscode-diff/-/vscode-diff-2.1.1.tgz", + "integrity": "sha512-S2BwZbrQCk4N6FqgYQQPlQ44OZKZNcS2VwhMj4xU8QvixXN9GeNQnN7/7XHFbwrs6h5BiLADDcERTrKvfWeG9g==", + "license": "MIT" + }, + "node_modules/vscode-jsonrpc": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.1.tgz", + "integrity": "sha512-kdjOSJ2lLIn7r1rtrMbbNCHjyMPfRnowdKjBQ+mGq6NAW5QY2bEZC/khaC5OR8svbbjvLEaIXkOq45e2X9BIbQ==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "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==", + "license": "BSD-2-Clause" + }, + "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==", + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.19", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", + "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/widest-line": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-5.0.0.tgz", + "integrity": "sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA==", + "license": "MIT", + "dependencies": { + "string-width": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/widest-line/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/widest-line/node_modules/emoji-regex": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", + "license": "MIT" + }, + "node_modules/widest-line/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/widest-line/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha512-1tMA907+V4QmxV7dbRvb4/8MaRALK6q9Abid3ndMYnbyo8piisCmeONVqVSXqQA3KaP4SLt5b7ud6E2sqP8TFw==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/wrap-ansi": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/emoji-regex": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", + "license": "MIT" + }, + "node_modules/wrap-ansi/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/ws": { + "version": "8.18.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", + "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", + "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/x256": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/x256/-/x256-0.0.2.tgz", + "integrity": "sha512-ZsIH+sheoF8YG9YG+QKEEIdtqpHRA9FYuD7MqhfyB1kayXU43RUNBFSxBEnF8ywSUxdg+8no4+bPr5qLbyxKgA==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/xml2js": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", + "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", + "license": "MIT", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "license": "MIT", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yoga-layout": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/yoga-layout/-/yoga-layout-3.2.1.tgz", + "integrity": "sha512-0LPOt3AxKqMdFBZA3HBAt/t/8vIKq7VaQYbuA8WxCgung+p9TVyKRYdpvCb80HcdTN2NkbIKbhNwKUfm3tQywQ==", + "license": "MIT" + }, + "node_modules/zen-observable": { + "version": "0.8.11", + "resolved": "https://registry.npmjs.org/zen-observable/-/zen-observable-0.8.11.tgz", + "integrity": "sha512-N3xXQVr4L61rZvGMpWe8XoCGX8vhU35dPyQ4fm5CY/KDlG0F75un14hjbckPXTDuKUY6V0dqR2giT6xN8Y4GEQ==", + "license": "MIT" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..30ba6b2 --- /dev/null +++ b/package.json @@ -0,0 +1,28 @@ +{ + "name": "codesandbox-clone", + "version": "0.1.0", + "description": "A full-featured CodeSandbox clone built with Next.js and the CodeSandbox SDK", + "private": true, + "scripts": { + "dev": "next dev --turbopack", + "build": "next build", + "start": "next start", + "lint": "next lint", + "template": "csb build ./sandbox-template --vm-tier Nano --vm-build-tier Micro --ports 5173 --alias sdk-example@latest" + }, + "dependencies": { + "@codesandbox/sdk": "^2.0.6-rc.1", + "@octokit/rest": "^22.0.0", + "next": "15.4.5", + "react": "19.1.0", + "react-dom": "19.1.0" + }, + "devDependencies": { + "@tailwindcss/postcss": "^4", + "@types/node": "^20", + "@types/react": "^19", + "@types/react-dom": "^19", + "tailwindcss": "^4", + "typescript": "^5" + } +} diff --git a/postcss.config.mjs b/postcss.config.mjs new file mode 100644 index 0000000..c7bcb4b --- /dev/null +++ b/postcss.config.mjs @@ -0,0 +1,5 @@ +const config = { + plugins: ["@tailwindcss/postcss"], +}; + +export default config; diff --git a/public/file.svg b/public/file.svg new file mode 100644 index 0000000..004145c --- /dev/null +++ b/public/file.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/globe.svg b/public/globe.svg new file mode 100644 index 0000000..567f17b --- /dev/null +++ b/public/globe.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/next.svg b/public/next.svg new file mode 100644 index 0000000..5174b28 --- /dev/null +++ b/public/next.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/vercel.svg b/public/vercel.svg new file mode 100644 index 0000000..7705396 --- /dev/null +++ b/public/vercel.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/window.svg b/public/window.svg new file mode 100644 index 0000000..b2b2a44 --- /dev/null +++ b/public/window.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/sandbox-template/.codesandbox/tasks.json b/sandbox-template/.codesandbox/tasks.json new file mode 100644 index 0000000..94411c2 --- /dev/null +++ b/sandbox-template/.codesandbox/tasks.json @@ -0,0 +1,16 @@ +{ + "setupTasks": [ + "curl -fsSL https://code-server.dev/install.sh | sh", + "cd app && npm install" + ], + "tasks": { + "dev-server": { + "name": "Dev Server", + "command": "cd app && npm run dev", + "preview": { + "port": 5173 + }, + "runAtStart": true + } + } +} diff --git a/sandbox-template/.devcontainer/.devcontainer b/sandbox-template/.devcontainer/.devcontainer new file mode 100644 index 0000000..0da459f --- /dev/null +++ b/sandbox-template/.devcontainer/.devcontainer @@ -0,0 +1,4 @@ +{ + "name": "Devcontainer", + "image": "mcr.microsoft.com/devcontainers/javascript-node:22" +} diff --git a/sandbox-template/.vscode/User/settings.json b/sandbox-template/.vscode/User/settings.json new file mode 100644 index 0000000..50f5ea1 --- /dev/null +++ b/sandbox-template/.vscode/User/settings.json @@ -0,0 +1,4 @@ +{ + "security.workspace.trust.enabled": false, + "workbench.startupEditor": "none" +} diff --git a/sandbox-template/README.md b/sandbox-template/README.md new file mode 100644 index 0000000..46650ea Binary files /dev/null and b/sandbox-template/README.md differ diff --git a/sandbox-template/app/.gitignore b/sandbox-template/app/.gitignore new file mode 100644 index 0000000..a547bf3 --- /dev/null +++ b/sandbox-template/app/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/sandbox-template/app/README.md b/sandbox-template/app/README.md new file mode 100644 index 0000000..7959ce4 --- /dev/null +++ b/sandbox-template/app/README.md @@ -0,0 +1,69 @@ +# React + TypeScript + Vite + +This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. + +Currently, two official plugins are available: + +- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) for Fast Refresh +- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh + +## Expanding the ESLint configuration + +If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules: + +```js +export default tseslint.config([ + globalIgnores(['dist']), + { + files: ['**/*.{ts,tsx}'], + extends: [ + // Other configs... + + // Remove tseslint.configs.recommended and replace with this + ...tseslint.configs.recommendedTypeChecked, + // Alternatively, use this for stricter rules + ...tseslint.configs.strictTypeChecked, + // Optionally, add this for stylistic rules + ...tseslint.configs.stylisticTypeChecked, + + // Other configs... + ], + languageOptions: { + parserOptions: { + project: ['./tsconfig.node.json', './tsconfig.app.json'], + tsconfigRootDir: import.meta.dirname, + }, + // other options... + }, + }, +]) +``` + +You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules: + +```js +// eslint.config.js +import reactX from 'eslint-plugin-react-x' +import reactDom from 'eslint-plugin-react-dom' + +export default tseslint.config([ + globalIgnores(['dist']), + { + files: ['**/*.{ts,tsx}'], + extends: [ + // Other configs... + // Enable lint rules for React + reactX.configs['recommended-typescript'], + // Enable lint rules for React DOM + reactDom.configs.recommended, + ], + languageOptions: { + parserOptions: { + project: ['./tsconfig.node.json', './tsconfig.app.json'], + tsconfigRootDir: import.meta.dirname, + }, + // other options... + }, + }, +]) +``` diff --git a/sandbox-template/app/eslint.config.js b/sandbox-template/app/eslint.config.js new file mode 100644 index 0000000..d94e7de --- /dev/null +++ b/sandbox-template/app/eslint.config.js @@ -0,0 +1,23 @@ +import js from '@eslint/js' +import globals from 'globals' +import reactHooks from 'eslint-plugin-react-hooks' +import reactRefresh from 'eslint-plugin-react-refresh' +import tseslint from 'typescript-eslint' +import { globalIgnores } from 'eslint/config' + +export default tseslint.config([ + globalIgnores(['dist']), + { + files: ['**/*.{ts,tsx}'], + extends: [ + js.configs.recommended, + tseslint.configs.recommended, + reactHooks.configs['recommended-latest'], + reactRefresh.configs.vite, + ], + languageOptions: { + ecmaVersion: 2020, + globals: globals.browser, + }, + }, +]) diff --git a/sandbox-template/app/index.html b/sandbox-template/app/index.html new file mode 100644 index 0000000..e4b78ea --- /dev/null +++ b/sandbox-template/app/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite + React + TS + + +
+ + + diff --git a/sandbox-template/app/package.json b/sandbox-template/app/package.json new file mode 100644 index 0000000..d34874e --- /dev/null +++ b/sandbox-template/app/package.json @@ -0,0 +1,29 @@ +{ + "name": "sandbox-template", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc -b && vite build", + "lint": "eslint .", + "preview": "vite preview" + }, + "dependencies": { + "react": "^19.1.0", + "react-dom": "^19.1.0" + }, + "devDependencies": { + "@eslint/js": "^9.30.1", + "@types/react": "^19.1.8", + "@types/react-dom": "^19.1.6", + "@vitejs/plugin-react-swc": "^3.10.2", + "eslint": "^9.30.1", + "eslint-plugin-react-hooks": "^5.2.0", + "eslint-plugin-react-refresh": "^0.4.20", + "globals": "^16.3.0", + "typescript": "~5.8.3", + "typescript-eslint": "^8.35.1", + "vite": "^7.0.4" + } +} diff --git a/sandbox-template/app/public/vite.svg b/sandbox-template/app/public/vite.svg new file mode 100644 index 0000000..e7b8dfb --- /dev/null +++ b/sandbox-template/app/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/sandbox-template/app/src/App.css b/sandbox-template/app/src/App.css new file mode 100644 index 0000000..b9d355d --- /dev/null +++ b/sandbox-template/app/src/App.css @@ -0,0 +1,42 @@ +#root { + max-width: 1280px; + margin: 0 auto; + padding: 2rem; + text-align: center; +} + +.logo { + height: 6em; + padding: 1.5em; + will-change: filter; + transition: filter 300ms; +} +.logo:hover { + filter: drop-shadow(0 0 2em #646cffaa); +} +.logo.react:hover { + filter: drop-shadow(0 0 2em #61dafbaa); +} + +@keyframes logo-spin { + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } +} + +@media (prefers-reduced-motion: no-preference) { + a:nth-of-type(2) .logo { + animation: logo-spin infinite 20s linear; + } +} + +.card { + padding: 2em; +} + +.read-the-docs { + color: #888; +} diff --git a/sandbox-template/app/src/App.tsx b/sandbox-template/app/src/App.tsx new file mode 100644 index 0000000..3d7ded3 --- /dev/null +++ b/sandbox-template/app/src/App.tsx @@ -0,0 +1,35 @@ +import { useState } from 'react' +import reactLogo from './assets/react.svg' +import viteLogo from '/vite.svg' +import './App.css' + +function App() { + const [count, setCount] = useState(0) + + return ( + <> + +

Vite + React

+
+ +

+ Edit src/App.tsx and save to test HMR +

+
+

+ Click on the Vite and React logos to learn more +

+ + ) +} + +export default App diff --git a/sandbox-template/app/src/assets/react.svg b/sandbox-template/app/src/assets/react.svg new file mode 100644 index 0000000..6c87de9 --- /dev/null +++ b/sandbox-template/app/src/assets/react.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/sandbox-template/app/src/index.css b/sandbox-template/app/src/index.css new file mode 100644 index 0000000..08a3ac9 --- /dev/null +++ b/sandbox-template/app/src/index.css @@ -0,0 +1,68 @@ +:root { + font-family: system-ui, Avenir, Helvetica, Arial, sans-serif; + line-height: 1.5; + font-weight: 400; + + color-scheme: light dark; + color: rgba(255, 255, 255, 0.87); + background-color: #242424; + + font-synthesis: none; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +a { + font-weight: 500; + color: #646cff; + text-decoration: inherit; +} +a:hover { + color: #535bf2; +} + +body { + margin: 0; + display: flex; + place-items: center; + min-width: 320px; + min-height: 100vh; +} + +h1 { + font-size: 3.2em; + line-height: 1.1; +} + +button { + border-radius: 8px; + border: 1px solid transparent; + padding: 0.6em 1.2em; + font-size: 1em; + font-weight: 500; + font-family: inherit; + background-color: #1a1a1a; + cursor: pointer; + transition: border-color 0.25s; +} +button:hover { + border-color: #646cff; +} +button:focus, +button:focus-visible { + outline: 4px auto -webkit-focus-ring-color; +} + +@media (prefers-color-scheme: light) { + :root { + color: #213547; + background-color: #ffffff; + } + a:hover { + color: #747bff; + } + button { + background-color: #f9f9f9; + } +} diff --git a/sandbox-template/app/src/main.tsx b/sandbox-template/app/src/main.tsx new file mode 100644 index 0000000..bef5202 --- /dev/null +++ b/sandbox-template/app/src/main.tsx @@ -0,0 +1,10 @@ +import { StrictMode } from 'react' +import { createRoot } from 'react-dom/client' +import './index.css' +import App from './App.tsx' + +createRoot(document.getElementById('root')!).render( + + + , +) diff --git a/sandbox-template/app/src/vite-env.d.ts b/sandbox-template/app/src/vite-env.d.ts new file mode 100644 index 0000000..11f02fe --- /dev/null +++ b/sandbox-template/app/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/sandbox-template/app/tsconfig.app.json b/sandbox-template/app/tsconfig.app.json new file mode 100644 index 0000000..227a6c6 --- /dev/null +++ b/sandbox-template/app/tsconfig.app.json @@ -0,0 +1,27 @@ +{ + "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + "target": "ES2022", + "useDefineForClassFields": true, + "lib": ["ES2022", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, + "moduleDetection": "force", + "noEmit": true, + "jsx": "react-jsx", + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "erasableSyntaxOnly": true, + "noFallthroughCasesInSwitch": true, + "noUncheckedSideEffectImports": true + }, + "include": ["src"] +} diff --git a/sandbox-template/app/tsconfig.json b/sandbox-template/app/tsconfig.json new file mode 100644 index 0000000..1ffef60 --- /dev/null +++ b/sandbox-template/app/tsconfig.json @@ -0,0 +1,7 @@ +{ + "files": [], + "references": [ + { "path": "./tsconfig.app.json" }, + { "path": "./tsconfig.node.json" } + ] +} diff --git a/sandbox-template/app/tsconfig.node.json b/sandbox-template/app/tsconfig.node.json new file mode 100644 index 0000000..f85a399 --- /dev/null +++ b/sandbox-template/app/tsconfig.node.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + "target": "ES2023", + "lib": ["ES2023"], + "module": "ESNext", + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, + "moduleDetection": "force", + "noEmit": true, + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "erasableSyntaxOnly": true, + "noFallthroughCasesInSwitch": true, + "noUncheckedSideEffectImports": true + }, + "include": ["vite.config.ts"] +} diff --git a/sandbox-template/app/vite.config.ts b/sandbox-template/app/vite.config.ts new file mode 100644 index 0000000..2328e17 --- /dev/null +++ b/sandbox-template/app/vite.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react-swc' + +// https://vite.dev/config/ +export default defineConfig({ + plugins: [react()], +}) diff --git a/setup-failure-7dv9sq-2025-08-04T12-53-35.522Z.log b/setup-failure-7dv9sq-2025-08-04T12-53-35.522Z.log new file mode 100644 index 0000000..4b17d05 --- /dev/null +++ b/setup-failure-7dv9sq-2025-08-04T12-53-35.522Z.log @@ -0,0 +1,18 @@ +[CODESANDBOX] Preparing devcontainer configuration and overrides + +npm ERR! code ENOENT + +npm ERR! syscall open +npm ERR! path /project/sandbox/package.json + +npm + ERR! errno -2 + +npm ERR! enoent Could not read package.json: Error: ENOENT: no such file or directory, open '/project/sandbox/package.json' + +npm ERR! enoent This is related to npm not being able to find a file. +npm ERR! enoent + + + +npm ERR! A complete log of this run can be found in: /root/.cache/npm/_logs/2025-08-04T12_53_35_226Z-debug-0.log diff --git a/setup-failure-vfhl4h-2025-08-04T12-53-35.306Z.log b/setup-failure-vfhl4h-2025-08-04T12-53-35.306Z.log new file mode 100644 index 0000000..1a49394 --- /dev/null +++ b/setup-failure-vfhl4h-2025-08-04T12-53-35.306Z.log @@ -0,0 +1,19 @@ +[CODESANDBOX] Preparing devcontainer configuration and overrides + +npm ERR! code ENOENT + +npm ERR! syscall open +npm ERR! path /project/workspace/package.json + +npm + ERR! +errno -2 + +npm ERR! enoent Could not read package.json: Error: ENOENT: no such file or directory, open '/project/workspace/package.json' +npm ERR! enoent This is related to npm not being able to find a file. +npm ERR! enoent + + + + +npm ERR! A complete log of this run can be found in: /root/.cache/npm/_logs/2025-08-04T12_53_34_858Z-debug-0.log diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..c133409 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,27 @@ +{ + "compilerOptions": { + "target": "ES2017", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve", + "incremental": true, + "plugins": [ + { + "name": "next" + } + ], + "paths": { + "@/*": ["./src/*"] + } + }, + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], + "exclude": ["node_modules"] +}