mirror of
https://github.com/oven-sh/bun
synced 2026-02-02 15:08:46 +00:00
Add compile-time flags to control .env and bunfig.toml autoloading (#24790)
## Summary
This PR adds two new compile options to control whether standalone
executables autoload `.env` files and `bunfig.toml` configuration files.
## New Options
### JavaScript API
```js
await Bun.build({
entrypoints: ["./entry.ts"],
compile: {
autoloadDotenv: false, // Disable .env loading (default: true)
autoloadBunfig: false, // Disable bunfig.toml loading (default: true)
}
});
```
### CLI Flags
```bash
bun build --compile --no-compile-autoload-dotenv entry.ts
bun build --compile --no-compile-autoload-bunfig entry.ts
bun build --compile --compile-autoload-dotenv entry.ts
bun build --compile --compile-autoload-bunfig entry.ts
```
## Implementation
The flags are stored in a new `Flags` packed struct in
`StandaloneModuleGraph`:
```zig
pub const Flags = packed struct(u32) {
disable_default_env_files: bool = false,
disable_autoload_bunfig: bool = false,
_padding: u30 = 0,
};
```
These flags are:
1. Set during compilation from CLI args or JS API options
2. Serialized into the `StandaloneModuleGraph` embedded in the
executable
3. Read at runtime in `bootStandalone()` to conditionally load config
files
## Testing
Manually tested and verified:
- ✅ Default behavior loads `.env` files
- ✅ `--no-compile-autoload-dotenv` disables `.env` loading
- ✅ `--compile-autoload-dotenv` explicitly enables `.env` loading
- ✅ Default behavior loads `bunfig.toml` (verified with preload script)
- ✅ `--no-compile-autoload-bunfig` disables `bunfig.toml` loading
Test cases added in `test/bundler/bundler_compile_autoload.test.ts`
## Files Changed
- `src/StandaloneModuleGraph.zig` - Added Flags struct, updated
encode/decode
- `src/bun.js.zig` - Checks flags in bootStandalone()
- `src/bun.js/api/JSBundler.zig` - Added autoload options to
CompileOptions
- `src/bundler/bundle_v2.zig` - Pass flags to toExecutable()
- `src/cli.zig` - Added flags to BundlerOptions
- `src/cli/Arguments.zig` - Added CLI argument parsing
- `src/cli/build_command.zig` - Pass flags from context
- `test/bundler/expectBundled.ts` - Support new compile options
- `test/bundler/bundler_compile_autoload.test.ts` - New test file
---------
Co-authored-by: Claude Bot <claude-bot@bun.sh>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
This commit is contained in:
267
test/bundler/bundler_compile_autoload.test.ts
Normal file
267
test/bundler/bundler_compile_autoload.test.ts
Normal file
@@ -0,0 +1,267 @@
|
||||
import { describe } from "bun:test";
|
||||
import { itBundled } from "./expectBundled";
|
||||
|
||||
describe("bundler", () => {
|
||||
// Test that .env files are loaded by default in standalone executables
|
||||
itBundled("compile/AutoloadDotenvDefault", {
|
||||
compile: true,
|
||||
files: {
|
||||
"/entry.ts": /* js */ `
|
||||
console.log(process.env.TEST_VAR || "not found");
|
||||
`,
|
||||
},
|
||||
runtimeFiles: {
|
||||
"/.env": `TEST_VAR=from_dotenv`,
|
||||
},
|
||||
run: {
|
||||
stdout: "from_dotenv",
|
||||
setCwd: true,
|
||||
},
|
||||
});
|
||||
|
||||
// Test that .env files can be disabled with autoloadDotenv: false
|
||||
itBundled("compile/AutoloadDotenvDisabled", {
|
||||
compile: {
|
||||
autoloadDotenv: false,
|
||||
},
|
||||
files: {
|
||||
"/entry.ts": /* js */ `
|
||||
console.log(process.env.TEST_VAR || "not found");
|
||||
`,
|
||||
},
|
||||
runtimeFiles: {
|
||||
"/.env": `TEST_VAR=from_dotenv`,
|
||||
},
|
||||
run: {
|
||||
stdout: "not found",
|
||||
setCwd: true,
|
||||
},
|
||||
});
|
||||
|
||||
// Test that .env files can be explicitly enabled with autoloadDotenv: true
|
||||
itBundled("compile/AutoloadDotenvEnabledExplicitly", {
|
||||
compile: {
|
||||
autoloadDotenv: true,
|
||||
},
|
||||
files: {
|
||||
"/entry.ts": /* js */ `
|
||||
console.log(process.env.TEST_VAR || "not found");
|
||||
`,
|
||||
},
|
||||
runtimeFiles: {
|
||||
"/.env": `TEST_VAR=from_dotenv`,
|
||||
},
|
||||
run: {
|
||||
stdout: "from_dotenv",
|
||||
setCwd: true,
|
||||
},
|
||||
});
|
||||
|
||||
// Test that process environment variables take precedence over .env files
|
||||
itBundled("compile/AutoloadDotenvWithExistingEnv", {
|
||||
compile: true,
|
||||
files: {
|
||||
"/entry.ts": /* js */ `
|
||||
console.log(process.env.TEST_VAR || "not found");
|
||||
`,
|
||||
},
|
||||
runtimeFiles: {
|
||||
"/.env": `TEST_VAR=from_dotenv`,
|
||||
},
|
||||
run: {
|
||||
stdout: "from_shell",
|
||||
setCwd: true,
|
||||
env: {
|
||||
TEST_VAR: "from_shell",
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// Test that bunfig.toml is loaded by default (preload is executed)
|
||||
itBundled("compile/AutoloadBunfigDefault", {
|
||||
compile: true,
|
||||
files: {
|
||||
"/entry.ts": /* js */ `
|
||||
console.log("ENTRY");
|
||||
`,
|
||||
},
|
||||
runtimeFiles: {
|
||||
"/bunfig.toml": `
|
||||
preload = ["./preload.ts"]
|
||||
`,
|
||||
"/preload.ts": `
|
||||
console.log("PRELOAD");
|
||||
`,
|
||||
},
|
||||
run: {
|
||||
stdout: "PRELOAD\nENTRY",
|
||||
setCwd: true,
|
||||
},
|
||||
});
|
||||
|
||||
// Test that bunfig.toml can be disabled with autoloadBunfig: false
|
||||
itBundled("compile/AutoloadBunfigDisabled", {
|
||||
compile: {
|
||||
autoloadBunfig: false,
|
||||
},
|
||||
files: {
|
||||
"/entry.ts": /* js */ `
|
||||
console.log("ENTRY");
|
||||
`,
|
||||
},
|
||||
runtimeFiles: {
|
||||
"/bunfig.toml": `
|
||||
preload = ["./preload.ts"]
|
||||
`,
|
||||
"/preload.ts": `
|
||||
console.log("PRELOAD");
|
||||
`,
|
||||
},
|
||||
run: {
|
||||
// When bunfig is disabled, preload should NOT execute
|
||||
stdout: "ENTRY",
|
||||
setCwd: true,
|
||||
},
|
||||
});
|
||||
|
||||
// Test that bunfig.toml can be explicitly enabled with autoloadBunfig: true
|
||||
itBundled("compile/AutoloadBunfigEnabled", {
|
||||
compile: {
|
||||
autoloadBunfig: true,
|
||||
},
|
||||
files: {
|
||||
"/entry.ts": /* js */ `
|
||||
console.log("ENTRY");
|
||||
`,
|
||||
},
|
||||
runtimeFiles: {
|
||||
"/bunfig.toml": `
|
||||
preload = ["./preload.ts"]
|
||||
`,
|
||||
"/preload.ts": `
|
||||
console.log("PRELOAD");
|
||||
`,
|
||||
},
|
||||
run: {
|
||||
stdout: "PRELOAD\nENTRY",
|
||||
setCwd: true,
|
||||
},
|
||||
});
|
||||
|
||||
// Test CLI backend with autoloadDotenv: false
|
||||
itBundled("compile/AutoloadDotenvDisabledCLI", {
|
||||
compile: {
|
||||
autoloadDotenv: false,
|
||||
},
|
||||
backend: "cli",
|
||||
files: {
|
||||
"/entry.ts": /* js */ `
|
||||
console.log(process.env.TEST_VAR || "not found");
|
||||
`,
|
||||
},
|
||||
runtimeFiles: {
|
||||
"/.env": `TEST_VAR=from_dotenv`,
|
||||
},
|
||||
run: {
|
||||
stdout: "not found",
|
||||
setCwd: true,
|
||||
},
|
||||
});
|
||||
|
||||
// Test CLI backend with autoloadDotenv: true
|
||||
itBundled("compile/AutoloadDotenvEnabledCLI", {
|
||||
compile: {
|
||||
autoloadDotenv: true,
|
||||
},
|
||||
backend: "cli",
|
||||
files: {
|
||||
"/entry.ts": /* js */ `
|
||||
console.log(process.env.TEST_VAR || "not found");
|
||||
`,
|
||||
},
|
||||
runtimeFiles: {
|
||||
"/.env": `TEST_VAR=from_dotenv`,
|
||||
},
|
||||
run: {
|
||||
stdout: "from_dotenv",
|
||||
setCwd: true,
|
||||
},
|
||||
});
|
||||
|
||||
// Test CLI backend with autoloadBunfig: false
|
||||
itBundled("compile/AutoloadBunfigDisabledCLI", {
|
||||
compile: {
|
||||
autoloadBunfig: false,
|
||||
},
|
||||
backend: "cli",
|
||||
files: {
|
||||
"/entry.ts": /* js */ `
|
||||
console.log("ENTRY");
|
||||
`,
|
||||
},
|
||||
runtimeFiles: {
|
||||
"/bunfig.toml": `
|
||||
preload = ["./preload.ts"]
|
||||
`,
|
||||
"/preload.ts": `
|
||||
console.log("PRELOAD");
|
||||
`,
|
||||
},
|
||||
run: {
|
||||
stdout: "ENTRY",
|
||||
setCwd: true,
|
||||
},
|
||||
});
|
||||
|
||||
// Test CLI backend with autoloadBunfig: true
|
||||
itBundled("compile/AutoloadBunfigEnabledCLI", {
|
||||
compile: {
|
||||
autoloadBunfig: true,
|
||||
},
|
||||
backend: "cli",
|
||||
files: {
|
||||
"/entry.ts": /* js */ `
|
||||
console.log("ENTRY");
|
||||
`,
|
||||
},
|
||||
runtimeFiles: {
|
||||
"/bunfig.toml": `
|
||||
preload = ["./preload.ts"]
|
||||
`,
|
||||
"/preload.ts": `
|
||||
console.log("PRELOAD");
|
||||
`,
|
||||
},
|
||||
run: {
|
||||
stdout: "PRELOAD\nENTRY",
|
||||
setCwd: true,
|
||||
},
|
||||
});
|
||||
|
||||
// Test that both flags can be disabled together without interference
|
||||
itBundled("compile/AutoloadBothDisabled", {
|
||||
compile: {
|
||||
autoloadDotenv: false,
|
||||
autoloadBunfig: false,
|
||||
},
|
||||
files: {
|
||||
"/entry.ts": /* js */ `
|
||||
console.log(process.env.TEST_VAR || "not found");
|
||||
console.log("ENTRY");
|
||||
`,
|
||||
},
|
||||
runtimeFiles: {
|
||||
"/.env": `TEST_VAR=from_dotenv`,
|
||||
"/bunfig.toml": `
|
||||
preload = ["./preload.ts"]
|
||||
`,
|
||||
"/preload.ts": `
|
||||
console.log("PRELOAD");
|
||||
`,
|
||||
},
|
||||
run: {
|
||||
stdout: "not found\nENTRY",
|
||||
setCwd: true,
|
||||
},
|
||||
});
|
||||
});
|
||||
@@ -702,6 +702,16 @@ function expectBundled(
|
||||
? Object.entries(bundleErrors).flatMap(([file, v]) => v.map(error => ({ file, error })))
|
||||
: null;
|
||||
|
||||
// Helper to add compile boolean flags
|
||||
const compileFlag = (prop: string, trueFlag: string, falseFlag: string): string[] => {
|
||||
if (compile && typeof compile === "object" && Object.prototype.hasOwnProperty.call(compile, prop)) {
|
||||
const value = (compile as any)[prop];
|
||||
if (value === true) return [trueFlag];
|
||||
if (value === false) return [falseFlag];
|
||||
}
|
||||
return [];
|
||||
};
|
||||
|
||||
if (backend === "cli") {
|
||||
if (plugins) {
|
||||
throw new Error("plugins not possible in backend=CLI");
|
||||
@@ -719,6 +729,8 @@ function expectBundled(
|
||||
compile && typeof compile === "object" && "execArgv" in compile
|
||||
? `--compile-exec-argv=${Array.isArray(compile.execArgv) ? compile.execArgv.join(" ") : compile.execArgv}`
|
||||
: [],
|
||||
compileFlag("autoloadDotenv", "--compile-autoload-dotenv", "--no-compile-autoload-dotenv"),
|
||||
compileFlag("autoloadBunfig", "--compile-autoload-bunfig", "--no-compile-autoload-bunfig"),
|
||||
outfile ? `--outfile=${outfile}` : `--outdir=${outdir}`,
|
||||
define && Object.entries(define).map(([k, v]) => ["--define", `${k}=${v}`]),
|
||||
`--target=${target}`,
|
||||
@@ -1058,6 +1070,12 @@ function expectBundled(
|
||||
target: compile,
|
||||
outfile: outfile,
|
||||
};
|
||||
} else if (typeof compile === "object") {
|
||||
// When compile is already an object, ensure it has outfile set
|
||||
compile = {
|
||||
...compile,
|
||||
outfile: outfile,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user