@karmaniverous/get-dotenv 6.0.0 → 6.1.1

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.
Files changed (57) hide show
  1. package/README.md +18 -14
  2. package/dist/cli.mjs +744 -360
  3. package/dist/cliHost.d.ts +14 -1
  4. package/dist/cliHost.mjs +54 -8
  5. package/dist/config.d.ts +4 -0
  6. package/dist/config.mjs +17 -7
  7. package/dist/env-overlay.d.ts +11 -0
  8. package/dist/env-overlay.mjs +24 -7
  9. package/dist/getdotenv.cli.mjs +744 -360
  10. package/dist/index.d.ts +88 -2
  11. package/dist/index.mjs +757 -361
  12. package/dist/plugins-aws.d.ts +4 -3
  13. package/dist/plugins-aws.mjs +369 -177
  14. package/dist/plugins-batch.d.ts +2 -1
  15. package/dist/plugins-batch.mjs +124 -48
  16. package/dist/plugins-cmd.d.ts +2 -1
  17. package/dist/plugins-cmd.mjs +77 -22
  18. package/dist/plugins-init.d.ts +2 -1
  19. package/dist/plugins-init.mjs +235 -128
  20. package/dist/plugins.d.ts +7 -2
  21. package/dist/plugins.mjs +740 -360
  22. package/dist/templates/cli/index.ts +1 -2
  23. package/dist/templates/cli/plugins/hello/defaultAction.ts +27 -0
  24. package/dist/templates/cli/plugins/hello/index.ts +26 -0
  25. package/dist/templates/cli/plugins/hello/options.ts +31 -0
  26. package/dist/templates/cli/plugins/hello/strangerAction.ts +20 -0
  27. package/dist/templates/cli/plugins/hello/types.ts +13 -0
  28. package/dist/templates/config/ts/getdotenv.config.ts +1 -1
  29. package/dist/templates/defaultAction.ts +27 -0
  30. package/dist/templates/getdotenv.config.ts +1 -1
  31. package/dist/templates/hello/defaultAction.ts +27 -0
  32. package/dist/templates/hello/index.ts +26 -0
  33. package/dist/templates/hello/options.ts +31 -0
  34. package/dist/templates/hello/strangerAction.ts +20 -0
  35. package/dist/templates/hello/types.ts +13 -0
  36. package/dist/templates/index.ts +22 -22
  37. package/dist/templates/options.ts +31 -0
  38. package/dist/templates/plugins/hello/defaultAction.ts +27 -0
  39. package/dist/templates/plugins/hello/index.ts +26 -0
  40. package/dist/templates/plugins/hello/options.ts +31 -0
  41. package/dist/templates/plugins/hello/strangerAction.ts +20 -0
  42. package/dist/templates/plugins/hello/types.ts +13 -0
  43. package/dist/templates/strangerAction.ts +20 -0
  44. package/dist/templates/ts/getdotenv.config.ts +1 -1
  45. package/dist/templates/types.ts +13 -0
  46. package/package.json +2 -2
  47. package/templates/cli/index.ts +1 -2
  48. package/templates/cli/plugins/hello/defaultAction.ts +27 -0
  49. package/templates/cli/plugins/hello/index.ts +26 -0
  50. package/templates/cli/plugins/hello/options.ts +31 -0
  51. package/templates/cli/plugins/hello/strangerAction.ts +20 -0
  52. package/templates/cli/plugins/hello/types.ts +13 -0
  53. package/templates/config/ts/getdotenv.config.ts +1 -1
  54. package/dist/templates/cli/plugins/hello.ts +0 -43
  55. package/dist/templates/hello.ts +0 -43
  56. package/dist/templates/plugins/hello.ts +0 -43
  57. package/templates/cli/plugins/hello.ts +0 -43
@@ -426,6 +426,7 @@ declare const batchPlugin: (opts?: BatchPluginOptions) => PluginWithInstanceHelp
426
426
  globs?: string | undefined;
427
427
  pkgCwd?: boolean | undefined;
428
428
  }, [], {}, {}>;
429
+ type BatchPlugin = ReturnType<typeof batchPlugin>;
429
430
 
430
431
  export { batchPlugin };
