From d20a2639b682bee1d47e4971db54161a1f1de28c Mon Sep 17 00:00:00 2001 From: shumengya Date: Wed, 27 May 2026 22:22:19 +0800 Subject: [PATCH] fix: load .env before imports and improve dev startup Co-authored-by: Cursor --- package-lock.json | 261 +++++++++++++++++++++++++++++++++++++- package.json | 6 +- server/index.ts | 31 ++++- server/load-env.ts | 13 ++ server/package.json | 4 + server/services/github.ts | 18 ++- web/src/api.ts | 44 +++++-- web/vite.config.js | 2 +- web/vite.config.ts | 2 +- 9 files changed, 359 insertions(+), 22 deletions(-) create mode 100644 server/load-env.ts diff --git a/package-lock.json b/package-lock.json index 7f4ad4e..87ea6ba 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,7 +15,8 @@ "devDependencies": { "adm-zip": "^0.5.17", "concurrently": "^9.1.2", - "typescript": "~5.6.2" + "typescript": "~5.6.2", + "wait-on": "^8.0.5" } }, "node_modules/@babel/code-frame": { @@ -742,6 +743,60 @@ "node": ">=18" } }, + "node_modules/@hapi/address": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@hapi/address/-/address-5.1.1.tgz", + "integrity": "sha512-A+po2d/dVoY7cYajycYI43ZbYMXukuopIsqCjh5QzsBCipDtdofHntljDlpccMjIfTy6UOkg+5KPriwYch2bXA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@hapi/hoek": "^11.0.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@hapi/formula": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@hapi/formula/-/formula-3.0.2.tgz", + "integrity": "sha512-hY5YPNXzw1He7s0iqkRQi+uMGh383CGdyyIGYtB+W5N3KHPXoqychklvHhKCC9M3Xtv0OCs/IHw+r4dcHtBYWw==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@hapi/hoek": { + "version": "11.0.7", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-11.0.7.tgz", + "integrity": "sha512-HV5undWkKzcB4RZUusqOpcgxOaq6VOAH7zhhIr2g3G8NF/MlFO75SjOr2NfuSx0Mh40+1FqCkagKLJRykUWoFQ==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@hapi/pinpoint": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@hapi/pinpoint/-/pinpoint-2.0.1.tgz", + "integrity": "sha512-EKQmr16tM8s16vTT3cA5L0kZZcTMU5DUOZTuvpnY738m+jyP3JIUj+Mm1xc1rsLkGBQ/gVnfKYPwOmPg1tUR4Q==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@hapi/tlds": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@hapi/tlds/-/tlds-1.1.6.tgz", + "integrity": "sha512-xdi7A/4NZokvV0ewovme3aUO5kQhW9pQ2YD1hRqZGhhSi5rBv4usHYidVocXSi9eihYsznZxLtAiEYYUL6VBGw==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@hapi/topo": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-6.0.2.tgz", + "integrity": "sha512-KR3rD5inZbGMrHmgPxsJ9dbi6zEK+C3ZwUwTa+eMwWLz7oijWUTWD2pMSNNYJAU6Qq+65NkxXjqHr/7LM2Xkqg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@hapi/hoek": "^11.0.2" + } + }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.13", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", @@ -1529,6 +1584,13 @@ "win32" ] }, + "node_modules/@standard-schema/spec": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", + "dev": true, + "license": "MIT" + }, "node_modules/@tauri-apps/cli": { "version": "2.11.2", "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-2.11.2.tgz", @@ -2020,6 +2082,19 @@ "node": ">=12.0" } }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -2058,6 +2133,26 @@ "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", "license": "MIT" }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/axios": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.16.1.tgz", + "integrity": "sha512-caYkukvroVPO8KrzuJEb50Hm07KwfBZPEC3VeFHTsqWHvKTsy54hjJz9BS/cdaypROE2rH6xvm9mHX4fgWkr3A==", + "dev": true, + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.16.0", + "form-data": "^4.0.5", + "https-proxy-agent": "^5.0.1", + "proxy-from-env": "^2.1.0" + } + }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -2392,6 +2487,19 @@ "dev": true, "license": "MIT" }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/concat-stream": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", @@ -2547,6 +2655,16 @@ "node": ">=4.0.0" } }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -2669,6 +2787,22 @@ "node": ">= 0.4" } }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/esbuild": { "version": "0.28.0", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.0.tgz", @@ -2879,6 +3013,44 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "license": "MIT" }, + "node_modules/follow-redirects": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", + "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "dev": true, + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -3024,6 +3196,22 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/hasown": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.3.tgz", @@ -3056,6 +3244,20 @@ "url": "https://opencollective.com/express" } }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -3125,6 +3327,25 @@ "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", "license": "MIT" }, + "node_modules/joi": { + "version": "18.2.1", + "resolved": "https://registry.npmjs.org/joi/-/joi-18.2.1.tgz", + "integrity": "sha512-2/OKlogiESf2Nh3TFCrRjrr9z1DRHeW0I+KReF67+4J0Ns+8hBtHRmoWAZ2OFU6I5+TWLEe6sVlSdXPjHm5UbQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@hapi/address": "^5.1.1", + "@hapi/formula": "^3.0.2", + "@hapi/hoek": "^11.0.7", + "@hapi/pinpoint": "^2.0.1", + "@hapi/tlds": "^1.1.1", + "@hapi/topo": "^6.0.2", + "@standard-schema/spec": "^1.1.0" + }, + "engines": { + "node": ">= 20" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -3158,6 +3379,13 @@ "node": ">=6" } }, + "node_modules/lodash": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", + "dev": true, + "license": "MIT" + }, "node_modules/lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -3561,6 +3789,16 @@ "node": ">= 0.10" } }, + "node_modules/proxy-from-env": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz", + "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, "node_modules/pump": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz", @@ -4926,6 +5164,26 @@ "@esbuild/win32-x64": "0.25.12" } }, + "node_modules/wait-on": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-8.0.5.tgz", + "integrity": "sha512-J3WlS0txVHkhLRb2FsmRg3dkMTCV1+M6Xra3Ho7HzZDHpE7DCOnoSoCJsZotrmW3uRMhvIJGSKUKrh/MeF4iag==", + "dev": true, + "license": "MIT", + "dependencies": { + "axios": "^1.12.1", + "joi": "^18.0.1", + "lodash": "^4.17.21", + "minimist": "^1.2.8", + "rxjs": "^7.8.2" + }, + "bin": { + "wait-on": "bin/wait-on" + }, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/web2app-server": { "resolved": "server", "link": true @@ -5020,6 +5278,7 @@ "server": { "name": "web2app-server", "version": "0.1.0", + "hasInstallScript": true, "dependencies": { "adm-zip": "^0.5.16", "better-sqlite3": "^11.8.1", diff --git a/package.json b/package.json index 8e2bda1..f8fe789 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,8 @@ "template" ], "scripts": { - "dev": "concurrently \"npm run dev:server\" \"npm run dev:web\"", + "dev": "concurrently -n server,web -c blue,green \"npm run dev:server\" \"npm run dev:web:wait\"", + "dev:web:wait": "wait-on http://127.0.0.1:3001/api/health -t 120000 && npm run dev -w web", "dev:web": "npm run dev -w web", "dev:server": "npm run dev -w server", "build": "npm run build -w web && npm run build -w server", @@ -18,6 +19,7 @@ "devDependencies": { "adm-zip": "^0.5.17", "concurrently": "^9.1.2", - "typescript": "~5.6.2" + "typescript": "~5.6.2", + "wait-on": "^8.0.5" } } diff --git a/server/index.ts b/server/index.ts index 3732cf6..d650c7e 100644 --- a/server/index.ts +++ b/server/index.ts @@ -1,12 +1,11 @@ +import "./load-env.js"; import cors from "cors"; -import dotenv from "dotenv"; import express from "express"; import path from "node:path"; import { fileURLToPath } from "node:url"; +import { MulterError } from "multer"; import { buildsRouter } from "./routes/builds.js"; -dotenv.config({ path: path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../.env") }); - const app = express(); const port = Number(process.env.PORT ?? "3001"); @@ -19,6 +18,28 @@ app.get("/api/health", (_req, res) => { app.use("/api/builds", buildsRouter); +app.use((err: unknown, _req: express.Request, res: express.Response, next: express.NextFunction) => { + if (res.headersSent) { + next(err); + return; + } + + if (err instanceof MulterError) { + const status = err.code === "LIMIT_FILE_SIZE" ? 413 : 400; + res.status(status).json({ error: err.message }); + return; + } + + if (err instanceof Error) { + console.error(err); + res.status(500).json({ error: err.message }); + return; + } + + console.error(err); + res.status(500).json({ error: "Internal server error" }); +}); + const webDist = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../web/dist"); app.use(express.static(webDist)); app.get("*", (_req, res, next) => { @@ -31,6 +52,6 @@ app.get("*", (_req, res, next) => { }); }); -app.listen(port, () => { - console.log(`Web2App server listening on http://localhost:${port}`); +app.listen(port, "127.0.0.1", () => { + console.log(`Web2App server listening on http://127.0.0.1:${port}`); }); diff --git a/server/load-env.ts b/server/load-env.ts new file mode 100644 index 0000000..62b8518 --- /dev/null +++ b/server/load-env.ts @@ -0,0 +1,13 @@ +import dotenv from "dotenv"; +import fs from "node:fs"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; + +const serverDir = path.dirname(fileURLToPath(import.meta.url)); +const rootEnv = path.resolve(serverDir, "../.env"); + +if (fs.existsSync(rootEnv)) { + dotenv.config({ path: rootEnv }); +} else { + dotenv.config(); +} diff --git a/server/package.json b/server/package.json index 4f66214..619ca8d 100644 --- a/server/package.json +++ b/server/package.json @@ -4,8 +4,12 @@ "version": "0.1.0", "type": "module", "scripts": { + "postinstall": "node -e \"try{require('better-sqlite3')}catch{process.exit(1)}\" || npm rebuild better-sqlite3", + "predev": "npm rebuild better-sqlite3", "dev": "tsx watch index.ts", + "prebuild": "npm rebuild better-sqlite3", "build": "tsc", + "prestart": "npm rebuild better-sqlite3", "start": "node dist/index.js" }, "dependencies": { diff --git a/server/services/github.ts b/server/services/github.ts index 26d7612..379263d 100644 --- a/server/services/github.ts +++ b/server/services/github.ts @@ -1,10 +1,16 @@ +import "../load-env.js"; import { Octokit } from "octokit"; -const owner = process.env.GITHUB_OWNER ?? ""; -const repo = process.env.GITHUB_REPO ?? ""; -const token = process.env.GITHUB_TOKEN ?? ""; +function getGitHubConfig() { + return { + owner: (process.env.GITHUB_OWNER ?? "").trim(), + repo: (process.env.GITHUB_REPO ?? "").trim(), + token: (process.env.GITHUB_TOKEN ?? "").trim(), + }; +} function getOctokit(): Octokit { + const { owner, repo, token } = getGitHubConfig(); if (!owner || !repo || !token) { throw new Error( "Missing GITHUB_OWNER, GITHUB_REPO, or GITHUB_TOKEN environment variables", @@ -14,10 +20,12 @@ function getOctokit(): Octokit { } export function getRepoInfo() { + const { owner, repo } = getGitHubConfig(); return { owner, repo }; } export async function uploadSiteZip(jobId: string, zipBuffer: Buffer): Promise { + const { owner, repo } = getGitHubConfig(); const octokit = getOctokit(); const path = `builds/${jobId}/site.zip`; const content = zipBuffer.toString("base64"); @@ -55,6 +63,7 @@ export async function triggerBuildWorkflow(input: { appName: string; appIdentifier: string; }): Promise { + const { owner, repo } = getGitHubConfig(); const octokit = getOctokit(); await octokit.rest.actions.createWorkflowDispatch({ @@ -95,6 +104,7 @@ export async function triggerBuildWorkflow(input: { } export async function getWorkflowRun(runId: number) { + const { owner, repo } = getGitHubConfig(); const octokit = getOctokit(); const { data } = await octokit.rest.actions.getWorkflowRun({ owner, @@ -108,6 +118,7 @@ export async function getReleaseAssets(jobId: string): Promise<{ windowsUrl: string | null; androidUrl: string | null; }> { + const { owner, repo } = getGitHubConfig(); const octokit = getOctokit(); const tag = `build-${jobId}`; @@ -146,6 +157,7 @@ export async function getReleaseAssets(jobId: string): Promise<{ } export function getActionsRunUrl(runId: number | null): string | null { + const { owner, repo } = getGitHubConfig(); if (!runId || !owner || !repo) return null; return `https://github.com/${owner}/${repo}/actions/runs/${runId}`; } diff --git a/web/src/api.ts b/web/src/api.ts index aad7fd6..be3c160 100644 --- a/web/src/api.ts +++ b/web/src/api.ts @@ -19,28 +19,54 @@ export interface Build { actionsUrl?: string | null; } -export async function createBuild(formData: FormData): Promise<{ id: string }> { - const response = await fetch("/api/builds", { - method: "POST", - body: formData, - }); +interface ApiErrorResponse { + error?: string; +} - const data = await response.json(); +interface CreateBuildResponse { + id: string; + error?: string; +} + +export async function createBuild(formData: FormData): Promise<{ id: string }> { + let response: Response; + try { + response = await fetch("/api/builds", { + method: "POST", + body: formData, + }); + } catch { + throw new Error("无法连接后端服务,请确认已运行 npm run dev 且 server 已启动"); + } + + const data = (await readJson(response)) as CreateBuildResponse; if (!response.ok) { - throw new Error(data.error ?? "Upload failed"); + throw new Error(data.error ?? "上传失败"); } return data; } export async function fetchBuild(id: string): Promise { const response = await fetch(`/api/builds/${id}`); - const data = await response.json(); + const data = (await readJson(response)) as Build; if (!response.ok) { - throw new Error(data.error ?? "Failed to load build"); + const errorData = data as Build & ApiErrorResponse; + throw new Error(errorData.error ?? "Failed to load build"); } return data; } +async function readJson(response: Response): Promise { + const text = await response.text(); + if (!text) return {}; + + try { + return JSON.parse(text) as unknown; + } catch { + throw new Error(`Unexpected response from server: ${text.slice(0, 200)}`); + } +} + export function statusLabel(status: BuildStatus): string { switch (status) { case "pending": diff --git a/web/vite.config.js b/web/vite.config.js index 4f2f46b..ef4f4ae 100644 --- a/web/vite.config.js +++ b/web/vite.config.js @@ -6,7 +6,7 @@ export default defineConfig({ port: 5173, proxy: { "/api": { - target: "http://localhost:3001", + target: "http://127.0.0.1:3001", changeOrigin: true, }, }, diff --git a/web/vite.config.ts b/web/vite.config.ts index 1dd2a10..41952ff 100644 --- a/web/vite.config.ts +++ b/web/vite.config.ts @@ -7,7 +7,7 @@ export default defineConfig({ port: 5173, proxy: { "/api": { - target: "http://localhost:3001", + target: "http://127.0.0.1:3001", changeOrigin: true, }, },