X-Git-Url: https://git.squeep.com/?a=blobdiff_plain;f=lib%2Fcommon.js;fp=lib%2Fcommon.js;h=c6c21efc705cf7581dfd351ffe8ba3a8275cbdb1;hb=281f49e3960d1562b86c56ebb75f340798623c62;hp=162b751ef23805d30bbf97eb71a69f367adf3d59;hpb=8d101705d3394039ddf2d2f3339a5e6ada911579;p=squeep-api-dingus diff --git a/lib/common.js b/lib/common.js index 162b751..c6c21ef 100644 --- a/lib/common.js +++ b/lib/common.js @@ -10,12 +10,17 @@ const uuid = require('uuid'); const Enum = require('./enum'); const { fileScope } = require('@squeep/log-helper'); +/** + * @typedef {import('node:http')} http + */ + /** * Simple ETag from data. - * @param {String} filePath (currently unused) - * @param {fs.Stats} fileStat + * @param {string} _filePath (currently unused) + * @param {object} fileStat node:fs.Stats object + * @param {number} fileStat.mtimeMs node:fs.Stats object * @param {crypto.BinaryLike} fileData content - * @returns {String} + * @returns {string} etag */ const generateETag = (_filePath, fileStat, fileData) => { const hash = crypto.createHash('sha256'); @@ -29,20 +34,21 @@ const generateETag = (_filePath, fileStat, fileData) => { /** * Access property with default. - * @param {Object} obj - * @param {String} prop + * @param {object} obj target object + * @param {string} prop target property * @param {*} def default value if prop does not exist for obj - * @return {*} + * @returns {*} property value or default */ const get = (obj, prop, def) => obj && prop && (prop in obj) ? obj[prop] : def; /** * Determine whether a client has already requested a resource, * based on If-Modified-Since and If-None-Match headers. - * @param {http.ClientRequest} req - * @param {Number} modifiedTimeMs - * @param {String} eTag - * @returns {Boolean} + * @param {http.ClientRequest} req request + * @param {(string) => string} req.getHeader header accessor + * @param {number} modifiedTimeMs ms timestamp from client + * @param {string} eTag etag from client + * @returns {boolean} whether our version matches what client knows */ const isClientCached = (req, modifiedTimeMs, eTag) => { let clientCached = false; @@ -73,9 +79,9 @@ const isClientCached = (req, modifiedTimeMs, eTag) => { /** * Shallow merge for enums, to be called by derived constructor. * Expects only one-level deep, is not recursive! - * @param {Object} origEnum - * @param {Object} additionalEnum - * @returns {Object} + * @param {object} origEnum enum object to be extended + * @param {object} additionalEnum enum object to add + * @returns {object} lightly merged enum object */ const mergeEnum = (origEnum, additionalEnum) => { for (const e of Object.keys(additionalEnum)) { @@ -93,17 +99,19 @@ const mergeEnum = (origEnum, additionalEnum) => { /** * Isolate the general category of an http status code. - * @param {Number} statusCode - * @returns {Number} + * @param {number} statusCode of response + * @returns {number} status category */ const httpStatusCodeClass = (statusCode) => Math.floor(statusCode / 100); const _isObject = (obj) => obj && typeof obj === 'object'; const _isArray = (obj) => Array.isArray(obj); + /** * Return a new object with all objects combined, later properties taking precedence. - * @param {...Object} objects - * @returns {Object} + * Arrays are concated. + * @param {...object} objects to be merged onto a new object + * @returns {object} new merged object */ const mergeDeep = (...objects) => { return objects.reduce((acc, obj) => { @@ -126,9 +134,9 @@ const mergeDeep = (...objects) => { /** * Return a new object with selected props. - * @param {Object} obj - * @param {String[]} props - * @returns {Object} + * @param {object} obj source object + * @param {string[]} props list of property names + * @returns {object} object with selected properties */ const pick = (obj, props) => { const picked = {}; @@ -142,19 +150,22 @@ const pick = (obj, props) => { /** * Store all properties in defaultOptions on target from either options or defaultOptions. - * @param {Object} target - * @param {Object} defaultOptions - * @param {Object} options + * @param {object} target object to populate + * @param {object} defaultOptions object with default property values + * @param {object} options object with potential overrides for defaults + * @returns {object} object with properties */ const setOptions = (target, defaultOptions, options) => { Object.assign(target, defaultOptions, pick(options, Object.keys(defaultOptions))); + return target; }; /** * Return a two-item list of src, split at first delimiter encountered. - * @param {String} src - * @param {String} delimiter - * @param {String} fill trailing stand-in if no delimiter in src + * @param {string} src source + * @param {string} delimiter delimiter + * @param {string} fill trailing stand-in if no delimiter in src + * @returns {string[]} [before-first-delimiter, rest-or-fill] */ const splitFirst = (src, delimiter, fill) => { const idx = src.indexOf(delimiter); @@ -167,7 +178,7 @@ const splitFirst = (src, delimiter, fill) => { /** * Generate a new request identifier, a time/host-based uuid. - * @returns {String} + * @returns {string} uuid */ const requestId = () => { return uuid.v1(); @@ -175,8 +186,8 @@ const requestId = () => { /** * Merges folded header lines - * @param {String[]} lines - * @returns {String} + * @param {string[]} lines header lines + * @returns {string} unfolded header string */ const unfoldHeaderLines = (lines) => { const foldedLineRE = /^(\t| +)(.*)$/; @@ -195,18 +206,19 @@ const unfoldHeaderLines = (lines) => { }; /** - * Adds a new cookie. - * @param {http.ServerResponse} res - * @param {String} name - * @param {String} value - * @param {Object=} opt - * @param {String=} opt.domain - * @param {Date=} opt.expires - * @param {Boolean=} opt.httpOnly - * @param {Number=} opt.maxAge - * @param {String=} opt.path - * @param {String=} opt.sameSite - * @param {Boolean=} opt.secure + * Adds a new set-cookie header value to response, with supplied data. + * @param {http.ServerResponse} res response + * @param {(string, string) => void} res.appendHeader sets header values + * @param {string} name cookie name + * @param {string} value cookie value + * @param {object=} opt cookie options + * @param {string=} opt.domain cookie domain + * @param {Date=} opt.expires cookie expiration + * @param {boolean=} opt.httpOnly cookie client visibility + * @param {number=} opt.maxAge cookie lifetime + * @param {string=} opt.path cookie path + * @param {string=} opt.sameSite cookie sharing + * @param {boolean=} opt.secure cookie security */ function addCookie(res, name, value, opt = {}) { const options = {