Im my project i am trying to use dotenv-cli with pnpm. I am using PowerShell 7.2.1 on windows. I have monorepo with package api
with script dev
in package.json
.
First what I tried was:
dotenv -e .\.env -- pnpm dev --filter api
And it did not work:
ERR_PNPM_RECURSIVE_EXEC_FIRST_FAIL not found: dev
But when I tried:
dotenv -e .\.env -- pnpm -- dev --filter api
It worked well.
As I had read --
signifies the end of command options, after which only positional arguments are accepted. So why do I need to use it twice for my command to work? Why is it working like that?
CodePudding user response:
The problem is that when you call from PowerShell (unlike from cmd.exe
), the command name dotenv
resolves to a PowerShell script, namely dotenv.ps1
, as you report.
When PowerShell calls a PowerShell-native command - including .ps1
files - its own parameter binder interprets the (first) --
argument and removes it; that is, the target command never sees it.
(The semantics of --
is analogous to that of Unix utilities: --
tells the parameter binder to treat subsequent arguments as positional ones, even if they look like parameter (option) names, such as -foo
.)
Thus, unfortunately, you need to specify --
twice in order to pass a single --
instance through to the .ps1
script itself:
# The first '--' is removed by PowerShell's parameter binder.
# The second one is then received as an actual, positional argument by
# dotenv.ps1
dotenv -e .\.env -- -- pnpm dev --filter api
Alternatively, assuming that dotenv.cmd
, i.e. a batch file version of the CLI exists too (and is also in a directory listed in $env:PATH
), you can bypass this problem by calling it explicitly, instead of the .ps1
; when calling external programs (including scripts interpreted by other shells / scripting engines, such as cmd.exe
), PowerShell does not remove --
:
# Calling the batch-file form of the command doesn't require
# passing '--' twice.
dotenv.cmd -e .\.env -- pnpm dev --filter api
Caveat: While it will typically not matter, the way a batch file parses its arguments differs from how PowerShell does it for its native commands.