From f890fc673f842470c721ae6668e148fd13072b7f Mon Sep 17 00:00:00 2001 From: Paul Bienkowski Date: Wed, 18 Nov 2020 23:00:08 +0100 Subject: [PATCH] refactor: switch to async/await syntax in track routes --- package.json | 2 +- routes/api/tracks.js | 724 +++++++++++++++++++++---------------------- 2 files changed, 348 insertions(+), 378 deletions(-) diff --git a/package.json b/package.json index 7e38eaa..efd9a6a 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "start": "node ./app.js", "dev": "nodemon ./app.js", "mongo:stop": "docker stop realworld-mongo && docker rm realworld-mongo", - "autoformat": "eslint --fix logic", + "autoformat": "eslint --fix logic routes/api/tracks.js", "test": "jest" }, "repository": { diff --git a/routes/api/tracks.js b/routes/api/tracks.js index 94e9654..12c5a1d 100644 --- a/routes/api/tracks.js +++ b/routes/api/tracks.js @@ -9,313 +9,286 @@ const currentTracks = new Map(); const TrackInfo = require('../../logic/TrackInfo'); const { addPointsToTrack } = require('../../logic/tracks'); +const wrapRoute = (fn) => async (req, res, next) => { + try { + return await fn(req, res); + } catch (err) { + next(err); + } +}; + // Preload track objects on routes with ':track' -router.param('track', function (req, res, next, slug) { - Track.findOne({ slug: slug }) - .populate('author') - .then(function (track) { - if (!track) { - return res.sendStatus(404); - } +router.param('track', async (req, res, next, slug) => { + try { + const track = await Track.findOne({ slug }).populate('author'); - req.track = track; + if (!track) { + return res.sendStatus(404); + } - return next(); - }) - .catch(next); + req.track = track; + + return next(); + } catch (err) { + return next(err); + } }); -router.param('comment', function (req, res, next, id) { - Comment.findById(id) - .then(function (comment) { - if (!comment) { - return res.sendStatus(404); - } +router.param('comment', async (req, res, next, id) => { + try { + const comment = await Comment.findById(id); - req.comment = comment; + if (!comment) { + return res.sendStatus(404); + } - return next(); - }) - .catch(next); + req.comment = comment; + + return next(); + } catch (err) { + return next(err); + } }); -router.get('/', auth.optional, function (req, res, next) { - const query = {}; - let limit = 20; - let offset = 0; +router.get( + '/', + auth.optional, + wrapRoute(async (req, res) => { + const query = {}; + let limit = 20; + let offset = 0; - if (typeof req.query.limit !== 'undefined') { - limit = req.query.limit; - } + if (typeof req.query.limit !== 'undefined') { + limit = req.query.limit; + } - if (typeof req.query.offset !== 'undefined') { - offset = req.query.offset; - } + if (typeof req.query.offset !== 'undefined') { + offset = req.query.offset; + } - if (typeof req.query.tag !== 'undefined') { - query.tagList = { $in: [req.query.tag] }; - } + if (typeof req.query.tag !== 'undefined') { + query.tagList = { $in: [req.query.tag] }; + } - Promise.all([ - req.query.author ? User.findOne({ username: req.query.author }) : null, - req.query.favorited ? User.findOne({ username: req.query.favorited }) : null, - ]) - .then(function (results) { - const author = results[0]; - const favoriter = results[1]; + const [author, favoriter] = await Promise.all([ + req.query.author ? User.findOne({ username: req.query.author }) : null, + req.query.favorited ? User.findOne({ username: req.query.favorited }) : null, + ]); - if (author) { - query.author = author._id; - } + if (author) { + query.author = author._id; + } - if (favoriter) { - query._id = { $in: favoriter.favorites }; - } else if (req.query.favorited) { - query._id = { $in: [] }; - } + if (favoriter) { + query._id = { $in: favoriter.favorites }; + } else if (req.query.favorited) { + query._id = { $in: [] }; + } - return Promise.all([ - Track.find(query) - .limit(Number(limit)) - .skip(Number(offset)) - .sort({ createdAt: 'desc' }) - .populate('author') - .where('visible') - .equals(true) - .exec(), - Track.countDocuments(query).exec(), - req.payload ? User.findById(req.payload.id) : null, - ]).then(function (results) { - const tracks = results[0]; - // const tracksCount = results[1]; - const user = results[2]; - // console.log(tracks); - const retTracks = []; - for (const t of tracks) { - // console.log(t); - // if (t.author.areTracksVisibleForAll || t.author == user) { - retTracks.push(t); - // } - } - return res.json({ - tracks: retTracks.map(function (track) { - return track.toJSONFor(user); - }), - tracksCount: retTracks.length, - }); - }); - }) - .catch(next); -}); + const results = await Promise.all([ + Track.find(query) + .limit(Number(limit)) + .skip(Number(offset)) + .sort({ createdAt: 'desc' }) + .populate('author') + .where('visible') + .equals(true) + .exec(), + Track.countDocuments(query).exec(), + req.payload ? User.findById(req.payload.id) : null, + ]); -router.get('/feed', auth.required, function (req, res, next) { - let limit = 20; - let offset = 0; + const [tracks, tracksCount, user] = results; - if (typeof req.query.limit !== 'undefined') { - limit = req.query.limit; - } + return res.json({ + tracks: tracks.map((track) => track.toJSONFor(user)), + tracksCount, + }); + }), +); - if (typeof req.query.offset !== 'undefined') { - offset = req.query.offset; - } +router.get( + '/feed', + auth.required, + wrapRoute(async (req, res) => { + let limit = 20; + let offset = 0; + + if (typeof req.query.limit !== 'undefined') { + limit = req.query.limit; + } + + if (typeof req.query.offset !== 'undefined') { + offset = req.query.offset; + } + + const user = await User.findById(req.payload.id); - User.findById(req.payload.id).then(function (user) { if (!user) { return res.sendStatus(401); } - if (user.following !== '') { - Promise.all([ - Track.find({ author: { $in: user.following } }) - .limit(Number(limit)) - .skip(Number(offset)) - .populate('author') - .exec(), - Track.countDocuments({ author: { $in: user.following } }), - ]) - .then(function (results) { - const tracks = results[0]; - const tracksCount = results[1]; - return res.json({ - tracks: tracks.map(function (track) { - return track.toJSONFor(user); - }), - tracksCount: tracksCount, - }); - }) - .catch(next); - } else { - Promise.all([ - Track.find({ author: { $in: req.payload.id } }) - .limit(Number(limit)) - .skip(Number(offset)) - .populate('author') - .exec(), - Track.countDocuments({ author: { $in: req.payload.id } }), - ]) - .then(function (results) { - const tracks = results[0]; - const tracksCount = results[1]; + const showByUserIds = [req.payload.id, ...(user.following || [])]; - return res.json({ - tracks: tracks.map(function (track) { - return track.toJSONFor(user); - }), - tracksCount: tracksCount, - }); - }) - .catch(next); + const [tracks, tracksCount] = await Promise.all([ + Track.find({ author: { $in: showByUserIds } }) + .limit(Number(limit)) + .skip(Number(offset)) + .populate('author') + .exec(), + Track.countDocuments({ author: { $in: showByUserIds } }), + ]); + + return res.json({ + tracks: tracks.map(function (track) { + return track.toJSONFor(user); + }), + tracksCount: tracksCount, + }); + }), +); + +router.post( + '/', + auth.required, + wrapRoute(async (req, res) => { + const user = await User.findById(req.payload.id); + + if (!user) { + return res.sendStatus(401); } - }); -}); -router.post('/', auth.required, function (req, res, next) { - User.findById(req.payload.id) - .then(function (user) { - if (!user) { - return res.sendStatus(401); - } + const track = new Track(req.body.track); + const trackData = new TrackData(); + track.trackData = trackData._id; - const track = new Track(req.body.track); - const trackData = new TrackData(); - track.trackData = trackData._id; + track.author = user; + track.visible = track.author.areTracksVisibleForAll; + await trackData.save(); - track.author = user; - track.visible = track.author.areTracksVisibleForAll; - trackData.save(function (err) { - if (err) { - console.log('failed to save trackData'); - } - }); + await track.save(); - return track.save().then(function () { - // console.log(track.author); - return res.json({ track: track.toJSONFor(user) }); - }); - }) - .catch(next); -}); + // console.log(track.author); + return res.json({ track: track.toJSONFor(user) }); + }), +); -router.post('/add', auth.optional, function (req, res, next) { - // console.log("Add"); +router.post( + '/add', + auth.optional, + wrapRoute(async (req, res) => { + // console.log("Add"); - // console.log(req.payload); - User.findById(req.body.id) - .then(function (user) { - if (!user) { - return res.sendStatus(401); - } + // console.log(req.payload); + const user = await User.findById(req.body.id); - let ti = null; - if (currentTracks.has(req.body.id)) ti = currentTracks.get(req.body.id); + if (!user) { + return res.sendStatus(401); + } - // console.log("TI" + ti); - // console.log("TILen" + ti.trackData.points.length); - // console.log("TITrack" + ti.track); - // console.log("Body" + req.body.track.body); - if (ti.track) { - addPointsToTrack(ti, req.body.track.body); - // console.log("TLen" + ti.trackData.points.length); - ti.track.author = user; - } + let ti = null; + if (currentTracks.has(req.body.id)) ti = currentTracks.get(req.body.id); - // return track.save().then(function(){ - // console.log(track.author); - // return res.json({ track: track.toJSONFor(user) }); - return res.sendStatus(200); - // }); - }) - .catch(next); -}); - -router.post('/begin', auth.optional, function (req, res, next) { - // console.log("Begin"); - // console.log(req.payload); - User.findById(req.body.id) - .then(function (user) { - if (!user) { - return res.sendStatus(401); - } - - if (currentTracks.has(req.body.id)) currentTracks.delete(req.body.id); // delete old parts if there are leftovers - const ti = new TrackInfo(new Track(req.body.track), new TrackData()); - ti.track.trackData = ti.trackData._id; - currentTracks.set(req.body.id, ti); - - // console.log("addToTrack"+req.body); - - addPointsToTrack(ti, ti.track.body); - - // console.log("TLen" + ti.track); - // console.log("TLen" + ti.trackData); + // console.log("TI" + ti); + // console.log("TILen" + ti.trackData.points.length); + // console.log("TITrack" + ti.track); + // console.log("Body" + req.body.track.body); + if (ti.track) { + addPointsToTrack(ti, req.body.track.body); // console.log("TLen" + ti.trackData.points.length); - - // console.log(track.trackData.points[0].date); ti.track.author = user; + } - // return track.save().then(function () { - // console.log(track.author); - return res.sendStatus(200); - // }); - }) - .catch(next); -}); + // await track.save() + // return res.json({ track: track.toJSONFor(user) }); + return res.sendStatus(200); + }), +); -router.post('/end', auth.optional, function (req, res, next) { - // console.log("End"); - // console.log(req.payload); - User.findById(req.body.id) - .then(function (user) { - if (!user) { - return res.sendStatus(401); - } +router.post( + '/begin', + auth.optional, + wrapRoute(async (req, res) => { + // console.log("Begin"); + // console.log(req.payload); + const user = await User.findById(req.body.id); - let ti; - if (currentTracks.has(req.body.id)) { - ti = currentTracks.get(req.body.id); - addPointsToTrack(ti, req.body.track.body); - } else { - ti = new TrackInfo(new Track(req.body.track), new TrackData()); - ti.track.trackData = ti.trackData._id; - addPointsToTrack(ti, ti.track.body); - } - if (ti.track) { - ti.track.author = user; - } + if (!user) { + return res.sendStatus(401); + } - currentTracks.delete(req.body.id); // we are done with this track, it is complete + if (currentTracks.has(req.body.id)) currentTracks.delete(req.body.id); // delete old parts if there are leftovers + const ti = new TrackInfo(new Track(req.body.track), new TrackData()); + ti.track.trackData = ti.trackData._id; + currentTracks.set(req.body.id, ti); + + // console.log("addToTrack"+req.body); + + addPointsToTrack(ti, ti.track.body); + + // console.log("TLen" + ti.track); + // console.log("TLen" + ti.trackData); + // console.log("TLen" + ti.trackData.points.length); + + // console.log(track.trackData.points[0].date); + ti.track.author = user; + + // await track.save() + // console.log(track.author); + return res.sendStatus(200); + }), +); + +router.post( + '/end', + auth.optional, + wrapRoute(async (req, res) => { + const user = await User.findById(req.body.id); + if (!user) { + return res.sendStatus(401); + } + + let ti; + if (currentTracks.has(req.body.id)) { + ti = currentTracks.get(req.body.id); + addPointsToTrack(ti, req.body.track.body); + } else { + ti = new TrackInfo(new Track(req.body.track), new TrackData()); + ti.track.trackData = ti.trackData._id; + addPointsToTrack(ti, ti.track.body); + } + if (ti.track) { ti.track.author = user; + } - // console.log(track); - // console.log("user:"+user); - return ti.track.save().then(function () { - // console.log("TLen" + ti.track); - // console.log("TLen" + ti.trackData); - // console.log("TLen" + ti.trackData.points.length); - ti.trackData.save(function (err) { - if (err) { - console.log('failed to save trackData' + err.toString()); - } - }); + currentTracks.delete(req.body.id); // we are done with this track, it is complete + ti.track.author = user; - console.log('successfulSave:'); - return res.sendStatus(200); - }); - }) - .catch(next); -}); + // console.log(track); + // console.log("user:"+user); + await ti.track.save(); + + // console.log("TLen" + ti.track); + // console.log("TLen" + ti.trackData); + // console.log("TLen" + ti.trackData.points.length); + await ti.trackData.save(); + + return res.sendStatus(200); + }), +); // return a track -router.get('/:track', auth.optional, function (req, res, next) { - Promise.all([req.payload ? User.findById(req.payload.id) : null, req.track.populate('author').execPopulate()]) - .then(function (results) { - const user = results[0]; - - return res.json({ track: req.track.toJSONFor(user, { body: true }) }); - }) - .catch(next); -}); +router.get( + '/:track', + auth.optional, + wrapRoute(async (req, res) => { + const [user] = await Promise.all([ + req.payload ? User.findById(req.payload.id) : null, + req.track.populate('author').execPopulate(), + ]); + return res.json({ track: req.track.toJSONFor(user, { body: true }) }); + }), +); // update track router.put('/:track', auth.required, async function (req, res, next) { @@ -356,140 +329,137 @@ router.put('/:track', auth.required, async function (req, res, next) { }); // delete track -router.delete('/:track', auth.required, function (req, res, next) { - User.findById(req.payload.id) - .then(function (user) { - if (!user) { - return res.sendStatus(401); - } - if (req.track.author._id.toString() === req.payload.id.toString()) { - TrackData.findByIdAndDelete(req.track.trackData, function (err, td) { - console.log('doneDelete'); - }); // delet our track data - return req.track.remove().then(function () { - return res.sendStatus(204); - }); - } else { - return res.sendStatus(403); - } - }) - .catch(next); -}); +router.delete( + '/:track', + auth.required, + wrapRoute(async (req, res) => { + const user = await User.findById(req.payload.id); + if (!user) { + return res.sendStatus(401); + } + if (req.track.author._id.toString() === req.payload.id.toString()) { + await TrackData.findByIdAndDelete(req.track.trackData); + await req.track.remove(); + return res.sendStatus(204); + } else { + return res.sendStatus(403); + } + }), +); // Favorite an track -router.post('/:track/favorite', auth.required, function (req, res, next) { - const trackId = req.track._id; +router.post( + '/:track/favorite', + auth.required, + wrapRoute(async (req, res) => { + const trackId = req.track._id; - User.findById(req.payload.id) - .then(function (user) { - if (!user) { - return res.sendStatus(401); - } + const user = await User.findById(req.payload.id); + if (!user) { + return res.sendStatus(401); + } - return user.favorite(trackId).then(function () { - return req.track.updateFavoriteCount().then(function (track) { - return res.json({ track: track.toJSONFor(user) }); - }); - }); - }) - .catch(next); -}); + await user.favorite(trackId); + const track = await req.track.updateFavoriteCount(); + return res.json({ track: track.toJSONFor(user) }); + }), +); // Unfavorite an track -router.delete('/:track/favorite', auth.required, function (req, res, next) { - const trackId = req.track._id; +router.delete( + '/:track/favorite', + auth.required, + wrapRoute(async (req, res) => { + const trackId = req.track._id; - User.findById(req.payload.id) - .then(function (user) { - if (!user) { - return res.sendStatus(401); - } + const user = await User.findById(req.payload.id); + if (!user) { + return res.sendStatus(401); + } - return user.unfavorite(trackId).then(function () { - return req.track.updateFavoriteCount().then(function (track) { - return res.json({ track: track.toJSONFor(user) }); - }); - }); - }) - .catch(next); -}); + await user.unfavorite(trackId); + const track = await req.track.updateFavoriteCount(); + return res.json({ track: track.toJSONFor(user) }); + }), +); // return an track's comments -router.get('/:track/comments', auth.optional, function (req, res, next) { - Promise.resolve(req.payload ? User.findById(req.payload.id) : null) - .then(function (user) { - return req.track - .populate({ - path: 'comments', - populate: { - path: 'author', +router.get( + '/:track/comments', + auth.optional, + wrapRoute(async (req, res) => { + const user = await Promise.resolve(req.payload ? User.findById(req.payload.id) : null); + + await req.track + .populate({ + path: 'comments', + populate: { + path: 'author', + }, + options: { + sort: { + createdAt: 'desc', }, - options: { - sort: { - createdAt: 'desc', - }, - }, - }) - .execPopulate() - .then(function (track) { - return res.json({ - comments: req.track.comments.map(function (comment) { - return comment.toJSONFor(user); - }), - }); - }); - }) - .catch(next); -}); + }, + }) + .execPopulate(); + + return res.json({ + comments: req.track.comments.map(function (comment) { + return comment.toJSONFor(user); + }), + }); + }), +); // create a new comment -router.post('/:track/comments', auth.required, function (req, res, next) { - User.findById(req.payload.id) - .then(function (user) { - if (!user) { - return res.sendStatus(401); - } +router.post( + '/:track/comments', + auth.required, + wrapRoute(async (req, res) => { + const user = await User.findById(req.payload.id); + if (!user) { + return res.sendStatus(401); + } - const comment = new Comment(req.body.comment); - comment.track = req.track; - comment.author = user; + const comment = new Comment(req.body.comment); + comment.track = req.track; + comment.author = user; - return comment.save().then(function () { - req.track.comments.push(comment); + await comment.save(); - return req.track.save().then(function (track) { - res.json({ comment: comment.toJSONFor(user) }); - }); - }); - }) - .catch(next); -}); + req.track.comments.push(comment); -router.delete('/:track/comments/:comment', auth.required, function (req, res, next) { - if (req.comment.author.toString() === req.payload.id.toString()) { - req.track.comments.remove(req.comment._id); - req.track - .save() - .then(Comment.find({ _id: req.comment._id }).remove().exec()) - .then(function () { - res.sendStatus(204); - }); - } else { - res.sendStatus(403); - } -}); + await req.track.save(); + return res.json({ comment: comment.toJSONFor(user) }); + }), +); + +router.delete( + '/:track/comments/:comment', + auth.required, + wrapRoute(async (req, res) => { + if (req.comment.author.toString() === req.payload.id.toString()) { + req.track.comments.remove(req.comment._id); + await req.track.save(); + await Comment.find({ _id: req.comment._id }).remove(); + res.sendStatus(204); + } else { + res.sendStatus(403); + } + }), +); // return an track's trackData -router.get('/:track/TrackData', auth.optional, function (req, res, next) { - Promise.resolve(req.payload ? User.findById(req.payload.id) : null) - .then(function (user) { - // console.log("requestTrackData"+req.track); - TrackData.findById(req.track.trackData, function (err, trackData) { - // console.log({trackData: trackData}); - return res.json({ trackData: trackData }); - }); - }) - .catch(next); -}); +router.get( + '/:track/TrackData', + auth.optional, + wrapRoute(async (req, res) => { + // console.log("requestTrackData"+req.track); + const trackData = await TrackData.findById(req.track.trackData); + // console.log({trackData: trackData}); + return res.json({ trackData: trackData }); + }), +); module.exports = router;