@karmaniverous/get-dotenv 4.3.2 → 4.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/README.md CHANGED
@@ -10,7 +10,7 @@ Load environment variables with a cascade of environment-aware dotenv files. You
10
10
  - Private files (e.g. `.env.local`, `env.dev.local`, `env.test.local`) are protected by `.gitignore`.
11
11
  - Global files (e.g. `.env`, `env.local`) apply to all environments.
12
12
  - Env files (e.g. `.env.dev`, `.env.dev.local`, `.env.test`, `.env.test.local`) apply to a specific environment.
13
- - Dynamic files (`.env.js`) export logic that dynamically & progressively generates new variables or overrides current ones.
13
+ - [Dynamic files](#dynamic-processing) (`.env.js`) export logic that dynamically & progressively generates new variables or overrides current ones.
14
14
 
15
15
  ✅ Dynamically specify which variables to load by type.
16
16
 
@@ -20,11 +20,13 @@ Load environment variables with a cascade of environment-aware dotenv files. You
20
20
 
21
21
  ✅ Customize your dotenv file directories & naming patterns.
22
22
 
23
- ✅ Perform all of the above either programmatically or from the command line, where you can also execute additional shell commands within the resulting context... including nested `getdotenv` commands that inherit the parent command's settings & context!
23
+ ✅ Perform all of the above either programmatically or [from the command line](#command-line-interface), where you can also execute additional commands within the resulting context... including nested `getdotenv` commands that inherit the parent command's settings & context!
24
+
25
+ ✅ [Execute batched CLI commands](#batch-command) across multiple working directories, with each command inheriting the `getdotenv` context.
24
26
 
25
27
  ✅ Set defaults for all options in a `getdotenv.config.json` file in your project root directory.
26
28
 
27
- ✅ Generate an extensible `getdotenv`-based CLI for use in your own projects.
29
+ [Generate an extensible `getdotenv`-based CLI](https://github.com/karmaniverous/get-dotenv-child) for use in your own projects.
28
30
 
29
31
  `getdotenv` relies on the excellent [`dotenv`](https://www.npmjs.com/package/dotenv) parser and somewhat improves on [`dotenv-expand`](https://www.npmjs.com/package/dotenv-expand) for recursive variable expansion.
30
32
 
@@ -113,6 +115,8 @@ You can also use `getdotenv` from the command line:
113
115
  # -v, --vars <string> extra variables expressed as delimited key-value pairs (dotenv-expanded): KEY1=VAL1 KEY2=VAL2
114
116
  # -c, --command <string> shell command string, conflicts with cmd subcommand (dotenv-expanded)
115
117
  # -o, --output-path <string> consolidated output file (dotenv-expanded)
118
+ # -s, --shell [string] command execution shell, no argument for default OS shell or provide shell string (default OS shell)
119
+ # -S, --shell-off command execution shell OFF
116
120
  # -p, --load-process load variables to process.env ON (default)
117
121
  # -P, --load-process-off load variables to process.env OFF
118
122
  # -a, --exclude-all exclude all dotenv variables from loading ON
@@ -150,6 +154,12 @@ You can also use `getdotenv` from the command line:
150
154
  # help [command] display help for command
151
155
  ```
152
156
 
157
+ By default, commands (`-c` or `--command` or the `cmd` subcommand) execute in the default OS shell with the `dotenv` context applied. The `-S` or `--shell-off` options will turn this off, and Execa will [execute your command as Javascript](https://github.com/sindresorhus/execa/blob/main/docs/bash.md).
158
+
159
+ Alternatively, you can use the `-s` or `--shell` option to specify a different shell [following the Execa spec](https://github.com/sindresorhus/execa/blob/main/docs/shell.md). This is useful if you're running a command that requires a specific shell, like `bash` or `zsh`.
160
+
161
+ Finally, you can set the [`shell`](https://github.com/karmaniverous/get-dotenv-child?tab=readme-ov-file#options) default globally in your `getdotenv.config.json` file.
162
+
153
163
  See [this example repo](https://github.com/karmaniverous/get-dotenv-child) for a deep dive on using the `getDotenv` CLI and how to extend it for your own projects.
154
164
 
155
165
  ### Batch Command
@@ -5055,11 +5055,11 @@ function resolveCommandAttempt(parsed, withoutPathExt) {
5055
5055
  return resolved;
5056
5056
  }
5057
5057
 
5058
- function resolveCommand$1(parsed) {
5058
+ function resolveCommand$2(parsed) {
5059
5059
  return resolveCommandAttempt(parsed) || resolveCommandAttempt(parsed, true);
5060
5060
  }
5061
5061
 
5062
- var resolveCommand_1 = resolveCommand$1;
5062
+ var resolveCommand_1 = resolveCommand$2;
5063
5063
 
5064
5064
  var _escape = {};
5065
5065
 
@@ -5151,7 +5151,7 @@ function readShebang$1(command) {
5151
5151
  var readShebang_1 = readShebang$1;
5152
5152
 
5153
5153
  const path$o = require$$0$2;
5154
- const resolveCommand = resolveCommand_1;
5154
+ const resolveCommand$1 = resolveCommand_1;
5155
5155
  const escape = _escape;
5156
5156
  const readShebang = readShebang_1;
5157
5157
 
@@ -5160,7 +5160,7 @@ const isExecutableRegExp = /\.(?:com|exe)$/i;
5160
5160
  const isCmdShimRegExp = /node_modules[\\/].bin[\\/][^\\/]+\.cmd$/i;
5161
5161
 
5162
5162
  function detectShebang(parsed) {
5163
- parsed.file = resolveCommand(parsed);
5163
+ parsed.file = resolveCommand$1(parsed);
5164
5164
 
5165
5165
  const shebang = parsed.file && readShebang(parsed.file);
5166
5166
 
@@ -5168,7 +5168,7 @@ function detectShebang(parsed) {
5168
5168
  parsed.args.unshift(parsed.file);
5169
5169
  parsed.command = shebang;
5170
5170
 
5171
- return resolveCommand(parsed);
5171
+ return resolveCommand$1(parsed);
5172
5172
  }
5173
5173
 
5174
5174
  return parsed.file;
@@ -31149,9 +31149,13 @@ const baseGetDotenvCliOptions = {
31149
31149
  paths: './',
31150
31150
  pathsDelimiter: ' ',
31151
31151
  privateToken: 'local',
31152
- shellScripts: {
31153
- 'git-status': 'git branch --show-current && git status -s -u',
31152
+ scripts: {
31153
+ 'git-status': {
31154
+ cmd: 'git branch --show-current && git status -s -u',
31155
+ shell: true,
31156
+ },
31154
31157
  },
31158
+ shell: true,
31155
31159
  vars: '',
31156
31160
  varsAssignor: '=',
31157
31161
  varsDelimiter: ' ',
@@ -31166,7 +31170,7 @@ const getDotenvOptionsFilename = 'getdotenv.config.json';
31166
31170
  * @returns `getDotenv` options.
31167
31171
  */
31168
31172
  const getDotenvCliOptions2Options = ({ paths, pathsDelimiter, pathsDelimiterPattern, vars, varsAssignor, varsAssignorPattern, varsDelimiter, varsDelimiterPattern, ...rest }) => ({
31169
- ..._.omit(rest, ['debug', 'shellScripts']),
31173
+ ..._.omit(rest, ['debug', 'scripts']),
31170
31174
  paths: paths?.split(pathsDelimiterPattern
31171
31175
  ? RegExp(pathsDelimiterPattern)
31172
31176
  : pathsDelimiter ?? ' ') ?? [],
@@ -31738,6 +31742,11 @@ const getDotenv = async (options = {}) => {
31738
31742
  return dotenv;
31739
31743
  };
31740
31744
 
31745
+ const resolveCommand = (scripts, command) => (scripts && _.isObject(scripts[command])
31746
+ ? scripts[command].cmd
31747
+ : scripts?.[command] ?? command);
31748
+ const resolveShell = (scripts, command, shell) => (scripts && _.isObject(scripts[command]) ? scripts[command].shell : shell);
31749
+
31741
31750
  /*
31742
31751
  * merge2
31743
31752
  * https://github.com/teambition/merge2
@@ -39479,7 +39488,7 @@ const globPaths = async ({ globs, logger, pkgCwd, rootPath, }) => {
39479
39488
  }
39480
39489
  return { absRootPath, paths };
39481
39490
  };
39482
- const execShellCommandBatch = async ({ command, globs, ignoreErrors, list, logger, pkgCwd, rootPath, }) => {
39491
+ const execShellCommandBatch = async ({ command, getDotenvCliOptions, globs, ignoreErrors, list, logger, pkgCwd, rootPath, shell, }) => {
39483
39492
  if (!command) {
39484
39493
  logger.error(`No command provided.`);
39485
39494
  process.exit(0);
@@ -39518,8 +39527,13 @@ const execShellCommandBatch = async ({ command, globs, ignoreErrors, list, logge
39518
39527
  try {
39519
39528
  await execaCommand(command, {
39520
39529
  cwd: path,
39530
+ env: {
39531
+ getDotenvCliOptions: getDotenvCliOptions
39532
+ ? JSON.stringify(getDotenvCliOptions)
39533
+ : undefined,
39534
+ },
39521
39535
  stdio: 'inherit',
39522
- shell: true,
39536
+ shell,
39523
39537
  });
39524
39538
  }
39525
39539
  catch (error) {
@@ -39541,19 +39555,21 @@ const cmdCommand$1 = new Command()
39541
39555
  throw new Error(`unable to resolve parent command`);
39542
39556
  if (!thisCommand.parent.parent)
39543
39557
  throw new Error(`unable to resolve root command`);
39544
- const { getDotenvCliOptions: { logger = console, shellScripts }, } = thisCommand.parent.parent;
39558
+ const { getDotenvCliOptions: { logger = console, ...getDotenvCliOptions }, } = thisCommand.parent.parent;
39545
39559
  const { ignoreErrors, globs, list, pkgCwd, rootPath } = thisCommand.parent.opts();
39546
39560
  // Execute shell command.
39547
39561
  {
39548
39562
  const command = thisCommand.args.join(' ');
39549
39563
  await execShellCommandBatch({
39550
- command: shellScripts?.[command] ?? command,
39564
+ command: resolveCommand(getDotenvCliOptions.scripts, command),
39565
+ getDotenvCliOptions,
39551
39566
  globs,
39552
39567
  ignoreErrors,
39553
39568
  list,
39554
39569
  logger,
39555
39570
  pkgCwd,
39556
39571
  rootPath,
39572
+ shell: resolveShell(getDotenvCliOptions.scripts, command, getDotenvCliOptions.shell),
39557
39573
  });
39558
39574
  }
39559
39575
  });
@@ -39566,13 +39582,13 @@ const batchCommand = new Command()
39566
39582
  .option('-p, --pkg-cwd', 'use nearest package directory as current working directory')
39567
39583
  .option('-r, --root-path <string>', 'path to batch root directory from current working directory', './')
39568
39584
  .option('-g, --globs <string>', 'space-delimited globs from root path', '*')
39569
- .option('-c, --command <string>', 'shell command string, conflicts with cmd subcommand (dotenv-expanded)', dotenvExpandFromProcessEnv)
39585
+ .option('-c, --command <string>', 'command string executed according to the base --shell option, conflicts with cmd subcommand (dotenv-expanded)', dotenvExpandFromProcessEnv)
39570
39586
  .option('-l, --list', 'list working directories without executing command')
39571
39587
  .option('-e, --ignore-errors', 'ignore errors and continue with next path')
39572
39588
  .hook('preSubcommand', async (thisCommand) => {
39573
39589
  if (!thisCommand.parent)
39574
39590
  throw new Error(`unable to resolve root command`);
39575
- const { getDotenvCliOptions: { logger = console, shellScripts }, } = thisCommand.parent;
39591
+ const { getDotenvCliOptions: { logger = console, ...getDotenvCliOptions }, } = thisCommand.parent;
39576
39592
  const { command, ignoreErrors, globs, list, pkgCwd, rootPath } = thisCommand.opts();
39577
39593
  if (command && thisCommand.args.length) {
39578
39594
  logger.error(`--command option conflicts with cmd subcommand.`);
@@ -39581,20 +39597,22 @@ const batchCommand = new Command()
39581
39597
  // Execute shell command.
39582
39598
  if (command)
39583
39599
  await execShellCommandBatch({
39584
- command: shellScripts?.[command] ?? command,
39600
+ command: resolveCommand(getDotenvCliOptions.scripts, command),
39601
+ getDotenvCliOptions,
39585
39602
  globs,
39586
39603
  ignoreErrors,
39587
39604
  list,
39588
39605
  logger,
39589
39606
  pkgCwd,
39590
39607
  rootPath,
39608
+ shell: resolveShell(getDotenvCliOptions.scripts, command, getDotenvCliOptions.shell),
39591
39609
  });
39592
39610
  })
39593
39611
  .addCommand(cmdCommand$1, { isDefault: true });
39594
39612
 
39595
39613
  const cmdCommand = new Command()
39596
39614
  .name('cmd')
39597
- .description('batch execute shell command, conflicts with --command option (default command)')
39615
+ .description('batch execute command string according to the --shell option, conflicts with --command option (default command)')
39598
39616
  .configureHelp({ showGlobalOptions: true })
39599
39617
  .enablePositionalOptions()
39600
39618
  .passThroughOptions()
@@ -39603,13 +39621,14 @@ const cmdCommand = new Command()
39603
39621
  return;
39604
39622
  if (!thisCommand.parent)
39605
39623
  throw new Error('parent command not found');
39606
- const { getDotenvCliOptions: { debug, logger = console, shellScripts }, } = thisCommand.parent;
39624
+ const { getDotenvCliOptions: { logger = console, ...getDotenvCliOptions }, } = thisCommand.parent;
39607
39625
  const command = thisCommand.args.join(' ');
39608
- const shellCommand = shellScripts?.[command] ?? command;
39609
- if (debug)
39610
- logger.log('\n*** shell command ***\n', `'${shellCommand}'`);
39611
- await execaCommand(shellCommand, {
39612
- shell: true,
39626
+ const cmd = resolveCommand(getDotenvCliOptions.scripts, command);
39627
+ if (getDotenvCliOptions.debug)
39628
+ logger.log('\n*** command ***\n', `'${cmd}'`);
39629
+ await execaCommand(cmd, {
39630
+ env: { getDotenvCliOptions: JSON.stringify(getDotenvCliOptions) },
39631
+ shell: resolveShell(getDotenvCliOptions.scripts, command, getDotenvCliOptions.shell),
39613
39632
  stdio: 'inherit',
39614
39633
  });
39615
39634
  });
@@ -39658,7 +39677,7 @@ const resolveExclusionAll = (exclude, excludeOff, defaultValue, excludeAll, excl
39658
39677
  * Generate a Commander CLI Command for get-dotenv.
39659
39678
  */
39660
39679
  const generateGetDotenvCli = async (customOptions) => {
39661
- const { alias, debug, defaultEnv, description, dotenvToken, dynamicPath, env, excludeDynamic, excludeEnv, excludeGlobal, excludePrivate, excludePublic, loadProcess, log, logger, outputPath, paths, pathsDelimiter, pathsDelimiterPattern, postHook, preHook, privateToken, shellScripts, varsAssignor, varsAssignorPattern, varsDelimiter, varsDelimiterPattern, } = await resolveGetDotenvCliGenerateOptions(customOptions);
39680
+ const { alias, debug, defaultEnv, description, dotenvToken, dynamicPath, env, excludeDynamic, excludeEnv, excludeGlobal, excludePrivate, excludePublic, loadProcess, log, logger, outputPath, paths, pathsDelimiter, pathsDelimiterPattern, postHook, preHook, privateToken, scripts, shell, varsAssignor, varsAssignorPattern, varsDelimiter, varsDelimiterPattern, } = await resolveGetDotenvCliGenerateOptions(customOptions);
39662
39681
  const excludeAll = !!excludeDynamic &&
39663
39682
  ((!!excludeEnv && !!excludeGlobal) ||
39664
39683
  (!!excludePrivate && !!excludePublic));
@@ -39674,8 +39693,10 @@ const generateGetDotenvCli = async (customOptions) => {
39674
39693
  ]
39675
39694
  .map((v) => v.join(varsAssignor))
39676
39695
  .join(varsDelimiter)}`, dotenvExpandFromProcessEnv)
39677
- .option('-c, --command <string>', 'shell command string, conflicts with cmd subcommand (dotenv-expanded)', dotenvExpandFromProcessEnv)
39696
+ .option('-c, --command <string>', 'command string executed according to the --shell option, conflicts with cmd subcommand (dotenv-expanded)', dotenvExpandFromProcessEnv)
39678
39697
  .option('-o, --output-path <string>', 'consolidated output file (dotenv-expanded)', dotenvExpandFromProcessEnv, outputPath)
39698
+ .addOption(new Option('-s, --shell [string]', `command execution shell, no argument for default OS shell or provide shell string${shell ? ` (default ${_.isBoolean(shell) ? 'OS shell' : shell})` : ''}`).conflicts('shellOff'))
39699
+ .addOption(new Option('-S, --shell-off', `command execution shell OFF${!shell ? ' (default)' : ''}`).conflicts('shell'))
39679
39700
  .addOption(new Option('-p, --load-process', `load variables to process.env ON${loadProcess ? ' (default)' : ''}`).conflicts('loadProcessOff'))
39680
39701
  .addOption(new Option('-P, --load-process-off', `load variables to process.env OFF${!loadProcess ? ' (default)' : ''}`).conflicts('loadProcess'))
39681
39702
  .addOption(new Option('-a, --exclude-all', `exclude all dotenv variables from loading ON${excludeAll ? ' (default)' : ''}`).conflicts('excludeAllOff'))
@@ -39705,8 +39726,8 @@ const generateGetDotenvCli = async (customOptions) => {
39705
39726
  .option('--vars-delimiter-pattern <string>', 'vars delimiter regex pattern', varsDelimiterPattern)
39706
39727
  .option('--vars-assignor <string>', 'vars assignment operator string', varsAssignor)
39707
39728
  .option('--vars-assignor-pattern <string>', 'vars assignment operator regex pattern', varsAssignorPattern)
39708
- .addOption(new Option('--shell-scripts <string>')
39709
- .default(JSON.stringify(shellScripts))
39729
+ .addOption(new Option('--scripts <string>')
39730
+ .default(JSON.stringify(scripts))
39710
39731
  .hideHelp())
39711
39732
  .addCommand(batchCommand)
39712
39733
  .addCommand(cmdCommand, { isDefault: true })
@@ -39718,10 +39739,10 @@ const generateGetDotenvCli = async (customOptions) => {
39718
39739
  // Get raw CLI options from commander.
39719
39740
  const rawCliOptions = thisCommand.opts();
39720
39741
  // Extract current GetDotenvCliOptions from raw CLI options.
39721
- const { command, debugOff, excludeAll, excludeAllOff, excludeDynamicOff, excludeEnvOff, excludeGlobalOff, excludePrivateOff, excludePublicOff, loadProcessOff, logOff, shellScripts, ...rawCliOptionsRest } = rawCliOptions;
39742
+ const { command, debugOff, excludeAll, excludeAllOff, excludeDynamicOff, excludeEnvOff, excludeGlobalOff, excludePrivateOff, excludePublicOff, loadProcessOff, logOff, scripts, shellOff, ...rawCliOptionsRest } = rawCliOptions;
39722
39743
  const currentGetDotenvCliOptions = rawCliOptionsRest;
39723
- if (shellScripts)
39724
- currentGetDotenvCliOptions.shellScripts = JSON.parse(shellScripts);
39744
+ if (scripts)
39745
+ currentGetDotenvCliOptions.scripts = JSON.parse(scripts);
39725
39746
  // Merge current & parent GetDotenvCliOptions.
39726
39747
  const mergedGetDotenvCliOptions = _.defaultsDeep(currentGetDotenvCliOptions, parentGetDotenvCliOptions ?? {});
39727
39748
  // Resolve flags.
@@ -39733,12 +39754,17 @@ const generateGetDotenvCli = async (customOptions) => {
39733
39754
  mergedGetDotenvCliOptions.excludePublic = resolveExclusionAll(mergedGetDotenvCliOptions.excludePublic, excludePublicOff, excludePublic, excludeAll, excludeAllOff);
39734
39755
  mergedGetDotenvCliOptions.log = resolveExclusion(mergedGetDotenvCliOptions.log, logOff, log);
39735
39756
  mergedGetDotenvCliOptions.loadProcess = resolveExclusion(mergedGetDotenvCliOptions.loadProcess, loadProcessOff, loadProcess);
39757
+ mergedGetDotenvCliOptions.shell = shellOff
39758
+ ? false
39759
+ : !_.isUndefined(mergedGetDotenvCliOptions.shell)
39760
+ ? mergedGetDotenvCliOptions.shell
39761
+ : !_.isUndefined(shell)
39762
+ ? shell
39763
+ : false;
39736
39764
  if (mergedGetDotenvCliOptions.debug && parentGetDotenvCliOptions)
39737
39765
  logger.debug('\n*** parent command GetDotenvCliOptions ***\n', parentGetDotenvCliOptions);
39738
39766
  if (mergedGetDotenvCliOptions.debug)
39739
39767
  logger.debug('\n*** current command raw options ***\n', rawCliOptions);
39740
- if (mergedGetDotenvCliOptions.debug)
39741
- logger.debug('\n*** current command GetDotenvCliOptions ***\n', currentGetDotenvCliOptions);
39742
39768
  if (mergedGetDotenvCliOptions.debug)
39743
39769
  logger.debug('\n*** merged GetDotenvCliOptions ***\n', {
39744
39770
  mergedGetDotenvCliOptions,
@@ -39764,15 +39790,15 @@ const generateGetDotenvCli = async (customOptions) => {
39764
39790
  process.exit(0);
39765
39791
  }
39766
39792
  if (command) {
39767
- const shellCommand = mergedGetDotenvCliOptions.shellScripts?.[command] ?? command;
39793
+ const cmd = resolveCommand(mergedGetDotenvCliOptions.scripts, command);
39768
39794
  if (mergedGetDotenvCliOptions.debug)
39769
- logger.debug('\n*** shell command ***\n', shellCommand);
39770
- await execaCommand(shellCommand, {
39795
+ logger.debug('\n*** command ***\n', cmd);
39796
+ await execaCommand(cmd, {
39771
39797
  env: {
39772
39798
  ...process.env,
39773
39799
  getDotenvCliOptions: JSON.stringify(_.omit(mergedGetDotenvCliOptions, ['logger'])),
39774
39800
  },
39775
- shell: true,
39801
+ shell: resolveShell(mergedGetDotenvCliOptions.scripts, command, mergedGetDotenvCliOptions.shell),
39776
39802
  stdio: 'inherit',
39777
39803
  });
39778
39804
  }
package/dist/index.cjs CHANGED
@@ -5056,11 +5056,11 @@ function resolveCommandAttempt(parsed, withoutPathExt) {
5056
5056
  return resolved;
5057
5057
  }
5058
5058
 
5059
- function resolveCommand$1(parsed) {
5059
+ function resolveCommand$2(parsed) {
5060
5060
  return resolveCommandAttempt(parsed) || resolveCommandAttempt(parsed, true);
5061
5061
  }
5062
5062
 
5063
- var resolveCommand_1 = resolveCommand$1;
5063
+ var resolveCommand_1 = resolveCommand$2;
5064
5064
 
5065
5065
  var _escape = {};
5066
5066
 
@@ -5152,7 +5152,7 @@ function readShebang$1(command) {
5152
5152
  var readShebang_1 = readShebang$1;
5153
5153
 
5154
5154
  const path$o = require$$0$2;
5155
- const resolveCommand = resolveCommand_1;
5155
+ const resolveCommand$1 = resolveCommand_1;
5156
5156
  const escape = _escape;
5157
5157
  const readShebang = readShebang_1;
5158
5158
 
@@ -5161,7 +5161,7 @@ const isExecutableRegExp = /\.(?:com|exe)$/i;
5161
5161
  const isCmdShimRegExp = /node_modules[\\/].bin[\\/][^\\/]+\.cmd$/i;
5162
5162
 
5163
5163
  function detectShebang(parsed) {
5164
- parsed.file = resolveCommand(parsed);
5164
+ parsed.file = resolveCommand$1(parsed);
5165
5165
 
5166
5166
  const shebang = parsed.file && readShebang(parsed.file);
5167
5167
 
@@ -5169,7 +5169,7 @@ function detectShebang(parsed) {
5169
5169
  parsed.args.unshift(parsed.file);
5170
5170
  parsed.command = shebang;
5171
5171
 
5172
- return resolveCommand(parsed);
5172
+ return resolveCommand$1(parsed);
5173
5173
  }
5174
5174
 
5175
5175
  return parsed.file;
@@ -31150,9 +31150,13 @@ const baseGetDotenvCliOptions = {
31150
31150
  paths: './',
31151
31151
  pathsDelimiter: ' ',
31152
31152
  privateToken: 'local',
31153
- shellScripts: {
31154
- 'git-status': 'git branch --show-current && git status -s -u',
31153
+ scripts: {
31154
+ 'git-status': {
31155
+ cmd: 'git branch --show-current && git status -s -u',
31156
+ shell: true,
31157
+ },
31155
31158
  },
31159
+ shell: true,
31156
31160
  vars: '',
31157
31161
  varsAssignor: '=',
31158
31162
  varsDelimiter: ' ',
@@ -31167,7 +31171,7 @@ const getDotenvOptionsFilename = 'getdotenv.config.json';
31167
31171
  * @returns `getDotenv` options.
31168
31172
  */
31169
31173
  const getDotenvCliOptions2Options = ({ paths, pathsDelimiter, pathsDelimiterPattern, vars, varsAssignor, varsAssignorPattern, varsDelimiter, varsDelimiterPattern, ...rest }) => ({
31170
- ..._.omit(rest, ['debug', 'shellScripts']),
31174
+ ..._.omit(rest, ['debug', 'scripts']),
31171
31175
  paths: paths?.split(pathsDelimiterPattern
31172
31176
  ? RegExp(pathsDelimiterPattern)
31173
31177
  : pathsDelimiter ?? ' ') ?? [],
@@ -31739,6 +31743,11 @@ const getDotenv = async (options = {}) => {
31739
31743
  return dotenv;
31740
31744
  };
31741
31745
 
31746
+ const resolveCommand = (scripts, command) => (scripts && _.isObject(scripts[command])
31747
+ ? scripts[command].cmd
31748
+ : scripts?.[command] ?? command);
31749
+ const resolveShell = (scripts, command, shell) => (scripts && _.isObject(scripts[command]) ? scripts[command].shell : shell);
31750
+
31742
31751
  /*
31743
31752
  * merge2
31744
31753
  * https://github.com/teambition/merge2
@@ -39480,7 +39489,7 @@ const globPaths = async ({ globs, logger, pkgCwd, rootPath, }) => {
39480
39489
  }
39481
39490
  return { absRootPath, paths };
39482
39491
  };
39483
- const execShellCommandBatch = async ({ command, globs, ignoreErrors, list, logger, pkgCwd, rootPath, }) => {
39492
+ const execShellCommandBatch = async ({ command, getDotenvCliOptions, globs, ignoreErrors, list, logger, pkgCwd, rootPath, shell, }) => {
39484
39493
  if (!command) {
39485
39494
  logger.error(`No command provided.`);
39486
39495
  process.exit(0);
@@ -39519,8 +39528,13 @@ const execShellCommandBatch = async ({ command, globs, ignoreErrors, list, logge
39519
39528
  try {
39520
39529
  await execaCommand(command, {
39521
39530
  cwd: path,
39531
+ env: {
39532
+ getDotenvCliOptions: getDotenvCliOptions
39533
+ ? JSON.stringify(getDotenvCliOptions)
39534
+ : undefined,
39535
+ },
39522
39536
  stdio: 'inherit',
39523
- shell: true,
39537
+ shell,
39524
39538
  });
39525
39539
  }
39526
39540
  catch (error) {
@@ -39542,19 +39556,21 @@ const cmdCommand$1 = new Command()
39542
39556
  throw new Error(`unable to resolve parent command`);
39543
39557
  if (!thisCommand.parent.parent)
39544
39558
  throw new Error(`unable to resolve root command`);
39545
- const { getDotenvCliOptions: { logger = console, shellScripts }, } = thisCommand.parent.parent;
39559
+ const { getDotenvCliOptions: { logger = console, ...getDotenvCliOptions }, } = thisCommand.parent.parent;
39546
39560
  const { ignoreErrors, globs, list, pkgCwd, rootPath } = thisCommand.parent.opts();
39547
39561
  // Execute shell command.
39548
39562
  {
39549
39563
  const command = thisCommand.args.join(' ');
39550
39564
  await execShellCommandBatch({
39551
- command: shellScripts?.[command] ?? command,
39565
+ command: resolveCommand(getDotenvCliOptions.scripts, command),
39566
+ getDotenvCliOptions,
39552
39567
  globs,
39553
39568
  ignoreErrors,
39554
39569
  list,
39555
39570
  logger,
39556
39571
  pkgCwd,
39557
39572
  rootPath,
39573
+ shell: resolveShell(getDotenvCliOptions.scripts, command, getDotenvCliOptions.shell),
39558
39574
  });
39559
39575
  }
39560
39576
  });
@@ -39567,13 +39583,13 @@ const batchCommand = new Command()
39567
39583
  .option('-p, --pkg-cwd', 'use nearest package directory as current working directory')
39568
39584
  .option('-r, --root-path <string>', 'path to batch root directory from current working directory', './')
39569
39585
  .option('-g, --globs <string>', 'space-delimited globs from root path', '*')
39570
- .option('-c, --command <string>', 'shell command string, conflicts with cmd subcommand (dotenv-expanded)', dotenvExpandFromProcessEnv)
39586
+ .option('-c, --command <string>', 'command string executed according to the base --shell option, conflicts with cmd subcommand (dotenv-expanded)', dotenvExpandFromProcessEnv)
39571
39587
  .option('-l, --list', 'list working directories without executing command')
39572
39588
  .option('-e, --ignore-errors', 'ignore errors and continue with next path')
39573
39589
  .hook('preSubcommand', async (thisCommand) => {
39574
39590
  if (!thisCommand.parent)
39575
39591
  throw new Error(`unable to resolve root command`);
39576
- const { getDotenvCliOptions: { logger = console, shellScripts }, } = thisCommand.parent;
39592
+ const { getDotenvCliOptions: { logger = console, ...getDotenvCliOptions }, } = thisCommand.parent;
39577
39593
  const { command, ignoreErrors, globs, list, pkgCwd, rootPath } = thisCommand.opts();
39578
39594
  if (command && thisCommand.args.length) {
39579
39595
  logger.error(`--command option conflicts with cmd subcommand.`);
@@ -39582,20 +39598,22 @@ const batchCommand = new Command()
39582
39598
  // Execute shell command.
39583
39599
  if (command)
39584
39600
  await execShellCommandBatch({
39585
- command: shellScripts?.[command] ?? command,
39601
+ command: resolveCommand(getDotenvCliOptions.scripts, command),
39602
+ getDotenvCliOptions,
39586
39603
  globs,
39587
39604
  ignoreErrors,
39588
39605
  list,
39589
39606
  logger,
39590
39607
  pkgCwd,
39591
39608
  rootPath,
39609
+ shell: resolveShell(getDotenvCliOptions.scripts, command, getDotenvCliOptions.shell),
39592
39610
  });
39593
39611
  })
39594
39612
  .addCommand(cmdCommand$1, { isDefault: true });
39595
39613
 
39596
39614
  const cmdCommand = new Command()
39597
39615
  .name('cmd')
39598
- .description('batch execute shell command, conflicts with --command option (default command)')
39616
+ .description('batch execute command string according to the --shell option, conflicts with --command option (default command)')
39599
39617
  .configureHelp({ showGlobalOptions: true })
39600
39618
  .enablePositionalOptions()
39601
39619
  .passThroughOptions()
@@ -39604,13 +39622,14 @@ const cmdCommand = new Command()
39604
39622
  return;
39605
39623
  if (!thisCommand.parent)
39606
39624
  throw new Error('parent command not found');
39607
- const { getDotenvCliOptions: { debug, logger = console, shellScripts }, } = thisCommand.parent;
39625
+ const { getDotenvCliOptions: { logger = console, ...getDotenvCliOptions }, } = thisCommand.parent;
39608
39626
  const command = thisCommand.args.join(' ');
39609
- const shellCommand = shellScripts?.[command] ?? command;
39610
- if (debug)
39611
- logger.log('\n*** shell command ***\n', `'${shellCommand}'`);
39612
- await execaCommand(shellCommand, {
39613
- shell: true,
39627
+ const cmd = resolveCommand(getDotenvCliOptions.scripts, command);
39628
+ if (getDotenvCliOptions.debug)
39629
+ logger.log('\n*** command ***\n', `'${cmd}'`);
39630
+ await execaCommand(cmd, {
39631
+ env: { getDotenvCliOptions: JSON.stringify(getDotenvCliOptions) },
39632
+ shell: resolveShell(getDotenvCliOptions.scripts, command, getDotenvCliOptions.shell),
39614
39633
  stdio: 'inherit',
39615
39634
  });
39616
39635
  });
@@ -39659,7 +39678,7 @@ const resolveExclusionAll = (exclude, excludeOff, defaultValue, excludeAll, excl
39659
39678
  * Generate a Commander CLI Command for get-dotenv.
39660
39679
  */
39661
39680
  const generateGetDotenvCli = async (customOptions) => {
39662
- const { alias, debug, defaultEnv, description, dotenvToken, dynamicPath, env, excludeDynamic, excludeEnv, excludeGlobal, excludePrivate, excludePublic, loadProcess, log, logger, outputPath, paths, pathsDelimiter, pathsDelimiterPattern, postHook, preHook, privateToken, shellScripts, varsAssignor, varsAssignorPattern, varsDelimiter, varsDelimiterPattern, } = await resolveGetDotenvCliGenerateOptions(customOptions);
39681
+ const { alias, debug, defaultEnv, description, dotenvToken, dynamicPath, env, excludeDynamic, excludeEnv, excludeGlobal, excludePrivate, excludePublic, loadProcess, log, logger, outputPath, paths, pathsDelimiter, pathsDelimiterPattern, postHook, preHook, privateToken, scripts, shell, varsAssignor, varsAssignorPattern, varsDelimiter, varsDelimiterPattern, } = await resolveGetDotenvCliGenerateOptions(customOptions);
39663
39682
  const excludeAll = !!excludeDynamic &&
39664
39683
  ((!!excludeEnv && !!excludeGlobal) ||
39665
39684
  (!!excludePrivate && !!excludePublic));
@@ -39675,8 +39694,10 @@ const generateGetDotenvCli = async (customOptions) => {
39675
39694
  ]
39676
39695
  .map((v) => v.join(varsAssignor))
39677
39696
  .join(varsDelimiter)}`, dotenvExpandFromProcessEnv)
39678
- .option('-c, --command <string>', 'shell command string, conflicts with cmd subcommand (dotenv-expanded)', dotenvExpandFromProcessEnv)
39697
+ .option('-c, --command <string>', 'command string executed according to the --shell option, conflicts with cmd subcommand (dotenv-expanded)', dotenvExpandFromProcessEnv)
39679
39698
  .option('-o, --output-path <string>', 'consolidated output file (dotenv-expanded)', dotenvExpandFromProcessEnv, outputPath)
39699
+ .addOption(new Option('-s, --shell [string]', `command execution shell, no argument for default OS shell or provide shell string${shell ? ` (default ${_.isBoolean(shell) ? 'OS shell' : shell})` : ''}`).conflicts('shellOff'))
39700
+ .addOption(new Option('-S, --shell-off', `command execution shell OFF${!shell ? ' (default)' : ''}`).conflicts('shell'))
39680
39701
  .addOption(new Option('-p, --load-process', `load variables to process.env ON${loadProcess ? ' (default)' : ''}`).conflicts('loadProcessOff'))
39681
39702
  .addOption(new Option('-P, --load-process-off', `load variables to process.env OFF${!loadProcess ? ' (default)' : ''}`).conflicts('loadProcess'))
39682
39703
  .addOption(new Option('-a, --exclude-all', `exclude all dotenv variables from loading ON${excludeAll ? ' (default)' : ''}`).conflicts('excludeAllOff'))
@@ -39706,8 +39727,8 @@ const generateGetDotenvCli = async (customOptions) => {
39706
39727
  .option('--vars-delimiter-pattern <string>', 'vars delimiter regex pattern', varsDelimiterPattern)
39707
39728
  .option('--vars-assignor <string>', 'vars assignment operator string', varsAssignor)
39708
39729
  .option('--vars-assignor-pattern <string>', 'vars assignment operator regex pattern', varsAssignorPattern)
39709
- .addOption(new Option('--shell-scripts <string>')
39710
- .default(JSON.stringify(shellScripts))
39730
+ .addOption(new Option('--scripts <string>')
39731
+ .default(JSON.stringify(scripts))
39711
39732
  .hideHelp())
39712
39733
  .addCommand(batchCommand)
39713
39734
  .addCommand(cmdCommand, { isDefault: true })
@@ -39719,10 +39740,10 @@ const generateGetDotenvCli = async (customOptions) => {
39719
39740
  // Get raw CLI options from commander.
39720
39741
  const rawCliOptions = thisCommand.opts();
39721
39742
  // Extract current GetDotenvCliOptions from raw CLI options.
39722
- const { command, debugOff, excludeAll, excludeAllOff, excludeDynamicOff, excludeEnvOff, excludeGlobalOff, excludePrivateOff, excludePublicOff, loadProcessOff, logOff, shellScripts, ...rawCliOptionsRest } = rawCliOptions;
39743
+ const { command, debugOff, excludeAll, excludeAllOff, excludeDynamicOff, excludeEnvOff, excludeGlobalOff, excludePrivateOff, excludePublicOff, loadProcessOff, logOff, scripts, shellOff, ...rawCliOptionsRest } = rawCliOptions;
39723
39744
  const currentGetDotenvCliOptions = rawCliOptionsRest;
39724
- if (shellScripts)
39725
- currentGetDotenvCliOptions.shellScripts = JSON.parse(shellScripts);
39745
+ if (scripts)
39746
+ currentGetDotenvCliOptions.scripts = JSON.parse(scripts);
39726
39747
  // Merge current & parent GetDotenvCliOptions.
39727
39748
  const mergedGetDotenvCliOptions = _.defaultsDeep(currentGetDotenvCliOptions, parentGetDotenvCliOptions ?? {});
39728
39749
  // Resolve flags.
@@ -39734,12 +39755,17 @@ const generateGetDotenvCli = async (customOptions) => {
39734
39755
  mergedGetDotenvCliOptions.excludePublic = resolveExclusionAll(mergedGetDotenvCliOptions.excludePublic, excludePublicOff, excludePublic, excludeAll, excludeAllOff);
39735
39756
  mergedGetDotenvCliOptions.log = resolveExclusion(mergedGetDotenvCliOptions.log, logOff, log);
39736
39757
  mergedGetDotenvCliOptions.loadProcess = resolveExclusion(mergedGetDotenvCliOptions.loadProcess, loadProcessOff, loadProcess);
39758
+ mergedGetDotenvCliOptions.shell = shellOff
39759
+ ? false
39760
+ : !_.isUndefined(mergedGetDotenvCliOptions.shell)
39761
+ ? mergedGetDotenvCliOptions.shell
39762
+ : !_.isUndefined(shell)
39763
+ ? shell
39764
+ : false;
39737
39765
  if (mergedGetDotenvCliOptions.debug && parentGetDotenvCliOptions)
39738
39766
  logger.debug('\n*** parent command GetDotenvCliOptions ***\n', parentGetDotenvCliOptions);
39739
39767
  if (mergedGetDotenvCliOptions.debug)
39740
39768
  logger.debug('\n*** current command raw options ***\n', rawCliOptions);
39741
- if (mergedGetDotenvCliOptions.debug)
39742
- logger.debug('\n*** current command GetDotenvCliOptions ***\n', currentGetDotenvCliOptions);
39743
39769
  if (mergedGetDotenvCliOptions.debug)
39744
39770
  logger.debug('\n*** merged GetDotenvCliOptions ***\n', {
39745
39771
  mergedGetDotenvCliOptions,
@@ -39765,15 +39791,15 @@ const generateGetDotenvCli = async (customOptions) => {
39765
39791
  process.exit(0);
39766
39792
  }
39767
39793
  if (command) {
39768
- const shellCommand = mergedGetDotenvCliOptions.shellScripts?.[command] ?? command;
39794
+ const cmd = resolveCommand(mergedGetDotenvCliOptions.scripts, command);
39769
39795
  if (mergedGetDotenvCliOptions.debug)
39770
- logger.debug('\n*** shell command ***\n', shellCommand);
39771
- await execaCommand(shellCommand, {
39796
+ logger.debug('\n*** command ***\n', cmd);
39797
+ await execaCommand(cmd, {
39772
39798
  env: {
39773
39799
  ...process.env,
39774
39800
  getDotenvCliOptions: JSON.stringify(_.omit(mergedGetDotenvCliOptions, ['logger'])),
39775
39801
  },
39776
- shell: true,
39802
+ shell: resolveShell(mergedGetDotenvCliOptions.scripts, command, mergedGetDotenvCliOptions.shell),
39777
39803
  stdio: 'inherit',
39778
39804
  });
39779
39805
  }
package/dist/index.d.cts CHANGED
@@ -1,5 +1,9 @@
1
1
  import { Command } from '@commander-js/extra-typings';
2
2
 
3
+ type Scripts = Record<string, string | {
4
+ cmd: string;
5
+ shell?: string | boolean;
6
+ }>;
3
7
  /**
4
8
  * Options passed programmatically to `getDotenvCli`.
5
9
  */
@@ -23,9 +27,17 @@ interface GetDotenvCliOptions extends Omit<GetDotenvOptions, 'paths' | 'vars'> {
23
27
  */
24
28
  pathsDelimiterPattern?: string;
25
29
  /**
26
- * Shell scripts that can be executed from the CLI, either individually or via the batch subcommand.
30
+ * Scripts that can be executed from the CLI, either individually or via the batch subcommand.
27
31
  */
28
- shellScripts?: Record<string, string>;
32
+ scripts?: Scripts;
33
+ /**
34
+ * Determines how commands and scripts are executed. If `false` or
35
+ * `undefined`, commands are executed as plain Javascript using the default
36
+ * execa parser. If `true`, commands are executed using the default OS shell
37
+ * parser. Otherwise the user may provide a specific shell string (e.g.
38
+ * `/bin/bash`)
39
+ */
40
+ shell?: string | boolean;
29
41
  /**
30
42
  * A delimited string of key-value pairs declaratively specifying variables &
31
43
  * values to be loaded in addition to any dotenv files.
package/dist/index.d.mts CHANGED
@@ -1,5 +1,9 @@
1
1
  import { Command } from '@commander-js/extra-typings';
2
2
 
3
+ type Scripts = Record<string, string | {
4
+ cmd: string;
5
+ shell?: string | boolean;
6
+ }>;
3
7
  /**
4
8
  * Options passed programmatically to `getDotenvCli`.
5
9
  */
@@ -23,9 +27,17 @@ interface GetDotenvCliOptions extends Omit<GetDotenvOptions, 'paths' | 'vars'> {
23
27
  */
24
28
  pathsDelimiterPattern?: string;
25
29
  /**
26
- * Shell scripts that can be executed from the CLI, either individually or via the batch subcommand.
30
+ * Scripts that can be executed from the CLI, either individually or via the batch subcommand.
27
31
  */
28
- shellScripts?: Record<string, string>;
32
+ scripts?: Scripts;
33
+ /**
34
+ * Determines how commands and scripts are executed. If `false` or
35
+ * `undefined`, commands are executed as plain Javascript using the default
36
+ * execa parser. If `true`, commands are executed using the default OS shell
37
+ * parser. Otherwise the user may provide a specific shell string (e.g.
38
+ * `/bin/bash`)
39
+ */
40
+ shell?: string | boolean;
29
41
  /**
30
42
  * A delimited string of key-value pairs declaratively specifying variables &
31
43
  * values to be loaded in addition to any dotenv files.
package/dist/index.d.ts CHANGED
@@ -1,5 +1,9 @@
1
1
  import { Command } from '@commander-js/extra-typings';
2
2
 
3
+ type Scripts = Record<string, string | {
4
+ cmd: string;
5
+ shell?: string | boolean;
6
+ }>;
3
7
  /**
4
8
  * Options passed programmatically to `getDotenvCli`.
5
9
  */
@@ -23,9 +27,17 @@ interface GetDotenvCliOptions extends Omit<GetDotenvOptions, 'paths' | 'vars'> {
23
27
  */
24
28
  pathsDelimiterPattern?: string;
25
29
  /**
26
- * Shell scripts that can be executed from the CLI, either individually or via the batch subcommand.
30
+ * Scripts that can be executed from the CLI, either individually or via the batch subcommand.
27
31
  */
28
- shellScripts?: Record<string, string>;
32
+ scripts?: Scripts;
33
+ /**
34
+ * Determines how commands and scripts are executed. If `false` or
35
+ * `undefined`, commands are executed as plain Javascript using the default
36
+ * execa parser. If `true`, commands are executed using the default OS shell
37
+ * parser. Otherwise the user may provide a specific shell string (e.g.
38
+ * `/bin/bash`)
39
+ */
40
+ shell?: string | boolean;
29
41
  /**
30
42
  * A delimited string of key-value pairs declaratively specifying variables &
31
43
  * values to be loaded in addition to any dotenv files.
package/dist/index.mjs CHANGED
@@ -5054,11 +5054,11 @@ function resolveCommandAttempt(parsed, withoutPathExt) {
5054
5054
  return resolved;
5055
5055
  }
5056
5056
 
5057
- function resolveCommand$1(parsed) {
5057
+ function resolveCommand$2(parsed) {
5058
5058
  return resolveCommandAttempt(parsed) || resolveCommandAttempt(parsed, true);
5059
5059
  }
5060
5060
 
5061
- var resolveCommand_1 = resolveCommand$1;
5061
+ var resolveCommand_1 = resolveCommand$2;
5062
5062
 
5063
5063
  var _escape = {};
5064
5064
 
@@ -5150,7 +5150,7 @@ function readShebang$1(command) {
5150
5150
  var readShebang_1 = readShebang$1;
5151
5151
 
5152
5152
  const path$o = require$$0$2;
5153
- const resolveCommand = resolveCommand_1;
5153
+ const resolveCommand$1 = resolveCommand_1;
5154
5154
  const escape = _escape;
5155
5155
  const readShebang = readShebang_1;
5156
5156
 
@@ -5159,7 +5159,7 @@ const isExecutableRegExp = /\.(?:com|exe)$/i;
5159
5159
  const isCmdShimRegExp = /node_modules[\\/].bin[\\/][^\\/]+\.cmd$/i;
5160
5160
 
5161
5161
  function detectShebang(parsed) {
5162
- parsed.file = resolveCommand(parsed);
5162
+ parsed.file = resolveCommand$1(parsed);
5163
5163
 
5164
5164
  const shebang = parsed.file && readShebang(parsed.file);
5165
5165
 
@@ -5167,7 +5167,7 @@ function detectShebang(parsed) {
5167
5167
  parsed.args.unshift(parsed.file);
5168
5168
  parsed.command = shebang;
5169
5169
 
5170
- return resolveCommand(parsed);
5170
+ return resolveCommand$1(parsed);
5171
5171
  }
5172
5172
 
5173
5173
  return parsed.file;
@@ -31148,9 +31148,13 @@ const baseGetDotenvCliOptions = {
31148
31148
  paths: './',
31149
31149
  pathsDelimiter: ' ',
31150
31150
  privateToken: 'local',
31151
- shellScripts: {
31152
- 'git-status': 'git branch --show-current && git status -s -u',
31151
+ scripts: {
31152
+ 'git-status': {
31153
+ cmd: 'git branch --show-current && git status -s -u',
31154
+ shell: true,
31155
+ },
31153
31156
  },
31157
+ shell: true,
31154
31158
  vars: '',
31155
31159
  varsAssignor: '=',
31156
31160
  varsDelimiter: ' ',
@@ -31165,7 +31169,7 @@ const getDotenvOptionsFilename = 'getdotenv.config.json';
31165
31169
  * @returns `getDotenv` options.
31166
31170
  */
31167
31171
  const getDotenvCliOptions2Options = ({ paths, pathsDelimiter, pathsDelimiterPattern, vars, varsAssignor, varsAssignorPattern, varsDelimiter, varsDelimiterPattern, ...rest }) => ({
31168
- ..._.omit(rest, ['debug', 'shellScripts']),
31172
+ ..._.omit(rest, ['debug', 'scripts']),
31169
31173
  paths: paths?.split(pathsDelimiterPattern
31170
31174
  ? RegExp(pathsDelimiterPattern)
31171
31175
  : pathsDelimiter ?? ' ') ?? [],
@@ -31737,6 +31741,11 @@ const getDotenv = async (options = {}) => {
31737
31741
  return dotenv;
31738
31742
  };
31739
31743
 
31744
+ const resolveCommand = (scripts, command) => (scripts && _.isObject(scripts[command])
31745
+ ? scripts[command].cmd
31746
+ : scripts?.[command] ?? command);
31747
+ const resolveShell = (scripts, command, shell) => (scripts && _.isObject(scripts[command]) ? scripts[command].shell : shell);
31748
+
31740
31749
  /*
31741
31750
  * merge2
31742
31751
  * https://github.com/teambition/merge2
@@ -39478,7 +39487,7 @@ const globPaths = async ({ globs, logger, pkgCwd, rootPath, }) => {
39478
39487
  }
39479
39488
  return { absRootPath, paths };
39480
39489
  };
39481
- const execShellCommandBatch = async ({ command, globs, ignoreErrors, list, logger, pkgCwd, rootPath, }) => {
39490
+ const execShellCommandBatch = async ({ command, getDotenvCliOptions, globs, ignoreErrors, list, logger, pkgCwd, rootPath, shell, }) => {
39482
39491
  if (!command) {
39483
39492
  logger.error(`No command provided.`);
39484
39493
  process.exit(0);
@@ -39517,8 +39526,13 @@ const execShellCommandBatch = async ({ command, globs, ignoreErrors, list, logge
39517
39526
  try {
39518
39527
  await execaCommand(command, {
39519
39528
  cwd: path,
39529
+ env: {
39530
+ getDotenvCliOptions: getDotenvCliOptions
39531
+ ? JSON.stringify(getDotenvCliOptions)
39532
+ : undefined,
39533
+ },
39520
39534
  stdio: 'inherit',
39521
- shell: true,
39535
+ shell,
39522
39536
  });
39523
39537
  }
39524
39538
  catch (error) {
@@ -39540,19 +39554,21 @@ const cmdCommand$1 = new Command()
39540
39554
  throw new Error(`unable to resolve parent command`);
39541
39555
  if (!thisCommand.parent.parent)
39542
39556
  throw new Error(`unable to resolve root command`);
39543
- const { getDotenvCliOptions: { logger = console, shellScripts }, } = thisCommand.parent.parent;
39557
+ const { getDotenvCliOptions: { logger = console, ...getDotenvCliOptions }, } = thisCommand.parent.parent;
39544
39558
  const { ignoreErrors, globs, list, pkgCwd, rootPath } = thisCommand.parent.opts();
39545
39559
  // Execute shell command.
39546
39560
  {
39547
39561
  const command = thisCommand.args.join(' ');
39548
39562
  await execShellCommandBatch({
39549
- command: shellScripts?.[command] ?? command,
39563
+ command: resolveCommand(getDotenvCliOptions.scripts, command),
39564
+ getDotenvCliOptions,
39550
39565
  globs,
39551
39566
  ignoreErrors,
39552
39567
  list,
39553
39568
  logger,
39554
39569
  pkgCwd,
39555
39570
  rootPath,
39571
+ shell: resolveShell(getDotenvCliOptions.scripts, command, getDotenvCliOptions.shell),
39556
39572
  });
39557
39573
  }
39558
39574
  });
@@ -39565,13 +39581,13 @@ const batchCommand = new Command()
39565
39581
  .option('-p, --pkg-cwd', 'use nearest package directory as current working directory')
39566
39582
  .option('-r, --root-path <string>', 'path to batch root directory from current working directory', './')
39567
39583
  .option('-g, --globs <string>', 'space-delimited globs from root path', '*')
39568
- .option('-c, --command <string>', 'shell command string, conflicts with cmd subcommand (dotenv-expanded)', dotenvExpandFromProcessEnv)
39584
+ .option('-c, --command <string>', 'command string executed according to the base --shell option, conflicts with cmd subcommand (dotenv-expanded)', dotenvExpandFromProcessEnv)
39569
39585
  .option('-l, --list', 'list working directories without executing command')
39570
39586
  .option('-e, --ignore-errors', 'ignore errors and continue with next path')
39571
39587
  .hook('preSubcommand', async (thisCommand) => {
39572
39588
  if (!thisCommand.parent)
39573
39589
  throw new Error(`unable to resolve root command`);
39574
- const { getDotenvCliOptions: { logger = console, shellScripts }, } = thisCommand.parent;
39590
+ const { getDotenvCliOptions: { logger = console, ...getDotenvCliOptions }, } = thisCommand.parent;
39575
39591
  const { command, ignoreErrors, globs, list, pkgCwd, rootPath } = thisCommand.opts();
39576
39592
  if (command && thisCommand.args.length) {
39577
39593
  logger.error(`--command option conflicts with cmd subcommand.`);
@@ -39580,20 +39596,22 @@ const batchCommand = new Command()
39580
39596
  // Execute shell command.
39581
39597
  if (command)
39582
39598
  await execShellCommandBatch({
39583
- command: shellScripts?.[command] ?? command,
39599
+ command: resolveCommand(getDotenvCliOptions.scripts, command),
39600
+ getDotenvCliOptions,
39584
39601
  globs,
39585
39602
  ignoreErrors,
39586
39603
  list,
39587
39604
  logger,
39588
39605
  pkgCwd,
39589
39606
  rootPath,
39607
+ shell: resolveShell(getDotenvCliOptions.scripts, command, getDotenvCliOptions.shell),
39590
39608
  });
39591
39609
  })
39592
39610
  .addCommand(cmdCommand$1, { isDefault: true });
39593
39611
 
39594
39612
  const cmdCommand = new Command()
39595
39613
  .name('cmd')
39596
- .description('batch execute shell command, conflicts with --command option (default command)')
39614
+ .description('batch execute command string according to the --shell option, conflicts with --command option (default command)')
39597
39615
  .configureHelp({ showGlobalOptions: true })
39598
39616
  .enablePositionalOptions()
39599
39617
  .passThroughOptions()
@@ -39602,13 +39620,14 @@ const cmdCommand = new Command()
39602
39620
  return;
39603
39621
  if (!thisCommand.parent)
39604
39622
  throw new Error('parent command not found');
39605
- const { getDotenvCliOptions: { debug, logger = console, shellScripts }, } = thisCommand.parent;
39623
+ const { getDotenvCliOptions: { logger = console, ...getDotenvCliOptions }, } = thisCommand.parent;
39606
39624
  const command = thisCommand.args.join(' ');
39607
- const shellCommand = shellScripts?.[command] ?? command;
39608
- if (debug)
39609
- logger.log('\n*** shell command ***\n', `'${shellCommand}'`);
39610
- await execaCommand(shellCommand, {
39611
- shell: true,
39625
+ const cmd = resolveCommand(getDotenvCliOptions.scripts, command);
39626
+ if (getDotenvCliOptions.debug)
39627
+ logger.log('\n*** command ***\n', `'${cmd}'`);
39628
+ await execaCommand(cmd, {
39629
+ env: { getDotenvCliOptions: JSON.stringify(getDotenvCliOptions) },
39630
+ shell: resolveShell(getDotenvCliOptions.scripts, command, getDotenvCliOptions.shell),
39612
39631
  stdio: 'inherit',
39613
39632
  });
39614
39633
  });
@@ -39657,7 +39676,7 @@ const resolveExclusionAll = (exclude, excludeOff, defaultValue, excludeAll, excl
39657
39676
  * Generate a Commander CLI Command for get-dotenv.
39658
39677
  */
39659
39678
  const generateGetDotenvCli = async (customOptions) => {
39660
- const { alias, debug, defaultEnv, description, dotenvToken, dynamicPath, env, excludeDynamic, excludeEnv, excludeGlobal, excludePrivate, excludePublic, loadProcess, log, logger, outputPath, paths, pathsDelimiter, pathsDelimiterPattern, postHook, preHook, privateToken, shellScripts, varsAssignor, varsAssignorPattern, varsDelimiter, varsDelimiterPattern, } = await resolveGetDotenvCliGenerateOptions(customOptions);
39679
+ const { alias, debug, defaultEnv, description, dotenvToken, dynamicPath, env, excludeDynamic, excludeEnv, excludeGlobal, excludePrivate, excludePublic, loadProcess, log, logger, outputPath, paths, pathsDelimiter, pathsDelimiterPattern, postHook, preHook, privateToken, scripts, shell, varsAssignor, varsAssignorPattern, varsDelimiter, varsDelimiterPattern, } = await resolveGetDotenvCliGenerateOptions(customOptions);
39661
39680
  const excludeAll = !!excludeDynamic &&
39662
39681
  ((!!excludeEnv && !!excludeGlobal) ||
39663
39682
  (!!excludePrivate && !!excludePublic));
@@ -39673,8 +39692,10 @@ const generateGetDotenvCli = async (customOptions) => {
39673
39692
  ]
39674
39693
  .map((v) => v.join(varsAssignor))
39675
39694
  .join(varsDelimiter)}`, dotenvExpandFromProcessEnv)
39676
- .option('-c, --command <string>', 'shell command string, conflicts with cmd subcommand (dotenv-expanded)', dotenvExpandFromProcessEnv)
39695
+ .option('-c, --command <string>', 'command string executed according to the --shell option, conflicts with cmd subcommand (dotenv-expanded)', dotenvExpandFromProcessEnv)
39677
39696
  .option('-o, --output-path <string>', 'consolidated output file (dotenv-expanded)', dotenvExpandFromProcessEnv, outputPath)
39697
+ .addOption(new Option('-s, --shell [string]', `command execution shell, no argument for default OS shell or provide shell string${shell ? ` (default ${_.isBoolean(shell) ? 'OS shell' : shell})` : ''}`).conflicts('shellOff'))
39698
+ .addOption(new Option('-S, --shell-off', `command execution shell OFF${!shell ? ' (default)' : ''}`).conflicts('shell'))
39678
39699
  .addOption(new Option('-p, --load-process', `load variables to process.env ON${loadProcess ? ' (default)' : ''}`).conflicts('loadProcessOff'))
39679
39700
  .addOption(new Option('-P, --load-process-off', `load variables to process.env OFF${!loadProcess ? ' (default)' : ''}`).conflicts('loadProcess'))
39680
39701
  .addOption(new Option('-a, --exclude-all', `exclude all dotenv variables from loading ON${excludeAll ? ' (default)' : ''}`).conflicts('excludeAllOff'))
@@ -39704,8 +39725,8 @@ const generateGetDotenvCli = async (customOptions) => {
39704
39725
  .option('--vars-delimiter-pattern <string>', 'vars delimiter regex pattern', varsDelimiterPattern)
39705
39726
  .option('--vars-assignor <string>', 'vars assignment operator string', varsAssignor)
39706
39727
  .option('--vars-assignor-pattern <string>', 'vars assignment operator regex pattern', varsAssignorPattern)
39707
- .addOption(new Option('--shell-scripts <string>')
39708
- .default(JSON.stringify(shellScripts))
39728
+ .addOption(new Option('--scripts <string>')
39729
+ .default(JSON.stringify(scripts))
39709
39730
  .hideHelp())
39710
39731
  .addCommand(batchCommand)
39711
39732
  .addCommand(cmdCommand, { isDefault: true })
@@ -39717,10 +39738,10 @@ const generateGetDotenvCli = async (customOptions) => {
39717
39738
  // Get raw CLI options from commander.
39718
39739
  const rawCliOptions = thisCommand.opts();
39719
39740
  // Extract current GetDotenvCliOptions from raw CLI options.
39720
- const { command, debugOff, excludeAll, excludeAllOff, excludeDynamicOff, excludeEnvOff, excludeGlobalOff, excludePrivateOff, excludePublicOff, loadProcessOff, logOff, shellScripts, ...rawCliOptionsRest } = rawCliOptions;
39741
+ const { command, debugOff, excludeAll, excludeAllOff, excludeDynamicOff, excludeEnvOff, excludeGlobalOff, excludePrivateOff, excludePublicOff, loadProcessOff, logOff, scripts, shellOff, ...rawCliOptionsRest } = rawCliOptions;
39721
39742
  const currentGetDotenvCliOptions = rawCliOptionsRest;
39722
- if (shellScripts)
39723
- currentGetDotenvCliOptions.shellScripts = JSON.parse(shellScripts);
39743
+ if (scripts)
39744
+ currentGetDotenvCliOptions.scripts = JSON.parse(scripts);
39724
39745
  // Merge current & parent GetDotenvCliOptions.
39725
39746
  const mergedGetDotenvCliOptions = _.defaultsDeep(currentGetDotenvCliOptions, parentGetDotenvCliOptions ?? {});
39726
39747
  // Resolve flags.
@@ -39732,12 +39753,17 @@ const generateGetDotenvCli = async (customOptions) => {
39732
39753
  mergedGetDotenvCliOptions.excludePublic = resolveExclusionAll(mergedGetDotenvCliOptions.excludePublic, excludePublicOff, excludePublic, excludeAll, excludeAllOff);
39733
39754
  mergedGetDotenvCliOptions.log = resolveExclusion(mergedGetDotenvCliOptions.log, logOff, log);
39734
39755
  mergedGetDotenvCliOptions.loadProcess = resolveExclusion(mergedGetDotenvCliOptions.loadProcess, loadProcessOff, loadProcess);
39756
+ mergedGetDotenvCliOptions.shell = shellOff
39757
+ ? false
39758
+ : !_.isUndefined(mergedGetDotenvCliOptions.shell)
39759
+ ? mergedGetDotenvCliOptions.shell
39760
+ : !_.isUndefined(shell)
39761
+ ? shell
39762
+ : false;
39735
39763
  if (mergedGetDotenvCliOptions.debug && parentGetDotenvCliOptions)
39736
39764
  logger.debug('\n*** parent command GetDotenvCliOptions ***\n', parentGetDotenvCliOptions);
39737
39765
  if (mergedGetDotenvCliOptions.debug)
39738
39766
  logger.debug('\n*** current command raw options ***\n', rawCliOptions);
39739
- if (mergedGetDotenvCliOptions.debug)
39740
- logger.debug('\n*** current command GetDotenvCliOptions ***\n', currentGetDotenvCliOptions);
39741
39767
  if (mergedGetDotenvCliOptions.debug)
39742
39768
  logger.debug('\n*** merged GetDotenvCliOptions ***\n', {
39743
39769
  mergedGetDotenvCliOptions,
@@ -39763,15 +39789,15 @@ const generateGetDotenvCli = async (customOptions) => {
39763
39789
  process.exit(0);
39764
39790
  }
39765
39791
  if (command) {
39766
- const shellCommand = mergedGetDotenvCliOptions.shellScripts?.[command] ?? command;
39792
+ const cmd = resolveCommand(mergedGetDotenvCliOptions.scripts, command);
39767
39793
  if (mergedGetDotenvCliOptions.debug)
39768
- logger.debug('\n*** shell command ***\n', shellCommand);
39769
- await execaCommand(shellCommand, {
39794
+ logger.debug('\n*** command ***\n', cmd);
39795
+ await execaCommand(cmd, {
39770
39796
  env: {
39771
39797
  ...process.env,
39772
39798
  getDotenvCliOptions: JSON.stringify(_.omit(mergedGetDotenvCliOptions, ['logger'])),
39773
39799
  },
39774
- shell: true,
39800
+ shell: resolveShell(mergedGetDotenvCliOptions.scripts, command, mergedGetDotenvCliOptions.shell),
39775
39801
  stdio: 'inherit',
39776
39802
  });
39777
39803
  }
package/package.json CHANGED
@@ -22,7 +22,7 @@
22
22
  "@commander-js/extra-typings": "^12.1.0",
23
23
  "@eslint/js": "^9.3.0",
24
24
  "@rollup/plugin-alias": "^5.1.0",
25
- "@rollup/plugin-commonjs": "^25.0.7",
25
+ "@rollup/plugin-commonjs": "^25.0.8",
26
26
  "@rollup/plugin-json": "^6.1.0",
27
27
  "@rollup/plugin-node-resolve": "^15.2.3",
28
28
  "@rollup/plugin-terser": "^0.4.4",
@@ -34,7 +34,7 @@
34
34
  "@types/fs-extra": "^11.0.4",
35
35
  "@types/lodash": "^4.17.4",
36
36
  "@types/mocha": "^10.0.6",
37
- "@types/node": "^20.12.12",
37
+ "@types/node": "^20.12.13",
38
38
  "auto-changelog": "^2.4.0",
39
39
  "chai": "^5.1.1",
40
40
  "cross-env": "^7.0.3",
@@ -45,7 +45,7 @@
45
45
  "eslint-plugin-tsdoc": "^0.2.17",
46
46
  "fs-extra": "^11.2.0",
47
47
  "jsdom-global": "^3.0.2",
48
- "lefthook": "^1.6.12",
48
+ "lefthook": "^1.6.14",
49
49
  "mocha": "^10.4.0",
50
50
  "nyc": "^15.1.0",
51
51
  "prettier": "^3.2.5",
@@ -57,7 +57,7 @@
57
57
  "ts-node": "^10.9.2",
58
58
  "tslib": "^2.6.2",
59
59
  "typescript": "^5.4.5",
60
- "typescript-eslint": "^7.10.0"
60
+ "typescript-eslint": "^7.11.0"
61
61
  },
62
62
  "exports": {
63
63
  ".": {
@@ -124,6 +124,7 @@
124
124
  },
125
125
  "scripts": {
126
126
  "build": "rimraf dist && rollup --config rollup.config.ts --configPlugin @rollup/plugin-typescript",
127
+ "cli": "node dist/getdotenv.cli.mjs",
127
128
  "lint": "eslint src/** && prettier -c src",
128
129
  "lint:fix": "eslint --fix src/** && prettier --write src",
129
130
  "release": "release-it",
@@ -131,5 +132,5 @@
131
132
  },
132
133
  "type": "module",
133
134
  "types": "dist/index.d.ts",
134
- "version": "4.3.2"
135
+ "version": "4.4.0"
135
136
  }