NodeJS dynamically environment variable setup - javascript

I create a NodeJS server and trying to setup environment variables dynamically. But I'm facing a weird problem. I create a env.js file and here is the related code:
const environment = {}
environment.dev = {
port: 3000,
envName: 'dev'
}
environment.prod = {
port: 5000,
envName: 'prod'
}
const currentEnvironment = typeof process.env.NODE_ENV === 'string'
? process.env.NODE_ENV
: 'dev'
console.log('current environment: ', currentEnvironment) // get currentEnvironment: prod
console.log('environment obj: ', environment) // get environment obj correctly
console.log('getting obj from environment obj: ', environment[currentEnvironment]) // But get undefined
const environmentToExport = typeof environment[currentEnvironment] === 'object'
? environment[currentEnvironment]
: environment.dev
module.exports = environmentToExport
I can't figure out why I'm getting undefined in environment[currentEnvironment].
And here is the package.json scripts from where I'm passing environment variable. I'm using windows by the way.
"scripts": {
"dev": "SET NODE_ENV=dev & nodemon index",
"prod": "SET NODE_ENV=prod & nodemon index"
}
Note: I'm using exported port number while creating server. But incase of getting undefined, I'm always exporting dev environment ! Hope you understand my problem.

Related

How to get the -p argument value in Next.js?

If my Nexs.js app is started with
yarn dev
Where package.json defines it as
{
"scripts": {
"dev": "next dev -p 4000"
}
}
How I get this 4000 value from the -p switch?
Because process.env.PORT is not set this way.
const getBaseUrl = () => {
if (typeof window !== 'undefined') return ''; // browser use relative path
// How to replace the ???? with the value of -p, defaulting to 3000 if not set
return 'http://localhost:????'; // dev SSR should use localhost
}

No metadata for "entity" was found when seeding

I'm building a seeding system using Faker over TypeORM throwing the following error on seeding:
🌱 TypeORM Seeding v1.6.1
âś” ORM Config loaded
âś” Factories are imported
âś” Seeders are imported
âś” Database connected
â ą Executing CreateUsers Seeder
❌ Could not save entity
EntityMetadataNotFound: No metadata for "UsersEntity" was found.
âś– Could not run the seed CreateUsers!
Error: Could not save entity
error Command failed with exit code 1.
I'm using the CLI of the typeorm-seeding npm package in my package.json
"seed": "yarn migration:up && cross-env CLI=true ts-node -r tsconfig-paths/register ./node_modules/typeorm-seeding/dist/cli.js ---root src/core/config -n database-configuration.ts seed",
I have my user.factory.ts using the users.entity.ts
define(UsersEntity, async (faker: typeof Faker) => {
const user = new UsersEntity();
user.firstName = faker.name.firstName();
user.lastName = faker.name.lastName();
user.email = faker.internet.email().toLowerCase();
user.phone = faker.phone.phoneNumber();
user.imageUrl = faker.image.people();
user.password = await CryptoUtils.getHash('password');
user.role = Role.User;
return user;
});
And the user.seeder.ts to run the seeding
export class CreateUsers implements Seeder {
public async run(factory: Factory): Promise<any> {
await factory(UsersEntity)().createMany(10);
}
}
Finally, here is my database configuration used in the CLI to run the seeding
return {
type: 'postgres',
host: process.env.POSTGRES_HOST,
port: +process.env.POSTGRES_PORT,
username: process.env.POSTGRES_USER,
password: process.env.POSTGRES_PASSWORD,
database: process.env.POSTGRES_DB,
entities:
process.env.NODE_ENV === 'test'
? ['src/**/*.entity.ts']
: ['dist/**/*.entity{.ts,.js}'],
synchronize: false,
keepConnectionAlive: true,
migrationsRun: true,
logging: process.env.DATABASE_SHOW_SQL === 'true' || false,
migrations:
process.env.NODE_ENV === 'test'
? ['src/core/database/migrations/**/*.ts']
: ['dist/core/database/migrations/**/*.js'],
seeds: ['src/core/database/seed/seeder/**/*{.ts,.js}'],
factories: ['src/core/database/seed/factory/**/*{.ts,.js}'],
cli: {
migrationsDir: 'src/core/database/migrations',
},
};
I solved this by adding the NODE_ENV check on my factories and seeds files to avoid getting files in dist and src.
The problem was that I am working in development environment. The entities were found in the dist directory instead of factories and seeds who were found in the src instead of the dist folder.
The solution was to apply the process.env.NODE_ENV check on the factories and seeds too:
seeds:
process.env.NODE_ENV === 'test'
? ['src/core/database/seed/seeder/**/*.ts']
: ['dist/core/database/seed/seeder/**/*.js'],
factories:
process.env.NODE_ENV === 'test'
? ['src/core/database/seed/factory/**/*.ts']
: ['dist/core/database/seed/factory/**/*.js'],

