Get param in URL without callback function - node.js

so I know how to get params from URL the normal way:
router.get('/products/:id', (request, response, next) => {
let id = request.params.id;
But when I want to refactor the code to many files, the code becomes something like:
const productService = require('../services/productService');
router.get('/products/:id', productService.getProductList);
How can I get the "id" from URL now?
The productService.js file:
var mongodb = require('mongodb');
const db = require('../models/mongoUtil.js').getDb();
const getProductList = async (request, response) => {
try {
let id = request.params.id;
let object_id = new mongodb.ObjectId(id);
const result = await db.collection('product_list').findOne({ '_id': object_id });
response.json(result);
console.log(result);
} catch (err) {
console.log(err);
}
};
module.exports = {
getProductList
};
Thank you. I am new to Node Js.

Related

NodeJS+Express+SQL Server backend application Error : Incorrect Syntax near '83' , Incorrect Syntax near '68' etc

In my application I get the following errors when I'm trying to reach GET, PUT, DELETE routes (tried POSTMAN and VSCode REST Server):
Error 1:
GET by ID : `Incorrect Syntax near '83'.`
Error 2:
GET ALL : `Incorrect Syntax near '83'.`
Error 3:
PUT : `Incorrect syntax near '85'.`
Error 4:
DELETE : `Incorrect syntax near '68'.`
I have googled the error but most of them are related to spacing errors in parameters in the SQL query but I have checked mine and the queries I have are all correct compared to those.
I suspect if this related to any SQL Server related encoding but not sure.
Below are some of my coding as a start to investigate:
eventController.js
'use strict';
const eventData = require('../data/events');
const getEvents = async (req, res, next) => {
try {
const events = await eventData.getEvents();
res.send(events);
}catch (error) {
res.status(400).send(error.message);
}
}
const getEvent = async (req, res, next) => {
try {
const eventId = req.params.id;
const oneEvent = await eventData.getById(eventId);
res.send(oneEvent)
} catch (error) {
res.status(400).send(error.message)
}
}
const updateEvent = async (req, res, next) => {
try {
const eventId = req.params.id;
const data = req.body;
const updated = await eventData.updateEvent(eventId, data);
res.send(updated);
} catch (error) {
res.status(400).send(error.message)
}
}
const deleteEvent = async (req, res, next) => {
try {
const eventId = req.params.id;
const deletedevent = await eventData.deleteEvent(eventId);
res.send(deletedevent);
} catch (error) {
res.status(400).send(error.message)
}
}
module.exports = {
getEvents,
getEvent,
updateEvent,
deleteEvent
}
eventslist.sql
SELECT [ord_type],
[ord_no],
[line_seq_no],
[lvl_no],
[cmt_type],
[cmt_seq_no],
[cmt],
[CMT_DOC_TYPE],
[EXTRA_1],
[extra_2],
[extra_3],
[extra_4],
[extra_5],
[extra_6],
[extra_7],
[extra_8],
[extra_9],
[extra_10],
[extra_11],
[extra_12],
[extra_13],
[extra_14],
[extra_15],
[FILLER_0001],
[ID],
[is_ext],
[RowVersion]
FROM [100].[dbo].[OELINCMT_SQL]
utils.js
'use strict';
const fs = require('fs-extra');
const {join} = require('path');
const loadSqlQueries = async (folderName) => {
const filePath = join(process.cwd(), 'data', folderName);
const files = await fs.readdir(filePath);
const sqlFiles = await files.filter(f => f.endsWith('.sql'));
const queries = {};
for (const sqlFile of sqlFiles) {
const query = await fs.readFileSync(join(filePath, sqlFile));
queries[sqlFile.replace(".sql", "")] = query
}
return queries;
}
module.exports = {
loadSqlQueries
}
UPDATE : Added data/events
index.js
'use strict';
const utils = require('../utils');
const config = require('../../config');
const sql = require('mssql');
const getEvents = async () => {
try {
let pool = await sql.connect(config.sql);
const sqlQueries = await utils.loadSqlQueries('events');
const list = await pool.request().query(sqlQueries.eventslist);
return list.recordset;
} catch (error) {
return error.message;
}
}
const getById = async (eventId) => {
try {
let pool = await sql.connect(config.sql);
const sqlQueries = await utils.loadSqlQueries('events');
const oneEvent = await pool.request()
.input('eventId', sql.Char(8), eventId)
.query(sqlQueries.eventbyId);
return oneEvent.recordset;
} catch (error) {
return error.message;
}
}
const updateEvent = async (eventId, eventData) => {
try {
let pool = await sql.connect(config.sql);
const sqlQueries = await utils.loadSqlQueries('events');
const update = await pool.request()
.input('eventId', sql.Char(8), eventId)
.input('cmt', sql.NVarChar(4000), eventData.cmt)
.query(sqlQueries.updateEvent);
return update.recordset;
} catch (error) {
return error.message
}
}
const deleteEvent = async (eventId) => {
try {
let pool = await sql.connect(config.sql);
const sqlQueries = await utils.loadSqlQueries('events');
const deleted = await pool.request()
.input('eventId', sql.Char(8), eventId)
.query(sqlQueries.deleteEvent);
return deleted.recordset;
} catch (error) {
return error.message
}
}
module.exports = {
getEvents,
getById,
updateEvent,
deleteEvent
}
eventbyId.sql
SELECT [ord_type]
,[ord_no]
,[line_seq_no]
,[lvl_no]
,[cmt_type]
,[cmt_seq_no]
,[cmt]
,[CMT_DOC_TYPE]
,[EXTRA_1]
,[extra_2]
,[extra_3]
,[extra_4]
,[extra_5]
,[extra_6]
,[extra_7]
,[extra_8]
,[extra_9]
,[extra_10]
,[extra_11]
,[extra_12]
,[extra_13]
,[extra_14]
,[extra_15]
,[FILLER_0001]
,[ID]
,[is_ext]
,[RowVersion]
FROM [100].[dbo].[OELINCMT_SQL]
WHERE [ord_no] = #eventId
Request for GET ALL via POSTMAN
Request for GET by ID via POSTMAN
Request for GET ALL via REST Server
RAW Body of GET ALL request
RAW Body of GET by ID request

Nodejs change the bot's nickname every time the variable change DISOCRD.JS

I'm doing a dominance ticker for bitcoin and I want to show the price in the nickname of the bot, the thing is that I don't know why but I can't change the nickname, it throws me an error.
const { Client } = require('discord.js');
const client = new Client();
const request = require("request");
var LastBitcoinDominance = 100;
client.on("ready", () => {
console.log(`Logged in as ${client.user.tag}!`);
})
myFunction()
function myFunction() {
const url = "API";
request(url, (err, res, body) => {
const data = JSON.parse(body);
var bitcoinDominance = data.bitcoin_dominance_percentage;
if (bitcoinDominance == LastBitcoinDominance){
console.log("Bitcoin dominance and LastBitcoinDominacne are the same")
}else {
client.user.setUsername(bitcoinDominance)
LastBitcoinDominance = bitcoinDominance;
}
});
setTimeout(myFunction, 10000);
}
client.login(TOKEN)
I think it is because client could not be detected. Because null means literally nothing.
Try using:
client.login(TOKEN);
instead of:
client.token(TOKEN);
Edit:
Try this:
const { Client } = require('discord.js');
const client = new Client();
const request = require("request");
var LastBitcoinDominance = 100;
client.on("ready", () => {
console.log(`Logged in as ${client.user.tag}!`);
})
myFunction(client)
function myFunction(client) {
const url = "API";
request(url, (err, res, body) => {
const data = JSON.parse(body);
var bitcoinDominance = data.bitcoin_dominance_percentage;
if (bitcoinDominance == LastBitcoinDominance){
console.log("Bitcoin dominance and LastBitcoinDominacne are the same")
}else {
client.user.setUsername(bitcoinDominance);
LastBitcoinDominance = bitcoinDominance;
}
});
setTimeout(myFunction, 10000);
}
client.login(TOKEN)
I added a parameter to your function myFunction, because you cannot use your client inside a function. Therefor you provide it for the parameter client. Inside the function the parameter client is now your client, because you provided it.
make sure the bot has permissions.
i tried running this and i didn't get any errors:

Chaining GET requests to WP REST API in Express

I am struggling to understand callbacks, promises, and async/await.
What I want to do is read a .csv file inside my project folder that contains 150+ post ID's.
For each one of those ID's I want to make a https GET request to fetch a JSON response from my Wordpress website.
Then for each one of those posts that gets returned I want to insert them in my Firestore database.
I'm struggling with how to properly set up the callback functions.
Please help.
Thanks in advance.
const express = require('express');
const router = express.Router();
const https = require("https");
const Recipe = require("../includes/newrecipe");
var admin = require('firebase-admin');
var serviceAccount = require("../service_key.json");
const collectionKey = "recipes"; //name of the collection
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "<MY_FIRESTORE_URL>"
});
const firestore = admin.firestore();
const fs = require('fs');
const parse = require('csv-parser');
function prepareCsvData() {
return new Promise((resolve, reject) => {
//establish empty csvData array and filename to be referenced
var csvData = [];
var filename = 'wprm_recipe_ids.csv';
//read the csv file and push the data object into the array
fs.createReadStream(filename)
.pipe(parse(['ID']))
.on('data', (data) => csvData.push(data))
.on('end', () => { resolve(csvData); });
});
}
function getRecipeFromBlog(recipeId) {
return new Promise((resolve, reject) => {
//make the get request to my website to get the recipe
https.get('<MY_WEBSITE_URL>' + recipeId, (response) => {
var body = "";
response.on('data', function (chunk) { body += chunk; });
response.on('end', () => {
var { recipe } = JSON.parse(body);
//build new recipe to be exported
var newRecipe = new Recipe(recipe);
resolve(newRecipe);
});
});
});
}
/* GET recipes. */
router.get('/', async (req, res, next) => {
//first prepare the csv data
//function returns a promise with the csv data
//that I can then use in the next step
const csvData = await prepareCsvData();
for (var i = 0; csvData.length < i; i++) {
getRecipeFromBlog(csvData[i].ID)
.then((newRecipe) => {
//when I have a recipe for a given recipe ID
//update database in firestore
firestore
.collection(collectionKey)
.doc(""+newRecipe.id)
.set(newRecipe)
.then(function() {
console.log('document written');
});
});
}
res.send('done');
});
You need to do something like below:
Play around this, You'll get it working hopefully!
Let me know if that worked!
router.get("/", async (req, res, next) => {
const csvData = await prepareCsvData();
const recipePromises = [];
// check if data is empty or not
if (!csvData.length) {
return res.send("Empty data");
}
csvData.forEach((element) => {
recipePromises.push(getRecipeFromBlog(element.id));
});
// await for all promises parallelly.
const result = await Promise.all(recipePromises);
// Get a new write batch
const batch = db.batch();
result.forEach((recipe) => {
const ref = db.collection("recipes").doc(`${recipe.id}`);
batch.set(ref, recipe);
});
// Commit the batch
await batch.commit();
res.send("done");
});
The OP code looks pretty close to working. Have the promise-returning functions been tested? Assuming they work, first decorate them as async...
async function prepareCsvData() {...}
async function getRecipeFromBlog(recipeId) {...}
Create another promise-returning function to insert many recipes into firebase...
async function writeRecipesToFB(recipes) {
const collectionRef = collection(collectionKey);
const promises = recipes.map(recipe => {
return collectionRef.doc(`${recipe.id}`).set(recipe);
});
return Promise.all(promises)
}
As another answer suggests, as an alternative, firebase's batch write is a good idea...
async function writeRecipesToFB(recipes) {
// as a set of promises
const collectionRef = collection(collectionKey);
const batch = db.batch();
recipes.forEach(recipe => {
const docRef = collectionRef.doc(`${recipe.id}`)
batch.set(docRef, recipe)
});
return batch.commit();
}
Now the express function is easy to write...
router.get('/', async (req, res, next) => {
const csvData = await prepareCsvData();
let promises = csvData.map(row => {
return getRecipeFromBlog(row.ID);
});
const recipes = await Promise.all(promises);
await writeRecipesToFB(recipes);
res.send('done');
});

