在 npm 脚本中设置环境变量*带空格*的跨平台方式

Cross-platform way to set environment variables *with spaces* in npm scripts

我正在开发无服务器 NodeJS 应用程序,需要在离线模式下对其进行测试。我在 package.json 文件中有一个 npm 脚本,如下所示:

  "scripts": {
    "serve": "cross-env AUTHORIZER='{\\"claims\\":{\\"permissions\\":\\"[view:accounts manage:accounts]\\",\\"sub\\":\\"auth0|5cfe0adce3c4c50ea072ea9f\\"}}' AWS_PROFILE=elit_nonprd serverless offline start -s dev --noAuth",
...

请注意,有两个权限需要 由 space 分隔。 运行 npm run serve 在 Windows 上给出以下错误:

> @mypackage@1.0.0 serve C:\path
> cross-env AUTHORIZER='{\"claims\":{\"permissions\":\"[view:accounts manage:accounts]\",\"sub\":\"auth0|5cfe0adce3c4c50ea072ea9f\"}}' AWS_PROFILE=elit_nonprd serverless offline start -s dev --noAuth

The filename, directory name, or volume label syntax is incorrect.
events.js:288
      throw er; // Unhandled 'error' event
      ^

Error: spawn manage:accounts]","sub":"auth0|5cfe0adce3c4c50ea072ea9f"}} ENOENT
    at notFoundError (C:\path\node_modules\cross-spawn\lib\enoent.js:6:26)
    at verifyENOENT (C:\path\node_modules\cross-spawn\lib\enoent.js:40:16)
    at ChildProcess.cp.emit (C:\path\node_modules\cross-spawn\lib\enoent.js:27:25)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:275:12)
Emitted 'error' event on ChildProcess instance at:
    at ChildProcess.cp.emit (C:\path\node_modules\cross-spawn\lib\enoent.js:30:37)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:275:12) {
  code: 'ENOENT',
  errno: 'ENOENT',
  syscall: 'spawn manage:accounts]","sub":"auth0|5cfe0adce3c4c50ea072ea9f"}}',
  path: 'manage:accounts]","sub":"auth0|5cfe0adce3c4c50ea072ea9f"}}',
  spawnargs: [
    'AWS_PROFILE=elit_nonprd',
    'serverless',
    'offline',
    'start',
    '-s',
    'dev',
    '--noAuth'
  ]
}

如果我将 cross-env 替换为 cross-env-shell,也会发生这种情况,尽管未显示堆栈跟踪。

当值包含 space 时,是否有通用的跨平台设置环境变量的方法?

更新:我希望的结果是将AUTHORIZER设置为以下值(感谢@RobC 要求澄清):

{
  "claims":
  {
    "permissions": "[view:accounts manage:accounts]",
    "sub": "auth0|5cfe0adce3c4c50ea072ea9f"
  }
}

实现 cross-platform 兼容性真是个难题。经过几次失败的尝试后,似乎无法使用 cross-env:

的单一语法

Windows (cmd) 在下面的 worksOnWin 示例中成功运行,*Nix (sh) 在下面的 worksOnNix 示例中成功运行.

{
  "scripts": {
    "worksOnWin": "cross-env AUTHORIZER={\\"claims\\":{\\"permissions\\":\\"\"[view:accounts manage:accounts]\"\\",\\"sub\\":\\"auth0|5cfe0adce3c4c50ea072ea9f\\"}} AWS_PROFILE=elit_nonprd serverless offline start -s dev --noAuth",
    "worksOnNix": "cross-env AUTHORIZER=\"{\\"claims\\":{\\"permissions\\":\\"[view:accounts manage:accounts]\\",\\"sub\\":\\"auth0|5cfe0adce3c4c50ea072ea9f\\"}}\" AWS_PROFILE=elit_nonprd serverless offline start -s dev --noAuth",
  }
}

解决方案

为了满足您对单一语法的要求 cross-platform 我会考虑使用 node.js 脚本来代替其他方法。

  1. 将此 serve.js 脚本(如下)保存在项目目录的根目录中,即将其保存在与 package.json[=105 相同的级别=] 居住。

    serve.js

    const spawn = require('child_process').spawn;
    
    const processEnv = process.env;
    
    processEnv.AUTHORIZER = '{"claims":{"permissions":"[view:accounts manage:accounts]","sub":"auth0|5cfe0adce3c4c50ea072ea9f"}}';
    processEnv.AWS_PROFILE = 'elit_nonprd';
    
    spawn('serverless', ['offline', 'start', '-s', 'dev', '--noAuth'], {
      env: processEnv,
      stdio: 'inherit',
      shell: true
    });
    
  2. package.jsonscripts 部分重新定义 serve 脚本如下:

    package.json

    {
      ...
      "scripts": {
        "serve": "node serve"
      }
      ...
    }
    
  3. 运行以下命令:

    npm run serve
    

说明

下面解释了serve.js中发生的事情:

  • 首先我们需要child_process module's spawn()方法。

  • 读的部分;[=4​​4=]

    const processEnv = process.env;
    
    processEnv.AUTHORIZER = '{"claims":{"permissions":"[view:accounts manage:accounts]","sub":"auth0|5cfe0adce3c4c50ea072ea9f"}}';
    processEnv.AWS_PROFILE = 'elit_nonprd';
    

    获取现有的环境变量,使用process.env,并将它们分配给processEnv变量。

    随后,我们使用 AUTHORIZERAWS_PROFILE 属性及其必要的值来扩充 processEnv 对象。这实质上定义了两个新的环境变量。

  • 最后我们"shell out" serverless offline start -s dev --noAuth 命令通过 child_process.spawn().

    • { env: processEnv } 部分将 child_process.spawnenv 选项设置为 processEnv 对象,即它为子进程设置环境变量.

    • stdio选项为子进程中的stdin、stdout、stderr配置管道。这可确保您在控制台中获得任何日志记录。

    • shell选项设置为true

注意: 使用此解决方案 cross-env 包变得多余。