@calvear/env 3.2.0 → 3.4.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/CHANGELOG.md CHANGED
@@ -2,6 +2,27 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## [3.4.0] - 2026-07-08
6
+
7
+ ### Added
8
+
9
+ - **environment inference from npm scripts**: when `-e` is not provided (neither by CLI nor config file), the environment is inferred from the npm script name (`npm_lifecycle_event`), taking the last segment after `:` — `start:dev` → `dev`. Per-env scripts no longer need to repeat `-e`: `"start:dev": "env -m debug : vite"`. Scripts without a `:` suffix and direct CLI invocations are unaffected. The inferred value is validated against the environments defined in the workspace, discovered dynamically as the union of the `|ENV|`/`|LOCAL|` section keys of `appsettings.json` and the per-env provider files (`appsettings.<env>[.local].json` / `<env>[.local].env.json`)
10
+
11
+ ### Changed
12
+
13
+ - **unknown inferred environment aborts**: if the environment inferred from the script name is not defined in the workspace, the command exits with an error listing the defined ones (catches typos like `start:prd`). Scripts with a non-env `:` suffix (i.e. `test:mutation`) that omit `-e` in a workspace with defined environments must now pass `-e` explicitly. When the workspace has no defined environments, inference is skipped and behavior is unchanged
14
+ - **unknown explicit environment warns**: passing `-e <env>` with an environment that is not defined now logs a warning (execution continues as before)
15
+
16
+ ## [3.3.0] - 2026-07-08
17
+
18
+ ### Changed
19
+
20
+ - **`app-settings` local layers now always win**: the merge order of the `app-settings` provider is now `flat root` < `|DEFAULT|` < `|ENV|` < `|MODE|` < `appsettings.<env>.json` < `appsettings.<mode>.json` < `|LOCAL|` < `appsettings.<env>.local.json`. Previously the unitary files were merged after every section (with `appsettings.<mode>.json` highest), so a committed `appsettings.<env|mode>.json` could override the `|LOCAL|` section and `appsettings.<env>.local.json` — contradicting the library-wide "local wins" principle (`package-json` < `app-settings` < `secrets` < `local`). Only setups that overlap keys between unitary files and local layers are affected.
21
+
22
+ ### Added
23
+
24
+ - precedence documented in README: the `app-settings` section now lists the full 8-layer section/file precedence, and the "Priority" section documents the complete provider chain (`NODE_ENV` base < `package-json` < `app-settings` < `secrets` < `local`) plus the fact that resolved variables override the inherited `process.env` of the child process
25
+
5
26
  ## [3.1.0] - 2026-06-02
6
27
 
7
28
  ### Added
package/README.md CHANGED
@@ -200,6 +200,45 @@ Run it:
200
200
 
