Brand new to node trying to understand a project. The project loads on dev on a windows machine just fine, but throws this error on Azure App Services..
TypeError: Cannot read property 'database' of undefined
when trying:
config.database for example in index.js
models/index.js
const env = process.env.NODE_ENV || "development";
const config = require(path.join(__dirname, '..', 'config', 'config.json'))[env];
>>> var whatever = config.database; <<<
config/config.json
{
"development": {
"logging": false,
"dialect": "mssql",
"username": "whatever",
"password": "whatever",
"database": "whatever",
"host": "whatever",
"dialectOptions": {
"encrypt": true
}
}
}
No idea where to start with this since it works fine on local. The file location seems correct, path is valid, path.join() works fine...
Thank you!
There is really only one main possibility here and you need to do a little bit of your own debugging to verify it.
Because this statement does not generate an error:
const config = require(path.join(__dirname, '..', 'config', 'config.json'))[env];
That means that require(path.join(__dirname, '..', 'config', 'config.json')) is returning a Javascript object. So, there must indeed be a file at the path you construct and it must be giving you an object when you require() it.
But, the error itself: TypeError: Cannot read property 'database' of undefined when you try to reference config.database means that config is undefined. The only way that happens is that you're using a value for env that is not in your config object.
That's like trying to do this:
const obj = {development: {someKey: "someValue"}}; // what require() gives you
const env = "test"; // your value for env
const config = obj[env]; // reading non-existent [env] property
console.log(config); // undefined
So, add console.log(env) to your code to see what env actually is and then verify that you have an object in your config data structure for that specific value (or set the desired value in the environment).
If you had verified the value of env yourself with basic debugging steps before posting here, you probably would have solved your own problem (hoping you can learn simple techniques to solve more of your own problems).
If you didn't follow all of my original logic, you could also just debug it like this:
const env = process.env.NODE_ENV || "development";
console.log("env: ", env);
const configPath = path.join(__dirname, '..', 'config', 'config.json');
console.log("configPath: ", configPath);
const configObj = require(configPath);
console.log("configObj: ", configObj);
const config = configObj[env];
console.log("config: ", config);
Related
in server code I have this:
import express from "express";
const server = express();
import path from "path";
// const expressStaticGzip = require("express-static-gzip");
import expressStaticGzip from "express-static-gzip";
import webpack from "webpack";
import webpackHotServerMiddleware from "webpack-hot-server-middleware";
import configDevClient from "../../config/webpack.dev-client";
import configDevServer from "../../config/webpack.dev-server.js";
import configProdClient from "../../config/webpack.prod-client.js";
import configProdServer from "../../config/webpack.prod-server.js";
const isProd = process.env.NODE_ENV === "production";
const isDev = !isProd;
const PORT = process.env.PORT || 8000;
let isBuilt = false;
const done = () => {
!isBuilt &&
server.listen(PORT, () => {
isBuilt = true;
console.log(
`Server listening on http://localhost:${PORT} in ${process.env.NODE_ENV}`
);
});
};
if (isDev) {
const compiler = webpack([configDevClient, configDevServer]);
const clientCompiler = compiler.compilers[0];
const serverCompiler = compiler.compilers[1];
const webpackDevMiddleware = require("webpack-dev-middleware")(
compiler,
configDevClient.devServer
);
const webpackHotMiddlware = require("webpack-hot-middleware")(
clientCompiler,
configDevClient.devServer
);
server.use(webpackDevMiddleware);
server.use(webpackHotMiddlware);
console.log("process.env.NODE_ENV",process.env.NODE_ENV);//RETURNS UNDEFINED
server.use(webpackHotServerMiddleware(compiler));
console.log("Middleware enabled");
done();
} else {
webpack([configProdClient, configProdServer]).run((err, stats) => {
const clientStats = stats.toJson().children[0];
const render = require("../../build/prod-server-bundle.js").default;
server.use(
expressStaticGzip("dist", {
enableBrotli: true
})
);
server.use(render({ clientStats }));
done();
});
}
I client and server config files I have this plugin enabled:
new webpack.DefinePlugin({
"process.env": {
NODE_ENV: JSON.stringify("development"),
WEBPACK: true
}
but this is the output
process.env.NODE_ENV undefined
Server listening on http://localhost:8000 in undefined
in client side it is working BUT express side process.env.NODE_ENV returns undefined
Assuming you using Webpack-Dev-Server, you can use this call syntax witch is proper :
const dev = Boolean( process.env.WEBPACK_DEV_SERVER )
You will no longer need to pass environment type parameters, because I think you pass parameters in your script run in packages.json
I'm writing my experience to help anyone out there with this problem, though I did not actually solve it. I had the same problem with setting the environment variables in my server-side project.
apparently, after you set the environment variables they are completely accessible in the building process, which is in the build tools like webpack config or even .babelrc.js.
but after the build process, the environment variables get overwritten AND there is a time gap between build process and overwriting environment variables.
I used many webpack or babel plugins but neither of them could hold on to environment variables after the build process ON the server-side but they were immediately defined on the client-side.
since I'm using ReactJs, I tried adding REACT_APP_ to the beginning of variables, but still no luck.
some other plugins I used: webpack dotenv, webpack.DefinePlugin, webpack.EnvironmentPlugin, babel-plugin-transform-define, babel-plugin-transform-inline-environment-variables
so it made me use the good old-fashion way of setting environment.js on DEPLOY but not on the BUILD process.
in case someone is not familiar: you have one main environment.js and (in my case) 2 other files, one for staging environment.staging.js and one for production environment.prod.js. On each deploy, you copy the related js to environment.js, the main environment file, and in your code, you always read global CONSTs,baseUrl for APIs and ... from environment.js.
hope it helps someone out there.
When trying to fetch data from an API, the key that I was using was considered "undefined". My key works because I replaced the {key=undefined} in the network console with the actual string and I was able to get the data that I needed. Any thoughts? Also, I know you shouldn't hide any API keys in a React app but I am just using this for testing purposes. If it helps to clarify things, I did use Create-React-App and they did have a major update in the last 3 months, so I wonder if that has anything to do with it.
const bartKey = process.env.REACT_API_BART_API_KEY;
console.log(`Api key: ${process.env.REACT_API_BART_API_KEY}` );
//inside class Component
async getAllStations(){
try{
const response = await fetch(`http://api.bart.gov/api/etd.aspx?cmd=etd&orig=${this.state.selectedStation}&key=${bartKey}&json=y`);
// console.log(response.json());
const data = await response.json();
console.log('Initial data: ', data);
// fetch(`http:api.bart.gov/api/etd.aspx?cmd=etd&orig=${this.state.selectedStation}&key=${bartKey}&json=y`)
// .then(response => response.json())
// .then(data => console.log(`here: ${data}`))
}catch(e){
console.log(`Error: ${e}`)
}
}
this works for me when using create-react-app:
instead of REACT_API_BART_API_KEY use REACT_APP_BART_API_KEY in your .env
Then you can call it as process.env.REACT_APP_BART_API_KEY
check this url from create-react-app docs https://facebook.github.io/create-react-app/docs/adding-custom-environment-variables
I would say a really good solution if your .env file is working weird is to make a config file. Keep the API key in there. Put that file in git ignore and it will be hidden the same way and it is sure to work.
This changes helped me solve my issue:
Please note dotenv is a zero-dependency module that loads environment variables from a .env file into process.env. So this you should at first download this package:
1 step: npm install dotenv --save-dev
Import webpack and dotenv in your webpack.config.js file and make this changes:
After make sure module.exports an function which at first generates the environment keys:
When the keys are generated use webpack.DefinePlugin() which will help you generate global constants for your app.
// other imports
const dotenv = require('dotenv');
const webpack = require('webpack');
module.exports = () => {
const env = dotenv.config().parsed;
const envKeys = Object.keys(env).reduce((prev, next) => {
prev[`process.env.${next}`] = JSON.stringify(env[next]);
return prev;
}, {});
return {
/* ... here should be your previous module.exports object attributes */
entry: ['babel-polyfill', './src/index.js'],
output: {
path: path.join(__dirname, 'build'),
filename: 'bundle.js',
},
plugins: [
new HtmlWebPackPlugin({
template: "./public/index.html",
filename: "./index.html"
}),
new webpack.DefinePlugin(envKeys)
]
}
};
Also note that on logging process.env you will still get empty object or nothing. But if you log process.env.YOU_KEY then you will get your key value stringified
Hope it helps you!
As early as possible in your application, require and configure dotenv. (https://www.npmjs.com/package/dotenv)
require('dotenv').config()
You should write that line as early as possible in your program.
So I have install npm config module.
I have trying to set a local variable that stores a secret/privateKey.
Tried setting an environment variable/private key using the following command
export VIDLY_JWTPRIVATEKEY=MYSECUREKEY
however it don't think It is being set as I get an error via
console.log("FATAL ERROR: JWTPRIVATEKEY is not defined");
This is how I am checking if the key is set..
index.js
if (!config.get("JWTPRIVATEKEY")) {
console.log("FATAL ERROR: JWTPRIVATEKEY is not defined");
// node environment variable. 1 (any other number exc. 0) is exit the app, 0 is success
process.exit(1);
}
userAuth.js I once again try to get the private, however its not set (?)
#code above
const token = jwt.sign({ _id: user._id }, config.get("JWTPRIVATEKEY"));
default.json (in config module folder)
{
"JWTPRIVATEKEY": ""
}
custom-environment-variables.json (in config folder)
{
"JWTPRIVATEKEY": "VIDLY_JWTPRIVATEKEY"
}
**
ERROR: "FATAL ERROR: JWTPRIVATEKEY is not defined"
**
What am I doing wrong?
Instead of setting the variable with this way, you can try to set it in production and development config folders like this:
config/development.js
const config = {
env: 'development',
JWTPRIVATEKEY: <your_dev_key>
};
module.exports = config;
config/production.js
const config = {
env: 'production',
JWTPRIVATEKEY: <your_prod_key>
};
module.exports = config;
it is two years later! but i think it can be useful, atleast for others.
if you set environment variable AND run the app in IDE's Terminal, it will not work!
but if do these in "cmd", it works.
I have a node.js application built using graphql. I need to check an 'environment variable' to see what environment I'm on (development, testing, production). Based on that environment, I need to set a url. I think I have a vague idea of what I need but don't know how to accomplish it.
Currently my config.js file looks something like this:
const configuration = convict({
env: {
format: ['development', 'testing', 'production'],
default: 'development',
arg: 'nodeEnv',
env: 'NODE_ENV'
}
const env = configuration.get('env');
configuration.loadFile(`./config/${env}.json`);
configuration.validate({allowed: 'strict'});
module.exports = configuration.getProperties();
)};
And then in a separate file where I actually need to set the url based on the environment, I need to do so based on the kind of environment (development, test or production) that I'm on. The code in that file would be:
If(env=='development'){
const url = 'abc.def.com/xxx/yyy/zzz/graphql';
}
Else If (env == 'testing'){
const url = 'xxx.yyyy.com/abc/def/ghi/graphql';
}
Else{
const url = '123.abc.com/cdc/def/hhh/graphql';
}
I tried to console.log the env value but when I try the following:
console.log( env );
I get an error: Reference error: env is not defined.
Can someone point me to what I'm missing/doing wrong to access the env variable?
You can access them like this:
process.env.VARIABLE_NAME
In a vue cli 3 project I want to display a version number in the webpage. The version number lies in the package.json file.
The only reference to this that I found is this link in the vue forum.
However, I can't get the proposed solution to work.
Things I tried
Use webpack.definePlugin as in the linked resource:
vue.config.js
const webpack = require('webpack');
module.exports = {
lintOnSave: true,
configureWebpack: config => {
return {
plugins: [
new webpack.DefinePlugin({
'process.env': {
VERSION: require('./package.json').version,
}
})
]
}
},
}
Then in main.ts I read process.env, but it does not contain VERSION (I tried several variants to this, like generating a PACKAGE_JSON field like in the linked page, and generating plain values like 'foo' instead of reading from package-json). It never worked, it is like the code is being ignored. I guess the process.env is being redefined later by vue webpack stuff.
The process log in main.ts contains, however, all the stuff that process usually contains in a vue-cli project, like the mode and the VUE_APP variables defined in .env files.
Try to write to process right on the configure webpack function,
like:
configureWebpack: config => {
process.VERSION = require('./package.json').version
},
(to be honest I did not have much hope with this, but had to try).
Tried the other solution proposed in the linked page,
like:
// vue.config.js
module.exports = {
chainWebpack: config => {
config.plugin('define').tap( ([options = {}]) => {
return [{
...options, // these are the env variables from your .env file, if any arr defined
VERSION: JSON.stringify(require('./package.json').version)
}]
})
}
}
But this fail silently too.
Use the config.plugin('define') syntax suggested by #Oluwafemi,
like:
chainWebpack: (config) => {
return config.plugin('define').tap(
args => merge(args, [VERSION])
)
},
Where VERSION is a local variable defined as:
const pkgVersion = require('./package.json').version;
const VERSION = {
'process.env': {
VUE_APP_VERSION: JSON.stringify(pkgVersion)
}
}
But this is not working either.
I am re-starting the whole project everytime, so that's not the reason why the process stuff does not show up.
My vue-cli version is 3.0.1.
I am adding my 2 cents, as I found a shorter way and apparently the right way (https://docs.npmjs.com/misc/scripts#packagejson-vars)
Add this in your vue.config.file before the export, not inside:
process.env.VUE_APP_VERSION = process.env.npm_package_version
And voilà!
You can then use it from a component with process.env.VUE_APP_VERSION
TLDR
The following snippet in the vue.config.js file will do the trick, and will allow you to access the version of your app as APPLICATION_VERSION:
module.exports = {
configureWebpack: config => {
return {
plugins: [
new webpack.DefinePlugin({
'APPLICATION_VERSION': JSON.stringify(require('./package.json').version),
})
]
}
},
}
TIP:
Don't even try to add some key to process.env via webpack.definePlugin: it won't work as you probably expect.
Why my previous efforts did not work
At the end, I solved the issue via webpack.DefinePlugin. The main issue I had is that the original solution I found was using definePlugin to write to a process.env.PACKAGE_JSON variable.
This suggests that definePlugin somehow allows to add variables to process or process.env, which is not the case. Whenever I did log process.env in the console, I didn't find the variables I was trying to push into process.env : so I though the definePlugin tech was not working.
Actually, what webpack.definePlugin does is to check for strings at compile time and change them to its value right on your code. So, if you define an ACME_VERSION variable via:
module.exports = {
lintOnSave: true,
configureWebpack: config => {
return {
plugins: [
new webpack.DefinePlugin({
'ACME_VERSION': 111,
})
]
}
},
}
and then, in main.js you print console.log(ACME_VERSION), you will get 111 properly logged.
Now, however, this is just a string change at compile time. If instead of ACME_VERSION you try to define process.env.VUE_APP_ACME_VERSION...
when you log process.env the VUE_APP_ACME_VERSION key won't show up in the object. However, a raw console.log('process.env.VUE_APP_ACME_VERSION') will yield 111 as expected.
So, basically, original link and the proposed solutions were correct to some degree. However, nothing was really being added to the process object. I was logging proccess.env during my initial tries, so I didn't see anything working.
Now, however, since the process object is not being modified, I strongly suggest anyone trying to load variables to their vue app at compile time not to use it. Is misleading at best.
You can simply import your package.json file and use its variables.
import { version } from "../../package.json";
console.log(version)
If you are using Webpack, you can inject the variable in the following way:
// webpack.config.js
plugins: [
new webpack.DefinePlugin({
VERSION: JSON.stringify(require("package.json").version)
})
]
// any-module.js
console.log("Version: " + VERSION);
https://github.com/webpack/webpack/issues/237
When building the Vue app, environment variables that don't begin with the VUE_APP_ prefix are filtered out. NODE_ENV and BASE_URL environment variables are the exception.
The above information applies when the environment variables are set prior to building the Vue app and not in this situation.
In a situation where environment variables are set during the build, it's important to look at what Vue CLI is doing.
The Vue CLI uses webpack.DefinePlugin to set environment variables using the object returned from the call to resolveClientEnv.
resolveClientEnv returns
{
'process.env': {}
}
This means when configuring your environment variables at build time, you need to come upon a way to merge with the existing one.
You need to perform a deep merge of both arrays, so that value for process.env key is an object containing keys from the resolved client environment and your keys.
chainWebpack key in the default export for vue.config.js is just about one of the ways to get this done.
The arguments passed to initialize the DefinePlugin can be merged with new environment variables that you like to configure using the underlying webpack-chain API. Here is an example:
// vue.config.js
const merge = require('deepmerge');
const pkgVersion = require('./package.json').version;
const VERSION = {
'process.env': {
VERSION: JSON.stringify(pkgVersion)
}
}
module.exports = {
chainWebpack: config =>
config
.plugin('define')
.tap(
args => merge(args, [VERSION])
)
}
Your initial attempt was fine, you were just missing the JSON.stringify part:
const webpack = require('webpack');
module.exports = {
configureWebpack: config => {
return {
plugins: [
new webpack.DefinePlugin({
'process.env': {
VERSION: JSON.stringify(require('./package.json').version),
}
})
]
}
},
}
Edit: although the webpack docs recommend the 'process.env.VERSION' way (yellow panel):
new webpack.DefinePlugin({
'process.env.VERSION': JSON.stringify(require('./package.json').version),
}),
Official solutions tend to be more reliable Modes and Environment Variables | Vue CLI
TIP
You can have computed env vars in your vue.config.js file. They still need to be prefixed with VUE_APP_. This is useful for version info
process.env.VUE_APP_VERSION = require('./package.json').version
module.exports = {
// config
}
I attempted the accepted answer, and had errors. However, in the vue docs, I was able to find an answer similar (but not quite) that of #antoni's answer.
In short, just have the following in vue.config.js:
process.env.VUE_APP_VERSION = require('./package.json').version
module.exports = {
// config
}
Docs 2020-10-27:
You can access env variables in your application code:
process.env.VUE_APP_NOT_SECRET_CODE = require('./package.json').version
During build, process.env.VUE_APP_NOT_SECRET_CODE will be replaced by the corresponding value. In the case of VUE_APP_NOT_SECRET_CODE=some_value, it will be replaced by "some_value".
In addition to VUE_APP_* variables, there are also two special variables that will always be available in your app code:
NODE_ENV - this will be one of "development", "production" or "test" depending on the mode the app is running in.
BASE_URL - this corresponds to the publicPath option in vue.config.js and is the base path your app is deployed at.
The answer for this on the official VueJS forum is like so:
chainWebpack: config => {
config
.plugin('define')
.tap(args => {
let v = JSON.stringify(require('./package.json').version)
args[0]['process.env']['VERSION'] = v
return args
})
}
Description
Add this line to your vue.config.js file
module.exports = {
...
chainWebpack: config => {
config
.plugin('define')
.tap(args => {
let v = JSON.stringify(require('./package.json').version)
args[0]['process.env']['VERSION'] = v
return args
})
}
};
Then you can use this in your vue files like so:
version: function () {
return process.env.VERSION
}
A one liner alternative:
//script tag
let packageJsonInfo = require("../../package.json");
//Then you can for example, get the version no
packageJsonInfo.version