Search code examples
powershellshellcommand-linepackage.jsondotenv

dotenv cli dynamically set environment varible from executed command in `package.json` script


I have a simple command like this to run nodejs program with dynamic environment variables set:

pnpm exec dotenv -v DATABASE_URL=$(pnpm exec ts-node ./getDatabaseUrl.ts) -- pnpm -C backend run migrate:dev:main

It executes getDatabaseUrl.ts script and assigns the result to the environment variable using dotenv-cli and then executes next script(pnpm -C backend run migrate:dev:main) for which DATABASE_URL env var will be available.

And it works perfectly when I run it in PowerShell 7.3.4 But when I put it in package.json it does not work:

{
  "scripts": {
    "migrate:dev:main": "pnpm exec dotenv -v DATABASE_URL=$(pnpm exec ts-node ./getDatabaseUrl.ts) -- pnpm -C backend run migrate:dev:main"
  }
}

shows such error: Unexpected argument DATABASE_URL=$(pnpm. Expected variable in format variable=value How to make this command work from package.json script? I also tried like this without pnpm at the beginning:

{
  "scripts": {
    "migrate:dev:main": "dotenv -v DATABASE_URL=$(pnpm exec ts-node ./getDatabaseUrl.ts) -- pnpm -C backend run migrate:dev:main"
  }
}

but it does not work anyway, error: -- was unexpected at this time. or like this(similar error):

{
  "scripts": {
    "migrate:dev:main": "dotenv -v DATABASE_URL=$(pnpm exec ts-node ./getDatabaseUrl.ts) pnpm -C backend run migrate:dev:main"
  }
}

error: pnpm was unexpected at this time.


Solution

  • The default script shell of npm is cmd.exe (source).

    You are probably using this default, because $(...) does not get evaluated. You can solve your problem in multiple ways:

    1. Change your script shell to pwsh (docs):

      pnpm config set script-shell "pwsh"
      

      Use an absolute path, if pwsh is not in your path, e. g. "C:\\path\\to\\pwsh.exe"

    2. Execute your command with PowerShell explicitly. That will work in both script shells, cmd and pwsh/powershell:

      {
        "scripts": {
          "migrate:dev:main": "pwsh -ExecutionPolicy ByPass -NoProfile -Command \"pnpm exec dotenv -v DATABASE_URL=$(pnpm exec ts-node ./getDatabaseUrl.ts) -- pnpm -C backend run migrate:dev:main\""
        }
      }