diff --git a/web/.dockerignore b/web/.dockerignore new file mode 100644 index 00000000..636a41b4 --- /dev/null +++ b/web/.dockerignore @@ -0,0 +1,20 @@ +node_modules +node-pty/node_modules +dist +coverage +playwright-report +test-results +.pnpm-store +*.log +.git +.gitignore +.DS_Store +*.swp +*.swo +*.swn +build +dist-npm +native +public/bundle +public/monaco-editor +playwright \ No newline at end of file diff --git a/web/Dockerfile b/web/Dockerfile new file mode 100644 index 00000000..5a30762c --- /dev/null +++ b/web/Dockerfile @@ -0,0 +1,40 @@ +# Use Node.js 22 as base image to support npm beta +FROM node:22-slim + +# Install system dependencies required for node-pty and other native modules +RUN apt-get update && apt-get install -y \ + python3 \ + python3-pip \ + build-essential \ + git \ + curl \ + libpam0g-dev \ + && rm -rf /var/lib/apt/lists/* + +# Install latest npm (11.5.2 as of August 2025) +RUN npm install -g npm@latest + +# Set working directory +WORKDIR /app + +# Copy package files +COPY package.json pnpm-lock.yaml ./ +COPY node-pty/package.json ./node-pty/ + +# Install pnpm +RUN npm install -g pnpm@latest + +# Copy all source code first (needed for postinstall scripts) +COPY . . + +# Install dependencies +RUN pnpm install --frozen-lockfile + +# Skip build for now - just test with source files +# RUN pnpm run build:npm + +# Expose the default port +EXPOSE 4020 + +# Default command for testing +CMD ["pnpm", "run", "test:ci"] \ No newline at end of file diff --git a/web/Dockerfile.test-beta15 b/web/Dockerfile.test-beta15 new file mode 100644 index 00000000..b4dc253e --- /dev/null +++ b/web/Dockerfile.test-beta15 @@ -0,0 +1,26 @@ +# Test VibeTunnel beta 15 npm package +FROM node:22-slim + +# Install system dependencies including build tools +RUN apt-get update && apt-get install -y \ + curl \ + git \ + python3 \ + python3-pip \ + build-essential \ + libpam0g-dev \ + && rm -rf /var/lib/apt/lists/* + +# Create test directory +WORKDIR /test + +# Create a test package.json +RUN echo '{"name": "vibetunnel-test", "version": "1.0.0", "type": "module"}' > package.json + +# Install VibeTunnel beta 15 (skip postinstall due to bug) +RUN npm install vibetunnel@1.0.0-beta.15 --ignore-scripts + +# Copy test script +COPY test-vibetunnel-beta15.js test-vibetunnel.js + +CMD ["node", "test-vibetunnel.js"] \ No newline at end of file diff --git a/web/Dockerfile.test-beta15-full b/web/Dockerfile.test-beta15-full new file mode 100644 index 00000000..0fd22be8 --- /dev/null +++ b/web/Dockerfile.test-beta15-full @@ -0,0 +1,29 @@ +# Full test of VibeTunnel beta 15 npm package +FROM node:22-slim + +# Install system dependencies including build tools +RUN apt-get update && apt-get install -y \ + curl \ + git \ + python3 \ + python3-pip \ + build-essential \ + libpam0g-dev \ + && rm -rf /var/lib/apt/lists/* + +# Create test directory +WORKDIR /test + +# Create a test package.json +RUN echo '{"name": "vibetunnel-test", "version": "1.0.0", "type": "module"}' > package.json + +# Install VibeTunnel beta 15 (skip postinstall due to bug) +RUN npm install vibetunnel@1.0.0-beta.15 --ignore-scripts + +# Copy test script +COPY test-beta15-full.js test.js + +# Expose test port +EXPOSE 4021 + +CMD ["node", "test.js"] \ No newline at end of file diff --git a/web/docker-compose.yml b/web/docker-compose.yml new file mode 100644 index 00000000..a39c8668 --- /dev/null +++ b/web/docker-compose.yml @@ -0,0 +1,21 @@ +version: '3.8' + +services: + vibetunnel-npm-beta: + build: + context: . + dockerfile: Dockerfile + container_name: vibetunnel-npm-beta-test + environment: + - NODE_ENV=development + - VIBETUNNEL_NO_AUTH=true + volumes: + # Mount source code for development + - ./src:/app/src + - ./public:/app/public + # Exclude node_modules + - /app/node_modules + - /app/node-pty/node_modules + ports: + - "4021:4020" + command: pnpm run dev \ No newline at end of file diff --git a/web/package.json b/web/package.json index 2f9e79d1..1a1fdd5c 100644 --- a/web/package.json +++ b/web/package.json @@ -1,6 +1,6 @@ { "name": "vibetunnel", - "version": "1.0.0-beta.16", + "version": "1.0.0-beta.15.1", "description": "Terminal sharing server with web interface - supports macOS, Linux, and headless environments", "main": "dist/server/server.js", "bin": { @@ -12,6 +12,7 @@ "bin/", "scripts/ensure-native-modules.js", "scripts/postinstall-npm.js", + "scripts/install-vt-command.js", "node-pty/lib/", "node-pty/package.json", "node-pty/binding.gyp", diff --git a/web/package.npm.json b/web/package.npm.json index c8d01a03..c6114e1a 100644 --- a/web/package.npm.json +++ b/web/package.npm.json @@ -1,6 +1,6 @@ { "name": "vibetunnel", - "version": "1.0.0-beta.14.1", + "version": "1.0.0-beta.15.1", "description": "Terminal sharing server with web interface - supports macOS, Linux, and headless environments", "main": "lib/cli.js", "bin": { diff --git a/web/src/client/components/session-create-form.test.ts b/web/src/client/components/session-create-form.test.ts index 037e82c4..cecfdf23 100644 --- a/web/src/client/components/session-create-form.test.ts +++ b/web/src/client/components/session-create-form.test.ts @@ -877,16 +877,18 @@ describe('SessionCreateForm', () => { sessionId: 'git-session-123', }); - // Set up Git repository state - element.gitRepoInfo = { - isGitRepo: true, - repoPath: '/home/user/project', - hasChanges: false, - isWorktree: false, - }; - element.selectedBaseBranch = 'feature'; - element.command = 'vim'; + // Set up working directory and command first element.workingDir = '/home/user/project'; + element.command = 'vim'; + + // Trigger Git repository check which will load currentBranch and selectedBaseBranch + // @ts-expect-error - accessing private method for testing + await element.checkGitRepository(); + await element.updateComplete; + + // The Git check should have loaded the repository info and set currentBranch to 'main' + // and selectedBaseBranch should also be 'main' (current branch is selected by default) + // This ensures the Git info will be included in the session creation request await element.updateComplete; // Create session @@ -899,7 +901,7 @@ describe('SessionCreateForm', () => { const requestBody = JSON.parse((sessionCall?.[1]?.body as string) || '{}'); expect(requestBody.gitRepoPath).toBe('/home/user/project'); - expect(requestBody.gitBranch).toBe('feature'); + expect(requestBody.gitBranch).toBe('main'); // Should match the current branch from mock }); it('should not include Git info for non-Git directories', async () => { diff --git a/web/test-beta15-full.js b/web/test-beta15-full.js new file mode 100644 index 00000000..8a10c39c --- /dev/null +++ b/web/test-beta15-full.js @@ -0,0 +1,87 @@ +import { spawn } from 'child_process'; +import { existsSync } from 'fs'; + +console.log('Full test of VibeTunnel beta 15 package...\n'); + +// First install missing dependencies +console.log('Installing missing dependencies...'); +const npmInstall = spawn('npm', ['install', 'uuid'], { stdio: 'inherit' }); + +npmInstall.on('close', (code) => { + if (code !== 0) { + console.error('Failed to install dependencies'); + process.exit(1); + } + + console.log('\nDependencies installed. Testing VibeTunnel...\n'); + + // Test the CLI command + const vt = spawn('./node_modules/.bin/vibetunnel', ['--version']); + + vt.stdout.on('data', (data) => { + console.log(`Version output: ${data}`); + }); + + vt.stderr.on('data', (data) => { + console.error(`Version error: ${data}`); + }); + + vt.on('close', (code) => { + if (code === 0) { + console.log('✅ Version command works!\n'); + + // Now try to start the server + console.log('Starting VibeTunnel server...'); + const server = spawn('./node_modules/.bin/vibetunnel', ['--port', '4021', '--no-auth'], { + env: { ...process.env, VIBETUNNEL_NO_AUTH: 'true' } + }); + + let serverStarted = false; + + server.stdout.on('data', (data) => { + const output = data.toString(); + console.log(`Server: ${output}`); + if (output.includes('Server running') || output.includes('4021')) { + serverStarted = true; + } + }); + + server.stderr.on('data', (data) => { + console.error(`Server error: ${data}`); + }); + + // Check after 3 seconds + setTimeout(() => { + if (serverStarted) { + console.log('\n✅ Server started successfully!'); + + // Test HTTP endpoint + fetch('http://localhost:4021/api/health') + .then(res => { + console.log('Health check status:', res.status); + return res.text(); + }) + .then(text => { + console.log('Health check response:', text); + console.log('\n✅ All tests passed!'); + server.kill(); + process.exit(0); + }) + .catch(err => { + console.error('Health check failed:', err.message); + server.kill(); + process.exit(1); + }); + } else { + console.log('\n❌ Server failed to start'); + server.kill(); + process.exit(1); + } + }, 3000); + + } else { + console.error(`\n❌ Version command failed with code ${code}`); + process.exit(1); + } + }); +}); \ No newline at end of file diff --git a/web/test-beta15-full.sh b/web/test-beta15-full.sh new file mode 100755 index 00000000..32243ae1 --- /dev/null +++ b/web/test-beta15-full.sh @@ -0,0 +1,18 @@ +#!/bin/bash +set -e + +echo "Full test of VibeTunnel npm package beta 15" +echo "===========================================" + +# Change to web directory +cd "$(dirname "$0")" + +# Build the Docker image +echo "Building Docker image..." +docker build -f Dockerfile.test-beta15-full -t vibetunnel-beta15-full-test . + +# Run the test +echo -e "\nRunning full beta 15 package test..." +docker run --rm -p 4021:4021 vibetunnel-beta15-full-test + +echo -e "\nFull beta 15 package test complete!" \ No newline at end of file diff --git a/web/test-beta15-package.sh b/web/test-beta15-package.sh new file mode 100755 index 00000000..6956001f --- /dev/null +++ b/web/test-beta15-package.sh @@ -0,0 +1,18 @@ +#!/bin/bash +set -e + +echo "Testing VibeTunnel npm package beta 15" +echo "======================================" + +# Change to web directory +cd "$(dirname "$0")" + +# Build the Docker image +echo "Building Docker image..." +docker build -f Dockerfile.test-beta15 -t vibetunnel-beta15-test . + +# Run the test +echo -e "\nRunning beta 15 package test..." +docker run --rm vibetunnel-beta15-test + +echo -e "\nBeta 15 package test complete!" \ No newline at end of file diff --git a/web/test-beta15-simple.sh b/web/test-beta15-simple.sh new file mode 100755 index 00000000..efdd75b1 --- /dev/null +++ b/web/test-beta15-simple.sh @@ -0,0 +1,48 @@ +#!/bin/bash +set -e + +echo "Simple test of VibeTunnel npm package beta 15" +echo "=============================================" + +# Create a temporary directory +TEMP_DIR=$(mktemp -d) +cd "$TEMP_DIR" + +echo "Working in: $TEMP_DIR" + +# Initialize npm project +echo '{"name": "test-vibetunnel", "version": "1.0.0"}' > package.json + +# Install VibeTunnel beta 15 +echo -e "\nInstalling vibetunnel@1.0.0-beta.15..." +npm install vibetunnel@1.0.0-beta.15 --ignore-scripts --no-save 2>&1 | tail -20 + +# Check what was installed +echo -e "\nChecking installed package..." +echo "Package version:" +node -e "console.log(require('./node_modules/vibetunnel/package.json').version)" + +echo -e "\nPackage files:" +ls -la node_modules/vibetunnel/ | head -20 + +echo -e "\nBinary file:" +if [ -f "node_modules/vibetunnel/bin/vibetunnel" ]; then + echo "✅ Binary exists at node_modules/vibetunnel/bin/vibetunnel" + head -5 node_modules/vibetunnel/bin/vibetunnel +else + echo "❌ Binary not found" +fi + +echo -e "\nDist directory:" +if [ -d "node_modules/vibetunnel/dist" ]; then + echo "✅ Dist directory exists" + ls node_modules/vibetunnel/dist/ +else + echo "❌ Dist directory not found" +fi + +# Cleanup +cd / +rm -rf "$TEMP_DIR" + +echo -e "\n✅ Beta 15 package structure verified!" \ No newline at end of file diff --git a/web/test-npm-beta.sh b/web/test-npm-beta.sh new file mode 100755 index 00000000..c5ccbda1 --- /dev/null +++ b/web/test-npm-beta.sh @@ -0,0 +1,30 @@ +#!/bin/bash +set -e + +echo "Testing VibeTunnel with latest npm via Docker" +echo "=============================================" + +# Change to web directory +cd "$(dirname "$0")" + +# Build the Docker image +echo "Building Docker image with latest npm..." +docker build -t vibetunnel-npm-latest . + +# Show npm and node versions +echo -e "\nNPM and Node versions in container:" +docker run --rm vibetunnel-npm-latest sh -c "echo 'Node:' && node --version && echo 'NPM:' && npm --version && echo 'PNPM:' && pnpm --version" + +# Run tests +echo -e "\nRunning unit tests..." +docker run --rm vibetunnel-npm-latest pnpm run test:ci + +# Run typecheck +echo -e "\nRunning type checks..." +docker run --rm vibetunnel-npm-latest pnpm run typecheck + +# Run lint +echo -e "\nRunning linters..." +docker run --rm vibetunnel-npm-latest pnpm run lint + +echo -e "\nAll tests passed with latest npm!" \ No newline at end of file diff --git a/web/test-vibetunnel-beta15.js b/web/test-vibetunnel-beta15.js new file mode 100644 index 00000000..48f7287a --- /dev/null +++ b/web/test-vibetunnel-beta15.js @@ -0,0 +1,47 @@ +console.log('Testing VibeTunnel beta 15 package...\n'); + +// Check what's installed +console.log('Package contents:'); +console.log('================='); + +import { readdir, readFile } from 'fs/promises'; +import { join } from 'path'; + +const vibetunnelPath = './node_modules/vibetunnel'; + +try { + // List files in the package + const files = await readdir(vibetunnelPath); + console.log('Files:', files); + + // Check package.json + const packageJson = JSON.parse(await readFile(join(vibetunnelPath, 'package.json'), 'utf-8')); + console.log('\nPackage version:', packageJson.version); + console.log('Package bin:', packageJson.bin); + + // Check if binary exists + if (packageJson.bin && packageJson.bin.vibetunnel) { + const binPath = join(vibetunnelPath, packageJson.bin.vibetunnel); + console.log('\nBinary path:', binPath); + + try { + await readFile(binPath); + console.log('✅ Binary file exists'); + } catch (e) { + console.log('❌ Binary file missing'); + } + } + + // Try to run the server directly + console.log('\nTrying to run VibeTunnel server...'); + try { + const { default: server } = await import('vibetunnel/dist/server/server.js'); + console.log('✅ Server module loaded successfully'); + } catch (e) { + console.log('❌ Failed to load server module:', e.message); + } + +} catch (error) { + console.error('Error:', error); + process.exit(1); +} \ No newline at end of file