Access npm task parameters from javascript files - node.js

In my package.json I have a script like so:
"start": "runsMyApp --value=tt && node -e 'console.log(process.env)'"
When I run my script
npm run start
I can see my variable logged:
npm_config_value: 'tt'
My question is, can I access the npm_config_value from process.env.npm_config_value in my js files as I can do with process.env.NODE_ENV ?
I can't manage to pick its value, I have also tried with process.npm_config_value without success...
Any hints on this?

Related

react-native unable to assign Production for NODE_ENV variable

I am trying to utilise the process.env.NODE_ENV to switch between the environments for my react native app, and am facing two issues here
1. Assigning parameter to NODE_ENV doesn't seem to change the env value straight forward,
executing the below command shows that it changed process.env.NODE_ENV value but doesnt seem to have changed the global.process.env.NODE_ENV
execution command:
NODE_ENV=development npm start -- --reset-cache
output: Please note, the second log statement still prints out development.
console.log("printing the changed value - ", process.env.NODE_ENV); // --> printing the changed value - production
console.log("checking the env content - ", process.env); // ---> checking the env content - { NODE_ENV: 'development' }
Workaround that i tried is to assign the process.env.NODE_ENV to the global instance,
global.process.env.NODE_ENV = process.env.NODE_ENV
Please do advise if this is a good approach to proceed with.
2. Assigning "Production" as a value to NODE_ENV throws Attempted to Assign to read only property error,
Execution Command:
NODE_ENV=production npm start -- --reset-cache
Please find image attached -
AssignToReadOnlyPropertyIssue
The problem your facing here comes from an erroneous assumption:
react-native doesn't execute javascript in the same way as node.
Let's consider the following npm script:
"scripts": {
"start": "node index.js"
}
When running SOME_VAR="some value" npm start, process.env will contain a entry for that environment variable, since it is running from the process where SOME_VAR was defined.
In react-native something different happens:
calling npm start starts the react-native packager which bundles your javascript code and then sends that javascript bundle to the installation in your emulator or device, where the bundle is in its turn executed. react-native's packager doesn't "forward" the environment variables defined where the javascript was bundled.
Hopefully there are packages that aid us to be able to keep using the same patterns we're used to using when developing node apps.
One I found really helpful was babel-plugin-transform-inline-environment-variables. This is a babel plugin that transforms process.env.SOME_VAR type calls to the value of SOME_VAR during bundle time.
The only headache I had with it was that when I was first trying to see how it worked I was changing the environment variables, but it only seemed to work "randomly". Turns out I was a victim of webpack's cache. If there are no changes in the code it is watching it won't update the bundle. I then learned I had to be aware of that

Target certain environments based on console input

To preface the question I am using an ejected create-react-app for the layout of my project.
I have 5 environments that my application is going to be deployed to. Each environment has the same set of services (mostly), for example one might look like:
//environment 1
https://environment1.service1.foo.bar
https://environment1.service2.foo.bar
//environment 2
https://environment2.service1.foo.bar
https://environment2.service2.foo.bar
To achieve this on past projects (Angular/Gulp) I had a gulp task that essentially would look for a variable being passed in
gulp build --environment environment1
The code to do so looks like this:
gulp.task('environment', ['clean-environment'], function() {
log('Copying environment');
var environmentFile = config.environmentSrcDir + 'env2.js';
if (args.environment !== 'env2' ||
args.environment === 'env3' ||
args.environment === 'env4' ||
args.environment === 'evn5') {
environmentFile = config.environmentSrcDir + args.environment + '.js';
}
return gulp
.src(environmentFile)
.pipe(rename(config.environmentService))
.pipe(gulp.dest(config.root));
});
And basically point to the correct file with the correct endpoints inside of it as well as other pertinent variables associated with that environment.
My question is, where given the fact that I am using create-react-app as a starting point, so webpack, and node scripts, how would I accomplish something like this. Basically I want to be able to say yarn build env1 and then the project to set a constant or file of constants as the 'active` constants so to speak.
If you are using "Create-react-app" then you have the ability to define development environment variable through different .env files.
Link: https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#adding-development-environment-variables-in-env
.env:
REACT_APP_GOOGLE_CLIENT_ID = XXX-YYY-ZZZ.apps.googleusercontent.com
REACT_APP_API_PROTOCOL = http:
REACT_APP_API_HOST = localhost:3000
NODE_PATH = src/scripts
PORT = 9001
.env.production:
REACT_APP_GOOGLE_CLIENT_ID = ZZZ-YYY-XXX.apps.googleusercontent.com
REACT_APP_API_PROTOCOL = https:
REACT_APP_API_HOST = api.my-applicaton.com
NODE_PATH = src/scripts
Read different .env configs according to current command (start / test / build). dev.env for start and test. prod.env for build. If custom config does not exist — read env variables from .env file.
Blockquote
You will tell which .env file will be used with your start project command.
You should have something like this in your package.json file under scripts object:
"start-js": "react-scripts start",
"start": "npm-run-all -p watch-css start-js",
"build": "npm run build-css && react-scripts build",
Then you can start your project using specified commands. From the documentation, files on the left have more priority than files on the right:
npm start: .env.development.local, .env.development, .env.local, .env
npm run build: .env.production.local, .env.production, .env.local, .env
npm test: .env.test.local, .env.test, .env (note .env.local is missing)
For example, if you start with npm run build, you will be able to access variables defined in .env.production file.
In JavaScript code, you can use process.env.REACT_APP_API_HOST.
Also, see this link on medium.com: https://medium.com/#tuchk4/why-i-love-create-react-app-e63b1be689a3

