From 4d016647871477d9ee75c714c557a1ed85163b94 Mon Sep 17 00:00:00 2001 From: oonyeje Date: Tue, 7 Jul 2026 11:51:54 +0000 Subject: [PATCH] Make PROJECT_CREDENTIALS and ROUTE_MAP parsing robust against wrapping quotes from hosting platforms; add clearer debug output --- src/server.ts | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/src/server.ts b/src/server.ts index bf05f1a..802bf44 100644 --- a/src/server.ts +++ b/src/server.ts @@ -38,6 +38,32 @@ interface RouteEntry { type RouteMap = Record; +// ----- Helpers -------------------------------------------------------------- + +/** + * Normalize a raw env-var value. Some hosting platforms (Coolify included) + * wrap pasted JSON values in extra quotes when the user doesn't quote-escape + * properly, producing strings like: + * "{\"square\":{...}}" + * which JSON.parse cannot read at position 1. + * + * This helper: + * 1. Trims whitespace + * 2. Strips a single surrounding layer of `"` or `'` + * 3. Unescapes `\"` -> `"`, `\'` -> `'`, and `\\` -> `\` + */ +function normalizeEnvValue(raw: string): string { + let value = raw.trim(); + if ( + (value.startsWith('"') && value.endsWith('"')) || + (value.startsWith("'") && value.endsWith("'")) + ) { + value = value.slice(1, -1); + value = value.replace(/\\"/g, '"').replace(/\\'/g, "'").replace(/\\\\/g, '\\'); + } + return value.trim(); +} + // ----- Config --------------------------------------------------------------- const PORT = parseInt(process.env.PORT ?? '3012', 10); @@ -45,17 +71,25 @@ const APPWRITE_BASE_URL = (process.env.APPWRITE_BASE_URL ?? 'https://appwrite.bs let PROJECT_CREDENTIALS: CredentialsMap = {}; try { - PROJECT_CREDENTIALS = JSON.parse(process.env.PROJECT_CREDENTIALS ?? '{}') as CredentialsMap; + const normalized = normalizeEnvValue(process.env.PROJECT_CREDENTIALS ?? ''); + if (!normalized) { + throw new Error('PROJECT_CREDENTIALS is empty'); + } + PROJECT_CREDENTIALS = JSON.parse(normalized) as CredentialsMap; } catch (err) { const message = err instanceof Error ? err.message : String(err); + const raw = (process.env.PROJECT_CREDENTIALS ?? '').slice(0, 300); console.error('[startup] PROJECT_CREDENTIALS is not valid JSON:', message); + console.error('[startup] Received value (first 300 chars):', raw); + console.error('[startup] Hint: in Coolify, paste the JSON without surrounding quotes. If the platform wraps it, set the env var to a single-line value with no leading/trailing whitespace.'); process.exit(1); } // Parse ROUTE_MAP. Format: "/path=>{json};/path2=>{json2}" const ROUTE_MAP: RouteMap = {}; if (process.env.ROUTE_MAP) { - for (const entry of process.env.ROUTE_MAP.split(';')) { + const normalizedRouteMap = normalizeEnvValue(process.env.ROUTE_MAP); + for (const entry of normalizedRouteMap.split(';')) { const trimmed = entry.trim(); if (!trimmed) continue; const arrowIdx = trimmed.indexOf('=>');