问题描述
我正在开发无服务器NodeJS应用,需要在离线模式下对其进行测试。我在npm
文件中有一个package.json
脚本,如下所示:
"scripts": {
"serve": "cross-env AUTHORIZER='{\\\"claims\\\":{\\\"permissions\\\":\\\"[view:accounts manage:accounts]\\\",\\\"sub\\\":\\\"auth0|5cfe0adce3c4c50ea072ea9f\\\"}}' AWS_PROFILE=elit_nonprd serverless offline start -s dev --noAuth",...
请注意,有两个权限需要用空格分隔。在Windows上运行npm run serve
会出现以下错误:
> @[email protected] 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]",spawnargs: [
'AWS_PROFILE=elit_nonprd','serverless','offline','start','-s','dev','--noAuth'
]
}
即使未显示堆栈跟踪,如果我将cross-env
替换为cross-env-shell
,也会发生这种情况。
当值包含空格时,是否存在一种通用的跨平台方法来设置环境变量?
更新:我希望得到的结果是将AUTHORIZER
设置为以下值(感谢@RobC要求澄清):
{
"claims":
{
"permissions": "[view:accounts manage:accounts]","sub": "auth0|5cfe0adce3c4c50ea072ea9f"
}
}
解决方法
实现跨平台兼容性是一个难题。在几次尝试失败之后,似乎无法在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",}
}
解决方案
要满足您对单一语法跨平台的需求,我会考虑通过使用 node.js 脚本代替的方法。
-
将此
serve.js
脚本(如下)保存在项目目录的根目录中,即,将其保存在 package.json 所在的同一级别。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 });
-
在您的 package.json 的
scripts
部分中,重新定义serve
脚本,如下所示:package.json
{ ... "scripts": { "serve": "node serve" } ... }
-
运行以下命令:
npm run serve
说明
以下内容说明 serve.js 中发生的事情:
-
首先,我们需要
child_process
模块的spawn()
方法。 -
阅读部分;
const processEnv = process.env; processEnv.AUTHORIZER = '{"claims":{"permissions":"[view:accounts manage:accounts]","sub":"auth0|5cfe0adce3c4c50ea072ea9f"}}'; processEnv.AWS_PROFILE = 'elit_nonprd';
使用
process.env
获取现有的环境变量,并将其分配给processEnv
变量。随后,我们使用
processEnv
和AUTHORIZER
属性及其必要的值来扩充AWS_PROFILE
对象。这实际上定义了两个新的环境变量。 -
最后我们通过
serverless offline start -s dev --noAuth
“掏空”child_process.spawn()
命令。-
{ env: processEnv }
部分将child_process.spawn
的{{3}}选项设置为processEnv
对象,即,它设置子进程的环境变量。 -
env
选项在子进程中为stdin,stdout,stderr配置管道。这样可以确保您在控制台中获得任何日志记录。 -
shell
选项设置为true
。
-
注意:使用该解决方案,cross-env
程序包变得多余。