diff --git a/Makefile b/Makefile index 30c4628b7..a0932f73c 100644 --- a/Makefile +++ b/Makefile @@ -100,26 +100,49 @@ help: ## Show this help message @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-20s\033[0m %s\n", $$1, $$2}' ## Development +ifeq ($(OS),Windows_NT) dev: node_modules/.installed build-main clean-cache ## Start development server (Vite + nodemon watcher for Windows compatibility) @echo "Starting dev mode (2 watchers: nodemon for main process, vite for renderer)..." - @NODE_OPTIONS="--max-old-space-size=4096" npx concurrently -k --raw \ - "npx nodemon --exec node scripts/build-main-watch.js" \ + # On Windows, use npm run because bunx doesn't correctly pass arguments to concurrently + # https://github.com/oven-sh/bun/issues/18275 + @NODE_OPTIONS="--max-old-space-size=4096" npm x concurrently -k --raw \ + "bun x nodemon --exec node scripts/build-main-watch.js" \ + "vite" +else +dev: node_modules/.installed build-main ## Start development server (Vite + tsgo watcher for 10x faster type checking) + @bun x concurrently -k \ + "bun x concurrently \"$(TSGO) -w -p tsconfig.main.json\" \"bun x tsc-alias -w -p tsconfig.main.json\"" \ "vite" +endif clean-cache: ## Clean Vite cache (helps with EMFILE errors on Windows) @echo "Cleaning Vite cache..." @rm -rf node_modules/.vite +ifeq ($(OS),Windows_NT) dev-server: node_modules/.installed build-main ## Start server mode with hot reload (backend :3000 + frontend :5173). Use VITE_HOST=0.0.0.0 BACKEND_HOST=0.0.0.0 for remote access @echo "Starting dev-server..." @echo " Backend (IPC/WebSocket): http://$(or $(BACKEND_HOST),localhost):$(or $(BACKEND_PORT),3000)" @echo " Frontend (with HMR): http://$(or $(VITE_HOST),localhost):$(or $(VITE_PORT),5173)" @echo "" @echo "For remote access: make dev-server VITE_HOST=0.0.0.0 BACKEND_HOST=0.0.0.0" - @npx concurrently -k \ - "npx nodemon --exec node scripts/build-main-watch.js" \ - "bun x nodemon --watch dist/main.js --watch dist/main-server.js --delay 500ms --exec \"node dist/main.js server --host $(or $(BACKEND_HOST),localhost) --port $(or $(BACKEND_PORT),3000)\"" \ + @# On Windows, use npm run because bunxdoesn't correctly pass arguments + @npmx concurrently -k \ + "npmx nodemon --exec node scripts/build-main-watch.js" \ + "npmx nodemon --watch dist/main.js --watch dist/main-server.js --delay 500ms --exec \"node dist/main.js server --host $(or $(BACKEND_HOST),localhost) --port $(or $(BACKEND_PORT),3000)\"" \ "$(SHELL) -lc \"CMUX_VITE_HOST=$(or $(VITE_HOST),127.0.0.1) CMUX_VITE_PORT=$(or $(VITE_PORT),5173) VITE_BACKEND_URL=http://$(or $(BACKEND_HOST),localhost):$(or $(BACKEND_PORT),3000) vite\"" +else +dev-server: node_modules/.installed build-main ## Start server mode with hot reload (backend :3000 + frontend :5173). Use VITE_HOST=0.0.0.0 BACKEND_HOST=0.0.0.0 for remote access + @echo "Starting dev-server..." + @echo " Backend (IPC/WebSocket): http://$(or $(BACKEND_HOST),localhost):$(or $(BACKEND_PORT),3000)" + @echo " Frontend (with HMR): http://$(or $(VITE_HOST),localhost):$(or $(VITE_PORT),5173)" + @echo "" + @echo "For remote access: make dev-server VITE_HOST=0.0.0.0 BACKEND_HOST=0.0.0.0" + @bun x concurrently -k \ + "bun x concurrently \"$(TSGO) -w -p tsconfig.main.json\" \"bun x tsc-alias -w -p tsconfig.main.json\"" \ + "bun x nodemon --watch dist/main.js --watch dist/main-server.js --delay 500ms --exec 'node dist/main.js server --host $(or $(BACKEND_HOST),localhost) --port $(or $(BACKEND_PORT),3000)'" \ + "CMUX_VITE_HOST=$(or $(VITE_HOST),127.0.0.1) CMUX_VITE_PORT=$(or $(VITE_PORT),5173) VITE_BACKEND_URL=http://$(or $(BACKEND_HOST),localhost):$(or $(BACKEND_PORT),3000) vite" +endif @@ -134,7 +157,7 @@ build-main: node_modules/.installed dist/main.js ## Build main process dist/main.js: src/version.ts tsconfig.main.json tsconfig.json $(TS_SOURCES) @echo "Building main process..." @NODE_ENV=production $(TSGO) -p tsconfig.main.json - @NODE_ENV=production bun x tsc-alias -p tsconfig.main.json + @NODE_ENV=production $(RUNNER) tsc-alias -p tsconfig.main.json build-preload: node_modules/.installed dist/preload.js ## Build preload script @@ -200,10 +223,18 @@ lint: node_modules/.installed ## Run ESLint (typecheck runs in separate target) lint-fix: node_modules/.installed ## Run linter with --fix @./scripts/lint.sh --fix +ifeq ($(OS),Windows_NT) typecheck: node_modules/.installed src/version.ts ## Run TypeScript type checking (uses tsgo for 10x speedup) - @npx concurrently -g \ + @# On Windows, use npm run because bun x doesn't correctly pass arguments + @npmx concurrently -g \ "$(TSGO) --noEmit" \ "$(TSGO) --noEmit -p tsconfig.main.json" +else +typecheck: node_modules/.installed src/version.ts + @bun x concurrently -g \ + "$(TSGO) --noEmit" \ + "$(TSGO) --noEmit -p tsconfig.main.json" +endif check-deadcode: node_modules/.installed ## Check for potential dead code (manual only, not in static-check) @echo "Checking for potential dead code with ts-prune..." diff --git a/src/runtime/LocalRuntime.ts b/src/runtime/LocalRuntime.ts index 5cd026291..a14110e0a 100644 --- a/src/runtime/LocalRuntime.ts +++ b/src/runtime/LocalRuntime.ts @@ -18,7 +18,7 @@ import type { } from "./Runtime"; import { RuntimeError as RuntimeErrorClass } from "./Runtime"; import { NON_INTERACTIVE_ENV_VARS } from "../constants/env"; -import { getBashPath } from "../utils/bashPath"; +import { getBashPath } from "../utils/main/bashPath"; import { EXIT_CODE_ABORTED, EXIT_CODE_TIMEOUT } from "../constants/exitCodes"; import { listLocalBranches } from "../git"; import { checkInitHookExists, getInitHookPath, createLineBufferedLoggers } from "./initHook"; diff --git a/src/runtime/SSHRuntime.ts b/src/runtime/SSHRuntime.ts index 4343d206d..ae997fad4 100644 --- a/src/runtime/SSHRuntime.ts +++ b/src/runtime/SSHRuntime.ts @@ -24,7 +24,7 @@ import { getProjectName } from "../utils/runtime/helpers"; import { getErrorMessage } from "../utils/errors"; import { execAsync, DisposableProcess } from "../utils/disposableExec"; import { getControlPath } from "./sshConnectionPool"; -import { getBashPath } from "../utils/bashPath"; +import { getBashPath } from "../utils/main/bashPath"; /** * Shell-escape helper for remote bash. diff --git a/src/services/bashExecutionService.ts b/src/services/bashExecutionService.ts index 175376b43..a03ea130d 100644 --- a/src/services/bashExecutionService.ts +++ b/src/services/bashExecutionService.ts @@ -1,7 +1,7 @@ import { spawn } from "child_process"; import type { ChildProcess } from "child_process"; import { log } from "./log"; -import { getBashPath } from "../utils/bashPath"; +import { getBashPath } from "../utils/main/bashPath"; /** * Configuration for bash execution diff --git a/src/utils/bashPath.ts b/src/utils/main/bashPath.ts similarity index 96% rename from src/utils/bashPath.ts rename to src/utils/main/bashPath.ts index e0f44e7f5..052de9e9b 100644 --- a/src/utils/bashPath.ts +++ b/src/utils/main/bashPath.ts @@ -22,9 +22,9 @@ function findWindowsBash(): string | null { "C:\\Program Files\\Git\\bin\\bash.exe", "C:\\Program Files (x86)\\Git\\bin\\bash.exe", // User-local Git installation - path.join(process.env.LOCALAPPDATA || "", "Programs", "Git", "bin", "bash.exe"), + path.join(process.env.LOCALAPPDATA ?? "", "Programs", "Git", "bin", "bash.exe"), // Portable Git - path.join(process.env.USERPROFILE || "", "scoop", "apps", "git", "current", "bin", "bash.exe"), + path.join(process.env.USERPROFILE ?? "", "scoop", "apps", "git", "current", "bin", "bash.exe"), // Chocolatey installation "C:\\tools\\git\\bin\\bash.exe", ];