mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-23 06:10:02 +08:00
* Add Node 24 environment-file support * Update runtime harnesses for environment-file URL paths * Link URL dependencies in weak metadata runtime tests
82 lines
4.4 KiB
JavaScript
82 lines
4.4 KiB
JavaScript
import { parseEnv } from "node:util";
|
|
import { loadEnvFile } from "node:process";
|
|
import { mkdtempSync, writeFileSync, rmSync } from "node:fs";
|
|
import { tmpdir } from "node:os";
|
|
import { pathToFileURL } from "node:url";
|
|
|
|
export function readEnv(key) { return process.env[key]; }
|
|
export function writeEnv(key, value) { process.env[key] = value; }
|
|
|
|
export function reportEnv() {
|
|
const samples = [
|
|
"Z=last\nA=first\nZ=replaced\nEMPTY=\n",
|
|
" # heading\nexport NAME = world\nINLINE=value#comment\nSPACES = two words \n",
|
|
"SINGLE='a # b\\n c'\nDOUBLE=\"a # b\\n c\"\nTICK=`a # b\\n c`\n",
|
|
"MULTI=\"first\nsecond\" trailing ignored\nNEXT=ok\n",
|
|
"UNCLOSED=\"one\nNEXT=two\nLAST=three",
|
|
"export X=\nexport Y= \n=\n = value\nexport =foo",
|
|
"X= \nY=foo",
|
|
"__proto__=ignored\nconstructor=own\ntoString=value\n2=two\n10=ten\n1=one",
|
|
"UNICODE=é 😀 你好\n\uFEFFBOM=kept\nNULL=va\0lue\nLONE=\ud800\nn\0ame=value",
|
|
"A=${OTHER}\nB=$OTHER\nC=one=two\nD=\"\\t\\r\\n\"", "",
|
|
];
|
|
for (const sample of samples) {
|
|
const result = parseEnv(sample);
|
|
console.log(JSON.stringify(result), JSON.stringify(Object.keys(result)));
|
|
console.log(Object.getPrototypeOf(result) === Object.prototype);
|
|
}
|
|
for (const value of [undefined, null, 42, true, {}, [], Symbol("x"), 1n, () => {}, new Date(0), Object.create(null), Object.assign(Object.create(null), { X: 1 })]) {
|
|
try { parseEnv(value); }
|
|
catch (e) { console.log(e.name, e.code, e.message); }
|
|
}
|
|
const fresh = parseEnv("FRESH=one");
|
|
fresh.FRESH = "changed";
|
|
console.log(fresh.FRESH, parseEnv("FRESH=one").FRESH);
|
|
|
|
const directory = mkdtempSync(tmpdir() + "/scriptc-env-island-");
|
|
const previous = process.cwd();
|
|
const prefix = "SCRIPTC_ENV_ISLAND_";
|
|
const symbol = Symbol("env");
|
|
console.log("symbols", process.env[symbol], symbol in process.env, delete process.env[symbol]);
|
|
const names = ["NEW", "KEEP", "EMPTY", "SECOND", "RAW", "NUL", "DEFINED", "NUMBER"];
|
|
for (const name of names) delete process.env[prefix + name];
|
|
process.env[prefix + "KEEP"] = "existing";
|
|
process.env[prefix + "EMPTY"] = "";
|
|
process.env[prefix + "NUMBER"] = 42;
|
|
Object.defineProperty(process.env, prefix + "DEFINED", { value: "defined", configurable: true, writable: true, enumerable: true });
|
|
try {
|
|
console.log("chdir", process.chdir(directory), process.cwd() === directory);
|
|
for (const value of [undefined, 42, {}]) {
|
|
try { process.chdir(value); }
|
|
catch (e) { console.log(e.name, e.code, e.message); }
|
|
}
|
|
writeFileSync(".env", prefix + "NEW=default\n" + prefix + "KEEP=replaced\n" + prefix + "EMPTY=replaced\n");
|
|
writeFileSync("second.env", prefix + "NEW=second\n" + prefix + "SECOND=\"two\\nlines\"\n");
|
|
console.log("default", loadEnvFile(), process.env[prefix + "NEW"], process.env[prefix + "KEEP"], JSON.stringify(process.env[prefix + "EMPTY"]));
|
|
loadEnvFile("second.env");
|
|
console.log("second", process.env[prefix + "NEW"], JSON.stringify(process.env[prefix + "SECOND"]));
|
|
for (const path of [undefined, null, Buffer.from(".env"), new Uint8Array(Buffer.from(".env")), pathToFileURL(directory + "/.env")]) {
|
|
delete process.env[prefix + "NEW"];
|
|
console.log("path", loadEnvFile(path), process.env[prefix + "NEW"]);
|
|
}
|
|
writeFileSync("raw.env", Buffer.concat([Buffer.from(prefix + "RAW="), Buffer.from([0xff, 0xe2, 0x82]), Buffer.from("\n" + prefix + "NUL=va\0lue")]));
|
|
loadEnvFile("raw.env");
|
|
console.log("raw", JSON.stringify(process.env[prefix + "RAW"]), process.env[prefix + "NUL"]);
|
|
console.log("keys", Object.keys(process.env).filter(k => k.startsWith(prefix)).sort().join(","));
|
|
console.log("descriptor", JSON.stringify(Object.getOwnPropertyDescriptor(process.env, prefix + "DEFINED")), process.env[prefix + "NUMBER"]);
|
|
for (const path of [42, false, {}, [], Symbol("path"), "a\0b", Buffer.from("a\0b"), new URL("https://example.com/"), new URL("file:///tmp/a%2fb"), "missing.env"]) {
|
|
try { loadEnvFile(path); }
|
|
catch (e) { console.log(e.name, e.code, e.message); }
|
|
}
|
|
try { Object.defineProperty(process.env, prefix + "BAD", { value: "bad" }); }
|
|
catch (e) { console.log(e.name, e.code, e.message); }
|
|
delete process.env[prefix + "KEEP"];
|
|
loadEnvFile();
|
|
console.log("reload", process.env[prefix + "KEEP"]);
|
|
} finally {
|
|
process.chdir(previous);
|
|
rmSync(directory, { recursive: true, force: true });
|
|
for (const name of names) delete process.env[prefix + name];
|
|
}
|
|
}
|