Convert directory structure in the filesystem to Json object - json

I Know how to convert the directory structure into JSON object, from here
But I want all the files in an array, and the folders in object with the object key as the folder name. I have been trying for a long time but just cannot get it done.
Thi is what I have tried so far:
var diretoryTreeToObj = function (dir, done) {
var results = {};
var _contents = [];
fs.readdir(dir, function (err, list) {
if (err) {
return done(err);
}
var pending = list.length;
if (!pending) {
return done(null, {name: path.basename(dir), type: 'folder', children: results});
}
list.forEach(function (file, index) {
file = path.resolve(dir, file);
fs.stat(file, function (err, stat) {
if (stat && stat.isDirectory()) {
diretoryTreeToObj(file, function (err, res) {
results[path.basename(file)] = {
name: path.basename(file),
type: 'folder',
path: path.dirname(file),
_contents: [res]
};
if (!--pending) {
done(null, results);
}
});
} else {
results['_contents'] = [{
name: path.basename(file),
path: file
}];
if (!--pending) {
done(null, results);
}
}
});
});
});
};
Thanks in advance. :)

Finally I figured out the solution, here it is if anybody needs it:
var diretoryTreeToObj = function (dir, done) {
var results = {};
var _contents = [];
var files = [];
fs.readdir(dir, function (err, list) {
if (err) {
return done(err);
}
var pending = list.length;
if (!pending) {
return done(null, {name: path.basename(dir), type: 'folder', children: results});
}
list.forEach(function (file, index) {
file = path.resolve(dir, file);
fs.stat(file, function (err, stat) {
results['_contents'] = files;
if (stat && stat.isDirectory()) {
diretoryTreeToObj(file, function (err, res) {
results[path.basename(file)] = res;
if (!--pending) {
done(null, results);
}
});
} else {
files.push({
name: path.basename(file),
path: file
});
results['_contents'] = files;
if (!--pending) {
done(null, results);
}
}
});
});
});
};

Related

Node.js Wait for redis client.get before send json object

res.json(data) is called before redis client get data from server... How can i wait for data before send json object?
app.get('/api/player/:name', function(req, res) {
var name = req.params.name;
var data = {
"connected": 0,
"health": 0,
"armour": 0
};
readClient.get(name + '.connected', function(err, value) {
data.connected = value;
});
readClient.get(name + '.health', function(err, value) {
data.health = value;
});
readClient.get(name + '.armour', function(err, value) {
data.armour = value;
console.log(data);
});
console.log(data);
res.json(data);
});
Well, redis calls are async. That means that every query call must receive a callback function that shall be called once the query completes injecting data an errors. In order to send res.json when all data is ready then you must do something like:
app.get('/api/player/:name', function(req, res) {
var name = req.params.name;
var data = {
"connected": 0,
"health": 0,
"armour": 0
};
var promises = [];
promises.push( new Promise( function(resolve,reject) {
readClient.get(name + '.connected', function(err, value) {
if(err) { reject(err); }
resolve(value);
});
} ) );
promises.push( new Promise( function(resolve,reject) {
readClient.get(name + '.health', function(err, value) {
if(err) { reject(err); }
resolve(value);
});
} ) );
promises.push( new Promise( function(resolve,reject) {
readClient.get(name + '.armour', function(err, value) {
if(err) { reject(err); }
resolve(value);
});
} ) );
Promise.all(promises).then( function(values) {
console.log(values);
data.connected = values[0];
data.health = values[1];
data.armour = values[2];
res.json(data);
} ).catch(handleError);
});
function handleError(err) {
res.status(501);
res.send({msg:err.message});
}
I'd recommend working with await and Promises however, but this is a good starting point.
Hope this helps

mysql node: can't set headers after they are sent

