Reputation: 4685
I am developing a serverless NodeJS app and need to test it in offline mode. I have an npm
script in a package.json
file that looks like this:
"scripts": {
"serve": "cross-env AUTHORIZER='{\\\"claims\\\":{\\\"permissions\\\":\\\"[view:accounts manage:accounts]\\\",\\\"sub\\\":\\\"auth0|5cfe0adce3c4c50ea072ea9f\\\"}}' AWS_PROFILE=elit_nonprd serverless offline start -s dev --noAuth",
...
Note that there two permissions that need to be separated by a space. Running npm run serve
on Windows gives the following error:
> @[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]","sub":"auth0|5cfe0adce3c4c50ea072ea9f"}}',
spawnargs: [
'AWS_PROFILE=elit_nonprd',
'serverless',
'offline',
'start',
'-s',
'dev',
'--noAuth'
]
}
This also happens if I replace cross-env
with cross-env-shell
, although the stack-trace is not shown.
Is there a common cross-platform way to set environment variables when the values contain spaces?
Update: the outcome I am hoping for is to set AUTHORIZER
to the following value (thanks to @RobC for requesting clarification):
{
"claims":
{
"permissions": "[view:accounts manage:accounts]",
"sub": "auth0|5cfe0adce3c4c50ea072ea9f"
}
}
Upvotes: 2
Views: 3120
Reputation: 24952
What a puzzle this is to achieve cross-platform compatibility. After several failed attempts it does not seem possible to utilize a single syntax with cross-env
:
Windows (cmd
) works successfully with the worksOnWin
example below, and *Nix (sh
) works successfully with the worksOnNix
example below.
{
"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",
}
}
To address your requirement for a single syntax cross-platform I would consider a different approach by utilizing a node.js script instead.
Save this serve.js
script (below) in the root of your project directory, i.e. save it at the same level where package.json resides.
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
});
In the scripts
section of your package.json redefine your serve
script as follows:
package.json
{
...
"scripts": {
"serve": "node serve"
}
...
}
Run the following command:
npm run serve
The following explains what's happening in serve.js:
Firstly we require the child_process
module's spawn()
method.
The part that reads;
const processEnv = process.env;
processEnv.AUTHORIZER = '{"claims":{"permissions":"[view:accounts manage:accounts]","sub":"auth0|5cfe0adce3c4c50ea072ea9f"}}';
processEnv.AWS_PROFILE = 'elit_nonprd';
obtains the existing environment variables, using process.env
, and assigns them to the processEnv
variable.
Subsequently, we augment the processEnv
object with the AUTHORIZER
and AWS_PROFILE
properties and their necessary values. This essentially defines the two new Environment variables.
Finally we "shell out" the serverless offline start -s dev --noAuth
command via child_process.spawn()
.
The { env: processEnv }
part sets child_process.spawn
's env
option to the processEnv
object, i.e. it sets the environment variables for the child process.
The stdio
option configures the pipes for stdin, stdout, stderr in the child process. This ensures you get any logging in the console.
The shell
option is set to true
.
Note: The cross-env
package becomes redundant using this solution.
Upvotes: 2