From 3fd45ec25321cf0f45bb992bc7f314a053d84ecd Mon Sep 17 00:00:00 2001 From: Will Chen Date: Tue, 16 Dec 2025 11:18:09 -0800 Subject: [PATCH] Do not hardcode 32100 port (#1969) Fixes #1949 --- > [!NOTE] > [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) is generating a summary for commit 46ac310c762fd4044c35bc59264122234ed19bbf. Configure [here](https://cursor.com/dashboard?tab=bugbot). --- ## Summary by cubic Make app ports dynamic instead of hardcoded 32100 to prevent conflicts and keep local runs, Docker, and env URLs in sync. Ports now derive from appId using a base of 32100. - **Bug Fixes** - Added getAppPort(appId) = 32100 + (appId % 10_000). - Used the dynamic port in NEXT_PUBLIC_SERVER_URL, start commands, Docker -p mapping, and cleanUpPort. - Updated getCommand to accept appId and generate a per-app default start command. Written for commit 46ac310c762fd4044c35bc59264122234ed19bbf. Summary will update automatically on new commits. --- shared/ports.ts | 7 +++++++ src/client_logic/template_hook.ts | 3 ++- src/ipc/handlers/app_handlers.ts | 27 +++++++++++++++++---------- 3 files changed, 26 insertions(+), 11 deletions(-) create mode 100644 shared/ports.ts diff --git a/shared/ports.ts b/shared/ports.ts new file mode 100644 index 0000000..b34c7ee --- /dev/null +++ b/shared/ports.ts @@ -0,0 +1,7 @@ +/** + * Calculate the port for a given app based on its ID. + * Uses a base port of 32100 and offsets by appId % 10_000. + */ +export function getAppPort(appId: number): number { + return 32100 + (appId % 10_000); +} diff --git a/src/client_logic/template_hook.ts b/src/client_logic/template_hook.ts index 70fa28c..c65a2fc 100644 --- a/src/client_logic/template_hook.ts +++ b/src/client_logic/template_hook.ts @@ -1,4 +1,5 @@ import { IpcClient } from "@/ipc/ipc_client"; +import { getAppPort } from "../../shared/ports"; import { v4 as uuidv4 } from "uuid"; @@ -29,7 +30,7 @@ export async function neonTemplateHook({ }, { key: "NEXT_PUBLIC_SERVER_URL", - value: "http://localhost:32100", + value: `http://localhost:${getAppPort(appId)}`, }, { key: "GMAIL_USER", diff --git a/src/ipc/handlers/app_handlers.ts b/src/ipc/handlers/app_handlers.ts index afc9304..760fa24 100644 --- a/src/ipc/handlers/app_handlers.ts +++ b/src/ipc/handlers/app_handlers.ts @@ -62,8 +62,12 @@ import { getVercelTeamSlug } from "../utils/vercel_utils"; import { storeDbTimestampAtCurrentVersion } from "../utils/neon_timestamp_utils"; import { AppSearchResult } from "@/lib/schemas"; -const DEFAULT_COMMAND = - "(pnpm install && pnpm run dev --port 32100) || (npm install --legacy-peer-deps && npm run dev -- --port 32100)"; +import { getAppPort } from "../../../shared/ports"; + +function getDefaultCommand(appId: number): string { + const port = getAppPort(appId); + return `(pnpm install && pnpm run dev --port ${port}) || (npm install --legacy-peer-deps && npm run dev -- --port ${port})`; +} async function copyDir( source: string, destination: string, @@ -150,7 +154,7 @@ async function executeAppLocalNode({ installCommand?: string | null; startCommand?: string | null; }): Promise { - const command = getCommand({ installCommand, startCommand }); + const command = getCommand({ appId, installCommand, startCommand }); const spawnedProcess = spawn(command, [], { cwd: appPath, shell: true, @@ -418,6 +422,7 @@ RUN npm install -g pnpm }); // Run the Docker container + const port = getAppPort(appId); const process = spawn( "docker", [ @@ -426,7 +431,7 @@ RUN npm install -g pnpm "--name", containerName, "-p", - "32100:32100", + `${port}:${port}`, "-v", `${appPath}:/app`, "-v", @@ -438,7 +443,7 @@ RUN npm install -g pnpm `dyad-app-${appId}`, "sh", "-c", - getCommand({ installCommand, startCommand }), + getCommand({ appId, installCommand, startCommand }), ], { stdio: "pipe", @@ -817,8 +822,8 @@ export function registerAppHandlers() { const appPath = getDyadAppPath(app.path); try { - // There may have been a previous run that left a process on port 32100. - await cleanUpPort(32100); + // There may have been a previous run that left a process on this port. + await cleanUpPort(getAppPort(appId)); await executeApp({ appPath, appId, @@ -918,8 +923,8 @@ export function registerAppHandlers() { logger.log(`App ${appId} not running. Proceeding to start.`); } - // There may have been a previous run that left a process on port 32100. - await cleanUpPort(32100); + // There may have been a previous run that left a process on this port. + await cleanUpPort(getAppPort(appId)); // Now start the app again const app = await db.query.apps.findFirst({ @@ -1573,16 +1578,18 @@ export function registerAppHandlers() { } function getCommand({ + appId, installCommand, startCommand, }: { + appId: number; installCommand?: string | null; startCommand?: string | null; }) { const hasCustomCommands = !!installCommand?.trim() && !!startCommand?.trim(); return hasCustomCommands ? `${installCommand!.trim()} && ${startCommand!.trim()}` - : DEFAULT_COMMAND; + : getDefaultCommand(appId); } async function cleanUpPort(port: number) {