431
- export type { BatchCmdSubcommandOptions, BatchGlobPathsOptions, BatchParentInvokerFlags, ExecShellCommandBatchOptions };
432
+ export type { BatchCmdSubcommandOptions, BatchGlobPathsOptions, BatchParentInvokerFlags, BatchPlugin, ExecShellCommandBatchOptions };
@@ -1,4 +1,3 @@
1
- import { Option, Command } from '@commander-js/extra-typings';
2
1
  import { z } from 'zod';
3
2
  import path, { join, extname } from 'path';
4
3
  import fs from 'fs-extra';
@@ -9,6 +8,7 @@ import { createHash } from 'crypto';
9
8
  import { nanoid } from 'nanoid';
10
9
  import { parse } from 'dotenv';
11
10
  import { execa, execaCommand } from 'execa';
11
+ import { Option, Command } from '@commander-js/extra-typings';
12
12
  import { globby } from 'globby';
13
13
 
14
14
  /**
@@ -152,6 +152,10 @@ function defaultsDeep(...layers) {
152
152
  /**
153
153
  * Serialize a dotenv record to a file with minimal quoting (multiline values are quoted).
154
154
  * Future-proofs for ordering/sorting changes (currently insertion order).
155
+ *
156
+ * @param filename - Destination dotenv file path.
157
+ * @param data - Env-like map of values to write (values may be `undefined`).
158
+ * @returns A `Promise\<void\>` which resolves when the file has been written.
155
159
  */
