Using dotenv in a Node JS module - javascript

I am building a Node app that returns results for a search using a Google Custom Search Engine(CSE).
I am going to separate the part of the app that sends the request to Google and returns the results into a module.
I use dotenv already in the app to store MongoDB credentials and the app's URL.
I also want to use dotenv in the module to store the Google CSE ID and the API key for the CSE.
I want my module to work independently of the main app but also to use the main app's dotenv file when it's a module.
Currently my module structure looks like this:
module
|
+-- node_modules
| |
| \-- dotenv
| |
| \-- (dotenv module's files....)
|
+-- .env
|
\-- index.js
This works perfectly on its own. The .env file stores the required environment variables and I can access them in the index.js file by requiring the dotenv module.
When included in the main app the structure looks like this:
app
|
+-- node_modules
| |
| +-- dotenv
| | |
| | \-- (dotenv module's files....)
| |
| \-- my_google_search_module
| |
| +-- node_modules
| | |
| | +-- dotenv
| | |
| | \-- (dotenv module's files...)
| |
| \-- index.js
|
+-- .env
|
\-- index.js
This also works. I store all the environment variables in the main app's .env file and by requiring dotenv in the app's index.js I can access those variables. Plus, the "my_google_search_module" seems to be pulling its required variables from the .env file in the root of the app. There is no .env file in the module.
My question is am I doing this the right way?

I have researched this further and can confirm that the module's .env is pulling the required environment variables from the app's .env file.
I believe this section from the dotenv readme, though not exactly related, verifies that -
https://www.npmjs.com/package/dotenv#what-happens-to-environment-variables-that-were-already-set
We will never modify any environment variables that have already been
set. In particular, if there is a variable in your .env file which
collides with one that already exists in your environment, then that
variable will be skipped. This behavior allows you to override all
.env configurations with a machine-specific environment, although it
is not recommended.

Yes, you are doing in a right way. There must be a single .env file in a whole project. But there is a trick to include it in the different directory structure.
For example:
Your index.js file is in /app/src, your .env file is in /app. Your index.js file has this
dotenv.config({path: "../.env"});
You could also use dotenv.config({path: path.join(__dirname, "../.env")});

for node projects, i would suggest to use npm package dotenv. You can find details on how to use it. do not forget to include require('dotenv').config() at the start of your project file, say index.js.
Now you can use .env contents anywhere you need. For example i want my server port to be 4000 which i define in .env as PORT=4000. Now, to use .env variables anywhere, simply provide variable name in suffix such as process.env.PORT. That is it. Though i am late on this post, hope this could be of any help.

Related

How can i access evironment variables in present NodeJS from ReactJS

I want to use my .env variable presend in my nodejs root folder in reactjs. I tried using process.env.TEST but i always get undefined. any solutions?
My folder structure.
Project root
|-client
| |- //react project files
| |-app.js
|
|- //nodejs project files
|-.env
|-server.js
I want to access my .env variables in app.js and its components
You can use find-up to get your variables in your whole monorepo.
Find here a bright article on the usage.

How to initialize a mono repo and create-react-app inside monorepo?

I want to initialize a monorepo, and then initialize apps inside the packages folder. I found a bunch of examples of how to do this. But, what I want to achieve is, I want to keep all the node_modules at the root level.
--monorepo
|--node_modules
|--packages
| |--create-react-app-1
| | |--src
| | |--{...rest}
| |--create-react-app-2
| | |--src
| | |--{...rest}
|--package.json
So, all the node_modules are at the root level and all the packages are using them from the root level. All the dependencies and dev-dependencies are listed in the root level package.json.
I want to use yarn as the package manager as well.
How I can achieve this?

angular2 spring-boot project structure

I have a new angular2 project that was built using the standard file structure described in the quickstart. I am attempting to build an API gateway and have spring-boot host my application, however I haven't been able to configure boot to use the /dist directory in my project where the generated sources are created. The project structure is as follows:
project
|--dist
|--node_modules
|--src
| |--app
| |--assets
| |--main
| | |--java
| | |--resources
| | | |--config
| | |--webapp
| | | |--WEB-INF
I would like to use the default /dist directory so that I can still use npm/webpack for continuous development on the UI.
I tried configuring the static resources directory like so:
spring.resources.staticLocations: /dist
But this doesn't seem to be working.
I created a resource handler to point directly to the dist directory:
#Configuration
public class WebMvcConfiguration extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
String currentPath = new File("./").getAbsolutePath();
currentPath = "file:///" + currentPath;
registry.addResourceHandler("/**").addResourceLocations(currentPath + "/dist/");
}
}
This solves part of the problem but now my root URL ('/') no longer maps to index.html.
Is there an easier/better way to configure spring-boot to find the /dist project directory? Should my project structure change? I would really like to get all of these pieces working together cleanly.
Spring Boot will automatically add static web resources
located within any of the following directories:
/META-INF/resources/
/resources/
/static/
/public/
The folders are relative to src/main/resources
If you put index.html like below, then spring can serve your file
without any configuration.
src/main/resources/META-INF/resources/index.html
src/main/resources/resources/index.html
src/main/resources/static/index.html
src/main/resources/public/index.html
I took #chrylis advice and pointed the destination directory for the webpack build to build/dist (using Gradle).
I avoided putting the generated sources in /resources/** because eventually this will get built into a .war and deployed to an enterprise application server -- I didn't want a lot of include/exclude logic in my build to support this. Plus the build directory seemed a more logical place for the generated .js source.
My project structure now looks like this:
project
|--build
| |--dist
| |--...
|--node_modules
|--src
| |--app
| |--assets
| |--main
| | |--java
| | |--resources
| | | |--config
| | |--webapp
| | | |--WEB-INF
I eliminated the WebMvcConfigurerAdapter and configured the static resources to point to my dist directory in build:
spring.resources.static-locations: "file:./build/dist/"
I'm now able to run Webpack, Spring-Boot or deploy to my application server with the same source and very little configuration overhead.

Importing bower component library into Angular 2 application

I am working on an Angular 2 application in ASP.NET Core and I am trying to import oidc-client (https://github.com/IdentityModel/oidc-client-js) into one of my Typescript files. The oidc-client files were installed via bower which placed them in the expected bower_components folder. The oidc-client.js file is copied to the lib folder under wwwroot via a gulp task on build.
My directory structure looks like this (only relevent portions represented):
wwwroot
|
--app
| |
| --shared
| |
| --auth
| |
| --token.service.ts
--lib
| |
| --oidc-client
| |
| --oidc-client.js
|
--bower_components
| |
| --oidc-client
| |
| --dist
| | |
| | --oidc-client.js
| --oidc-client.d.ts
|
--typings
|
--index.d.ts
I need to use the oidc-client library in my token.service.ts file so I am doing this:
import { Oidc } from './lib/oidc-client/oidc-client';
But this results in an error 'Cannot find module './lib/oidc-client/oidc-client'.
I've tried different variations on the path, relative and non-relative, and I can't seem to figure out how to import the oid-client library.
Maybe its the typings not working? Do I need to do anything special with the d.ts file to make it work?
Thanks for any guidance.
As mentioned in a comment made above, using the NPM distribution of oidc-client would be the preferred option.
However, the typings that are included in the oidc-client are a little strange. Usually, the typings .d.ts file sits side-by-side with the .js file. With oidc-client, they are in different directories and that's what's causing problems with your import statement.
If you install the NPM module and add node_modules/oidc-client/oidc-client.d.ts to the files configuration of your tsconfig.json:
{
"files": [
"index.ts",
"node_modules/oidc-client/oidc-client.d.ts"
]
}
You should be able to create an index.ts file that imports oidc-client:
import { OidcClient } from "oidc-client";
If the .d.ts file and the .js file had been side-by-side, your import would have worked, but they are not, so it doesn't.
If you do not want to use the NPM distribution, it is likely that the separation of the .d.ts and .js files is what's causing the problem with the Bower distribution, too.

Cannot find module - relative paths

I wrote a very simple local module to manage a few lines of localized text.
It uses node's require to load the language files, but I'm having trouble with paths, most likely.
I'm getting the Cannot find module error.
File structure
.
+-- local_modules
| +-- lang
| | +-- package.json
| | +-- index.js
+-- locale
| +-- en.js
| +-- de.coffee
+-- init.js
+-- index.coffee
+-- package.json
Relevant module code
Should require the file if it is not already loaded.
join = require('path').join;
_config.path = './locale';
lang = 'en';
_locales = {};
if(!_locales[lang]){
_locales[lang] = require(join(_config.path, lang));
}
Every file in the locale directory is a typical Node.js module, for example en.js:
module.exports = {
test: 'Hello World!'
};
The local module exports a function(req, res, next){}, which is used as Express middleware and is supposed
to attach the required object with localized strings onto res.locals, however, I'm seeing Cannot find module 'locale/en' error.
I've tried to manually add the .js extensions (but that shouldn't be neccessary as far as I know).
I have also tried different variations on the path, such as locale or /locale.
The module is called in index.coffee.
App is launched using init.js, which contains the following:
require('coffee-script/register');
require('./index');
Maybe it's just that the module is a .js (and the module itself doesn't have CoffeeScript as a dependency) so it can not load a .coffee file? Although CoffeeScript should be registered globally, or am I wrong? Either way, it doesn't work with the .js file either, so I guess it has something to do with paths.
path.join() also normalizes the created path, which (probably) means the ./ part was always removed, and what remained was a relative path.
Instead, when path.resolve() is used, it creates an absolute path, which is what is needed in this case.

Categories

Resources