How to change variable value in index.html based on the environment in angular

How can i change config.apiKey value based on the angular environments like Development & Production.
For Production config.appKey = 'AB-AAB-AAB-MPR';
For Development config.appKey = 'AC-DDR-SST-DKR';
Please find the code for reference.
`<script charset='UTF-8'>
window['adrum-start-time'] = new Date().getTime();
(function(config){
config.appKey = 'AC-DDR-SST-DKR';
})(window['adrum-config'] || (window['adrum-config'] = {}));
</script>
`
Thanks
Reading environment file in index.html will be difficult. I am not saying it is not possible there may be a workaround for that. But I recommend you to do this in app.component.ts file on
ngOnInit() {
this.loadScript();
}
private loadScript() {
const script = document.createElement('script');
script.type = 'text/javascript';
script.innerHTML = 'window["adrum-start-time"] = new Date().getTime(); (function(config){ config.appKey = ' + environment.key + '; })(window["adrum-config"] || (window["adrum-config"] = {}));';
const head = document.getElementsByTagName('head')[0];
if (head !== null && head !== undefined) {
document.head.appendChild(script);
}
}
Hopefully, this will solve the problem
You can use your angular.json to replace your index.html file.
just create a copy of the index.html and name it to index.env.html
and then in your angular.json you can use fileReplacements in your specific env like the following
"fileReplacements": [
{
"replace": "src/index.html",
"with": "src/index.env.html"
}
]
You can simply use isDevMode()
or else use this way
└──myProject/src/environments/
└──environment.ts
└──environment.prod.ts
└──environment.stage.ts
export const environment = {
production: false,
apiUrl: 'http://my-api-url'
};
export const environment = {
production: true,
apiUrl: 'http://my-prod-url'
};
Read more on angular guide
you can add those key in environment.ts and environment.prod.ts file so you need to write the development api key in environment.ts and production key in environment.prod.ts so if you are creating a build by using a this command ng build --prod it will take the api key from environment.prod.ts file. here is the example
environment.ts
export const environment = {
production: false,
appKey: 'AB-AAB-AAB-MPR';
};
environment.prod.ts
export const environment = {
production: true,
appKey: 'AC-DDR-SST-DKR';
};
service
// here we are importing our environment like this
import { environment } from '../../environments/environment';
getData() {
console.log(environment.apiKey);
// here you will get the apiKey based on your environment if it is dev environment then it take the "apiKey" from environment.ts and if it is production env then it will take the "apiKey" from the environment.prod.ts
// api call or other business logic
}
You can find solution here: How to use environment variable in index.html for Angular 6
TL,DR: use files for each enviroment and config it in angular.json
I created different folder for prod, staging etc environment and instead of using variable, I placed three different index.html as per the environment, I answered the same here https://stackoverflow.com/a/67091452/1843984
you can simply either use env files to manage your different environments or else you can also use this i have use in my react app as below
in your package.json use
"start": "react-scripts start",
"start:staging": "REACT_APP_BUILD_TYPE=staging npm start",
"start:prod": "REACT_APP_BUILD_TYPE=production npm start",
"build": "REACT_APP_BUILD_TYPE=production react-scripts build",
"build:staging": "REACT_APP_BUILD_TYPE=staging react-scripts build",
},
and the file you have written above can be use as
"REACT_APP_BUILD_TYPE=staging ? config.appKey = 'AB-AAB-AAB-MPR' : config.appKey = 'AC-DDR-SST-DKR';
export const environment = {
production: true,
apiUrl: 'http://my-api-url',
appKey: 'AC-DDR-SST-DKR'
};
check the angular.json file for fileReplacements config
here it is: stackblitz

