Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Socket
Sign inDemoInstall

@metamask/auto-changelog

Package Overview
Dependencies
Maintainers
8
Versions
20
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@metamask/auto-changelog - npm Package Compare versions

Comparing version 2.6.1 to 3.0.0

33

dist/changelog.d.ts
import { ChangeCategory, Version } from './constants';
interface ReleaseMetadata {
declare type ReleaseMetadata = {
/**

@@ -16,4 +16,4 @@ * The version of the current release.

status?: string;
}
interface AddReleaseOptions {
};
declare type AddReleaseOptions = {
addToStart?: boolean;

@@ -23,4 +23,4 @@ date?: string;

version: Version;
}
interface AddChangeOptions {
};
declare type AddChangeOptions = {
addToStart?: boolean;

@@ -30,3 +30,3 @@ category: ChangeCategory;

version?: Version;
}
};
/**

@@ -45,10 +45,13 @@ * A changelog that complies with the

private _repoUrl;
private _tagPrefix;
/**
* Construct an empty changelog
* Construct an empty changelog.
*
* @param options
* @param options.repoUrl - The GitHub repository URL for the current project
* @param options - Changelog options.
* @param options.repoUrl - The GitHub repository URL for the current project.
* @param options.tagPrefix - The prefix used in tags before the version number.
*/
constructor({ repoUrl }: {
constructor({ repoUrl, tagPrefix, }: {
repoUrl: string;
tagPrefix?: string;
});

@@ -58,3 +61,3 @@ /**

*
* @param options
* @param options - Release options.
* @param options.addToStart - Determines whether the change is added to the

@@ -66,4 +69,4 @@ * top or bottom of the list of changes in this category. This defaults to

* date.
* @param options.status - The status of the release (e.g. 'WITHDRAWN',
* 'DEPRECATED')
* @param options.status - The status of the release (e.g., 'WITHDRAWN',
* 'DEPRECATED').
* @param options.version - The version of the current release, which should

@@ -76,3 +79,3 @@ * be a [SemVer](https://semver.org/spec/v2.0.0.html)-compatible version.

*
* @param options
* @param options - Change options.
* @param options.addToStart - Determines whether the change is added to the

@@ -126,3 +129,3 @@ * top or bottom of the list of changes in this category. This defaults to

/**
* Gets all changes that have not yet been released
* Gets all changes that have not yet been released.
*

@@ -129,0 +132,0 @@ * @returns The changes that have not yet been released.

@@ -14,2 +14,9 @@ "use strict";

// Stringification helpers
/**
* Stringify a changelog category section.
*
* @param category - The title of the changelog category.
* @param changes - The changes included in this category.
* @returns The stringified category section.
*/
function stringifyCategory(category, changes) {

@@ -25,2 +32,12 @@ const categoryHeader = `### ${category}`;

}
/**
* Stringify a changelog release section.
*
* @param version - The release version.
* @param categories - The categories of changes included in this release.
* @param options - Additional release options.
* @param options.date - The date of the release.
* @param options.status - The status of the release (e.g., "DEPRECATED").
* @returns The stringified release section.
*/
function stringifyRelease(version, categories, { date, status } = {}) {

@@ -40,2 +57,9 @@ const releaseHeader = `## [${version}]${date ? ` - ${date}` : ''}${status ? ` [${status}]` : ''}`;

}
/**
* Stringify a set of changelog release sections.
*
* @param releases - The releases to stringify.
* @param changes - The set of changes to include, organized by release.
* @returns The stringified set of release sections.
*/
function stringifyReleases(releases, changes) {

@@ -49,12 +73,44 @@ const stringifiedUnreleased = stringifyRelease(constants_1.unreleased, changes[constants_1.unreleased]);

}
/**
* Return the given URL with a trailing slash. It is returned unaltered if it
* already has a trailing slash.
*
* @param url - The URL string.
* @returns The URL string with a trailing slash.
*/
function withTrailingSlash(url) {
return url.endsWith('/') ? url : `${url}/`;
}
/**
* Get the GitHub URL for comparing two git commits.
*
* @param repoUrl - The URL for the GitHub repository.
* @param firstRef - A reference (e.g., commit hash, tag, etc.) to the first commit to compare.
* @param secondRef - A reference (e.g., commit hash, tag, etc.) to the second commit to compare.
* @returns The comparison URL for the two given commits.
*/
function getCompareUrl(repoUrl, firstRef, secondRef) {
return `${withTrailingSlash(repoUrl)}compare/${firstRef}...${secondRef}`;
}
/**
* Get a GitHub tag URL.
*
* @param repoUrl - The URL for the GitHub repository.
* @param tag - The tag name.
* @returns The URL for the given tag.
*/
function getTagUrl(repoUrl, tag) {
return `${withTrailingSlash(repoUrl)}releases/tag/${tag}`;
}
function stringifyLinkReferenceDefinitions(repoUrl, releases) {
/**
* Get a stringified list of link definitions for the given set of releases. The first release is
* linked to the corresponding tag, and each subsequent release is linked to a comparison with the
* previous release.
*
* @param repoUrl - The URL for the GitHub repository.
* @param tagPrefix - The prefix used in tags before the version number.
* @param releases - The releases to generate link definitions for.
* @returns The stringified release link definitions.
*/
function stringifyLinkReferenceDefinitions(repoUrl, tagPrefix, releases) {
// A list of release versions in descending SemVer order

@@ -81,3 +137,3 @@ const descendingSemverVersions = releases

const unreleasedLinkReferenceDefinition = `[${constants_1.unreleased}]: ${hasReleases
? getCompareUrl(repoUrl, `v${latestSemverVersion}`, 'HEAD')
? getCompareUrl(repoUrl, `${tagPrefix}${latestSemverVersion}`, 'HEAD')
: withTrailingSlash(repoUrl)}`;

@@ -92,3 +148,3 @@ // The "previous" release that should be used for comparison is not always

if (version === chronologicalVersions[chronologicalVersions.length - 1]) {
diffUrl = getTagUrl(repoUrl, `v${version}`);
diffUrl = getTagUrl(repoUrl, `${tagPrefix}${version}`);
}

@@ -103,4 +159,4 @@ else {

diffUrl = previousVersion
? getCompareUrl(repoUrl, `v${previousVersion}`, `v${version}`)
: getTagUrl(repoUrl, `v${version}`);
? getCompareUrl(repoUrl, `${tagPrefix}${previousVersion}`, `${tagPrefix}${version}`)
: getTagUrl(repoUrl, `${tagPrefix}${version}`);
}

@@ -123,11 +179,13 @@ return `[${version}]: ${diffUrl}`;

/**
* Construct an empty changelog
* Construct an empty changelog.
*
* @param options
* @param options.repoUrl - The GitHub repository URL for the current project
* @param options - Changelog options.
* @param options.repoUrl - The GitHub repository URL for the current project.
* @param options.tagPrefix - The prefix used in tags before the version number.
*/
constructor({ repoUrl }) {
constructor({ repoUrl, tagPrefix = 'v', }) {
this._releases = [];
this._changes = { [constants_1.unreleased]: {} };
this._repoUrl = repoUrl;
this._tagPrefix = tagPrefix;
}

@@ -137,3 +195,3 @@ /**

*
* @param options
* @param options - Release options.
* @param options.addToStart - Determines whether the change is added to the

@@ -145,4 +203,4 @@ * top or bottom of the list of changes in this category. This defaults to

* date.
* @param options.status - The status of the release (e.g. 'WITHDRAWN',
* 'DEPRECATED')
* @param options.status - The status of the release (e.g., 'WITHDRAWN',
* 'DEPRECATED').
* @param options.version - The version of the current release, which should

@@ -173,3 +231,3 @@ * be a [SemVer](https://semver.org/spec/v2.0.0.html)-compatible version.

*
* @param options
* @param options - Change options.
* @param options.addToStart - Determines whether the change is added to the

@@ -281,3 +339,3 @@ * top or bottom of the list of changes in this category. This defaults to

/**
* Gets all changes that have not yet been released
* Gets all changes that have not yet been released.
*

@@ -300,3 +358,3 @@ * @returns The changes that have not yet been released.

${stringifyLinkReferenceDefinitions(this._repoUrl, this._releases)}`;
${stringifyLinkReferenceDefinitions(this._repoUrl, this._tagPrefix, this._releases)}`;
}

@@ -303,0 +361,0 @@ }

@@ -33,4 +33,8 @@ #!/usr/bin/env node

formatting is correct. Verification of the contents is left for manual review.`;
// eslint-disable-next-line node/no-process-env
const npmPackageVersion = process.env.npm_package_version;
/**
* Determine whether the given URL is valid.
*
* @param proposedUrl - The URL to validate.
* @returns True if the URL is valid, false otherwise.
*/
function isValidUrl(proposedUrl) {

@@ -46,2 +50,7 @@ try {

}
/**
* Exit the process with the given error.
*
* @param errorMessage - The error message to exit with.
*/
function exitWithError(errorMessage) {

@@ -51,2 +60,8 @@ console.error(errorMessage);

}
/**
* Read the changelog contents from the filesystem.
*
* @param changelogPath - The path to the changelog file.
* @returns The changelog contents.
*/
async function readChangelog(changelogPath) {

@@ -57,6 +72,23 @@ return await fs_1.promises.readFile(changelogPath, {

}
/**
* Save the changelog to the filesystem.
*
* @param changelogPath - The path to the changelog file.
* @param newChangelogContent - The new changelog contents to save.
*/
async function saveChangelog(changelogPath, newChangelogContent) {
await fs_1.promises.writeFile(changelogPath, newChangelogContent);
}
async function update({ changelogPath, currentVersion, isReleaseCandidate, repoUrl, projectRootDirectory, }) {
/**
* Update the changelog.
*
* @param options - Update options.
* @param options.changelogPath - The path to the changelog file.
* @param options.currentVersion - The current project version.
* @param options.isReleaseCandidate - Whether the current branch is a release candidate or not.
* @param options.repoUrl - The GitHub repository URL for the current project.
* @param options.projectRootDirectory - The root project directory.
* @param options.tagPrefix - The prefix used in tags before the version number.
*/
async function update({ changelogPath, currentVersion, isReleaseCandidate, repoUrl, projectRootDirectory, tagPrefix, }) {
const changelogContent = await readChangelog(changelogPath);

@@ -69,2 +101,3 @@ const newChangelogContent = await update_changelog_1.updateChangelog({

projectRootDirectory,
tagPrefixes: [tagPrefix],
});

@@ -79,3 +112,13 @@ if (newChangelogContent) {

}
async function validate({ changelogPath, currentVersion, isReleaseCandidate, repoUrl, }) {
/**
* Validate the changelog.
*
* @param options - Validation options.
* @param options.changelogPath - The path to the changelog file.
* @param options.currentVersion - The current project version.
* @param options.isReleaseCandidate - Whether the current branch is a release candidate or not.
* @param options.repoUrl - The GitHub repository URL for the current project.
* @param options.tagPrefix - The prefix used in tags before the version number.
*/
async function validate({ changelogPath, currentVersion, isReleaseCandidate, repoUrl, tagPrefix, }) {
const changelogContent = await readChangelog(changelogPath);

@@ -88,3 +131,5 @@ try {

isReleaseCandidate,
tagPrefix,
});
return undefined;
}

@@ -95,8 +140,6 @@ catch (error) {

const diff = generate_diff_1.generateDiff(validChangelog, invalidChangelog);
exitWithError(`Changelog not well-formatted. Diff:\n\n${diff}`);
return;
return exitWithError(`Changelog not well-formatted. Diff:\n\n${diff}`);
}
else if (error instanceof validate_changelog_1.InvalidChangelogError) {
exitWithError(`Changelog is invalid: ${error.message}`);
return;
return exitWithError(`Changelog is invalid: ${error.message}`);
}

@@ -106,4 +149,12 @@ throw error;

}
async function init({ changelogPath, repoUrl }) {
const changelogContent = await init_1.createEmptyChangelog({ repoUrl });
/**
* Create a new empty changelog.
*
* @param options - Initialization options.
* @param options.changelogPath - The path to the changelog file.
* @param options.repoUrl - The GitHub repository URL for the current project.
* @param options.tagPrefix - The prefix used in tags before the version number.
*/
async function init({ changelogPath, repoUrl, tagPrefix }) {
const changelogContent = await init_1.createEmptyChangelog({ repoUrl, tagPrefix });
await saveChangelog(changelogPath, changelogContent);

@@ -115,2 +166,8 @@ }

(defaults to the current working directory).`;
/**
* Configure options that are common to all commands.
*
* @param _yargs - The yargs instance to configure.
* @returns A Yargs instance configured with all common commands.
*/
function configureCommonCommandOptions(_yargs) {

@@ -131,4 +188,12 @@ return _yargs

type: 'string',
})
.option('tagPrefix', {
default: 'v',
description: 'The prefix used in tags before the version number.',
type: 'string',
});
}
/**
* The entrypoint for the auto-changelog CLI.
*/
async function main() {

@@ -143,3 +208,2 @@ const { argv } = yargs_1.default(helpers_1.hideBin(process.argv))

.option('currentVersion', {
default: npmPackageVersion,
description: 'The current version of the project that the changelog belongs to.',

@@ -156,3 +220,2 @@ type: 'string',

.option('currentVersion', {
default: npmPackageVersion,
description: 'The current version of the project that the changelog belongs to.',

@@ -169,19 +232,4 @@ type: 'string',

.usage(`Utilities for validating and updating "Keep a Changelog" formatted changelogs.\nUsage: $0 [command] [options]`);
const { currentVersion, file: changelogFilename, rc: isReleaseCandidate, repo: repoUrl, root: projectRootDirectory, } = argv;
if (isReleaseCandidate && !currentVersion) {
exitWithError(`Version not found. Please set the --currentVersion flag, or run this as an npm script from a project with the 'version' field set.`);
return;
}
else if (currentVersion && semver_1.default.valid(currentVersion) === null) {
exitWithError(`Current version is not valid SemVer: '${currentVersion}'`);
return;
}
else if (!repoUrl) {
exitWithError(`npm package repository URL not found. Please set the '--repo' flag, or run this as an npm script from a project with the 'repository' field set.`);
return;
}
else if (!isValidUrl(repoUrl)) {
exitWithError(`Invalid repo URL: '${repoUrl}'`);
return;
}
const { file: changelogFilename, rc: isReleaseCandidate, repo: repoUrl, root: projectRootDirectory, tagPrefix, } = argv;
let { currentVersion } = argv;
if (projectRootDirectory) {

@@ -191,4 +239,3 @@ try {

if (!stat.isDirectory()) {
exitWithError(`Project root must be a directory: '${projectRootDirectory}'`);
return;
return exitWithError(`Project root must be a directory: '${projectRootDirectory}'`);
}

@@ -198,8 +245,6 @@ }

if (error.code === 'ENOENT') {
exitWithError(`Root directory specified does not exist: '${projectRootDirectory}'`);
return;
return exitWithError(`Root directory specified does not exist: '${projectRootDirectory}'`);
}
else if (error.code === 'EACCES') {
exitWithError(`Access to root directory is forbidden by file access permissions: '${projectRootDirectory}'`);
return;
return exitWithError(`Access to root directory is forbidden by file access permissions: '${projectRootDirectory}'`);
}

@@ -209,2 +254,38 @@ throw error;

}
if (!currentVersion) {
const manifestPath = projectRootDirectory
? path_1.default.join(projectRootDirectory, 'package.json')
: path_1.default.resolve('package.json');
try {
const manifestText = await fs_1.promises.readFile(manifestPath, {
encoding: 'utf-8',
});
const manifest = JSON.parse(manifestText);
currentVersion = manifest.version;
}
catch (error) {
if (error.code === 'ENOENT') {
return exitWithError(`Package manifest not found at path: '${manifestPath}'\nRun this script from the project root directory, or set the project directory using the '--root' flag.`);
}
else if (error.code === 'EACCES') {
return exitWithError(`Access to package manifest is forbidden by file access permissions: '${manifestPath}'`);
}
else if (error.name === 'SyntaxError') {
return exitWithError(`Package manifest cannot be parsed as JSON: '${manifestPath}'`);
}
throw error;
}
}
if (!currentVersion) {
return exitWithError(`Version not found. Please set the --currentVersion flag, or run this as an npm script from a project with the 'version' field set.`);
}
else if (currentVersion && semver_1.default.valid(currentVersion) === null) {
return exitWithError(`Current version is not valid SemVer: '${currentVersion}'`);
}
else if (!repoUrl) {
return exitWithError(`npm package repository URL not found. Please set the '--repo' flag, or run this as an npm script from a project with the 'repository' field set.`);
}
else if (!isValidUrl(repoUrl)) {
return exitWithError(`Invalid repo URL: '${repoUrl}'`);
}
let changelogPath = changelogFilename;

@@ -225,8 +306,5 @@ if (!path_1.default.isAbsolute(changelogFilename) && projectRootDirectory) {

if (error.code === 'ENOENT') {
exitWithError(`File does not exist: '${changelogPath}'`);
return exitWithError(`File does not exist: '${changelogPath}'`);
}
else {
exitWithError(`File is not writable: '${changelogPath}'`);
}
return;
return exitWithError(`File is not writable: '${changelogPath}'`);
}

@@ -241,2 +319,3 @@ }

projectRootDirectory,
tagPrefix,
});

@@ -250,2 +329,3 @@ }

repoUrl,
tagPrefix,
});

@@ -257,4 +337,6 @@ }

repoUrl,
tagPrefix,
});
}
return undefined;
}

@@ -261,0 +343,0 @@ main().catch((error) => {

@@ -6,6 +6,7 @@ /**

* section where possible.
*
* @param before - The string representing the base for the comparison.
* @param after - The string representing the changes being compared.
* @returns The genereated text diff
* @returns The genereated text diff.
*/
export declare function generateDiff(before: string, after: string): string;

@@ -27,4 +27,5 @@ "use strict";

* line. The trailing newline is optional.
* @param value - The string value to split into lines
* @returns The lines, without trailing newlines
*
* @param value - The string value to split into lines.
* @returns The lines, without trailing newlines.
*/

@@ -42,5 +43,6 @@ function getTrimmedLines(value) {

* section where possible.
*
* @param before - The string representing the base for the comparison.
* @param after - The string representing the changes being compared.
* @returns The genereated text diff
* @returns The genereated text diff.
*/

@@ -47,0 +49,0 @@ function generateDiff(before, after) {

/**
* Creates a new empty changelog.
*
* @param options
* @param options - Changelog options.
* @param options.repoUrl - The GitHub repository URL for the current project.
* @param options.tagPrefix - The prefix used in tags before the version number.
* @returns The initial changelog text.
*/
export declare function createEmptyChangelog({ repoUrl }: {
export declare function createEmptyChangelog({ repoUrl, tagPrefix, }: {
repoUrl: string;
tagPrefix?: string;
}): string;

@@ -11,8 +11,9 @@ "use strict";

*
* @param options
* @param options - Changelog options.
* @param options.repoUrl - The GitHub repository URL for the current project.
* @param options.tagPrefix - The prefix used in tags before the version number.
* @returns The initial changelog text.
*/
function createEmptyChangelog({ repoUrl }) {
const changelog = new changelog_1.default({ repoUrl });
function createEmptyChangelog({ repoUrl, tagPrefix = 'v', }) {
const changelog = new changelog_1.default({ repoUrl, tagPrefix });
return changelog.toString();

@@ -19,0 +20,0 @@ }

@@ -5,10 +5,13 @@ import Changelog from './changelog';

* is parsed for release and change information.
* @param options
* @param options.changelogContent - The changelog to parse
*
* @param options - Options.
* @param options.changelogContent - The changelog to parse.
* @param options.repoUrl - The GitHub repository URL for the current project.
* @param options.tagPrefix - The prefix used in tags before the version number.
* @returns A changelog instance that reflects the changelog text provided.
*/
export declare function parseChangelog({ changelogContent, repoUrl, }: {
export declare function parseChangelog({ changelogContent, repoUrl, tagPrefix, }: {
changelogContent: string;
repoUrl: string;
tagPrefix?: string;
}): Changelog;

@@ -9,5 +9,17 @@ "use strict";

const constants_1 = require("./constants");
/**
* Truncate the given string at 80 characters.
*
* @param line - The string to truncate.
* @returns The truncated string.
*/
function truncated(line) {
return line.length > 80 ? `${line.slice(0, 80)}...` : line;
}
/**
* Returns whether the given string is recognized as a valid change category.
*
* @param category - The string to validate.
* @returns Whether the given string is a valid change category.
*/
function isValidChangeCategory(category) {

@@ -19,10 +31,12 @@ return constants_1.ChangeCategory[category] !== undefined;

* is parsed for release and change information.
* @param options
* @param options.changelogContent - The changelog to parse
*
* @param options - Options.
* @param options.changelogContent - The changelog to parse.
* @param options.repoUrl - The GitHub repository URL for the current project.
* @param options.tagPrefix - The prefix used in tags before the version number.
* @returns A changelog instance that reflects the changelog text provided.
*/
function parseChangelog({ changelogContent, repoUrl, }) {
function parseChangelog({ changelogContent, repoUrl, tagPrefix = 'v', }) {
const changelogLines = changelogContent.split('\n');
const changelog = new changelog_1.default({ repoUrl });
const changelog = new changelog_1.default({ repoUrl, tagPrefix });
const unreleasedHeaderIndex = changelogLines.indexOf(`## [${constants_1.unreleased}]`);

@@ -47,3 +61,3 @@ if (unreleasedHeaderIndex === -1) {

*
* @param options
* @param options - Options.
* @param options.removeTrailingNewline - Indicates that the trailing newline

@@ -50,0 +64,0 @@ * is not a part of the change description, and should therefore be removed.

@@ -0,1 +1,6 @@

/**
* Return the current project repository URL.
*
* @returns The repository URL.
*/
export declare function getRepositoryUrl(): string | null;

@@ -10,2 +10,7 @@ "use strict";

const fs_1 = __importDefault(require("fs"));
/**
* Return the current project repository URL.
*
* @returns The repository URL.
*/
function getRepositoryUrl() {

@@ -12,0 +17,0 @@ var _a;

import { Version } from './constants';
export interface UpdateChangelogOptions {
export declare type UpdateChangelogOptions = {
changelogContent: string;

@@ -8,8 +8,10 @@ currentVersion?: Version;

projectRootDirectory?: string;
}
tagPrefixes?: [string, ...string[]];
};
/**
* Update a changelog with any commits made since the last release. Commits for
* PRs that are already included in the changelog are omitted.
* @param options
* @param options.changelogContent - The current changelog
*
* @param options - Update options.
* @param options.changelogContent - The current changelog.
* @param options.currentVersion - The current version. Required if

@@ -26,4 +28,6 @@ * `isReleaseCandidate` is set, but optional otherwise.

* current git repository.
* @returns The updated changelog text
* @param options.tagPrefixes - A list of tag prefixes to look for, where the first is the intended
* prefix and each subsequent prefix is a fallback in case the previous tag prefixes are not found.
* @returns The updated changelog text.
*/
export declare function updateChangelog({ changelogContent, currentVersion, repoUrl, isReleaseCandidate, projectRootDirectory, }: UpdateChangelogOptions): Promise<string | undefined>;
export declare function updateChangelog({ changelogContent, currentVersion, repoUrl, isReleaseCandidate, projectRootDirectory, tagPrefixes, }: UpdateChangelogOptions): Promise<string | undefined>;

@@ -11,9 +11,28 @@ "use strict";

const constants_1 = require("./constants");
async function getMostRecentTag() {
const revListArgs = ['rev-list', '--tags', '--max-count=1', '--date-order'];
const results = await runCommand('git', revListArgs);
if (results.length === 0) {
/**
* Get the most recent tag for a project.
*
* @param options - Options.
* @param options.tagPrefixes - A list of tag prefixes to look for, where the first is the intended
* prefix and each subsequent prefix is a fallback in case the previous tag prefixes are not found.
* @returns The most recent tag.
*/
async function getMostRecentTag({ tagPrefixes, }) {
let mostRecentTagCommitHash = null;
for (const tagPrefix of tagPrefixes) {
const revListArgs = [
'rev-list',
`--tags=${tagPrefix}*`,
'--max-count=1',
'--date-order',
];
const results = await runCommand('git', revListArgs);
if (results.length) {
mostRecentTagCommitHash = results[0];
break;
}
}
if (mostRecentTagCommitHash === null) {
return null;
}
const [mostRecentTagCommitHash] = results;
const [mostRecentTag] = await runCommand('git', [

@@ -24,5 +43,10 @@ 'describe',

]);
assert_1.strict.equal(mostRecentTag === null || mostRecentTag === void 0 ? void 0 : mostRecentTag[0], 'v', 'Most recent tag should start with v');
return mostRecentTag;
}
/**
* Get commit details for each given commit hash.
*
* @param commitHashes - The list of commit hashes.
* @returns Commit details for each commit, including description and PR number (if present).
*/
async function getCommits(commitHashes) {

@@ -69,2 +93,8 @@ var _a;

}
/**
* Get all change descriptions from a changelog.
*
* @param changelog - The changelog.
* @returns All commit descriptions included in the given changelog.
*/
function getAllChangeDescriptions(changelog) {

@@ -78,2 +108,8 @@ const releases = changelog.getReleases();

}
/**
* Get all pull request numbers included in the given changelog.
*
* @param changelog - The changelog.
* @returns All pull request numbers included in the given changelog.
*/
function getAllLoggedPrNumbers(changelog) {

@@ -90,2 +126,9 @@ const changeDescriptions = getAllChangeDescriptions(changelog);

}
/**
* Get all commit hashes included in the given commit range.
*
* @param commitRange - The commit range.
* @param rootDirectory - The project root directory.
* @returns A list of commit hashes for the given range.
*/
async function getCommitHashesInRange(commitRange, rootDirectory) {

@@ -101,4 +144,5 @@ const revListArgs = ['rev-list', commitRange];

* PRs that are already included in the changelog are omitted.
* @param options
* @param options.changelogContent - The current changelog
*
* @param options - Update options.
* @param options.changelogContent - The current changelog.
* @param options.currentVersion - The current version. Required if

@@ -115,13 +159,22 @@ * `isReleaseCandidate` is set, but optional otherwise.

* current git repository.
* @returns The updated changelog text
* @param options.tagPrefixes - A list of tag prefixes to look for, where the first is the intended
* prefix and each subsequent prefix is a fallback in case the previous tag prefixes are not found.
* @returns The updated changelog text.
*/
async function updateChangelog({ changelogContent, currentVersion, repoUrl, isReleaseCandidate, projectRootDirectory, }) {
async function updateChangelog({ changelogContent, currentVersion, repoUrl, isReleaseCandidate, projectRootDirectory, tagPrefixes = ['v'], }) {
if (isReleaseCandidate && !currentVersion) {
throw new Error(`A version must be specified if 'isReleaseCandidate' is set.`);
}
const changelog = parse_changelog_1.parseChangelog({ changelogContent, repoUrl });
const changelog = parse_changelog_1.parseChangelog({
changelogContent,
repoUrl,
tagPrefix: tagPrefixes[0],
});
// Ensure we have all tags on remote
await runCommand('git', ['fetch', '--tags']);
const mostRecentTag = await getMostRecentTag();
if (isReleaseCandidate && mostRecentTag === `v${currentVersion}`) {
const mostRecentTag = await getMostRecentTag({
tagPrefixes,
});
if (isReleaseCandidate &&
mostRecentTag === `${tagPrefixes[0]}${currentVersion}`) {
throw new Error(`Current version already has tag, which is unexpected for a release candidate.`);

@@ -128,0 +181,0 @@ }

@@ -21,3 +21,5 @@ import { Version } from './constants';

/**
* @param currentVersion - The current version
* Construct a changelog missing version error.
*
* @param currentVersion - The current version.
*/

@@ -32,3 +34,5 @@ constructor(currentVersion: Version);

/**
* @param options
* Construct a changelog formatting error.
*
* @param options - Error options.
* @param options.validChangelog - The string contents of the well-formatted

@@ -44,3 +48,3 @@ * changelog.

}
interface ValidateChangelogOptions {
declare type ValidateChangelogOptions = {
changelogContent: string;

@@ -50,8 +54,9 @@ currentVersion?: Version;

isReleaseCandidate: boolean;
}
tagPrefix?: string;
};
/**
* Validates that a changelog is well-formatted.
*
* @param options
* @param options.changelogContent - The current changelog
* @param options - Validation options.
* @param options.changelogContent - The current changelog.
* @param options.currentVersion - The current version. Required if

@@ -65,2 +70,3 @@ * `isReleaseCandidate` is set, but optional otherwise.

* header, and that there are no unreleased changes present.
* @param options.tagPrefix - The prefix used in tags before the version number.
* @throws `InvalidChangelogError` - Will throw if the changelog is invalid

@@ -76,3 +82,3 @@ * @throws `MissingCurrentVersionError` - Will throw if `isReleaseCandidate` is

*/
export declare function validateChangelog({ changelogContent, currentVersion, repoUrl, isReleaseCandidate, }: ValidateChangelogOptions): void;
export declare function validateChangelog({ changelogContent, currentVersion, repoUrl, isReleaseCandidate, tagPrefix, }: ValidateChangelogOptions): void;
export {};

@@ -32,3 +32,5 @@ "use strict";

/**
* @param currentVersion - The current version
* Construct a changelog missing version error.
*
* @param currentVersion - The current version.
*/

@@ -45,3 +47,5 @@ constructor(currentVersion) {

/**
* @param options
* Construct a changelog formatting error.
*
* @param options - Error options.
* @param options.validChangelog - The string contents of the well-formatted

@@ -64,4 +68,4 @@ * changelog.

*
* @param options
* @param options.changelogContent - The current changelog
* @param options - Validation options.
* @param options.changelogContent - The current changelog.
* @param options.currentVersion - The current version. Required if

@@ -75,2 +79,3 @@ * `isReleaseCandidate` is set, but optional otherwise.

* header, and that there are no unreleased changes present.
* @param options.tagPrefix - The prefix used in tags before the version number.
* @throws `InvalidChangelogError` - Will throw if the changelog is invalid

@@ -86,5 +91,5 @@ * @throws `MissingCurrentVersionError` - Will throw if `isReleaseCandidate` is

*/
function validateChangelog({ changelogContent, currentVersion, repoUrl, isReleaseCandidate, }) {
function validateChangelog({ changelogContent, currentVersion, repoUrl, isReleaseCandidate, tagPrefix = 'v', }) {
var _a, _b;
const changelog = parse_changelog_1.parseChangelog({ changelogContent, repoUrl });
const changelog = parse_changelog_1.parseChangelog({ changelogContent, repoUrl, tagPrefix });
const hasUnreleasedChanges = Object.keys(changelog.getUnreleasedChanges()).length !== 0;

@@ -91,0 +96,0 @@ const releaseChanges = currentVersion

{
"name": "@metamask/auto-changelog",
"version": "2.6.1",
"version": "3.0.0",
"description": "Utilities for validating and updating \"Keep a Changelog\" formatted changelogs",

@@ -12,3 +12,3 @@ "publishConfig": {

"engines": {
"node": ">=12.0.0"
"node": ">=14.0.0"
},

@@ -23,9 +23,7 @@ "files": [

"scripts": {
"setup": "yarn install && yarn setup:postinstall",
"setup:postinstall": "yarn allow-scripts",
"test": "jest",
"test:watch": "jest --watch",
"prepublishOnly": "yarn build:clean && chmod +x dist/cli.js && yarn lint && yarn test",
"prepack": "./scripts/prepack.sh",
"lint:eslint": "eslint . --cache --ext js,ts",
"lint:misc": "prettier '**/*.json' '**/*.md' '!CHANGELOG.md' '**/*.yml' --ignore-path .gitignore",
"lint:misc": "prettier '**/*.json' '**/*.md' '!CHANGELOG.md' '**/*.yml' '!.yarnrc.yml' --ignore-path .gitignore",
"lint": "yarn lint:eslint && yarn lint:misc --check",

@@ -44,7 +42,7 @@ "lint:fix": "yarn lint:eslint --fix && yarn lint:misc --write",

"devDependencies": {
"@lavamoat/allow-scripts": "^1.0.6",
"@metamask/eslint-config": "^7.0.1",
"@metamask/eslint-config-jest": "^7.0.0",
"@metamask/eslint-config-nodejs": "^7.0.1",
"@metamask/eslint-config-typescript": "^7.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",
"@types/cross-spawn": "^6.0.2",

@@ -55,10 +53,11 @@ "@types/diff": "^5.0.0",

"@types/yargs": "^16.0.1",
"@typescript-eslint/eslint-plugin": "^4.23.0",
"@typescript-eslint/parser": "^4.23.0",
"eslint": "^7.23.0",
"eslint-config-prettier": "^8.1.0",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-jest": "^24.3.4",
"@typescript-eslint/eslint-plugin": "^5.41.0",
"@typescript-eslint/parser": "^5.41.0",
"eslint": "^8.26.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-node": "^11.1.0",
"eslint-plugin-prettier": "^3.3.1",
"eslint-plugin-prettier": "^4.2.1",
"jest": "^26.4.2",

@@ -75,3 +74,4 @@ "outdent": "^0.8.0",

}
}
},
"packageManager": "yarn@3.2.4"
}

@@ -90,7 +90,6 @@ # @metamask/auto-changelog

- Install [Node.js](https://nodejs.org) version 12
- Install [Node.js](https://nodejs.org) version 14
- If you are using [nvm](https://github.com/creationix/nvm#installation) (recommended) running `nvm use` will automatically choose the right node version for you.
- Install [Yarn v1](https://yarnpkg.com/en/docs/install)
- Run `yarn setup` to install dependencies and run any requried post-install scripts
- **Warning**: Do not use the `yarn` / `yarn install` command directly. Use `yarn setup` instead. The normal install command will skip required post-install scripts, leaving your development environment in an invalid state.
- Install [Yarn v3](https://yarnpkg.com/getting-started/install)
- Run `yarn install` to install dependencies and run any required post-install scripts

@@ -97,0 +96,0 @@ ### Testing and Linting

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

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc