store sql queries as string in node server to get them as a response(express) - sql

I am trying to do something may or may not be possible.
I have a SQL file called "travel.sql" that I am trying to make an api out of, so I thought the simplest thing to do is to save the queries as strings in an array and then save the array of strings as a response for a node server(express.js)
so simply here's the code till now but this is returning nothing in postman and I don't know what's missing or not
I checked all the packages and they are installed properly
const express = require('express')
const fse = require( "fs-extra" );
const { join } = require( "path" );
const app = express()
const port = 3000
app.get('/sqlfile', (req, res) => {
const loadSqlQueries = async folderName => {
// determine the file path for the folder
const filePath = join( process.cwd(), travel );
// get a list of all the files in the folder
const files = await fse.readdir( filePath );
// only files that have the .sql extension
const sqlFiles = files.filter( f => f.endsWith( ".sql" ) );
// loop over the files and read in their contents
const queries = {};
for ( let i = 0; i < sqlFiles.length; i++ ) {
const query = fse.readFileSync( join( filePath, sqlFiles[ i ] ), { encoding: "UTF-8" } );
queries[ sqlFiles[ i ].replace( ".sql", "" ) ] = query;
console.log(queries)
}
return queries;
res.send(queries);
};
})
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`)
})

I'm not quite sure of what you are trying to achieve, But anyway You have multiple parts of your code need to be enhanced:
As a first proposal I suggest to add a "try and catch" to your code so you can know the errors you are facing.
You are creating a function expression "loadSqlQueries" which I think is not needed and it never runs as you are just creating it but you never used it.
As the function expression is not needed then also the "return" is not needed.
To be able to use "await" like here: const files = await fse.readdir( filePath ); You need to use it inside "async" function.
You are using "travel" here const filePath = join( process.cwd(), travel ); as a variable, you need to use it as a string like this const filePath = join( process.cwd(), "travel" );
I've applied the above mentioned changes, kindly read the comments I added to your code to catch the changes and here is the final code:
const express = require('express')
const fse = require("fs-extra");
const { join } = require("path");
const app = express()
const port = 3000
app.get('/sqlfile',
// add async to be able to use await
async (req, res) => {
// add try and catch block to your code to catch the errors
try {
// no need for the function expression which is never used
// const loadSqlQueries = async folderName => {
// determine the file path for the folder
//use travel as a string not a variable
const filePath = join(process.cwd(), "travel");
// get a list of all the files in the folder
const files = await fse.readdir(filePath);
// only files that have the .sql extension
const sqlFiles = files.filter(f => f.endsWith(".sql"));
// loop over the files and read in their contents
const queries = {};
for (let i = 0; i < sqlFiles.length; i++) {
const query = fse.readFileSync(join(filePath, sqlFiles[i]), { encoding: "UTF-8" });
queries[sqlFiles[i].replace(".sql", "")] = query;
console.log(queries)
}
// As the function expression is not used we will comment return
// return queries;
res.send(queries);
// }
} catch (error) {
console.log(error);
}
})
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`)
})

Related

handling error trying to set key of immutable and frozen object