I am trying to get a list of movies in a directory, parse titles, get movie information on TMDB than check if movie info is stored in mysql database and if not stored, insert info into the database.
I am using NodeJS/Express and mysql.
Here is my code so far:
exports.checkForMovies = function (req, res, next) {
const testFolder = './test/';
var movieList = [];
var movieResultsPromise = [];
var movieResults = [];
fs.readdirSync(testFolder).forEach(file => {
movieList.push(tnp(file));
});
movieList.forEach(movie => {
var waitPromise = searchTMDB(movie.title);
movieResultsPromise.push(waitPromise);
});
Promise.all(movieResultsPromise).then(result => {
movieResults = result;
movieResults.forEach(movie => {
checkMoviesInDB(movie.id, (err, data) => {
if (err) {
console.log(err)
}
if (data && data.update === true) {
var movieObj = {
m_tmdb_id: movie.id
};
insertMoviesToDB(movieObj, (resp, err) => {
if (err) {
console.log(err);
} else {
return res.json(resp);
}
});
} else {
return res.json(data);
}
});
});
});
}
function checkMoviesInDB(id, cb) {
var sql = "SELECT * FROM ?? WHERE m_tmdb_id = ?"
var table = ['movie', id];
sql = mysql.format(sql, table);
connection.query(sql, function (err, rows) {
if (err) {
return cb(err);
}
if (rows.length > 0) {
return cb(null, {
success: true,
update: false,
message: 'Movies up to date!'
})
} else {
return cb(null, {
update: true,
message: 'Updating database!'
})
}
});
}
function insertMoviesToDB(movie, cb) {
var sql = "INSERT INTO ?? SET ?";
var table = ['movie', movie];
sql = mysql.format(sql, table);
connection.query(sql, function (err, rows) {
if (err) {
return cb(err);
} else {
return cb(null, {
success: true,
message: 'Movie database updated!'
})
}
});
}
function searchTMDB(title) {
return new Promise((resolve, reject) => {
https.get(config.tmdbURL + title, response => {
var body = "";
response.setEncoding("utf8");
response.on("data", data => {
body += data;
});
response.on("end", () => {
body = JSON.parse(body);
resolve(body.results[0]);
});
response.on("error", (err) => {
reject(err);
});
});
});
}
After code execution it inserts movie info in the database or responses with "Movies up to date" but I am getting this error and NodeJS crashes:
Error: Can't set headers after they are sent.
Any help is appreciated, thanks!
EDIT!
This is the new code and I am still getting the same error...
exports.checkForMovies = function (req, res) {
const testFolder = './test/';
var movieList = [];
var movieResults = [];
fs.readdirSync(testFolder).forEach(file => {
movieList.push(tnp(file));
});
var movieObj = movieList.map(movie => {
var tmp = [];
return searchTMDB(movie.title).then(data => {
tmp.push(data);
return tmp
});
});
var checkDB = Promise.all(movieObj).then(moviesData => {
moviesData.map(movieData => {
checkMoviesInDB(movieData[0]).then(checkResponse => {
if (!checkResponse.movieToInsert) {
res.json(checkResponse);
} else {
var insertArray = checkResponse.movieToInsert;
var inserting = insertArray.map(movie => {
var movieObject = {
m_tmdb_id: movie.id,
m_name: movie.title,
m_year: movie.release_date,
m_desc: movie.overview,
m_genre: undefined,
m_poster: movie.poster_path,
m_watched: 0
};
insertMoviesToDB(movieObject).then(insertResponse => {
res.json(insertResponse);
});
});
}
});
});
});
}
function checkMoviesInDB(movie) {
var moviesToInsert = [];
return new Promise((resolve, reject) => {
var sql = "SELECT * FROM ?? WHERE m_tmdb_id = ?"
var table = ['movie', movie.id];
sql = mysql.format(sql, table);
connection.query(sql, function (err, rows) {
if (err) {
return reject(err);
}
if (rows.length === 0) {
moviesToInsert.push(movie);
resolve({
success: true,
movieToInsert: moviesToInsert
});
} else {
resolve({
success: true,
message: 'No movie to insert'
});
}
});
});
}
function insertMoviesToDB(movie) {
return new Promise((resolve, reject) => {
var sql = "INSERT INTO ?? SET ?";
var table = ['movie', movie];
sql = mysql.format(sql, table);
connection.query(sql, function (err, rows) {
if (err) {
return reject(err);
} else {
resolve({
success: true,
message: 'Movie added!'
});
}
});
});
}
function searchTMDB(title) {
return new Promise((resolve, reject) => {
https.get(config.tmdbURL + title, response => {
var body = "";
response.setEncoding("utf8");
response.on("data", data => {
body += data;
});
response.on("end", () => {
body = JSON.parse(body);
resolve(body.results[0]);
});
response.on("error", (err) => {
reject(err);
});
});
});
}
Auth.js
const config = require('./config');
const jwt = require('jsonwebtoken');
module.exports = function (req, res, next) {
var token = req.body.token || req.params.token || req.headers['x-access-token'];
if (token) {
jwt.verify(token, config.secret, function (err, decoded) {
if (err) {
return res.json({
success: false,
message: 'Failed to authenticate token.'
});
} else {
req.decoded = decoded;
next();
}
});
} else {
return res.status(403).send({
success: false,
message: 'Please login in to countinue!'
});
}
};
Hope this helps:
// Bad Way
const checkForMovies = (req, res) => {
const movieList = ['Braveheart', 'Highlander', 'Logan'];
movieList.forEach(movie => {
res.json(movie); // Will get Error on second loop: Can't set headers after they are sent.
})
}
// Good Way
const checkForMovies = (req, res) => {
const movieList = ['Braveheart', 'Highlander', 'Logan'];
const payload = { data: { movieList: [] } };
movieList.forEach(movie => {
payload.data.movieList.push(movie);
});
// send res once after the loop with aggregated data
res.json(payload);
}
/* GET home page. */
router.get('/', checkForMovies);

