The ConventionalChangelog class provides a comprehensive fluent API for generating changelogs programmatically with extensive configuration options and multiple output formats.
interface GetSemverTagsParams {
prefix?: string;
skipUnstable?: boolean;
}
interface GetCommitsParams {
from?: string;
to?: string;
path?: string;
format?: string;
merges?: boolean;
reverse?: boolean;
}
interface ParserStreamOptions {
noteKeywords?: string[];
referenceActions?: string[];
issuePrefixes?: string[];
warn?: Logger;
}
interface WriterOptions {
finalizeContext?: (context: any, options: any, commits: any, keyCommit: any, originalCommits: any) => any;
reverse?: boolean;
doFlush?: boolean;
debug?: Logger;
}
interface Options {
reset?: boolean;
append?: boolean;
releaseCount?: number;
outputUnreleased?: boolean;
transformCommit?: CommitTransformFunction;
warn?: Logger;
debug?: Logger;
formatDate?(date: string | Date): string;
}
interface Preset {
tags?: GetSemverTagsParams;
commits?: GetCommitsParams;
parser?: ParserStreamOptions;
writer?: WriterOptions;
}
interface Package {
name?: string;
version?: string;
description?: string;
repository?: {
type?: string;
url?: string;
};
[key: string]: any;
}
interface HostedGitInfo {
url: string;
type: HostType;
host: string;
owner?: string;
project?: string;
}
type HostType = 'github' | 'gitlab' | 'bitbucket' | 'sourcehut' | '';
interface Context {
version?: string;
previousTag?: string;
currentTag?: string;
host?: string;
owner?: string;
repository?: string;
repoUrl?: string;
[key: string]: any;
}
interface Commit {
hash?: string;
date?: string;
message?: string;
subject?: string;
body?: string;
type?: string;
scope?: string;
notes?: Array<{ title: string; text: string }>;
references?: Array<{ issue: string; action: string }>;
gitTags?: string;
committerDate?: string;
}
type Logger = (source: string, messages: string | string[]) => void;
type PackageTransform = (pkg: Package) => Package;
type CommitTransformFunction = (
commit: Commit,
params: Params
) => Partial<Commit> | null | Promise<Partial<Commit> | null>;
interface Params extends Preset {
commits: GetCommitsParams;
options: Options;
context?: Context;
repository?: Partial<HostedGitInfo> | null;
package?: Package;
}
interface PresetParams<T = any> {
name?: string;
[key: string]: any;
}
interface PresetModuleLoader {
(name: string): Promise<any>;
}
interface Details<T> {
context: Context;
commits: T[];
keyCommit?: T;
}Creates a new changelog generator instance.
interface ConventionalGitClient {
cwd: string;
getSemverTags(params?: GetSemverTagsParams): AsyncGenerator<string>;
getCommits(params: GetCommitsParams, parserOptions?: ParserStreamOptions): AsyncGenerator<Commit>;
verify(ref: string): Promise<void>;
getConfig(key: string): Promise<string>;
}
/**
* Creates a new ConventionalChangelog instance
* @param cwdOrGitClient - Working directory path or existing git client instance
*/
constructor(cwdOrGitClient?: string | ConventionalGitClient);Usage Example:
import { ConventionalChangelog } from "conventional-changelog";
// Use current working directory
const changelog = new ConventionalChangelog();
// Use specific directory
const changelog2 = new ConventionalChangelog("/path/to/repo");
// Use existing git client
import { ConventionalGitClient } from "@conventional-changelog/git-client";
const gitClient = new ConventionalGitClient("/path/to/repo");
const changelog3 = new ConventionalChangelog(gitClient);Methods for setting up the changelog generation configuration.
/**
* Load configuration from a preset
* @param preset - Preset name or configuration
* @param loader - Optional custom preset loader
*/
loadPreset<PresetCreatorParams extends UnknownPresetCreatorParams = UnknownPresetCreatorParams>(
preset: PresetParams<PresetCreatorParams>,
loader?: PresetModuleLoader
): this;
/**
* Set configuration directly
* @param config - Configuration object or promise
*/
config(config: Preset | Promise<Preset>): this;
/**
* Read package.json automatically from working directory
* @param transform - Optional package data transformer
*/
readPackage(transform?: PackageTransform): this;
/**
* Read package.json from specific path
* @param path - Path to package.json file
* @param transform - Optional package data transformer
*/
readPackage(path?: string, transform?: PackageTransform): this;
/**
* Set package data manually
* @param pkg - Package data object
*/
package(pkg: Record<string, unknown>): this;
/**
* Read repository information from git configuration
*/
readRepository(): this;
/**
* Set repository information manually
* @param infoOrGitUrl - Repository info object or git URL string
*/
repository(infoOrGitUrl: string | Partial<HostedGitInfo>): this;
/**
* Set changelog generation options
* @param options - Generation options
*/
options(options: Options): this;
/**
* Set writer context data
* @param context - Context data for template rendering
*/
context(context: Context): this;
/**
* Set parameters for retrieving semver tags
* @param params - Tag retrieval parameters
*/
tags(params: GetSemverTagsParams): this;
/**
* Set parameters for retrieving commits
* @param params - Commit retrieval parameters
* @param parserOptions - Optional parser configuration
*/
commits(params: GetCommitsParams, parserOptions?: ParserStreamOptions): this;
/**
* Set writer options for output formatting
* @param params - Writer configuration options
*/
writer(params: WriterOptions): this;Configuration Example:
import { ConventionalChangelog } from "conventional-changelog";
const changelog = new ConventionalChangelog()
.loadPreset("angular") // Use Angular commit convention
.readPackage() // Read package.json automatically
.readRepository() // Read git repository info
.options({
releaseCount: 2, // Generate last 2 releases
append: false, // Don't append to existing changelog
outputUnreleased: true // Include unreleased changes
})
.context({
version: "1.2.0", // Override version
date: new Date().toISOString() // Set release date
});Methods for generating changelog output in various formats.
/**
* Generate changelog as async generator of strings
* @param includeDetails - When false, yields changelog markdown strings
*/
write(includeDetails?: false): AsyncGenerator<string, void>;
/**
* Generate changelog as async generator of data objects
* @param includeDetails - When true, yields detailed commit data objects
*/
write(includeDetails: true): AsyncGenerator<Details<Commit>, void>;
/**
* Generate changelog as readable stream
* @param includeDetails - Whether to include detailed data objects
*/
writeStream(includeDetails?: boolean): NodeJS.ReadableStream;Generation Examples:
// Generate as markdown strings
for await (const chunk of changelog.write()) {
console.log(chunk);
}
// Generate as data objects for custom processing
for await (const details of changelog.write(true)) {
console.log("Version:", details.context.version);
console.log("Commits:", details.commits.length);
console.log("Keycommit:", details.keyCommit);
}
// Generate as stream for file writing
import { createWriteStream } from "fs";
const output = createWriteStream("CHANGELOG.md");
changelog.writeStream().pipe(output);The ConventionalChangelog class supports method chaining for concise configuration:
const changelog = new ConventionalChangelog("/path/to/repo")
.loadPreset("angular")
.readPackage("./custom/package.json")
.repository("https://github.com/user/repo.git")
.options({ releaseCount: 3, append: false })
.tags({ prefix: "v" })
.commits({ from: "v1.0.0" });
// Generate changelog
const changelogContent = [];
for await (const chunk of changelog.write()) {
changelogContent.push(chunk);
}
console.log(changelogContent.join(""));import { ConventionalChangelog } from "conventional-changelog";
const changelog = new ConventionalChangelog()
.loadPreset("angular")
.options({
transformCommit: (commit, params) => {
// Custom commit filtering and transformation
if (commit.type === "chore") return null; // Skip chore commits
return {
...commit,
subject: commit.subject?.toUpperCase() // Transform subject
};
}
});const changelog = new ConventionalChangelog()
.loadPreset("angular")
.options({
warn: (namespace, message) => {
console.warn(`[${namespace}] ${message}`);
},
debug: (namespace, message) => {
console.debug(`[${namespace}] ${message}`);
}
});