Apply the same env-value normalization to per-route JSON fragments in ROUTE_MAP
This commit is contained in:
parent
bc09e3a0cf
commit
5a43802a8e
@ -40,6 +40,26 @@ type RouteMap = Record<string, RouteEntry>;
|
||||
|
||||
// ----- Helpers --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Try to parse a string as JSON. If parsing fails, run the string through
|
||||
* normalizeEnvValue (in case the host shell escaped/quoted it) and retry.
|
||||
* Returns the parsed JSON value, or null if both attempts fail.
|
||||
*/
|
||||
function safeJsonParse<T>(raw: string): T | null {
|
||||
const trimmed = raw.trim();
|
||||
try {
|
||||
return JSON.parse(trimmed) as T;
|
||||
} catch {
|
||||
// fall through
|
||||
}
|
||||
const normalized = normalizeEnvValue(trimmed);
|
||||
try {
|
||||
return JSON.parse(normalized) as T;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize a raw env-var value. Different hosting platforms apply different
|
||||
* (and surprising) transformations when you paste a JSON value into an
|
||||
@ -61,11 +81,8 @@ function normalizeEnvValue(raw: string): string {
|
||||
|
||||
const candidates: string[] = [
|
||||
value,
|
||||
// Strip a single surrounding layer of `"` or `'`
|
||||
stripWrappingQuotes(value),
|
||||
// Unescape every \" -> " (handles Coolify double-escape)
|
||||
value.replace(/\\"/g, '"').replace(/\\'/g, "'").replace(/\\\\/g, '\\'),
|
||||
// Combined: strip wrapping quotes AND unescape inner escapes
|
||||
stripWrappingQuotes(value).replace(/\\"/g, '"').replace(/\\'/g, "'").replace(/\\\\/g, '\\'),
|
||||
];
|
||||
|
||||
@ -103,11 +120,11 @@ const APPWRITE_BASE_URL = (process.env.APPWRITE_BASE_URL ?? 'https://appwrite.bs
|
||||
|
||||
let PROJECT_CREDENTIALS: CredentialsMap = {};
|
||||
try {
|
||||
const normalized = normalizeEnvValue(process.env.PROJECT_CREDENTIALS ?? '');
|
||||
if (!normalized) {
|
||||
throw new Error('PROJECT_CREDENTIALS is empty');
|
||||
const parsed = safeJsonParse<CredentialsMap>(process.env.PROJECT_CREDENTIALS ?? '');
|
||||
if (!parsed) {
|
||||
throw new Error('PROJECT_CREDENTIALS is empty or unparseable');
|
||||
}
|
||||
PROJECT_CREDENTIALS = JSON.parse(normalized) as CredentialsMap;
|
||||
PROJECT_CREDENTIALS = parsed;
|
||||
} catch (err) {
|
||||
const message = err instanceof Error ? err.message : String(err);
|
||||
const raw = (process.env.PROJECT_CREDENTIALS ?? '').slice(0, 300);
|
||||
@ -118,6 +135,9 @@ try {
|
||||
}
|
||||
|
||||
// Parse ROUTE_MAP. Format: "/path=>{json};/path2=>{json2}"
|
||||
// The inner {json} fragment can have the same escaping problems as top-level
|
||||
// env vars, so we normalize the full route map as a raw string first, then
|
||||
// also try safeJsonParse on each per-route fragment as a defensive fallback.
|
||||
const ROUTE_MAP: RouteMap = {};
|
||||
if (process.env.ROUTE_MAP) {
|
||||
const normalizedRouteMap = normalizeEnvValue(process.env.ROUTE_MAP);
|
||||
@ -128,10 +148,15 @@ if (process.env.ROUTE_MAP) {
|
||||
if (arrowIdx === -1) continue;
|
||||
const path = trimmed.slice(0, arrowIdx).trim();
|
||||
const cfgStr = trimmed.slice(arrowIdx + 2).trim();
|
||||
try {
|
||||
ROUTE_MAP[path] = JSON.parse(cfgStr) as RouteEntry;
|
||||
} catch (err) {
|
||||
const message = err instanceof Error ? err.message : String(err);
|
||||
|
||||
// Try direct parse first, then fall back to normalized parse (handles
|
||||
// cases where the outer wrapper was stripped but inner quotes are still
|
||||
// escaped).
|
||||
const parsed = safeJsonParse<RouteEntry>(cfgStr);
|
||||
if (parsed) {
|
||||
ROUTE_MAP[path] = parsed;
|
||||
} else {
|
||||
const message = `expected valid JSON, got "${cfgStr.slice(0, 80)}"`;
|
||||
console.error(`[startup] Invalid ROUTE_MAP entry for "${path}":`, message);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user