-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathstring.ts
More file actions
79 lines (74 loc) · 2.81 KB
/
string.ts
File metadata and controls
79 lines (74 loc) · 2.81 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
/**
* @fileoverview `envAsString` — coerce an env-var-shaped value into
* a string. Defaults to trimming whitespace; `trim: false` preserves
* the value as-is. Positional second argument is back-compat for the
* legacy `defaultValue` form.
*/
import { ArrayIsArray } from '../primordials/array'
import type { EnvAsStringOptions } from './types'
// IMPORTANT: Do not use destructuring here - use direct assignment instead.
// tsgo has a bug that incorrectly transpiles destructured exports, resulting in
// `exports.SomeName = void 0;` which causes runtime errors.
// See: https://github.com/SocketDev/socket-packageurl-js/issues/3
const StringCtor = String
/**
* Convert an environment variable value to a string.
*
* Back-compat overload: passing a bare string as the second argument is
* equivalent to `{ defaultValue: S }`.
*
* @param value - The value to convert
* @param defaultValueOrOptions - Default (string) or options object
* @returns The string value, or the default value
*
* @example
* ```typescript
* import { envAsString } from '@socketsecurity/lib/env/string'
*
* envAsString(' hello ') // 'hello' (trimmed)
* envAsString(' hello ', { trim: false }) // ' hello '
* envAsString(undefined) // ''
* envAsString(null, 'n/a') // 'n/a' (legacy positional)
* ```
*/
/*@__NO_SIDE_EFFECTS__*/
export function envAsString(
value: unknown,
defaultValueOrOptions: string | EnvAsStringOptions | undefined = '',
): string {
// Accept bare string OR any non-options value as positional default for
// legacy compat (`envAsString(null, 123)` coerces to '123'). Options form
// is detected by plain-object shape with known keys.
const isOptionsObject =
typeof defaultValueOrOptions === 'object' &&
defaultValueOrOptions !== null &&
!ArrayIsArray(defaultValueOrOptions) &&
('defaultValue' in defaultValueOrOptions || 'trim' in defaultValueOrOptions)
// Defensive default-value coercion arms; tests pass strings or
// options objects.
/* c8 ignore start */
const opts: EnvAsStringOptions = isOptionsObject
? (defaultValueOrOptions as EnvAsStringOptions)
: {
defaultValue:
defaultValueOrOptions === undefined
? ''
: typeof defaultValueOrOptions === 'string'
? defaultValueOrOptions
: StringCtor(defaultValueOrOptions),
}
/* c8 ignore stop */
const { defaultValue = '', trim = true } = opts
if (value === undefined || value === null) {
return defaultValue === '' || !trim
? defaultValue
: StringCtor(defaultValue).trim()
}
if (typeof value === 'string') {
return trim ? value.trim() : value
}
// Non-string coercion path; tests pass strings.
/* c8 ignore next 2 */
const str = StringCtor(value)
return trim ? str.trim() : str
}