UNPKG

@eighty4/changelog

Version:
80 lines (79 loc) 3.62 kB
import { writeFile } from 'node:fs/promises'; import { BadChangelogError, CliError } from "./errors.js"; import { inspectChangelog } from "./inspect.js"; import { readChangelogFile } from "./readChangelog.js"; import { isSemverVersion } from "./semver.js"; export function parseArgs(args) { const nextVersion = args.shift(); if (typeof nextVersion === 'undefined') { throw new CliError('missing version'); } if (!isSemverVersion(nextVersion)) { throw new CliError(nextVersion + ' is not a `vX.X.X` format semver'); } const opts = { changelogFile: 'CHANGELOG.md', gitTag: nextVersion, nextVersion, }; let shifted; while ((shifted = args.shift())) { switch (shifted) { case '--changelog-file': if (typeof (shifted = args.shift()) === 'undefined') { throw new CliError('--changelog-file value is missing'); } opts.changelogFile = shifted; break; case '--git-tag': if (typeof (shifted = args.shift()) === 'undefined') { throw new CliError('--git-tag value is missing'); } opts.gitTag = shifted; break; default: throw new CliError(`bad arg \`${shifted}\``); } } return opts; } export async function nextVersionRolloverFromCliArgs(args) { await nextVersionRollover(parseArgs(args)); } export async function nextVersionRollover(opts) { const changelogContent = await readChangelogFile(opts.changelogFile); const inspectResult = inspectChangelog(changelogContent); if (inspectResult.errors.length) { throw new BadChangelogError(opts.changelogFile, inspectResult.errors); } const unreleasedLinkRegex = /^.*\[Unreleased\]:\s+?(?<url>.*)$/m; const githubUrlRegex = /^https:\/\/github\.com\/(?<owner>\S+?)\/(?<name>\S+?)\/(?<path>.*)$/; const unreleasedLink = changelogContent.match(unreleasedLinkRegex)?.groups?.url; if (!unreleasedLink) { throw new Error('Unreleased url is missing'); } const unreleasedLinkGithubUrlMatch = unreleasedLink.match(githubUrlRegex); if (!unreleasedLinkGithubUrlMatch?.groups) { throw new Error('Unreleased url is malformed'); } const { owner, name, path: unreleasedGitHubUrlPath, } = unreleasedLinkGithubUrlMatch.groups; let result = changelogContent.replace(/## \[Unreleased\]/, `## [Unreleased]\n\n${inspectResult.listMarker} ???\n\n## [${opts.nextVersion}] - ${getCurrentDate()}`); if (unreleasedGitHubUrlPath.startsWith('compare/') && unreleasedGitHubUrlPath.endsWith('...HEAD')) { result = result .replace(/\.\.\.HEAD/, `...${opts.gitTag}`) .replace(/\[Unreleased\]:/, `[Unreleased]: https://github.com/${owner}/${name}/compare/${opts.gitTag}...HEAD\n[${opts.nextVersion}]:`); } else { const next = `[Unreleased]: https://github.com/${owner}/${name}/compare/${opts.gitTag}...HEAD`; const previous = `[${opts.nextVersion}]: https://github.com/${owner}/${name}/releases/tag/${opts.gitTag}`; result = result.replace(unreleasedLinkRegex, next + '\n' + previous); } await writeFile(opts.changelogFile, result); } export function getCurrentDate() { const now = new Date(); const offset = now.getTimezoneOffset(); const local = new Date(now.getTime() - offset * 60 * 1000); return `${local.getFullYear()}-${String(local.getMonth() + 1).padStart(2, '0')}-${String(local.getDate()).padStart(2, '0')}`; }