mirror of
https://github.com/samsonjs/vibetunnel.git
synced 2026-03-25 09:25:50 +00:00
Fix linter formatting issues
🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
eac1d8251a
commit
c04cb26f4e
9 changed files with 904 additions and 125 deletions
228
web/README.md
228
web/README.md
|
|
@ -1,115 +1,179 @@
|
|||
# VibeTunnel Web Frontend
|
||||
|
||||
A web interface for the VibeTunnel terminal multiplexer. This frontend allows you to view and interact with multiple terminal sessions through a browser interface.
|
||||
A modern web interface for the VibeTunnel terminal multiplexer built with TypeScript, Lit Elements, and XTerm.js. Provides professional terminal emulation with mobile-optimized controls and real-time session management.
|
||||
|
||||
## Features
|
||||
|
||||
- View multiple terminal processes in a web interface
|
||||
- Real-time terminal output using asciinema player
|
||||
- Interactive terminal input via WebSocket connections
|
||||
- Terminal-themed UI with monospace fonts
|
||||
- Mock server for development without backend dependencies
|
||||
- **Professional Terminal Emulation** using XTerm.js with full VT compatibility
|
||||
- **Real-time Session Management** with live streaming via Server-Sent Events
|
||||
- **Mobile-Optimized Interface** with touch controls and responsive design
|
||||
- **Session Snapshots** for previewing terminal output in card view
|
||||
- **Interactive Terminal Input** with full keyboard support and mobile input overlay
|
||||
- **VS Code Dark Theme** with consistent styling throughout
|
||||
- **Custom Font Support** using Fira Code with programming ligatures
|
||||
- **File Browser** for selecting working directories
|
||||
- **Session Lifecycle Management** (create, monitor, kill, cleanup)
|
||||
|
||||
## Setup
|
||||
## Quick Start
|
||||
|
||||
1. **Install dependencies:**
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
2. **Build CSS:**
|
||||
```bash
|
||||
npm run build-css
|
||||
```
|
||||
|
||||
## Development
|
||||
|
||||
1. **Start the development server:**
|
||||
2. **Start development server:**
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
2. **Open your browser:**
|
||||
3. **Open browser:**
|
||||
Navigate to `http://localhost:3000`
|
||||
|
||||
3. **CSS Development:**
|
||||
For live CSS rebuilding during development, run in a separate terminal:
|
||||
```bash
|
||||
npm run build-css
|
||||
```
|
||||
## Development Scripts
|
||||
|
||||
The development server includes:
|
||||
- Mock API endpoints for process management
|
||||
- Mock WebSocket connections with sample terminal data
|
||||
- Hot reloading for server changes (restart with `npm run dev`)
|
||||
```bash
|
||||
# Development (auto-rebuild and watch)
|
||||
npm run dev # Start full dev environment
|
||||
npm run watch:server # Watch server TypeScript only
|
||||
npm run watch:css # Watch CSS changes only
|
||||
|
||||
## Build for Deployment
|
||||
# Building
|
||||
npm run build # Build everything for production
|
||||
npm run build:server # Build server TypeScript
|
||||
npm run build:client # Build client TypeScript
|
||||
npm run build:css # Build Tailwind CSS
|
||||
|
||||
To build the project for production deployment:
|
||||
# Bundling (ES modules)
|
||||
npm run bundle # Bundle client code
|
||||
npm run bundle:watch # Watch and bundle client code
|
||||
|
||||
1. **Compile TypeScript:**
|
||||
# Code Quality
|
||||
npm run lint # Check ESLint issues
|
||||
npm run lint:fix # Auto-fix ESLint issues
|
||||
npm run format # Format code with Prettier
|
||||
npm run format:check # Check code formatting
|
||||
npm run pre-commit # Run all quality checks
|
||||
|
||||
# Testing
|
||||
npm run test # Run Jest tests
|
||||
npm run test:watch # Watch and run tests
|
||||
```
|
||||
|
||||
## Architecture
|
||||
|
||||
### Client-Side Components
|
||||
|
||||
Built with **Lit Elements** (Web Components):
|
||||
|
||||
```
|
||||
src/client/
|
||||
├── app.ts # Main application controller
|
||||
├── components/
|
||||
│ ├── app-header.ts # Main navigation and controls
|
||||
│ ├── session-list.ts # Session grid with cards
|
||||
│ ├── session-card.ts # Individual session preview
|
||||
│ ├── session-view.ts # Full terminal view
|
||||
│ ├── session-create-form.ts # New session modal
|
||||
│ └── file-browser.ts # Directory selection
|
||||
├── renderer.ts # XTerm.js terminal renderer
|
||||
└── scale-fit-addon.ts # Custom terminal scaling
|
||||
```
|
||||
|
||||
### Server-Side Architecture
|
||||
|
||||
**Express.js** server with **tty-fwd integration**:
|
||||
|
||||
```
|
||||
src/
|
||||
├── server.ts # Main Express server
|
||||
└── input.css # Tailwind source styles
|
||||
```
|
||||
|
||||
### Build Output
|
||||
|
||||
```
|
||||
dist/ # Compiled TypeScript
|
||||
public/
|
||||
├── bundle/
|
||||
│ ├── client-bundle.js # Bundled client code
|
||||
│ ├── renderer.js # Terminal renderer
|
||||
│ └── output.css # Compiled styles
|
||||
├── fonts/ # Fira Code font files
|
||||
└── index.html # Main HTML
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### Session Management
|
||||
|
||||
```
|
||||
GET /api/sessions # List all sessions
|
||||
POST /api/sessions # Create new session
|
||||
DELETE /api/sessions/:id # Kill session
|
||||
DELETE /api/sessions/:id/cleanup # Clean up session files
|
||||
POST /api/cleanup-exited # Clean all exited sessions
|
||||
```
|
||||
|
||||
### Terminal I/O
|
||||
|
||||
```
|
||||
GET /api/sessions/:id/stream # Live session stream (SSE)
|
||||
GET /api/sessions/:id/snapshot # Session snapshot (cast format)
|
||||
POST /api/sessions/:id/input # Send input to session
|
||||
```
|
||||
|
||||
### File System
|
||||
|
||||
```
|
||||
GET /api/fs/browse?path=<path> # Browse directories
|
||||
POST /api/mkdir # Create directory
|
||||
```
|
||||
|
||||
## Technology Stack
|
||||
|
||||
- **Frontend Framework:** Lit Elements (Web Components)
|
||||
- **Terminal Emulation:** XTerm.js with custom addons
|
||||
- **Styling:** Tailwind CSS with VS Code theme
|
||||
- **Typography:** Fira Code Variable Font
|
||||
- **Backend:** Express.js + TypeScript
|
||||
- **Terminal Backend:** tty-fwd (Rust binary)
|
||||
- **Build Tools:** TypeScript, ESBuild, Tailwind
|
||||
- **Code Quality:** ESLint, Prettier, Pre-commit hooks
|
||||
|
||||
## Mobile Support
|
||||
|
||||
- **Touch-optimized scrolling** with proper overscroll prevention
|
||||
- **Mobile input overlay** with virtual keyboard support
|
||||
- **Responsive design** with mobile-first approach
|
||||
- **Gesture navigation** (swipe from edge to go back)
|
||||
- **Pull-to-refresh prevention** during terminal interaction
|
||||
|
||||
## Browser Compatibility
|
||||
|
||||
- **Modern ES6+ browsers** (Chrome 63+, Firefox 67+, Safari 13+)
|
||||
- **Mobile browsers** with full touch support
|
||||
- **Progressive enhancement** with graceful degradation
|
||||
|
||||
## Deployment
|
||||
|
||||
1. **Build for production:**
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
2. **Build CSS:**
|
||||
```bash
|
||||
npm run build-css
|
||||
```
|
||||
|
||||
3. **Create deployment files:**
|
||||
```bash
|
||||
# Create dist directory structure
|
||||
mkdir -p dist/public
|
||||
|
||||
# Copy static files
|
||||
cp public/index.html dist/public/
|
||||
cp public/app.js dist/public/
|
||||
cp public/output.css dist/public/
|
||||
|
||||
# The compiled server will be in dist/server.js
|
||||
```
|
||||
|
||||
After building, your `dist/` folder will contain:
|
||||
- `dist/server.js` - Compiled Express server
|
||||
- `dist/public/index.html` - Main HTML file
|
||||
- `dist/public/app.js` - Client-side JavaScript
|
||||
- `dist/public/output.css` - Compiled Tailwind CSS
|
||||
|
||||
## Deployment
|
||||
|
||||
1. **Production server:**
|
||||
2. **Start production server:**
|
||||
```bash
|
||||
npm start
|
||||
```
|
||||
|
||||
2. **Environment variables:**
|
||||
3. **Environment variables:**
|
||||
- `PORT` - Server port (default: 3000)
|
||||
- `TTY_FWD_CONTROL_DIR` - tty-fwd control directory
|
||||
|
||||
## Project Structure
|
||||
## Development Notes
|
||||
|
||||
```
|
||||
src/
|
||||
├── server.ts # Express server with mock API and WebSocket
|
||||
├── input.css # Tailwind CSS source
|
||||
public/
|
||||
├── index.html # Main HTML interface
|
||||
└── app.js # Client-side terminal management
|
||||
dist/ # Built files (created after build)
|
||||
├── server.js # Compiled server
|
||||
└── public/ # Static assets
|
||||
```
|
||||
|
||||
## API Endpoints
|
||||
|
||||
The mock server provides these endpoints:
|
||||
|
||||
- `GET /api/processes` - List all processes
|
||||
- `GET /api/processes/:id` - Get specific process details
|
||||
- `WebSocket /?processId=:id` - Connect to process terminal stream
|
||||
|
||||
## Technology Stack
|
||||
|
||||
- **Frontend:** Vanilla JavaScript, Tailwind CSS, Asciinema Player
|
||||
- **Backend:** Express.js, WebSocket, TypeScript
|
||||
- **Build Tools:** TypeScript Compiler, Tailwind CSS, PostCSS
|
||||
- **Hot reload** enabled in development
|
||||
- **TypeScript strict mode** with comprehensive type checking
|
||||
- **ESLint + Prettier** enforced via pre-commit hooks
|
||||
- **Component-based architecture** for maintainability
|
||||
- **Mobile-first responsive design** principles
|
||||
623
web/package-lock.json
generated
623
web/package-lock.json
generated
|
|
@ -34,7 +34,9 @@
|
|||
"eslint": "^9.29.0",
|
||||
"eslint-config-prettier": "^10.1.5",
|
||||
"eslint-plugin-prettier": "^5.4.1",
|
||||
"husky": "^9.1.7",
|
||||
"jest": "^29.7.0",
|
||||
"lint-staged": "^16.1.2",
|
||||
"postcss": "^8.5.5",
|
||||
"prettier": "^3.5.3",
|
||||
"puppeteer": "^21.0.0",
|
||||
|
|
@ -3448,6 +3450,93 @@
|
|||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"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==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"restore-cursor": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"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==",
|
||||
"dev": true,
|
||||
"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==",
|
||||
"dev": true,
|
||||
"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==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"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==",
|
||||
"dev": true,
|
||||
"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==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansi-regex": "^6.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/strip-ansi?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/cliui": {
|
||||
"version": "8.0.1",
|
||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
|
||||
|
|
@ -3557,6 +3646,13 @@
|
|||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/colorette": {
|
||||
"version": "2.0.20",
|
||||
"resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz",
|
||||
"integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/combined-stream": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
|
|
@ -4031,6 +4127,19 @@
|
|||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/environment": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz",
|
||||
"integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/error-ex": {
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
|
||||
|
|
@ -4524,6 +4633,13 @@
|
|||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/eventemitter3": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz",
|
||||
"integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/execa": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
|
||||
|
|
@ -5039,6 +5155,19 @@
|
|||
"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==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/get-intrinsic": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
|
||||
|
|
@ -5387,6 +5516,22 @@
|
|||
"node": ">=10.17.0"
|
||||
}
|
||||
},
|
||||
"node_modules/husky": {
|
||||
"version": "9.1.7",
|
||||
"resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz",
|
||||
"integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"husky": "bin.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/typicode"
|
||||
}
|
||||
},
|
||||
"node_modules/iconv-lite": {
|
||||
"version": "0.4.24",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
|
||||
|
|
@ -6519,6 +6664,185 @@
|
|||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lint-staged": {
|
||||
"version": "16.1.2",
|
||||
"resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-16.1.2.tgz",
|
||||
"integrity": "sha512-sQKw2Si2g9KUZNY3XNvRuDq4UJqpHwF0/FQzZR2M7I5MvtpWvibikCjUVJzZdGE0ByurEl3KQNvsGetd1ty1/Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"chalk": "^5.4.1",
|
||||
"commander": "^14.0.0",
|
||||
"debug": "^4.4.1",
|
||||
"lilconfig": "^3.1.3",
|
||||
"listr2": "^8.3.3",
|
||||
"micromatch": "^4.0.8",
|
||||
"nano-spawn": "^1.0.2",
|
||||
"pidtree": "^0.6.0",
|
||||
"string-argv": "^0.3.2",
|
||||
"yaml": "^2.8.0"
|
||||
},
|
||||
"bin": {
|
||||
"lint-staged": "bin/lint-staged.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.17"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/lint-staged"
|
||||
}
|
||||
},
|
||||
"node_modules/lint-staged/node_modules/chalk": {
|
||||
"version": "5.4.1",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz",
|
||||
"integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "^12.17.0 || ^14.13 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/chalk?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/lint-staged/node_modules/commander": {
|
||||
"version": "14.0.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-14.0.0.tgz",
|
||||
"integrity": "sha512-2uM9rYjPvyq39NwLRqaiLtWHyDC1FvryJDa2ATTVims5YAS4PupsEQsDvP14FqhFr0P49CYDugi59xaxJlTXRA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
}
|
||||
},
|
||||
"node_modules/lint-staged/node_modules/debug": {
|
||||
"version": "4.4.1",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
|
||||
"integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ms": "^2.1.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"supports-color": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/lint-staged/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==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/listr2": {
|
||||
"version": "8.3.3",
|
||||
"resolved": "https://registry.npmjs.org/listr2/-/listr2-8.3.3.tgz",
|
||||
"integrity": "sha512-LWzX2KsqcB1wqQ4AHgYb4RsDXauQiqhjLk+6hjbaeHG4zpjjVAB6wC/gz6X0l+Du1cN3pUB5ZlrvTbhGSNnUQQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"cli-truncate": "^4.0.0",
|
||||
"colorette": "^2.0.20",
|
||||
"eventemitter3": "^5.0.1",
|
||||
"log-update": "^6.1.0",
|
||||
"rfdc": "^1.4.1",
|
||||
"wrap-ansi": "^9.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/listr2/node_modules/ansi-regex": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
|
||||
"integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/ansi-regex?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/listr2/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==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/listr2/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==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/listr2/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==",
|
||||
"dev": true,
|
||||
"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/listr2/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==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansi-regex": "^6.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/strip-ansi?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/listr2/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==",
|
||||
"dev": true,
|
||||
"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/lit": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/lit/-/lit-3.3.0.tgz",
|
||||
|
|
@ -6584,6 +6908,160 @@
|
|||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/log-update": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz",
|
||||
"integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansi-escapes": "^7.0.0",
|
||||
"cli-cursor": "^5.0.0",
|
||||
"slice-ansi": "^7.1.0",
|
||||
"strip-ansi": "^7.1.0",
|
||||
"wrap-ansi": "^9.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/log-update/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==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"environment": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/log-update/node_modules/ansi-regex": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
|
||||
"integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/ansi-regex?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/log-update/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==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/log-update/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==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/log-update/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==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"get-east-asian-width": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/log-update/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==",
|
||||
"dev": true,
|
||||
"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/log-update/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==",
|
||||
"dev": true,
|
||||
"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/log-update/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==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansi-regex": "^6.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/strip-ansi?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/log-update/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==",
|
||||
"dev": true,
|
||||
"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/lru-cache": {
|
||||
"version": "7.18.3",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
|
||||
|
|
@ -6750,6 +7228,19 @@
|
|||
"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==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/minimatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
|
|
@ -6811,6 +7302,19 @@
|
|||
"integrity": "sha512-DANghxFkS1plDdRsX0X9pm0Z6SJNN6gBdtXfanwoZ8hooC5gosGFSBGRYHUVPz1asKA/kMRqDRdHrluZ61SpBQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/nano-spawn": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/nano-spawn/-/nano-spawn-1.0.2.tgz",
|
||||
"integrity": "sha512-21t+ozMQDAL/UGgQVBbZ/xXvNO10++ZPuTmKRO8k9V3AClVRht49ahtDjfY8l1q6nSHOrE5ASfthzH3ol6R/hg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=20.17"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sindresorhus/nano-spawn?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/nanoid": {
|
||||
"version": "3.3.11",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
|
||||
|
|
@ -7278,6 +7782,19 @@
|
|||
"url": "https://github.com/sponsors/jonschlinkert"
|
||||
}
|
||||
},
|
||||
"node_modules/pidtree": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz",
|
||||
"integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"pidtree": "bin/pidtree.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/pify": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
|
||||
|
|
@ -7901,6 +8418,52 @@
|
|||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"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==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"onetime": "^7.0.0",
|
||||
"signal-exit": "^4.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/restore-cursor/node_modules/onetime": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz",
|
||||
"integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"mimic-function": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/restore-cursor/node_modules/signal-exit": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
|
||||
"integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/reusify": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz",
|
||||
|
|
@ -7912,6 +8475,13 @@
|
|||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/rfdc": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz",
|
||||
"integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/run-parallel": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
|
||||
|
|
@ -8195,6 +8765,49 @@
|
|||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"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==",
|
||||
"dev": true,
|
||||
"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/slice-ansi/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==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/slice-ansi/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==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/smart-buffer": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
|
||||
|
|
@ -8352,6 +8965,16 @@
|
|||
"bare-events": "^2.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/string-argv": {
|
||||
"version": "0.3.2",
|
||||
"resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz",
|
||||
"integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.6.19"
|
||||
}
|
||||
},
|
||||
"node_modules/string-length": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz",
|
||||
|
|
|
|||
|
|
@ -22,7 +22,8 @@
|
|||
"lint": "eslint 'src/**/*.{ts,tsx}'",
|
||||
"lint:fix": "eslint 'src/**/*.{ts,tsx}' --fix",
|
||||
"format": "prettier --write 'src/**/*.{ts,tsx,js,jsx,json,css,md}'",
|
||||
"format:check": "prettier --check 'src/**/*.{ts,tsx,js,jsx,json,css,md}'"
|
||||
"format:check": "prettier --check 'src/**/*.{ts,tsx,js,jsx,json,css,md}'",
|
||||
"pre-commit": "./scripts/pre-commit-check.sh"
|
||||
},
|
||||
"dependencies": {
|
||||
"@xterm/addon-fit": "^0.10.0",
|
||||
|
|
@ -50,7 +51,9 @@
|
|||
"eslint": "^9.29.0",
|
||||
"eslint-config-prettier": "^10.1.5",
|
||||
"eslint-plugin-prettier": "^5.4.1",
|
||||
"husky": "^9.1.7",
|
||||
"jest": "^29.7.0",
|
||||
"lint-staged": "^16.1.2",
|
||||
"postcss": "^8.5.5",
|
||||
"prettier": "^3.5.3",
|
||||
"puppeteer": "^21.0.0",
|
||||
|
|
|
|||
50
web/scripts/pre-commit-check.sh
Executable file
50
web/scripts/pre-commit-check.sh
Executable file
|
|
@ -0,0 +1,50 @@
|
|||
#!/bin/bash
|
||||
|
||||
# VibeTunnel Pre-commit Check Script
|
||||
# Can be run manually: npm run pre-commit
|
||||
|
||||
set -e
|
||||
|
||||
echo "🔍 Running pre-commit checks..."
|
||||
|
||||
# Check if we're in a git repository
|
||||
if ! git rev-parse --git-dir > /dev/null 2>&1; then
|
||||
echo "❌ Not in a git repository"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Get staged files or all TypeScript files if not in a commit
|
||||
if git diff --cached --quiet; then
|
||||
echo "📁 No staged files, checking all TypeScript files..."
|
||||
TS_FILES=$(find src -name "*.ts" -o -name "*.tsx" | tr '\n' ' ')
|
||||
else
|
||||
echo "📁 Checking staged TypeScript files..."
|
||||
TS_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep -E '\.(ts|tsx)$' | tr '\n' ' ')
|
||||
fi
|
||||
|
||||
if [ -z "$TS_FILES" ]; then
|
||||
echo "✅ No TypeScript files to check"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "Files to check: $TS_FILES"
|
||||
|
||||
# Run ESLint
|
||||
echo "🔧 Running ESLint..."
|
||||
npm run lint
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "❌ ESLint failed. Run 'npm run lint:fix' to auto-fix issues."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Run Prettier check
|
||||
echo "✨ Checking Prettier formatting..."
|
||||
npm run format:check
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "❌ Prettier formatting issues found. Run 'npm run format' to fix."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✅ All checks passed!"
|
||||
|
|
@ -45,39 +45,57 @@ export class AppHeader extends LitElement {
|
|||
<div class="flex flex-col gap-3 sm:hidden">
|
||||
<!-- Centered VibeTunnel title -->
|
||||
<div class="text-vs-user font-mono text-sm text-center">-=[ VibeTunnel ]=-</div>
|
||||
|
||||
|
||||
<!-- Controls row: hide exited on left, buttons on right -->
|
||||
<div class="flex items-center justify-between">
|
||||
<label class="flex items-center gap-2 text-vs-text text-sm cursor-pointer hover:text-vs-accent transition-colors">
|
||||
<label
|
||||
class="flex items-center gap-2 text-vs-text text-sm cursor-pointer hover:text-vs-accent transition-colors"
|
||||
>
|
||||
<div class="relative">
|
||||
<input
|
||||
type="checkbox"
|
||||
class="sr-only"
|
||||
.checked=${this.hideExited}
|
||||
@change=${(e: Event) => this.dispatchEvent(new CustomEvent('hide-exited-change', { detail: (e.target as HTMLInputElement).checked }))}
|
||||
@change=${(e: Event) =>
|
||||
this.dispatchEvent(
|
||||
new CustomEvent('hide-exited-change', {
|
||||
detail: (e.target as HTMLInputElement).checked,
|
||||
})
|
||||
)}
|
||||
/>
|
||||
<div
|
||||
class="w-4 h-4 border border-vs-border rounded bg-vs-bg-secondary flex items-center justify-center transition-all ${this
|
||||
.hideExited
|
||||
? 'bg-vs-user border-vs-user'
|
||||
: 'hover:border-vs-accent'}"
|
||||
>
|
||||
<div class="w-4 h-4 border border-vs-border rounded bg-vs-bg-secondary flex items-center justify-center transition-all ${
|
||||
this.hideExited ? 'bg-vs-user border-vs-user' : 'hover:border-vs-accent'
|
||||
}">
|
||||
${this.hideExited ? html`
|
||||
<svg class="w-3 h-3 text-vs-bg" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"></path>
|
||||
</svg>
|
||||
` : ''}
|
||||
${this.hideExited
|
||||
? html`
|
||||
<svg class="w-3 h-3 text-vs-bg" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z"
|
||||
clip-rule="evenodd"
|
||||
></path>
|
||||
</svg>
|
||||
`
|
||||
: ''}
|
||||
</div>
|
||||
</div>
|
||||
hide exited
|
||||
</label>
|
||||
|
||||
|
||||
<div class="flex gap-1">
|
||||
${runningSessions.length > 0 && !this.killingAll ? html`
|
||||
<button
|
||||
class="bg-vs-warning text-vs-bg hover:bg-vs-highlight font-mono px-2 py-1.5 border-none rounded transition-colors text-xs whitespace-nowrap"
|
||||
@click=${this.handleKillAll}
|
||||
>
|
||||
KILL (${runningSessions.length})
|
||||
</button>
|
||||
` : ''}
|
||||
${runningSessions.length > 0 && !this.killingAll
|
||||
? html`
|
||||
<button
|
||||
class="bg-vs-warning text-vs-bg hover:bg-vs-highlight font-mono px-2 py-1.5 border-none rounded transition-colors text-xs whitespace-nowrap"
|
||||
@click=${this.handleKillAll}
|
||||
>
|
||||
KILL (${runningSessions.length})
|
||||
</button>
|
||||
`
|
||||
: ''}
|
||||
<button
|
||||
class="bg-vs-user text-vs-text hover:bg-vs-accent font-mono px-2 py-1.5 border-none rounded transition-colors text-xs whitespace-nowrap"
|
||||
@click=${this.handleCreateSession}
|
||||
|
|
@ -87,12 +105,14 @@ export class AppHeader extends LitElement {
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Desktop layout: single row -->
|
||||
<div class="hidden sm:flex sm:items-center sm:justify-between">
|
||||
<div class="text-vs-user font-mono text-sm">-=[ VibeTunnel ]=-</div>
|
||||
<div class="flex items-center gap-3">
|
||||
<label class="flex items-center gap-2 text-vs-text text-sm cursor-pointer hover:text-vs-accent transition-colors">
|
||||
<label
|
||||
class="flex items-center gap-2 text-vs-text text-sm cursor-pointer hover:text-vs-accent transition-colors"
|
||||
>
|
||||
<div class="relative">
|
||||
<input
|
||||
type="checkbox"
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ export class SessionCard extends LitElement {
|
|||
if (!playerElement) return;
|
||||
|
||||
// Create single renderer for this card
|
||||
this.renderer = new Renderer(playerElement, 80, 24, 10000, 4, false);
|
||||
this.renderer = new Renderer(playerElement, 80, 24, 10000, 4);
|
||||
|
||||
// Always use snapshot endpoint for cards
|
||||
const url = `/api/sessions/${this.session.id}/snapshot`;
|
||||
|
|
|
|||
|
|
@ -187,10 +187,16 @@ export class SessionView extends LitElement {
|
|||
}, delay);
|
||||
|
||||
// Listen for session exit events
|
||||
terminalElement.addEventListener('session-exit', this.handleSessionExit.bind(this) as EventListener);
|
||||
|
||||
terminalElement.addEventListener(
|
||||
'session-exit',
|
||||
this.handleSessionExit.bind(this) as EventListener
|
||||
);
|
||||
|
||||
// Listen for terminal resize events to capture dimensions
|
||||
terminalElement.addEventListener('terminal-resize', this.handleTerminalResize.bind(this) as EventListener);
|
||||
terminalElement.addEventListener(
|
||||
'terminal-resize',
|
||||
this.handleTerminalResize.bind(this) as EventListener
|
||||
);
|
||||
}
|
||||
|
||||
private async handleKeyboardInput(e: KeyboardEvent) {
|
||||
|
|
@ -383,14 +389,16 @@ export class SessionView extends LitElement {
|
|||
controls.style.transition = 'transform 0.3s ease';
|
||||
|
||||
// Calculate available space to match closed keyboard layout
|
||||
const header = this.querySelector('.flex.items-center.justify-between.p-4.border-b') as HTMLElement;
|
||||
const header = this.querySelector(
|
||||
'.flex.items-center.justify-between.p-4.border-b'
|
||||
) as HTMLElement;
|
||||
const headerHeight = header?.offsetHeight || 60;
|
||||
const controlsHeight = controls?.offsetHeight || 120;
|
||||
|
||||
// Calculate exact space to maintain same gap as when keyboard is closed
|
||||
const availableHeight = viewportHeight - headerHeight - controlsHeight;
|
||||
const inputArea = textarea.parentElement as HTMLElement;
|
||||
|
||||
|
||||
if (inputArea && availableHeight > 0) {
|
||||
// Set the input area to exactly fill the space, maintaining natural flex behavior
|
||||
inputArea.style.height = `${availableHeight}px`;
|
||||
|
|
@ -717,11 +725,16 @@ export class SessionView extends LitElement {
|
|||
<span class="${this.session.status === 'running' ? 'text-vs-user' : 'text-vs-warning'}">
|
||||
${this.session.status.toUpperCase()}
|
||||
</span>
|
||||
${this.terminalCols > 0 && this.terminalRows > 0 ? html`
|
||||
<span class="text-vs-muted text-xs opacity-60" style="font-size: 10px; line-height: 1;">
|
||||
${this.terminalCols}×${this.terminalRows}
|
||||
</span>
|
||||
` : ''}
|
||||
${this.terminalCols > 0 && this.terminalRows > 0
|
||||
? html`
|
||||
<span
|
||||
class="text-vs-muted text-xs opacity-60"
|
||||
style="font-size: 10px; line-height: 1;"
|
||||
>
|
||||
${this.terminalCols}×${this.terminalRows}
|
||||
</span>
|
||||
`
|
||||
: ''}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -160,7 +160,7 @@ export class Renderer {
|
|||
|
||||
parseCastFile(content: string): void {
|
||||
const lines = content.trim().split('\n');
|
||||
let outputEvents: string[] = [];
|
||||
const outputEvents: string[] = [];
|
||||
|
||||
// Clear terminal
|
||||
this.terminal.clear();
|
||||
|
|
@ -194,7 +194,7 @@ export class Renderer {
|
|||
console.warn('Failed to parse cast line:', line);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Write all output at once, then scroll when rendering is complete
|
||||
if (outputEvents.length > 0) {
|
||||
const allOutput = outputEvents.join('');
|
||||
|
|
@ -236,11 +236,11 @@ export class Renderer {
|
|||
this.terminal.resize(width, height);
|
||||
// Always use ScaleFitAddon for consistent scaling behavior
|
||||
this.scaleFitAddon.fit();
|
||||
|
||||
|
||||
// Emit custom event with terminal dimensions
|
||||
const event = new CustomEvent('terminal-resize', {
|
||||
detail: { cols: width, rows: height },
|
||||
bubbles: true
|
||||
bubbles: true,
|
||||
});
|
||||
this.container.dispatchEvent(event);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,18 +8,22 @@
|
|||
font-style: normal;
|
||||
font-weight: 300 700;
|
||||
font-display: swap;
|
||||
src: url('/fonts/FiraCode-VF.woff2') format('woff2-variations'),
|
||||
url('/fonts/FiraCode-VF.ttf') format('truetype-variations');
|
||||
src:
|
||||
url('/fonts/FiraCode-VF.woff2') format('woff2-variations'),
|
||||
url('/fonts/FiraCode-VF.ttf') format('truetype-variations');
|
||||
font-variation-settings: 'wght' 400;
|
||||
}
|
||||
|
||||
/* Override Tailwind's font-mono to use Fira Code */
|
||||
.font-mono {
|
||||
font-family: 'Fira Code', ui-monospace, SFMono-Regular, 'SF Mono', Consolas, 'Liberation Mono', Menlo, monospace !important;
|
||||
font-family:
|
||||
'Fira Code', ui-monospace, SFMono-Regular, 'SF Mono', Consolas, 'Liberation Mono', Menlo,
|
||||
monospace !important;
|
||||
}
|
||||
|
||||
/* Mobile scroll and touch behavior fixes */
|
||||
html, body {
|
||||
html,
|
||||
body {
|
||||
overscroll-behavior: none;
|
||||
touch-action: pan-x pan-y;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
|
|
@ -76,7 +80,9 @@ body {
|
|||
/* XTerm terminal styling */
|
||||
.xterm {
|
||||
padding: 0 !important;
|
||||
font-family: 'Fira Code', ui-monospace, SFMono-Regular, 'SF Mono', Consolas, 'Liberation Mono', Menlo, monospace !important;
|
||||
font-family:
|
||||
'Fira Code', ui-monospace, SFMono-Regular, 'SF Mono', Consolas, 'Liberation Mono', Menlo,
|
||||
monospace !important;
|
||||
}
|
||||
|
||||
.xterm .xterm-viewport {
|
||||
|
|
|
|||
Loading…
Reference in a new issue