diff options
| author | 2022-09-18 13:11:16 +0800 | |
|---|---|---|
| committer | 2022-09-17 22:11:16 -0700 | |
| commit | 184230058a5ce9782a30dfd52955c2e201064ea0 (patch) | |
| tree | 7c386edc05ef8cb12722ac9caef2b7a1cc602655 /src | |
| parent | a08b323e617c6e2db6c6bc2e1731f447b43ccb50 (diff) | |
| download | bun-184230058a5ce9782a30dfd52955c2e201064ea0.tar.gz bun-184230058a5ce9782a30dfd52955c2e201064ea0.tar.zst bun-184230058a5ce9782a30dfd52955c2e201064ea0.zip | |
feat: env loader nested values with curly braces (#1246)
* [env loader] Add support for nested value with curly braces
does not support default values for nested values, e.g., ${undefined:default}, ${undefined:-default}, or ${undefined-default}
* fix: minor fix and add more test
* [env loader] Improve nested value parsing performance
remove unnecessary branching
Co-authored-by: Like <like@ekil.sh>
Diffstat (limited to 'src')
| -rw-r--r-- | src/env_loader.zig | 47 |
1 files changed, 46 insertions, 1 deletions
diff --git a/src/env_loader.zig b/src/env_loader.zig index 72efce55f..be2bce933 100644 --- a/src/env_loader.zig +++ b/src/env_loader.zig @@ -72,11 +72,18 @@ pub const Lexer = struct { i += 1; const start = i; + const curly_braces_offset: usize = if (variable.value[i] == '{') 1 else 0; + i += curly_braces_offset; + while (i < variable.value.len) { switch (variable.value[i]) { 'a'...'z', 'A'...'Z', '0'...'9', '-', '_' => { i += 1; }, + '}' => { + i += curly_braces_offset; + break; + }, else => { break; }, @@ -85,7 +92,7 @@ pub const Lexer = struct { try writer.writeAll(variable.value[last_flush .. start - 1]); last_flush = i; - const name = variable.value[start..i]; + const name = variable.value[start + curly_braces_offset .. i - curly_braces_offset]; if (@call(.{ .modifier = .always_inline }, getter, .{ ctx, name })) |new_value| { if (new_value.len > 0) { @@ -1089,10 +1096,17 @@ test "DotEnv Loader - basic" { \\ \\NESTED_VALUE='$API_KEY' \\ + \\NESTED_VALUE_WITH_CURLY_BRACES='${API_KEY}' + \\NESTED_VALUE_WITHOUT_OPENING_CURLY_BRACE='$API_KEY}' + \\ \\RECURSIVE_NESTED_VALUE=$NESTED_VALUE:$API_KEY \\ + \\RECURSIVE_NESTED_VALUE_WITH_CURLY_BRACES=${NESTED_VALUE}:${API_KEY} + \\ \\NESTED_VALUES_RESPECT_ESCAPING='\$API_KEY' \\ + \\NESTED_VALUES_WITH_CURLY_BRACES_RESPECT_ESCAPING='\${API_KEY}' + \\ \\EMPTY_SINGLE_QUOTED_VALUE_IS_EMPTY_STRING='' \\ \\EMPTY_DOUBLE_QUOTED_VALUE_IS_EMPTY_STRING="" @@ -1108,9 +1122,13 @@ test "DotEnv Loader - basic" { false, ); try expectString(map.get("NESTED_VALUES_RESPECT_ESCAPING").?, "\\$API_KEY"); + try expectString(map.get("NESTED_VALUES_WITH_CURLY_BRACES_RESPECT_ESCAPING").?, "\\${API_KEY}"); try expectString(map.get("NESTED_VALUE").?, "verysecure"); + try expectString(map.get("NESTED_VALUE_WITH_CURLY_BRACES").?, "verysecure"); + try expectString(map.get("NESTED_VALUE_WITHOUT_OPENING_CURLY_BRACE").?, "verysecure}"); try expectString(map.get("RECURSIVE_NESTED_VALUE").?, "verysecure:verysecure"); + try expectString(map.get("RECURSIVE_NESTED_VALUE_WITH_CURLY_BRACES").?, "verysecure:verysecure"); try expectString(map.get("API_KEY").?, "verysecure"); try expectString(map.get("process.env.WAT").?, "ABCDEFGHIJKLMNOPQRSTUVWXYZZ10239457123"); @@ -1128,6 +1146,33 @@ test "DotEnv Loader - basic" { try expectString(map.get("EMPTY_DOUBLE_QUOTED_VALUE_IS_EMPTY_STRING").?, ""); } +test "DotEnv Loader - Nested values with curly braces" { + const VALID_ENV = + \\DB_USER=postgres + \\DB_PASS=xyz + \\DB_HOST=localhost + \\DB_PORT=5432 + \\DB_NAME=db + \\ + \\DB_USER2=${DB_USER} + \\ + \\DATABASE_URL="postgresql://${DB_USER}:${DB_PASS}@${DB_HOST}:${DB_PORT}/${DB_NAME}?pool_timeout=30&connection_limit=22" + \\ + ; + const source = logger.Source.initPathString(".env", VALID_ENV); + var map = Map.init(default_allocator); + Parser.parse( + &source, + default_allocator, + &map, + true, + false, + ); + try expectString(map.get("DB_USER").?, "postgres"); + try expectString(map.get("DB_USER2").?, "postgres"); + try expectString(map.get("DATABASE_URL").?, "postgresql://postgres:xyz@localhost:5432/db?pool_timeout=30&connection_limit=22"); +} + test "DotEnv Process" { var map = Map.init(default_allocator); var process = try std.process.getEnvMap(default_allocator); |
