mirror of
https://github.com/hanzoai/dev.git
synced 2026-10-25 03:32:32 +00:00
feat(release): add @hanzo/dev npm package publishing
Create parallel dev-cli/ package structure for @hanzo/dev npm distribution: - Add bin/dev.js entry point that resolves platform binary - Add postinstall.js for binary download on install - Add scripts/preinstall.js for Windows cleanup - Add scripts/windows-cleanup.ps1 PowerShell helper Update release workflow to: - Create @hanzo/dev-* platform packages alongside @just-every/code-* - Rename code-* binaries to dev-* in @hanzo/dev packages - Update dev-cli/package.json with version and optionalDependencies - Publish @hanzo/dev main package to npm This fixes the broken @hanzo/dev npm package which was missing platform binary packages (@hanzo/dev-darwin-arm64, etc.)
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
#!/usr/bin/env node
|
||||
// Windows-friendly preinstall: proactively free file locks from prior installs
|
||||
// so npm/yarn/pnpm can stage the new package. No-ops on non-Windows.
|
||||
|
||||
import { platform } from 'os';
|
||||
import { execSync } from 'child_process';
|
||||
import { existsSync, readdirSync, rmSync, readFileSync, statSync } from 'fs';
|
||||
import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
|
||||
function isWSL() {
|
||||
if (platform() !== 'linux') return false;
|
||||
try {
|
||||
const rel = readFileSync('/proc/version', 'utf8').toLowerCase();
|
||||
return rel.includes('microsoft') || !!process.env.WSL_DISTRO_NAME;
|
||||
} catch { return false; }
|
||||
}
|
||||
|
||||
const isWin = platform() === 'win32';
|
||||
const wsl = isWSL();
|
||||
const isWinLike = isWin || wsl;
|
||||
|
||||
// Scope: only run for global installs, unless explicitly forced. Allow opt-out.
|
||||
const isGlobal = process.env.npm_config_global === 'true';
|
||||
const force = process.env.DEV_FORCE_PREINSTALL === '1';
|
||||
const skip = process.env.DEV_SKIP_PREINSTALL === '1';
|
||||
if (!isWinLike || skip || (!isGlobal && !force)) process.exit(0);
|
||||
|
||||
function tryExec(cmd, opts = {}) {
|
||||
try { execSync(cmd, { stdio: ['ignore', 'ignore', 'ignore'], shell: true, ...opts }); } catch { /* ignore */ }
|
||||
}
|
||||
|
||||
// 1) Stop our native binary if it is holding locks. Avoid killing unrelated tools.
|
||||
// Only available on native Windows; skip entirely on WSL to avoid noise.
|
||||
if (isWin) {
|
||||
tryExec('taskkill /IM dev-x86_64-pc-windows-msvc.exe /F');
|
||||
}
|
||||
|
||||
// 2) Remove stale staging dirs from previous failed installs under the global
|
||||
// @hanzo scope, which npm will reuse (e.g., .dev-XXXXX). Remove only
|
||||
// old entries and never the current staging or live package.
|
||||
try {
|
||||
let scopeDir = '';
|
||||
try {
|
||||
const root = execSync('npm root -g', { stdio: ['ignore', 'pipe', 'ignore'], shell: true }).toString().trim();
|
||||
scopeDir = path.join(root, '@hanzo');
|
||||
} catch {
|
||||
// Fall back to guessing from this script location: <staging>\..\..\
|
||||
const here = path.resolve(path.dirname(fileURLToPath(import.meta.url)));
|
||||
scopeDir = path.resolve(here, '..');
|
||||
}
|
||||
if (existsSync(scopeDir)) {
|
||||
const now = Date.now();
|
||||
const maxAgeMs = 2 * 60 * 60 * 1000; // 2 hours
|
||||
const currentDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
||||
for (const name of readdirSync(scopeDir)) {
|
||||
if (!name.startsWith('.dev-')) continue;
|
||||
const p = path.join(scopeDir, name);
|
||||
if (path.resolve(p) === currentDir) continue; // never remove our current dir
|
||||
try {
|
||||
const st = statSync(p);
|
||||
const age = now - st.mtimeMs;
|
||||
if (age > maxAgeMs) rmSync(p, { recursive: true, force: true });
|
||||
} catch { /* ignore */ }
|
||||
}
|
||||
}
|
||||
} catch { /* ignore */ }
|
||||
|
||||
process.exit(0);
|
||||
@@ -0,0 +1,31 @@
|
||||
<#
|
||||
Helper to recover from EBUSY/EPERM during global npm upgrades on Windows.
|
||||
Closes running processes and removes stale package folders.
|
||||
|
||||
Usage (PowerShell):
|
||||
Set-ExecutionPolicy -Scope Process Bypass -Force
|
||||
./dev-cli/scripts/windows-cleanup.ps1
|
||||
#>
|
||||
|
||||
$ErrorActionPreference = 'SilentlyContinue'
|
||||
|
||||
Write-Host "Stopping running Hanzo Dev processes..."
|
||||
taskkill /IM dev-x86_64-pc-windows-msvc.exe /F 2>$null | Out-Null
|
||||
taskkill /IM dev.exe /F 2>$null | Out-Null
|
||||
taskkill /IM hanzo.exe /F 2>$null | Out-Null
|
||||
|
||||
Write-Host "Removing old global package (if present)..."
|
||||
$npmRoot = (& npm root -g).Trim()
|
||||
$pkgPath = Join-Path $npmRoot "@hanzo\dev"
|
||||
if (Test-Path $pkgPath) {
|
||||
try { Remove-Item -LiteralPath $pkgPath -Recurse -Force -ErrorAction Stop } catch {}
|
||||
}
|
||||
|
||||
Write-Host "Removing temp staging directories (if present)..."
|
||||
Get-ChildItem -LiteralPath (Join-Path $npmRoot "@hanzo") -Force -ErrorAction SilentlyContinue |
|
||||
Where-Object { $_.Name -like '.dev-*' } |
|
||||
ForEach-Object {
|
||||
try { Remove-Item -LiteralPath $_.FullName -Recurse -Force -ErrorAction Stop } catch {}
|
||||
}
|
||||
|
||||
Write-Host "Cleanup complete. You can now run: npm install -g @hanzo/dev@latest"
|
||||
Reference in New Issue
Block a user