-
Notifications
You must be signed in to change notification settings - Fork 0
/
helperFunctions.js
101 lines (94 loc) · 4.77 KB
/
helperFunctions.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
const fetch = require('node-fetch'); // JS's default fetch doesn't work server side in Node.js
/**
* @param {Object[]} searchArray Array of objects, each with an id property, to search
* @param {Number[]} idArray Array of ids to search with
* @return {Object[]} Array of objects from searchArray with an id value in idArray
*/
module.exports.searchId = function (searchArray, idArray) {
const results = [];
for (const item of searchArray) {
if (idArray.includes(item.id)) {
results.push(item);
}
}
return results;
};
/**
* @param {Object[]} searchArray Array of objects, each with an id property, to search
* @param {String | undefined} paramId Id provided to API via URL parameter as a String (takes precedence over queryIds) (i.e. '1' from /cards/1)
* @param {String} queryIds Comma-separated list of ids provided to API via ids query string in URL (i.e. '1,2,3' from /cards?ids=1,2,3)
* @return {Object[]} Array of objects from searchArray with an id value either matching paramId or, failing that, in queryIds
*/
module.exports.handleIdUrl = function (searchArray, paramId, queryIds) {
if (paramId !== undefined) { // req.params.id in app.js will return undefined if user didn't provide a parameter in the url
const paramIdNum = Number(paramId);
return module.exports.searchId(searchArray, [paramIdNum]); // searchId(...) requires idArray to be an Array
} else if (queryIds) {
// split queryIds string by commas using RegExp and mapping while also converting each id to a Number
const commaSplitRegExp = /, */;
const queryIdsArray = queryIds.split(commaSplitRegExp).map((s) => Number(s));
return module.exports.searchId(searchArray, queryIdsArray);
} else {
return searchArray;
}
};
/**
* @param {String} redditUrl Basic Reddit URL to fetch data from (without any .json added - the function does this)
* @return {Promise<{score: Number, author: String, replies: Object[] | String} | undefined>} Required data (more is returned than is typed here) from Reddit's JSON API (redditJSON[1].data.children[0].data) if no error occurred during fetching process (e.g. url doesn't exist); else, undefined
*/
module.exports.getRedditData = async function (redditUrl) {
const redditJSONUrl = redditUrl + '.json';
const redditResponse = await fetch(redditJSONUrl);
const redditJSON = await redditResponse.json();
if (!redditJSON.error) {
return redditJSON[1].data.children[0].data;
} else {
return undefined;
}
};
/**
* @param {Object} cardObj The card object to modify with the newRedditData provided
* @param {{score: Number, author: String, replies: Object[] | String}} newRedditData The Object returned by getRedditData(...) above; including score, author and replies properties
*/
module.exports.updateCardRedditData = function (cardObj, newRedditData) {
cardObj.redditData = {};
cardObj.redditData.score = newRedditData.score;
cardObj.redditData.author = newRedditData.author;
if (newRedditData.replies !== '') { // Reddit inserts an empty string (rather than an empty Array) if a comment has no replies
// noinspection JSUnresolvedVariable - otherwise I would have to type to end of the earth to satisfy WebStorm
cardObj.redditData.replies = newRedditData.replies.data.children.length;
} else {
cardObj.redditData.replies = 0;
}
};
/**
* @param {Object[]} currentArray Array containing all current objects (each with an id property) to consider
* @return {Number} The largest currently in use index + 1 - i.e. this new id can be safely used for a new object to add to currentArray
*/
module.exports.getNewId = function (currentArray) {
if (currentArray.length > 0) {
const usedIds = currentArray.map(e => e.id); // creates an array of all the objects' ids
return Math.max(...usedIds) + 1; // new id generated by adding 1 to max element in current cards list
} else {
return 0; // list is empty so start the ids at 0
}
};
/**
* @param {Object} reqBody JS Object returned from req.body
* @param {String[]} propertiesArray Array of property names reqBody should possess
* @param {Response} response express Response object to set status on and return json to client through
* @returns Boolean true if reqBody has all the properties specified in propertiesArray; else, false
*/
module.exports.requestBodyIsValid = function (reqBody, propertiesArray, response) {
for (const prop of propertiesArray) {
if (!Object.prototype.hasOwnProperty.call(reqBody, prop)) {
response.status(400); // 400 Bad Request
response.json({
error: 'request-body-field-missing',
message: `The request body did not include all the expected fields of ${propertiesArray.join(', ')}`
});
return false; // return false to abort the processing of this request
}
}
return true; // body is valid, continue processing
};