@gajae-code/utils 0.14.0 → 0.14.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/types/env-file.d.ts +11 -0
- package/package.json +2 -2
- package/src/env-file.ts +41 -4
package/dist/types/env-file.d.ts
CHANGED
|
@@ -17,5 +17,16 @@ export declare function parseShellEnvFile(filePath: string): Record<string, stri
|
|
|
17
17
|
* Ignores lines that are empty or start with '#'. Trims whitespace.
|
|
18
18
|
* Allows values to be quoted with single or double quotes.
|
|
19
19
|
* Returns an object of key-value pairs.
|
|
20
|
+
*
|
|
21
|
+
* The trust guards (`trustedAgentDirOverrideFor`, `trustedConfigDirName`,
|
|
22
|
+
* `filterCredentialInheritedEnv`) decide provenance by comparing
|
|
23
|
+
* `process.env` against this parse, so the accepted syntax must be a superset
|
|
24
|
+
* of what Bun's own dotenv loader honors in `cwd/.env`: `export KEY=value`,
|
|
25
|
+
* whitespace around `=`, and `#` comments after unquoted values (quotes keep
|
|
26
|
+
* their `#`). Values that Bun would expand (`$VAR`, `${VAR}`, backticks,
|
|
27
|
+
* command substitution) are kept as their literal text: the trust rule only
|
|
28
|
+
* needs the parser to see the key at all, and an operator environment value
|
|
29
|
+
* cannot equal attacker-written expansion text, so a literal parse stays
|
|
30
|
+
* conservative.
|
|
20
31
|
*/
|
|
21
32
|
export declare function parseEnvFile(filePath: string): Record<string, string>;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@gajae-code/utils",
|
|
4
|
-
"version": "0.14.
|
|
4
|
+
"version": "0.14.1",
|
|
5
5
|
"description": "Shared utilities for pi packages",
|
|
6
6
|
"homepage": "https://gajae-code.com",
|
|
7
7
|
"author": "Yeachan-Heo",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"fmt": "biome format --write ."
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@gajae-code/natives": "0.14.
|
|
34
|
+
"@gajae-code/natives": "0.14.1",
|
|
35
35
|
"beautiful-mermaid": "^1.1.3",
|
|
36
36
|
"handlebars": "^4.7.9",
|
|
37
37
|
"winston": "^3.19.0",
|
package/src/env-file.ts
CHANGED
|
@@ -38,6 +38,30 @@ function stripInlineShellComment(value: string): string {
|
|
|
38
38
|
return value.trimEnd();
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
/**
|
|
42
|
+
* Strips an unquoted trailing `# comment` from a dotenv value the way Bun's
|
|
43
|
+
* dotenv loader does: an unescaped `#` starts a comment regardless of the
|
|
44
|
+
* preceding character (`a#b` loads as `a`), while `#` inside quotes or after a
|
|
45
|
+
* backslash escape survives. Used only by `parseEnvFile`; shell files use
|
|
46
|
+
* `stripInlineShellComment`, whose POSIX rule requires whitespace before `#`.
|
|
47
|
+
*/
|
|
48
|
+
function stripInlineDotenvComment(value: string): string {
|
|
49
|
+
let quote: '"' | "'" | undefined;
|
|
50
|
+
for (let i = 0; i < value.length; i++) {
|
|
51
|
+
const char = value[i];
|
|
52
|
+
if (char === "\\") {
|
|
53
|
+
i++;
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
if ((char === '"' || char === "'") && (!quote || quote === char)) {
|
|
57
|
+
quote = quote ? undefined : char;
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
if (char === "#" && !quote) return value.slice(0, i).trimEnd();
|
|
61
|
+
}
|
|
62
|
+
return value.trimEnd();
|
|
63
|
+
}
|
|
64
|
+
|
|
41
65
|
/**
|
|
42
66
|
* Parses simple POSIX shell environment assignments from files such as
|
|
43
67
|
* ~/.zshrc without executing user shell code. Supports `export KEY=value` and
|
|
@@ -81,6 +105,17 @@ export function parseShellEnvFile(filePath: string): Record<string, string> {
|
|
|
81
105
|
* Ignores lines that are empty or start with '#'. Trims whitespace.
|
|
82
106
|
* Allows values to be quoted with single or double quotes.
|
|
83
107
|
* Returns an object of key-value pairs.
|
|
108
|
+
*
|
|
109
|
+
* The trust guards (`trustedAgentDirOverrideFor`, `trustedConfigDirName`,
|
|
110
|
+
* `filterCredentialInheritedEnv`) decide provenance by comparing
|
|
111
|
+
* `process.env` against this parse, so the accepted syntax must be a superset
|
|
112
|
+
* of what Bun's own dotenv loader honors in `cwd/.env`: `export KEY=value`,
|
|
113
|
+
* whitespace around `=`, and `#` comments after unquoted values (quotes keep
|
|
114
|
+
* their `#`). Values that Bun would expand (`$VAR`, `${VAR}`, backticks,
|
|
115
|
+
* command substitution) are kept as their literal text: the trust rule only
|
|
116
|
+
* needs the parser to see the key at all, and an operator environment value
|
|
117
|
+
* cannot equal attacker-written expansion text, so a literal parse stays
|
|
118
|
+
* conservative.
|
|
84
119
|
*/
|
|
85
120
|
export function parseEnvFile(filePath: string): Record<string, string> {
|
|
86
121
|
const result: Record<string, string> = {};
|
|
@@ -91,13 +126,15 @@ export function parseEnvFile(filePath: string): Record<string, string> {
|
|
|
91
126
|
// Skip comments and blank lines
|
|
92
127
|
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
93
128
|
|
|
94
|
-
const
|
|
95
|
-
if (
|
|
129
|
+
const match = /^(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)$/.exec(trimmed);
|
|
130
|
+
if (!match) continue;
|
|
96
131
|
|
|
97
|
-
const key =
|
|
132
|
+
const key = match[1];
|
|
98
133
|
if (!isValidEnvName(key)) continue;
|
|
99
134
|
|
|
100
|
-
|
|
135
|
+
// Strip an unquoted trailing `# comment` the way Bun's dotenv loader
|
|
136
|
+
// does (`KEY=v#note` loads as `v`); quoted `#` survives.
|
|
137
|
+
let value = stripInlineDotenvComment(match[2] ?? "").trim();
|
|
101
138
|
|
|
102
139
|
// Remove surrounding quotes (" or ')
|
|
103
140
|
if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"))) {
|