@metamask/auto-changelog
Advanced tools
Comparing version 3.1.0 to 3.3.0
import { ChangeCategory, Version } from './constants'; | ||
/** | ||
* Formatter function that formats a Markdown changelog string. | ||
*/ | ||
export declare type Formatter = (changelog: string) => string; | ||
declare type ReleaseMetadata = { | ||
@@ -39,6 +43,3 @@ /** | ||
export default class Changelog { | ||
private _releases; | ||
private _changes; | ||
private _repoUrl; | ||
private _tagPrefix; | ||
#private; | ||
/** | ||
@@ -50,6 +51,8 @@ * Construct an empty changelog. | ||
* @param options.tagPrefix - The prefix used in tags before the version number. | ||
* @param options.formatter - A function that formats the changelog string. | ||
*/ | ||
constructor({ repoUrl, tagPrefix, }: { | ||
constructor({ repoUrl, tagPrefix, formatter, }: { | ||
repoUrl: string; | ||
tagPrefix?: string; | ||
formatter?: Formatter; | ||
}); | ||
@@ -56,0 +59,0 @@ /** |
"use strict"; | ||
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { | ||
if (kind === "m") throw new TypeError("Private method is not writable"); | ||
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); | ||
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); | ||
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; | ||
}; | ||
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { | ||
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); | ||
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); | ||
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); | ||
}; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
var _Changelog_releases, _Changelog_changes, _Changelog_repoUrl, _Changelog_tagPrefix, _Changelog_formatter; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -177,8 +189,15 @@ const semver_1 = __importDefault(require("semver")); | ||
* @param options.tagPrefix - The prefix used in tags before the version number. | ||
* @param options.formatter - A function that formats the changelog string. | ||
*/ | ||
constructor({ repoUrl, tagPrefix = 'v', }) { | ||
this._releases = []; | ||
this._changes = { [constants_1.unreleased]: {} }; | ||
this._repoUrl = repoUrl; | ||
this._tagPrefix = tagPrefix; | ||
constructor({ repoUrl, tagPrefix = 'v', formatter = (changelog) => changelog, }) { | ||
_Changelog_releases.set(this, void 0); | ||
_Changelog_changes.set(this, void 0); | ||
_Changelog_repoUrl.set(this, void 0); | ||
_Changelog_tagPrefix.set(this, void 0); | ||
_Changelog_formatter.set(this, void 0); | ||
__classPrivateFieldSet(this, _Changelog_releases, [], "f"); | ||
__classPrivateFieldSet(this, _Changelog_changes, { [constants_1.unreleased]: {} }, "f"); | ||
__classPrivateFieldSet(this, _Changelog_repoUrl, repoUrl, "f"); | ||
__classPrivateFieldSet(this, _Changelog_tagPrefix, tagPrefix, "f"); | ||
__classPrivateFieldSet(this, _Changelog_formatter, formatter, "f"); | ||
} | ||
@@ -207,12 +226,12 @@ /** | ||
} | ||
else if (this._changes[version]) { | ||
else if (__classPrivateFieldGet(this, _Changelog_changes, "f")[version]) { | ||
throw new Error(`Release already exists: '${version}'`); | ||
} | ||
this._changes[version] = {}; | ||
__classPrivateFieldGet(this, _Changelog_changes, "f")[version] = {}; | ||
const newRelease = { version, date, status }; | ||
if (addToStart) { | ||
this._releases.unshift(newRelease); | ||
__classPrivateFieldGet(this, _Changelog_releases, "f").unshift(newRelease); | ||
} | ||
else { | ||
this._releases.push(newRelease); | ||
__classPrivateFieldGet(this, _Changelog_releases, "f").push(newRelease); | ||
} | ||
@@ -243,8 +262,8 @@ } | ||
} | ||
else if (version !== undefined && !this._changes[version]) { | ||
else if (version !== undefined && !__classPrivateFieldGet(this, _Changelog_changes, "f")[version]) { | ||
throw new Error(`Specified release version does not exist: '${version}'`); | ||
} | ||
const release = version | ||
? this._changes[version] | ||
: this._changes[constants_1.unreleased]; | ||
? __classPrivateFieldGet(this, _Changelog_changes, "f")[version] | ||
: __classPrivateFieldGet(this, _Changelog_changes, "f")[constants_1.unreleased]; | ||
if (!release[category]) { | ||
@@ -271,7 +290,7 @@ release[category] = []; | ||
migrateUnreleasedChangesToRelease(version) { | ||
const releaseChanges = this._changes[version]; | ||
const releaseChanges = __classPrivateFieldGet(this, _Changelog_changes, "f")[version]; | ||
if (!releaseChanges) { | ||
throw new Error(`Specified release version does not exist: '${version}'`); | ||
} | ||
const unreleasedChanges = this._changes[constants_1.unreleased]; | ||
const unreleasedChanges = __classPrivateFieldGet(this, _Changelog_changes, "f")[constants_1.unreleased]; | ||
for (const category of Object.keys(unreleasedChanges)) { | ||
@@ -288,3 +307,3 @@ if (releaseChanges[category]) { | ||
} | ||
this._changes[constants_1.unreleased] = {}; | ||
__classPrivateFieldGet(this, _Changelog_changes, "f")[constants_1.unreleased] = {}; | ||
} | ||
@@ -297,3 +316,3 @@ /** | ||
getReleases() { | ||
return this._releases; | ||
return __classPrivateFieldGet(this, _Changelog_releases, "f"); | ||
} | ||
@@ -331,3 +350,3 @@ /** | ||
getReleaseChanges(version) { | ||
return this._changes[version]; | ||
return __classPrivateFieldGet(this, _Changelog_changes, "f")[version]; | ||
} | ||
@@ -340,3 +359,3 @@ /** | ||
getUnreleasedChanges() { | ||
return this._changes[constants_1.unreleased]; | ||
return __classPrivateFieldGet(this, _Changelog_changes, "f")[constants_1.unreleased]; | ||
} | ||
@@ -349,11 +368,13 @@ /** | ||
toString() { | ||
return `${changelogTitle} | ||
const changelog = `${changelogTitle} | ||
${changelogDescription} | ||
${stringifyReleases(this._releases, this._changes)} | ||
${stringifyReleases(__classPrivateFieldGet(this, _Changelog_releases, "f"), __classPrivateFieldGet(this, _Changelog_changes, "f"))} | ||
${stringifyLinkReferenceDefinitions(this._repoUrl, this._tagPrefix, this._releases)}`; | ||
${stringifyLinkReferenceDefinitions(__classPrivateFieldGet(this, _Changelog_repoUrl, "f"), __classPrivateFieldGet(this, _Changelog_tagPrefix, "f"), __classPrivateFieldGet(this, _Changelog_releases, "f"))}`; | ||
return __classPrivateFieldGet(this, _Changelog_formatter, "f").call(this, changelog); | ||
} | ||
} | ||
exports.default = Changelog; | ||
_Changelog_releases = new WeakMap(), _Changelog_changes = new WeakMap(), _Changelog_repoUrl = new WeakMap(), _Changelog_tagPrefix = new WeakMap(), _Changelog_formatter = new WeakMap(); | ||
//# sourceMappingURL=changelog.js.map |
@@ -9,16 +9,12 @@ #!/usr/bin/env node | ||
const path_1 = __importDefault(require("path")); | ||
// Intentionally shadowing 'URL' global, which is equivalent | ||
// Can't use global directly because of missing type, see: | ||
// https://github.com/DefinitelyTyped/DefinitelyTyped/issues/34960 | ||
// eslint-disable-next-line @typescript-eslint/no-shadow | ||
const url_1 = require("url"); | ||
const prettier_1 = __importDefault(require("prettier")); | ||
const semver_1 = __importDefault(require("semver")); | ||
const helpers_1 = require("yargs/helpers"); | ||
const yargs_1 = __importDefault(require("yargs/yargs")); | ||
const helpers_1 = require("yargs/helpers"); | ||
const update_changelog_1 = require("./update-changelog"); | ||
const constants_1 = require("./constants"); | ||
const generate_diff_1 = require("./generate-diff"); | ||
const init_1 = require("./init"); | ||
const constants_1 = require("./constants"); | ||
const repo_1 = require("./repo"); | ||
const update_changelog_1 = require("./update-changelog"); | ||
const validate_changelog_1 = require("./validate-changelog"); | ||
const repo_1 = require("./repo"); | ||
const updateEpilog = `New commits will be added to the "${constants_1.unreleased}" section (or \ | ||
@@ -43,3 +39,3 @@ to the section for the current release if the '--rc' flag is used) in reverse \ | ||
// eslint-disable-next-line no-new | ||
new url_1.URL(proposedUrl); | ||
new URL(proposedUrl); | ||
return true; | ||
@@ -90,4 +86,5 @@ } | ||
* @param options.tagPrefix - The prefix used in tags before the version number. | ||
* @param options.formatter - A custom Markdown formatter to use. | ||
*/ | ||
async function update({ changelogPath, currentVersion, isReleaseCandidate, repoUrl, projectRootDirectory, tagPrefix, }) { | ||
async function update({ changelogPath, currentVersion, isReleaseCandidate, repoUrl, projectRootDirectory, tagPrefix, formatter, }) { | ||
const changelogContent = await readChangelog(changelogPath); | ||
@@ -101,2 +98,3 @@ const newChangelogContent = await (0, update_changelog_1.updateChangelog)({ | ||
tagPrefixes: [tagPrefix], | ||
formatter, | ||
}); | ||
@@ -120,4 +118,6 @@ if (newChangelogContent) { | ||
* @param options.tagPrefix - The prefix used in tags before the version number. | ||
* @param options.fix - Whether to attempt to fix the changelog or not. | ||
* @param options.formatter - A custom Markdown formatter to use. | ||
*/ | ||
async function validate({ changelogPath, currentVersion, isReleaseCandidate, repoUrl, tagPrefix, }) { | ||
async function validate({ changelogPath, currentVersion, isReleaseCandidate, repoUrl, tagPrefix, fix, formatter, }) { | ||
const changelogContent = await readChangelog(changelogPath); | ||
@@ -131,2 +131,3 @@ try { | ||
tagPrefix, | ||
formatter, | ||
}); | ||
@@ -138,2 +139,6 @@ return undefined; | ||
const { validChangelog, invalidChangelog } = error.data; | ||
if (fix) { | ||
await saveChangelog(changelogPath, validChangelog); | ||
return undefined; | ||
} | ||
const diff = (0, generate_diff_1.generateDiff)(validChangelog, invalidChangelog); | ||
@@ -167,3 +172,3 @@ return exitWithError(`Changelog not well-formatted. Diff:\n\n${diff}`); | ||
async function init({ changelogPath, repoUrl, tagPrefix }) { | ||
const changelogContent = await (0, init_1.createEmptyChangelog)({ repoUrl, tagPrefix }); | ||
const changelogContent = (0, init_1.createEmptyChangelog)({ repoUrl, tagPrefix }); | ||
await saveChangelog(changelogPath, changelogContent); | ||
@@ -218,2 +223,7 @@ } | ||
}) | ||
.option('prettier', { | ||
default: false, | ||
description: `Expect the changelog to be formatted with Prettier.`, | ||
type: 'boolean', | ||
}) | ||
.epilog(updateEpilog)) | ||
@@ -230,2 +240,12 @@ .command('validate', 'Validate the changelog, ensuring that it is well-formatted.\nUsage: $0 validate [options]', (_yargs) => configureCommonCommandOptions(_yargs) | ||
}) | ||
.option('fix', { | ||
default: false, | ||
description: `Attempt to fix any formatting errors in the changelog`, | ||
type: 'boolean', | ||
}) | ||
.option('prettier', { | ||
default: false, | ||
description: `Expect the changelog to be formatted with Prettier.`, | ||
type: 'boolean', | ||
}) | ||
.epilog(validateEpilog)) | ||
@@ -239,3 +259,3 @@ .command('init', 'Initialize a new empty changelog', (_yargs) => { | ||
.usage(`Utilities for validating and updating "Keep a Changelog" formatted changelogs.\nUsage: $0 [command] [options]`); | ||
const { file: changelogFilename, rc: isReleaseCandidate, repo: repoUrl, root: projectRootDirectory, tagPrefix, } = argv; | ||
const { file: changelogFilename, rc: isReleaseCandidate, repo: repoUrl, root: projectRootDirectory, tagPrefix, fix, prettier: usePrettier, } = argv; | ||
let { currentVersion } = argv; | ||
@@ -319,2 +339,7 @@ if (projectRootDirectory) { | ||
} | ||
const formatter = (changelog) => { | ||
return usePrettier | ||
? prettier_1.default.format(changelog, { parser: 'markdown' }) | ||
: changelog; | ||
}; | ||
if (command === 'update') { | ||
@@ -328,2 +353,3 @@ await update({ | ||
tagPrefix, | ||
formatter, | ||
}); | ||
@@ -338,2 +364,4 @@ } | ||
tagPrefix, | ||
fix, | ||
formatter, | ||
}); | ||
@@ -340,0 +368,0 @@ } |
@@ -1,2 +0,2 @@ | ||
import Changelog from './changelog'; | ||
import Changelog, { Formatter } from './changelog'; | ||
/** | ||
@@ -10,8 +10,10 @@ * Constructs a Changelog instance that represents the given changelog, which | ||
* @param options.tagPrefix - The prefix used in tags before the version number. | ||
* @param options.formatter - A custom Markdown formatter to use. | ||
* @returns A changelog instance that reflects the changelog text provided. | ||
*/ | ||
export declare function parseChangelog({ changelogContent, repoUrl, tagPrefix, }: { | ||
export declare function parseChangelog({ changelogContent, repoUrl, tagPrefix, formatter, }: { | ||
changelogContent: string; | ||
repoUrl: string; | ||
tagPrefix?: string; | ||
formatter?: Formatter; | ||
}): Changelog; |
@@ -36,7 +36,8 @@ "use strict"; | ||
* @param options.tagPrefix - The prefix used in tags before the version number. | ||
* @param options.formatter - A custom Markdown formatter to use. | ||
* @returns A changelog instance that reflects the changelog text provided. | ||
*/ | ||
function parseChangelog({ changelogContent, repoUrl, tagPrefix = 'v', }) { | ||
function parseChangelog({ changelogContent, repoUrl, tagPrefix = 'v', formatter = undefined, }) { | ||
const changelogLines = changelogContent.split('\n'); | ||
const changelog = new changelog_1.default({ repoUrl, tagPrefix }); | ||
const changelog = new changelog_1.default({ repoUrl, tagPrefix, formatter }); | ||
const unreleasedHeaderIndex = changelogLines.indexOf(`## [${constants_1.unreleased}]`); | ||
@@ -43,0 +44,0 @@ if (unreleasedHeaderIndex === -1) { |
@@ -8,4 +8,4 @@ "use strict"; | ||
exports.getRepositoryUrl = void 0; | ||
const fs_1 = __importDefault(require("fs")); | ||
const path_1 = __importDefault(require("path")); | ||
const fs_1 = __importDefault(require("fs")); | ||
/** | ||
@@ -12,0 +12,0 @@ * Return the current project repository URL. |
@@ -0,1 +1,2 @@ | ||
import { Formatter } from './changelog'; | ||
import { Version } from './constants'; | ||
@@ -9,2 +10,3 @@ export declare type UpdateChangelogOptions = { | ||
tagPrefixes?: [string, ...string[]]; | ||
formatter?: Formatter; | ||
}; | ||
@@ -30,4 +32,5 @@ /** | ||
* prefix and each subsequent prefix is a fallback in case the previous tag prefixes are not found. | ||
* @param options.formatter - A custom Markdown formatter to use. | ||
* @returns The updated changelog text. | ||
*/ | ||
export declare function updateChangelog({ changelogContent, currentVersion, repoUrl, isReleaseCandidate, projectRootDirectory, tagPrefixes, }: UpdateChangelogOptions): Promise<string | undefined>; | ||
export declare function updateChangelog({ changelogContent, currentVersion, repoUrl, isReleaseCandidate, projectRootDirectory, tagPrefixes, formatter, }: UpdateChangelogOptions): Promise<string | undefined>; |
@@ -9,4 +9,4 @@ "use strict"; | ||
const execa_1 = __importDefault(require("execa")); | ||
const constants_1 = require("./constants"); | ||
const parse_changelog_1 = require("./parse-changelog"); | ||
const constants_1 = require("./constants"); | ||
/** | ||
@@ -52,3 +52,3 @@ * Get the most recent tag for a project. | ||
async function getCommits(commitHashes) { | ||
var _a; | ||
var _a, _b; | ||
const commits = []; | ||
@@ -69,3 +69,3 @@ for (const commitHash of commitHashes) { | ||
prNumber = matchResults[1]; | ||
description = ((_a = subject.match(/^(.+)\s\(#\d+\)/u)) === null || _a === void 0 ? void 0 : _a[1]) || ''; | ||
description = (_b = (_a = subject.match(/^(.+)\s\(#\d+\)/u)) === null || _a === void 0 ? void 0 : _a[1]) !== null && _b !== void 0 ? _b : ''; | ||
} | ||
@@ -118,3 +118,5 @@ else { | ||
for (const description of changeDescriptions) { | ||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion | ||
if (!description) { | ||
continue; | ||
} | ||
const matchResults = description.matchAll(/\[#(\d+)\]/gu); | ||
@@ -159,5 +161,6 @@ const prNumbers = Array.from(matchResults, (result) => result[1]); | ||
* prefix and each subsequent prefix is a fallback in case the previous tag prefixes are not found. | ||
* @param options.formatter - A custom Markdown formatter to use. | ||
* @returns The updated changelog text. | ||
*/ | ||
async function updateChangelog({ changelogContent, currentVersion, repoUrl, isReleaseCandidate, projectRootDirectory, tagPrefixes = ['v'], }) { | ||
async function updateChangelog({ changelogContent, currentVersion, repoUrl, isReleaseCandidate, projectRootDirectory, tagPrefixes = ['v'], formatter = undefined, }) { | ||
if (isReleaseCandidate && !currentVersion) { | ||
@@ -170,2 +173,3 @@ throw new Error(`A version must be specified if 'isReleaseCandidate' is set.`); | ||
tagPrefix: tagPrefixes[0], | ||
formatter, | ||
}); | ||
@@ -178,3 +182,3 @@ // Ensure we have all tags on remote | ||
if (isReleaseCandidate && | ||
mostRecentTag === `${tagPrefixes[0]}${currentVersion}`) { | ||
mostRecentTag === `${tagPrefixes[0]}${currentVersion || ''}`) { | ||
throw new Error(`Current version already has tag, which is unexpected for a release candidate.`); | ||
@@ -181,0 +185,0 @@ } |
@@ -0,1 +1,2 @@ | ||
import { Formatter } from './changelog'; | ||
import { Version } from './constants'; | ||
@@ -52,2 +53,3 @@ /** | ||
tagPrefix?: string; | ||
formatter?: Formatter; | ||
}; | ||
@@ -68,2 +70,3 @@ /** | ||
* @param options.tagPrefix - The prefix used in tags before the version number. | ||
* @param options.formatter - A custom Markdown formatter to use. | ||
* @throws `InvalidChangelogError` - Will throw if the changelog is invalid | ||
@@ -79,3 +82,3 @@ * @throws `MissingCurrentVersionError` - Will throw if `isReleaseCandidate` is | ||
*/ | ||
export declare function validateChangelog({ changelogContent, currentVersion, repoUrl, isReleaseCandidate, tagPrefix, }: ValidateChangelogOptions): void; | ||
export declare function validateChangelog({ changelogContent, currentVersion, repoUrl, isReleaseCandidate, tagPrefix, formatter, }: ValidateChangelogOptions): void; | ||
export {}; |
@@ -77,2 +77,3 @@ "use strict"; | ||
* @param options.tagPrefix - The prefix used in tags before the version number. | ||
* @param options.formatter - A custom Markdown formatter to use. | ||
* @throws `InvalidChangelogError` - Will throw if the changelog is invalid | ||
@@ -88,5 +89,10 @@ * @throws `MissingCurrentVersionError` - Will throw if `isReleaseCandidate` is | ||
*/ | ||
function validateChangelog({ changelogContent, currentVersion, repoUrl, isReleaseCandidate, tagPrefix = 'v', }) { | ||
function validateChangelog({ changelogContent, currentVersion, repoUrl, isReleaseCandidate, tagPrefix = 'v', formatter = undefined, }) { | ||
var _a, _b; | ||
const changelog = (0, parse_changelog_1.parseChangelog)({ changelogContent, repoUrl, tagPrefix }); | ||
const changelog = (0, parse_changelog_1.parseChangelog)({ | ||
changelogContent, | ||
repoUrl, | ||
tagPrefix, | ||
formatter, | ||
}); | ||
const hasUnreleasedChanges = Object.keys(changelog.getUnreleasedChanges()).length !== 0; | ||
@@ -93,0 +99,0 @@ const releaseChanges = currentVersion |
{ | ||
"name": "@metamask/auto-changelog", | ||
"version": "3.1.0", | ||
"version": "3.3.0", | ||
"description": "Utilities for validating and updating \"Keep a Changelog\" formatted changelogs", | ||
@@ -36,2 +36,3 @@ "publishConfig": { | ||
"execa": "^5.1.1", | ||
"prettier": "^2.8.8", | ||
"semver": "^7.3.5", | ||
@@ -42,6 +43,6 @@ "yargs": "^17.0.1" | ||
"@lavamoat/allow-scripts": "^2.1.0", | ||
"@metamask/eslint-config": "^10.0.0", | ||
"@metamask/eslint-config-jest": "^10.0.0", | ||
"@metamask/eslint-config-nodejs": "^10.0.0", | ||
"@metamask/eslint-config-typescript": "^10.0.0", | ||
"@metamask/eslint-config": "^11.1.0", | ||
"@metamask/eslint-config-jest": "^11.1.0", | ||
"@metamask/eslint-config-nodejs": "^11.1.0", | ||
"@metamask/eslint-config-typescript": "^11.1.0", | ||
"@types/cross-spawn": "^6.0.2", | ||
@@ -52,9 +53,9 @@ "@types/diff": "^5.0.0", | ||
"@types/yargs": "^16.0.1", | ||
"@typescript-eslint/eslint-plugin": "^5.41.0", | ||
"@typescript-eslint/parser": "^5.41.0", | ||
"eslint": "^8.26.0", | ||
"@typescript-eslint/eslint-plugin": "^5.42.1", | ||
"@typescript-eslint/parser": "^5.42.1", | ||
"eslint": "^8.40.0", | ||
"eslint-config-prettier": "^8.5.0", | ||
"eslint-plugin-import": "^2.26.0", | ||
"eslint-plugin-jest": "^26.8.2", | ||
"eslint-plugin-jsdoc": "^39.3.25", | ||
"eslint-plugin-jest": "^27.1.5", | ||
"eslint-plugin-jsdoc": "^39.6.2", | ||
"eslint-plugin-node": "^11.1.0", | ||
@@ -64,3 +65,2 @@ "eslint-plugin-prettier": "^4.2.1", | ||
"outdent": "^0.8.0", | ||
"prettier": "^2.2.1", | ||
"rimraf": "^3.0.2", | ||
@@ -67,0 +67,0 @@ "ts-jest": "^26.5.6", |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
173551
24
1831
5
+ Addedprettier@^2.8.8
+ Addedprettier@2.8.8(transitive)