How to set nodejs to work synchronously?

var job = new cronJob('* * * * * *', function () {
Draft.find().then(data => {
var finalData = data;
finalData.forEach(function(item2) {
if (item2.scheduledTime === 'now') {
finalData.forEach(function (item) {
var psms = {
phoneno: item.senderdata,
sender: item.senderName,
message: item.message
}
var obj = psms;
var finalpostsms = obj.phoneno.split("\n").map(s => ({ ...obj,
phoneno: +s
}));
Profsms.bulkCreate(finalpostsms).then(function (data) {
if (data) {
console.log("successfully moved in profsms mysql");
} else {
console.log("failed");
}
})
});
} else {
console.log('Better you be in drafts..manual input');
}
//delete from draft
if (item2.scheduledTime === 'now') {
Draft.findOneAndRemove({
_id: item2._id
}, function (err, employee) {
if (err)
console.log('err');
console.log('Successfully deleted from draft');
});
} else {
console.log('You cant delete from drafts hahaha because no sendnow statement');
}
});
});
}, function () {
console.log('DelCron Job finished.');
}, true, 'Asia/Calcutta');
This above code, working as asynchronously.
I want the above code to be work as synchronous, need some answers. I am a newbie for JS development
Is it possible to do with async await? i dont know how to write async await code.
Your callback should be
async function(){
let data = await Draft.find();
...process data;
}
This is an async await sample code, you can modify based on your need. But first you need to use Node that support async syntax. I believe node 8 LTS is already have async/await feature.
function get() {
// your db code block
return Promise.resolve(7);
}
async function main() {
const r = await get();
console.log(r);
}
main();

How to store data in MongoDb using mongoose and async waterfall model

Hello i am new to node and i am trying to save data in mongoose. The problem is that there are 3 collections Units, Building and Section. The Schema of Building is :
var buildingsSchema=new Schema({
buildingname:String,
status:String
});
Schema of Section is :
var sectionsSchema=new Schema({
section_type:String,
buildings:{ type: Schema.Types.ObjectId, ref: 'buildings' },
status:String
});
Schema of Units is :
var unitsSchema=new Schema({
unit_type:String,
unit_num:String,
unit_ac_num:Number,
buildings:{ type: Schema.Types.ObjectId, ref: 'buildings' },
sections:{ type: Schema.Types.ObjectId, ref: 'sections' },
shares:Number
});
in Section there is an Id of Building and in Units there is Id's of both Building & Section
now i have used xlsx plugin to convert uploaded excel file to json by :-
var wb = XLSX.readFile("uploads/xls/" + req.file.filename);
data = XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]], {header:1});
and to map it into json object and saving i am using Async Waterfall Model
for (var index = 1; index < data.length - 1 ; index++) {
var ele= data[index];
// console.log(ele);
var d = { // this is an object which will hold data
record_id: ele[0],
residenceone_unit_id : ele[1],
official_unit_id: ele[2],
building: ele[3],
unit_type : ele[4],
section: ele[5],
shares: ele[6],
unit_style : ele[7]
}
// console.log(d);
var unt = new Units(); // to save units
unt = {
unit_type: d.unit_type,
unit_num: d.residenceone_unit_id,
unit_ac_num: d.official_unit_id,
buildings: '', // empty because need to put id of that particular building
sections: '', // empty because need to put id of that particular sections
shares:d.shares
}
async.waterfall([
function (callback) {
// find building first
Buildings.findOne({buildingname : ele.building})
.exec(function (err,doc) {
if (err) {
return callback(err);
}
// if no building then save one
else if (!doc) {
// console.log("Building is going to save")
var build = new Buildings();
build.buildingname = d.building;
build.status = "active";
build.save(function (err,dc) {
if (err) {
return callback(err);
}
else {
// assign id of building to unit
unt.buildings = dc._id ;
callback(null);
}
})
}
else {
// if building is there then no need to save assign id of it to units
// console.log("Building already exists;")
unt.buildings = doc._id ;
// execute second function
callback(null);
}
// callback(null);
})
},
function (callback) {
// same as building find section of that building first with building Id and section type
Sections.findOne({buildings : unt.buildings,section_type: d.section})
.exec(function (err,doc) {
if (err) {
return callback(err);
}
if (!doc) {
// if no section of that building is there then save one
// console.log("Section needs to be save")
var sect = new Sections();
sect.section_type = d.section;
sect.buildings = unt.buildings;
sect.status = "active";
sect.save(function (err,dc) {
if (err) {
return callback(err);
}
else {
// assign its id to unit
// console.log("Section is saved")
unt.sections = dc._id;
// execute third function
callback(null);
}
})
}
else {
// if there is section of that building id is available than assign id to units
// console.log("Section already exists");
unt.sections = doc._id;
// execute third function
callback(null);
}
})
},
function (callback) {
// there is no need to seaarch just need to save unit
// console.log("Units is going to save")
// console.log(unt);
unt.save(function (err, doc) {
if (err) {
} else if (doc){
// console.log("Unit Saved");
// console.log(doc);
}
})
}
])
}
}
its working but every time instead of searching of data in mongodb it save everytime. Duplication is the main problem if any other way to save units in mongodb will help me a lot.
first i have save Buildings and section :
async.every(uniqueSection,function (uS,callback) {
if (uS != undefined) {
console.log(uS);
Buildings.findOne({buildingname:uS.building}, function (err,doc) {
if (doc) {
// console.log(doc);
Sections.findOne({buildings:doc._id,section_type:uS.section},function (er,sd) {
if (sd) {
// then dont save
console.log(sd);
}
if (er) {
console.log(er);
}
if (!sd) {
// then save
var sect = new Sections();
sect.buildings = doc._id;
sect.section_type = uS.section;
sect.status = 'active';
sect.save(function (err,st) {
if(err) console.log(err);
console.log(st);
})
}
})
}
if (!doc) {
if (uS.building != undefined) {
var building = new Buildings();
building.buildingname = uS.building;
building.status = "active";
building.save(function (er,dc) {
if (dc) {
// console.log(dc);
Sections.findOne({buildings:dc._id,section_type:uS.section},function (er,sd) {
if (sd) {
// then dont save
console.log(sd);
}
if (er) {
console.log(er);
}
if (!sd) {
// then save
var sect = new Sections();
sect.buildings = dc._id;
sect.section_type = uS.section;
sect.status = 'active';
sect.save(function (err,st) {
if(err) console.log(err);
console.log(st);
})
}
})
}
if (er) {
console.log(er);
}
})
}
}
if (err) {
console.log(err);
}
})
}
})
then i have saved Units by :
async.waterfall([
function(callback) {
Buildings.findOne({buildingname:d.building}, function (err,doc) {
if (doc) {
buildingId = doc._id;
callback(null, doc);
}
if (err) {
console.log(err);
}
})
},
function(doc,callback) {
Sections.findOne({buildings: buildingId,section_type:d.section},function (er,sd) {
if (sd) {
sectionId = sd._id;
callback(null,doc,sd);
}
if (er) {
console.log(er);
}
})
},
function (bld,st,callback) {
var s = d.shares.replace(",","");
var unit = {
unit_type: d.unit_type,
unit_num: d.residenceone_unit_id,
unit_ac_num: d.official_unit_id,
buildings: bld._id,
sections: st._id,
shares: s
}
Units.findOne(unit,function (err,unt) {
if (err) {
console.log(err);
}
if(unt) {
console.log(unt)
}
if (!unt) {
var units = new Units();
units.unit_type = d.unit_type;
units.unit_num = d.residenceone_unit_id;
units.unit_ac_num = d.official_unit_id;
units.buildings = bld._id;
units.sections = st._id;
units.shares = s;
units.save(function (er,doc) {
if (er) console.log(er);
console.log(doc);
})
}
})
}
], function(err) {
console.log(err)
});