156
160
  async function writeDotenvFile(filename, data) {
157
161
  // Serialize: key=value with quotes only for multiline values.
@@ -387,14 +391,20 @@ const cleanupOldCacheFiles = async (cacheDir, baseName, keep = Math.max(1, Numbe
387
391
  }
388
392
  };
389
393
  /**
390
- * Load a module default export from a JS/TS file with robust fallbacks:
391
- * - .js/.mjs/.cjs: direct import * - .ts/.mts/.cts/.tsx:
392
- * 1) try direct import (if a TS loader is active),
393
- * 2) esbuild bundle to a temp ESM file,
394
- * 3) typescript.transpileModule fallback for simple modules.
394
+ * Load a module default export from a JS/TS file with robust fallbacks.
395
+ *
396
+ * Behavior by extension:
395
397
  *
396
- * @param absPath - absolute path to source file
397
- * @param cacheDirName - cache subfolder under .tsbuild
398
+ * - `.js`/`.mjs`/`.cjs`: direct dynamic import.
399
+ * - `.ts`/`.mts`/`.cts`/`.tsx`:
400
+ * - try direct dynamic import (when a TS loader is active),
401
+ * - else compile via `esbuild` to a cached `.mjs` file and import,
402
+ * - else fallback to `typescript.transpileModule` for simple modules.
403
+ *
404
+ * @typeParam T - Type of the expected default export.
405
+ * @param absPath - Absolute path to the source file.
406
+ * @param cacheDirName - Cache subfolder under `.tsbuild/`.
407
+ * @returns A `Promise\<T | undefined\>` resolving to the default export (if any).
398
408
  */
399
409
  const loadModuleDefault = async (absPath, cacheDirName) => {
400
410
  const ext = path.extname(absPath).toLowerCase();
@@ -466,6 +476,10 @@ const loadModuleDefault = async (absPath, cacheDirName) => {
466
476
  /**
467
477
  * Omit keys whose runtime value is undefined from a shallow object.
468
478
  * Returns a Partial with non-undefined value types preserved.
479
+ *
480
+ * @typeParam T - Input object shape.
481
+ * @param obj - Object to filter.
482
+ * @returns A shallow copy of `obj` without keys whose value is `undefined`.
469
483
  */
470
484
  function omitUndefined(obj) {
471
485
  const out = {};
@@ -477,6 +491,10 @@ function omitUndefined(obj) {
477
491
  }
478
492
  /**
479
493
  * Specialized helper for env-like maps: drop undefined and return string-only.
494
+ *
495
+ * @typeParam V - Value type for present entries (must extend `string`).
496
+ * @param obj - Env-like record containing `string | undefined` values.
497
+ * @returns A new record containing only the keys with defined values.
480
498
  */
481
499
  function omitUndefinedRecord(obj) {
482
500
  const out = {};
@@ -691,6 +709,11 @@ const resolveGetDotenvConfigSources = async (importMetaUrl) => {
691
709
  * Apply a dynamic map to the target progressively.
692
710
  * - Functions receive (target, env) and may return string | undefined.
693
711
  * - Literals are assigned directly (including undefined).
712
+ *
713
+ * @param target - Mutable target environment to assign into.
714
+ * @param map - Dynamic map to apply (functions and/or literal values).
715
+ * @param env - Selected environment name (if any) passed through to dynamic functions.
716
+ * @returns Nothing.
694
717
  */
695
718
  function applyDynamicMap(target, map, env) {
696
719
  if (!map)
@@ -710,6 +733,12 @@ function applyDynamicMap(target, map, env) {
710
733
  * Error behavior:
711
734
  * - On failure to load/compile/evaluate the module, throws a unified message:
712
735
  * "Unable to load dynamic TypeScript file: <absPath>. Install 'esbuild'..."
736
+ *
737
+ * @param target - Mutable target environment to assign into.
738
+ * @param absPath - Absolute path to the dynamic module file.
739
+ * @param env - Selected environment name (if any).
740
+ * @param cacheDirName - Cache subdirectory under `.tsbuild/` for compiled artifacts.
741
+ * @returns A `Promise\<void\>` which resolves after the module (if present) has been applied.
713
742
  */
714
743
  async function loadAndApplyDynamic(target, absPath, env, cacheDirName) {
715
744
  if (!(await fs.exists(absPath)))
@@ -1781,6 +1810,10 @@ function renderOptionGroups(cmd) {
1781
1810
  /**
1782
1811
  * Compose root/parent help output by inserting grouped sections between
1783
1812
  * Options and Commands, ensuring a trailing blank line.
1813
+ *
1814
+ * @param base - Base help text produced by Commander.
1815
+ * @param cmd - Command instance whose grouped options should be rendered.
1816
+ * @returns The modified help text with grouped blocks inserted.
1784
1817
  */
1785
1818
  function buildHelpInformation(base, cmd) {
1786
1819
  const groups = renderOptionGroups(cmd);
@@ -2276,6 +2309,10 @@ class GetDotenvCli extends Command {
2276
2309
  /**
2277
2310
  * Compose a child-process env overlay from dotenv and the merged CLI options bag.
2278
2311
  * Returns a shallow object including getDotenvCliOptions when serializable.
2312
+ *
2313
+ * @param merged - Resolved CLI options bag (or a JSON-serializable subset).
2314
+ * @param dotenv - Composed dotenv variables for the current invocation.
2315
+ * @returns A string-only env overlay suitable for child process spawning.
2279
2316
  */
2280
2317
  function composeNestedEnv(merged, dotenv) {
2281
2318
  const out = {};
@@ -2298,6 +2335,7 @@ function composeNestedEnv(merged, dotenv) {
2298
2335
  * Strip one layer of symmetric outer quotes (single or double) from a string.
2299
2336
  *
2300
2337
  * @param s - Input string.
2338
+ * @returns `s` without one symmetric outer quote pair (when present).
2301
2339
  */
2302
2340
  const stripOne = (s) => {
2303
2341
  if (s.length < 2)
@@ -2310,6 +2348,9 @@ const stripOne = (s) => {
2310
2348
  /**
2311
2349
  * Preserve argv array for Node -e/--eval payloads under shell-off and
2312
2350
  * peel one symmetric outer quote layer from the code argument.
2351
+ *
2352
+ * @param args - Argument vector intended for direct execution (shell-off).
2353
+ * @returns Either the original `args` or a modified copy with a normalized eval payload.
2313
2354
  */
2314
2355
  function maybePreserveNodeEvalArgv(args) {
2315
2356
  if (args.length >= 3) {
@@ -2530,7 +2571,7 @@ const execShellCommandBatch = async ({ command, getDotenvCliOptions, dotenvEnv,
2530
2571
  /**
2531
2572
  * Attach the default "cmd" subcommand action with contextual typing.
2532
2573
  */
2533
- const attachDefaultCmdAction = (plugin, cli, batchCmd, pluginOpts, cmd) => {
2574
+ const attachBatchCmdAction = (plugin, cli, batchCmd, pluginOpts, cmd) => {
2534
2575
  cmd.action(async (commandParts, _subOpts, thisCommand) => {
2535
2576
  const mergedBag = readMergedOptions(batchCmd);
2536
2577
  const logger = mergedBag.logger;
@@ -2639,11 +2680,37 @@ const attachDefaultCmdAction = (plugin, cli, batchCmd, pluginOpts, cmd) => {
2639
2680
  });
2640
2681
  };
2641
2682
 
2683
+ /**
2684
+ * Attach the default `cmd` subcommand under the `batch` command.
2685
+ *
2686
+ * This encapsulates:
2687
+ * - Subcommand construction (`new Command().name('cmd')…`)
2688
+ * - Action wiring
2689
+ * - Mounting as the default subcommand for `batch`
2690
+ *
2691
+ * @param plugin - The batch plugin instance.
2692
+ * @param cli - The batch command mount.
2693
+ * @param batchCmd - The `batch` command (same as `cli` mount).
2694
+ * @param pluginOpts - Batch plugin factory options.
2695
+ *
2696
+ * @internal
2697
+ */
2698
+ const attachBatchCmdSubcommand = (plugin, cli, batchCmd, pluginOpts) => {
2699
+ const cmdSub = new Command()
2700
+ .name('cmd')
2701
+ .description('execute command, conflicts with --command option (default subcommand)')
2702
+ .enablePositionalOptions()
2703
+ .passThroughOptions()
2704
+ .argument('[command...]');
2705
+ attachBatchCmdAction(plugin, cli, batchCmd, pluginOpts, cmdSub);
2706
+ batchCmd.addCommand(cmdSub, { isDefault: true });
2707
+ };
2708
+
2642
2709
  /**
2643
2710
  * Attach the parent-level action for the batch plugin.
2644
2711
  * Handles parent flags (e.g. `getdotenv batch -l`) and delegates to the batch executor.
2645
2712
  */
2646
- const attachParentInvoker = (plugin, cli, pluginOpts, parent) => {
2713
+ const attachBatchDefaultAction = (plugin, cli, pluginOpts, parent) => {
2647
2714
  parent.action(async function (...args) {
2648
2715
  // Commander Unknown generics: [...unknown[], OptionValues, thisCommand]
2649
2716
  const thisCommand = args[args.length - 1];
@@ -2744,6 +2811,45 @@ const attachParentInvoker = (plugin, cli, pluginOpts, parent) => {
2744
2811
  });
2745
2812
  };
2746
2813
 
2814
+ /**
2815
+ * Attach options/arguments for the batch plugin mount.
2816
+ *
2817
+ * Note: the plugin description is owned by `src/plugins/batch/index.ts` and
2818
+ * must not be set here.
2819
+ *
2820
+ * @param plugin - Batch plugin instance (for dynamic option descriptions).
2821
+ * @param cli - The `batch` command mount.
2822
+ * @returns The same `cli` instance for chaining.
2823
+ *
2824
+ * @internal
2825
+ */
2826
+ function attachBatchOptions(plugin, cli) {
2827
+ const GROUP = `plugin:${cli.name()}`;
2828
+ return (cli
2829
+ .enablePositionalOptions()
2830
+ .passThroughOptions()
2831
+ // Dynamic help: show effective defaults from the merged/interpolated plugin config slice.
2832
+ .addOption((() => {
2833
+ const opt = plugin.createPluginDynamicOption(cli, '-p, --pkg-cwd', (_bag, cfg) => `use nearest package directory as current working directory${cfg.pkgCwd ? ' (default)' : ''}`);
2834
+ cli.setOptionGroup(opt, GROUP);
2835
+ return opt;
2836
+ })())
2837
+ .addOption((() => {
2838
+ const opt = plugin.createPluginDynamicOption(cli, '-r, --root-path <string>', (_bag, cfg) => `path to batch root directory from current working directory (default: ${JSON.stringify(cfg.rootPath || './')})`);
2839
+ cli.setOptionGroup(opt, GROUP);
2840
+ return opt;
2841
+ })())
2842
+ .addOption((() => {
2843
+ const opt = plugin.createPluginDynamicOption(cli, '-g, --globs <string>', (_bag, cfg) => `space-delimited globs from root path (default: ${JSON.stringify(cfg.globs || '*')})`);
2844
+ cli.setOptionGroup(opt, GROUP);
2845
+ return opt;
2846
+ })())
2847
+ .option('-c, --command <string>', 'command executed according to the base shell resolution')
2848
+ .option('-l, --list', 'list working directories without executing command')
2849
+ .option('-e, --ignore-errors', 'ignore errors and continue with next path')
2850
+ .argument('[command...]'));
2851
+ }
2852
+
2747
2853
  /**
2748
2854
  * Zod schema for a single script entry (string or object).
2749
2855
  */
@@ -2757,7 +2863,7 @@ const ScriptSchema = z.union([
2757
2863
  /**
2758
2864
  * Zod schema for batch plugin configuration.
2759
2865
  */
2760
- const BatchConfigSchema = z.object({
2866
+ const batchPluginConfigSchema = z.object({
2761
2867
  scripts: z.record(z.string(), ScriptSchema).optional(),
2762
2868
  shell: z.union([z.string(), z.boolean()]).optional(),
2763
2869
  rootPath: z.string().optional(),
@@ -2783,45 +2889,15 @@ const batchPlugin = (opts = {}) => {
2783
2889
  ns: 'batch',
2784
2890
  // Host validates this when config-loader is enabled; plugins may also
2785
2891
  // re-validate at action time as a safety belt.
2786
- configSchema: BatchConfigSchema,
2892
+ configSchema: batchPluginConfigSchema,
2787
2893
  setup(cli) {
2788
2894
  const batchCmd = cli; // mount provided by host
2789
- const GROUP = `plugin:${cli.name()}`;
2790
- batchCmd
2791
- .description('Batch command execution across multiple working directories.')
2792
- .enablePositionalOptions()
2793
- .passThroughOptions()
2794
- // Dynamic help: show effective defaults from the merged/interpolated plugin config slice.
2795
- .addOption((() => {
2796
- const opt = plugin.createPluginDynamicOption(cli, '-p, --pkg-cwd', (_bag, cfg) => `use nearest package directory as current working directory${cfg.pkgCwd ? ' (default)' : ''}`);
2797
- cli.setOptionGroup(opt, GROUP);
2798
- return opt;
2799
- })())
2800
- .addOption((() => {
2801
- const opt = plugin.createPluginDynamicOption(cli, '-r, --root-path <string>', (_bag, cfg) => `path to batch root directory from current working directory (default: ${JSON.stringify(cfg.rootPath || './')})`);
2802
- cli.setOptionGroup(opt, GROUP);
2803
- return opt;
2804
- })())
2805
- .addOption((() => {
2806
- const opt = plugin.createPluginDynamicOption(cli, '-g, --globs <string>', (_bag, cfg) => `space-delimited globs from root path (default: ${JSON.stringify(cfg.globs || '*')})`);
2807
- cli.setOptionGroup(opt, GROUP);
2808
- return opt;
2809
- })())
2810
- .option('-c, --command <string>', 'command executed according to the base shell resolution')
2811
- .option('-l, --list', 'list working directories without executing command')
2812
- .option('-e, --ignore-errors', 'ignore errors and continue with next path')
2813
- .argument('[command...]');
2814
- // Default subcommand "cmd" with contextual typing for args/opts
2815
- const cmdSub = new Command()
2816
- .name('cmd')
2817
- .description('execute command, conflicts with --command option (default subcommand)')
2818
- .enablePositionalOptions()
2819
- .passThroughOptions()
2820
- .argument('[command...]');
2821
- attachDefaultCmdAction(plugin, cli, batchCmd, opts, cmdSub);
2822
- batchCmd.addCommand(cmdSub, { isDefault: true });
2823
- // Parent invoker (unified naming)
2824
- attachParentInvoker(plugin, cli, opts, batchCmd);
2895
+ batchCmd.description('Batch command execution across multiple working directories.');
2896
+ attachBatchOptions(plugin, batchCmd);
2897
+ // Default subcommand `cmd` (mounted as batch default subcommand)
2898
+ attachBatchCmdSubcommand(plugin, cli, batchCmd, opts);
2899
+ // Default action for the batch command mount (parent flags and positional form)
2900
+ attachBatchDefaultAction(plugin, cli, opts, batchCmd);
2825
2901
  return undefined;
2826
2902
  },
2827
2903
  });
@@ -342,6 +342,7 @@ interface RunCmdWithContextOptions {
342
342
  declare const cmdPlugin: (options?: CmdPluginOptions) => PluginWithInstanceHelpers<GetDotenvOptions, {
343
343
  expand?: boolean | undefined;
344
344
  }, [], {}, {}>;
345
+ type CmdPlugin = ReturnType<typeof cmdPlugin>;
345
346
 
346
347
  export { cmdPlugin };
347
- export type { RunCmdWithContextOptions };
348
+ export type { CmdPlugin, RunCmdWithContextOptions };
@@ -151,6 +151,10 @@ function defaultsDeep(...layers) {
151
151
  /**
152
152
  * Serialize a dotenv record to a file with minimal quoting (multiline values are quoted).
153
153
  * Future-proofs for ordering/sorting changes (currently insertion order).
154
+ *
155
+ * @param filename - Destination dotenv file path.
156
+ * @param data - Env-like map of values to write (values may be `undefined`).
157
+ * @returns A `Promise\<void\>` which resolves when the file has been written.
154
158
  */
155
159
  async function writeDotenvFile(filename, data) {
156
160
  // Serialize: key=value with quotes only for multiline values.
@@ -386,14 +390,20 @@ const cleanupOldCacheFiles = async (cacheDir, baseName, keep = Math.max(1, Numbe
386
390
  }
387
391
  };
388
392
  /**
389
- * Load a module default export from a JS/TS file with robust fallbacks:
390
- * - .js/.mjs/.cjs: direct import * - .ts/.mts/.cts/.tsx:
391
- * 1) try direct import (if a TS loader is active),
392
- * 2) esbuild bundle to a temp ESM file,
393
- * 3) typescript.transpileModule fallback for simple modules.
393
+ * Load a module default export from a JS/TS file with robust fallbacks.
394
+ *
395
+ * Behavior by extension:
396
+ *
397
+ * - `.js`/`.mjs`/`.cjs`: direct dynamic import.
398
+ * - `.ts`/`.mts`/`.cts`/`.tsx`:
399
+ * - try direct dynamic import (when a TS loader is active),
400
+ * - else compile via `esbuild` to a cached `.mjs` file and import,
401
+ * - else fallback to `typescript.transpileModule` for simple modules.
394
402
  *
395
- * @param absPath - absolute path to source file
396
- * @param cacheDirName - cache subfolder under .tsbuild
403
+ * @typeParam T - Type of the expected default export.
404
+ * @param absPath - Absolute path to the source file.
405
+ * @param cacheDirName - Cache subfolder under `.tsbuild/`.
406
+ * @returns A `Promise\<T | undefined\>` resolving to the default export (if any).
397
407
  */
398
408
  const loadModuleDefault = async (absPath, cacheDirName) => {
399
409
  const ext = path.extname(absPath).toLowerCase();
@@ -465,6 +475,10 @@ const loadModuleDefault = async (absPath, cacheDirName) => {
465
475
  /**
466
476
  * Omit keys whose runtime value is undefined from a shallow object.
467
477
  * Returns a Partial with non-undefined value types preserved.
478
+ *
479
+ * @typeParam T - Input object shape.
480
+ * @param obj - Object to filter.
481
+ * @returns A shallow copy of `obj` without keys whose value is `undefined`.
468
482
  */
469
483
  function omitUndefined(obj) {
470
484
  const out = {};
@@ -476,6 +490,10 @@ function omitUndefined(obj) {
476
490
  }
477
491
  /**
478
492
  * Specialized helper for env-like maps: drop undefined and return string-only.
493
+ *
494
+ * @typeParam V - Value type for present entries (must extend `string`).
495
+ * @param obj - Env-like record containing `string | undefined` values.
496
+ * @returns A new record containing only the keys with defined values.
479
497
  */
480
498
  function omitUndefinedRecord(obj) {
481
499
  const out = {};
@@ -696,6 +714,11 @@ const resolveGetDotenvConfigSources = async (importMetaUrl) => {
696
714
  * Apply a dynamic map to the target progressively.
697
715
  * - Functions receive (target, env) and may return string | undefined.
698
716
  * - Literals are assigned directly (including undefined).
717
+ *
718
+ * @param target - Mutable target environment to assign into.
719
+ * @param map - Dynamic map to apply (functions and/or literal values).
720
+ * @param env - Selected environment name (if any) passed through to dynamic functions.
721
+ * @returns Nothing.
699
722
  */
700
723
  function applyDynamicMap(target, map, env) {
701
724
  if (!map)
@@ -715,6 +738,12 @@ function applyDynamicMap(target, map, env) {
715
738
  * Error behavior:
716
739
  * - On failure to load/compile/evaluate the module, throws a unified message:
717
740
  * "Unable to load dynamic TypeScript file: <absPath>. Install 'esbuild'..."
741
+ *
742
+ * @param target - Mutable target environment to assign into.
743
+ * @param absPath - Absolute path to the dynamic module file.
744
+ * @param env - Selected environment name (if any).
745
+ * @param cacheDirName - Cache subdirectory under `.tsbuild/` for compiled artifacts.
746
+ * @returns A `Promise\<void\>` which resolves after the module (if present) has been applied.
718
747
  */
719
748
  async function loadAndApplyDynamic(target, absPath, env, cacheDirName) {
720
749
  if (!(await fs.exists(absPath)))
@@ -1863,6 +1892,10 @@ function renderOptionGroups(cmd) {
1863
1892
  /**
1864
1893
  * Compose root/parent help output by inserting grouped sections between
1865
1894
  * Options and Commands, ensuring a trailing blank line.
1895
+ *
1896
+ * @param base - Base help text produced by Commander.
1897
+ * @param cmd - Command instance whose grouped options should be rendered.
1898
+ * @returns The modified help text with grouped blocks inserted.
1866
1899
  */
1867
1900
  function buildHelpInformation(base, cmd) {
1868
1901
  const groups = renderOptionGroups(cmd);
@@ -2364,6 +2397,10 @@ const baseGetDotenvCliOptions = baseRootOptionDefaults;
2364
2397
  /**
2365
2398
  * Compose a child-process env overlay from dotenv and the merged CLI options bag.
2366
2399
  * Returns a shallow object including getDotenvCliOptions when serializable.
2400
+ *
2401
+ * @param merged - Resolved CLI options bag (or a JSON-serializable subset).
2402
+ * @param dotenv - Composed dotenv variables for the current invocation.
2403
+ * @returns A string-only env overlay suitable for child process spawning.
2367
2404
  */
2368
2405
  function composeNestedEnv(merged, dotenv) {
2369
2406
  const out = {};
@@ -2386,6 +2423,7 @@ function composeNestedEnv(merged, dotenv) {
2386
2423
  * Strip one layer of symmetric outer quotes (single or double) from a string.
2387
2424
  *
2388
2425
  * @param s - Input string.
2426
+ * @returns `s` without one symmetric outer quote pair (when present).
2389
2427
  */
2390
2428
  const stripOne = (s) => {
2391
2429
  if (s.length < 2)
@@ -2398,6 +2436,9 @@ const stripOne = (s) => {
2398
2436
  /**
2399
2437
  * Preserve argv array for Node -e/--eval payloads under shell-off and
2400
2438
  * peel one symmetric outer quote layer from the code argument.
2439
+ *
2440
+ * @param args - Argument vector intended for direct execution (shell-off).
2441
+ * @returns Either the original `args` or a modified copy with a normalized eval payload.
2401
2442
  */
2402
2443
  function maybePreserveNodeEvalArgv(args) {
2403
2444
  if (args.length >= 3) {
@@ -2727,14 +2768,11 @@ async function runCmdWithContext(cli, merged, command, _opts) {
2727
2768
  }
2728
2769
 
2729
2770
  /**
2730
- * Attach the default "cmd" subcommand action (unified name).
2771
+ * Attach the default "cmd" subcommand action.
2731
2772
  * Mirrors the prior inline implementation in cmd/index.ts.
2732
2773
  */
2733
- const attachDefaultCmdAction = (cli, cmd, aliasKey) => {
2734
- cmd
2735
- .enablePositionalOptions()
2736
- .passThroughOptions()
2737
- .action(async function (...allArgs) {
2774
+ const attachCmdDefaultAction = (cli, cmd, aliasKey) => {
2775
+ cmd.action(async function (...allArgs) {
2738
2776
  // Commander passes: [...positionals, options, thisCommand]
2739
2777
  const thisCommand = allArgs[allArgs.length - 1];
2740
2778
  const commandParts = allArgs[0];
@@ -2767,11 +2805,29 @@ const attachDefaultCmdAction = (cli, cmd, aliasKey) => {
2767
2805
  });
2768
2806
  };
2769
2807
 
2808
+ /**
2809
+ * Attach options/arguments for the cmd plugin mount.
2810
+ *
2811
+ * Note: the plugin description is owned by `src/plugins/cmd/index.ts` and must
2812
+ * not be set here.
2813
+ *
2814
+ * @param cli - The `cmd` command mount.
2815
+ * @returns The same `cli` instance for chaining.
2816
+ *
2817
+ * @internal
2818
+ */
2819
+ function attachCmdOptions(cli) {
2820
+ return cli
2821
+ .enablePositionalOptions()
2822
+ .passThroughOptions()
2823
+ .argument('[command...]');
2824
+ }
2825
+
2770
2826
  /**
2771
2827
  * Install the parent-level invoker (alias) for the cmd plugin.
2772
2828
  * Unifies naming with batch attachParentInvoker; behavior unchanged.
2773
2829
  */
2774
- const attachParentInvoker = (cli, options, _cmd, plugin) => {
2830
+ const attachCmdParentInvoker = (cli, options, plugin) => {
2775
2831
  const dbg = (...args) => {
2776
2832
  if (process.env.GETDOTENV_DEBUG) {
2777
2833
  try {
@@ -2882,7 +2938,7 @@ const attachParentInvoker = (cli, options, _cmd, plugin) => {
2882
2938
  /**
2883
2939
  * Zod schema for cmd plugin configuration.
2884
2940
  */
2885
- const CmdConfigSchema = z
2941
+ const cmdPluginConfigSchema = z
2886
2942
  .object({
2887
2943
  expand: z.boolean().optional(),
2888
2944
  })
@@ -2902,7 +2958,7 @@ const CmdConfigSchema = z
2902
2958
  const cmdPlugin = (options = {}) => {
2903
2959
  const plugin = definePlugin({
2904
2960
  ns: 'cmd',
2905
- configSchema: CmdConfigSchema,
2961
+ configSchema: cmdPluginConfigSchema,
2906
2962
  setup(cli) {
2907
2963
  const aliasSpec = typeof options.optionAlias === 'string'
2908
2964
  ? { flags: options.optionAlias}
@@ -2914,14 +2970,13 @@ const cmdPlugin = (options = {}) => {
2914
2970
  };
2915
2971
  const aliasKey = aliasSpec ? deriveKey(aliasSpec.flags) : undefined;
2916
2972
  // Mount is the command ('cmd'); attach default action.
2917
- cli
2918
- .description('Execute command according to the --shell option, conflicts with --command option (default subcommand)')
2919
- // Accept payload tokens as positional arguments for the default subcommand.
2920
- .argument('[command...]');
2921
- attachDefaultCmdAction(cli, cli, aliasKey);
2973
+ cli.description('Execute command according to the --shell option, conflicts with --command option (default subcommand)');
2974
+ // Options/arguments (positional payload, argv routing) are attached separately.
2975
+ attachCmdOptions(cli);
2976
+ attachCmdDefaultAction(cli, cli, aliasKey);
2922
2977
  // Parent-attached option alias (optional, unified naming).
2923
2978
  if (aliasSpec !== undefined) {
2924
- attachParentInvoker(cli, options, cli, plugin);
2979
+ attachCmdParentInvoker(cli, options, plugin);
2925
2980
  }
2926
2981
  return undefined;
2927
2982
  },
@@ -329,6 +329,7 @@ interface PlanCliCopiesOptions {
329
329
  * Supports collision detection, interactive prompts, and CI bypass.
330
330
  */
331
331
  declare const initPlugin: () => PluginWithInstanceHelpers<GetDotenvOptions, {}, [], {}, {}>;
332
+ type InitPlugin = ReturnType<typeof initPlugin>;
332
333
 
333
334
  export { initPlugin };
334
- export type { PlanCliCopiesOptions, PlanConfigCopiesOptions };
335
+ export type { InitPlugin, PlanCliCopiesOptions, PlanConfigCopiesOptions };