How should I parse URL parameters using Node JS express?

I would like to pass the lat lon from this URL http://localhost:8080/fp?lon=103.742463567216646&lat=1.336711421273283. Where should I place the "req.query.lon" and "req.query.lat" in the following code?
I am hoping to parse the users input in the URL link so that I can dynamically retrieve from the database.
const {Client} = require("pg")
const express = require ("express")
const url=require('url')
const fs= require('')
const app = express();
app.use(express.json())
const client = new Client({
"user": "xxx",
"password" : "xxx",
"host" : "xxx",
"port" : xxx,
"database" : "xxx"
})
//app.get("/", (req, res) => res.sendFile(`${__dirname}/index.html`))
app.get("/fp", async (req, res) => {
//const lon = 103.742463567216646;
//const lat = 1.336711421273283;
//const lon = req.query.lon;
//const lat = req.query.lat;
const rows = await readTodos ();
res.send(JSON.stringify(rows))
})
app.listen(8080, () => console.log("Web server is listening.. on port 8080"))
start()
async function start() {
await connect();
}
async function connect() {
try {
await client.connect();
}
catch(e) {
console.error(`Failed to connect ${e}`)
}
}
async function readTodos() {
try {
const results = await client.query("SELECT ST_AsText(ST_Force2D(geom)) FROM fp ORDER BY geom <-> ST_SetSRID(ST_MakePoint("+lon+ ","+lat+ "), 3993) LIMIT 1;");
return results.rows;
}
catch(e){
return [];
}
}
Express parses it by default and store them in req.query.
Accessing req.query.<key> will give you the value you are looking for.
For instance, in your example, express will store it inside req.query.lon and req.query.lat.
So, actually you access them right in the request handler of /fp, just comment out the access to these variables and pass them as parameters to readTodos():
app.get("/fp", async (req, res) => {
const lon = req.query.lon;
const lat = req.query.lat;
const rows = await readTodos(lon, lat);
res.send(JSON.stringify(rows))
})
async function readTodos(lon, lat) {
try {
const results = await client.query("SELECT ST_AsText(ST_Force2D(geom)) FROM fp ORDER BY geom <-> ST_SetSRID(ST_MakePoint("+lon+ ","+lat+ "), 3993) LIMIT 1;");
return results.rows;
}
catch(e){
return [];
}
}