Webpack run plug-in scripts on watch

I have webpack set up with a plug-in handling application files & css.
webpack.config.js
const path = require('path');
const glob = require('glob');
const uglify = require("uglify-js");
const cleanCSS = require("clean-css");
const merge = require('webpack-merge-and-include-globally');
const mode = 'dev';
const ext = mode === 'prod' ? '.min' : '';
module.exports = (event, arg) => {
let config = {
mode: mode === 'dev' ? 'development' : 'prod' ? 'production' : '',
entry: {
bundle : [ "./build/index.js" ]
},
output: {
path: __dirname + '/public',
filename: "js/[name].js"
},
plugins: [
new merge({
files: {
// concatenate angular app
'./app/app.js' : [
'./build/app/js/app.js',
'./build/app/js/controllers/*',
'./build/app/js/directives/*',
'./build/app/js/services/*',
],
// compile scripts & css
'./js/scripts.js' : [ './build/js/scripts.js' ],
'./css/style.css' : [ './build/css/*' ]
},
transform: { // minify in prod mode
'./app/app.js' : code => mode === 'prod' ? uglify.minify(code).code : code,
'./js/scripts.js' : code => mode === 'prod' ? uglify.minify(code).code : code,
'./css/style.css' : code => mode === 'prod' ? new cleanCSS({}).minify(code).styles : code
}
})
]
}
return config;
}
When I run npm run build the script works as expected building a bundle.js with my dependencies, an app.js with my application, and a style.css with my css.
However when I run npm run watch webpack only watches the entry files for bundle.js - index.js.
Is it possible to indicate that webpack watch entry files for the plugins as well? Or can I indicate that the build script is triggered on the changing of some arbitrary files?
I was able to find a solution using the webpack-watch-files plugin
const WatchExternalFilesPlugin = require('webpack-watch-files-plugin').default;
new WatchExternalFilesPlugin({
files: [
'./build/app/js/**/*.js',
'./build/js/*.js',
'./build/css/*.css',
// '!./src/*.test.js'
]
})
** Note: .default in the require statement is needed with Webpack 4

node require module passing arg with square brackets? is this a mistake?

I saw the following nodeJS code on a git hub repo:
var env = process.env.NODE_ENV || 'development'
, config = require('./config/config')[env]
, auth = require('./config/middlewares/authorization')
, mongoose = require('mongoose');
I've never seen the square brackets before [env] is this a mistake?
I thought args could only be passed in normal brackets ( ). I could not find documentation anywhere about this.
repo in question is here https://github.com/diki/nodejs-passport-boilerplate and its on line 17 of server.js.
Looking at their config.js example, that file exports an object with each environment as keys:
module.exports = {
development: {
db: 'mongodb://localhost/noobjs_dev',
root: rootPath,
// ...
},
test: {
db: 'mongodb://localhost/noobjs_test',
root: rootPath,
// ...
},
production: {}
}
The square brackets will select only the configs related to the environment defined in your NODE_ENV variable.
Assuming NODE_ENV holds the value development, this would be the same as doing this:
var config = require('./config/config').development;
Which is the same as this:
var config = require('./config/config')['development'];
The advantage of square brackets it that they allow you to select the key on the object dynamically.

Categories