Something went wrong. Try again.
Monorepo for the nibling.run platform
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107// util.parseEnv: a .env-file parser matching Node's src/node_dotenv.cc ParseContent// (reimplemented from its documented behavior). No variable interpolation: `${FOO}`// is kept literally, as Node's own parser does.function trimSpaces(s: string): string { const start = s.search(/[^ \t\n]/); if (start === -1) return ""; let end = s.length - 1; while (end >= 0 && " \t\n".includes(s[end]!)) end--; return s.slice(start, end + 1);}
export function parseEnv(content: unknown): Record<string, string> { if (typeof content !== "string") { const got = content === null || content === undefined ? ` Received ${content}` : typeof content === "function" ? ` Received function ${(content as { name?: string }).name || "anonymous"}` : typeof content === "object" ? ` Received an instance of ${(content as object).constructor?.name ?? "Object"}` : ` Received type ${typeof content} (${String(content)})`; throw Object.assign(new TypeError(`The "content" argument must be of type string.${got}`), { code: "ERR_INVALID_ARG_TYPE" }); } const store: Record<string, string> = Object.create(null); const text = content.replace(/\r/g, ""); let rest = trimSpaces(text);
while (rest.length > 0) { if (rest[0] === "\n" || rest[0] === "#") { const nl = rest.indexOf("\n"); rest = nl === -1 ? "" : rest.slice(nl + 1); continue; }
const stop = (() => { for (let i = 0; i < rest.length; i++) { if (rest[i] === "=" || rest[i] === "\n") return i; } return -1; })(); if (stop === -1 || rest[stop] === "\n") { if (stop !== -1) { rest = trimSpaces(rest.slice(stop + 1)); continue; } break; }
let key = trimSpaces(rest.slice(0, stop)); rest = rest.slice(stop + 1);
if (rest.length === 0 || rest[0] === "\n") { if (key) store[key] = ""; rest = rest.length === 0 ? "" : rest.slice(1); continue; }
rest = trimSpaces(rest); if (key === "") continue; if (key.startsWith("export ")) key = trimSpaces(key.slice(7));
if (rest.length === 0) { store[key] = ""; break; }
// A double-quoted value may span lines; \n inside it becomes a real newline. if (rest[0] === '"') { const closing = rest.indexOf('"', 1); if (closing !== -1) { const value = rest.slice(1, closing).replace(/\\n/g, "\n"); store[key] = value; const nl = rest.indexOf("\n", closing + 1); rest = nl === -1 ? "" : rest.slice(nl + 1); continue; } }
if (rest[0] === "'" || rest[0] === '"' || rest[0] === "`") { const quote = rest[0]; const closing = rest.indexOf(quote, 1); if (closing === -1) { const nl = rest.indexOf("\n"); if (nl !== -1) { store[key] = rest.slice(0, nl); rest = rest.slice(nl + 1); } else { store[key] = rest; break; } } else { store[key] = rest.slice(1, closing); const nl = rest.indexOf("\n", closing + 1); rest = nl === -1 ? "" : rest.slice(nl + 1); continue; } } else { const nl = rest.indexOf("\n"); let value = nl === -1 ? rest : rest.slice(0, nl); const hash = value.indexOf("#"); if (hash !== -1) value = value.slice(0, hash); store[key] = trimSpaces(value); rest = nl === -1 ? "" : rest.slice(nl + 1); }
rest = trimSpaces(rest); }
return store;}