From 2d0985599afa7c8a16286b6cbb0f78720c2d2165 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Flor=C3=AAncio?= Date: Tue, 3 Feb 2026 09:50:43 +0000 Subject: [PATCH] feat: improve make start --- Makefile | 10 +++++++++- apps/cli/src/cli.ts | 10 ++++++++-- apps/cli/src/start.ts | 40 +++++++++++++++++++++++++++++++--------- 3 files changed, 48 insertions(+), 12 deletions(-) diff --git a/Makefile b/Makefile index 45f0963199..7087dd9b9a 100644 --- a/Makefile +++ b/Makefile @@ -20,6 +20,8 @@ CYAN := \033[36m YELLOW := \033[33m MAGENTA := \033[35m +VERBOSE ?= 0 + # Phase headers define phase @printf "\n$(BOLD)$(BLUE)━━━ $(1) ━━━$(RESET)\n\n" @@ -49,6 +51,8 @@ help: @echo "" @echo "Production Commands:" @echo " start Install deps, build, and start backend + web in production mode" + @echo " start-verbose Start in production mode with info logs from backend + web" + @echo " start VERBOSE=1 Same as start-verbose" @echo "" @echo "Build Commands:" @echo " build Build backend and web app" @@ -123,7 +127,11 @@ start: @$(MAKE) -s build-web-quiet $(call success,Build complete) $(call phase,Starting Server) - @cd $(APPS_DIR) && $(PNPM) -C cli dev -- start + @cd $(APPS_DIR) && $(PNPM) -C cli dev -- start $(if $(filter 1 true yes,$(VERBOSE)),--verbose,) + +.PHONY: start-verbose +start-verbose: + @$(MAKE) start VERBOSE=1 .PHONY: build-backend build-backend: diff --git a/apps/cli/src/cli.ts b/apps/cli/src/cli.ts index 334b90d409..f1b28a812d 100644 --- a/apps/cli/src/cli.ts +++ b/apps/cli/src/cli.ts @@ -15,6 +15,7 @@ type CliOptions = { version?: string; backendPort?: number; webPort?: number; + verbose?: boolean; }; function printHelp() { @@ -23,7 +24,7 @@ function printHelp() { Usage: kandev run [--version ] [--backend-port ] [--web-port ] kandev dev [--backend-port ] [--web-port ] - kandev start [--backend-port ] [--web-port ] + kandev start [--backend-port ] [--web-port ] [--verbose] kandev [--version ] [--backend-port ] [--web-port ] kandev --dev [--backend-port ] [--web-port ] @@ -44,6 +45,7 @@ Options: --version Release tag to install (default: latest). --backend-port Override backend port. --web-port Override web port. + --verbose, -v Show info logs from backend + web (start mode only). --help, -h Show help. `); } @@ -91,6 +93,10 @@ function parseArgs(argv: string[]): CliOptions { opts.webPort = Number(arg.split("=")[1]); continue; } + if (arg === "--verbose" || arg === "-v") { + opts.verbose = true; + continue; + } } return opts; } @@ -137,7 +143,7 @@ async function main(): Promise { if (!repoRoot) { throw new Error("Unable to locate repo root for start. Run from the repo."); } - await runStart({ repoRoot, backendPort, webPort }); + await runStart({ repoRoot, backendPort, webPort, verbose: raw.verbose }); return; } diff --git a/apps/cli/src/start.ts b/apps/cli/src/start.ts index 17aa978752..eca48c3d7e 100644 --- a/apps/cli/src/start.ts +++ b/apps/cli/src/start.ts @@ -34,6 +34,8 @@ export type StartOptions = { backendPort?: number; /** Optional preferred web port (finds available port if not specified) */ webPort?: number; + /** Show info logs from backend + web */ + verbose?: boolean; }; /** @@ -49,7 +51,12 @@ export type StartOptions = { * @param options - Configuration for the start command * @throws Error if backend binary or web build is not found */ -export async function runStart({ repoRoot, backendPort, webPort }: StartOptions): Promise { +export async function runStart({ + repoRoot, + backendPort, + webPort, + verbose = false, +}: StartOptions): Promise { const ports = await pickPorts(backendPort, webPort); const backendBin = path.join(repoRoot, "apps", "backend", "bin", getBinaryName("kandev")); @@ -62,24 +69,39 @@ export async function runStart({ repoRoot, backendPort, webPort }: StartOptions) if (!fs.existsSync(webServerPath)) { throw new Error("Web standalone build not found. Run `make build` first."); } + const webStandaloneDir = path.dirname(webServerPath); + const webStaticDir = path.join(repoRoot, "apps", "web", ".next", "static"); + const standaloneStaticDir = path.join(webStandaloneDir, ".next", "static"); + if (fs.existsSync(webStaticDir) && !fs.existsSync(standaloneStaticDir)) { + fs.mkdirSync(path.dirname(standaloneStaticDir), { recursive: true }); + try { + fs.symlinkSync(webStaticDir, standaloneStaticDir, "junction"); + } catch (err) { + console.warn( + `[kandev] failed to link Next.js static assets: ${err instanceof Error ? err.message : String(err)}`, + ); + } + } - // Production mode: use warn log level for clean output - const backendEnv = buildBackendEnv({ ports, logLevel: "warn" }); + // Production mode: use warn log level for clean output unless verbose + const backendEnv = buildBackendEnv({ ports, logLevel: verbose ? "info" : "warn" }); const webEnv = buildWebEnv({ ports, includeMcp: true, production: true }); const supervisor = createProcessSupervisor(); supervisor.attachSignalHandlers(); - // Start backend with piped stdio (quiet mode) + // Start backend with piped stdio (quiet mode unless verbose) const backendProc = spawn(backendBin, [], { cwd: path.dirname(backendBin), env: backendEnv, - stdio: ["ignore", "pipe", "pipe"], + stdio: verbose ? ["ignore", "inherit", "inherit"] : ["ignore", "pipe", "pipe"], }); supervisor.children.push(backendProc); - // Forward stderr only (warnings/errors) - backendProc.stderr?.pipe(process.stderr); + // Forward stderr only (warnings/errors) when quiet + if (!verbose) { + backendProc.stderr?.pipe(process.stderr); + } attachBackendExitHandler(backendProc, supervisor); @@ -88,12 +110,12 @@ export async function runStart({ repoRoot, backendPort, webPort }: StartOptions) launchWebApp({ command: "node", args: [webServerPath], - cwd: path.dirname(webServerPath), + cwd: webStandaloneDir, env: webEnv, url: webUrl, supervisor, label: "web", - quiet: true, + quiet: !verbose, }); const healthTimeoutMs = resolveHealthTimeoutMs(HEALTH_TIMEOUT_MS_RELEASE);