201
201
  See [🙈 Masking secrets](#-masking-secrets) for the full masking semantics.
202
202
 
203
+ ### 🔮 Environment inference from npm scripts
204
+
205
+ When `-e` is not provided (neither by CLI nor config file), the CLI infers the
206
+ environment from the **npm script name** (`npm_lifecycle_event`), taking the
207
+ last segment after `:` — running `npm run start:dev` infers `dev`, so the
208
+ `-e` flag becomes redundant in per-env scripts:
209
+
210
+ ```jsonc
211
+ {
212
+ "scripts": {
213
+ "start:dev": "env -m debug : node dist/main.js", // infers "dev"
214
+ "start:qa": "env -m debug : node dist/main.js", // infers "qa"
215
+ "start:prod": "env -m debug : node dist/main.js", // infers "prod"
216
+ },
217
+ }
218
+ ```
219
+
220
+ The inferred value is validated against the environments **defined** in the
221
+ workspace, discovered dynamically as the union of:
222
+
223
+ - the `|ENV|` and `|LOCAL|` section keys of `appsettings.json`,
224
+ - per-env provider files in the root folder (`appsettings.<env>.json`,
225
+ `appsettings.<env>.local.json`, `<env>.env.json`, `<env>.local.env.json`).
226
+
227
+ Validation rules:
228
+
229
+ - **inferred** env unknown → the command **aborts** listing the defined
230
+ environments (catches typos like `start:prd`);
231
+ - **explicit** `-e` unknown → only a **warning**;
232
+ - no defined environments → inference is skipped silently;
233
+ - scripts without a `:` suffix (i.e. `preview`) and direct CLI invocations
234
+ are unaffected.
235
+
236
+ Scripts whose suffix is **not** an environment (i.e. `test:mutation`,
237
+ `env:schema`) must keep an explicit `-e`.
238
+
239
+ > `[[env]]` inside `--configFile` cannot reference an inferred environment —
240
+ > the config file is loaded **before** inference runs.
241
+
203
242
  ---
204
243
 
205
244
  ### `env`
@@ -304,20 +343,36 @@ Non-secret loader for `appsettings.json`, organized by sections:
304
343
  ```jsonc
305
344
  {
306
345
  "|DEFAULT|": { "VAR1": "v1_default" },
307
- "|MODE|": {
308
- "build": { "NODE_ENV": "production" },
309
- "debug": { "NODE_ENV": "development" },
310
- },
311
346
  "|ENV|": {
312
347
  "dev": {
313
348
  "C1": "V1",
314
349
  "GROUP1": { "VAR2": "G1V2", "GROUP2": { "VAR1": "G1G2V1" } },
315
350
  },
316
351
  },
352
+ "|MODE|": {
353
+ "build": { "NODE_ENV": "production" },
354
+ "debug": { "NODE_ENV": "development" },
355
+ },
317
356
  "|LOCAL|": { "dev": { "LOCAL_VAR": "only-local" } },
318
357
  }
319
358
  ```
320
359
 
360
+ It also merges the unitary files `appsettings.<env>.json`,
361
+ `appsettings.<mode>.json` and `appsettings.<env>.local.json`.
362
+
363
+ #### Precedence (lowest → highest)
364
+
365
+ 1. flat root object (only when no `|...|` section is present)
366
+ 2. `|DEFAULT|`
367
+ 3. `|ENV|` for the current `--env`
368
+ 4. `|MODE|` for each `--modes` entry (later modes win)
369
+ 5. `appsettings.<env>.json`
370
+ 6. `appsettings.<mode>.json` (one per mode, in `--modes` order)
371
+ 7. `|LOCAL|` for the current `--env`
372
+ 8. `appsettings.<env>.local.json`
373
+
374
+ Local layers (7 and 8) always win, and both are skipped in `--ci`.
375
+
321
376
  | Option | Description | Type | Default |
322
377
  | ----------------- | ----------------------------- | -------- | --------------------------- |
323
378
  | `--ef, --envFile` | Non-secret settings file path | `string` | `[[root]]/appsettings.json` |
@@ -493,10 +548,17 @@ process.env.GROUP1__VAR; // "anyValue"
493
548
 
494
549
  ### Priority (lowest → highest)
495
550
 
496
- 1. `package-json` info
497
- 2. `appsettings.json` (`app-settings`)
498
- 3. `<env>.env.json` (`secrets`)
499
- 4. `<env>.local.env.json` (`local`, skipped in `--ci`)
551
+ Providers are merged in declaration order — with the default `providers` list:
552
+
553
+ 1. `NODE_ENV=development` (built-in base value)
554
+ 2. `package-json` info
555
+ 3. `appsettings.json` (`app-settings` — see the
556
+ [app-settings precedence](#precedence-lowest--highest) above)
557
+ 4. `<env>.env.json` (`secrets`)
558
+ 5. `<env>.local.env.json` (`local`, skipped in `--ci` — overrides everything)
559
+
560
+ > The resolved variables are written into the child process `process.env`, so
561
+ > they override any variables inherited from the parent shell.
500
562
 
501
563
  <p align="right">(<a href="#top">back to top</a>)</p>
502
564
 
package/exec.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"exec.d.ts","sourceRoot":"","sources":["../src/exec.ts"],"names":[],"mappings":"AAoFA;;;;;;GAMG;AACH,wBAAsB,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,iBA2D3C"}
1
+ {"version":3,"file":"exec.d.ts","sourceRoot":"","sources":["../src/exec.ts"],"names":[],"mappings":"AAqFA;;;;;;GAMG;AACH,wBAAsB,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,iBAgE3C"}
package/exec.js CHANGED
@@ -1,25 +1,26 @@
1
1
  import { getSubcommand as e, loadConfigFile as t, loadProjectInfo as n, loadSchemaFile as r } from "./utils/command.util.js";
2
- import { interpolateJson as i } from "./utils/interpolate.util.js";
3
- import { resolvePath as a } from "./utils/json.util.js";
4
- import { configureLogger as o, logger as s } from "./utils/logger.js";
5
- import { ui as c } from "./utils/ui.js";
2
+ import { resolveEnv as i } from "./utils/infer-env.util.js";
3
+ import { interpolateJson as a } from "./utils/interpolate.util.js";
4
+ import { resolvePath as o } from "./utils/json.util.js";
5
+ import { configureLogger as s, logger as c } from "./utils/logger.js";
6
+ import { ui as l } from "./utils/ui.js";
6
7
  import "./utils/index.js";
7
- import { IntegratedProviders as l } from "./providers/index.js";
8
- import { args as u } from "./arguments.js";
9
- import { envCommand as d } from "./commands/env.command.js";
10
- import { exportCommand as f } from "./commands/export.command.js";
11
- import { pullCommand as p } from "./commands/pull.command.js";
12
- import { pushCommand as m } from "./commands/push.command.js";
13
- import { schemaCommand as h } from "./commands/schema.command.js";
8
+ import { IntegratedProviders as u } from "./providers/index.js";
9
+ import { args as d } from "./arguments.js";
10
+ import { envCommand as f } from "./commands/env.command.js";
11
+ import { exportCommand as p } from "./commands/export.command.js";
12
+ import { pullCommand as m } from "./commands/pull.command.js";
13
+ import { pushCommand as h } from "./commands/push.command.js";
14
+ import { schemaCommand as g } from "./commands/schema.command.js";
14
15
  import "./commands/index.js";
15
- import g from "picocolors";
16
- import { readFileSync as _ } from "node:fs";
17
- import { fileURLToPath as v } from "node:url";
18
- import y from "yargs";
19
- import { Parser as b } from "yargs/helpers";
16
+ import _ from "picocolors";
17
+ import { readFileSync as v } from "node:fs";
18
+ import { fileURLToPath as y } from "node:url";
19
+ import b from "yargs";
20
+ import { Parser as x } from "yargs/helpers";
20
21
  //#region src/exec.ts
21
- async function x(e, n, r) {
22
- let i = b.detailed(e, {
22
+ async function S(e, n, r) {
23
+ let i = x.detailed(e, {
23
24
  array: [
24
25
  "modes",
25
26
  "logMaskAnyRegEx",
@@ -35,63 +36,65 @@ async function x(e, n, r) {
35
36
  "logLevel"
36
37
  ],
37
38
  alias: {
38
- configFile: u.configFile.alias,
39
- env: u.env.alias,
40
- logLevel: u.logLevel.alias,
41
- logMaskAnyRegEx: u.logMaskAnyRegEx.alias,
42
- logMaskValuesOfKeys: u.logMaskValuesOfKeys.alias,
43
- modes: u.modes.alias
39
+ configFile: d.configFile.alias,
40
+ env: d.env.alias,
41
+ logLevel: d.logLevel.alias,
42
+ logMaskAnyRegEx: d.logMaskAnyRegEx.alias,
43
+ logMaskValuesOfKeys: d.logMaskValuesOfKeys.alias,
44
+ modes: d.modes.alias
44
45
  },
45
46
  default: {
46
- configFile: u.configFile.default,
47
- root: u.root.default
47
+ configFile: d.configFile.default,
48
+ root: d.root.default
48
49
  }
49
50
  }).argv;
50
- await t(i, r), i.logLevel ??= u.logLevel.default, i.logMaskAnyRegEx ??= u.logMaskAnyRegEx.default, i.logMaskValuesOfKeys ??= u.logMaskValuesOfKeys.default, i.providers ??= u.providers.default;
51
- let { logLevel: a, logMaskAnyRegEx: c, logMaskValuesOfKeys: l } = i;
52
- return o(s, {
53
- maskAnyRegEx: c,
51
+ await t(i, r), i.logLevel ??= d.logLevel.default, i.logMaskAnyRegEx ??= d.logMaskAnyRegEx.default, i.logMaskValuesOfKeys ??= d.logMaskValuesOfKeys.default, i.providers ??= d.providers.default;
52
+ let { logLevel: a, logMaskAnyRegEx: o, logMaskValuesOfKeys: l } = i;
53
+ return s(c, {
54
+ maskAnyRegEx: o,
54
55
  maskValuesOfKeys: l,
55
56
  minLevel: a
56
57
  }), i;
57
58
  }
58
- async function S(t) {
59
- let { config: n, version: r } = JSON.parse(_(v(new URL("package.json", "" + import.meta.url)), "utf8")), i = e(t, n.delimiters.subcommand), o = await x(t, n.parser, n.delimiters.template), { env: u, help: d, modes: f, providers: p } = o;
60
- d && C(t, o, i, n, r), (!Array.isArray(p) || p.length === 0) && (s.error("no providers found"), process.exit(1)), c.header(r, u, f);
61
- for (let e of p) try {
62
- if (s.debug(`using ${g.yellow(e.path)} provider`), !e.type || e.type === "integrated") e.handler = l[e.path];
59
+ async function C(t) {
60
+ let { config: n, version: r } = JSON.parse(v(y(new URL("package.json", "" + import.meta.url)), "utf8")), a = e(t, n.delimiters.subcommand), s = await S(t, n.parser, n.delimiters.template);
61
+ s.help || await i(s, n.delimiters.template);
62
+ let { env: d, help: f, modes: p, providers: m } = s;
63
+ f && w(t, s, a, n, r), (!Array.isArray(m) || m.length === 0) && (c.error("no providers found"), process.exit(1)), l.header(r, d, p);
64
+ for (let e of m) try {
65
+ if (c.debug(`using ${_.yellow(e.path)} provider`), !e.type || e.type === "integrated") e.handler = u[e.path];
63
66
  else {
64
- let { default: t } = await (e.type === "module" ? import(e.path) : import(a(e.path)));
67
+ let { default: t } = await (e.type === "module" ? import(e.path) : import(o(e.path)));
65
68
  e.handler = t;
66
69
  }
67
70
  } catch {
68
- s.error(`${g.yellow(e.path)} provider not found or not compatible`), process.exit(1);
71
+ c.error(`${_.yellow(e.path)} provider not found or not compatible`), process.exit(1);
69
72
  }
70
- C(t, o, i, n, r);
73
+ w(t, s, a, n, r);
71
74
  }
72
- function C(e, t, a, o, c = "unknown") {
73
- let l = g.dim(`v${c}`), _ = [
75
+ function w(e, t, i, o, s = "unknown") {
76
+ let l = _.dim(`v${s}`), u = [
74
77
  "",
75
- `${g.bold(g.yellow("⚡ env"))} ${l} ${g.dim("· environment variables made easy")}`,
78
+ `${_.bold(_.yellow("⚡ env"))} ${l} ${_.dim("· environment variables made easy")}`,
76
79
  "",
77
- `${g.bold("Usage:")} $0 [command] [options..] ${g.dim(": <subcmd> :")} [options..]`
78
- ].join("\n"), v = [`${g.dim("Run")} ${g.cyan("env <command> --help")} ${g.dim("for command-specific options.")}`, `${g.dim("Use")} ${g.cyan("--log debug")} ${g.dim("to inspect the resolved environment (secrets stay masked).")}`].join("\n"), b = y(e).strict().scriptName("env").version(c).detectLocale(!1).showHelpOnFail(!1).parserConfiguration(o.parser).wrap(Math.min(110, process.stdout.columns ?? 110)).usage(_).epilog(v).options(u).middleware(async (e) => {
79
- a?.length > 0 && (e.subcmd = a);
80
+ `${_.bold("Usage:")} $0 [command] [options..] ${_.dim(": <subcmd> :")} [options..]`
81
+ ].join("\n"), v = [`${_.dim("Run")} ${_.cyan("env <command> --help")} ${_.dim("for command-specific options.")}`, `${_.dim("Use")} ${_.cyan("--log debug")} ${_.dim("to inspect the resolved environment (secrets stay masked).")}`].join("\n"), y = b(e).strict().scriptName("env").version(s).detectLocale(!1).showHelpOnFail(!1).parserConfiguration(o.parser).wrap(Math.min(110, process.stdout.columns ?? 110)).usage(u).epilog(v).options(d).middleware(async (e) => {
82
+ i?.length > 0 && (e.subcmd = i);
80
83
  for (let n in t) {
81
84
  let r = t[n];
82
85
  typeof e[n] == "boolean" && (r === "true" || r === "false") || (e[n] = r);
83
86
  }
84
- s.silly("interpolating arguments surrounded by", g.bold(g.yellow(`${o.delimiters.template[0]} ${o.delimiters.template[1]}`)));
85
- let c = e.subcmd;
86
- if (i(e, e, o.delimiters.template), Array.isArray(e.subcmd)) for (let t in e.subcmd) e.subcmd[t]?.includes("undefined") && (e.subcmd[t] = c[t]);
87
- s.silly("config loaded:", e), [e.projectInfo, e.schema] = await Promise.all([n(e.packageJson ?? e.pkg), r(e, o.delimiters.template)]), e.schemaValidate && (e.schemaValidate = !!e.schema, e.schemaValidate && s.silly("schema loaded:", e.schema));
87
+ c.silly("interpolating arguments surrounded by", _.bold(_.yellow(`${o.delimiters.template[0]} ${o.delimiters.template[1]}`)));
88
+ let s = e.subcmd;
89
+ if (a(e, e, o.delimiters.template), Array.isArray(e.subcmd)) for (let t in e.subcmd) e.subcmd[t]?.includes("undefined") && (e.subcmd[t] = s[t]);
90
+ c.silly("config loaded:", e), [e.projectInfo, e.schema] = await Promise.all([n(e.packageJson ?? e.pkg), r(e, o.delimiters.template)]), e.schemaValidate && (e.schemaValidate = !!e.schema, e.schemaValidate && c.silly("schema loaded:", e.schema));
88
91
  });
89
- b.command(d), b.command(f), b.command(p), b.command(m), b.command(h);
92
+ y.command(f), y.command(p), y.command(m), y.command(h), y.command(g);
90
93
  let { providers: x } = t;
91
- for (let { handler: e } of x) e?.builder && e.builder(b);
92
- b.parse();
94
+ for (let { handler: e } of x) e?.builder && e.builder(y);
95
+ y.parse();
93
96
  }
94
97
  //#endregion
95
- export { S as exec };
98
+ export { C as exec };
96
99
 
97
100
  //# sourceMappingURL=exec.js.map
package/exec.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"exec.js","names":[],"sources":["../src/exec.ts"],"sourcesContent":["import { readFileSync } from 'node:fs';\r\nimport { fileURLToPath } from 'node:url';\r\nimport pc from 'picocolors';\r\nimport yargs from 'yargs';\r\nimport type { Arguments } from 'yargs';\r\nimport { Parser } from 'yargs/helpers';\r\nimport { args } from './arguments.js';\r\nimport type { CommandArguments } from './arguments.js';\r\nimport {\r\n\tenvCommand,\r\n\texportCommand,\r\n\tpullCommand,\r\n\tpushCommand,\r\n\tschemaCommand,\r\n} from './commands/index.js';\r\nimport { IntegratedProviders } from './providers/index.js';\r\nimport {\r\n\tconfigureLogger,\r\n\tgetSubcommand,\r\n\tinterpolateJson,\r\n\tloadConfigFile,\r\n\tloadProjectInfo,\r\n\tloadSchemaFile,\r\n\tlogger,\r\n\tresolvePath,\r\n\tui,\r\n} from './utils/index.js';\r\n\r\ntype Alias = string[] | string;\r\n\r\n/**\r\n * Preload basic config from command line and config file.\r\n *\r\n * @param {string[]} rawArgv process.argv\r\n * @param {Partial<yargsParser.Configuration>} parser yargs parser config\r\n * @param {[string, string]} delimiters\r\n *\r\n * @returns {Promise<Partial<CommandArguments>>} preloaded config\r\n */\r\nasync function preloadConfig(\r\n\trawArgv: string[],\r\n\tparser: Record<string, unknown>,\r\n\tdelimiters: [string, string],\r\n): Promise<Partial<CommandArguments>> {\r\n\t// preload base config\r\n\tconst preloadedArgv = Parser.detailed(rawArgv, {\r\n\t\tarray: ['modes', 'logMaskAnyRegEx', 'logMaskValuesOfKeys'],\r\n\t\tboolean: ['help'],\r\n\t\tconfiguration: parser as any,\r\n\t\tstring: ['root', 'env', 'configFile', 'schemaFile', 'logLevel'],\r\n\t\talias: {\r\n\t\t\tconfigFile: args.configFile.alias as Alias,\r\n\t\t\tenv: args.env.alias as Alias,\r\n\t\t\tlogLevel: args.logLevel.alias as Alias,\r\n\t\t\tlogMaskAnyRegEx: args.logMaskAnyRegEx.alias as Alias,\r\n\t\t\tlogMaskValuesOfKeys: args.logMaskValuesOfKeys.alias as Alias,\r\n\t\t\tmodes: args.modes.alias as Alias,\r\n\t\t},\r\n\t\tdefault: {\r\n\t\t\tconfigFile: args.configFile.default,\r\n\t\t\troot: args.root.default,\r\n\t\t},\r\n\t}).argv;\r\n\r\n\t// loads configuration file\r\n\tawait loadConfigFile(preloadedArgv, delimiters);\r\n\r\n\tpreloadedArgv.logLevel ??= args.logLevel.default;\r\n\tpreloadedArgv.logMaskAnyRegEx ??= args.logMaskAnyRegEx.default;\r\n\tpreloadedArgv.logMaskValuesOfKeys ??= args.logMaskValuesOfKeys.default;\r\n\tpreloadedArgv.providers ??= args.providers.default;\r\n\r\n\tconst { logLevel, logMaskAnyRegEx, logMaskValuesOfKeys } = preloadedArgv;\r\n\r\n\t// logging level\r\n\tconfigureLogger(logger, {\r\n\t\tmaskAnyRegEx: logMaskAnyRegEx,\r\n\t\tmaskValuesOfKeys: logMaskValuesOfKeys,\r\n\t\tminLevel: logLevel,\r\n\t});\r\n\r\n\treturn preloadedArgv;\r\n}\r\n\r\n/**\r\n * Command preprocessing and lib info\r\n * reading from package.json.\r\n * Preloads config file and setup basic config.\r\n *\r\n * @param {string[]} rawArgv process.argv\r\n */\r\nexport async function exec(rawArgv: string[]) {\r\n\t// reads some lib base config from package.json\r\n\tconst pkg = JSON.parse(\r\n\t\treadFileSync(\r\n\t\t\tfileURLToPath(new URL('package.json', import.meta.url)),\r\n\t\t\t'utf8',\r\n\t\t),\r\n\t) as { config: Record<string, any>; version: string };\r\n\tconst { config, version } = pkg;\r\n\r\n\t// execs yargs\r\n\tconst subcommand = getSubcommand(rawArgv, config.delimiters.subcommand);\r\n\r\n\tconst preloadedArgv = await preloadConfig(\r\n\t\trawArgv,\r\n\t\tconfig.parser,\r\n\t\tconfig.delimiters.template,\r\n\t);\r\n\r\n\tconst { env, help, modes, providers } = preloadedArgv;\r\n\r\n\tif (help) build(rawArgv, preloadedArgv, subcommand, config, version);\r\n\r\n\tif (!Array.isArray(providers) || providers.length === 0) {\r\n\t\tlogger.error('no providers found');\r\n\r\n\t\tprocess.exit(1);\r\n\t}\r\n\r\n\tui.header(version, env, modes);\r\n\r\n\t// read loaders from config\r\n\tfor (const provider of providers!) {\r\n\t\ttry {\r\n\t\t\tlogger.debug(`using ${pc.yellow(provider.path)} provider`);\r\n\r\n\t\t\tif (!provider.type || provider.type === 'integrated') {\r\n\t\t\t\tprovider.handler = IntegratedProviders[provider.path];\r\n\t\t\t} else {\r\n\t\t\t\tconst { default: module } = await import(\r\n\t\t\t\t\tprovider.type === 'module'\r\n\t\t\t\t\t\t? provider.path\r\n\t\t\t\t\t\t: resolvePath(provider.path)\r\n\t\t\t\t);\r\n\r\n\t\t\t\tprovider.handler = module;\r\n\t\t\t}\r\n\t\t} catch {\r\n\t\t\tlogger.error(\r\n\t\t\t\t`${pc.yellow(\r\n\t\t\t\t\tprovider.path,\r\n\t\t\t\t)} provider not found or not compatible`,\r\n\t\t\t);\r\n\r\n\t\t\tprocess.exit(1);\r\n\t\t}\r\n\t}\r\n\r\n\tbuild(rawArgv, preloadedArgv, subcommand, config, version);\r\n}\r\n\r\n/**\r\n * Builds commands and execs Yargs.\r\n *\r\n * @param {string[]} rawArgv process.argv.slice(2)\r\n * @param {Partial<Arguments<CommandArguments>>} preloadedArgv\r\n * @param {string[]} subcommand subcommand for wrap if exists\r\n * @param {Record<string, any>} config lib config from package.json\r\n * @param {string} version lib version from package.json\r\n */\r\nfunction build(\r\n\trawArgv: string[],\r\n\tpreloadedArgv: Partial<Arguments<CommandArguments>>,\r\n\tsubcommand: string[],\r\n\tconfig: Record<string, any>,\r\n\tversion = 'unknown',\r\n): void {\r\n\tconst versionTag = pc.dim(`v${version}`);\r\n\tconst banner = [\r\n\t\t'',\r\n\t\t`${pc.bold(pc.yellow('⚡ env'))} ${versionTag} ${pc.dim('· environment variables made easy')}`,\r\n\t\t'',\r\n\t\t`${pc.bold('Usage:')} $0 [command] [options..] ${pc.dim(': <subcmd> :')} [options..]`,\r\n\t].join('\\n');\r\n\tconst epilog = [\r\n\t\t`${pc.dim('Run')} ${pc.cyan('env <command> --help')} ${pc.dim('for command-specific options.')}`,\r\n\t\t`${pc.dim('Use')} ${pc.cyan('--log debug')} ${pc.dim('to inspect the resolved environment (secrets stay masked).')}`,\r\n\t].join('\\n');\r\n\r\n\tconst builder = yargs(rawArgv)\r\n\t\t.strict()\r\n\t\t.scriptName('env')\r\n\t\t.version(version)\r\n\t\t.detectLocale(false)\r\n\t\t.showHelpOnFail(false)\r\n\t\t.parserConfiguration(config.parser)\r\n\t\t.wrap(Math.min(110, process.stdout.columns ?? 110))\r\n\t\t.usage(banner)\r\n\t\t.epilog(epilog)\r\n\t\t.options(args)\r\n\t\t.middleware(async (argv): Promise<void> => {\r\n\t\t\t// in case of subcommand argument for main\r\n\t\t\tif (subcommand?.length > 0) argv.subcmd = subcommand;\r\n\r\n\t\t\t// merges preloaded args, preserving booleans already\r\n\t\t\t// typed by yargs (preload parser reads them as strings)\r\n\t\t\tfor (const key in preloadedArgv) {\r\n\t\t\t\tconst value = preloadedArgv[key];\r\n\r\n\t\t\t\tif (\r\n\t\t\t\t\ttypeof argv[key] === 'boolean' &&\r\n\t\t\t\t\t(value === 'true' || value === 'false')\r\n\t\t\t\t)\r\n\t\t\t\t\tcontinue;\r\n\r\n\t\t\t\targv[key] = value;\r\n\t\t\t}\r\n\r\n\t\t\tlogger.silly(\r\n\t\t\t\t'interpolating arguments surrounded by',\r\n\t\t\t\tpc.bold(\r\n\t\t\t\t\tpc.yellow(\r\n\t\t\t\t\t\t`${config.delimiters.template[0]} ${config.delimiters.template[1]}`,\r\n\t\t\t\t\t),\r\n\t\t\t\t),\r\n\t\t\t);\r\n\r\n\t\t\tconst subcmdAux = argv.subcmd as string[];\r\n\t\t\t// applies string templating with current vars\r\n\t\t\tinterpolateJson(argv, argv, config.delimiters.template);\r\n\r\n\t\t\tif (Array.isArray(argv.subcmd)) {\r\n\t\t\t\t// fix for argv interpolation pre env interpolation for subcommand\r\n\t\t\t\tfor (const index in argv.subcmd) {\r\n\t\t\t\t\tif (argv.subcmd[index]?.includes('undefined'))\r\n\t\t\t\t\t\targv.subcmd[index] = subcmdAux[index];\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tlogger.silly('config loaded:', argv);\r\n\r\n\t\t\t// loads environment JSON schema if exists\r\n\t\t\t// and current project info from package.json\r\n\t\t\t[argv.projectInfo, argv.schema] = await Promise.all([\r\n\t\t\t\tloadProjectInfo((argv.packageJson ?? argv.pkg) as string),\r\n\t\t\t\tloadSchemaFile(argv, config.delimiters.template),\r\n\t\t\t]);\r\n\r\n\t\t\tif (argv.schemaValidate) {\r\n\t\t\t\targv.schemaValidate = !!argv.schema;\r\n\r\n\t\t\t\tif (argv.schemaValidate)\r\n\t\t\t\t\tlogger.silly('schema loaded:', argv.schema);\r\n\t\t\t}\r\n\t\t});\r\n\r\n\t// integrated commands builder\r\n\tbuilder.command(envCommand);\r\n\tbuilder.command(exportCommand);\r\n\tbuilder.command(pullCommand);\r\n\tbuilder.command(pushCommand);\r\n\tbuilder.command(schemaCommand);\r\n\r\n\tconst { providers } = preloadedArgv;\r\n\r\n\t// extends command from plugins\r\n\tfor (const { handler } of providers!)\r\n\t\tif (handler?.builder) handler.builder(builder);\r\n\r\n\t// executes command processing\r\n\tvoid builder.parse();\r\n}\r\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAuCA,eAAe,EACd,GACA,GACA,GACqC;CAErC,IAAM,IAAgB,EAAO,SAAS,GAAS;EAC9C,OAAO;GAAC;GAAS;GAAmB;EAAqB;EACzD,SAAS,CAAC,MAAM;EAChB,eAAe;EACf,QAAQ;GAAC;GAAQ;GAAO;GAAc;GAAc;EAAU;EAC9D,OAAO;GACN,YAAY,EAAK,WAAW;GAC5B,KAAK,EAAK,IAAI;GACd,UAAU,EAAK,SAAS;GACxB,iBAAiB,EAAK,gBAAgB;GACtC,qBAAqB,EAAK,oBAAoB;GAC9C,OAAO,EAAK,MAAM;EACnB;EACA,SAAS;GACR,YAAY,EAAK,WAAW;GAC5B,MAAM,EAAK,KAAK;EACjB;CACD,CAAC,CAAC,CAAC;CAQH,AALA,MAAM,EAAe,GAAe,CAAU,GAE9C,EAAc,aAAa,EAAK,SAAS,SACzC,EAAc,oBAAoB,EAAK,gBAAgB,SACvD,EAAc,wBAAwB,EAAK,oBAAoB,SAC/D,EAAc,cAAc,EAAK,UAAU;CAE3C,IAAM,EAAE,aAAU,oBAAiB,2BAAwB;CAS3D,OANA,EAAgB,GAAQ;EACvB,cAAc;EACd,kBAAkB;EAClB,UAAU;CACX,CAAC,GAEM;AACR;AASA,eAAsB,EAAK,GAAmB;CAQ7C,IAAM,EAAE,WAAQ,eANJ,KAAK,MAChB,EACC,EAAc,IAAA,IAAA,gBAAA,KAAA,OAAA,KAAA,GAAA,CAAwC,GACtD,MACD,CAE2B,GAGtB,IAAa,EAAc,GAAS,EAAO,WAAW,UAAU,GAEhE,IAAgB,MAAM,EAC3B,GACA,EAAO,QACP,EAAO,WAAW,QACnB,GAEM,EAAE,QAAK,SAAM,UAAO,iBAAc;CAUxC,AARI,KAAM,EAAM,GAAS,GAAe,GAAY,GAAQ,CAAO,IAE/D,CAAC,MAAM,QAAQ,CAAS,KAAK,EAAU,WAAW,OACrD,EAAO,MAAM,oBAAoB,GAEjC,QAAQ,KAAK,CAAC,IAGf,EAAG,OAAO,GAAS,GAAK,CAAK;CAG7B,KAAK,IAAM,KAAY,GACtB,IAAI;EAGH,IAFA,EAAO,MAAM,SAAS,EAAG,OAAO,EAAS,IAAI,EAAE,UAAU,GAErD,CAAC,EAAS,QAAQ,EAAS,SAAS,cACvC,EAAS,UAAU,EAAoB,EAAS;OAC1C;GACN,IAAM,EAAE,SAAS,MAAW,OAC3B,EAAS,SAAS,WAAA,OACf,EAAS,QAAA,OACT,EAAY,EAAS,IAAI;GAG7B,EAAS,UAAU;EACpB;CACD,QAAQ;EAOP,AANA,EAAO,MACN,GAAG,EAAG,OACL,EAAS,IACV,EAAE,sCACH,GAEA,QAAQ,KAAK,CAAC;CACf;CAGD,EAAM,GAAS,GAAe,GAAY,GAAQ,CAAO;AAC1D;AAWA,SAAS,EACR,GACA,GACA,GACA,GACA,IAAU,WACH;CACP,IAAM,IAAa,EAAG,IAAI,IAAI,GAAS,GACjC,IAAS;EACd;EACA,GAAG,EAAG,KAAK,EAAG,OAAO,OAAO,CAAC,EAAE,GAAG,EAAW,IAAI,EAAG,IAAI,mCAAmC;EAC3F;EACA,GAAG,EAAG,KAAK,QAAQ,EAAE,4BAA4B,EAAG,IAAI,cAAc,EAAE;CACzE,CAAC,CAAC,KAAK,IAAI,GACL,IAAS,CACd,GAAG,EAAG,IAAI,KAAK,EAAE,GAAG,EAAG,KAAK,sBAAsB,EAAE,GAAG,EAAG,IAAI,+BAA+B,KAC7F,GAAG,EAAG,IAAI,KAAK,EAAE,GAAG,EAAG,KAAK,aAAa,EAAE,GAAG,EAAG,IAAI,4DAA4D,GAClH,CAAC,CAAC,KAAK,IAAI,GAEL,IAAU,EAAM,CAAO,CAAC,CAC5B,OAAO,CAAC,CACR,WAAW,KAAK,CAAC,CACjB,QAAQ,CAAO,CAAC,CAChB,aAAa,EAAK,CAAC,CACnB,eAAe,EAAK,CAAC,CACrB,oBAAoB,EAAO,MAAM,CAAC,CAClC,KAAK,KAAK,IAAI,KAAK,QAAQ,OAAO,WAAW,GAAG,CAAC,CAAC,CAClD,MAAM,CAAM,CAAC,CACb,OAAO,CAAM,CAAC,CACd,QAAQ,CAAI,CAAC,CACb,WAAW,OAAO,MAAwB;EAE1C,AAAI,GAAY,SAAS,MAAG,EAAK,SAAS;EAI1C,KAAK,IAAM,KAAO,GAAe;GAChC,IAAM,IAAQ,EAAc;GAG3B,OAAO,EAAK,MAAS,cACpB,MAAU,UAAU,MAAU,aAIhC,EAAK,KAAO;EACb;EAEA,EAAO,MACN,yCACA,EAAG,KACF,EAAG,OACF,GAAG,EAAO,WAAW,SAAS,GAAG,GAAG,EAAO,WAAW,SAAS,IAChE,CACD,CACD;EAEA,IAAM,IAAY,EAAK;EAIvB,IAFA,EAAgB,GAAM,GAAM,EAAO,WAAW,QAAQ,GAElD,MAAM,QAAQ,EAAK,MAAM,QAEvB,IAAM,KAAS,EAAK,QACxB,AAAI,EAAK,OAAO,EAAM,EAAE,SAAS,WAAW,MAC3C,EAAK,OAAO,KAAS,EAAU;EAalC,AATA,EAAO,MAAM,kBAAkB,CAAI,GAInC,CAAC,EAAK,aAAa,EAAK,UAAU,MAAM,QAAQ,IAAI,CACnD,EAAiB,EAAK,eAAe,EAAK,GAAc,GACxD,EAAe,GAAM,EAAO,WAAW,QAAQ,CAChD,CAAC,GAEG,EAAK,mBACR,EAAK,iBAAiB,CAAC,CAAC,EAAK,QAEzB,EAAK,kBACR,EAAO,MAAM,kBAAkB,EAAK,MAAM;CAE7C,CAAC;CAOF,AAJA,EAAQ,QAAQ,CAAU,GAC1B,EAAQ,QAAQ,CAAa,GAC7B,EAAQ,QAAQ,CAAW,GAC3B,EAAQ,QAAQ,CAAW,GAC3B,EAAQ,QAAQ,CAAa;CAE7B,IAAM,EAAE,iBAAc;CAGtB,KAAK,IAAM,EAAE,gBAAa,GACzB,AAAI,GAAS,WAAS,EAAQ,QAAQ,CAAO;CAG9C,EAAa,MAAM;AACpB"}
1
+ {"version":3,"file":"exec.js","names":[],"sources":["../src/exec.ts"],"sourcesContent":["import { readFileSync } from 'node:fs';\r\nimport { fileURLToPath } from 'node:url';\r\nimport pc from 'picocolors';\r\nimport yargs from 'yargs';\r\nimport type { Arguments } from 'yargs';\r\nimport { Parser } from 'yargs/helpers';\r\nimport { args } from './arguments.js';\r\nimport type { CommandArguments } from './arguments.js';\r\nimport {\r\n\tenvCommand,\r\n\texportCommand,\r\n\tpullCommand,\r\n\tpushCommand,\r\n\tschemaCommand,\r\n} from './commands/index.js';\r\nimport { IntegratedProviders } from './providers/index.js';\r\nimport {\r\n\tconfigureLogger,\r\n\tgetSubcommand,\r\n\tinterpolateJson,\r\n\tloadConfigFile,\r\n\tloadProjectInfo,\r\n\tloadSchemaFile,\r\n\tlogger,\r\n\tresolveEnv,\r\n\tresolvePath,\r\n\tui,\r\n} from './utils/index.js';\r\n\r\ntype Alias = string[] | string;\r\n\r\n/**\r\n * Preload basic config from command line and config file.\r\n *\r\n * @param {string[]} rawArgv process.argv\r\n * @param {Partial<yargsParser.Configuration>} parser yargs parser config\r\n * @param {[string, string]} delimiters\r\n *\r\n * @returns {Promise<Partial<CommandArguments>>} preloaded config\r\n */\r\nasync function preloadConfig(\r\n\trawArgv: string[],\r\n\tparser: Record<string, unknown>,\r\n\tdelimiters: [string, string],\r\n): Promise<Partial<CommandArguments>> {\r\n\t// preload base config\r\n\tconst preloadedArgv = Parser.detailed(rawArgv, {\r\n\t\tarray: ['modes', 'logMaskAnyRegEx', 'logMaskValuesOfKeys'],\r\n\t\tboolean: ['help'],\r\n\t\tconfiguration: parser as any,\r\n\t\tstring: ['root', 'env', 'configFile', 'schemaFile', 'logLevel'],\r\n\t\talias: {\r\n\t\t\tconfigFile: args.configFile.alias as Alias,\r\n\t\t\tenv: args.env.alias as Alias,\r\n\t\t\tlogLevel: args.logLevel.alias as Alias,\r\n\t\t\tlogMaskAnyRegEx: args.logMaskAnyRegEx.alias as Alias,\r\n\t\t\tlogMaskValuesOfKeys: args.logMaskValuesOfKeys.alias as Alias,\r\n\t\t\tmodes: args.modes.alias as Alias,\r\n\t\t},\r\n\t\tdefault: {\r\n\t\t\tconfigFile: args.configFile.default,\r\n\t\t\troot: args.root.default,\r\n\t\t},\r\n\t}).argv;\r\n\r\n\t// loads configuration file\r\n\tawait loadConfigFile(preloadedArgv, delimiters);\r\n\r\n\tpreloadedArgv.logLevel ??= args.logLevel.default;\r\n\tpreloadedArgv.logMaskAnyRegEx ??= args.logMaskAnyRegEx.default;\r\n\tpreloadedArgv.logMaskValuesOfKeys ??= args.logMaskValuesOfKeys.default;\r\n\tpreloadedArgv.providers ??= args.providers.default;\r\n\r\n\tconst { logLevel, logMaskAnyRegEx, logMaskValuesOfKeys } = preloadedArgv;\r\n\r\n\t// logging level\r\n\tconfigureLogger(logger, {\r\n\t\tmaskAnyRegEx: logMaskAnyRegEx,\r\n\t\tmaskValuesOfKeys: logMaskValuesOfKeys,\r\n\t\tminLevel: logLevel,\r\n\t});\r\n\r\n\treturn preloadedArgv;\r\n}\r\n\r\n/**\r\n * Command preprocessing and lib info\r\n * reading from package.json.\r\n * Preloads config file and setup basic config.\r\n *\r\n * @param {string[]} rawArgv process.argv\r\n */\r\nexport async function exec(rawArgv: string[]) {\r\n\t// reads some lib base config from package.json\r\n\tconst pkg = JSON.parse(\r\n\t\treadFileSync(\r\n\t\t\tfileURLToPath(new URL('package.json', import.meta.url)),\r\n\t\t\t'utf8',\r\n\t\t),\r\n\t) as { config: Record<string, any>; version: string };\r\n\tconst { config, version } = pkg;\r\n\r\n\t// execs yargs\r\n\tconst subcommand = getSubcommand(rawArgv, config.delimiters.subcommand);\r\n\r\n\tconst preloadedArgv = await preloadConfig(\r\n\t\trawArgv,\r\n\t\tconfig.parser,\r\n\t\tconfig.delimiters.template,\r\n\t);\r\n\r\n\t// infers env from npm script name (npm_lifecycle_event) when\r\n\t// not provided by -e nor config file; skipped for --help\r\n\tif (!preloadedArgv.help)\r\n\t\tawait resolveEnv(preloadedArgv, config.delimiters.template);\r\n\r\n\tconst { env, help, modes, providers } = preloadedArgv;\r\n\r\n\tif (help) build(rawArgv, preloadedArgv, subcommand, config, version);\r\n\r\n\tif (!Array.isArray(providers) || providers.length === 0) {\r\n\t\tlogger.error('no providers found');\r\n\r\n\t\tprocess.exit(1);\r\n\t}\r\n\r\n\tui.header(version, env, modes);\r\n\r\n\t// read loaders from config\r\n\tfor (const provider of providers!) {\r\n\t\ttry {\r\n\t\t\tlogger.debug(`using ${pc.yellow(provider.path)} provider`);\r\n\r\n\t\t\tif (!provider.type || provider.type === 'integrated') {\r\n\t\t\t\tprovider.handler = IntegratedProviders[provider.path];\r\n\t\t\t} else {\r\n\t\t\t\tconst { default: module } = await import(\r\n\t\t\t\t\tprovider.type === 'module'\r\n\t\t\t\t\t\t? provider.path\r\n\t\t\t\t\t\t: resolvePath(provider.path)\r\n\t\t\t\t);\r\n\r\n\t\t\t\tprovider.handler = module;\r\n\t\t\t}\r\n\t\t} catch {\r\n\t\t\tlogger.error(\r\n\t\t\t\t`${pc.yellow(\r\n\t\t\t\t\tprovider.path,\r\n\t\t\t\t)} provider not found or not compatible`,\r\n\t\t\t);\r\n\r\n\t\t\tprocess.exit(1);\r\n\t\t}\r\n\t}\r\n\r\n\tbuild(rawArgv, preloadedArgv, subcommand, config, version);\r\n}\r\n\r\n/**\r\n * Builds commands and execs Yargs.\r\n *\r\n * @param {string[]} rawArgv process.argv.slice(2)\r\n * @param {Partial<Arguments<CommandArguments>>} preloadedArgv\r\n * @param {string[]} subcommand subcommand for wrap if exists\r\n * @param {Record<string, any>} config lib config from package.json\r\n * @param {string} version lib version from package.json\r\n */\r\nfunction build(\r\n\trawArgv: string[],\r\n\tpreloadedArgv: Partial<Arguments<CommandArguments>>,\r\n\tsubcommand: string[],\r\n\tconfig: Record<string, any>,\r\n\tversion = 'unknown',\r\n): void {\r\n\tconst versionTag = pc.dim(`v${version}`);\r\n\tconst banner = [\r\n\t\t'',\r\n\t\t`${pc.bold(pc.yellow('⚡ env'))} ${versionTag} ${pc.dim('· environment variables made easy')}`,\r\n\t\t'',\r\n\t\t`${pc.bold('Usage:')} $0 [command] [options..] ${pc.dim(': <subcmd> :')} [options..]`,\r\n\t].join('\\n');\r\n\tconst epilog = [\r\n\t\t`${pc.dim('Run')} ${pc.cyan('env <command> --help')} ${pc.dim('for command-specific options.')}`,\r\n\t\t`${pc.dim('Use')} ${pc.cyan('--log debug')} ${pc.dim('to inspect the resolved environment (secrets stay masked).')}`,\r\n\t].join('\\n');\r\n\r\n\tconst builder = yargs(rawArgv)\r\n\t\t.strict()\r\n\t\t.scriptName('env')\r\n\t\t.version(version)\r\n\t\t.detectLocale(false)\r\n\t\t.showHelpOnFail(false)\r\n\t\t.parserConfiguration(config.parser)\r\n\t\t.wrap(Math.min(110, process.stdout.columns ?? 110))\r\n\t\t.usage(banner)\r\n\t\t.epilog(epilog)\r\n\t\t.options(args)\r\n\t\t.middleware(async (argv): Promise<void> => {\r\n\t\t\t// in case of subcommand argument for main\r\n\t\t\tif (subcommand?.length > 0) argv.subcmd = subcommand;\r\n\r\n\t\t\t// merges preloaded args, preserving booleans already\r\n\t\t\t// typed by yargs (preload parser reads them as strings)\r\n\t\t\tfor (const key in preloadedArgv) {\r\n\t\t\t\tconst value = preloadedArgv[key];\r\n\r\n\t\t\t\tif (\r\n\t\t\t\t\ttypeof argv[key] === 'boolean' &&\r\n\t\t\t\t\t(value === 'true' || value === 'false')\r\n\t\t\t\t)\r\n\t\t\t\t\tcontinue;\r\n\r\n\t\t\t\targv[key] = value;\r\n\t\t\t}\r\n\r\n\t\t\tlogger.silly(\r\n\t\t\t\t'interpolating arguments surrounded by',\r\n\t\t\t\tpc.bold(\r\n\t\t\t\t\tpc.yellow(\r\n\t\t\t\t\t\t`${config.delimiters.template[0]} ${config.delimiters.template[1]}`,\r\n\t\t\t\t\t),\r\n\t\t\t\t),\r\n\t\t\t);\r\n\r\n\t\t\tconst subcmdAux = argv.subcmd as string[];\r\n\t\t\t// applies string templating with current vars\r\n\t\t\tinterpolateJson(argv, argv, config.delimiters.template);\r\n\r\n\t\t\tif (Array.isArray(argv.subcmd)) {\r\n\t\t\t\t// fix for argv interpolation pre env interpolation for subcommand\r\n\t\t\t\tfor (const index in argv.subcmd) {\r\n\t\t\t\t\tif (argv.subcmd[index]?.includes('undefined'))\r\n\t\t\t\t\t\targv.subcmd[index] = subcmdAux[index];\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tlogger.silly('config loaded:', argv);\r\n\r\n\t\t\t// loads environment JSON schema if exists\r\n\t\t\t// and current project info from package.json\r\n\t\t\t[argv.projectInfo, argv.schema] = await Promise.all([\r\n\t\t\t\tloadProjectInfo((argv.packageJson ?? argv.pkg) as string),\r\n\t\t\t\tloadSchemaFile(argv, config.delimiters.template),\r\n\t\t\t]);\r\n\r\n\t\t\tif (argv.schemaValidate) {\r\n\t\t\t\targv.schemaValidate = !!argv.schema;\r\n\r\n\t\t\t\tif (argv.schemaValidate)\r\n\t\t\t\t\tlogger.silly('schema loaded:', argv.schema);\r\n\t\t\t}\r\n\t\t});\r\n\r\n\t// integrated commands builder\r\n\tbuilder.command(envCommand);\r\n\tbuilder.command(exportCommand);\r\n\tbuilder.command(pullCommand);\r\n\tbuilder.command(pushCommand);\r\n\tbuilder.command(schemaCommand);\r\n\r\n\tconst { providers } = preloadedArgv;\r\n\r\n\t// extends command from plugins\r\n\tfor (const { handler } of providers!)\r\n\t\tif (handler?.builder) handler.builder(builder);\r\n\r\n\t// executes command processing\r\n\tvoid builder.parse();\r\n}\r\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAwCA,eAAe,EACd,GACA,GACA,GACqC;CAErC,IAAM,IAAgB,EAAO,SAAS,GAAS;EAC9C,OAAO;GAAC;GAAS;GAAmB;EAAqB;EACzD,SAAS,CAAC,MAAM;EAChB,eAAe;EACf,QAAQ;GAAC;GAAQ;GAAO;GAAc;GAAc;EAAU;EAC9D,OAAO;GACN,YAAY,EAAK,WAAW;GAC5B,KAAK,EAAK,IAAI;GACd,UAAU,EAAK,SAAS;GACxB,iBAAiB,EAAK,gBAAgB;GACtC,qBAAqB,EAAK,oBAAoB;GAC9C,OAAO,EAAK,MAAM;EACnB;EACA,SAAS;GACR,YAAY,EAAK,WAAW;GAC5B,MAAM,EAAK,KAAK;EACjB;CACD,CAAC,CAAC,CAAC;CAQH,AALA,MAAM,EAAe,GAAe,CAAU,GAE9C,EAAc,aAAa,EAAK,SAAS,SACzC,EAAc,oBAAoB,EAAK,gBAAgB,SACvD,EAAc,wBAAwB,EAAK,oBAAoB,SAC/D,EAAc,cAAc,EAAK,UAAU;CAE3C,IAAM,EAAE,aAAU,oBAAiB,2BAAwB;CAS3D,OANA,EAAgB,GAAQ;EACvB,cAAc;EACd,kBAAkB;EAClB,UAAU;CACX,CAAC,GAEM;AACR;AASA,eAAsB,EAAK,GAAmB;CAQ7C,IAAM,EAAE,WAAQ,eANJ,KAAK,MAChB,EACC,EAAc,IAAA,IAAA,gBAAA,KAAA,OAAA,KAAA,GAAA,CAAwC,GACtD,MACD,CAE2B,GAGtB,IAAa,EAAc,GAAS,EAAO,WAAW,UAAU,GAEhE,IAAgB,MAAM,EAC3B,GACA,EAAO,QACP,EAAO,WAAW,QACnB;CAIA,AAAK,EAAc,QAClB,MAAM,EAAW,GAAe,EAAO,WAAW,QAAQ;CAE3D,IAAM,EAAE,QAAK,SAAM,UAAO,iBAAc;CAUxC,AARI,KAAM,EAAM,GAAS,GAAe,GAAY,GAAQ,CAAO,IAE/D,CAAC,MAAM,QAAQ,CAAS,KAAK,EAAU,WAAW,OACrD,EAAO,MAAM,oBAAoB,GAEjC,QAAQ,KAAK,CAAC,IAGf,EAAG,OAAO,GAAS,GAAK,CAAK;CAG7B,KAAK,IAAM,KAAY,GACtB,IAAI;EAGH,IAFA,EAAO,MAAM,SAAS,EAAG,OAAO,EAAS,IAAI,EAAE,UAAU,GAErD,CAAC,EAAS,QAAQ,EAAS,SAAS,cACvC,EAAS,UAAU,EAAoB,EAAS;OAC1C;GACN,IAAM,EAAE,SAAS,MAAW,OAC3B,EAAS,SAAS,WAAA,OACf,EAAS,QAAA,OACT,EAAY,EAAS,IAAI;GAG7B,EAAS,UAAU;EACpB;CACD,QAAQ;EAOP,AANA,EAAO,MACN,GAAG,EAAG,OACL,EAAS,IACV,EAAE,sCACH,GAEA,QAAQ,KAAK,CAAC;CACf;CAGD,EAAM,GAAS,GAAe,GAAY,GAAQ,CAAO;AAC1D;AAWA,SAAS,EACR,GACA,GACA,GACA,GACA,IAAU,WACH;CACP,IAAM,IAAa,EAAG,IAAI,IAAI,GAAS,GACjC,IAAS;EACd;EACA,GAAG,EAAG,KAAK,EAAG,OAAO,OAAO,CAAC,EAAE,GAAG,EAAW,IAAI,EAAG,IAAI,mCAAmC;EAC3F;EACA,GAAG,EAAG,KAAK,QAAQ,EAAE,4BAA4B,EAAG,IAAI,cAAc,EAAE;CACzE,CAAC,CAAC,KAAK,IAAI,GACL,IAAS,CACd,GAAG,EAAG,IAAI,KAAK,EAAE,GAAG,EAAG,KAAK,sBAAsB,EAAE,GAAG,EAAG,IAAI,+BAA+B,KAC7F,GAAG,EAAG,IAAI,KAAK,EAAE,GAAG,EAAG,KAAK,aAAa,EAAE,GAAG,EAAG,IAAI,4DAA4D,GAClH,CAAC,CAAC,KAAK,IAAI,GAEL,IAAU,EAAM,CAAO,CAAC,CAC5B,OAAO,CAAC,CACR,WAAW,KAAK,CAAC,CACjB,QAAQ,CAAO,CAAC,CAChB,aAAa,EAAK,CAAC,CACnB,eAAe,EAAK,CAAC,CACrB,oBAAoB,EAAO,MAAM,CAAC,CAClC,KAAK,KAAK,IAAI,KAAK,QAAQ,OAAO,WAAW,GAAG,CAAC,CAAC,CAClD,MAAM,CAAM,CAAC,CACb,OAAO,CAAM,CAAC,CACd,QAAQ,CAAI,CAAC,CACb,WAAW,OAAO,MAAwB;EAE1C,AAAI,GAAY,SAAS,MAAG,EAAK,SAAS;EAI1C,KAAK,IAAM,KAAO,GAAe;GAChC,IAAM,IAAQ,EAAc;GAG3B,OAAO,EAAK,MAAS,cACpB,MAAU,UAAU,MAAU,aAIhC,EAAK,KAAO;EACb;EAEA,EAAO,MACN,yCACA,EAAG,KACF,EAAG,OACF,GAAG,EAAO,WAAW,SAAS,GAAG,GAAG,EAAO,WAAW,SAAS,IAChE,CACD,CACD;EAEA,IAAM,IAAY,EAAK;EAIvB,IAFA,EAAgB,GAAM,GAAM,EAAO,WAAW,QAAQ,GAElD,MAAM,QAAQ,EAAK,MAAM,QAEvB,IAAM,KAAS,EAAK,QACxB,AAAI,EAAK,OAAO,EAAM,EAAE,SAAS,WAAW,MAC3C,EAAK,OAAO,KAAS,EAAU;EAalC,AATA,EAAO,MAAM,kBAAkB,CAAI,GAInC,CAAC,EAAK,aAAa,EAAK,UAAU,MAAM,QAAQ,IAAI,CACnD,EAAiB,EAAK,eAAe,EAAK,GAAc,GACxD,EAAe,GAAM,EAAO,WAAW,QAAQ,CAChD,CAAC,GAEG,EAAK,mBACR,EAAK,iBAAiB,CAAC,CAAC,EAAK,QAEzB,EAAK,kBACR,EAAO,MAAM,kBAAkB,EAAK,MAAM;CAE7C,CAAC;CAOF,AAJA,EAAQ,QAAQ,CAAU,GAC1B,EAAQ,QAAQ,CAAa,GAC7B,EAAQ,QAAQ,CAAW,GAC3B,EAAQ,QAAQ,CAAW,GAC3B,EAAQ,QAAQ,CAAa;CAE7B,IAAM,EAAE,iBAAc;CAGtB,KAAK,IAAM,EAAE,gBAAa,GACzB,AAAI,GAAS,WAAS,EAAQ,QAAQ,CAAO;CAG9C,EAAa,MAAM;AACpB"}
package/package.json CHANGED
@@ -1,110 +1,110 @@
1
- {
2
- "version": "3.2.0",
3
- "project": "common",
4
- "name": "@calvear/env",
5
- "type": "module",
6
- "title": "Environment Variables CLI Tool",
7
- "description": "Extensible environment variables handler for NodeJS apps",
8
- "author": "Alvear Candia, Cristopher Alejandro <calvear93@gmail.com>",
9
- "repository": "https://github.com/calvear93/env",
10
- "license": "MIT",
11
- "private": false,
12
- "keywords": [
13
- "env",
14
- "node",
15
- "cli",
16
- "typescript"
17
- ],
18
- "scripts": {
19
- "build": "pnpm prebuild && vite build && pnpm postbuild",
20
- "test": "vitest run --project unit",
21
- "test:watch": "vitest --project unit",
22
- "test:cov": "vitest run --project unit --coverage",
23
- "test:int": "vitest run --project integration",
24
- "run:test": "node dist/main.js --root tests/env --log debug -e dev : node tests/run.js",
25
- "typecheck": "tsc --noEmit",
26
- "lint": "eslint --cache --cache-location node_modules/.cache/eslint/ .",
27
- "lint:fix": "eslint --fix --cache --cache-location node_modules/.cache/eslint/ .",
28
- "format": "prettier --cache --write \"**/*.{ts,cts,mts,js,cjs,mjs,json,md,yml,yaml}\"",
29
- "format:check": "prettier --cache --check \"**/*.{ts,cts,mts,js,cjs,mjs,json,md,yml,yaml}\"",
30
- "pub": "pnpm typecheck && pnpm lint && pnpm test:cov && pnpm build && npm publish ./dist --access public --no-git-checks",
31
- "pub:alpha": "pnpm typecheck && pnpm lint && pnpm test:cov && pnpm build && pnpm publish ./dist --tag alpha --access public --no-git-checks",
32
- "prebuild": "del-cli dist",
33
- "postbuild": "copyfiles package.json README.md LICENSE.md CHANGELOG.md schemas/env.schema.json schemas/settings.schema.json assets/* dist"
34
- },
35
- "dependencies": {
36
- "ajv": "^8.20.0",
37
- "ajv-formats": "^3.0.1",
38
- "ci-info": "^4.4.0",
39
- "merge-deep": "^3.0.3",
40
- "picocolors": "^1.1.1",
41
- "subslate": "^1.0.0",
42
- "to-json-schema": "^0.2.5",
43
- "tslog": "^4.10.2",
44
- "yargs": "^18.0.0"
45
- },
46
- "devDependencies": {
47
- "@types/merge-deep": "^3.0.3",
48
- "@types/node": "^26.0.0",
49
- "@types/to-json-schema": "^0.2.4",
50
- "@types/yargs": "^17.0.35",
51
- "@vitest/coverage-v8": "^4.1.9",
52
- "@vitest/eslint-plugin": "^1.6.20",
53
- "copyfiles": "^2.4.1",
54
- "del-cli": "^7.0.0",
55
- "eslint": "^10.5.0",
56
- "eslint-config-prettier": "^10.1.8",
57
- "eslint-plugin-perfectionist": "^5.9.1",
58
- "eslint-plugin-prettier": "^5.5.6",
59
- "eslint-plugin-promise": "^7.3.0",
60
- "eslint-plugin-regexp": "^3.1.0",
61
- "eslint-plugin-sonarjs": "^4.1.0",
62
- "eslint-plugin-unicorn": "^68.0.0",
63
- "globals": "^17.7.0",
64
- "prettier": "^3.8.4",
65
- "typescript": "^6.0.3",
66
- "typescript-eslint": "^8.62.0",
67
- "vite": "^8.1.0",
68
- "vite-plugin-dts": "^5.0.3",
69
- "vitest": "^4.1.9"
70
- },
71
- "exports": {
72
- ".": {
73
- "types": "./index.d.ts",
74
- "import": "./index.js"
75
- },
76
- "./utils": {
77
- "types": "./utils/index.d.ts",
78
- "import": "./utils/index.js"
79
- },
80
- "./package.json": "./package.json"
81
- },
82
- "main": "index.js",
83
- "types": "index.d.ts",
84
- "bin": {
85
- "env": "main.js"
86
- },
87
- "engines": {
88
- "node": ">=20",
89
- "pnpm": ">=9"
90
- },
91
- "config": {
92
- "delimiters": {
93
- "template": [
94
- "[[",
95
- "]]"
96
- ],
97
- "subcommand": [
98
- ":",
99
- ":"
100
- ]
101
- },
102
- "parser": {
103
- "short-option-groups": true,
104
- "camel-case-expansion": false,
105
- "dot-notation": true,
106
- "parse-numbers": true,
107
- "boolean-negation": false
108
- }
109
- }
110
- }
1
+ {
2
+ "version": "3.4.0",
3
+ "project": "common",
4
+ "name": "@calvear/env",
5
+ "type": "module",
6
+ "title": "Environment Variables CLI Tool",
7
+ "description": "Extensible environment variables handler for NodeJS apps",
8
+ "author": "Alvear Candia, Cristopher Alejandro <calvear93@gmail.com>",
9
+ "repository": "https://github.com/calvear93/env",
10
+ "license": "MIT",
11
+ "private": false,
12
+ "keywords": [
13
+ "env",
14
+ "node",
15
+ "cli",
16
+ "typescript"
17
+ ],
18
+ "scripts": {
19
+ "build": "pnpm prebuild && vite build && pnpm postbuild",
20
+ "test": "vitest run --project unit",
21
+ "test:watch": "vitest --project unit",
22
+ "test:cov": "vitest run --project unit --coverage",
23
+ "test:int": "vitest run --project integration",
24
+ "run:test": "node dist/main.js --root tests/env --log debug -e dev : node tests/run.js",
25
+ "typecheck": "tsc --noEmit",
26
+ "lint": "eslint --cache --cache-location node_modules/.cache/eslint/ .",
27
+ "lint:fix": "eslint --fix --cache --cache-location node_modules/.cache/eslint/ .",
28
+ "format": "prettier --cache --write \"**/*.{ts,cts,mts,js,cjs,mjs,json,md,yml,yaml}\"",
29
+ "format:check": "prettier --cache --check \"**/*.{ts,cts,mts,js,cjs,mjs,json,md,yml,yaml}\"",
30
+ "pub": "pnpm typecheck && pnpm lint && pnpm test:cov && pnpm build && npm publish ./dist --access public --no-git-checks",
31
+ "pub:alpha": "pnpm typecheck && pnpm lint && pnpm test:cov && pnpm build && pnpm publish ./dist --tag alpha --access public --no-git-checks",
32
+ "prebuild": "del-cli dist",
33
+ "postbuild": "copyfiles package.json README.md LICENSE.md CHANGELOG.md schemas/env.schema.json schemas/settings.schema.json assets/* dist"
34
+ },
35
+ "dependencies": {
36
+ "ajv": "^8.20.0",
37
+ "ajv-formats": "^3.0.1",
38
+ "ci-info": "^4.4.0",
39
+ "merge-deep": "^3.0.3",
40
+ "picocolors": "^1.1.1",
41
+ "subslate": "^1.0.0",
42
+ "to-json-schema": "^0.2.5",
43
+ "tslog": "^4.10.2",
44
+ "yargs": "^18.0.0"
45
+ },
46
+ "devDependencies": {
47
+ "@types/merge-deep": "^3.0.3",
48
+ "@types/node": "^26.0.0",
49
+ "@types/to-json-schema": "^0.2.4",
50
+ "@types/yargs": "^17.0.35",
51
+ "@vitest/coverage-v8": "^4.1.9",
52
+ "@vitest/eslint-plugin": "^1.6.20",
53
+ "copyfiles": "^2.4.1",
54
+ "del-cli": "^7.0.0",
55
+ "eslint": "^10.5.0",
56
+ "eslint-config-prettier": "^10.1.8",
57
+ "eslint-plugin-perfectionist": "^5.9.1",
58
+ "eslint-plugin-prettier": "^5.5.6",
59
+ "eslint-plugin-promise": "^7.3.0",
60
+ "eslint-plugin-regexp": "^3.1.0",
61
+ "eslint-plugin-sonarjs": "^4.1.0",
62
+ "eslint-plugin-unicorn": "^68.0.0",
63
+ "globals": "^17.7.0",
64
+ "prettier": "^3.8.4",
65
+ "typescript": "^6.0.3",
66
+ "typescript-eslint": "^8.62.0",
67
+ "vite": "^8.1.0",
68
+ "vite-plugin-dts": "^5.0.3",
69
+ "vitest": "^4.1.9"
70
+ },
71
+ "exports": {
72
+ ".": {
73
+ "types": "./index.d.ts",
74
+ "import": "./index.js"
75
+ },
76
+ "./utils": {
77
+ "types": "./utils/index.d.ts",
78
+ "import": "./utils/index.js"
79
+ },
80
+ "./package.json": "./package.json"
81
+ },
82
+ "main": "index.js",
83
+ "types": "index.d.ts",
84
+ "bin": {
85
+ "env": "main.js"
86
+ },
87
+ "engines": {
88
+ "node": ">=20",
89
+ "pnpm": ">=9"
90
+ },
91
+ "config": {
92
+ "delimiters": {
93
+ "template": [
94
+ "[[",
95
+ "]]"
96
+ ],
97
+ "subcommand": [
98
+ ":",
99
+ ":"
100
+ ]
101
+ },
102
+ "parser": {
103
+ "short-option-groups": true,
104
+ "camel-case-expansion": false,
105
+ "dot-notation": true,
106
+ "parse-numbers": true,
107
+ "boolean-negation": false
108
+ }
109
+ }
110
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"app-settings.provider.d.ts","sourceRoot":"","sources":["../../src/providers/app-settings.provider.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAS1D,UAAU,2BAA4B,SAAQ,gBAAgB;IAC7D,OAAO,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,eAAO,MAAM,mBAAmB,EAAE,WAAW,CAAC,2BAA2B,CAyDxE,CAAC"}
1
+ {"version":3,"file":"app-settings.provider.d.ts","sourceRoot":"","sources":["../../src/providers/app-settings.provider.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAgB1D,UAAU,2BAA4B,SAAQ,gBAAgB;IAC7D,OAAO,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,eAAO,MAAM,mBAAmB,EAAE,WAAW,CAAC,2BAA2B,CAkExE,CAAC"}
@@ -1,38 +1,41 @@
1
- import { readJson as e } from "../utils/json.util.js";
2
- import { logger as t } from "../utils/logger.js";
1
+ import { SECTION_DEFAULT as e, SECTION_ENV as t, SECTION_LOCAL as n, SECTION_MODE as r } from "../utils/infer-env.util.js";
2
+ import { readJson as i } from "../utils/json.util.js";
3
+ import { logger as a } from "../utils/logger.js";
3
4
  import "../utils/index.js";
4
- import n from "picocolors";
5
+ import o from "picocolors";
5
6
  //#region src/providers/app-settings.provider.ts
6
- var r = "app-settings", i = t.getSubLogger({ prefix: [n.bold(n.blue(`[${r}]`))] }), a = {
7
- key: r,
7
+ var s = "app-settings", c = a.getSubLogger({ prefix: [o.bold(o.blue(`[${s}]`))] }), l = {
8
+ key: s,
8
9
  builder: (e) => {
9
10
  e.options({ envFile: {
10
11
  alias: "ef",
11
12
  default: "[[root]]/appsettings.json",
12
13
  describe: "Environment variables file path (non secrets)",
13
- group: r,
14
+ group: s,
14
15
  type: "string"
15
16
  } });
16
17
  },
17
- load: async ({ ci: t, env: r, envFile: a, modes: o = [], root: s }) => {
18
- let [c = {}, l] = await e(a);
19
- l || i.warn(`${n.blue(a)} not found`);
20
- let u = c["|DEFAULT|"] || c["|ENV|"] || c["|MODE|"] || c["|LOCAL|"], d = await Promise.all([
21
- e(`${s}/appsettings.${r}.json`).then(([e]) => e),
22
- e(`${s}/appsettings.${r}.local.json`).then(([e]) => t ? {} : e),
23
- ...o.map((t) => e(`${s}/appsettings.${t}.json`).then(([e]) => e))
18
+ load: async ({ ci: a, env: s, envFile: l, modes: u = [], root: d }) => {
19
+ let [f = {}, p] = await i(l);
20
+ p || c.warn(`${o.blue(l)} not found`);
21
+ let m = f["|DEFAULT|"] || f["|ENV|"] || f["|MODE|"] || f["|LOCAL|"], [h, g, ..._] = await Promise.all([
22
+ i(`${d}/appsettings.${s}.json`).then(([e]) => e),
23
+ i(`${d}/appsettings.${s}.local.json`).then(([e]) => a ? {} : e),
24
+ ...u.map((e) => i(`${d}/appsettings.${e}.json`).then(([e]) => e))
24
25
  ]);
25
- return t && (c["|LOCAL|"] = null), [
26
- u ? {} : c,
27
- c["|DEFAULT|"],
28
- c["|ENV|"]?.[r],
29
- ...o.map((e) => c["|MODE|"]?.[e]),
30
- c["|LOCAL|"]?.[r],
31
- ...d
26
+ return a && (f[n] = null), [
27
+ m ? {} : f,
28
+ f[e],
29
+ f[t]?.[s],
30
+ ...u.map((e) => f[r]?.[e]),
31
+ h,
32
+ ..._,
33
+ f[n]?.[s],
34
+ g
32
35
  ];
33
36
  }
34
37
  };
35
38
  //#endregion
36
- export { a as AppSettingsProvider };
39
+ export { l as AppSettingsProvider };
37
40
 
38
41
  //# sourceMappingURL=app-settings.provider.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"app-settings.provider.js","names":[],"sources":["../../src/providers/app-settings.provider.ts"],"sourcesContent":["import pc from 'picocolors';\r\nimport type { CommandArguments } from '../arguments.js';\r\nimport type { EnvProvider } from '../interfaces/index.js';\r\nimport { logger as globalLogger, readJson } from '../utils/index.js';\r\n\r\nconst KEY = 'app-settings';\r\n\r\nconst logger = globalLogger.getSubLogger({\r\n\tprefix: [pc.bold(pc.blue(`[${KEY}]`))],\r\n});\r\n\r\ninterface AppSettingsCommandArguments extends CommandArguments {\r\n\tenvFile: string;\r\n}\r\n\r\n/**\r\n * Loads config from appsettings.json.\r\n */\r\nexport const AppSettingsProvider: EnvProvider<AppSettingsCommandArguments> = {\r\n\tkey: KEY,\r\n\r\n\tbuilder: (builder) => {\r\n\t\tbuilder.options({\r\n\t\t\tenvFile: {\r\n\t\t\t\talias: 'ef',\r\n\t\t\t\tdefault: '[[root]]/appsettings.json',\r\n\t\t\t\tdescribe: 'Environment variables file path (non secrets)',\r\n\t\t\t\tgroup: KEY,\r\n\t\t\t\ttype: 'string',\r\n\t\t\t},\r\n\t\t});\r\n\t},\r\n\r\n\tload: async ({ ci, env, envFile, modes = [], root }) => {\r\n\t\tconst [appsettings = {}, wasFound] = await readJson(envFile);\r\n\r\n\t\tif (!wasFound) logger.warn(`${pc.blue(envFile)} not found`);\r\n\r\n\t\tconst composite =\r\n\t\t\tappsettings['|DEFAULT|'] ||\r\n\t\t\tappsettings['|ENV|'] ||\r\n\t\t\tappsettings['|MODE|'] ||\r\n\t\t\tappsettings['|LOCAL|'];\r\n\r\n\t\tconst unitary = await Promise.all([\r\n\t\t\treadJson(`${root}/appsettings.${env}.json`).then(\r\n\t\t\t\t([settings]) => settings,\r\n\t\t\t),\r\n\t\t\treadJson(`${root}/appsettings.${env}.local.json`).then(\r\n\t\t\t\t([settings]) => (ci ? {} : settings),\r\n\t\t\t),\r\n\t\t\t...modes.map((mode) =>\r\n\t\t\t\treadJson(`${root}/appsettings.${mode}.json`).then(\r\n\t\t\t\t\t([settings]) => settings,\r\n\t\t\t\t),\r\n\t\t\t),\r\n\t\t]);\r\n\r\n\t\t// only load local in env load cmd\r\n\t\tif (ci) appsettings['|LOCAL|'] = null;\r\n\r\n\t\treturn [\r\n\t\t\tcomposite ? {} : appsettings,\r\n\r\n\t\t\tappsettings['|DEFAULT|'],\r\n\r\n\t\t\tappsettings['|ENV|']?.[env],\r\n\r\n\t\t\t...modes.map((mode) => appsettings['|MODE|']?.[mode]),\r\n\r\n\t\t\tappsettings['|LOCAL|']?.[env],\r\n\r\n\t\t\t...unitary,\r\n\t\t];\r\n\t},\r\n};\r\n"],"mappings":";;;;;AAKA,IAAM,IAAM,gBAEN,IAAS,EAAa,aAAa,EACxC,QAAQ,CAAC,EAAG,KAAK,EAAG,KAAK,IAAI,EAAI,EAAE,CAAC,CAAC,EACtC,CAAC,GASY,IAAgE;CAC5E,KAAK;CAEL,UAAU,MAAY;EACrB,EAAQ,QAAQ,EACf,SAAS;GACR,OAAO;GACP,SAAS;GACT,UAAU;GACV,OAAO;GACP,MAAM;EACP,EACD,CAAC;CACF;CAEA,MAAM,OAAO,EAAE,OAAI,QAAK,YAAS,WAAQ,CAAC,GAAG,cAAW;EACvD,IAAM,CAAC,IAAc,CAAC,GAAG,KAAY,MAAM,EAAS,CAAO;EAE3D,AAAK,KAAU,EAAO,KAAK,GAAG,EAAG,KAAK,CAAO,EAAE,WAAW;EAE1D,IAAM,IACL,EAAY,gBACZ,EAAY,YACZ,EAAY,aACZ,EAAY,YAEP,IAAU,MAAM,QAAQ,IAAI;GACjC,EAAS,GAAG,EAAK,eAAe,EAAI,MAAM,CAAC,CAAC,MAC1C,CAAC,OAAc,CACjB;GACA,EAAS,GAAG,EAAK,eAAe,EAAI,YAAY,CAAC,CAAC,MAChD,CAAC,OAAe,IAAK,CAAC,IAAI,CAC5B;GACA,GAAG,EAAM,KAAK,MACb,EAAS,GAAG,EAAK,eAAe,EAAK,MAAM,CAAC,CAAC,MAC3C,CAAC,OAAc,CACjB,CACD;EACD,CAAC;EAKD,OAFI,MAAI,EAAY,aAAa,OAE1B;GACN,IAAY,CAAC,IAAI;GAEjB,EAAY;GAEZ,EAAY,QAAQ,GAAG;GAEvB,GAAG,EAAM,KAAK,MAAS,EAAY,SAAS,GAAG,EAAK;GAEpD,EAAY,UAAU,GAAG;GAEzB,GAAG;EACJ;CACD;AACD"}
1
+ {"version":3,"file":"app-settings.provider.js","names":[],"sources":["../../src/providers/app-settings.provider.ts"],"sourcesContent":["import pc from 'picocolors';\r\nimport type { CommandArguments } from '../arguments.js';\r\nimport type { EnvProvider } from '../interfaces/index.js';\r\nimport {\r\n\tlogger as globalLogger,\r\n\treadJson,\r\n\tSECTION_DEFAULT,\r\n\tSECTION_ENV,\r\n\tSECTION_LOCAL,\r\n\tSECTION_MODE,\r\n} from '../utils/index.js';\r\n\r\nconst KEY = 'app-settings';\r\n\r\nconst logger = globalLogger.getSubLogger({\r\n\tprefix: [pc.bold(pc.blue(`[${KEY}]`))],\r\n});\r\n\r\ninterface AppSettingsCommandArguments extends CommandArguments {\r\n\tenvFile: string;\r\n}\r\n\r\n/**\r\n * Loads config from appsettings.json.\r\n */\r\nexport const AppSettingsProvider: EnvProvider<AppSettingsCommandArguments> = {\r\n\tkey: KEY,\r\n\r\n\tbuilder: (builder) => {\r\n\t\tbuilder.options({\r\n\t\t\tenvFile: {\r\n\t\t\t\talias: 'ef',\r\n\t\t\t\tdefault: '[[root]]/appsettings.json',\r\n\t\t\t\tdescribe: 'Environment variables file path (non secrets)',\r\n\t\t\t\tgroup: KEY,\r\n\t\t\t\ttype: 'string',\r\n\t\t\t},\r\n\t\t});\r\n\t},\r\n\r\n\tload: async ({ ci, env, envFile, modes = [], root }) => {\r\n\t\tconst [appsettings = {}, wasFound] = await readJson(envFile);\r\n\r\n\t\tif (!wasFound) logger.warn(`${pc.blue(envFile)} not found`);\r\n\r\n\t\tconst composite =\r\n\t\t\tappsettings[SECTION_DEFAULT] ||\r\n\t\t\tappsettings[SECTION_ENV] ||\r\n\t\t\tappsettings[SECTION_MODE] ||\r\n\t\t\tappsettings[SECTION_LOCAL];\r\n\r\n\t\tconst [envFileSettings, envLocalFileSettings, ...modeFileSettings] =\r\n\t\t\tawait Promise.all([\r\n\t\t\t\treadJson(`${root}/appsettings.${env}.json`).then(\r\n\t\t\t\t\t([settings]) => settings,\r\n\t\t\t\t),\r\n\t\t\t\treadJson(`${root}/appsettings.${env}.local.json`).then(\r\n\t\t\t\t\t([settings]) => (ci ? {} : settings),\r\n\t\t\t\t),\r\n\t\t\t\t...modes.map((mode) =>\r\n\t\t\t\t\treadJson(`${root}/appsettings.${mode}.json`).then(\r\n\t\t\t\t\t\t([settings]) => settings,\r\n\t\t\t\t\t),\r\n\t\t\t\t),\r\n\t\t\t]);\r\n\r\n\t\t// only load local in env load cmd\r\n\t\tif (ci) appsettings[SECTION_LOCAL] = null;\r\n\r\n\t\t// order defines section + file merge precedence (later entries win):\r\n\t\t// flat root < |DEFAULT| < |ENV| < |MODE| < appsettings.<env>.json\r\n\t\t// < appsettings.<mode>.json < |LOCAL| < appsettings.<env>.local.json.\r\n\t\t// Local layers are always highest — do NOT reorder.\r\n\t\treturn [\r\n\t\t\tcomposite ? {} : appsettings,\r\n\r\n\t\t\tappsettings[SECTION_DEFAULT],\r\n\r\n\t\t\tappsettings[SECTION_ENV]?.[env],\r\n\r\n\t\t\t...modes.map((mode) => appsettings[SECTION_MODE]?.[mode]),\r\n\r\n\t\t\tenvFileSettings,\r\n\r\n\t\t\t...modeFileSettings,\r\n\r\n\t\t\tappsettings[SECTION_LOCAL]?.[env],\r\n\r\n\t\t\tenvLocalFileSettings,\r\n\t\t];\r\n\t},\r\n};\r\n"],"mappings":";;;;;;AAYA,IAAM,IAAM,gBAEN,IAAS,EAAa,aAAa,EACxC,QAAQ,CAAC,EAAG,KAAK,EAAG,KAAK,IAAI,EAAI,EAAE,CAAC,CAAC,EACtC,CAAC,GASY,IAAgE;CAC5E,KAAK;CAEL,UAAU,MAAY;EACrB,EAAQ,QAAQ,EACf,SAAS;GACR,OAAO;GACP,SAAS;GACT,UAAU;GACV,OAAO;GACP,MAAM;EACP,EACD,CAAC;CACF;CAEA,MAAM,OAAO,EAAE,OAAI,QAAK,YAAS,WAAQ,CAAC,GAAG,cAAW;EACvD,IAAM,CAAC,IAAc,CAAC,GAAG,KAAY,MAAM,EAAS,CAAO;EAE3D,AAAK,KAAU,EAAO,KAAK,GAAG,EAAG,KAAK,CAAO,EAAE,WAAW;EAE1D,IAAM,IACL,EAAA,gBACA,EAAA,YACA,EAAA,aACA,EAAA,YAEK,CAAC,GAAiB,GAAsB,GAAG,KAChD,MAAM,QAAQ,IAAI;GACjB,EAAS,GAAG,EAAK,eAAe,EAAI,MAAM,CAAC,CAAC,MAC1C,CAAC,OAAc,CACjB;GACA,EAAS,GAAG,EAAK,eAAe,EAAI,YAAY,CAAC,CAAC,MAChD,CAAC,OAAe,IAAK,CAAC,IAAI,CAC5B;GACA,GAAG,EAAM,KAAK,MACb,EAAS,GAAG,EAAK,eAAe,EAAK,MAAM,CAAC,CAAC,MAC3C,CAAC,OAAc,CACjB,CACD;EACD,CAAC;EASF,OANI,MAAI,EAAY,KAAiB,OAM9B;GACN,IAAY,CAAC,IAAI;GAEjB,EAAY;GAEZ,EAAY,EAAY,GAAG;GAE3B,GAAG,EAAM,KAAK,MAAS,EAAY,EAAa,GAAG,EAAK;GAExD;GAEA,GAAG;GAEH,EAAY,EAAc,GAAG;GAE7B;EACD;CACD;AACD"}
package/utils/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  export * from './argv.util.js';
2
2
  export * from './command.util.js';
3
+ export * from './infer-env.util.js';
3
4
  export * from './interpolate.util.js';
4
5
  export * from './json.util.js';
5
6
  export * from './logger.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,uBAAuB,CAAC;AACtC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,aAAa,CAAC;AAC5B,cAAc,qBAAqB,CAAC;AACpC,cAAc,kBAAkB,CAAC;AACjC,cAAc,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,aAAa,CAAC;AAC5B,cAAc,qBAAqB,CAAC;AACpC,cAAc,kBAAkB,CAAC;AACjC,cAAc,SAAS,CAAC"}
package/utils/index.js CHANGED
@@ -1,9 +1,10 @@
1
1
  import { normalizeRawArgv as e } from "./argv.util.js";
2
2
  import { flatAndValidateResults as t, flatResults as n, generateSchemaFrom as r, getSubcommand as i, loadConfigFile as a, loadProjectInfo as o, loadSchemaFile as s, loadVariablesFromProviders as c } from "./command.util.js";
3
- import { interpolate as l, interpolateJson as u, isRecord as d } from "./interpolate.util.js";
4
- import { readJson as f, resolvePath as p, writeEnvFromJson as m, writeJson as h } from "./json.util.js";
5
- import { LOG_LEVELS as g, configureLogger as _, createLogger as v, logger as y } from "./logger.js";
6
- import { flatten as b, normalize as x } from "./normalize.util.js";
7
- import { createValidator as S, createValidators as C, flatSchema as w, isJsonSchemaObject as T, schemaFrom as E, schemaToJson as D } from "./schema.util.js";
8
- import { formatDuration as O, ui as k } from "./ui.js";
9
- export { g as LOG_LEVELS, _ as configureLogger, v as createLogger, S as createValidator, C as createValidators, t as flatAndValidateResults, n as flatResults, w as flatSchema, b as flatten, O as formatDuration, r as generateSchemaFrom, i as getSubcommand, l as interpolate, u as interpolateJson, T as isJsonSchemaObject, d as isRecord, a as loadConfigFile, o as loadProjectInfo, s as loadSchemaFile, c as loadVariablesFromProviders, y as logger, x as normalize, e as normalizeRawArgv, f as readJson, p as resolvePath, E as schemaFrom, D as schemaToJson, k as ui, m as writeEnvFromJson, h as writeJson };
3
+ import { SECTION_DEFAULT as l, SECTION_ENV as u, SECTION_LOCAL as d, SECTION_MODE as f, discoverEnvironments as p, inferEnvFromScript as m, resolveEnv as h } from "./infer-env.util.js";
4
+ import { interpolate as g, interpolateJson as _, isRecord as v } from "./interpolate.util.js";
5
+ import { readJson as y, resolvePath as b, writeEnvFromJson as x, writeJson as S } from "./json.util.js";
6
+ import { LOG_LEVELS as C, configureLogger as w, createLogger as T, logger as E } from "./logger.js";
7
+ import { flatten as D, normalize as O } from "./normalize.util.js";
8
+ import { createValidator as k, createValidators as A, flatSchema as j, isJsonSchemaObject as M, schemaFrom as N, schemaToJson as P } from "./schema.util.js";
9
+ import { formatDuration as F, ui as I } from "./ui.js";
10
+ export { C as LOG_LEVELS, l as SECTION_DEFAULT, u as SECTION_ENV, d as SECTION_LOCAL, f as SECTION_MODE, w as configureLogger, T as createLogger, k as createValidator, A as createValidators, p as discoverEnvironments, t as flatAndValidateResults, n as flatResults, j as flatSchema, D as flatten, F as formatDuration, r as generateSchemaFrom, i as getSubcommand, m as inferEnvFromScript, g as interpolate, _ as interpolateJson, M as isJsonSchemaObject, v as isRecord, a as loadConfigFile, o as loadProjectInfo, s as loadSchemaFile, c as loadVariablesFromProviders, E as logger, O as normalize, e as normalizeRawArgv, y as readJson, h as resolveEnv, b as resolvePath, N as schemaFrom, P as schemaToJson, I as ui, x as writeEnvFromJson, S as writeJson };
@@ -0,0 +1,51 @@
1
+ import { Arguments } from 'yargs';
2
+ import { CommandArguments } from '../arguments.js';
3
+ /** appsettings.json section keys. */
4
+ export declare const SECTION_DEFAULT = "|DEFAULT|";
5
+ export declare const SECTION_ENV = "|ENV|";
6
+ export declare const SECTION_LOCAL = "|LOCAL|";
7
+ export declare const SECTION_MODE = "|MODE|";
8
+ /**
9
+ * Infers the environment from the npm script name
10
+ * (npm_lifecycle_event), i.e. "start:dev" → "dev".
11
+ *
12
+ * @export
13
+ * @param {string | undefined} lifecycleEvent npm script name
14
+ *
15
+ * @returns {string | undefined} environment, or undefined
16
+ * when there is no ':' suffix (i.e. "preview") or the CLI
17
+ * was invoked outside an npm script
18
+ */
19
+ export declare function inferEnvFromScript(lifecycleEvent: string | undefined): string | undefined;
20
+ /**
21
+ * Discovers the environments defined in the workspace, as the union of
22
+ * the |ENV| and |LOCAL| section keys of appsettings.json and the per-env
23
+ * provider files found in the root folder (appsettings.<env>.json,
24
+ * appsettings.<env>.local.json, <env>.env.json, <env>.local.env.json).
25
+ *
26
+ * @export
27
+ * @param {Partial<Arguments<CommandArguments>>} argv preloaded arguments
28
+ * @param {[string, string]} delimiters template delimiters
29
+ *
30
+ * @returns {Promise<Set<string>>} known environments
31
+ */
32
+ export declare function discoverEnvironments(argv: Partial<Arguments<CommandArguments>>, delimiters: [string, string]): Promise<Set<string>>;
33
+ /**
34
+ * Resolves argv.env when not provided by -e nor config file,
35
+ * inferring it from the npm script name (npm_lifecycle_event)
36
+ * and validating it against the known environments.
37
+ *
38
+ * Validation rules:
39
+ * - explicit env unknown → warning, continues
40
+ * - inferred env unknown → fatal error listing known environments
41
+ * - no known environments → inference is discarded (debug log)
42
+ *
43
+ * Mutates argv so build()'s middleware propagates the resolved
44
+ * env to the main yargs parse.
45
+ *
46
+ * @export
47
+ * @param {Partial<Arguments<CommandArguments>>} argv preloaded arguments
48
+ * @param {[string, string]} delimiters template delimiters
49
+ */
50
+ export declare function resolveEnv(argv: Partial<Arguments<CommandArguments>>, delimiters: [string, string]): Promise<void>;
51
+ //# sourceMappingURL=infer-env.util.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"infer-env.util.d.ts","sourceRoot":"","sources":["../../src/utils/infer-env.util.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAGxD,qCAAqC;AACrC,eAAO,MAAM,eAAe,cAAc,CAAC;AAC3C,eAAO,MAAM,WAAW,UAAU,CAAC;AACnC,eAAO,MAAM,aAAa,YAAY,CAAC;AACvC,eAAO,MAAM,YAAY,WAAW,CAAC;AAWrC;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CACjC,cAAc,EAAE,MAAM,GAAG,SAAS,GAChC,MAAM,GAAG,SAAS,CAMpB;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,oBAAoB,CACzC,IAAI,EAAE,OAAO,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC,EAC1C,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,GAC1B,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAyCtB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,UAAU,CAC/B,IAAI,EAAE,OAAO,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC,EAC1C,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,GAC1B,OAAO,CAAC,IAAI,CAAC,CA2Cf"}
@@ -0,0 +1,53 @@
1
+ import { interpolate as e } from "./interpolate.util.js";
2
+ import { readJson as t } from "./json.util.js";
3
+ import { logger as n } from "./logger.js";
4
+ import "./index.js";
5
+ import r from "picocolors";
6
+ import { readdir as i } from "node:fs/promises";
7
+ //#region src/utils/infer-env.util.ts
8
+ var a = "|DEFAULT|", o = "|ENV|", s = "|LOCAL|", c = "|MODE|", l = [
9
+ /^appsettings\.([^.]+)\.local\.json$/,
10
+ /^appsettings\.([^.]+)\.json$/,
11
+ /^([^.]+)\.local\.env\.json$/,
12
+ /^([^.]+)\.env\.json$/
13
+ ];
14
+ function u(e) {
15
+ if (e?.includes(":")) return e.slice(e.lastIndexOf(":") + 1) || void 0;
16
+ }
17
+ async function d(n, r) {
18
+ let { modes: a = [], root: c = "env" } = n, u = /* @__PURE__ */ new Set(), [d] = await t(e(n.envFile ?? `${c}/appsettings.json`, n, r));
19
+ for (let e in d[o]) u.add(e);
20
+ for (let e in d[s]) u.add(e);
21
+ let f = /* @__PURE__ */ new Set([...Object.keys(d["|MODE|"] ?? {}), ...a]), p;
22
+ try {
23
+ p = await i(c);
24
+ } catch {
25
+ return u;
26
+ }
27
+ for (let e of p) for (let t of l) {
28
+ let n = t.exec(e)?.[1];
29
+ if (n) {
30
+ (!e.startsWith("appsettings.") || !f.has(n)) && u.add(n);
31
+ break;
32
+ }
33
+ }
34
+ return u;
35
+ }
36
+ async function f(e, t) {
37
+ let i = process.env.npm_lifecycle_event, a = e.env ? void 0 : u(i);
38
+ if (!e.env && !a) return;
39
+ let o = await d(e, t);
40
+ if (e.env) {
41
+ o.size > 0 && !o.has(e.env) && n.warn(`environment ${r.yellow(e.env)} is not defined,`, `known environments: ${[...o].sort().join(", ")}`);
42
+ return;
43
+ }
44
+ if (o.size === 0) {
45
+ n.debug(`environment inference from npm script ${r.yellow(i)} skipped,`, "no environments found in workspace");
46
+ return;
47
+ }
48
+ o.has(a) || (n.error(`environment ${r.red(a)} inferred from npm script ${r.yellow(i)} is not defined,`, `known environments: ${[...o].sort().join(", ")},`, "use -e explicitly or define it in appsettings.json or a provider file"), process.exit(1)), e.env = a, n.info(`environment ${r.bold(r.green(a))} inferred from npm script ${r.yellow(i)}`);
49
+ }
50
+ //#endregion
51
+ export { a as SECTION_DEFAULT, o as SECTION_ENV, s as SECTION_LOCAL, c as SECTION_MODE, d as discoverEnvironments, u as inferEnvFromScript, f as resolveEnv };
52
+
53
+ //# sourceMappingURL=infer-env.util.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"infer-env.util.js","names":[],"sources":["../../src/utils/infer-env.util.ts"],"sourcesContent":["import { readdir } from 'node:fs/promises';\nimport pc from 'picocolors';\nimport type { Arguments } from 'yargs';\nimport type { CommandArguments } from '../arguments.js';\nimport { interpolate, logger, readJson } from './index.js';\n\n/** appsettings.json section keys. */\nexport const SECTION_DEFAULT = '|DEFAULT|';\nexport const SECTION_ENV = '|ENV|';\nexport const SECTION_LOCAL = '|LOCAL|';\nexport const SECTION_MODE = '|MODE|';\n\n// filename → env patterns; appsettings.<x>.json is ambiguous with\n// per-mode files, so the caller filters matches against |MODE| keys\nconst ENV_FILE_REGEXES = [\n\t/^appsettings\\.([^.]+)\\.local\\.json$/,\n\t/^appsettings\\.([^.]+)\\.json$/,\n\t/^([^.]+)\\.local\\.env\\.json$/,\n\t/^([^.]+)\\.env\\.json$/,\n];\n\n/**\n * Infers the environment from the npm script name\n * (npm_lifecycle_event), i.e. \"start:dev\" → \"dev\".\n *\n * @export\n * @param {string | undefined} lifecycleEvent npm script name\n *\n * @returns {string | undefined} environment, or undefined\n * when there is no ':' suffix (i.e. \"preview\") or the CLI\n * was invoked outside an npm script\n */\nexport function inferEnvFromScript(\n\tlifecycleEvent: string | undefined,\n): string | undefined {\n\tif (!lifecycleEvent?.includes(':')) return undefined;\n\n\tconst env = lifecycleEvent.slice(lifecycleEvent.lastIndexOf(':') + 1);\n\n\treturn env || undefined;\n}\n\n/**\n * Discovers the environments defined in the workspace, as the union of\n * the |ENV| and |LOCAL| section keys of appsettings.json and the per-env\n * provider files found in the root folder (appsettings.<env>.json,\n * appsettings.<env>.local.json, <env>.env.json, <env>.local.env.json).\n *\n * @export\n * @param {Partial<Arguments<CommandArguments>>} argv preloaded arguments\n * @param {[string, string]} delimiters template delimiters\n *\n * @returns {Promise<Set<string>>} known environments\n */\nexport async function discoverEnvironments(\n\targv: Partial<Arguments<CommandArguments>>,\n\tdelimiters: [string, string],\n): Promise<Set<string>> {\n\tconst { modes = [], root = 'env' } = argv;\n\tconst known = new Set<string>();\n\n\tconst envFile = interpolate(\n\t\t(argv.envFile as string | undefined) ?? `${root}/appsettings.json`,\n\t\targv,\n\t\tdelimiters,\n\t);\n\tconst [appsettings] = await readJson(envFile);\n\n\tfor (const key in appsettings[SECTION_ENV]) known.add(key);\n\tfor (const key in appsettings[SECTION_LOCAL]) known.add(key);\n\n\tconst knownModes = new Set<string>([\n\t\t...Object.keys(appsettings[SECTION_MODE] ?? {}),\n\t\t...modes,\n\t]);\n\n\tlet files: string[];\n\ttry {\n\t\tfiles = await readdir(root);\n\t} catch {\n\t\t// root folder may not exist\n\t\treturn known;\n\t}\n\n\tfor (const file of files) {\n\t\tfor (const regex of ENV_FILE_REGEXES) {\n\t\t\tconst env = regex.exec(file)?.[1];\n\n\t\t\tif (!env) continue;\n\n\t\t\tif (!file.startsWith('appsettings.') || !knownModes.has(env))\n\t\t\t\tknown.add(env);\n\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn known;\n}\n\n/**\n * Resolves argv.env when not provided by -e nor config file,\n * inferring it from the npm script name (npm_lifecycle_event)\n * and validating it against the known environments.\n *\n * Validation rules:\n * - explicit env unknown → warning, continues\n * - inferred env unknown → fatal error listing known environments\n * - no known environments → inference is discarded (debug log)\n *\n * Mutates argv so build()'s middleware propagates the resolved\n * env to the main yargs parse.\n *\n * @export\n * @param {Partial<Arguments<CommandArguments>>} argv preloaded arguments\n * @param {[string, string]} delimiters template delimiters\n */\nexport async function resolveEnv(\n\targv: Partial<Arguments<CommandArguments>>,\n\tdelimiters: [string, string],\n): Promise<void> {\n\tconst script = process.env.npm_lifecycle_event;\n\tconst inferred = argv.env ? undefined : inferEnvFromScript(script);\n\n\tif (!argv.env && !inferred) return;\n\n\tconst known = await discoverEnvironments(argv, delimiters);\n\n\tif (argv.env) {\n\t\tif (known.size > 0 && !known.has(argv.env)) {\n\t\t\tlogger.warn(\n\t\t\t\t`environment ${pc.yellow(argv.env)} is not defined,`,\n\t\t\t\t`known environments: ${[...known].sort().join(', ')}`,\n\t\t\t);\n\t\t}\n\n\t\treturn;\n\t}\n\n\tif (known.size === 0) {\n\t\tlogger.debug(\n\t\t\t`environment inference from npm script ${pc.yellow(script!)} skipped,`,\n\t\t\t'no environments found in workspace',\n\t\t);\n\n\t\treturn;\n\t}\n\n\tif (!known.has(inferred!)) {\n\t\tlogger.error(\n\t\t\t`environment ${pc.red(inferred!)} inferred from npm script ${pc.yellow(script!)} is not defined,`,\n\t\t\t`known environments: ${[...known].sort().join(', ')},`,\n\t\t\t'use -e explicitly or define it in appsettings.json or a provider file',\n\t\t);\n\n\t\tprocess.exit(1);\n\t}\n\n\targv.env = inferred;\n\n\tlogger.info(\n\t\t`environment ${pc.bold(pc.green(inferred!))} inferred from npm script ${pc.yellow(script!)}`,\n\t);\n}\n"],"mappings":";;;;;;;AAOA,IAAa,IAAkB,aAClB,IAAc,SACd,IAAgB,WAChB,IAAe,UAItB,IAAmB;CACxB;CACA;CACA;CACA;AACD;AAaA,SAAgB,EACf,GACqB;CAChB,OAAgB,SAAS,GAAG,GAIjC,OAFY,EAAe,MAAM,EAAe,YAAY,GAAG,IAAI,CAE5D,KAAO,KAAA;AACf;AAcA,eAAsB,EACrB,GACA,GACuB;CACvB,IAAM,EAAE,WAAQ,CAAC,GAAG,UAAO,UAAU,GAC/B,oBAAQ,IAAI,IAAY,GAOxB,CAAC,KAAe,MAAM,EALZ,EACd,EAAK,WAAkC,GAAG,EAAK,oBAChD,GACA,CAEoC,CAAO;CAE5C,KAAK,IAAM,KAAO,EAAY,IAAc,EAAM,IAAI,CAAG;CACzD,KAAK,IAAM,KAAO,EAAY,IAAgB,EAAM,IAAI,CAAG;CAE3D,IAAM,oBAAa,IAAI,IAAY,CAClC,GAAG,OAAO,KAAK,EAAA,aAA6B,CAAC,CAAC,GAC9C,GAAG,CACJ,CAAC,GAEG;CACJ,IAAI;EACH,IAAQ,MAAM,EAAQ,CAAI;CAC3B,QAAQ;EAEP,OAAO;CACR;CAEA,KAAK,IAAM,KAAQ,GAClB,KAAK,IAAM,KAAS,GAAkB;EACrC,IAAM,IAAM,EAAM,KAAK,CAAI,CAAC,GAAG;EAE1B,OAEL;IAAI,CAAC,EAAK,WAAW,cAAc,KAAK,CAAC,EAAW,IAAI,CAAG,MAC1D,EAAM,IAAI,CAAG;GAEd;EAFc;CAGf;CAGD,OAAO;AACR;AAmBA,eAAsB,EACrB,GACA,GACgB;CAChB,IAAM,IAAS,QAAQ,IAAI,qBACrB,IAAW,EAAK,MAAM,KAAA,IAAY,EAAmB,CAAM;CAEjE,IAAI,CAAC,EAAK,OAAO,CAAC,GAAU;CAE5B,IAAM,IAAQ,MAAM,EAAqB,GAAM,CAAU;CAEzD,IAAI,EAAK,KAAK;EACb,AAAI,EAAM,OAAO,KAAK,CAAC,EAAM,IAAI,EAAK,GAAG,KACxC,EAAO,KACN,eAAe,EAAG,OAAO,EAAK,GAAG,EAAE,mBACnC,uBAAuB,CAAC,GAAG,CAAK,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,IAAI,GACnD;EAGD;CACD;CAEA,IAAI,EAAM,SAAS,GAAG;EACrB,EAAO,MACN,yCAAyC,EAAG,OAAO,CAAO,EAAE,YAC5D,oCACD;EAEA;CACD;CAcA,AAZK,EAAM,IAAI,CAAS,MACvB,EAAO,MACN,eAAe,EAAG,IAAI,CAAS,EAAE,4BAA4B,EAAG,OAAO,CAAO,EAAE,mBAChF,uBAAuB,CAAC,GAAG,CAAK,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,IAAI,EAAE,IACpD,uEACD,GAEA,QAAQ,KAAK,CAAC,IAGf,EAAK,MAAM,GAEX,EAAO,KACN,eAAe,EAAG,KAAK,EAAG,MAAM,CAAS,CAAC,EAAE,4BAA4B,EAAG,OAAO,CAAO,GAC1F;AACD"}