UNPKG

@nlabs/lex

Version:
129 lines (127 loc) 16.2 kB
import { execa } from "execa"; import { writeFileSync } from "fs"; import capitalize from "lodash/capitalize.js"; import isEmpty from "lodash/isEmpty.js"; import merge from "lodash/merge.js"; import { DateTime } from "luxon"; import { join as pathJoin } from "path"; import { createSpinner } from "../utils/app.js"; import { log } from "../utils/log.js"; const createChangelog = async ({ cliName, config, outputFile = "changelog.tmp.md", quiet }) => { const spinner = createSpinner(quiet); const gitOptions = [ "log", "-3", '--pretty=format:{"authorName": "%an", "authorEmail": "%ae", "hashShort": "%h", "hashFull": "%H", "tag": "%D", "date": %ct, "subject": "%s","comments": "%b"}[lex_break]' ]; try { const git = await execa("git", gitOptions, { encoding: "utf8" }); const { stdout } = git; const entries = stdout.split("[lex_break]").filter((item) => !!item); const gitJson = JSON.parse( `[${entries.join(",")}]`.replace(/"[^"]*(?:""[^"]*)*"/g, (match) => match.replace(/\n/g, "[lex_break]")) ); const commitContent = {}; let version = "Unreleased"; gitJson.forEach((item) => { const { comments, authorEmail, authorName, date, hashFull, hashShort, tag } = item; const formatDate = DateTime.fromMillis(date).toFormat("DDD"); if (!isEmpty(tag)) { const refs = tag.split(", "); const updatedVersion = refs.reduce((ref, tagItem) => { let updatedRef = ref; if (updatedRef === "" && tagItem.includes("tag: v")) { updatedRef = tagItem.replace("tag: v", "").trim(); } return updatedRef; }, ""); if (!isEmpty(updatedVersion)) { version = updatedVersion; commitContent[version] = { date: formatDate, version: updatedVersion }; } } if (!commitContent[version]) { commitContent[version] = { list: {} }; } const subjectLines = comments.split("[lex_break]"); const topics = {}; for (let idx = 0, len = subjectLines.length; idx < len; idx++) { const nextLine = subjectLines[idx]; const formatLine = nextLine.trim(); const headerPattern = /^(\w*)(?:\(([\w$.\- *]*)\))?: (.*)$/; const matches = formatLine.match(headerPattern); if (matches) { const itemType = capitalize(matches[1]); const itemScope = matches[2]; const itemDetails = matches[3]; const details = { authorEmail, authorName, details: itemDetails, hashFull, hashShort, type: itemType }; if (!topics[itemScope]) { topics[itemScope] = { [itemType]: [details] }; } else { topics[itemScope][itemType].push(details); } } } commitContent[version] = merge(commitContent[version], { list: topics }); }); const formatLog = Object.keys(commitContent).reduce((content, versionKey) => { const { date, list = {}, version: version2 } = commitContent[versionKey]; const formatScopes = Object.keys(list); let updatedContent = content; const versionLabel = version2 ? version2 : "Unreleased"; const headerLabels = [versionLabel]; if (date) { headerLabels.push(`(${date})`); } updatedContent += ` ## ${headerLabels.join(" ")} `; formatScopes.forEach((scopeName) => { updatedContent += ` ### ${scopeName} `; const itemList = list[scopeName]; const itemNames = Object.keys(itemList); itemNames.forEach((itemName) => { updatedContent += `* ${itemName} `; itemList[itemName].forEach((changes) => { const { authorEmail, authorName, details, hashFull, hashShort } = changes; const { gitUrl } = config; let hash = `#${hashShort}`; if (!isEmpty(gitUrl)) { let commitPath = "commits"; if (gitUrl.includes("github.com")) { commitPath = "commit"; } hash = `[#${hashShort}](${gitUrl}/${commitPath}/${hashFull})`; } updatedContent += ` * ${details} ([${authorName}](mailto:${authorEmail}) in ${hash}) `; }); }); }); return updatedContent; }, "# Changes\n"); const logFile = pathJoin(process.cwd(), outputFile); writeFileSync(logFile, formatLog); spinner.succeed("Git change log complete!"); return 0; } catch (error) { log(` ${cliName} Error: ${error.message}`, "error", quiet); spinner.fail("Failed generating change log!"); return error.status; } }; export { createChangelog }; //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vc3JjL2NyZWF0ZS9jaGFuZ2Vsb2cudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbIi8qKlxuICogQ29weXJpZ2h0IChjKSAyMDE4LVByZXNlbnQsIE5pdHJvZ2VuIExhYnMsIEluYy5cbiAqIENvcHlyaWdodHMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLiBTZWUgdGhlIGFjY29tcGFueWluZyBMSUNFTlNFIGZpbGUgZm9yIHRlcm1zLlxuICovXG5pbXBvcnQge2V4ZWNhfSBmcm9tICdleGVjYSc7XG5pbXBvcnQge3dyaXRlRmlsZVN5bmN9IGZyb20gJ2ZzJztcbmltcG9ydCBjYXBpdGFsaXplIGZyb20gJ2xvZGFzaC9jYXBpdGFsaXplLmpzJztcbmltcG9ydCBpc0VtcHR5IGZyb20gJ2xvZGFzaC9pc0VtcHR5LmpzJztcbmltcG9ydCBtZXJnZSBmcm9tICdsb2Rhc2gvbWVyZ2UuanMnO1xuaW1wb3J0IHtEYXRlVGltZX0gZnJvbSAnbHV4b24nO1xuaW1wb3J0IHtqb2luIGFzIHBhdGhKb2lufSBmcm9tICdwYXRoJztcblxuXG5pbXBvcnQge2NyZWF0ZVNwaW5uZXJ9IGZyb20gJy4uL3V0aWxzL2FwcC5qcyc7XG5pbXBvcnQge2xvZ30gZnJvbSAnLi4vdXRpbHMvbG9nLmpzJztcblxuZXhwb3J0IGNvbnN0IGNyZWF0ZUNoYW5nZWxvZyA9IGFzeW5jICh7Y2xpTmFtZSwgY29uZmlnLCBvdXRwdXRGaWxlID0gJ2NoYW5nZWxvZy50bXAubWQnLCBxdWlldH0pOiBQcm9taXNlPG51bWJlcj4gPT4ge1xuICBjb25zdCBzcGlubmVyID0gY3JlYXRlU3Bpbm5lcihxdWlldCk7XG5cbiAgY29uc3QgZ2l0T3B0aW9uczogc3RyaW5nW10gPSBbXG4gICAgJ2xvZycsXG4gICAgJy0zJyxcbiAgICAnLS1wcmV0dHk9Zm9ybWF0OntcImF1dGhvck5hbWVcIjogXCIlYW5cIiwgXCJhdXRob3JFbWFpbFwiOiBcIiVhZVwiLCBcImhhc2hTaG9ydFwiOiBcIiVoXCIsIFwiaGFzaEZ1bGxcIjogXCIlSFwiLCBcInRhZ1wiOiBcIiVEXCIsIFwiZGF0ZVwiOiAlY3QsIFwic3ViamVjdFwiOiBcIiVzXCIsXCJjb21tZW50c1wiOiBcIiViXCJ9W2xleF9icmVha10nXG4gIF07XG5cbiAgdHJ5IHtcbiAgICBjb25zdCBnaXQgPSBhd2FpdCBleGVjYSgnZ2l0JywgZ2l0T3B0aW9ucywge2VuY29kaW5nOiAndXRmOCd9KTtcblxuICAgIGNvbnN0IHtzdGRvdXR9ID0gZ2l0O1xuICAgIGNvbnN0IGVudHJpZXM6IHN0cmluZ1tdID0gc3Rkb3V0LnNwbGl0KCdbbGV4X2JyZWFrXScpLmZpbHRlcigoaXRlbSkgPT4gISFpdGVtKTtcbiAgICBjb25zdCBnaXRKc29uID0gSlNPTi5wYXJzZShcbiAgICAgIChgWyR7ZW50cmllcy5qb2luKCcsJyl9XWApLnJlcGxhY2UoL1wiW15cIl0qKD86XCJcIlteXCJdKikqXCIvZywgKG1hdGNoKSA9PiBtYXRjaC5yZXBsYWNlKC9cXG4vZywgJ1tsZXhfYnJlYWtdJykpXG4gICAgKTtcbiAgICBjb25zdCBjb21taXRDb250ZW50ID0ge307XG4gICAgbGV0IHZlcnNpb246IHN0cmluZyA9ICdVbnJlbGVhc2VkJztcblxuICAgIGdpdEpzb24uZm9yRWFjaCgoaXRlbSkgPT4ge1xuICAgICAgY29uc3Qge2NvbW1lbnRzLCBhdXRob3JFbWFpbCwgYXV0aG9yTmFtZSwgZGF0ZSwgaGFzaEZ1bGwsIGhhc2hTaG9ydCwgdGFnfSA9IGl0ZW07XG4gICAgICBjb25zdCBmb3JtYXREYXRlOiBzdHJpbmcgPSBEYXRlVGltZS5mcm9tTWlsbGlzKGRhdGUpLnRvRm9ybWF0KCdEREQnKTtcblxuICAgICAgaWYoIWlzRW1wdHkodGFnKSkge1xuICAgICAgICBjb25zdCByZWZzID0gdGFnLnNwbGl0KCcsICcpO1xuICAgICAgICBjb25zdCB1cGRhdGVkVmVyc2lvbjogc3RyaW5nID0gcmVmcy5yZWR1Y2UoKHJlZjogc3RyaW5nLCB0YWdJdGVtOiBzdHJpbmcpID0+IHtcbiAgICAgICAgICBsZXQgdXBkYXRlZFJlZjogc3RyaW5nID0gcmVmO1xuXG4gICAgICAgICAgaWYodXBkYXRlZFJlZiA9PT0gJycgJiYgdGFnSXRlbS5pbmNsdWRlcygndGFnOiB2JykpIHtcbiAgICAgICAgICAgIHVwZGF0ZWRSZWYgPSB0YWdJdGVtLnJlcGxhY2UoJ3RhZzogdicsICcnKS50cmltKCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgcmV0dXJuIHVwZGF0ZWRSZWY7XG4gICAgICAgIH0sICcnKTtcblxuICAgICAgICBpZighaXNFbXB0eSh1cGRhdGVkVmVyc2lvbikpIHtcbiAgICAgICAgICB2ZXJzaW9uID0gdXBkYXRlZFZlcnNpb247XG4gICAgICAgICAgY29tbWl0Q29udGVudFt2ZXJzaW9uXSA9IHtkYXRlOiBmb3JtYXREYXRlLCB2ZXJzaW9uOiB1cGRhdGVkVmVyc2lvbn07XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYoIWNvbW1pdENvbnRlbnRbdmVyc2lvbl0pIHtcbiAgICAgICAgY29tbWl0Q29udGVudFt2ZXJzaW9uXSA9IHtsaXN0OiB7fX07XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHN1YmplY3RMaW5lczogc3RyaW5nW10gPSBjb21tZW50cy5zcGxpdCgnW2xleF9icmVha10nKTtcbiAgICAgIGNvbnN0IHRvcGljcyA9IHt9O1xuXG5cbiAgICAgIGZvcihsZXQgaWR4OiBudW1iZXIgPSAwLCBsZW46IG51bWJlciA9IHN1YmplY3RMaW5lcy5sZW5ndGg7IGlkeCA8IGxlbjsgaWR4KyspIHtcbiAgICAgICAgY29uc3QgbmV4dExpbmU6IHN0cmluZyA9IHN1YmplY3RMaW5lc1tpZHhdO1xuICAgICAgICBjb25zdCBmb3JtYXRMaW5lOiBzdHJpbmcgPSBuZXh0TGluZS50cmltKCk7XG4gICAgICAgIGNvbnN0IGhlYWRlclBhdHRlcm46IFJlZ0V4cCA9IC9eKFxcdyopKD86XFwoKFtcXHckLlxcLSAqXSopXFwpKT86ICguKikkLztcbiAgICAgICAgY29uc3QgbWF0Y2hlcyA9IGZvcm1hdExpbmUubWF0Y2goaGVhZGVyUGF0dGVybik7XG5cbiAgICAgICAgaWYobWF0Y2hlcykge1xuICAgICAgICAgIGNvbnN0IGl0ZW1UeXBlOiBzdHJpbmcgPSBjYXBpdGFsaXplKG1hdGNoZXNbMV0pO1xuICAgICAgICAgIGNvbnN0IGl0ZW1TY29wZTogc3RyaW5nID0gbWF0Y2hlc1syXTtcbiAgICAgICAgICBjb25zdCBpdGVtRGV0YWlsczogc3RyaW5nID0gbWF0Y2hlc1szXTtcbiAgICAgICAgICBjb25zdCBkZXRhaWxzID0ge1xuICAgICAgICAgICAgYXV0aG9yRW1haWwsXG4gICAgICAgICAgICBhdXRob3JOYW1lLFxuICAgICAgICAgICAgZGV0YWlsczogaXRlbURldGFpbHMsXG4gICAgICAgICAgICBoYXNoRnVsbCxcbiAgICAgICAgICAgIGhhc2hTaG9ydCxcbiAgICAgICAgICAgIHR5cGU6IGl0ZW1UeXBlXG4gICAgICAgICAgfTtcblxuICAgICAgICAgIGlmKCF0b3BpY3NbaXRlbVNjb3BlXSkge1xuICAgICAgICAgICAgdG9waWNzW2l0ZW1TY29wZV0gPSB7W2l0ZW1UeXBlXTogW2RldGFpbHNdfTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdG9waWNzW2l0ZW1TY29wZV1baXRlbVR5cGVdLnB1c2goZGV0YWlscyk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGNvbW1pdENvbnRlbnRbdmVyc2lvbl0gPSBtZXJnZShjb21taXRDb250ZW50W3ZlcnNpb25dLCB7bGlzdDogdG9waWNzfSk7XG4gICAgfSk7XG5cbiAgICBjb25zdCBmb3JtYXRMb2c6IHN0cmluZyA9IE9iamVjdC5rZXlzKGNvbW1pdENvbnRlbnQpLnJlZHVjZSgoY29udGVudDogc3RyaW5nLCB2ZXJzaW9uS2V5OiBzdHJpbmcpID0+IHtcbiAgICAgIGNvbnN0IHtkYXRlLCBsaXN0ID0ge30sIHZlcnNpb259ID0gY29tbWl0Q29udGVudFt2ZXJzaW9uS2V5XTtcbiAgICAgIGNvbnN0IGZvcm1hdFNjb3Blczogc3RyaW5nW10gPSBPYmplY3Qua2V5cyhsaXN0KTtcbiAgICAgIGxldCB1cGRhdGVkQ29udGVudDogc3RyaW5nID0gY29udGVudDtcblxuICAgICAgY29uc3QgdmVyc2lvbkxhYmVsOiBzdHJpbmcgPSB2ZXJzaW9uID8gdmVyc2lvbiA6ICdVbnJlbGVhc2VkJztcbiAgICAgIGNvbnN0IGhlYWRlckxhYmVsczogc3RyaW5nW10gPSBbdmVyc2lvbkxhYmVsXTtcbiAgICAgIGlmKGRhdGUpIHtcbiAgICAgICAgaGVhZGVyTGFiZWxzLnB1c2goYCgke2RhdGV9KWApO1xuICAgICAgfVxuXG4gICAgICB1cGRhdGVkQ29udGVudCArPSBgXFxuIyMgJHtoZWFkZXJMYWJlbHMuam9pbignICcpfVxcbmA7XG5cbiAgICAgIGZvcm1hdFNjb3Blcy5mb3JFYWNoKChzY29wZU5hbWU6IHN0cmluZykgPT4ge1xuICAgICAgICB1cGRhdGVkQ29udGVudCArPSBgXFxuIyMjICR7c2NvcGVOYW1lfVxcblxcbmA7XG5cbiAgICAgICAgLy8gR2V0IHRoZSB0b3BpYyBuYW1lXG4gICAgICAgIGNvbnN0IGl0ZW1MaXN0ID0gbGlzdFtzY29wZU5hbWVdO1xuICAgICAgICBjb25zdCBpdGVtTmFtZXM6IHN0cmluZ1tdID0gT2JqZWN0LmtleXMoaXRlbUxpc3QpO1xuXG4gICAgICAgIGl0ZW1OYW1lcy5mb3JFYWNoKChpdGVtTmFtZTogc3RyaW5nKSA9PiB7XG4gICAgICAgICAgdXBkYXRlZENvbnRlbnQgKz0gYCogJHtpdGVtTmFtZX1cXG5gO1xuXG4gICAgICAgICAgaXRlbUxpc3RbaXRlbU5hbWVdLmZvckVhY2goKGNoYW5nZXMpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHthdXRob3JFbWFpbCwgYXV0aG9yTmFtZSwgZGV0YWlscywgaGFzaEZ1bGwsIGhhc2hTaG9ydH0gPSBjaGFuZ2VzO1xuICAgICAgICAgICAgY29uc3Qge2dpdFVybH0gPSBjb25maWc7XG4gICAgICAgICAgICBsZXQgaGFzaDogc3RyaW5nID0gYCMke2hhc2hTaG9ydH1gO1xuXG4gICAgICAgICAgICBpZighaXNFbXB0eShnaXRVcmwpKSB7XG4gICAgICAgICAgICAgIGxldCBjb21taXRQYXRoOiBzdHJpbmcgPSAnY29tbWl0cyc7XG5cbiAgICAgICAgICAgICAgaWYoZ2l0VXJsLmluY2x1ZGVzKCdnaXRodWIuY29tJykpIHtcbiAgICAgICAgICAgICAgICBjb21taXRQYXRoID0gJ2NvbW1pdCc7XG4gICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICBoYXNoID0gYFsjJHtoYXNoU2hvcnR9XSgke2dpdFVybH0vJHtjb21taXRQYXRofS8ke2hhc2hGdWxsfSlgO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB1cGRhdGVkQ29udGVudCArPSBgICAqICR7ZGV0YWlsc30gKFske2F1dGhvck5hbWV9XShtYWlsdG86JHthdXRob3JFbWFpbH0pIGluICR7aGFzaH0pXFxuYDtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcblxuICAgICAgcmV0dXJuIHVwZGF0ZWRDb250ZW50O1xuICAgIH0sICcjIENoYW5nZXNcXG4nKTtcblxuICAgIGNvbnN0IGxvZ0ZpbGU6IHN0cmluZyA9IHBhdGhKb2luKHByb2Nlc3MuY3dkKCksIG91dHB1dEZpbGUpO1xuICAgIHdyaXRlRmlsZVN5bmMobG9nRmlsZSwgZm9ybWF0TG9nKTtcbiAgICBzcGlubmVyLnN1Y2NlZWQoJ0dpdCBjaGFuZ2UgbG9nIGNvbXBsZXRlIScpO1xuXG4gICAgLy8gS2lsbCBwcm9jZXNzXG4gICAgcmV0dXJuIDA7XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgLy8gRGlzcGxheSBlcnJvciBtZXNzYWdlXG4gICAgbG9nKGBcXG4ke2NsaU5hbWV9IEVycm9yOiAke2Vycm9yLm1lc3NhZ2V9YCwgJ2Vycm9yJywgcXVpZXQpO1xuXG4gICAgLy8gU3RvcCBzcGlubmVyXG4gICAgc3Bpbm5lci5mYWlsKCdGYWlsZWQgZ2VuZXJhdGluZyBjaGFuZ2UgbG9nIScpO1xuXG4gICAgLy8gS2lsbCBwcm9jZXNzXG4gICAgcmV0dXJuIGVycm9yLnN0YXR1cztcbiAgfVxufTsiXSwKICAibWFwcGluZ3MiOiAiQUFJQSxTQUFRLGFBQVk7QUFDcEIsU0FBUSxxQkFBb0I7QUFDNUIsT0FBTyxnQkFBZ0I7QUFDdkIsT0FBTyxhQUFhO0FBQ3BCLE9BQU8sV0FBVztBQUNsQixTQUFRLGdCQUFlO0FBQ3ZCLFNBQVEsUUFBUSxnQkFBZTtBQUcvQixTQUFRLHFCQUFvQjtBQUM1QixTQUFRLFdBQVU7QUFFWCxNQUFNLGtCQUFrQixPQUFPLEVBQUMsU0FBUyxRQUFRLGFBQWEsb0JBQW9CLE1BQUssTUFBdUI7QUFDbkgsUUFBTSxVQUFVLGNBQWMsS0FBSztBQUVuQyxRQUFNLGFBQXVCO0FBQUEsSUFDM0I7QUFBQSxJQUNBO0FBQUEsSUFDQTtBQUFBLEVBQ0Y7QUFFQSxNQUFJO0FBQ0YsVUFBTSxNQUFNLE1BQU0sTUFBTSxPQUFPLFlBQVksRUFBQyxVQUFVLE9BQU0sQ0FBQztBQUU3RCxVQUFNLEVBQUMsT0FBTSxJQUFJO0FBQ2pCLFVBQU0sVUFBb0IsT0FBTyxNQUFNLGFBQWEsRUFBRSxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUMsSUFBSTtBQUM3RSxVQUFNLFVBQVUsS0FBSztBQUFBLE1BQ2xCLElBQUksUUFBUSxLQUFLLEdBQUcsQ0FBQyxJQUFLLFFBQVEsd0JBQXdCLENBQUMsVUFBVSxNQUFNLFFBQVEsT0FBTyxhQUFhLENBQUM7QUFBQSxJQUMzRztBQUNBLFVBQU0sZ0JBQWdCLENBQUM7QUFDdkIsUUFBSSxVQUFrQjtBQUV0QixZQUFRLFFBQVEsQ0FBQyxTQUFTO0FBQ3hCLFlBQU0sRUFBQyxVQUFVLGFBQWEsWUFBWSxNQUFNLFVBQVUsV0FBVyxJQUFHLElBQUk7QUFDNUUsWUFBTSxhQUFxQixTQUFTLFdBQVcsSUFBSSxFQUFFLFNBQVMsS0FBSztBQUVuRSxVQUFHLENBQUMsUUFBUSxHQUFHLEdBQUc7QUFD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