Compare commits

...

5 Commits

Author SHA1 Message Date
Dylan Conway
43e479339e make more better 2025-08-25 17:05:22 -07:00
Dylan Conway
308a51542e update 2025-08-25 17:04:16 -07:00
autofix-ci[bot]
e095e57078 [autofix.ci] apply automated fixes 2025-08-25 23:36:03 +00:00
Claude Bot
65c257ace8 Simplify implementation: remove schema.peechy changes, use direct assignment, restore bunfig.toml
- Reverted changes to schema.peechy (not needed)
- Removed setAutoExpand function, use direct assignment instead
- Reverted cli.zig to use std.mem.zeroes()
- Set default env_auto_expand = true in bunfig parsing
- Restored bunfig.toml with example configuration
2025-08-25 23:33:24 +00:00
Claude Bot
f7a2c1a926 Add env.autoExpand configuration option to bunfig.toml
Adds a new boolean configuration option `env.autoExpand` to control whether
environment variables are expanded in .env files. This allows users to
disable variable expansion when they want literal dollar signs preserved.

- Defaults to `true` (existing behavior - expansion enabled)
- When set to `false`, variables like $FOO and ${FOO} are not expanded
- Added comprehensive tests covering all scenarios

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-25 23:17:37 +00:00
5 changed files with 90 additions and 5 deletions

View File

@@ -1723,6 +1723,10 @@ pub const api = struct {
serve_hmr: ?bool = null,
serve_define: ?StringMap = null,
// [env]
// autoExpand = false
env_auto_expand: bool = true,
// from --no-addons. null == true
allow_addons: ?bool = null,
/// from --unhandled-rejections, default is 'bun'

View File

@@ -191,6 +191,13 @@ pub const Bunfig = struct {
this.bunfig.origin = try expr.data.e_string.string(allocator);
}
if (json.get("env")) |env_expr| {
if (env_expr.get("autoExpand")) |auto_expand| {
try this.expect(auto_expand, .e_boolean);
this.bunfig.env_auto_expand = auto_expand.data.e_boolean.value;
}
}
if (comptime cmd == .RunCommand or cmd == .AutoCommand) {
if (json.get("serve")) |expr| {
if (expr.get("port")) |port| {

View File

@@ -21,6 +21,7 @@ pub const Loader = struct {
custom_files_loaded: bun.StringArrayHashMap(logger.Source),
quiet: bool = false,
auto_expand: bool = true,
did_load_process: bool = false,
reject_unauthorized: ?bool = null,
@@ -782,7 +783,7 @@ pub const Loader = struct {
value_buffer,
override,
false,
true,
this.auto_expand,
);
@field(this, base) = source.*;
@@ -855,7 +856,7 @@ pub const Loader = struct {
value_buffer,
override,
false,
true,
this.auto_expand,
);
try this.custom_files_loaded.put(file_path, source.*);
@@ -1066,7 +1067,7 @@ const Parser = struct {
map: *Map,
comptime override: bool,
comptime is_process: bool,
comptime expand: bool,
expand: bool,
) OOM!void {
var count = map.map.count();
while (this.pos < this.src.len) {
@@ -1090,7 +1091,7 @@ const Parser = struct {
.conditional = false,
};
}
if (comptime !is_process and expand) {
if (!is_process and expand) {
var it = map.iterator();
while (it.next()) |entry| {
if (count > 0) {
@@ -1113,7 +1114,7 @@ const Parser = struct {
value_buffer: *std.ArrayList(u8),
comptime override: bool,
comptime is_process: bool,
comptime expand: bool,
expand: bool,
) OOM!void {
// Clear the buffer before each parse to ensure no leftover data
value_buffer.clearRetainingCapacity();

View File

@@ -407,6 +407,9 @@ pub const Transpiler = struct {
break :brk loader;
};
// Set autoExpand from the TransformOptions
env_loader.auto_expand = opts.env_auto_expand;
if (DotEnv.instance == null) {
DotEnv.instance = env_loader;
}

View File

@@ -0,0 +1,70 @@
import { describe, expect, test } from "bun:test";
import { bunRun, tempDirWithFiles } from "harness";
describe("env.autoExpand in bunfig.toml", () => {
test("autoExpand: true - variable expansion works (default behavior)", () => {
const dir = tempDirWithFiles("dotenv-auto-expand-true", {
"bunfig.toml": `
[env]
autoExpand = true
`,
".env": "FOO=foo\nBAR=$FOO bar\nMOO=${FOO} ${BAR:-fail} ${MOZ:-moo}",
"index.ts": "console.log([process.env.FOO, process.env.BAR, process.env.MOO].join('|'));",
});
const { stdout } = bunRun(`${dir}/index.ts`);
expect(stdout).toBe("foo|foo bar|foo foo bar moo");
});
test("autoExpand: false - variable expansion is disabled", () => {
const dir = tempDirWithFiles("dotenv-auto-expand-false", {
"bunfig.toml": `
[env]
autoExpand = false
`,
".env": "FOO=foo\nBAR=$FOO bar\nMOO=${FOO} ${BAR:-fail} ${MOZ:-moo}",
"index.ts": "console.log([process.env.FOO, process.env.BAR, process.env.MOO].join('|'));",
});
const { stdout } = bunRun(`${dir}/index.ts`);
expect(stdout).toBe("foo|$FOO bar|${FOO} ${BAR:-fail} ${MOZ:-moo}");
});
test("autoExpand not specified - defaults to true (expansion enabled)", () => {
const dir = tempDirWithFiles("dotenv-auto-expand-default", {
"bunfig.toml": `
# no env.autoExpand setting
`,
".env": "FOO=foo\nBAR=$FOO bar",
"index.ts": "console.log([process.env.FOO, process.env.BAR].join('|'));",
});
const { stdout } = bunRun(`${dir}/index.ts`);
expect(stdout).toBe("foo|foo bar");
});
test("autoExpand: false with different expansion patterns", () => {
const dir = tempDirWithFiles("dotenv-auto-expand-patterns", {
"bunfig.toml": `
[env]
autoExpand = false
`,
".env": "BASE=base\nSIMPLE=$BASE\nBRACED=${BASE}\nWITH_DEFAULT=${MISSING:-default}\nNESTED=${BASE}_${BASE}",
"index.ts":
"console.log([process.env.BASE, process.env.SIMPLE, process.env.BRACED, process.env.WITH_DEFAULT, process.env.NESTED].join('|'));",
});
const { stdout } = bunRun(`${dir}/index.ts`);
expect(stdout).toBe("base|$BASE|${BASE}|${MISSING:-default}|${BASE}_${BASE}");
});
test("autoExpand: false with escaped dollar signs", () => {
const dir = tempDirWithFiles("dotenv-auto-expand-escaped", {
"bunfig.toml": `
[env]
autoExpand = false
`,
".env": "FOO=foo\nBAR=\\$FOO\nMOO=\\$\\$FOO",
"index.ts": "console.log([process.env.FOO, process.env.BAR, process.env.MOO].join('|'));",
});
const { stdout } = bunRun(`${dir}/index.ts`);
// When autoExpand is false, escaped dollar signs should remain as-is
expect(stdout).toBe("foo|\\$FOO|\\$\\$FOO");
});
});