Skip to content

Commit e3c9bc1

Browse files
committed
perf(env): optimize case-insensitive lookup with length fast path
Add findCaseInsensitiveKey helper that checks string length before calling toUpperCase(), reducing unnecessary string operations. DRY improvements: - Extract duplicate case-insensitive search logic into helper - Reuse helper in both get() and has() Proxy handlers Performance impact: - Fast path: O(1) length check eliminates mismatched keys immediately - Only calls toUpperCase() when lengths match (rare case) - Reduces overhead for common lookups with many env vars
1 parent b135a1a commit e3c9bc1

1 file changed

Lines changed: 30 additions & 18 deletions

File tree

src/env.ts

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,26 @@ export function envAsString(value: unknown, defaultValue = ''): string {
5454
return StringCtor(value).trim()
5555
}
5656

57+
/**
58+
* Helper to find a case-insensitive key match in an object.
59+
* Uses fast path checks to minimize expensive toUpperCase() calls.
60+
*/
61+
function findCaseInsensitiveKey(
62+
obj: Record<string, string | undefined>,
63+
upperProp: string,
64+
): string | undefined {
65+
const targetLength = upperProp.length
66+
for (const key of Object.keys(obj)) {
67+
// Fast path: bail early if lengths don't match.
68+
if (key.length !== targetLength) continue
69+
// Only call toUpperCase if length matches.
70+
if (key.toUpperCase() === upperProp) {
71+
return key
72+
}
73+
}
74+
return undefined
75+
}
76+
5777
/**
5878
* Create a case-insensitive environment variable Proxy for Windows compatibility.
5979
* On Windows, environment variables are case-insensitive (PATH vs Path vs path).
@@ -132,17 +152,15 @@ export function createEnvProxy(
132152
if (caseInsensitiveKeys.has(upperProp)) {
133153
// Check overrides with case variations.
134154
if (overrides) {
135-
for (const key of Object.keys(overrides)) {
136-
if (key.toUpperCase() === upperProp) {
137-
return overrides[key]
138-
}
155+
const key = findCaseInsensitiveKey(overrides, upperProp)
156+
if (key !== undefined) {
157+
return overrides[key]
139158
}
140159
}
141160
// Check base with case variations.
142-
for (const key of Object.keys(base)) {
143-
if (key.toUpperCase() === upperProp) {
144-
return base[key]
145-
}
161+
const key = findCaseInsensitiveKey(base, upperProp)
162+
if (key !== undefined) {
163+
return base[key]
146164
}
147165
}
148166

@@ -192,17 +210,11 @@ export function createEnvProxy(
192210
// Case-insensitive check.
193211
const upperProp = prop.toUpperCase()
194212
if (caseInsensitiveKeys.has(upperProp)) {
195-
if (overrides) {
196-
for (const key of Object.keys(overrides)) {
197-
if (key.toUpperCase() === upperProp) {
198-
return true
199-
}
200-
}
213+
if (overrides && findCaseInsensitiveKey(overrides, upperProp) !== undefined) {
214+
return true
201215
}
202-
for (const key of Object.keys(base)) {
203-
if (key.toUpperCase() === upperProp) {
204-
return true
205-
}
216+
if (findCaseInsensitiveKey(base, upperProp) !== undefined) {
217+
return true
206218
}
207219
}
208220

0 commit comments

Comments
 (0)