ASYNC/AWAIT for Chaining multiple http.requests

How would I go about chaining an http.request within the response of another http.request and then push them into an array before going to the front end?
router.get("/:team", (req, res) => {
let teamParams = teams[req.params.team];
twitter.get("search/tweets", teamParams, (err, data, resp) => {
let tweetArr = [];
let text = data.statuses;
text.map((dat) => {
let im = dat.entities.urls[0].url
dat.links = im;
tweetArr.push(dat);
});
res.json({ message: "Success", tweets: tweetArr });
});
});
Currently I get my data object loop through it and add a url as a property. Now I want to chain another http request to make an API call to another API and get a response, before I use res.json.
I've tried a workaround with promises but I can never return the full object with the response from the second api call.
This is what I have so far, I have managed to get to a point where my object contains the requests from the second link. How can I return all the tweets into an array I can finally resolve?
require("dotenv").config();
const Twitter = require("twitter");
const API_IMAGE_PREV = "http://api.linkpreview.net/";
const request = require("request");
const key = process.env.IM_PREV_KEY;
let twitter = new Twitter({
consumer_key: process.env.TWITTER_CONSUMER_KEY,
consumer_secret: process.env.TWITTER_CONSUMER_SECRET,
bearer_token: process.env.TWITTER_BEARER_TOKEN
});
let teamParams = {
q: "from:ManUtdMEN MUFC",
count: 2,
result_type: "recent"
};
var third = function thirdUrl(next) {
var promise = new Promise(function(resolve, reject) {
next.forEach(x => {
let ln = x.links;
const options = {
url: "http://api.linkpreview.net/?key=" + key + "&q=" + ln,
method: "get"
};
request.get(options, (err, req, res) => {
if (err) {
console.log(err);
} else {
x.desc = res;
}
});
});
});
};
var second = function secondUrl(previous) {
var promise = new Promise(function(resolve, reject) {
let p = previous.statuses;
let links = [];
p.forEach(t => {
let l = t.entities.urls[0].url;
t.links = l;
});
resolve(p);
});
return promise;
};
twitter
.get("search/tweets", teamParams)
.then(second)
.then(third)
.catch(function(error) {
throw error;
});
What module are you using for the http requests? Here's an example with axios.
const axios = require('axios');
router.get("/:team", (req, res) => {
let teamParams = teams[req.params.team];
twitter.get("search/tweets", teamParams, async (err, data, resp) => {
let tweetArr = [];
let text = data.statuses;
text.map((dat) => {
let im = dat.entities.urls[0].url
dat.links = im;
tweetArr.push(dat);
});
let res = await Promise.all(tweetArr.map(dat => axios.get(dat.links));
res.json({ message: "Success", tweets: res });
});
})

Resources