Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 30 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ include fmt.mk
.PHONY: docs-server check-docs-links
.PHONY: storybook storybook-build test-storybook chromatic
.PHONY: benchmark-terminal
.PHONY: ensure-deps rebuild-native
.PHONY: ensure-deps rebuild-native mux
.PHONY: check-eager-imports check-bundle-size check-startup

# Build tools
Expand Down Expand Up @@ -107,6 +107,17 @@ rebuild-native: node_modules/.installed ## Rebuild native modules (node-pty) for
@npx @electron/rebuild -f -m node_modules/node-pty
@echo "Native modules rebuilt successfully"

# Run compiled CLI with trailing arguments (builds only if missing)
mux: ## Run the compiled mux CLI (e.g., make mux server --port 3000)
@test -f dist/cli/index.js -a -f dist/cli/api.mjs || $(MAKE) build-main
@node dist/cli/index.js $(filter-out $@,$(MAKECMDGOALS))

# Catch unknown targets passed to mux (prevents "No rule to make target" errors)
ifneq ($(filter mux,$(MAKECMDGOALS)),)
%:
@:
endif

## Help
help: ## Show this help message
@echo 'Usage: make [target]'
Expand All @@ -117,16 +128,18 @@ help: ## Show this help message
## Development
ifeq ($(OS),Windows_NT)
dev: node_modules/.installed build-main ## Start development server (Vite + nodemon watcher for Windows compatibility)
@echo "Starting dev mode (2 watchers: nodemon for main process, vite for renderer)..."
@echo "Starting dev mode (3 watchers: nodemon for main process, esbuild for api, vite for renderer)..."
# 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 --watch src --watch tsconfig.main.json --watch tsconfig.json --ext ts,tsx,json --ignore dist --ignore node_modules --exec node scripts/build-main-watch.js" \
"npx esbuild src/cli/api.ts --bundle --format=esm --platform=node --outfile=dist/cli/api.mjs --external:zod --external:commander --external:@trpc/server --watch" \
"vite"
else
dev: node_modules/.installed build-main build-preload ## 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\"" \
"bun x esbuild src/cli/api.ts --bundle --format=esm --platform=node --outfile=dist/cli/api.mjs --external:zod --external:commander --external:@trpc/server --watch" \
"vite"
endif

Expand All @@ -140,6 +153,7 @@ dev-server: node_modules/.installed build-main ## Start server mode with hot rel
@# On Windows, use npm run because bunx doesn't correctly pass arguments
@npmx concurrently -k \
"npmx nodemon --watch src --watch tsconfig.main.json --watch tsconfig.json --ext ts,tsx,json --ignore dist --ignore node_modules --exec node scripts/build-main-watch.js" \
"npx esbuild src/cli/api.ts --bundle --format=esm --platform=node --outfile=dist/cli/api.mjs --external:zod --external:commander --external:@trpc/server --watch" \
"npmx nodemon --watch dist/cli/index.js --watch dist/cli/server.js --delay 500ms --exec \"node dist/cli/index.js server --host $(or $(BACKEND_HOST),localhost) --port $(or $(BACKEND_PORT),3000)\"" \
"$(SHELL) -lc \"MUX_VITE_HOST=$(or $(VITE_HOST),127.0.0.1) MUX_VITE_PORT=$(or $(VITE_PORT),5173) VITE_BACKEND_URL=http://$(or $(BACKEND_HOST),localhost):$(or $(BACKEND_PORT),3000) vite\""
else
Expand All @@ -151,6 +165,7 @@ dev-server: node_modules/.installed build-main ## Start server mode with hot rel
@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 esbuild src/cli/api.ts --bundle --format=esm --platform=node --outfile=dist/cli/api.mjs --external:zod --external:commander --external:@trpc/server --watch" \
"bun x nodemon --watch dist/cli/index.js --watch dist/cli/server.js --delay 500ms --exec 'NODE_ENV=development node dist/cli/index.js server --host $(or $(BACKEND_HOST),localhost) --port $(or $(BACKEND_PORT),3000)'" \
"MUX_VITE_HOST=$(or $(VITE_HOST),127.0.0.1) MUX_VITE_PORT=$(or $(VITE_PORT),5173) VITE_BACKEND_URL=http://$(or $(BACKEND_HOST),localhost):$(or $(BACKEND_PORT),3000) vite"
endif
Expand All @@ -163,13 +178,25 @@ start: node_modules/.installed build-main build-preload build-static ## Build an
## Build targets (can run in parallel)
build: node_modules/.installed src/version.ts build-renderer build-main build-preload build-icons build-static ## Build all targets

build-main: node_modules/.installed dist/cli/index.js ## Build main process
build-main: node_modules/.installed dist/cli/index.js dist/cli/api.mjs ## Build main process

dist/cli/index.js: src/cli/index.ts src/desktop/main.ts src/cli/server.ts 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

# Build API CLI as ESM bundle (trpc-cli requires ESM with top-level await)
dist/cli/api.mjs: src/cli/api.ts src/cli/proxifyOrpc.ts $(TS_SOURCES)
@echo "Building API CLI (ESM)..."
@bun x esbuild src/cli/api.ts \
--bundle \
--format=esm \
--platform=node \
--outfile=dist/cli/api.mjs \
--external:zod \
--external:commander \
--external:@trpc/server

build-preload: node_modules/.installed dist/preload.js ## Build preload script

dist/preload.js: src/desktop/preload.ts $(TS_SOURCES)
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@
},
"files": [
"dist/**/*.js",
"dist/**/*.mjs",
"dist/**/*.js.map",
"dist/**/*.wasm",
"dist/**/*.html",
Expand Down
9 changes: 9 additions & 0 deletions scripts/smoke-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,15 @@ fi

log_info "✅ mux binary found"

# Test that mux api subcommand works (requires ESM bundle api.mjs)
log_info "Testing mux api subcommand (ESM bundle)..."
if ! node_modules/.bin/mux api --help >/dev/null 2>&1; then
log_error "mux api --help failed - ESM bundle (api.mjs) may be missing from package"
exit 1
fi

log_info "✅ mux api subcommand works"

# Start the server in background
log_info "Starting mux server on $SERVER_HOST:$SERVER_PORT..."
node_modules/.bin/mux server --host "$SERVER_HOST" --port "$SERVER_PORT" >server.log 2>&1 &
Expand Down
8 changes: 5 additions & 3 deletions src/cli/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,11 @@ if (subcommand === "run") {
require("./server");
} else if (subcommand === "api") {
process.argv.splice(2, 1);
// Dynamic import required: trpc-cli is ESM-only and can't be require()'d
// eslint-disable-next-line no-restricted-syntax
void import("./api");
// Must use native import() to load ESM module - trpc-cli requires ESM with top-level await.
// Using Function constructor prevents TypeScript from converting this to require().
// The .mjs extension is critical for Node.js to treat it as ESM.
// eslint-disable-next-line @typescript-eslint/no-implied-eval, @typescript-eslint/no-unsafe-call
void new Function("return import('./api.mjs')")();
} else if (
subcommand === "desktop" ||
(isElectron && (subcommand === undefined || isElectronLaunchArg))
Expand Down