From 34c5a378a86c8e5b912deaa5eb5e975dce8dcf86 Mon Sep 17 00:00:00 2001 From: "Andres G. Aragoneses" Date: Fri, 6 Sep 2024 13:47:55 +0800 Subject: [PATCH] commitlint: start using FP patterns --- commitlint.config.ts | 110 ++++++++++++++++++++---------------------- commitlint/helpers.ts | 26 ++++++++-- commitlint/plugins.ts | 38 +++++++++------ 3 files changed, 97 insertions(+), 77 deletions(-) diff --git a/commitlint.config.ts b/commitlint.config.ts index 2f208321..96ab0892 100644 --- a/commitlint.config.ts +++ b/commitlint.config.ts @@ -6,8 +6,19 @@ let bodyMaxLineLength = 64; let headerMaxLineLength = 50; let footerMaxLineLength = 150; -function notNullStringErrorMessage(stringType: string): string { - return `This is unexpected because ${stringType} should never be null`; +function notStringErrorMessage(variableName: string): string { + return `This is unexpected because ${variableName} should have been a string`; +} + +function extractStringFromCommitlintParam( + paramName: string, + variable: any +): string { + let str = Helpers.assertNotNone( + Helpers.convertAnyToString(variable), + notStringErrorMessage(paramName) + ); + return str; } export default { @@ -64,27 +75,21 @@ export default { { rules: { "body-prose": ({ raw }: { raw: any }) => { - let rawStr = Helpers.assertNotNull( - Helpers.convertAnyToString(raw), - notNullStringErrorMessage("raw") - ); + let rawStr = extractStringFromCommitlintParam("raw", raw); return Plugins.bodyProse(rawStr); }, "commit-hash-alone": ({ raw }: { raw: any }) => { - let rawStr = Helpers.assertNotNull( - Helpers.convertAnyToString(raw), - notNullStringErrorMessage("raw") - ); + let rawStr = extractStringFromCommitlintParam("raw", raw); return Plugins.commitHashAlone(rawStr); }, "empty-wip": ({ header }: { header: any }) => { - let headerStr = Helpers.assertNotNull( - Helpers.convertAnyToString(header), - notNullStringErrorMessage("header") + let headerStr = extractStringFromCommitlintParam( + "header", + header ); return Plugins.emptyWip(headerStr); @@ -95,9 +100,9 @@ export default { _: any, maxLineLength: number ) => { - let headerStr = Helpers.assertNotNull( - Helpers.convertAnyToString(header), - notNullStringErrorMessage("header") + let headerStr = extractStringFromCommitlintParam( + "header", + header ); return Plugins.headerMaxLengthWithSuggestions( @@ -107,15 +112,12 @@ export default { }, "footer-notes-misplacement": ({ body }: { body: any }) => { - let bodyStr = Helpers.convertAnyToString(body); - return Plugins.footerNotesMisplacement(bodyStr); + let maybeBody = Helpers.convertAnyToString(body); + return Plugins.footerNotesMisplacement(maybeBody); }, "footer-refs-validity": ({ raw }: { raw: any }) => { - let rawStr = Helpers.assertNotNull( - Helpers.convertAnyToString(raw), - notNullStringErrorMessage("raw") - ); + let rawStr = extractStringFromCommitlintParam("raw", raw); return Plugins.footerRefsValidity(rawStr); }, @@ -125,54 +127,48 @@ export default { }: { header: any; }) => { - let headerStr = Helpers.assertNotNull( - Helpers.convertAnyToString(header), - notNullStringErrorMessage("header") + let headerStr = extractStringFromCommitlintParam( + "header", + header ); return Plugins.preferSlashOverBackslash(headerStr); }, "proper-issue-refs": ({ raw }: { raw: any }) => { - let rawStr = Helpers.assertNotNull( - Helpers.convertAnyToString(raw), - notNullStringErrorMessage("raw") - ); + let rawStr = extractStringFromCommitlintParam("raw", raw); return Plugins.properIssueRefs(rawStr); }, "title-uppercase": ({ header }: { header: any }) => { - let headerStr = Helpers.assertNotNull( - Helpers.convertAnyToString(header), - notNullStringErrorMessage("header") + let headerStr = extractStringFromCommitlintParam( + "header", + header ); return Plugins.titleUppercase(headerStr); }, "too-many-spaces": ({ raw }: { raw: any }) => { - let rawStr = Helpers.assertNotNull( - Helpers.convertAnyToString(raw), - notNullStringErrorMessage("raw") - ); + let rawStr = extractStringFromCommitlintParam("raw", raw); return Plugins.tooManySpaces(rawStr); }, "type-space-after-colon": ({ header }: { header: any }) => { - let headerStr = Helpers.assertNotNull( - Helpers.convertAnyToString(header), - notNullStringErrorMessage("header") + let headerStr = extractStringFromCommitlintParam( + "header", + header ); return Plugins.typeSpaceAfterColon(headerStr); }, "type-with-square-brackets": ({ header }: { header: any }) => { - let headerStr = Helpers.assertNotNull( - Helpers.convertAnyToString(header), - notNullStringErrorMessage("header") + let headerStr = extractStringFromCommitlintParam( + "header", + header ); return Plugins.typeWithSquareBrackets(headerStr); @@ -180,17 +176,18 @@ export default { // NOTE: we use 'header' instead of 'subject' as a workaround to this bug: https://github.com/conventional-changelog/commitlint/issues/3404 "subject-lowercase": ({ header }: { header: any }) => { - let headerStr = Helpers.assertNotNull( - Helpers.convertAnyToString(header), - notNullStringErrorMessage("header") + let headerStr = extractStringFromCommitlintParam( + "header", + header ); + return Plugins.subjectLowercase(headerStr); }, "type-space-after-comma": ({ header }: { header: any }) => { - let headerStr = Helpers.assertNotNull( + let headerStr = Helpers.assertNotNone( Helpers.convertAnyToString(header), - notNullStringErrorMessage("header") + notStringErrorMessage("header") ); return Plugins.typeSpaceAfterComma(headerStr); @@ -201,35 +198,32 @@ export default { _: any, maxLineLength: number ) => { - let bodyStr = Helpers.convertAnyToString(body); + let maybeBody = Helpers.convertAnyToString(body); return Plugins.bodySoftMaxLineLength( - bodyStr, + maybeBody, maxLineLength ); }, "body-paragraph-line-min-length": ({ body }: { body: any }) => { - let bodyStr = Helpers.convertAnyToString(body); + let maybeBody = Helpers.convertAnyToString(body); return Plugins.bodyParagraphLineMinLength( - bodyStr, + maybeBody, headerMaxLineLength, bodyMaxLineLength ); }, "trailing-whitespace": ({ raw }: { raw: any }) => { - let rawStr = Helpers.assertNotNull( - Helpers.convertAnyToString(raw), - notNullStringErrorMessage("raw") - ); + let rawStr = extractStringFromCommitlintParam("raw", raw); return Plugins.trailingWhitespace(rawStr); }, "type-space-before-paren": ({ header }: { header: any }) => { - let headerStr = Helpers.assertNotNull( - Helpers.convertAnyToString(header), - notNullStringErrorMessage("header") + let headerStr = extractStringFromCommitlintParam( + "header", + header ); return Plugins.typeSpaceBeforeParen(headerStr); diff --git a/commitlint/helpers.ts b/commitlint/helpers.ts index 8c788e85..3b88bf7b 100644 --- a/commitlint/helpers.ts +++ b/commitlint/helpers.ts @@ -1,3 +1,5 @@ +import { None, Some, Option, OptionStatic, TypeHelpers } from "./fpHelpers.js"; + export abstract class Helpers { public static errMessageSuffix = "\nFor reference, these are the guidelines that include our commit message conventions: https://github.com/nblockchain/conventions/blob/master/docs/WorkflowGuidelines.md"; @@ -16,9 +18,25 @@ export abstract class Helpers { } // to convert from 'any' type - public static convertAnyToString(potentialString: any): string | null { - // this null/undefined check is required, otherwise, String(null) might give us the stupid string "null" - return potentialString ? String(potentialString) : null; + public static convertAnyToString(potentialString: any): Option { + if (TypeHelpers.IsNullOrUndefined(potentialString)) { + return OptionStatic.None; + } + // this type check is required, otherwise, String(null) would give us the stupid string "null" + if (TypeHelpers.IsInstanceOf(potentialString, String)) { + return new Some(String(potentialString)); + } + return OptionStatic.None; + } + + public static assertNotNone( + text: Option, + errorMessage: string + ): string { + if (text instanceof None) { + throw new Error(errorMessage); + } + return text.value; } public static assertNotNull( @@ -72,7 +90,7 @@ export abstract class Helpers { public static findUrls(text: string) { var urlRegex = /(https?:\/\/[^\s]+)/g; - return text.match(urlRegex); + return OptionStatic.OfObj(text.match(urlRegex)); } public static isCommitUrl(url: string) { diff --git a/commitlint/plugins.ts b/commitlint/plugins.ts index 5eafec5c..da962c59 100644 --- a/commitlint/plugins.ts +++ b/commitlint/plugins.ts @@ -1,4 +1,4 @@ -import { Option, Some, None } from "./fpHelpers.js"; +import { Option, Some, None, OptionStatic } from "./fpHelpers.js"; import { abbr } from "./abbreviations.js"; import { Helpers } from "./helpers.js"; @@ -91,13 +91,18 @@ export abstract class Plugins { let urls = Helpers.findUrls(rawStr); - let gitRepo = process.env["GITHUB_REPOSITORY"]; - if (gitRepo !== undefined && urls !== null) { - for (let url of urls.entries()) { - let urlStr = url[1].toString(); - if (Helpers.isCommitUrl(urlStr) && urlStr.includes(gitRepo)) { - offence = true; - break; + let gitRepo = OptionStatic.OfObj(process.env["GITHUB_REPOSITORY"]); + if (!(gitRepo instanceof None)) { + if (!(urls instanceof None)) { + for (let url of urls.value.entries()) { + let urlStr = url[1].toString(); + if ( + Helpers.isCommitUrl(urlStr) && + urlStr.includes(gitRepo.value) + ) { + offence = true; + break; + } } } } @@ -155,10 +160,11 @@ export abstract class Plugins { return [!offence, message + Helpers.errMessageSuffix]; } - public static footerNotesMisplacement(bodyStr: string | null) { + public static footerNotesMisplacement(body: Option) { let offence = false; - if (bodyStr !== null) { + if (!(body instanceof None)) { + let bodyStr = body.value; bodyStr = Helpers.removeAllCodeBlocks(bodyStr).trim(); let seenBody = false; let seenFooter = false; @@ -377,12 +383,13 @@ export abstract class Plugins { } public static bodySoftMaxLineLength( - bodyStr: string | null, + body: Option, bodyMaxLineLength: number ) { let offence = false; - if (bodyStr !== null) { + if (!(body instanceof None)) { + let bodyStr = body.value; bodyStr = bodyStr.trim(); bodyStr = Helpers.removeAllCodeBlocks(bodyStr).trim(); @@ -434,13 +441,14 @@ export abstract class Plugins { } public static bodyParagraphLineMinLength( - bodyStr: string | null, + body: Option, paragraphLineMinLength: number, paragraphLineMaxLength: number ) { - let offence: Option = new None(); + let offence: Option = OptionStatic.None; - if (bodyStr !== null) { + if (!(body instanceof None)) { + let bodyStr = body.value; bodyStr = Helpers.removeAllCodeBlocks(bodyStr).trim(); let paragraphs = Helpers.splitByEOLs(bodyStr, 2);