How does npm run a script to set system environment which can be used by another npm run script

I set several scripts in package.json of npm, e.g.
{
"scripts": {
"server:install": ". ./scripts/server-install.sh",
"server:start": ". ./scripts/server-start.sh",
"server:stop": ". ./scripts/server-stop.sh",
"test:e2e": "jest --collectCoverage false test/**/*"
}
}
in server-start.sh, I will start dynamoDB service locally and need to set system environment AWS_API_KEY value. The value will be used in test cases when npm run test:e2e.
But, the problem is that the value I set for AWS_API_KEY in server:start can't be used in test:e2e. It seems that the variable set operation in server-start.sh will not change the system variables of current console/sessions.
I googled and tried like:
"server:start": "AWS_API_KEY=dummy . ./scripts/server-start.sh"
or by using cross-env
"server:start": "cross-env-shell AWS_API_KEY=dummy && . ./scripts/server-start.sh"
Both failed. The only left idea I can think of is to write the AWS_API_KEY to ~/.bash_profile. I don't want to do that.
Any help will be much appreciated.

Passing environment variables in npm-scripts

I have a package.json with following (simplified) content in the scripts key:
...
scripts: {
"start": "NODE_ENV=${NODE_ENV:=production} node start-app.js",
"poststart": "echo $NODE_ENV"
}
...
From the command line I can run:
npm start
This will run my start-app.js script and set the process.env.NODE_ENV environment variable to "production". See here for syntax explanation.
The poststart will automatically run after start as described here.
However poststart will not "inherit" the NODE_ENV shell environment variable, so the echo command will not echo anything.
My producation code is a little more complex, but what I am trying to accomplish is passing down the NODE_ENV variable from the "starting point" to dependent scripts. Any suggestions/best practices on how to do that?
I dont want to hardcode the NODE_ENV in the poststart, because I might want to do:
NODE_ENV=development npm start
and I want everyting "down the chain" inherit the same environment.
You have a few options:
better-npm-run,which can define an env for each command separately
Instead of a poststart script, you can concatenate commands for npm like so: "start": "NODE_ENV=${NODE_ENV:=production} node start-app.js && echo $NODE_ENV"
Use a process manager in production like pm2. pm2 lets you define environment specific json files with settings such as NODE_ENV. At our company, we successfully run all of our apps in different environments with pm2 (all the while having the same start command)
this is how I did it, first you need to install two dev-dependencies
https://www.npmjs.com/package/env-cmd
this load your env var from your file
https://www.npmjs.com/package/cross-env
this use environment variable in script
example scripts:
"env-cmd ./.config/prod.env cross-env-shell \"docker volume create $DOCKER_VOLUME\""
this load $DOCKER_VOLUME env var from prod.env
update:
starting from env-cmd version 10, you need specify -f flag if you want to use a custom env file path
"env-cmd -f ./.config/prod.env cross-env-shell \"docker volume create $DOCKER_VOLUME\""
If you have small use cased, use better-npm-run. For small cases, it works fine. Somehow if you have a lot of commands and it hard manage. Try, batman-cli. Work well and handle lot of environment-dependent issues
npm i -g batman-cli

How to use nodemon/grunt with .env files?

I am using an .env file to work with foreman, but am trying to configure nodemon to start my server using grunt, because I enjoy how nodemon restarts when files become modified.
I am trying avoid having an .env file for foreman AND having environment variables stored in my ~/.bash_profile for nodemon. Instead, I would like to configure my .env file to work for both cases.
I found some answers here, and the second answer should work for grunt.
My .env file is of JSON format, which should flatten environment variables via concatenation (see here).
When I run the following command $ env $(cat .env) nodemon app.js, I receive the following error: env: {: No such file or directory.
Anyone have an idea of what the problem may be? Cheers.
I'd suggest filing this at http://github.com/remy/nodemon/issues/new - but I'd also say that there's environment config support in nodemon as of 1.0.9 - though I'm not 100% sure it'll solve what you want.
Basically you put a nodemon.json file in your home directory, and have:
{
"env": {
"USER": "remy",
"PORT": "8000",
"ETC": "etc"
}
}
An example of the config can be seen here and a few more details here.
I haven't tried using the nodemon. But I've figured out how to do restart the server using foreman.
Define a key on your Procfile to run your application with node-supervisor
My proc file have a dev key that is like this: dev: node-supervisor -w .,lib/ webserver.js
The -w option is a comma separated list of the folders that you want to watch.

Resources