How export a module in node.js - javascript

emailConfirmation.js:
var configAuth = require('../../authentication/sendgrid');
var sendgrid = require('sendgrid')(configAuth.sg.username, configAuth.sg.password);
var from_address = "mycompany#pubcrawlsp.com";
var text_body = "sometextbody";
var html_body = "somehtml";
Them i need export in my routes, to use in a post route, like this:
app.post('/', function(req, res) {
sendgrid.send({
to: req.body.email,
from: the from_adrres variable from the other file,
subject: "Some subjec",
text: the text_body variable from the other file
html: the html_body variable from the other file
}, function(err, json) {
if (err) {
return console.error(err);
}
console.log(json);
});
});
How can i export the emailConfirmation.js and use like that??

Start by creating a file just for your code.
At the end of the file, you would "expose" parts of the code to a consumer. For example:
In your case you could wrap your code like so:
module.exports.set = function(app) {
app.post('/', function(req, res) {
/* the post code goes here */
});
};
You could consume it with app.js like so on app.js:
require('./sendgrid').set(app);
This would effectively set your route(s) for sendgrid.

Related

Access express response data client side

In my express router I check if the data inserted on a form are valid then if they are I render another page passing form data. I would like to access the data I pass client-side. On the chat.ejs view I have a chatroom.js client file, I want to access the data there without having to access them in a script tag.
I thought about using Ajax but the only answer I found here on StackOverflow was marked as wrong, so how do I go about that?
router.js
module.exports=function(app) {
const express = require('express');
const router = express.Router();
const {check, validationResult} = require('express-validator');
const {matchedData} = require('express-validator/filter');
router.get('/', (req, res) => {
res.render('index', {
data: {},
errors: {}
})
});
router.post('/enter', [
check('username')
.isLength({min: 1})
.withMessage('Username is required').trim(),
check('room')//implement personalized check
], (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.render('index', {
data: req.body,
errors: errors.mapped()
})
}
else {
const data = matchedData(req);
return res.render('chat',{
user: data.username,
room:data.room
})
}
});
return router;
//MOVE TO SUPPORT
function find(name) {
return 1;
}
}
there is really nothing client-side so far so It seems useless just posting my views. Alternatively, I could use Ajax on client.ejs to handle the form submission but I would like to keep this clean and handle the routing with the router file.
I ended up creating two global variables in a script tag for my index.ejs page like this
<script>
var user = <%- JSON.stringify( user ) %>
var room = <%- JSON.stringify(room)%>;
</script>
and then I could access them in the chatroom.js file linked below

Pass variable to html template in nodemailer

