@karmaniverous/get-dotenv 4.5.2 → 5.0.0-0
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/LICENSE +28 -0
- package/README.md +369 -215
- package/dist/cliHost.cjs +1078 -0
- package/dist/cliHost.d.cts +193 -0
- package/dist/cliHost.d.mts +193 -0
- package/dist/cliHost.d.ts +193 -0
- package/dist/cliHost.mjs +1074 -0
- package/dist/config.cjs +247 -0
- package/dist/config.d.cts +53 -0
- package/dist/config.d.mts +53 -0
- package/dist/config.d.ts +53 -0
- package/dist/config.mjs +242 -0
- package/dist/env-overlay.cjs +163 -0
- package/dist/env-overlay.d.cts +50 -0
- package/dist/env-overlay.d.mts +50 -0
- package/dist/env-overlay.d.ts +50 -0
- package/dist/env-overlay.mjs +161 -0
- package/dist/getdotenv.cli.mjs +2817 -40874
- package/dist/index.cjs +1482 -40965
- package/dist/index.d.cts +206 -67
- package/dist/index.d.mts +206 -67
- package/dist/index.d.ts +206 -67
- package/dist/index.mjs +1454 -40939
- package/dist/plugins-aws.cjs +618 -0
- package/dist/plugins-aws.d.cts +178 -0
- package/dist/plugins-aws.d.mts +178 -0
- package/dist/plugins-aws.d.ts +178 -0
- package/dist/plugins-aws.mjs +616 -0
- package/dist/plugins-batch.cjs +569 -0
- package/dist/plugins-batch.d.cts +200 -0
- package/dist/plugins-batch.d.mts +200 -0
- package/dist/plugins-batch.d.ts +200 -0
- package/dist/plugins-batch.mjs +567 -0
- package/dist/plugins-init.cjs +282 -0
- package/dist/plugins-init.d.cts +182 -0
- package/dist/plugins-init.d.mts +182 -0
- package/dist/plugins-init.d.ts +182 -0
- package/dist/plugins-init.mjs +280 -0
- package/getdotenv.config.json +19 -0
- package/package.json +228 -139
- package/templates/cli/ts/index.ts +9 -0
- package/templates/cli/ts/plugins/hello.ts +17 -0
- package/templates/config/js/getdotenv.config.js +15 -0
- package/templates/config/json/local/getdotenv.config.local.json +7 -0
- package/templates/config/json/public/getdotenv.config.json +12 -0
- package/templates/config/public/getdotenv.config.json +13 -0
- package/templates/config/ts/getdotenv.config.ts +16 -0
- package/templates/config/yaml/local/getdotenv.config.local.yaml +7 -0
- package/templates/config/yaml/public/getdotenv.config.yaml +10 -0
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Dotenv expansion utilities.
|
|
5
|
+
*
|
|
6
|
+
* This module implements recursive expansion of environment-variable
|
|
7
|
+
* references in strings and records. It supports both whitespace and
|
|
8
|
+
* bracket syntaxes with optional defaults:
|
|
9
|
+
*
|
|
10
|
+
* - Whitespace: `$VAR[:default]`
|
|
11
|
+
* - Bracketed: `${VAR[:default]}`
|
|
12
|
+
*
|
|
13
|
+
* Escaped dollar signs (`\$`) are preserved.
|
|
14
|
+
* Unknown variables resolve to empty string unless a default is provided.
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* Like String.prototype.search but returns the last index.
|
|
18
|
+
* @internal
|
|
19
|
+
*/
|
|
20
|
+
const searchLast = (str, rgx) => {
|
|
21
|
+
const matches = Array.from(str.matchAll(rgx));
|
|
22
|
+
return matches.length > 0 ? (matches.slice(-1)[0]?.index ?? -1) : -1;
|
|
23
|
+
};
|
|
24
|
+
const replaceMatch = (value, match, ref) => {
|
|
25
|
+
/**
|
|
26
|
+
* @internal
|
|
27
|
+
*/
|
|
28
|
+
const group = match[0];
|
|
29
|
+
const key = match[1];
|
|
30
|
+
const defaultValue = match[2];
|
|
31
|
+
if (!key)
|
|
32
|
+
return value;
|
|
33
|
+
const replacement = value.replace(group, ref[key] ?? defaultValue ?? '');
|
|
34
|
+
return interpolate(replacement, ref);
|
|
35
|
+
};
|
|
36
|
+
const interpolate = (value = '', ref = {}) => {
|
|
37
|
+
/**
|
|
38
|
+
* @internal
|
|
39
|
+
*/
|
|
40
|
+
// if value is falsy, return it as is
|
|
41
|
+
if (!value)
|
|
42
|
+
return value;
|
|
43
|
+
// get position of last unescaped dollar sign
|
|
44
|
+
const lastUnescapedDollarSignIndex = searchLast(value, /(?!(?<=\\))\$/g);
|
|
45
|
+
// return value if none found
|
|
46
|
+
if (lastUnescapedDollarSignIndex === -1)
|
|
47
|
+
return value;
|
|
48
|
+
// evaluate the value tail
|
|
49
|
+
const tail = value.slice(lastUnescapedDollarSignIndex);
|
|
50
|
+
// find whitespace pattern: $KEY:DEFAULT
|
|
51
|
+
const whitespacePattern = /^\$([\w]+)(?::([^\s]*))?/;
|
|
52
|
+
const whitespaceMatch = whitespacePattern.exec(tail);
|
|
53
|
+
if (whitespaceMatch != null)
|
|
54
|
+
return replaceMatch(value, whitespaceMatch, ref);
|
|
55
|
+
else {
|
|
56
|
+
// find bracket pattern: ${KEY:DEFAULT}
|
|
57
|
+
const bracketPattern = /^\${([\w]+)(?::([^}]*))?}/;
|
|
58
|
+
const bracketMatch = bracketPattern.exec(tail);
|
|
59
|
+
if (bracketMatch != null)
|
|
60
|
+
return replaceMatch(value, bracketMatch, ref);
|
|
61
|
+
}
|
|
62
|
+
return value;
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* Recursively expands environment variables in a string. Variables may be
|
|
66
|
+
* presented with optional default as `$VAR[:default]` or `${VAR[:default]}`.
|
|
67
|
+
* Unknown variables will expand to an empty string.
|
|
68
|
+
*
|
|
69
|
+
* @param value - The string to expand.
|
|
70
|
+
* @param ref - The reference object to use for variable expansion.
|
|
71
|
+
* @returns The expanded string.
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* ```ts
|
|
75
|
+
* process.env.FOO = 'bar';
|
|
76
|
+
* dotenvExpand('Hello $FOO'); // "Hello bar"
|
|
77
|
+
* dotenvExpand('Hello $BAZ:world'); // "Hello world"
|
|
78
|
+
* ```
|
|
79
|
+
*
|
|
80
|
+
* @remarks
|
|
81
|
+
* The expansion is recursive. If a referenced variable itself contains
|
|
82
|
+
* references, those will also be expanded until a stable value is reached.
|
|
83
|
+
* Escaped references (e.g. `\$FOO`) are preserved as literals.
|
|
84
|
+
*/
|
|
85
|
+
const dotenvExpand = (value, ref = process.env) => {
|
|
86
|
+
const result = interpolate(value, ref);
|
|
87
|
+
return result ? result.replace(/\\\$/g, '$') : undefined;
|
|
88
|
+
};
|
|
89
|
+
/**
|
|
90
|
+
* Recursively expands environment variables in the values of a JSON object.
|
|
91
|
+
* Variables may be presented with optional default as `$VAR[:default]` or
|
|
92
|
+
* `${VAR[:default]}`. Unknown variables will expand to an empty string.
|
|
93
|
+
*
|
|
94
|
+
* @param values - The values object to expand.
|
|
95
|
+
* @param options - Expansion options.
|
|
96
|
+
* @returns The value object with expanded string values.
|
|
97
|
+
*
|
|
98
|
+
* @example
|
|
99
|
+
* ```ts
|
|
100
|
+
* process.env.FOO = 'bar';
|
|
101
|
+
* dotenvExpandAll({ A: '$FOO', B: 'x${FOO}y' });
|
|
102
|
+
* // => { A: "bar", B: "xbary" }
|
|
103
|
+
* ```
|
|
104
|
+
*
|
|
105
|
+
* @remarks
|
|
106
|
+
* Options:
|
|
107
|
+
* - ref: The reference object to use for expansion (defaults to process.env).
|
|
108
|
+
* - progressive: Whether to progressively add expanded values to the set of
|
|
109
|
+
* reference keys.
|
|
110
|
+
*
|
|
111
|
+
* When `progressive` is true, each expanded key becomes available for
|
|
112
|
+
* subsequent expansions in the same object (left-to-right by object key order).
|
|
113
|
+
*/
|
|
114
|
+
const dotenvExpandAll = (values = {}, options = {}) => Object.keys(values).reduce((acc, key) => {
|
|
115
|
+
const { ref = process.env, progressive = false } = options;
|
|
116
|
+
acc[key] = dotenvExpand(values[key], {
|
|
117
|
+
...ref,
|
|
118
|
+
...(progressive ? acc : {}),
|
|
119
|
+
});
|
|
120
|
+
return acc;
|
|
121
|
+
}, {});
|
|
122
|
+
|
|
123
|
+
const applyKv = (current, kv) => {
|
|
124
|
+
if (!kv || Object.keys(kv).length === 0)
|
|
125
|
+
return current;
|
|
126
|
+
const expanded = dotenvExpandAll(kv, { ref: current, progressive: true });
|
|
127
|
+
return { ...current, ...expanded };
|
|
128
|
+
};
|
|
129
|
+
const applyConfigSlice = (current, cfg, env) => {
|
|
130
|
+
if (!cfg)
|
|
131
|
+
return current;
|
|
132
|
+
// kind axis: global then env (env overrides global)
|
|
133
|
+
const afterGlobal = applyKv(current, cfg.vars);
|
|
134
|
+
const envKv = env && cfg.envVars ? cfg.envVars[env] : undefined;
|
|
135
|
+
return applyKv(afterGlobal, envKv);
|
|
136
|
+
};
|
|
137
|
+
/**
|
|
138
|
+
* Overlay config-provided values onto a base ProcessEnv using precedence axes:
|
|
139
|
+
* - kind: env \> global
|
|
140
|
+
* - privacy: local \> public
|
|
141
|
+
* - source: project \> packaged \> base
|
|
142
|
+
*
|
|
143
|
+
* Programmatic explicit vars (if provided) override all config slices.
|
|
144
|
+
* Progressive expansion is applied within each slice.
|
|
145
|
+
*/
|
|
146
|
+
const overlayEnv = ({ base, env, configs, programmaticVars, }) => {
|
|
147
|
+
let current = { ...base };
|
|
148
|
+
// Source: packaged (public -> local)
|
|
149
|
+
current = applyConfigSlice(current, configs.packaged, env);
|
|
150
|
+
// Packaged "local" is not expected by policy; if present, honor it.
|
|
151
|
+
// We do not have a separate object for packaged.local in sources, keep as-is.
|
|
152
|
+
// Source: project (public -> local)
|
|
153
|
+
current = applyConfigSlice(current, configs.project?.public, env);
|
|
154
|
+
current = applyConfigSlice(current, configs.project?.local, env);
|
|
155
|
+
// Programmatic explicit vars (top of static tier)
|
|
156
|
+
if (programmaticVars) {
|
|
157
|
+
const toApply = Object.fromEntries(Object.entries(programmaticVars).filter(([_k, v]) => typeof v === 'string'));
|
|
158
|
+
current = applyKv(current, toApply);
|
|
159
|
+
}
|
|
160
|
+
return current;
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
exports.overlayEnv = overlayEnv;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A minimal representation of an environment key/value mapping.
|
|
3
|
+
* Values may be `undefined` to represent "unset".
|
|
4
|
+
*/
|
|
5
|
+
type ProcessEnv = Record<string, string | undefined>;
|
|
6
|
+
|
|
7
|
+
type Scripts = Record<string, string | {
|
|
8
|
+
cmd: string;
|
|
9
|
+
shell?: string | boolean;
|
|
10
|
+
}>;
|
|
11
|
+
|
|
12
|
+
type GetDotenvConfigResolved = {
|
|
13
|
+
dotenvToken?: string;
|
|
14
|
+
privateToken?: string;
|
|
15
|
+
paths?: string[];
|
|
16
|
+
loadProcess?: boolean;
|
|
17
|
+
log?: boolean;
|
|
18
|
+
shell?: string | boolean;
|
|
19
|
+
scripts?: Scripts;
|
|
20
|
+
vars?: Record<string, string>;
|
|
21
|
+
envVars?: Record<string, Record<string, string>>;
|
|
22
|
+
dynamic?: unknown;
|
|
23
|
+
plugins?: Record<string, unknown>;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
type OverlayConfigSources = {
|
|
27
|
+
packaged?: GetDotenvConfigResolved;
|
|
28
|
+
project?: {
|
|
29
|
+
public?: GetDotenvConfigResolved;
|
|
30
|
+
local?: GetDotenvConfigResolved;
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Overlay config-provided values onto a base ProcessEnv using precedence axes:
|
|
35
|
+
* - kind: env \> global
|
|
36
|
+
* - privacy: local \> public
|
|
37
|
+
* - source: project \> packaged \> base
|
|
38
|
+
*
|
|
39
|
+
* Programmatic explicit vars (if provided) override all config slices.
|
|
40
|
+
* Progressive expansion is applied within each slice.
|
|
41
|
+
*/
|
|
42
|
+
declare const overlayEnv: ({ base, env, configs, programmaticVars, }: {
|
|
43
|
+
base: ProcessEnv;
|
|
44
|
+
env: string | undefined;
|
|
45
|
+
configs: OverlayConfigSources;
|
|
46
|
+
programmaticVars?: ProcessEnv;
|
|
47
|
+
}) => ProcessEnv;
|
|
48
|
+
|
|
49
|
+
export { overlayEnv };
|
|
50
|
+
export type { OverlayConfigSources };
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A minimal representation of an environment key/value mapping.
|
|
3
|
+
* Values may be `undefined` to represent "unset".
|
|
4
|
+
*/
|
|
5
|
+
type ProcessEnv = Record<string, string | undefined>;
|
|
6
|
+
|
|
7
|
+
type Scripts = Record<string, string | {
|
|
8
|
+
cmd: string;
|
|
9
|
+
shell?: string | boolean;
|
|
10
|
+
}>;
|
|
11
|
+
|
|
12
|
+
type GetDotenvConfigResolved = {
|
|
13
|
+
dotenvToken?: string;
|
|
14
|
+
privateToken?: string;
|
|
15
|
+
paths?: string[];
|
|
16
|
+
loadProcess?: boolean;
|
|
17
|
+
log?: boolean;
|
|
18
|
+
shell?: string | boolean;
|
|
19
|
+
scripts?: Scripts;
|
|
20
|
+
vars?: Record<string, string>;
|
|
21
|
+
envVars?: Record<string, Record<string, string>>;
|
|
22
|
+
dynamic?: unknown;
|
|
23
|
+
plugins?: Record<string, unknown>;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
type OverlayConfigSources = {
|
|
27
|
+
packaged?: GetDotenvConfigResolved;
|
|
28
|
+
project?: {
|
|
29
|
+
public?: GetDotenvConfigResolved;
|
|
30
|
+
local?: GetDotenvConfigResolved;
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Overlay config-provided values onto a base ProcessEnv using precedence axes:
|
|
35
|
+
* - kind: env \> global
|
|
36
|
+
* - privacy: local \> public
|
|
37
|
+
* - source: project \> packaged \> base
|
|
38
|
+
*
|
|
39
|
+
* Programmatic explicit vars (if provided) override all config slices.
|
|
40
|
+
* Progressive expansion is applied within each slice.
|
|
41
|
+
*/
|
|
42
|
+
declare const overlayEnv: ({ base, env, configs, programmaticVars, }: {
|
|
43
|
+
base: ProcessEnv;
|
|
44
|
+
env: string | undefined;
|
|
45
|
+
configs: OverlayConfigSources;
|
|
46
|
+
programmaticVars?: ProcessEnv;
|
|
47
|
+
}) => ProcessEnv;
|
|
48
|
+
|
|
49
|
+
export { overlayEnv };
|
|
50
|
+
export type { OverlayConfigSources };
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A minimal representation of an environment key/value mapping.
|
|
3
|
+
* Values may be `undefined` to represent "unset".
|
|
4
|
+
*/
|
|
5
|
+
type ProcessEnv = Record<string, string | undefined>;
|
|
6
|
+
|
|
7
|
+
type Scripts = Record<string, string | {
|
|
8
|
+
cmd: string;
|
|
9
|
+
shell?: string | boolean;
|
|
10
|
+
}>;
|
|
11
|
+
|
|
12
|
+
type GetDotenvConfigResolved = {
|
|
13
|
+
dotenvToken?: string;
|
|
14
|
+
privateToken?: string;
|
|
15
|
+
paths?: string[];
|
|
16
|
+
loadProcess?: boolean;
|
|
17
|
+
log?: boolean;
|
|
18
|
+
shell?: string | boolean;
|
|
19
|
+
scripts?: Scripts;
|
|
20
|
+
vars?: Record<string, string>;
|
|
21
|
+
envVars?: Record<string, Record<string, string>>;
|
|
22
|
+
dynamic?: unknown;
|
|
23
|
+
plugins?: Record<string, unknown>;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
type OverlayConfigSources = {
|
|
27
|
+
packaged?: GetDotenvConfigResolved;
|
|
28
|
+
project?: {
|
|
29
|
+
public?: GetDotenvConfigResolved;
|
|
30
|
+
local?: GetDotenvConfigResolved;
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Overlay config-provided values onto a base ProcessEnv using precedence axes:
|
|
35
|
+
* - kind: env \> global
|
|
36
|
+
* - privacy: local \> public
|
|
37
|
+
* - source: project \> packaged \> base
|
|
38
|
+
*
|
|
39
|
+
* Programmatic explicit vars (if provided) override all config slices.
|
|
40
|
+
* Progressive expansion is applied within each slice.
|
|
41
|
+
*/
|
|
42
|
+
declare const overlayEnv: ({ base, env, configs, programmaticVars, }: {
|
|
43
|
+
base: ProcessEnv;
|
|
44
|
+
env: string | undefined;
|
|
45
|
+
configs: OverlayConfigSources;
|
|
46
|
+
programmaticVars?: ProcessEnv;
|
|
47
|
+
}) => ProcessEnv;
|
|
48
|
+
|
|
49
|
+
export { overlayEnv };
|
|
50
|
+
export type { OverlayConfigSources };
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dotenv expansion utilities.
|
|
3
|
+
*
|
|
4
|
+
* This module implements recursive expansion of environment-variable
|
|
5
|
+
* references in strings and records. It supports both whitespace and
|
|
6
|
+
* bracket syntaxes with optional defaults:
|
|
7
|
+
*
|
|
8
|
+
* - Whitespace: `$VAR[:default]`
|
|
9
|
+
* - Bracketed: `${VAR[:default]}`
|
|
10
|
+
*
|
|
11
|
+
* Escaped dollar signs (`\$`) are preserved.
|
|
12
|
+
* Unknown variables resolve to empty string unless a default is provided.
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* Like String.prototype.search but returns the last index.
|
|
16
|
+
* @internal
|
|
17
|
+
*/
|
|
18
|
+
const searchLast = (str, rgx) => {
|
|
19
|
+
const matches = Array.from(str.matchAll(rgx));
|
|
20
|
+
return matches.length > 0 ? (matches.slice(-1)[0]?.index ?? -1) : -1;
|
|
21
|
+
};
|
|
22
|
+
const replaceMatch = (value, match, ref) => {
|
|
23
|
+
/**
|
|
24
|
+
* @internal
|
|
25
|
+
*/
|
|
26
|
+
const group = match[0];
|
|
27
|
+
const key = match[1];
|
|
28
|
+
const defaultValue = match[2];
|
|
29
|
+
if (!key)
|
|
30
|
+
return value;
|
|
31
|
+
const replacement = value.replace(group, ref[key] ?? defaultValue ?? '');
|
|
32
|
+
return interpolate(replacement, ref);
|
|
33
|
+
};
|
|
34
|
+
const interpolate = (value = '', ref = {}) => {
|
|
35
|
+
/**
|
|
36
|
+
* @internal
|
|
37
|
+
*/
|
|
38
|
+
// if value is falsy, return it as is
|
|
39
|
+
if (!value)
|
|
40
|
+
return value;
|
|
41
|
+
// get position of last unescaped dollar sign
|
|
42
|
+
const lastUnescapedDollarSignIndex = searchLast(value, /(?!(?<=\\))\$/g);
|
|
43
|
+
// return value if none found
|
|
44
|
+
if (lastUnescapedDollarSignIndex === -1)
|
|
45
|
+
return value;
|
|
46
|
+
// evaluate the value tail
|
|
47
|
+
const tail = value.slice(lastUnescapedDollarSignIndex);
|
|
48
|
+
// find whitespace pattern: $KEY:DEFAULT
|
|
49
|
+
const whitespacePattern = /^\$([\w]+)(?::([^\s]*))?/;
|
|
50
|
+
const whitespaceMatch = whitespacePattern.exec(tail);
|
|
51
|
+
if (whitespaceMatch != null)
|
|
52
|
+
return replaceMatch(value, whitespaceMatch, ref);
|
|
53
|
+
else {
|
|
54
|
+
// find bracket pattern: ${KEY:DEFAULT}
|
|
55
|
+
const bracketPattern = /^\${([\w]+)(?::([^}]*))?}/;
|
|
56
|
+
const bracketMatch = bracketPattern.exec(tail);
|
|
57
|
+
if (bracketMatch != null)
|
|
58
|
+
return replaceMatch(value, bracketMatch, ref);
|
|
59
|
+
}
|
|
60
|
+
return value;
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* Recursively expands environment variables in a string. Variables may be
|
|
64
|
+
* presented with optional default as `$VAR[:default]` or `${VAR[:default]}`.
|
|
65
|
+
* Unknown variables will expand to an empty string.
|
|
66
|
+
*
|
|
67
|
+
* @param value - The string to expand.
|
|
68
|
+
* @param ref - The reference object to use for variable expansion.
|
|
69
|
+
* @returns The expanded string.
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* ```ts
|
|
73
|
+
* process.env.FOO = 'bar';
|
|
74
|
+
* dotenvExpand('Hello $FOO'); // "Hello bar"
|
|
75
|
+
* dotenvExpand('Hello $BAZ:world'); // "Hello world"
|
|
76
|
+
* ```
|
|
77
|
+
*
|
|
78
|
+
* @remarks
|
|
79
|
+
* The expansion is recursive. If a referenced variable itself contains
|
|
80
|
+
* references, those will also be expanded until a stable value is reached.
|
|
81
|
+
* Escaped references (e.g. `\$FOO`) are preserved as literals.
|
|
82
|
+
*/
|
|
83
|
+
const dotenvExpand = (value, ref = process.env) => {
|
|
84
|
+
const result = interpolate(value, ref);
|
|
85
|
+
return result ? result.replace(/\\\$/g, '$') : undefined;
|
|
86
|
+
};
|
|
87
|
+
/**
|
|
88
|
+
* Recursively expands environment variables in the values of a JSON object.
|
|
89
|
+
* Variables may be presented with optional default as `$VAR[:default]` or
|
|
90
|
+
* `${VAR[:default]}`. Unknown variables will expand to an empty string.
|
|
91
|
+
*
|
|
92
|
+
* @param values - The values object to expand.
|
|
93
|
+
* @param options - Expansion options.
|
|
94
|
+
* @returns The value object with expanded string values.
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
* ```ts
|
|
98
|
+
* process.env.FOO = 'bar';
|
|
99
|
+
* dotenvExpandAll({ A: '$FOO', B: 'x${FOO}y' });
|
|
100
|
+
* // => { A: "bar", B: "xbary" }
|
|
101
|
+
* ```
|
|
102
|
+
*
|
|
103
|
+
* @remarks
|
|
104
|
+
* Options:
|
|
105
|
+
* - ref: The reference object to use for expansion (defaults to process.env).
|
|
106
|
+
* - progressive: Whether to progressively add expanded values to the set of
|
|
107
|
+
* reference keys.
|
|
108
|
+
*
|
|
109
|
+
* When `progressive` is true, each expanded key becomes available for
|
|
110
|
+
* subsequent expansions in the same object (left-to-right by object key order).
|
|
111
|
+
*/
|
|
112
|
+
const dotenvExpandAll = (values = {}, options = {}) => Object.keys(values).reduce((acc, key) => {
|
|
113
|
+
const { ref = process.env, progressive = false } = options;
|
|
114
|
+
acc[key] = dotenvExpand(values[key], {
|
|
115
|
+
...ref,
|
|
116
|
+
...(progressive ? acc : {}),
|
|
117
|
+
});
|
|
118
|
+
return acc;
|
|
119
|
+
}, {});
|
|
120
|
+
|
|
121
|
+
const applyKv = (current, kv) => {
|
|
122
|
+
if (!kv || Object.keys(kv).length === 0)
|
|
123
|
+
return current;
|
|
124
|
+
const expanded = dotenvExpandAll(kv, { ref: current, progressive: true });
|
|
125
|
+
return { ...current, ...expanded };
|
|
126
|
+
};
|
|
127
|
+
const applyConfigSlice = (current, cfg, env) => {
|
|
128
|
+
if (!cfg)
|
|
129
|
+
return current;
|
|
130
|
+
// kind axis: global then env (env overrides global)
|
|
131
|
+
const afterGlobal = applyKv(current, cfg.vars);
|
|
132
|
+
const envKv = env && cfg.envVars ? cfg.envVars[env] : undefined;
|
|
133
|
+
return applyKv(afterGlobal, envKv);
|
|
134
|
+
};
|
|
135
|
+
/**
|
|
136
|
+
* Overlay config-provided values onto a base ProcessEnv using precedence axes:
|
|
137
|
+
* - kind: env \> global
|
|
138
|
+
* - privacy: local \> public
|
|
139
|
+
* - source: project \> packaged \> base
|
|
140
|
+
*
|
|
141
|
+
* Programmatic explicit vars (if provided) override all config slices.
|
|
142
|
+
* Progressive expansion is applied within each slice.
|
|
143
|
+
*/
|
|
144
|
+
const overlayEnv = ({ base, env, configs, programmaticVars, }) => {
|
|
145
|
+
let current = { ...base };
|
|
146
|
+
// Source: packaged (public -> local)
|
|
147
|
+
current = applyConfigSlice(current, configs.packaged, env);
|
|
148
|
+
// Packaged "local" is not expected by policy; if present, honor it.
|
|
149
|
+
// We do not have a separate object for packaged.local in sources, keep as-is.
|
|
150
|
+
// Source: project (public -> local)
|
|
151
|
+
current = applyConfigSlice(current, configs.project?.public, env);
|
|
152
|
+
current = applyConfigSlice(current, configs.project?.local, env);
|
|
153
|
+
// Programmatic explicit vars (top of static tier)
|
|
154
|
+
if (programmaticVars) {
|
|
155
|
+
const toApply = Object.fromEntries(Object.entries(programmaticVars).filter(([_k, v]) => typeof v === 'string'));
|
|
156
|
+
current = applyKv(current, toApply);
|
|
157
|
+
}
|
|
158
|
+
return current;
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
export { overlayEnv };
|