mirror of
https://github.com/samsonjs/vibetunnel.git
synced 2026-03-25 09:25:50 +00:00
Fix npm package installation issues (#377)
This commit is contained in:
parent
8173a0f500
commit
d69a4c1ef3
4 changed files with 180 additions and 71 deletions
112
web/docs/npm.md
112
web/docs/npm.md
|
|
@ -414,4 +414,114 @@ npm install -g vibetunnel --build-from-source
|
|||
- `scripts/build-npm.js` - Unified npm build process with multi-platform support
|
||||
- `scripts/postinstall-npm.js` - Fallback compilation logic
|
||||
- `.prebuildrc` - Prebuild configuration for target platforms
|
||||
- `package.json` - Package configuration and file inclusions
|
||||
- `package.json` - Package configuration and file inclusions
|
||||
|
||||
## Release Notes
|
||||
|
||||
### Version 1.0.0-beta.11 (2025-07-16)
|
||||
|
||||
**Published to npm**: Successfully published as `vibetunnel@beta`
|
||||
|
||||
**Key Features**:
|
||||
- Cross-platform support for macOS (x64, arm64) and Linux (x64, arm64)
|
||||
- Pre-built native binaries for Node.js versions 20, 22, 23, and 24
|
||||
- Zero-dependency installation experience (no build tools required)
|
||||
- Comprehensive prebuild system with 24 total binaries included
|
||||
|
||||
**Release Process Learnings**:
|
||||
|
||||
1. **Version Synchronization**:
|
||||
- Must update version in both `web/package.json` and `mac/VibeTunnel/version.xcconfig`
|
||||
- Build process validates version sync to prevent mismatches
|
||||
- Version mismatch will cause build failure with clear error message
|
||||
|
||||
2. **NPM Publishing Requirements**:
|
||||
- Beta versions require `--tag beta` flag when publishing
|
||||
- Previously published versions cannot be overwritten (must increment version)
|
||||
- Use `--access public` flag for public package publishing
|
||||
|
||||
3. **Package Build Process**:
|
||||
- `pnpm run build:npm` creates the complete package with all prebuilds
|
||||
- Build output filename may show older version in logs but creates correct package
|
||||
- Always verify package version in `dist-npm/package.json` before publishing
|
||||
|
||||
4. **Docker Testing Verification**:
|
||||
- Successfully tested on Ubuntu 22.04 (both ARM64 and x64 architectures)
|
||||
- Installation works without any build tools installed
|
||||
- Server starts correctly with all expected functionality
|
||||
- HTTP endpoints respond properly
|
||||
|
||||
5. **Package Structure**:
|
||||
- Final package size: 8.3 MB (24.9 MB unpacked)
|
||||
- Contains 198 files including all prebuilds and web assets
|
||||
- Proper postinstall script ensures seamless installation
|
||||
|
||||
**Installation**:
|
||||
```bash
|
||||
npm install -g vibetunnel@beta
|
||||
```
|
||||
|
||||
**Testing Commands Used**:
|
||||
```bash
|
||||
# Build the package
|
||||
cd web && pnpm run build:npm
|
||||
|
||||
# Verify package contents
|
||||
tar -tzf vibetunnel-1.0.0-beta.11.tgz | head -50
|
||||
|
||||
# Test with Docker
|
||||
docker build -t vibetunnel-test .
|
||||
docker run --rm vibetunnel-test
|
||||
|
||||
# Test cross-platform
|
||||
docker run --rm --platform linux/amd64 vibetunnel-test
|
||||
```
|
||||
|
||||
### Version History
|
||||
|
||||
- **1.0.0-beta.11.1** (2025-07-16): Fixed npm installation issues, latest stable release
|
||||
- **1.0.0-beta.11** (2025-07-16): Initial release with full prebuild system
|
||||
- **1.0.0-beta.10** (2025-07-14): Previous version (unpublished)
|
||||
|
||||
## NPM Distribution Tags
|
||||
|
||||
VibeTunnel uses npm dist-tags to manage different release channels:
|
||||
|
||||
### Current Tags
|
||||
- **latest**: Points to the most stable release (currently 1.0.0-beta.11.1)
|
||||
- **beta**: Points to the latest beta release (currently 1.0.0-beta.11.1)
|
||||
|
||||
### Managing Tags
|
||||
|
||||
```bash
|
||||
# View current tags
|
||||
npm dist-tag ls vibetunnel
|
||||
|
||||
# Set a version as latest
|
||||
npm dist-tag add vibetunnel@1.0.0-beta.11.1 latest
|
||||
|
||||
# Add a new tag
|
||||
npm dist-tag add vibetunnel@1.0.0-beta.12 next
|
||||
|
||||
# Remove a tag
|
||||
npm dist-tag rm vibetunnel next
|
||||
```
|
||||
|
||||
### Installation by Tag
|
||||
|
||||
```bash
|
||||
# Install latest stable (default)
|
||||
npm install -g vibetunnel
|
||||
|
||||
# Install specific tag
|
||||
npm install -g vibetunnel@beta
|
||||
npm install -g vibetunnel@latest
|
||||
|
||||
# Install specific version
|
||||
npm install -g vibetunnel@1.0.0-beta.11.1
|
||||
```
|
||||
|
||||
### Best Practices
|
||||
- Always tag beta releases with `beta` tag
|
||||
- Only promote to `latest` after testing confirms stability
|
||||
- Use semantic versioning for beta iterations (e.g., 1.0.0-beta.11.1, 1.0.0-beta.11.2)
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "vibetunnel",
|
||||
"version": "1.0.0-beta.10",
|
||||
"version": "1.0.0-beta.11",
|
||||
"description": "Terminal sharing server with web interface - supports macOS, Linux, and headless environments",
|
||||
"main": "lib/cli.js",
|
||||
"bin": {
|
||||
|
|
@ -48,7 +48,6 @@
|
|||
"@codemirror/theme-one-dark": "^6.1.3",
|
||||
"@codemirror/view": "^6.38.0",
|
||||
"@xterm/headless": "^5.5.0",
|
||||
"authenticate-pam": "^1.0.5",
|
||||
"bonjour-service": "^1.3.0",
|
||||
"chalk": "^5.4.1",
|
||||
"compression": "^1.8.0",
|
||||
|
|
@ -60,13 +59,14 @@
|
|||
"mime-types": "^3.0.1",
|
||||
"monaco-editor": "^0.52.2",
|
||||
"multer": "^2.0.1",
|
||||
"node-addon-api": "^7.1.0",
|
||||
"node-pty": "file:node-pty",
|
||||
"postject": "1.0.0-alpha.6",
|
||||
"signal-exit": "^4.1.0",
|
||||
"web-push": "^3.6.7",
|
||||
"ws": "^8.18.3"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"authenticate-pam": "^1.0.5"
|
||||
},
|
||||
"keywords": [
|
||||
"terminal",
|
||||
"multiplexer",
|
||||
|
|
|
|||
|
|
@ -375,6 +375,60 @@ function mergePrebuilds() {
|
|||
console.log(`✅ Merged prebuilds: ${nodePtyCount} node-pty + ${pamCount} authenticate-pam = ${allPrebuilds.length} total\n`);
|
||||
}
|
||||
|
||||
// Bundle node-pty with its dependencies
|
||||
function bundleNodePty() {
|
||||
console.log('📦 Bundling node-pty with dependencies...\n');
|
||||
|
||||
const nodePtyDir = path.join(DIST_DIR, 'node-pty');
|
||||
const nodeAddonApiDest = path.join(nodePtyDir, 'node_modules', 'node-addon-api');
|
||||
|
||||
// Try multiple strategies to find node-addon-api
|
||||
const possiblePaths = [];
|
||||
|
||||
// Strategy 1: Direct dependency in node_modules
|
||||
const directPath = path.join(ROOT_DIR, 'node_modules', 'node-addon-api');
|
||||
if (fs.existsSync(directPath)) {
|
||||
possiblePaths.push(directPath);
|
||||
}
|
||||
|
||||
// Strategy 2: pnpm structure (any version)
|
||||
const pnpmDir = path.join(ROOT_DIR, 'node_modules', '.pnpm');
|
||||
if (fs.existsSync(pnpmDir)) {
|
||||
const pnpmEntries = fs.readdirSync(pnpmDir)
|
||||
.filter(dir => dir.startsWith('node-addon-api@'))
|
||||
.map(dir => path.join(pnpmDir, dir, 'node_modules', 'node-addon-api'))
|
||||
.filter(fs.existsSync);
|
||||
possiblePaths.push(...pnpmEntries);
|
||||
}
|
||||
|
||||
// Strategy 3: Check if it's a dependency of node-pty
|
||||
const nodePtyModules = path.join(ROOT_DIR, 'node-pty', 'node_modules', 'node-addon-api');
|
||||
if (fs.existsSync(nodePtyModules)) {
|
||||
possiblePaths.push(nodePtyModules);
|
||||
}
|
||||
|
||||
// Strategy 4: Hoisted by npm/yarn (parent directory)
|
||||
const hoistedPath = path.join(ROOT_DIR, '..', 'node_modules', 'node-addon-api');
|
||||
if (fs.existsSync(hoistedPath)) {
|
||||
possiblePaths.push(hoistedPath);
|
||||
}
|
||||
|
||||
if (possiblePaths.length > 0) {
|
||||
const nodeAddonApiSrc = possiblePaths[0];
|
||||
fs.mkdirSync(path.dirname(nodeAddonApiDest), { recursive: true });
|
||||
fs.cpSync(nodeAddonApiSrc, nodeAddonApiDest, { recursive: true });
|
||||
console.log(` ✅ Bundled node-addon-api from: ${path.relative(ROOT_DIR, nodeAddonApiSrc)}`);
|
||||
} else {
|
||||
console.error(' ❌ CRITICAL: node-addon-api not found - source compilation will fail!');
|
||||
console.error(' Please ensure node-addon-api is installed as a dependency.');
|
||||
console.error(' Run: pnpm add -D node-addon-api');
|
||||
// Don't exit during build - let the developer decide
|
||||
console.warn(' ⚠️ Continuing build, but npm package may have issues if prebuilds are missing.');
|
||||
}
|
||||
|
||||
console.log('✅ node-pty bundled with dependencies\n');
|
||||
}
|
||||
|
||||
// Copy authenticate-pam module for Linux support (OUR LINUX FIX)
|
||||
function copyAuthenticatePam() {
|
||||
console.log('📦 Copying authenticate-pam module for Linux support...\n');
|
||||
|
|
@ -577,11 +631,14 @@ async function main() {
|
|||
copyRecursive(src, dest);
|
||||
});
|
||||
|
||||
// Step 4: Copy authenticate-pam module for Linux support (OUR ENHANCEMENT)
|
||||
// Step 4: Bundle node-pty with dependencies
|
||||
bundleNodePty();
|
||||
|
||||
// Step 5: Copy authenticate-pam module for Linux support (OUR ENHANCEMENT)
|
||||
copyAuthenticatePam();
|
||||
|
||||
// Step 5: Use package.npm.json if available, otherwise create clean package.json
|
||||
console.log('\n4️⃣ Creating package.json for npm...\n');
|
||||
// Step 6: Use package.npm.json if available, otherwise create clean package.json
|
||||
console.log('\n6️⃣ Creating package.json for npm...\n');
|
||||
|
||||
const npmPackageJsonPath = path.join(ROOT_DIR, 'package.npm.json');
|
||||
let npmPackageJson;
|
||||
|
|
|
|||
|
|
@ -21,23 +21,8 @@ if (isDevelopment) {
|
|||
return;
|
||||
}
|
||||
|
||||
// Create node_modules directory if it doesn't exist
|
||||
const nodeModulesDir = path.join(__dirname, '..', 'node_modules');
|
||||
if (!fs.existsSync(nodeModulesDir)) {
|
||||
fs.mkdirSync(nodeModulesDir, { recursive: true });
|
||||
}
|
||||
|
||||
// Create symlink for node-pty so it can be required normally
|
||||
const nodePtySource = path.join(__dirname, '..', 'node-pty');
|
||||
const nodePtyTarget = path.join(nodeModulesDir, 'node-pty');
|
||||
if (!fs.existsSync(nodePtyTarget) && fs.existsSync(nodePtySource)) {
|
||||
try {
|
||||
fs.symlinkSync(nodePtySource, nodePtyTarget, 'dir');
|
||||
console.log('✓ Created node-pty symlink in node_modules');
|
||||
} catch (error) {
|
||||
console.warn('Warning: Could not create node-pty symlink:', error.message);
|
||||
}
|
||||
}
|
||||
// For npm package, node-pty is bundled in the package root
|
||||
// No need to create symlinks as it's accessed directly
|
||||
|
||||
// Get Node ABI version
|
||||
const nodeABI = process.versions.modules;
|
||||
|
|
@ -114,51 +99,8 @@ const compileFromSource = (moduleName, moduleDir) => {
|
|||
execSync('npm install -g node-gyp', { stdio: 'inherit' });
|
||||
}
|
||||
|
||||
// For node-pty, ensure node-addon-api is available
|
||||
if (moduleName === 'node-pty') {
|
||||
const nodeAddonApiPath = path.join(moduleDir, 'node_modules', 'node-addon-api');
|
||||
if (!fs.existsSync(nodeAddonApiPath)) {
|
||||
console.log(` Setting up node-addon-api for ${moduleName}...`);
|
||||
|
||||
// Create node_modules directory
|
||||
const nodeModulesDir = path.join(moduleDir, 'node_modules');
|
||||
fs.mkdirSync(nodeModulesDir, { recursive: true });
|
||||
|
||||
// Try multiple locations for node-addon-api
|
||||
const possiblePaths = [
|
||||
path.join(__dirname, '..', 'node_modules', 'node-addon-api'),
|
||||
path.join(__dirname, '..', '..', 'node_modules', 'node-addon-api'),
|
||||
path.join(__dirname, '..', '..', '..', 'node_modules', 'node-addon-api'),
|
||||
'/usr/local/lib/node_modules/vibetunnel/node_modules/node-addon-api',
|
||||
'/usr/lib/node_modules/vibetunnel/node_modules/node-addon-api'
|
||||
];
|
||||
|
||||
let found = false;
|
||||
for (const sourcePath of possiblePaths) {
|
||||
if (fs.existsSync(sourcePath)) {
|
||||
console.log(` Found node-addon-api at: ${sourcePath}`);
|
||||
console.log(` Copying to ${nodeAddonApiPath}...`);
|
||||
fs.cpSync(sourcePath, nodeAddonApiPath, { recursive: true });
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
// As a fallback, install it
|
||||
console.log(` Installing node-addon-api package...`);
|
||||
try {
|
||||
execSync('npm install node-addon-api@^7.1.0 --no-save --no-package-lock', {
|
||||
cwd: moduleDir,
|
||||
stdio: 'inherit'
|
||||
});
|
||||
} catch (e) {
|
||||
console.error(' Failed to install node-addon-api:', e.message);
|
||||
console.error(' Trying to continue anyway...');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// For node-pty, node-addon-api is included as a dependency in its package.json
|
||||
// npm should handle it automatically during source compilation
|
||||
|
||||
execSync('node-gyp rebuild', {
|
||||
cwd: moduleDir,
|
||||
|
|
@ -186,7 +128,7 @@ const modules = [
|
|||
version: '1.0.5',
|
||||
dir: path.join(__dirname, '..', 'node_modules', 'authenticate-pam'),
|
||||
build: path.join(__dirname, '..', 'node_modules', 'authenticate-pam', 'build', 'Release', 'authenticate_pam.node'),
|
||||
essential: true, // PAM is essential for server environments
|
||||
essential: false, // Optional - falls back to other auth methods
|
||||
platforms: ['linux', 'darwin'] // Needed on Linux and macOS
|
||||
}
|
||||
];
|
||||
|
|
|
|||
Loading…
Reference in a new issue