i have the following object in a state:
App.js
const data = {name: 'John', status:'employeed' };
const [manager, updateManager] = useState(data);
const updateStatus = async () =>{
await service.setStatus(manager);
}
setStatus does modify the manager directly, which I think is the source of the problem
service.js
setStatus(manager){
manager.status = 'employeed';
}
so I modified the call to send a copy of the manager object and return a new object but still I get the error
you tried to modify 'status' key of an immutable object.
here is my new change
App.js
const updateStatus = async () =>{
const g = await service.setStatus({...manager});
updateManager(g);
}
service.js
setStatus(manager){
manager.status = 'employeed';
return manager;
}
Why has this function to be async?
const updateStatus = async () =>{
await service.setStatus(manager);
}
This return a new/updated object but it won‘t do any permanent changes.
setStatus(manager){
return {…manager,status: 'employeed'};
}
Does the problem after your last changes persists?
You should pass a callback like this:
const updateStatus = (manager) => {
service.setStatus(()=> updateManager({
...manager,
status: 'employeed'
}));
Service.js
setStatus(updateManager){
updateManager(manager);
}

How to check if a file exist in nuxt

I'm on Nuxt 2.15.4 and i wanna check in my store codes if a file exist in nuxt directory by fs-extra package.
it is simple in modules because i can get files path by this code:
const path = require('path')
const fse = require('fs-extra');
const FilePath = path.join(this.options.rootDir, './static/myfile.json')
const fse = require('fs-extra');
fse.pathExists(FilePath, (err, exists) => {
console.log(err) // => null
console.log(exists) // => true
})
but in vuex store i dont have access to this.options.rootDir and this code is always return false:
export const actions = {
async nuxtServerInit({dispatch, commit}) {
if(process.server){
const fse = require('fs-extra');
fse.pathExists('~/static/myfile.json', (err, exists) => {
console.log(err) // => null
console.log(exists) // => false
})
}
}
}
how can i get files fullpath or check if it exits??
#UPDATE
It looks like I had a little mistake in my file path so used ./static/myfile.json and the check is done!!
but got another problem!! I have another json file, when I'm trying to use Object.assign(mainfile, myfile) it won't work!!
here is a sample:
async nuxtServerInit({dispatch, commit}) {
let mainfile = require('../assets/mainfile.json')
// if i use assign here it works and merge them together
// let myfile = require('../assets/myfile.json')
// Object.assign(mainfile, myfile)
if(process.server){
const fse = require('fs-extra');
fse.pathExists('./static/myfile.json', (err, exists) => {
if(exists){
Object.assign(mainfile, myfile)
commit('SET_FILE', mainfile); // this send the unmerged file to mutation
console.log(mainfile); // but get the merged json here
}
})
console.log(mainfile); // it is unmerged
}
console.log(mainfile); // it is unmerged
}
For your updated question, be sure that exists is truthy, that you're entering in the loop and that mainfile is in the format that you're expecting.
Then, you could do
mainfile = {...mainfile, ...myfile} // rather than Object.assign
Ok, thanks to #kissu I found out the problem. As kissu mentioned in his answer's comment, commit is synchronous; I tried await action but didn't get the result; so I used pathExistsSync instead and done!!
async nuxtServerInit({dispatch, commit}) {
let myfile = {}
let mainfile = require('../assets/mainfile.json')
if(process.server){
const fse = require('fs-extra');
if(fse.pathExistsSync('./static/myfile.json')){
myfile = require('../assets/myfile.json')
Object.assign(mainfile, myfile)
}
}
await dispatch('setMyFile', mainfile)
}
#Update
require('../assets/mainfile.json') still throw error if file doesn't exist even with if(fse.pathExistsSync('./static/myfile.json')) statement so:
async nuxtServerInit({dispatch, commit}) {
let myfile = {}
let mainfile = require('../assets/mainfile.json')
if(process.server){
const fse = require('fs-extra');
if(fse.pathExistsSync('./static/myfile.json')){
myfile = readJsonSync('./static/myfile.json')
Object.assign(mainfile, myfile)
}
}
await dispatch('setMyFile', mainfile)
}

How to exit a while loop depending of the result of an Axios call?

In order to make sure a user-entered word exists, I need to keep prompting (while loop) for a word until the word API finds the word.
My question is: how can I exit the while loop depending of Axios call result?
Below is my code so far.
const wordApiBaseUrl = 'https://www.dictionaryapi.com/api/v1/references/sd4/xml'
while (true) {
const wordToGuess = prompt('Enter a word:').toLowerCase()
const endPointUrl = `${wordApiBaseUrl}/${wordToGuess}?key=${wordApiKey}`
this.axios.get(endPointUrl).then(res => {
if (res.data.includes('def')) {
break
}
})
}
Try this:
const wordApiBaseUrl = 'https://www.dictionaryapi.com/api/v1/references/sd4/xml'
const vm = this; // <--- assuming this is the Vue instance
const dispatcher = {
execute: function() {
const wordToGuess = prompt('Enter a word:').toLowerCase()
const endPointUrl = `${wordApiBaseUrl}/${wordToGuess}?key=${wordApiKey}`
const dispatcher = this;
vm.axios.get(endPointUrl).then(res => {
if (!res.data.includes('def')) {
dispatcher.execute();
}
})
}
}
dispatcher.execute();
Rather than using a while loop or using an async/await you can use recursion in our promise. If the result is not satisfied, re-run the AJAX call.

How to implement validation in a separate file using express-validator

I am trying to use express-validator to validate the req.body before sending a post request to insert data to postgres.
I have a route file, controller file and I want to carryout validation in a file called validate.js. Meanwhile, I have installed express-validator and in my server.js I have imported it. Other resources I come across seem to implement the validation in the function that contains the logic for inserting the data.
//server.js
....
import expressValidator from 'express-validator';
...
app.use(bodyParser.urlencoded({ extended: false }));
app.use(expressValidator);
//route.js
import express from 'express';
import usersController from './controller';
const router = express.Router();
router.post('/createuser', usersController.createUser);
//controller.js
createUser(req, res){
// ...
const { firstName, lastName, email, password } = req.body;
//code to insert user details to the database
}
//validator.js
import { check } from 'express-validator/check';
module.exports = [check('email').isEmail()];
I expect to implemet the validation in a file called validator.js to, say, validate the email before inserting to the database
I have same approach, except one thing that is we shouldn't handle validation error in our controller. So If any error is occurring at Validation Layer, it should throw back from there only. We shouldn't allow our control flow to enter into the Controller Layer. So below are the code example:
useRoute.js
const route = express.Router();
const {
**validateUser**,
} = require('../middlewares/validators/userValidator');
route.route('/').post(**validateUser**, createUser);
route.route('/:id').put(**validateUser**, updateUser);
module.exports = route;
userValidator.js
const {check, validationResult} = require('express-validator');
exports.validateUser = [
check('name')
.trim()
.escape()
.not()
.isEmpty()
.withMessage('User name can not be empty!')
.bail()
.isLength({min: 3})
.withMessage('Minimum 3 characters required!')
.bail(),
check('email')
.trim()
.normalizeEmail()
.not()
.isEmpty()
.withMessage('Invalid email address!')
.bail(),
(req, res, next) => {
const errors = validationResult(req);
if (!errors.isEmpty())
return res.status(422).json({errors: errors.array()});
next();
},
];
controller.js
/**
* #desc - create new User
* #method - POST
*/
exports.createCategory = async (req, res) => {
// do your stuff here. (No need to check any validation error here)
}
Here is the way i use express-validator. I have a file validator.js where i have validation logic for many routes. For example:
validator.js
const { check } = require('express-validator/check');
exports.createUser = [check('email').isEmail()];
exports.anotherRoute = [// check data];
exports.doSomethingElse = [// check data];
Now in your route file you require the validator.js file const validator = require("./validator"); // or where your file is located
and use the validation logic you want as a middleware. For example:
route.js
//
router.post('/createuser', validator.createUser, usersController.createUser);
Last, inside your controller you have to check for possible errors created during validation, after requiring validationResult.
controller.js
const { validationResult } = require('express-validator/check');
exports.createUser(req, res) {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(422).json({ errors: errors.array() });
}
// do stuff here.
}
Also, you don't have to use app.use(expressValidator); in your server.js file
I was running into a few problems with async functions, here is my humble solution hope this helps someone:
Route Definitions
const router = require('express').Router();
const userValidator = require('./Validators/UserValidator');
const userController = require('./Controllers/UserController');
router.post('/users', userValidator.add, userController.add);
Validator
const { check, validationResult } = require('express-validator');
const generateValidators = () => [
check('first_name')...,
check('last_name')...,
check('email')...,
check('password')...
]
const reporter = (req, res, next) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
const errorMessages = errors.array().map(error => error.msg);
return res.status(400).json({
errors: errorMessages
});
}
next();
}
module.exports = {
add: [
generateValidators(),
reporter
]
};
just adding few changes to Shivam's answer for
email
const {check, validationResult} = require('express-validator');
exports.validateUser = [
check('name')
.trim()
.escape()
.not()
.isEmpty()
.withMessage('User name can not be empty!')
.bail()
.isLength({min: 3})
.withMessage('Minimum 3 characters required!')
.bail(),
check('email')
trim()
.not()
.isEmpty()
.withMessage("Email name can not be empty!")
.bail()
.isEmail()
.withMessage("Invalid email address!")
.bail(),
(req, res, next) => {
const errors = validationResult(req);
if (!errors.isEmpty())
return res.status(422).json({errors: errors.array()});
next();
},
];

mongoose query array as an arg of Promise.all doesn't seem work properly

I'm working with express and mongoose, having problem.
As an API server, I implemented a router js file. One of posts is to save four objects in db at once.
As I know, mongoose query function like save() can be used as a promise object.
So I attended to make a mongoose query array, and put it into Promise.all as an argument, but It doesn't work. (I can't find any records on db after run this code.)
following is my code, please review it and teach me why it doesn't work.
import { Router } from 'express';
import Collection from '../models/collection.model';
const router = new Router();
router.post('/api/collections/basic-pick/:userId', (req, res) => {
const pickedMons = req.body.pickedMons;
const collections = [];
let condition = 1;
for (const mon of pickedMons) {
condition = Math.floor((Math.random() * 5) + 1);
const collection = new Collection({
_monId: mon._id,
_userId: req.params.userId,
condition,
});
// this log prints right objects
console.log('collection: ' + collection);
collections.push(collection);
}
const proms = [];
for (const collection of collections) {
// collection.save() function returns promise, right?
proms.push(collection.save);
}
Promise.all(proms).then(() => {
return res.json({ success: true });
});
});
export default router;