I want to send email with nodemailer using html template. In that template I need to inject some dynamically some variables and I really can't do that. My code:
var nodemailer = require('nodemailer');
var smtpTransport = require('nodemailer-smtp-transport');
smtpTransport = nodemailer.createTransport(smtpTransport({
host: mailConfig.host,
secure: mailConfig.secure,
port: mailConfig.port,
auth: {
user: mailConfig.auth.user,
pass: mailConfig.auth.pass
}
}));
var mailOptions = {
from: 'my#email.com',
to : 'some#email.com',
subject : 'test subject',
html : { path: 'app/public/pages/emailWithPDF.html' }
};
smtpTransport.sendMail(mailOptions, function (error, response) {
if (error) {
console.log(error);
callback(error);
}
});
Let's say I want in emailWithPDF.html something like this:
Hello {{username}}!
I've found some examples, where was smth like this:
...
html: '<p>Hello {{username}}</p>'
...
but I want it in separate html file. Is it possible?
What you can do is read the HTML file using fs module in node and then replace the elements that you want changed in the html string using handlebars
var nodemailer = require('nodemailer');
var smtpTransport = require('nodemailer-smtp-transport');
var handlebars = require('handlebars');
var fs = require('fs');
var readHTMLFile = function(path, callback) {
fs.readFile(path, {encoding: 'utf-8'}, function (err, html) {
if (err) {
callback(err);
}
else {
callback(null, html);
}
});
};
smtpTransport = nodemailer.createTransport(smtpTransport({
host: mailConfig.host,
secure: mailConfig.secure,
port: mailConfig.port,
auth: {
user: mailConfig.auth.user,
pass: mailConfig.auth.pass
}
}));
readHTMLFile(__dirname + 'app/public/pages/emailWithPDF.html', function(err, html) {
if (err) {
console.log('error reading file', err);
return;
}
var template = handlebars.compile(html);
var replacements = {
username: "John Doe"
};
var htmlToSend = template(replacements);
var mailOptions = {
from: 'my#email.com',
to : 'some#email.com',
subject : 'test subject',
html : htmlToSend
};
smtpTransport.sendMail(mailOptions, function (error, response) {
if (error) {
console.log(error);
}
});
});
I use it in all my projects. more clean and up to date and understandable. callback hell doesn't exist.
sendMail.ts The html file reads with handlebar, puts the relevant variables into the contents, and sends.
import * as nodemailer from 'nodemailer';
import * as handlebars from 'handlebars';
import * as fs from 'fs';
import * as path from 'path';
export async function sendEmail(email: string, subject: string, url: string) {
const __dirname = path.resolve();
const filePath = path.join(__dirname, '../emails/password-reset.html');
const source = fs.readFileSync(filePath, 'utf-8').toString();
const template = handlebars.compile(source);
const replacements = {
username: "Umut YEREBAKMAZ"
};
const htmlToSend = template(replacements);
const transporter = nodemailer.createTransport({
host: "smtp.mailtrap.io",
port: 2525, // 587
secure: false,
auth: {
user: "fg7f6g7g67",
pass: "asds7ds7d6"
}
});
const mailOptions = {
from: '"noreply#yourdomain.com" <noreply#yourdomain.com>',
to: email,
subject: subject,
text: url,
html: htmlToSend
};
const info = await transporter.sendMail(mailOptions);
console.log("Message sent: %s", info.messageId);
console.log("Preview URL: %s", "https://mailtrap.io/inboxes/test/messages/");
}
String replace isn't a good idea because you'll have to restore old strings or create a backup file to be able to change them another time, also it won't be asynchrone and it will cause a problem in every way!
you can do it much easier and more cleaner:
just go to your mail options and add context with your variables:
var mailOptions = {
from: 'nginx-iwnl#gmail.com',
to: 'username#gmail.com',
subject: 'Sending email',
template: 'yourTemplate',
context: { // <=
username: username,
whatever: variable
}
};
next thing to do is openning your html file and call your variables like:
{{username}}
If you're using Nodemailer 2.0.0 or higher, check this documentation:
https://community.nodemailer.com/2-0-0-beta/templating/ There they explain how to make use of external rendering with templates like that:
// external renderer
var EmailTemplate = require('email-templates').EmailTemplate;
var send = transporter.templateSender(new EmailTemplate('template/directory'));
They also give this example:
// create template based sender function
// assumes text.{ext} and html.{ext} in template/directory
var sendPwdReminder = transporter.templateSender(new EmailTemplate('template/directory'), {
from: 'sender#example.com',
});
where you see how to pass variables.
You will need the email-templates module: https://github.com/crocodilejs/node-email-templates and a template engine of your choice.
Also in the documentation of email-templates you'll find how to make your file structure in order that your templates can be found:
html.{{ext}} (required) - for html format of email
text.{{ext}} (optional) - for text format of email style.
{{ext}}(optional) - styles for html format subject.
{{ext}}(optional) - for subject of email
See supported template engines for possible template engine extensions (e.g. .ejs, .jade, .nunjucks) to use for the value of {{ext}} above.
You may prefix any file name with anything you like to help you identify the files more easily in your IDE. The only requirement is that the filename contains html., text., style., and subject. respectively.
Create one file emailTemplates.js there yo can store each template as a function
emailTemplates.js
const newsLetterEmail = (clientName) => `<p>Hi ${clientName}, here you have today news.</p>`
const welcomeEmail = (clientName, username) => `<p>Welcome ${clientName}, your username is ${username}.</p>`
export {newsLetterEmail, welcomeEmail}
Then in the controllers call any templateFunction and store in output varaible
controller.js
import {welcomeEmail} from './emailTeamplates.js'
const registerUser = async(req, res) => {
const {name, usename, email} = req.body
// User register code....
const output = welcomeEmail(name, username)
let mailOptions = {
from: '"Welcome" <welcome#welcome.com>',
to: 'client#gmail.com',
subject: 'Welcome email!',
text: 'Hello World',
html: output,
}
For those using pug as templating engine
Just a quick way to render a template in a separate file using pug's render function:
// function to send an e-mail. Assumes you've got nodemailer and pug templating engine installed.
// transporter object relates to nodemailer, see nodemailer docs for details
const nodemailer = require('nodemailer');
const pug = require('pug');
function send_some_mail(iterable){
var message = {
from: 'from#example.com',
to: 'to#example.com',
subject: 'Message title',
html: pug.renderFile(__dirname + 'path_to_template.pug', {iterable: iterable})
};
transporter.sendMail(message, function(err, info){...})
}
// template.pug
each item in iterable
li
p #{item.name}
See https://pugjs.org/api/getting-started.html for further details. Note that this will cause template re-compilation every time a message is sent. That is fine for occasional e-mail deliveries. If you send tons of e-mails, you can cache the compiled template to work around that. Check out pug docs for that set up if you need it.
You can use a Web Request to build an html template using handlebars or any other engine.
Create a template
First you must create an html template for the email body. In this example I used a handlebars hbs file.
Do your design stuff with html and add the variables that you will need in the message:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Welcome Email Template</title>
</head>
<body>
<p style="font-size: 14px; font-weight: normal;">Hi {{data.name}}</p>
</body>
</html>
Create a template request
You must create the access to this view. Then a request is created where we can send the template name as an url parameter to make the request parameterizable for other templates.
const web = express.Router()
web.post('/template/email/:template', function(req, res) {
res.render(`templates/email/${req.params.template}`, {
data: req.body
})
})
Mail function
Finally you can send the email after making the request to the template. You can use a function like the following:
const nodemailer = require('nodemailer')
const request = require("request")
function sendEmail(toEmail, subject, templateFile) {
var options = {
uri: `http://localhost:3000/template/email/${templateFile}`,
method: 'POST',
json: { name: "Jon Snow" } // All the information that needs to be sent
};
request(options, function (error, response, body) {
if (error) console.log(error)
var transporter = nodemailer.createTransport({
host: mailConfig.host,
port: mailConfig.port,
secure: true,
auth: {
user: mailConfig.account,
pass: mailConfig.password
}
})
var mailOptions = {
from: mailConfig.account,
to: toEmail,
subject: subject,
html: body
}
transporter.sendMail(mailOptions, function(error, info) {
if (error) console.log(error)
})
})
}
This can be done without templates.
Try changing it to this:
`Hello ${username}!`
Make sure that these are not inverted commas but back ticks.
There is one easy way to insert variable inside html in nodemailer.
html:"<p>Your message "+variable1+".Message continueous "+variable 2+"</p>"
You can also use async/await syntax or promises and avoid using callbacks, like I did here, using async/await:
const fs = require("fs").promises;
const path = require("path");
const handlebars = require("handlebars");
const relativeTemplatePath = "../../html/reset-pw-email-template.html";
function sendEmail(){
const templatePath = path.join(__dirname, relativeTemplatePath);
const templateFile = await fs.readFile(templatePath, 'utf-8');
const template = handlebars.compile(templateFile);
const replacements = {
username:""
};
const finalHtml = template(replacements);
const mailOptions = {
from: "",
to: "",
subject: "",
html: finalHtml,
};
}

GET in a Route - Nodejs

what´s the best way if I want to make a GET request in a route?
api.js
api.route('/guests')
.get(function(req, res) {
Guest.find(function(err, guests) {
if (err)
res.send(err);
res.json(guests);
});
});
routes.js
app.get('/export', requiresLogin, function(req, res) {
/* make a GET request to my api (eg.: 'api/guests') */
/* and save the 'guests' to a variable */
});
First Solution
Instead of calling internal apis, you can define a controller guestCtrl.js and call the function from guestCtrl.js in api.js and routes.js
guestCtrl.js
module.exports = {
getGuests : function(){
Guest.find(function(err, guests) {
if (err)
//handle error
return [];
else
return guests;
});
}
}
api.js
//path of guests.js
var guestCtrl = require('guestCtrl.js');
api.route('/guests').get(function(req, res) {
return guestCtrl.getGuests();
});
routes.js
var guestCtrl = require('guestCtrl.js');
app.get('/export', requiresLogin, function(req, res) {
var guests = guestsCtrl.getGuests();
// do whatever you like to do with guests
});
Second Solution
If you really want to work with internal api, then you can use request module.
e.g.
routes.js
var request = require('request');
app.get('/export', requiresLogin, function(req, res) {
// you can put the hostname and port here
request('http://127.0.0.1:3000/api/guests', function(err, body, response){
var guests = body; // and save the 'guests' to a variable
});
});

Node.js API design and route handling

I am not really sure what to title this, but I'm new to Node.js. I just found a neat REST API project on GitHub to implement but I'm not sure how I can split all GET and POST etc. to separate files.
I have one singular api.js file where I have
function API_ROUTER(router, connection, md5) {
var self = this;
self.handleRoutes(router, connection, md5);
}
API_ROUTER.prototype.handleRoutes = function(router, connection, md5) {
router.get("/", function(req, res) {
res.json({"Message" : "Hello World !"});
});
};
module.exports = API_ROUTER;
Now how can I create a sibling other.js and use:
var api = require('./api.js');
// Create router.get, router.post etc. here?
but I'm not sure how I can split all GET and POST etc. to separate files.
One way you can organize your routes would be to have a separate object for each route that has the handlers (separated by HTTP methods) and other needed info such as the path:
api/home.js
module.exports = {
path: '/',
handlers: {
'get': function(req, res) {
res.json({"Message" : "Hello World !"});
},
'post': {
// ...
}
// ...
}
}
api/other.js
module.exports = {
path: '/other',
handlers: {
'get': function(req, res) {
res.json({"Message" : "Other !"});
},
// ...
Then you can load all of these inside the handleRoutes method:
API_ROUTER.prototype.handleRoutes = function(router, connection, md5) {
var routes = ['home', 'other'];
routes.forEach(function(name) {
// load the current route object (NOTE: you should use the path module for determining file path in a cross-platform manner)
var routeObject = require('./' + name + '.js');
var apiPath = routeObject.path;
var handlers = routeObject.handlers;
var methods = Object.keys(handlers);
// assign handlers for each method
methods.forEach(function(method) {
router[method](apiPath, handlers[method]);
});
});
};
This will install all your routes with the appropriate information and handlers.
Now you can call this code by instantiating your API_ROUTER with the necessary data:
// initialize the api (and handle the routes internally)
var Api = new require('./api.js')(router, connection, md5);
If you implement a RESTful API, then you should keep in mind that this is just one way how you can provide data, and you might want to change it in future, as of that the API will most of the time only be a translation layer.
Normally you will split your code based on the resources, and the code that is handling the request won't have so much logic, it will just take the request and pass it to you internal API. For that purpose you not really need an additional layer if you already use express.js or a similar library.
In express the app.use([path,] function [, function...]), already provides the functionality you would need to modularize your code. For each resource your will create an own express.Router that itself also might mount another sub module. So for this part you do not really need a library.
When might a library be useful:
if it automatically translates thrown errors to the correct response codes
if it includes a tool to automatically create a documentation to your API
if it fully abstracts the underlaying routing system so that you can hook into express, hapi, ... without the need to change the code.
Here how a setup with express.js could look like
./lib/rest/customer.js
var customerSystem = require('../customer-system');
var express = require('express');
var router = new express.Router();
router.get('/:id', function(req, res, next) {
customerSystem.find({
id: req.params.id
}, function(err, customer) {
if (err) {
res.status( /*correct status code*/ ).send( /*depending on the api return json, xml, ....*/ )
} else {
res.send( /*depending on the api return json, xml, ....*/ )
}
})
});
router.delete('/:id', function(req, res, next) {
customerSystem.delete({
id: req.params.id
}, function(err) {
//...
});
});
router.post('/', function(req, res, next) {
//...
});
//save the customer id for the pass to the sub routers
router.use('/:id', function(req, res, next) {
req.customerId = req.params.id;
next();
});
router.use('/:id/addresses', require('./customer-address') )
module.exports = router;
./lib/rest/customer-address.js
var customerSystem = require('../customer-system');
var express = require('express');
var router = new express.Router();
router.get('/:id', function(req, res, next) {
customerSystem.find({
id: req.customerId
}, function(err, customer) {
// ...
})
});
/* ..... */
//save the address id for the pass to the sub routers
router.use('/:id', function(req, res, next) {
req.addressId = req.params.id;
next();
});
router.use('/:id/addresses', require('./customer-address') )
module.exports = router;

Express routes: .get() requires callback functions but got a [object Object]

Ok, this should be easy for somebody to point out.
I checked the other similar questions and none helped.
I'm trying to move all my routes to a separate routes.js file. In it I have:
module.exports = function (app) {
var user = {
list : require('./routes/user.js')
}
, index = {
index : require('./routes/index.js')
}
app.get('/', function(request, response){
response.send('You made it to the home page.')
});
app.get('/users', user.list);
}
And in my app.js file I have this:
var register_routes = require('./routes.js')
register_routes(app)
My index route works fine, but it kicks back on app.get('/users', user.list); with this error:
.get() requires callback functions but got a [object Object]
This is an out of the box express app so theres not too much to describe.
Thanks.
EDIT: Per request, here is what is in ./routes/user.js :
exports.list = function(req, res){
res.send("respond with a resource");
};
You export an object with the key list having the your function as value.
So to access your function you would need to do this require('./routes/user.js').list
Or with your code user.list.list.
To solve this you have two possibilities.
Either write:
var user = {
list : require('./routes/user.js').list
}
Or:
module.exports = function(req, res){
res.send("respond with a resource");
};
EDIT
If your routes/user.js will probably later look like this:
module.exports.list = function(req, res){
res.send("respond with a resource");
};
module.exports.delete = function(req, res){
res.send("delete user");
};
If yes then you can just write it that way in your routes.js:
var user = require('./routes/user.js');
I think what you want is:
module.exports = function (app) {
var user = {
list : function(request, response){
require('./routes/user.js');
}
}
}
, index = {
index : function(request, response){
require('./routes/index.js')
}
}
app.get('/', function(request, response){
response.send('You made it to the home page.')
});
app.get('/users', user.list);
}
In this way give a callback to the route and this callback execute the require.
If you are using router in your application for all routing purpose,
var express = require('express');
var router = express.Router();
var index = require('./index');
/* GET home page. */
router.get('/', index.list);
module.exports = router;
then in your index.js file, just do
router.list = function(req, res){
res.send("respond with a resource");
};
After so many time seeking around in web, I found something.
First of all, You instantiate the code like this on another file, (e.g.: humancomms.ts):
import express from 'express';
export function shout(request: express.Request, response: express.Response, next: () => void) {
response.send('Shout so loud!');
}
export function speak(request: express.Request, response: express.Response, next: () => void) {
response.send('Speak less loud!');
}
What exactly this code does? Nobody knows.(Hehe, just kiddin')
This make a middleware functions to separate from main server file to... organize, of course.
And how We can use it? Just like this (inside your server file):
const shout = require('./humancomms').shout;
const speak = require('./humancomms').speak;
app.use('/shout', shout);
app.use('/speak', speak);
This code takes all middlewares funcs and executes when some path is called.
This not solve all problems like multi path to same type, as if You want call differently intensities of shout ('/shout/high?asd=asd', '/shout/low?asd=asd'), but there is a catch You can try on secondary file:
import express from 'express';
export function shout(request: express.Request, response: express.Response, next: () => void) {
if (request.path.includes('/high')) {
response.send('Shout so loud!');
} else if (request.path.includes('/low')) {
response.send('Really shout?');
}
}
Look at this good article about:
TypeScript Express tutorial #1. Middleware, routing, and controllers (https://wanago.io/2018/12/03/typescript-express-tutorial-routing-controllers-middleware/)
and the official documentation website:
Writing middleware for use in Express apps (http://expressjs.com/en/guide/writing-middleware.html)

Categories

Resources