@karmaniverous/get-dotenv 6.0.0-1 → 6.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/README.md +91 -379
- package/dist/cli.d.ts +569 -0
- package/dist/cli.mjs +18788 -0
- package/dist/cliHost.d.ts +515 -184
- package/dist/cliHost.mjs +1931 -1428
- package/dist/config.d.ts +187 -14
- package/dist/config.mjs +256 -81
- package/dist/env-overlay.d.ts +212 -16
- package/dist/env-overlay.mjs +168 -4
- package/dist/getdotenv.cli.mjs +18227 -3487
- package/dist/index.d.ts +541 -260
- package/dist/index.mjs +18294 -3556
- package/dist/plugins-aws.d.ts +221 -91
- package/dist/plugins-aws.mjs +2360 -361
- package/dist/plugins-batch.d.ts +300 -103
- package/dist/plugins-batch.mjs +2519 -484
- package/dist/plugins-cmd.d.ts +229 -106
- package/dist/plugins-cmd.mjs +2480 -793
- package/dist/plugins-init.d.ts +221 -95
- package/dist/plugins-init.mjs +2102 -104
- package/dist/plugins.d.ts +246 -125
- package/dist/plugins.mjs +17861 -1973
- package/dist/templates/cli/index.ts +26 -0
- package/{templates/cli/ts → dist/templates/cli}/plugins/hello.ts +11 -6
- package/dist/templates/config/js/getdotenv.config.js +20 -0
- package/dist/templates/config/json/local/getdotenv.config.local.json +7 -0
- package/dist/templates/config/json/public/getdotenv.config.json +9 -0
- package/dist/templates/config/public/getdotenv.config.json +8 -0
- package/dist/templates/config/ts/getdotenv.config.ts +28 -0
- package/dist/templates/config/yaml/local/getdotenv.config.local.yaml +7 -0
- package/dist/templates/config/yaml/public/getdotenv.config.yaml +7 -0
- package/dist/templates/getdotenv.config.js +20 -0
- package/dist/templates/getdotenv.config.json +9 -0
- package/dist/templates/getdotenv.config.local.json +7 -0
- package/dist/templates/getdotenv.config.local.yaml +7 -0
- package/dist/templates/getdotenv.config.ts +28 -0
- package/dist/templates/getdotenv.config.yaml +7 -0
- package/dist/templates/hello.ts +43 -0
- package/dist/templates/index.ts +26 -0
- package/dist/templates/js/getdotenv.config.js +20 -0
- package/dist/templates/json/local/getdotenv.config.local.json +7 -0
- package/dist/templates/json/public/getdotenv.config.json +9 -0
- package/dist/templates/local/getdotenv.config.local.json +7 -0
- package/dist/templates/local/getdotenv.config.local.yaml +7 -0
- package/dist/templates/plugins/hello.ts +43 -0
- package/dist/templates/public/getdotenv.config.json +9 -0
- package/dist/templates/public/getdotenv.config.yaml +7 -0
- package/dist/templates/ts/getdotenv.config.ts +28 -0
- package/dist/templates/yaml/local/getdotenv.config.local.yaml +7 -0
- package/dist/templates/yaml/public/getdotenv.config.yaml +7 -0
- package/getdotenv.config.json +1 -19
- package/package.json +42 -39
- package/templates/cli/index.ts +26 -0
- package/templates/cli/plugins/hello.ts +43 -0
- package/templates/config/js/getdotenv.config.js +8 -3
- package/templates/config/json/public/getdotenv.config.json +0 -3
- package/templates/config/public/getdotenv.config.json +0 -5
- package/templates/config/ts/getdotenv.config.ts +9 -4
- package/templates/config/yaml/public/getdotenv.config.yaml +0 -3
- package/dist/plugins-demo.d.ts +0 -204
- package/dist/plugins-demo.mjs +0 -496
- package/templates/cli/ts/index.ts +0 -9
package/dist/env-overlay.d.ts
CHANGED
|
@@ -1,42 +1,238 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Minimal root options shape shared by CLI and generator layers.
|
|
3
|
+
* Keep keys optional to respect exactOptionalPropertyTypes semantics.
|
|
4
|
+
*
|
|
5
|
+
* @public
|
|
6
|
+
*/
|
|
7
|
+
interface RootOptionsShape {
|
|
8
|
+
/** Target environment (dotenv-expanded). */
|
|
9
|
+
env?: string;
|
|
10
|
+
/** Explicit variable overrides (dotenv-expanded). */
|
|
11
|
+
vars?: string;
|
|
12
|
+
/** Command to execute (dotenv-expanded). */
|
|
13
|
+
command?: string;
|
|
14
|
+
/** Output path for the consolidated environment file (dotenv-expanded). */
|
|
15
|
+
outputPath?: string;
|
|
16
|
+
/**
|
|
17
|
+
* Shell execution strategy.
|
|
18
|
+
* - `true`: use default OS shell.
|
|
19
|
+
* - `false`: use plain execution (no shell).
|
|
20
|
+
* - string: use specific shell path.
|
|
21
|
+
*/
|
|
22
|
+
shell?: string | boolean;
|
|
23
|
+
/** Whether to load variables into `process.env`. */
|
|
24
|
+
loadProcess?: boolean;
|
|
25
|
+
/** Exclude all variables from loading. */
|
|
26
|
+
excludeAll?: boolean;
|
|
27
|
+
/** Exclude dynamic variables. */
|
|
28
|
+
excludeDynamic?: boolean;
|
|
29
|
+
/** Exclude environment-specific variables. */
|
|
30
|
+
excludeEnv?: boolean;
|
|
31
|
+
/** Exclude global variables. */
|
|
32
|
+
excludeGlobal?: boolean;
|
|
33
|
+
/** Exclude private variables. */
|
|
34
|
+
excludePrivate?: boolean;
|
|
35
|
+
/** Exclude public variables. */
|
|
36
|
+
excludePublic?: boolean;
|
|
37
|
+
/** Enable console logging of loaded variables. */
|
|
38
|
+
log?: boolean;
|
|
39
|
+
/** Enable debug logging to stderr. */
|
|
40
|
+
debug?: boolean;
|
|
41
|
+
/** Capture child process stdio (useful for tests/CI). */
|
|
42
|
+
capture?: boolean;
|
|
43
|
+
/** Fail on validation errors (schema/requiredKeys). */
|
|
44
|
+
strict?: boolean;
|
|
45
|
+
/** Enable presentation-time redaction of secret-like keys. */
|
|
46
|
+
redact?: boolean;
|
|
47
|
+
/** Enable entropy warnings for high-entropy values. */
|
|
48
|
+
warnEntropy?: boolean;
|
|
49
|
+
/** Entropy threshold (bits/char) for warnings (default 3.8). */
|
|
50
|
+
entropyThreshold?: number;
|
|
51
|
+
/** Minimum string length to check for entropy (default 16). */
|
|
52
|
+
entropyMinLength?: number;
|
|
53
|
+
/** Regex patterns for keys to exclude from entropy checks. */
|
|
54
|
+
entropyWhitelist?: ReadonlyArray<string>;
|
|
55
|
+
/** Additional regex patterns for keys to redact. */
|
|
56
|
+
redactPatterns?: string[];
|
|
57
|
+
/** Default target environment when not specified. */
|
|
58
|
+
defaultEnv?: string;
|
|
59
|
+
/** Token indicating a dotenv file (default: ".env"). */
|
|
60
|
+
dotenvToken?: string;
|
|
61
|
+
/** Path to dynamic variables module (default: undefined). */
|
|
62
|
+
dynamicPath?: string;
|
|
63
|
+
/**
|
|
64
|
+
* Emit diagnostics for child env composition.
|
|
65
|
+
* - `true`: trace all keys.
|
|
66
|
+
* - `string[]`: trace selected keys.
|
|
67
|
+
*/
|
|
68
|
+
trace?: boolean | string[];
|
|
69
|
+
/** Paths to search for dotenv files (space-delimited string or array). */
|
|
70
|
+
paths?: string;
|
|
71
|
+
/** Delimiter for paths string (default: space). */
|
|
72
|
+
pathsDelimiter?: string;
|
|
73
|
+
/** Regex pattern for paths delimiter. */
|
|
74
|
+
pathsDelimiterPattern?: string;
|
|
75
|
+
/** Token indicating private variables (default: "local"). */
|
|
76
|
+
privateToken?: string;
|
|
77
|
+
/** Delimiter for vars string (default: space). */
|
|
78
|
+
varsDelimiter?: string;
|
|
79
|
+
/** Regex pattern for vars delimiter. */
|
|
80
|
+
varsDelimiterPattern?: string;
|
|
81
|
+
/** Assignment operator for vars (default: "="). */
|
|
82
|
+
varsAssignor?: string;
|
|
83
|
+
/** Regex pattern for vars assignment operator. */
|
|
84
|
+
varsAssignorPattern?: string;
|
|
85
|
+
/** Table of named scripts for execution. */
|
|
86
|
+
scripts?: ScriptsTable;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Definition for a single script entry.
|
|
3
90
|
*/
|
|
4
|
-
|
|
91
|
+
interface ScriptDef<TShell extends string | boolean = string | boolean> {
|
|
92
|
+
/** The command string to execute. */
|
|
5
93
|
cmd: string;
|
|
94
|
+
/** Shell override for this script. */
|
|
6
95
|
shell?: TShell | undefined;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Scripts table shape.
|
|
99
|
+
*/
|
|
100
|
+
type ScriptsTable<TShell extends string | boolean = string | boolean> = Record<string, string | ScriptDef<TShell>>;
|
|
10
101
|
|
|
11
102
|
/**
|
|
12
|
-
*
|
|
13
|
-
* Values may be `undefined` to represent "unset".
|
|
103
|
+
* Unify Scripts via the generic ScriptsTable<TShell> so shell types propagate.
|
|
14
104
|
*/
|
|
15
|
-
type
|
|
105
|
+
type Scripts = ScriptsTable;
|
|
16
106
|
|
|
17
107
|
type GetDotenvConfigResolved = {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
108
|
+
/**
|
|
109
|
+
* Help-time/runtime root defaults applied by the host (collapsed families; CLI‑like).
|
|
110
|
+
*/
|
|
111
|
+
rootOptionDefaults?: Partial<RootOptionsShape>;
|
|
112
|
+
/**
|
|
113
|
+
* Help-time visibility for root flags; when a key is false the corresponding
|
|
114
|
+
* option(s) are hidden in root help output.
|
|
115
|
+
*/
|
|
116
|
+
rootOptionVisibility?: Partial<Record<keyof RootOptionsShape, boolean>>;
|
|
117
|
+
/**
|
|
118
|
+
* Merged scripts table for resolving commands and shell behavior.
|
|
119
|
+
* Entries may be strings or objects with `cmd` and optional `shell`.
|
|
120
|
+
*/
|
|
24
121
|
scripts?: Scripts;
|
|
122
|
+
/**
|
|
123
|
+
* Keys required to be present in the final composed environment.
|
|
124
|
+
* Validation occurs after overlays and dynamics.
|
|
125
|
+
*/
|
|
25
126
|
requiredKeys?: string[];
|
|
127
|
+
/**
|
|
128
|
+
* Optional validation schema (e.g., Zod). When present and it exposes
|
|
129
|
+
* `safeParse(finalEnv)`, the host executes it once after overlays.
|
|
130
|
+
*/
|
|
26
131
|
schema?: unknown;
|
|
132
|
+
/**
|
|
133
|
+
* Public global variables (string‑only).
|
|
134
|
+
*/
|
|
27
135
|
vars?: Record<string, string>;
|
|
136
|
+
/**
|
|
137
|
+
* Public per‑environment variables (string‑only).
|
|
138
|
+
*/
|
|
28
139
|
envVars?: Record<string, Record<string, string>>;
|
|
140
|
+
/**
|
|
141
|
+
* Dynamic variable definitions (JS/TS configs only).
|
|
142
|
+
*/
|
|
29
143
|
dynamic?: unknown;
|
|
144
|
+
/**
|
|
145
|
+
* Per‑plugin configuration slices keyed by realized mount path
|
|
146
|
+
* (for example, "aws/whoami").
|
|
147
|
+
*/
|
|
30
148
|
plugins?: Record<string, unknown>;
|
|
31
149
|
};
|
|
32
150
|
|
|
151
|
+
/**
|
|
152
|
+
* Canonical programmatic options and helpers for get-dotenv.
|
|
153
|
+
*
|
|
154
|
+
* Requirements addressed:
|
|
155
|
+
* - GetDotenvOptions derives from the Zod schema output (single source of truth).
|
|
156
|
+
* - Removed deprecated/compat flags from the public shape (e.g., useConfigLoader).
|
|
157
|
+
* - Provide Vars-aware defineDynamic and a typed config builder defineGetDotenvConfig\<Vars, Env\>().
|
|
158
|
+
* - Preserve existing behavior for defaults resolution and compat converters.
|
|
159
|
+
*/
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* A minimal representation of an environment key/value mapping.
|
|
163
|
+
* Values may be `undefined` to represent "unset".
|
|
164
|
+
*/
|
|
165
|
+
type ProcessEnv = Record<string, string | undefined>;
|
|
166
|
+
/**
|
|
167
|
+
* Dynamic variable function signature. Receives the current expanded variables
|
|
168
|
+
* and the selected environment (if any), and returns either a string to set
|
|
169
|
+
* or `undefined` to unset/skip the variable.
|
|
170
|
+
*/
|
|
171
|
+
type GetDotenvDynamicFunction = (vars: ProcessEnv, env: string | undefined) => string | undefined;
|
|
172
|
+
/**
|
|
173
|
+
* A map of dynamic variable definitions.
|
|
174
|
+
* Keys are variable names; values are either literal strings or functions.
|
|
175
|
+
*/
|
|
176
|
+
type GetDotenvDynamic = Record<string, GetDotenvDynamicFunction | ReturnType<GetDotenvDynamicFunction>>;
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Apply a dynamic map to the target progressively.
|
|
180
|
+
* - Functions receive (target, env) and may return string | undefined.
|
|
181
|
+
* - Literals are assigned directly (including undefined).
|
|
182
|
+
*/
|
|
183
|
+
declare function applyDynamicMap(target: ProcessEnv, map?: GetDotenvDynamic, env?: string): void;
|
|
184
|
+
/**
|
|
185
|
+
* Load a default-export dynamic map from a JS/TS file and apply it.
|
|
186
|
+
* Uses util/loadModuleDefault for robust TS handling (direct import, esbuild,
|
|
187
|
+
* typescript.transpile fallback).
|
|
188
|
+
*
|
|
189
|
+
* Error behavior:
|
|
190
|
+
* - On failure to load/compile/evaluate the module, throws a unified message:
|
|
191
|
+
* "Unable to load dynamic TypeScript file: <absPath>. Install 'esbuild'..."
|
|
192
|
+
*/
|
|
193
|
+
declare function loadAndApplyDynamic(target: ProcessEnv, absPath: string, env: string | undefined, cacheDirName: string): Promise<void>;
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Configuration sources for environment overlay.
|
|
197
|
+
* Organized by scope (packaged vs project) and privacy (public vs local).
|
|
198
|
+
*
|
|
199
|
+
* @public
|
|
200
|
+
*/
|
|
33
201
|
type OverlayConfigSources = {
|
|
202
|
+
/** Packaged configuration (public). */
|
|
34
203
|
packaged?: GetDotenvConfigResolved;
|
|
204
|
+
/** Project configuration (public and local). */
|
|
35
205
|
project?: {
|
|
206
|
+
/** Project public configuration. */
|
|
36
207
|
public?: GetDotenvConfigResolved;
|
|
208
|
+
/** Project local configuration. */
|
|
37
209
|
local?: GetDotenvConfigResolved;
|
|
38
210
|
};
|
|
39
211
|
};
|
|
212
|
+
/**
|
|
213
|
+
* Base options for overlaying config-provided values onto a dotenv map.
|
|
214
|
+
*
|
|
215
|
+
* @typeParam B - base env shape
|
|
216
|
+
* @public
|
|
217
|
+
*/
|
|
218
|
+
interface OverlayEnvOptionsBase<B extends Record<string, string | undefined> | Readonly<Record<string, string | undefined>>> {
|
|
219
|
+
/** Base environment variables. */
|
|
220
|
+
base: B;
|
|
221
|
+
/** Target environment name. */
|
|
222
|
+
env: string | undefined;
|
|
223
|
+
/** Configuration sources to overlay. */
|
|
224
|
+
configs: OverlayConfigSources;
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Options including explicit programmatic variables which take top precedence.
|
|
228
|
+
*
|
|
229
|
+
* @typeParam B - base env shape
|
|
230
|
+
* @typeParam P - programmatic vars shape
|
|
231
|
+
* @public
|
|
232
|
+
*/
|
|
233
|
+
interface OverlayEnvOptionsWithProgrammatic<B extends Record<string, string | undefined> | Readonly<Record<string, string | undefined>>, P extends Record<string, string | undefined> | Readonly<Record<string, string | undefined>>> extends OverlayEnvOptionsBase<B> {
|
|
234
|
+
programmaticVars: P;
|
|
235
|
+
}
|
|
40
236
|
/**
|
|
41
237
|
* Overlay config-provided values onto a base ProcessEnv using precedence axes:
|
|
42
238
|
* - kind: env \> global
|
|
@@ -58,5 +254,5 @@ declare function overlayEnv<B extends ProcessEnv | Readonly<Record<string, strin
|
|
|
58
254
|
programmaticVars: P;
|
|
59
255
|
}): B & P;
|
|
60
256
|
|
|
61
|
-
export { overlayEnv };
|
|
62
|
-
export type { OverlayConfigSources };
|
|
257
|
+
export { applyDynamicMap, loadAndApplyDynamic, overlayEnv };
|
|
258
|
+
export type { OverlayConfigSources, OverlayEnvOptionsBase, OverlayEnvOptionsWithProgrammatic };
|
package/dist/env-overlay.mjs
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
import fs from 'fs-extra';
|
|
2
|
+
import { createHash } from 'crypto';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import url from 'url';
|
|
5
|
+
|
|
1
6
|
/**
|
|
2
7
|
* Dotenv expansion utilities.
|
|
3
8
|
*
|
|
@@ -122,6 +127,164 @@ function dotenvExpandAll(values, options = {}) {
|
|
|
122
127
|
return out;
|
|
123
128
|
}
|
|
124
129
|
|
|
130
|
+
const importDefault = async (fileUrl) => {
|
|
131
|
+
const mod = (await import(fileUrl));
|
|
132
|
+
return mod.default;
|
|
133
|
+
};
|
|
134
|
+
const cacheHash = (absPath, mtimeMs) => createHash('sha1')
|
|
135
|
+
.update(absPath)
|
|
136
|
+
.update(String(mtimeMs))
|
|
137
|
+
.digest('hex')
|
|
138
|
+
.slice(0, 12);
|
|
139
|
+
/**
|
|
140
|
+
* Remove older compiled cache files for a given source base name, keeping
|
|
141
|
+
* at most `keep` most-recent files. Errors are ignored by design.
|
|
142
|
+
*/
|
|
143
|
+
const cleanupOldCacheFiles = async (cacheDir, baseName, keep = Math.max(1, Number.parseInt(process.env.GETDOTENV_CACHE_KEEP ?? '2'))) => {
|
|
144
|
+
try {
|
|
145
|
+
const entries = await fs.readdir(cacheDir);
|
|
146
|
+
const mine = entries
|
|
147
|
+
.filter((f) => f.startsWith(`${baseName}.`) && f.endsWith('.mjs'))
|
|
148
|
+
.map((f) => path.join(cacheDir, f));
|
|
149
|
+
if (mine.length <= keep)
|
|
150
|
+
return;
|
|
151
|
+
const stats = await Promise.all(mine.map(async (p) => ({ p, mtimeMs: (await fs.stat(p)).mtimeMs })));
|
|
152
|
+
stats.sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
153
|
+
const toDelete = stats.slice(keep).map((s) => s.p);
|
|
154
|
+
await Promise.all(toDelete.map(async (p) => {
|
|
155
|
+
try {
|
|
156
|
+
await fs.remove(p);
|
|
157
|
+
}
|
|
158
|
+
catch {
|
|
159
|
+
// best-effort cleanup
|
|
160
|
+
}
|
|
161
|
+
}));
|
|
162
|
+
}
|
|
163
|
+
catch {
|
|
164
|
+
// best-effort cleanup
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
/**
|
|
168
|
+
* Load a module default export from a JS/TS file with robust fallbacks:
|
|
169
|
+
* - .js/.mjs/.cjs: direct import * - .ts/.mts/.cts/.tsx:
|
|
170
|
+
* 1) try direct import (if a TS loader is active),
|
|
171
|
+
* 2) esbuild bundle to a temp ESM file,
|
|
172
|
+
* 3) typescript.transpileModule fallback for simple modules.
|
|
173
|
+
*
|
|
174
|
+
* @param absPath - absolute path to source file
|
|
175
|
+
* @param cacheDirName - cache subfolder under .tsbuild
|
|
176
|
+
*/
|
|
177
|
+
const loadModuleDefault = async (absPath, cacheDirName) => {
|
|
178
|
+
const ext = path.extname(absPath).toLowerCase();
|
|
179
|
+
const fileUrl = url.pathToFileURL(absPath).toString();
|
|
180
|
+
if (!['.ts', '.mts', '.cts', '.tsx'].includes(ext)) {
|
|
181
|
+
return importDefault(fileUrl);
|
|
182
|
+
}
|
|
183
|
+
// Try direct import first (TS loader active)
|
|
184
|
+
try {
|
|
185
|
+
const dyn = await importDefault(fileUrl);
|
|
186
|
+
if (dyn)
|
|
187
|
+
return dyn;
|
|
188
|
+
}
|
|
189
|
+
catch {
|
|
190
|
+
/* fall through */
|
|
191
|
+
}
|
|
192
|
+
const stat = await fs.stat(absPath);
|
|
193
|
+
const hash = cacheHash(absPath, stat.mtimeMs);
|
|
194
|
+
const cacheDir = path.resolve('.tsbuild', cacheDirName);
|
|
195
|
+
await fs.ensureDir(cacheDir);
|
|
196
|
+
const cacheFile = path.join(cacheDir, `${path.basename(absPath)}.${hash}.mjs`);
|
|
197
|
+
// Try esbuild
|
|
198
|
+
try {
|
|
199
|
+
const esbuild = (await import('esbuild'));
|
|
200
|
+
await esbuild.build({
|
|
201
|
+
entryPoints: [absPath],
|
|
202
|
+
bundle: true,
|
|
203
|
+
platform: 'node',
|
|
204
|
+
format: 'esm',
|
|
205
|
+
target: 'node20',
|
|
206
|
+
outfile: cacheFile,
|
|
207
|
+
sourcemap: false,
|
|
208
|
+
logLevel: 'silent',
|
|
209
|
+
});
|
|
210
|
+
const result = await importDefault(url.pathToFileURL(cacheFile).toString());
|
|
211
|
+
// Best-effort: trim older cache files for this source.
|
|
212
|
+
await cleanupOldCacheFiles(cacheDir, path.basename(absPath));
|
|
213
|
+
return result;
|
|
214
|
+
}
|
|
215
|
+
catch {
|
|
216
|
+
/* fall through to TS transpile */
|
|
217
|
+
}
|
|
218
|
+
// TypeScript transpile fallback
|
|
219
|
+
try {
|
|
220
|
+
const ts = (await import('typescript'));
|
|
221
|
+
const code = await fs.readFile(absPath, 'utf-8');
|
|
222
|
+
const out = ts.transpileModule(code, {
|
|
223
|
+
compilerOptions: {
|
|
224
|
+
module: 'ESNext',
|
|
225
|
+
target: 'ES2022',
|
|
226
|
+
moduleResolution: 'NodeNext',
|
|
227
|
+
},
|
|
228
|
+
}).outputText;
|
|
229
|
+
await fs.writeFile(cacheFile, out, 'utf-8');
|
|
230
|
+
const result = await importDefault(url.pathToFileURL(cacheFile).toString());
|
|
231
|
+
// Best-effort: trim older cache files for this source.
|
|
232
|
+
await cleanupOldCacheFiles(cacheDir, path.basename(absPath));
|
|
233
|
+
return result;
|
|
234
|
+
}
|
|
235
|
+
catch {
|
|
236
|
+
// Caller decides final error wording; rethrow for upstream mapping.
|
|
237
|
+
throw new Error(`Unable to load JS/TS module: ${absPath}. Install 'esbuild' or ensure a TS loader.`);
|
|
238
|
+
}
|
|
239
|
+
};
|
|
240
|
+
|
|
241
|
+
/** src/env/dynamic.ts
|
|
242
|
+
* Helpers for applying and loading dynamic variables (JS/TS).
|
|
243
|
+
*
|
|
244
|
+
* Requirements addressed:
|
|
245
|
+
* - Single service to apply a dynamic map progressively.
|
|
246
|
+
* - Single service to load a JS/TS dynamic module with robust fallbacks (util/loadModuleDefault).
|
|
247
|
+
* - Unify error messaging so callers show consistent guidance.
|
|
248
|
+
*/
|
|
249
|
+
/**
|
|
250
|
+
* Apply a dynamic map to the target progressively.
|
|
251
|
+
* - Functions receive (target, env) and may return string | undefined.
|
|
252
|
+
* - Literals are assigned directly (including undefined).
|
|
253
|
+
*/
|
|
254
|
+
function applyDynamicMap(target, map, env) {
|
|
255
|
+
if (!map)
|
|
256
|
+
return;
|
|
257
|
+
for (const key of Object.keys(map)) {
|
|
258
|
+
const val = typeof map[key] === 'function'
|
|
259
|
+
? map[key](target, env)
|
|
260
|
+
: map[key];
|
|
261
|
+
Object.assign(target, { [key]: val });
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Load a default-export dynamic map from a JS/TS file and apply it.
|
|
266
|
+
* Uses util/loadModuleDefault for robust TS handling (direct import, esbuild,
|
|
267
|
+
* typescript.transpile fallback).
|
|
268
|
+
*
|
|
269
|
+
* Error behavior:
|
|
270
|
+
* - On failure to load/compile/evaluate the module, throws a unified message:
|
|
271
|
+
* "Unable to load dynamic TypeScript file: <absPath>. Install 'esbuild'..."
|
|
272
|
+
*/
|
|
273
|
+
async function loadAndApplyDynamic(target, absPath, env, cacheDirName) {
|
|
274
|
+
if (!(await fs.exists(absPath)))
|
|
275
|
+
return;
|
|
276
|
+
let dyn;
|
|
277
|
+
try {
|
|
278
|
+
dyn = await loadModuleDefault(absPath, cacheDirName);
|
|
279
|
+
}
|
|
280
|
+
catch {
|
|
281
|
+
// Preserve legacy/clear guidance used by tests and docs.
|
|
282
|
+
throw new Error(`Unable to load dynamic TypeScript file: ${absPath}. ` +
|
|
283
|
+
`Install 'esbuild' (devDependency) to enable TypeScript dynamic modules.`);
|
|
284
|
+
}
|
|
285
|
+
applyDynamicMap(target, dyn, env);
|
|
286
|
+
}
|
|
287
|
+
|
|
125
288
|
const applyKv = (current, kv) => {
|
|
126
289
|
if (!kv || Object.keys(kv).length === 0)
|
|
127
290
|
return current;
|
|
@@ -136,7 +299,8 @@ const applyConfigSlice = (current, cfg, env) => {
|
|
|
136
299
|
const envKv = env && cfg.envVars ? cfg.envVars[env] : undefined;
|
|
137
300
|
return applyKv(afterGlobal, envKv);
|
|
138
301
|
};
|
|
139
|
-
function overlayEnv(
|
|
302
|
+
function overlayEnv(args) {
|
|
303
|
+
const { base, env, configs } = args;
|
|
140
304
|
let current = { ...base };
|
|
141
305
|
// Source: packaged (public -> local)
|
|
142
306
|
current = applyConfigSlice(current, configs.packaged, env);
|
|
@@ -146,11 +310,11 @@ function overlayEnv({ base, env, configs, programmaticVars, }) {
|
|
|
146
310
|
current = applyConfigSlice(current, configs.project?.public, env);
|
|
147
311
|
current = applyConfigSlice(current, configs.project?.local, env);
|
|
148
312
|
// Programmatic explicit vars (top of static tier)
|
|
149
|
-
if (programmaticVars) {
|
|
150
|
-
const toApply = Object.fromEntries(Object.entries(programmaticVars).filter(([_k, v]) => typeof v === 'string'));
|
|
313
|
+
if ('programmaticVars' in args) {
|
|
314
|
+
const toApply = Object.fromEntries(Object.entries(args.programmaticVars).filter(([_k, v]) => typeof v === 'string'));
|
|
151
315
|
current = applyKv(current, toApply);
|
|
152
316
|
}
|
|
153
317
|
return current;
|
|
154
318
|
}
|
|
155
319
|
|
|
156
|
-
export { overlayEnv };
|
|
320
|
+
export { applyDynamicMap, loadAndApplyDynamic, overlayEnv };
|