Node.js Express JSON search functionality

Using MEAN stack to create search functionality using JSON data. As shown below by connecting to mongo DB and pushing everything to the data array.
app.get('/all/', function(req, res) {
var data = [];
mongodb.MongoClient.connect(url, function(err, db) {
var position = db.collection('Namers').find();
position.forEach(function(doc, err) {
data.push(doc);
}, function() {
db.close();
res.json(data);
});
});
});
I want to do a parameter search like:
app.get('all/:search)
In order to filter the JSON information corresponding to either the Name or Codes that is in my JSON file. Which an example can be seen below:
[{"Name":"Bob", "Code":"23234"},{"Name":"Tim", "Code":"24924"}]
How would I go about achieving this using express (Node.js)?
edit: (complete code)
app.get('/all/', function(req, res) {
var data = [];
mongodb.MongoClient.connect(url, function(err, db) {
var position = db.collection('Modules').find();
position.forEach(function(doc, err) {
data.push(doc);
}, function() {
db.close();
var filtered = data.filter(function(item){
var result = false;
Object.keys(item).map(function(key){
if (item[key] == req.params.search){
result = true;
}
})
return result;
});
res.json(filtered);
});
});
});
app.get('all/:search', function(req, res) {
});
app.get('/all/', function(req, res) {
var data = [];
mongodb.MongoClient.connect(url, function(err, db) {
var position = db.collection('Modules').find();
position.forEach(function(doc, err) {
data.push(doc);
}, function() {
db.close();
res.json(data);
});
});
});
app.get('all/:search', function(req, res) {
var data = [];
mongodb.MongoClient.connect(url, function(err, db) {
var position = db.collection('Modules').find();
position.forEach(function(doc, err) {
data.push(doc);
}, function() {
db.close();
var filtered = data.filter(function(item){
var result = false;
Object.keys(item).map(function(key){
if (item[key] == req.params.search){
result = true;
}
})
return result;
});
res.json(filtered);
});
});
});