I am new to Node js, started developing the Angular application using Angular 1.2 and Node js. As of now, I have hardcoded the REST API(Java) endpoints in the node services.js. Now I want to load the base endpoint URI specific to the environment. I have tried few ways by setting a new key value for the process.env, a env file and load it. Can anyone please help me.
I have tried below approach.
Created devEnv.env file under root folder.
Added 3 key-value pairs
hostname = xyz
apikey = 123
devUrl = xyz/xyz/xyz.com/
Then in terminal, I am trying to add it to the source.
$ source denEnv.env
I am getting source not found.
Another way I have added the script in package.json file
{
"start-dev": "source devEnv.env; node server.js"
}
In terminal I executed
$ npm start-dev
It's also failing. Can anyone please let me know what mistake I am doing and what is the correct approach.
Thanks in advance.
There are three methods known to me:
1) .env file
You need to install dotenv package using npm install/yarn add and on top of your main file (e.g. index.js) put require('dotenv').config(). That should load your variables to node.
2) passed on a start
If you want pass a small amount of environmental variables you can try something like this in your package.json:
{
"start-dev": "hostname=xyz apikey=123 devUrl=xyz/xyz/xyz.com node server.js"
}
Advice: environmental variables should look like HOSTNAME, API_KEY or DEV_URL.
3) system environmental variables
Solution: Set environment variables from file
Your variables are most likely not being exported to the shell. To be able to source your devEnv.env script, try to modify it as follows:
#!/bin/bash
export hostname=xyz
export apikey=123
export devUrl=xyz/xyz/xyz.com/
You most likely need to give it executable rights:
chmod +x devEnv.env
And then source it by running:
. devEnv.env
Another example can be found here: Set environment variables from file
Related
this is my first time im trying to handle " Web api ", so i took this project to get many call but after it running well, when i try to click to "search" it dosent work,
I guess the problem arises from api call because chrome inspector show me that :
I was able to understand on the different forums, for handling apis call with Node.js that must be encapsulated API calls behind "Environment variable".
That the config.js file
When i try to put on the terminal export env.API_KEY='000000000000000' it made me :
export: not valid in this context: env.API_KEY
I hope you can point me in the right direction, I very tried everything, to run it that.
I personally like to use a npm package called dotenv:
You can install it by running npm i dotenv within your api directory.
Have a file called .env within your api directory which contains all of your environment variables:
APP_ID="000000000000000"
API_KEY="000000000000000"
Then change config.js to load all environment variable files when it is executed by including require('dotenv').config():
require('dotenv').config()
module.exports = {
APP_ID: process.env.APP_ID,
API_KEY: process.env.API_KEY,
BASE_URL: 'https://api.adzuna.com/v1/api/jobs',
BASE_PARAMS: 'search/1?&results_per_page=20&content-type=application/json',
};
Note: you will also want to add .env to your .gitingore so that your sensitive API keys aren't included in your git repository
I have a plain old NodeJS project (with Typescript) and I'm really struggling to find out how to do ES6 imports for local files without having to do "../../../foo/bar" all the time.
There are loads of similar questions but all seem to revolve around babel/Webpack which I'm not using.
If I do the following:
import foo from `/bar`
it looks for it in the root folder of my PC (e.g. c:/bar) and fails.
I have tried using a .env file with NODE_PATH set to various hings ("/", "." etc) but no luck. I have also tried setting "type: 'module'" in my package.json and my tsconfig.json file has {"baseUrl": "."}
So I think I've tried every answer I can find. Am I just doing them in the wrong combination or is the solution something different?
Here are two tricks I've used for this, with Node.js and native ES modules.
file: dependencies
If you want to access <project root>/bar from a sub package two levels down, adding this to the package.json dependencies:
"#local/bar": "file:../../bar",
..makes bar available to the said subpackage as #local/bar.
While relative paths are still present, they are now all in the package.json files and the sources never need to know..
Use dynamic import()
Pick the root folder's path to a constant and do this:
const foo = await import(`${rootPath}/bar`);
This was pretty simple to implement for me, using Typescript in VSCode.
In tsconfig.json, I added "baseUrl": "./", under compilerOptions
After a restart of VSCode, VSCode will automatically import using psuedo-absolute paths.
The paths won't begin with /, that still points to your drive root.
If the is below the current file, it will still use a ./relative/path, but no more ../../tree/traversing
Then I set dev in packages.json to
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "cross-env NODE_PATH=./ nodemon ./app.ts"
},
I use cross-env. You may use the set command and nodemon for automatic reloading of change files.
Setting NODE_PATH to ./ tells NodeJS to do what Visual Studio and TypeScript are doing.
I do have package.json in my src directory. You may not, and may need to change some pathing to adjust.
I am not sure what you mean by "local files without having to do "../../../foo/bar""
Let me explain how Javascript handles imports. Here is a basic folder structure.
C:Users/NAME/Project/randomfolder/bar.js
- Project
- Random Folder
- foo.js
- bar.js
Option 1 Probably the better option for 95% of what you will do
Let's say you are trying to import foo.js into bar.js we first get our current location of bar.js using a . so it would be
import foo from "./Random Folder/foo.js"
If you are going the other way the . is still used to say get current location in the folder structure but you pass a second . so .. then a / to go up a folder. So to import bar.js into foo.js it would look like this:
import bar from "../bar.js"
We are going up a folder then looking for the file we want.
Option 2
But if you know you folder structure is going to be very big and you will be importing always a few folders up or down why not make a variable and then use string literals.
let folder = `../../../`
import test from `${folder}foo`
You have a few options of how to handle what you want to do.
Option 3 For NodeJS and modules
If you are using NodeJS and want to get the path not relative, the use the app-root-path module. It lets you always get your project root and then dig into to files accordingly. This can be accomplished with string literals.
var appRoot = require('app-root-path');
import foo from appRoot + "/foo/bar/folders/bla/bla"
or
import foo from `${appRoot}/foo/bar/folders/bla/bla` <-- string literals
What's the proper way of setting environment variables in netlify? I would like to be able to set different values for the variables depending on the environment.
Pseudo code:
let host;
if (process.env.GATSBY_CUSTOM_CONTEXT === 'production') {
host = process.env.PRODUCTION_HOST
} else if (process.env.GATSBY_CUSTOM_CONTEXT === 'development') {
host = process.env.DEVELOPMENT_HOST
}
I have tried passing env variable thru CLI, like GATSBY_CUSTOM_CONTEXT=production gatsby build and I also tried using same command with cross-env.
My other attempt used netlify.toml:
[build]
base = "/"
publish = "public"
command = "yarn build"
functions = "src/functions"
[context.production]
[context.production.environment]
GATSBY_CUSTOM_CONTEXT = "production"
All of these options worked with netlify dev locally, but in production GATSBY_CUSTOM_CONTEXT is always undefined.
The reason you can't resolve the environment variables in your Netlify functions is because as of the time of your question, Netlify does not transfer the environment variables from the netlify.toml file.
You must put them into the admin panel in your site settings in the app.netlify.com dashboard.
Unfortunately, what you're looking to doesn't seem to be currently supported. Though they provide an alternative approach.
I found this snippet on their docs:
CALLING ENVIRONMENT VARIABLES
Using environment variables directly as
values ($VARIABLENAME) in your netlify.toml file is not supported.
However, the following workflow can be used to substitute values in
the file with environment variable values, assuming you are only
trying to change headers or redirects. The rest of the file is read
BEFORE your build — but those sections are read AFTER the build
process.
Add a placeholder like HEADER_PLACEHOLDER somewhere in the netlify.toml redirects or headers sections.
Create an environment variable, for example PROD_API_LOCATION, with the desired value. You can create environment variables in the
toml file or in our UI. You might use the latter to keep sensitive
values out of your repository.
Prepend a replacement command to your build command. Here’s an example for a site using yarn build to build: sed -i
s/HEADER_PLACEHOLDER/${PROD_API_LOCATION}/g netlify.toml && yarn build
Taken from here: https://www.netlify.com/docs/netlify-toml-reference/
Background:
I have 3 different URLs, one per environment (dev, test, prod), and I don't want to expose all the URLs in the client (source code).
How can I expose in the client code, just the one corresponding to the environment in context?
Note: As I understand, I need to do something in the build process using environment variables (I'm using node.js). However, I don't want to touch anything related with webpack, as what I'm trying to do is a standalone package that can be imported in any application regardless of the framework they are using. Webpack plugins/configuration are not an option, but I can use any npm package if required.
During your build process, you can check the environment variable and then copy over a config file. For example, you could keep your URIs in /config/<env>.js, and then copy/rename it to /settings.js during the build. Your URL could be exported from that.
The following npm package fits my requirements completely https://www.npmjs.com/package/config , you can load conditional files based on the node environment variable NODE_ENV, so when NODE_ENV=development, the file /config/development.js is used to create the build. you can use different extensions for the config files, also you can customize the config folder path by changing the environment variable $NODE_CONFIG_DIR heres an example:
const config = require('config');
process.env.$NODE_CONFIG_DIR = './' // relative path ./config
const url = config.get('url');
//if NODE_ENV is development will load the file config/development.js
console.log(url);
I'm using Express and I need to use different credentials for each server (staging and production).
I could setup the variables in the server.coffee file but then I'd need to access those variables in different files.
server.coffee:
app.configure 'production', () ->
app.use express.errorHandler()
What's the solution? Setup the variables and then export them?
./config.js
var development = {
appAddress : '127.0.0.1:3000',
socketPort : 4000,
socketHost : '127.0.0.1',
env : global.process.env.NODE_ENV || 'development'
};
var production = {
appAddress : 'someDomain.com',
socketPort : 4000,
socketHost : '8.8.8.8',
env : global.process.env.NODE_ENV || 'production'
};
exports.Config = global.process.env.NODE_ENV === 'production' ? production : development;
./app.js
var cfg = require('./config').Config;
if (cfg.something) { // switch on environment
// your logic
}
This might be a good place to use npm-config.
When running scripts (see npm-scripts(7)) the package.json "config" keys are overwritten in the environment if there is a config param of <name>[#<version>]:<key>
I would not use them for every type of variable configuration setting, but I think it's a good solution for simple cases like URLs and ports because:
You put them directly into package.json.
In addition, you can specify them on the command line or as ENV variables.
Anything run through npm can refer to them (e.g., scripts).
You can set them per-user with `npm config set foo:port 80
The one caveat is that the config parameter in your package.json is only automatically exported into the environment when you run your code through npm. So, if you just run it with node, like, node ./myapp.js, then you can't expect that process.env.npm_package_config_foo will contain your value. However, you can always var pkg = require('./package.json'); and access the values at pkg.config.
Because it might not be immediately obvious, I'd also add that the npm_package_config environment variables do not bubble up to apps that depend on your npm package. So, if your depended-on package refers to process.env.npm_package_config_foo, then the dependent package would have to define that in its own package.json. I guess since it's an "npm_package_config" it wouldn't make sense to push them all the way up the tree.
So, how would I use one npm config variable and have it work all the way up the tree, in both the base package and the packages that depend on it? It's actually a little confusing, and I had to figure this out through trial and error.
Let's say you have a package connector and package client. client depends on connector and you want to specify a config parameter for connector that can be used or overwritten in client. If you use process.env.npm_package_config.port in your connector module, then when it's depended on in client module, then that variable won't be exported and it will end up as undefined.
However, if you instead use process.env.npm_config_connector_port (notice the first one starts with npm_package_config and the other with npm_config_packagename), then you can at least set that in your .npmrc using npm config set connector:port 80 and it will be "namespaced" as process.env.npm__config_connector_port everywhere that you run npm, including scripts that you run in client that depend on connector, and you'll always be able to overwrite it on the command line, in your ENV, or in your .npmrc. You just have to keep in mind that, as with any environment variable, it may not always be set. So, I would use the default operator with the process.env.npm_config_connector_port as the first (preferred) value:
var port = process.env.npm_config_connector_port || sane_default
Here, sane_default could be populated from one of the other recommended methods. Personally, I like keeping configuration data like these in JSON files at the very least, and package.json seems like the best JSON file to put them in. Store them in data instead of code and then you can easily use the static JSON in-line, generate them dynamically, or pull them from the filesystem, URLs or databases.
I have uploaded an implementation into https://github.com/qiangyu/nodejsconfig. I believe it will satisfy your needs. Basically, you only need to provide one configuration file:
dev.appAddress = '127.0.0.1:3000';
prod.appAddress = 'someDomain.com';
Then, you use following code to read the appAddress in prod environments:
var xnconfig = require('nodejsconfig');
var fs = require('fs');
var data = fs.readFileSync(__dirname+"/config.properties", "UTF8");
// assume we will be using environment "prod"
var config = xnconfig.parse("prod", data);
// the output will be someDomain.com
console.log(config.getConfig("appAddress"));
If you don't want the logic for determining which config to use in each file (which would look pretty ugly), you'll have to export it somewhere.
What I would suggest: Have a config.json file containing the different configs. The main file requires it and does something like config.default = config.(condition ? 'production':'development'). In all other files, you can now just do require('./config').default.
I have an app which uses three different methods of declaring config variables (uris, api keys, credentials, etc.) depending upon the environment (production = environment variables; staging = command line args; local = config files.)
I wrote a little "config" module to handle merging all of these options into one object that I can use in my app and uploaded it as a gist: https://gist.github.com/1616583
It might not be the best implementation, but it's been working pretty well so far :).