diff --git a/package.json b/package.json index 8a65ef12a..904ab52fb 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ ], "scripts": { "dev": "./scripts/dev.sh", + "dev:win": "powershell ./scripts/dev.ps1", "dev:server": "npm run dev --workspace=@getpaseo/server", "dev:app": "npm run start --workspace=@getpaseo/app", "dev:website": "npm run dev --workspace=@getpaseo/website", @@ -36,6 +37,7 @@ "ios": "npm run ios --workspace=@getpaseo/app", "web": "npm run web --workspace=@getpaseo/app", "dev:desktop": "npm run dev --workspace=@getpaseo/desktop", + "dev:win:desktop": "npm run dev:win --workspace=@getpaseo/desktop", "build:desktop": "npm run version:sync-internal && npm run build:web --workspace=@getpaseo/app && npm run build --workspace=@getpaseo/desktop", "cli": "npx tsx packages/cli/src/index.js", "version": "npm run version:sync-internal && npm run release:prepare && git add -A", diff --git a/packages/desktop/package.json b/packages/desktop/package.json index 9b18e8e5b..7cf98e142 100644 --- a/packages/desktop/package.json +++ b/packages/desktop/package.json @@ -8,6 +8,7 @@ "build": "npm --prefix ../.. run build:daemon && npm run build:main && electron-builder --config electron-builder.yml", "build:main": "tsc -p tsconfig.json", "dev": "./scripts/dev.sh", + "dev:win": "powershell ./scripts/dev.ps1", "test": "vitest run", "typecheck": "tsc --noEmit -p tsconfig.json" }, diff --git a/packages/desktop/scripts/dev.ps1 b/packages/desktop/scripts/dev.ps1 new file mode 100644 index 000000000..609704eac --- /dev/null +++ b/packages/desktop/scripts/dev.ps1 @@ -0,0 +1,36 @@ +$ErrorActionPreference = "Stop" + +$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path +$DesktopDir = (Resolve-Path "$ScriptDir\..").Path +$AppDir = (Resolve-Path "$DesktopDir\..\app").Path +$RootDir = (Resolve-Path "$DesktopDir\..\..").Path + +# Build the Electron main process +npm run build:main + +# Get a random available port for Metro +$env:EXPO_PORT = (npx get-port-cli).Trim() + +# Set EXPO_DEV_URL in the environment so Electron inherits it +$env:EXPO_DEV_URL = "http://localhost:$($env:EXPO_PORT)" + +# Allow any origin in dev so Electron on random ports works. +# SECURITY: wildcard CORS is unsafe in production — only acceptable here because +# the daemon binds to localhost and this script is never used for production. +$env:PASEO_CORS_ORIGINS = "*" + +Write-Host @" +====================================================== + Paseo Desktop Dev (Windows) +====================================================== + Metro: http://localhost:$($env:EXPO_PORT) +====================================================== +"@ + +# Launch Metro + Electron together, kill both on exit +& "$RootDir\node_modules\.bin\concurrently" ` + --kill-others ` + --names "metro,electron" ` + --prefix-colors "magenta,cyan" ` + "cd `"$AppDir`" && npx expo start --port $($env:EXPO_PORT)" ` + "npx wait-on tcp:$($env:EXPO_PORT) && npx electron `"$DesktopDir`"" diff --git a/scripts/dev.ps1 b/scripts/dev.ps1 new file mode 100644 index 000000000..d86811c82 --- /dev/null +++ b/scripts/dev.ps1 @@ -0,0 +1,65 @@ +$ErrorActionPreference = "Stop" + +# Ensure node_modules/.bin is in PATH +$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path +$env:PATH = "$ScriptDir\..\node_modules\.bin;$env:PATH" + +# Derive PASEO_HOME: stable name for worktrees, temporary dir otherwise +if (-not $env:PASEO_HOME) { + $GitDir = git rev-parse --git-dir 2>$null + $GitCommonDir = git rev-parse --git-common-dir 2>$null + + if ($GitDir -and $GitCommonDir -and ($GitDir -ne $GitCommonDir)) { + # Inside a worktree — derive a stable home from the worktree name + $WorktreeRoot = git rev-parse --show-toplevel + $WorktreeName = (Split-Path -Leaf $WorktreeRoot).ToLower() -replace '[^a-z0-9-]', '-' -replace '-+', '-' -replace '^-|-$', '' + $env:PASEO_HOME = "$env:USERPROFILE\.paseo-$WorktreeName" + New-Item -ItemType Directory -Force -Path $env:PASEO_HOME | Out-Null + } else { + $env:PASEO_HOME = Join-Path ([System.IO.Path]::GetTempPath()) "paseo-dev-$([System.Guid]::NewGuid().ToString('N').Substring(0,6))" + New-Item -ItemType Directory -Force -Path $env:PASEO_HOME | Out-Null + # Register cleanup on exit + $TempPaseoHome = $env:PASEO_HOME + Register-EngineEvent PowerShell.Exiting -Action { + Remove-Item -Recurse -Force $TempPaseoHome -ErrorAction SilentlyContinue + } | Out-Null + } +} + +# Share speech models with the main install to avoid duplicate downloads +if (-not $env:PASEO_LOCAL_MODELS_DIR) { + $env:PASEO_LOCAL_MODELS_DIR = "$env:USERPROFILE\.paseo\models\local-speech" + New-Item -ItemType Directory -Force -Path $env:PASEO_LOCAL_MODELS_DIR | Out-Null +} + +Write-Host @" +====================================================== + Paseo Dev (Windows) +====================================================== + Home: $($env:PASEO_HOME) + Models: $($env:PASEO_LOCAL_MODELS_DIR) + Daemon: localhost:6767 +====================================================== +"@ + +# Allow any origin in dev so Electron on random ports all work. +# SECURITY: wildcard CORS is unsafe in production — only acceptable here because +# the daemon binds to localhost and this script is never used for production. +# Build dependencies required by the daemon (they only ship dist/) +Write-Host "Building @getpaseo/highlight..." +npm run build --workspace=@getpaseo/highlight +Write-Host "Building @getpaseo/relay..." +npm run build --workspace=@getpaseo/relay + +$env:PASEO_CORS_ORIGINS = "*" + +# Configure the app to auto-connect to this daemon on localhost +$env:EXPO_PUBLIC_LOCAL_DAEMON = "localhost:6767" +$env:BROWSER = "none" + +# Run both with concurrently +concurrently ` + --names "daemon,metro" ` + --prefix-colors "cyan,magenta" ` + "npm run dev:server" ` + "cd packages/app && npx expo start"