From c227cd81cb2097db3a96f6ed27c7f0fbd608035b Mon Sep 17 00:00:00 2001 From: Frazer Smith Date: Mon, 18 Dec 2023 20:09:44 +0000 Subject: [PATCH] style: jsdoc comments must be complete sentences --- .eslintrc.js | 1 + scripts/license-checker.js | 2 +- src/plugins/clean-object/index.js | 2 +- .../convert-date-param-operator/index.js | 2 +- src/plugins/db/index.js | 2 +- src/plugins/hashed-bearer-auth/index.js | 2 +- src/routes/admin/access/bearer-token/index.js | 32 +++++++++---------- .../admin/access/bearer-token/schema.js | 2 +- src/routes/contact/index.js | 26 +++++++-------- src/routes/contact/schema.js | 4 +-- src/server.js | 14 ++++---- src/server.test.js | 2 +- 12 files changed, 46 insertions(+), 45 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index c548e074..9a8de79e 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -47,6 +47,7 @@ module.exports = { "@eslint-community/eslint-comments/require-description": "error", "import/no-extraneous-dependencies": "error", "jsdoc/check-syntax": "error", + "jsdoc/require-description-complete-sentence": "error", "jsdoc/require-hyphen-before-param-description": "error", "no-multiple-empty-lines": ["error", { max: 1 }], "prefer-destructuring": ["error", { object: true, array: false }], diff --git a/scripts/license-checker.js b/scripts/license-checker.js index 0b7d6de9..c974f5fa 100644 --- a/scripts/license-checker.js +++ b/scripts/license-checker.js @@ -18,7 +18,7 @@ async function checkLicenses() { console.log("Checking licenses of direct production dependencies..."); /** - * List of deprecated copyleft license identifiers + * List of deprecated copyleft license identifiers. * @see {@link https://spdx.org/licenses/#deprecated | SPDX Deprecated License Identifiers} */ const deprecatedLicenseList = [ diff --git a/src/plugins/clean-object/index.js b/src/plugins/clean-object/index.js index c5097998..037140d3 100644 --- a/src/plugins/clean-object/index.js +++ b/src/plugins/clean-object/index.js @@ -17,7 +17,7 @@ async function plugin(server) { * @description Recursively removes key value pairs from an object where the value is null * or undefined. * @param {object} [object] - Object to be parsed and cleaned. - * @returns {object} cleaned object. + * @returns {object} Cleaned object. */ function cleanObject(object = {}) { Object.keys(object).forEach((key) => { diff --git a/src/plugins/convert-date-param-operator/index.js b/src/plugins/convert-date-param-operator/index.js index e071bf18..c58a7ce6 100644 --- a/src/plugins/convert-date-param-operator/index.js +++ b/src/plugins/convert-date-param-operator/index.js @@ -25,7 +25,7 @@ async function plugin(server) { * @author Frazer Smith * @description Converts date param operator to corresponding value. * @param {string} operator - Date param operator, in any letter case. - * @returns {string} converted date param operator. + * @returns {string} Converted date param operator. */ function convDateParamOperator(operator) { return operatorMap[operator.toLowerCase()] || "="; diff --git a/src/plugins/db/index.js b/src/plugins/db/index.js index 44392c37..a87f7f07 100644 --- a/src/plugins/db/index.js +++ b/src/plugins/db/index.js @@ -27,7 +27,7 @@ async function plugin(server, options) { /** * Attempt to connect to DB and check connection string - * is valid, will throw error if not + * is valid, will throw error if not. */ await pool.query("SELECT version();"); diff --git a/src/plugins/hashed-bearer-auth/index.js b/src/plugins/hashed-bearer-auth/index.js index ee265a9b..f119fa54 100644 --- a/src/plugins/hashed-bearer-auth/index.js +++ b/src/plugins/hashed-bearer-auth/index.js @@ -32,7 +32,7 @@ async function plugin(server) { /** * Database client packages return results in different structures, - * (mssql uses recordsets, pg uses rows) thus the optional chaining + * (mssql uses recordsets, pg uses rows) thus the optional chaining. */ const tokens = results.recordsets?.[0] ?? results.rows; diff --git a/src/routes/admin/access/bearer-token/index.js b/src/routes/admin/access/bearer-token/index.js index ef46efdc..9d52a4d6 100644 --- a/src/routes/admin/access/bearer-token/index.js +++ b/src/routes/admin/access/bearer-token/index.js @@ -42,7 +42,7 @@ const keyDashRegex = /-/gu; * @param {string} result.created - Date bearer token record was created. * @param {string} [result.last_updated] - Date bearer token record was last updated. * @param {object} [req] - Fastify Request object. - * @returns {object} bearer token record. + * @returns {object} Bearer token record. */ function buildBearerTokenRecord(result, req) { return { @@ -60,7 +60,7 @@ function buildBearerTokenRecord(result, req) { hash: result.hash, /** * Database client packages return result in different structures: - * mssql returns JSON as string; pg returns JSON as object + * mssql returns JSON as string; pg returns JSON as object. */ scopes: typeof result.scopes === "string" @@ -105,7 +105,7 @@ async function route(server, options) { /** * Database client packages return results in different structures, - * (mssql uses rowsAffected, pg uses rowCount) thus the optional chaining + * (mssql uses rowsAffected, pg uses rowCount) thus the optional chaining. */ if (results.rowsAffected?.[0] > 0 || results.rowCount > 0) { return res.status(204).send(); @@ -133,7 +133,7 @@ async function route(server, options) { /** * Database client packages return results in different structures, - * (mssql uses recordsets, pg uses rows) thus the optional chaining + * (mssql uses recordsets, pg uses rows) thus the optional chaining. */ const token = results.recordsets?.[0] ?? results.rows; @@ -214,8 +214,8 @@ async function route(server, options) { } /** - * access.expires - Datetime when bearer token expires, - * can be a string or array + * Access.expires - Datetime when bearer token expires, + * can be a string or array. */ if (req.query?.["access.expires"]) { const expires = Array.isArray(req.query["access.expires"]) @@ -237,8 +237,8 @@ async function route(server, options) { } /** - * meta.created - Datetime when bearer token record was created, - * can be a string or array + * Meta.created - Datetime when bearer token record was created, + * can be a string or array. */ if (req.query?.["meta.created"]) { const created = Array.isArray(req.query["meta.created"]) @@ -260,8 +260,8 @@ async function route(server, options) { } /** - * meta.last_updated - Last modified datetime of bearer token record, - * can be a string or array + * Meta.last_updated - Last modified datetime of bearer token record, + * can be a string or array. */ if (req.query?.["meta.last_updated"]) { const lastUpdated = Array.isArray( @@ -291,8 +291,8 @@ async function route(server, options) { const perPage = parseInt(req.query.per_page, 10); /** - * Stops SQL query with empty WHERE clause from being made and throwing errors - * @todo replace with JSON Schema subschemas when supported + * Stops SQL query with empty WHERE clause from being made and throwing errors. + * @todo Replace with JSON Schema subschemas when supported. */ if (whereArray.length === 0) { return res.badRequest( @@ -312,7 +312,7 @@ async function route(server, options) { /** * Database client packages return results in different structures, - * (mssql uses recordsets, pg uses rows) thus the optional chaining + * (mssql uses recordsets, pg uses rows) thus the optional chaining. */ const count = results.recordsets?.[0]?.[0]?.total ?? @@ -358,7 +358,7 @@ async function route(server, options) { * generated strings. * * Underscores are also good as they allow for the whole token to be selected - * when double-clicking on it, as opposed to dashes + * when double-clicking on it, as opposed to dashes. */ const key = `ydhcc_${randomUUID().replace(keyDashRegex, "_")}`; @@ -378,7 +378,7 @@ async function route(server, options) { /** * Database client packages return results in different structures, - * (mssql uses recordsets, pg uses rows) thus the optional chaining + * (mssql uses recordsets, pg uses rows) thus the optional chaining. */ let token = results.recordsets?.[0] ?? results.rows; @@ -391,7 +391,7 @@ async function route(server, options) { token: key, /** * Database client packages return results in different structures: - * mssql returns JSON as string; pg returns JSON as object + * mssql returns JSON as string; pg returns JSON as object. */ scopes: typeof token.scopes === "string" diff --git a/src/routes/admin/access/bearer-token/schema.js b/src/routes/admin/access/bearer-token/schema.js index 3311ca8e..aa9a97be 100644 --- a/src/routes/admin/access/bearer-token/schema.js +++ b/src/routes/admin/access/bearer-token/schema.js @@ -7,7 +7,7 @@ const tags = ["System administration"]; /** * JSON Schema expects a String, `fluent-json-schema` - * converts this from a RegExp to a String + * converts this from a RegExp to a String. */ const dateTimeSearchPattern = // eslint-disable-next-line security/detect-unsafe-regex -- False positive diff --git a/src/routes/contact/index.js b/src/routes/contact/index.js index 42489726..41294ec4 100644 --- a/src/routes/contact/index.js +++ b/src/routes/contact/index.js @@ -40,7 +40,7 @@ const sqlLikeWildRegex = /\*/gu; * @param {string} results.created - Date community contact record was created. * @param {string} [results.last_updated] - Date community contact record was last updated. * @param {object} [req] - Fastify Request object. - * @returns {object} community contact record. + * @returns {object} Community contact record. */ function buildContact(results, req) { return { @@ -60,7 +60,7 @@ function buildContact(results, req) { }, /** * Database client packages return results in different structures: - * mssql returns JSON as string; pg returns JSON as object + * mssql returns JSON as string; pg returns JSON as object. */ telecom: typeof results.telecom === "string" @@ -139,7 +139,7 @@ async function route(server, options) { /** * Database client packages return results in different structures, - * (mssql uses rowsAffected, pg uses rowCount) thus the optional chaining + * (mssql uses rowsAffected, pg uses rowCount) thus the optional chaining. */ if (results.rowsAffected?.[0] > 0 || results.rowCount > 0) { return res.status(204).send(); @@ -177,7 +177,7 @@ async function route(server, options) { /** * Database client packages return results in different structures, - * (mssql uses recordsets, pg uses rows) thus the optional chaining + * (mssql uses recordsets, pg uses rows) thus the optional chaining. */ const contact = results.recordsets?.[0] ?? results.rows; @@ -262,8 +262,8 @@ async function route(server, options) { } /** - * meta.created - Datetime when community contact record was created, - * can be a string or array + * Meta.created - Datetime when community contact record was created, + * can be a string or array. */ if (req.query?.["meta.created"]) { const created = Array.isArray(req.query["meta.created"]) @@ -285,8 +285,8 @@ async function route(server, options) { } /** - * meta.last_updated - Last modified datetime of community contact record, - * can be a string or array + * Meta.last_updated - Last modified datetime of community contact record, + * can be a string or array. */ if (req.query?.["meta.last_updated"]) { const lastUpdated = Array.isArray( @@ -316,8 +316,8 @@ async function route(server, options) { const perPage = parseInt(req.query.per_page, 10); /** - * Stops SQL query with empty WHERE clause from being made and throwing errors - * @todo replace with JSON Schema subschemas when supported + * Stops SQL query with empty WHERE clause from being made and throwing errors. + * @todo Replace with JSON Schema subschemas when supported. */ if (whereArray.length === 0) { return res.badRequest( @@ -337,7 +337,7 @@ async function route(server, options) { /** * Database client packages return results in different structures, - * (mssql uses recordsets, pg uses rows) thus the optional chaining + * (mssql uses recordsets, pg uses rows) thus the optional chaining. */ const count = results.recordsets?.[0]?.[0]?.total ?? @@ -398,7 +398,7 @@ async function route(server, options) { /** * Database client packages return results in different structures, - * (mssql uses recordsets, pg uses rows) thus the optional chaining + * (mssql uses recordsets, pg uses rows) thus the optional chaining. */ let contact = results.recordsets?.[0] ?? results.rows; @@ -457,7 +457,7 @@ async function route(server, options) { /** * Database client packages return results in different structures, - * (mssql uses rowsAffected, pg uses rowCount) thus the optional chaining + * (mssql uses rowsAffected, pg uses rowCount) thus the optional chaining. */ if (results.rowsAffected?.[0] > 0 || results.rowCount > 0) { return res.status(204).send(); diff --git a/src/routes/contact/schema.js b/src/routes/contact/schema.js index 5d330f8d..1c69b812 100644 --- a/src/routes/contact/schema.js +++ b/src/routes/contact/schema.js @@ -6,7 +6,7 @@ const tags = ["Community contacts"]; /** * JSON Schema expects a String, `fluent-json-schema` - * converts this from a RegExp to a String + * converts this from a RegExp to a String. */ const dateTimeSearchPattern = // eslint-disable-next-line security/detect-unsafe-regex -- False positive @@ -25,7 +25,7 @@ const dateTimeSearchPatternExamples = [ /** * JSON Schema expects a String, `fluent-json-schema` - * converts this from a RegExp to a String + * converts this from a RegExp to a String. */ // eslint-disable-next-line security/detect-unsafe-regex -- False positive const phoneNumberPattern = /^\+?(?:\d\s?){10,12}$/u; diff --git a/src/server.js b/src/server.js index ffb2509f..8a72525e 100644 --- a/src/server.js +++ b/src/server.js @@ -32,7 +32,7 @@ const sharedSchemas = require("./plugins/shared-schemas"); async function plugin(server, config) { /** * Stop routes from accepting 'text/plain' POST/PUT/PATCH - * requests by removing included default parser + * requests by removing included default parser. */ server.removeContentTypeParser("text/plain"); @@ -87,7 +87,7 @@ async function plugin(server, config) { * Helmet sets `x-xss-protection` and `content-security-policy` by default. * These are only useful for HTML/XML content; the only CSP directive that * is of use to other content is "frame-ancestors 'none'" to stop responses - * from being wrapped in iframes and used for clickjacking attacks + * from being wrapped in iframes and used for clickjacking attacks. */ .addHook("onSend", async (_req, res, payload) => { if ( @@ -130,7 +130,7 @@ async function plugin(server, config) { await serializedContext /** * Encapsulate plugins and routes into secured child context, so that other - * routes do not inherit bearer token auth plugin (if enabled) + * routes do not inherit bearer token auth plugin (if enabled). */ .register(async (securedContext) => { // Protect routes with Bearer token auth if enabled @@ -148,7 +148,7 @@ async function plugin(server, config) { /** * Encapsulate the admin/access routes into a child context, so that the other - * routes do not inherit basic auth plugin + * routes do not inherit basic auth plugin. */ .register(async (adminContext) => { await adminContext @@ -180,7 +180,7 @@ async function plugin(server, config) { /** * Encapsulate the docs routes into a child context, so that the * CSP can be relaxed, and cache enabled, without affecting - * security of other routes + * security of other routes. */ .register(async (publicContext) => { const relaxedHelmetConfig = structuredClone(config.helmet); @@ -234,13 +234,13 @@ async function plugin(server, config) { /** * Catch 5xx errors, log them, and return a generic 500 * response. This avoids leaking internal server error details - * to the client + * to the client. */ if ( (err.statusCode >= 500 && err.statusCode !== 503) || /** * Uncaught errors will have a res.statusCode but not - * an err.statusCode as @fastify/sensible sets that + * an err.statusCode as @fastify/sensible sets that. */ (res.statusCode === 200 && !err.statusCode) ) { diff --git a/src/server.test.js b/src/server.test.js index 5f8a452d..a740bce4 100644 --- a/src/server.test.js +++ b/src/server.test.js @@ -582,7 +582,7 @@ describe("Server deployment", () => { afterAll(async () => server.close()); describe("/admin/access/bearer-token/:id route", () => { - /** @todo use `it.concurrent.each()` once it is no longer experimental */ + /** @todo Use `it.concurrent.each()` once it is no longer experimental. */ it.each([ { testName: "basic auth username invalid",