conventional-changelog-core
Advanced tools
Comparing version
69
index.js
@@ -7,6 +7,4 @@ 'use strict' | ||
const conventionalChangelogWriter = require('conventional-changelog-writer') | ||
const _ = require('lodash') | ||
const stream = require('stream') | ||
const through = require('through2') | ||
const execFileSync = require('child_process').execFileSync | ||
const { Readable, Transform } = require('stream') | ||
const { execFileSync } = require('child_process') | ||
@@ -17,3 +15,3 @@ const mergeConfig = require('./lib/merge-config') | ||
const readable = new stream.Readable({ | ||
const readable = new Readable({ | ||
objectMode: writerOpts.includeDetails | ||
@@ -25,3 +23,3 @@ }) | ||
let commitsStream = new stream.Readable({ | ||
let commitsStream = new Readable({ | ||
objectMode: true | ||
@@ -32,6 +30,7 @@ }) | ||
function commitsRange (from, to) { | ||
return gitRawCommits(_.merge({}, gitRawCommitsOpts, { | ||
return gitRawCommits({ | ||
...gitRawCommitsOpts, | ||
from: from, | ||
to: to | ||
})) | ||
}) | ||
.on('error', function (err) { | ||
@@ -107,9 +106,15 @@ if (!commitsErrorThrown) { | ||
// so we don't need to transform here | ||
.pipe(through.obj(function (chunk, enc, cb) { | ||
try { | ||
options.transform.call(this, chunk, cb) | ||
} catch (err) { | ||
cb(err) | ||
} | ||
})) | ||
.pipe( | ||
new Transform({ | ||
objectMode: true, | ||
highWaterMark: 16, | ||
transform (chunk, enc, cb) { | ||
try { | ||
options.transform.call(this, chunk, cb) | ||
} catch (err) { | ||
cb(err) | ||
} | ||
} | ||
}) | ||
) | ||
.on('error', function (err) { | ||
@@ -124,19 +129,23 @@ err.message = 'Error in options.transform: ' + err.message | ||
}) | ||
.pipe(through({ | ||
objectMode: writerOpts.includeDetails | ||
}, function (chunk, enc, cb) { | ||
try { | ||
readable.push(chunk) | ||
} catch (err) { | ||
setImmediate(function () { | ||
throw err | ||
}) | ||
} | ||
.pipe( | ||
new Transform({ | ||
objectMode: writerOpts.includeDetails, | ||
transform (chunk, enc, cb) { | ||
try { | ||
readable.push(chunk) | ||
} catch (err) { | ||
setImmediate(function () { | ||
throw err | ||
}) | ||
} | ||
cb() | ||
}, function (cb) { | ||
readable.push(null) | ||
cb() | ||
}, | ||
flush (cb) { | ||
readable.push(null) | ||
cb() | ||
})) | ||
cb() | ||
} | ||
}) | ||
) | ||
}) | ||
@@ -143,0 +152,0 @@ .catch(function (err) { |
'use strict' | ||
const { promisify } = require('util') | ||
const dateFormat = require('dateformat') | ||
@@ -6,3 +7,2 @@ const getPkgRepo = require('get-pkg-repo') | ||
const normalizePackageData = require('normalize-package-data') | ||
const Q = require('q') | ||
let gitRemoteOriginUrl | ||
@@ -12,10 +12,7 @@ try { | ||
} catch (err) { | ||
gitRemoteOriginUrl = function () { | ||
return Q.reject(err) | ||
} | ||
gitRemoteOriginUrl = () => Promise.reject(err) | ||
} | ||
const readPkg = require('read-pkg') | ||
const readPkgUp = require('read-pkg-up') | ||
const URL = require('url').URL | ||
const _ = require('lodash') | ||
const { URL } = require('url') | ||
@@ -25,4 +22,9 @@ const rhosts = /github|bitbucket|gitlab/i | ||
function semverTagsPromise (options) { | ||
return Q.Promise(function (resolve, reject) { | ||
gitSemverTags({ lernaTags: !!options.lernaPackage, package: options.lernaPackage, tagPrefix: options.tagPrefix, skipUnstable: options.skipUnstable }, function (err, result) { | ||
return new Promise((resolve, reject) => { | ||
gitSemverTags({ | ||
lernaTags: !!options.lernaPackage, | ||
package: options.lernaPackage, | ||
tagPrefix: options.tagPrefix, | ||
skipUnstable: options.skipUnstable | ||
}, (err, result) => { | ||
if (err) { | ||
@@ -57,3 +59,3 @@ reject(err) | ||
function mergeConfig (options, context, gitRawCommitsOpts, parserOpts, writerOpts, gitRawExecOpts) { | ||
async function mergeConfig (options, context, gitRawCommitsOpts, parserOpts, writerOpts, gitRawExecOpts) { | ||
let configPromise | ||
@@ -68,8 +70,3 @@ let pkgPromise | ||
options = _.merge({ | ||
pkg: { | ||
transform: function (pkg) { | ||
return pkg | ||
} | ||
}, | ||
options = { | ||
append: false, | ||
@@ -80,3 +77,3 @@ releaseCount: 1, | ||
transform: function (commit, cb) { | ||
if (_.isString(commit.gitTags)) { | ||
if (typeof commit.gitTags === 'string') { | ||
const match = rtag.exec(commit.gitTags) | ||
@@ -96,4 +93,11 @@ rtag.lastIndex = 0 | ||
}, | ||
lernaPackage: null | ||
}, options) | ||
lernaPackage: null, | ||
...options, | ||
pkg: { | ||
transform: function (pkg) { | ||
return pkg | ||
}, | ||
...options?.pkg | ||
} | ||
} | ||
@@ -103,6 +107,6 @@ options.warn = options.warn || options.debug | ||
if (options.config) { | ||
if (_.isFunction(options.config)) { | ||
configPromise = Q.nfcall(options.config) | ||
if (typeof options.config === 'function') { | ||
configPromise = promisify(options.config)() | ||
} else { | ||
configPromise = Q(options.config) | ||
configPromise = Promise.resolve(options.config) | ||
} | ||
@@ -113,242 +117,250 @@ } | ||
if (options.pkg.path) { | ||
pkgPromise = Q(readPkg(options.pkg.path)) | ||
pkgPromise = Promise.resolve(readPkg(options.pkg.path)) | ||
} else { | ||
pkgPromise = Q(readPkgUp()) | ||
pkgPromise = Promise.resolve(readPkgUp()) | ||
} | ||
} | ||
const gitRemoteOriginUrlPromise = Q(gitRemoteOriginUrl()) | ||
const gitRemoteOriginUrlPromise = Promise.resolve(gitRemoteOriginUrl()) | ||
const [ | ||
configObj, | ||
pkgObj, | ||
tagsObj, | ||
gitRemoteOriginUrlObj | ||
] = await Promise.allSettled([ | ||
configPromise, | ||
pkgPromise, | ||
semverTagsPromise(options), | ||
gitRemoteOriginUrlPromise | ||
]) | ||
let config | ||
let pkg | ||
let fromTag | ||
let repo | ||
return Q.allSettled([configPromise, pkgPromise, semverTagsPromise(options), gitRemoteOriginUrlPromise]) | ||
.spread(function (configObj, pkgObj, tagsObj, gitRemoteOriginUrlObj) { | ||
let config | ||
let pkg | ||
let fromTag | ||
let repo | ||
let hostOpts | ||
let hostOpts | ||
let gitSemverTags = [] | ||
let gitSemverTags = [] | ||
if (configPromise) { | ||
if (configObj.status === 'fulfilled') { | ||
config = configObj.value | ||
} else { | ||
options.warn('Error in config' + configObj.reason.toString()) | ||
config = {} | ||
} | ||
} else { | ||
config = {} | ||
} | ||
if (configPromise) { | ||
if (configObj.state === 'fulfilled') { | ||
config = configObj.value | ||
} else { | ||
options.warn('Error in config' + configObj.reason.toString()) | ||
config = {} | ||
} | ||
context = { | ||
...context, | ||
...config.context | ||
} | ||
if (options.pkg) { | ||
if (pkgObj.status === 'fulfilled') { | ||
if (options.pkg.path) { | ||
pkg = pkgObj.value | ||
} else { | ||
config = {} | ||
pkg = pkgObj.value.pkg || {} | ||
} | ||
context = _.assign(context, config.context) | ||
pkg = options.pkg.transform(pkg) | ||
} else if (options.pkg.path) { | ||
options.warn(pkgObj.reason.toString()) | ||
} | ||
} | ||
if (options.pkg) { | ||
if (pkgObj.state === 'fulfilled') { | ||
if (options.pkg.path) { | ||
pkg = pkgObj.value | ||
} else { | ||
pkg = pkgObj.value.pkg || {} | ||
} | ||
if ((!pkg || !pkg.repository || !pkg.repository.url) && gitRemoteOriginUrlObj.status === 'fulfilled') { | ||
pkg = pkg || {} | ||
pkg.repository = pkg.repository || {} | ||
pkg.repository.url = gitRemoteOriginUrlObj.value | ||
normalizePackageData(pkg) | ||
} | ||
pkg = options.pkg.transform(pkg) | ||
} else if (options.pkg.path) { | ||
options.warn(pkgObj.reason.toString()) | ||
} | ||
} | ||
if (pkg) { | ||
context.version = context.version || pkg.version | ||
if ((!pkg || !pkg.repository || !pkg.repository.url) && gitRemoteOriginUrlObj.state === 'fulfilled') { | ||
pkg = pkg || {} | ||
pkg.repository = pkg.repository || {} | ||
pkg.repository.url = gitRemoteOriginUrlObj.value | ||
normalizePackageData(pkg) | ||
} | ||
try { | ||
repo = getPkgRepo(pkg) | ||
} catch (err) { | ||
repo = {} | ||
} | ||
if (pkg) { | ||
context.version = context.version || pkg.version | ||
try { | ||
repo = getPkgRepo(pkg) | ||
} catch (err) { | ||
repo = {} | ||
} | ||
if (repo.browse) { | ||
const browse = repo.browse() | ||
if (!context.host) { | ||
if (repo.domain) { | ||
const parsedBrowse = new URL(browse) | ||
if (parsedBrowse.origin.indexOf('//') !== -1) { | ||
context.host = parsedBrowse.protocol + '//' + repo.domain | ||
} else { | ||
context.host = parsedBrowse.protocol + repo.domain | ||
} | ||
} else { | ||
context.host = null | ||
} | ||
} | ||
context.owner = context.owner || repo.user || '' | ||
context.repository = context.repository || repo.project | ||
if (repo.host && repo.project && repo.user) { | ||
context.repoUrl = browse | ||
if (repo.browse) { | ||
const browse = repo.browse() | ||
if (!context.host) { | ||
if (repo.domain) { | ||
const parsedBrowse = new URL(browse) | ||
if (parsedBrowse.origin.indexOf('//') !== -1) { | ||
context.host = parsedBrowse.protocol + '//' + repo.domain | ||
} else { | ||
context.repoUrl = context.host | ||
context.host = parsedBrowse.protocol + repo.domain | ||
} | ||
} else { | ||
context.host = null | ||
} | ||
context.packageData = pkg | ||
} | ||
context.owner = context.owner || repo.user || '' | ||
context.repository = context.repository || repo.project | ||
if (repo.host && repo.project && repo.user) { | ||
context.repoUrl = browse | ||
} else { | ||
context.repoUrl = context.host | ||
} | ||
} | ||
context.version = context.version || '' | ||
context.packageData = pkg | ||
} | ||
if (tagsObj.state === 'fulfilled') { | ||
gitSemverTags = context.gitSemverTags = tagsObj.value | ||
fromTag = gitSemverTags[options.releaseCount - 1] | ||
const lastTag = gitSemverTags[0] | ||
context.version = context.version || '' | ||
if (lastTag === context.version || lastTag === 'v' + context.version) { | ||
if (options.outputUnreleased) { | ||
context.version = 'Unreleased' | ||
} else { | ||
options.outputUnreleased = false | ||
} | ||
} | ||
} | ||
if (tagsObj.status === 'fulfilled') { | ||
gitSemverTags = context.gitSemverTags = tagsObj.value | ||
fromTag = gitSemverTags[options.releaseCount - 1] | ||
const lastTag = gitSemverTags[0] | ||
if (!_.isBoolean(options.outputUnreleased)) { | ||
options.outputUnreleased = true | ||
if (lastTag === context.version || lastTag === 'v' + context.version) { | ||
if (options.outputUnreleased) { | ||
context.version = 'Unreleased' | ||
} else { | ||
options.outputUnreleased = false | ||
} | ||
} | ||
} | ||
if (context.host && (!context.issue || !context.commit || !parserOpts || !parserOpts.referenceActions)) { | ||
let type | ||
if (typeof options.outputUnreleased !== 'boolean') { | ||
options.outputUnreleased = true | ||
} | ||
if (context.host) { | ||
const match = context.host.match(rhosts) | ||
if (match) { | ||
type = match[0] | ||
} | ||
} else if (repo && repo.type) { | ||
type = repo.type | ||
} | ||
if (context.host && (!context.issue || !context.commit || !parserOpts || !parserOpts.referenceActions)) { | ||
let type | ||
if (type) { | ||
hostOpts = require('../hosts/' + type) | ||
context = _.assign({ | ||
issue: hostOpts.issue, | ||
commit: hostOpts.commit | ||
}, context) | ||
} else { | ||
options.warn('Host: "' + context.host + '" does not exist') | ||
hostOpts = {} | ||
} | ||
} else { | ||
hostOpts = {} | ||
if (context.host) { | ||
const match = context.host.match(rhosts) | ||
if (match) { | ||
type = match[0] | ||
} | ||
} else if (repo && repo.type) { | ||
type = repo.type | ||
} | ||
if (context.resetChangelog) { | ||
fromTag = null | ||
if (type) { | ||
hostOpts = require('../hosts/' + type) | ||
context = { | ||
issue: hostOpts.issue, | ||
commit: hostOpts.commit, | ||
...context | ||
} | ||
} else { | ||
options.warn('Host: "' + context.host + '" does not exist') | ||
hostOpts = {} | ||
} | ||
} else { | ||
hostOpts = {} | ||
} | ||
gitRawCommitsOpts = _.assign({ | ||
format: '%B%n-hash-%n%H%n-gitTags-%n%d%n-committerDate-%n%ci', | ||
from: fromTag, | ||
merges: false, | ||
debug: options.debug | ||
}, | ||
config.gitRawCommitsOpts, | ||
gitRawCommitsOpts | ||
) | ||
if (context.resetChangelog) { | ||
fromTag = null | ||
} | ||
if (options.append) { | ||
gitRawCommitsOpts.reverse = gitRawCommitsOpts.reverse || true | ||
} | ||
gitRawCommitsOpts = { | ||
format: '%B%n-hash-%n%H%n-gitTags-%n%d%n-committerDate-%n%ci', | ||
from: fromTag, | ||
merges: false, | ||
debug: options.debug, | ||
...config.gitRawCommitsOpts, | ||
...gitRawCommitsOpts | ||
} | ||
parserOpts = _.assign( | ||
{}, config.parserOpts, { | ||
warn: options.warn | ||
}, | ||
parserOpts) | ||
if (options.append) { | ||
gitRawCommitsOpts.reverse = gitRawCommitsOpts.reverse || true | ||
} | ||
if (hostOpts.referenceActions && parserOpts) { | ||
parserOpts.referenceActions = hostOpts.referenceActions | ||
} | ||
parserOpts = { | ||
...config.parserOpts, | ||
warn: options.warn, | ||
...parserOpts | ||
} | ||
if (_.isEmpty(parserOpts.issuePrefixes) && hostOpts.issuePrefixes) { | ||
parserOpts.issuePrefixes = hostOpts.issuePrefixes | ||
} | ||
if (hostOpts.referenceActions && parserOpts) { | ||
parserOpts.referenceActions = hostOpts.referenceActions | ||
} | ||
writerOpts = _.assign({ | ||
finalizeContext: function (context, writerOpts, filteredCommits, keyCommit, originalCommits) { | ||
const firstCommit = originalCommits[0] | ||
const lastCommit = originalCommits[originalCommits.length - 1] | ||
const firstCommitHash = firstCommit ? firstCommit.hash : null | ||
const lastCommitHash = lastCommit ? lastCommit.hash : null | ||
if (!parserOpts.issuePrefixes?.length && hostOpts.issuePrefixes) { | ||
parserOpts.issuePrefixes = hostOpts.issuePrefixes | ||
} | ||
if ((!context.currentTag || !context.previousTag) && keyCommit) { | ||
const match = /tag:\s*(.+?)[,)]/gi.exec(keyCommit.gitTags) | ||
const currentTag = context.currentTag | ||
context.currentTag = currentTag || match ? match[1] : null | ||
const index = gitSemverTags.indexOf(context.currentTag) | ||
writerOpts = { | ||
finalizeContext: function (context, writerOpts, filteredCommits, keyCommit, originalCommits) { | ||
const firstCommit = originalCommits[0] | ||
const lastCommit = originalCommits[originalCommits.length - 1] | ||
const firstCommitHash = firstCommit ? firstCommit.hash : null | ||
const lastCommitHash = lastCommit ? lastCommit.hash : null | ||
// if `keyCommit.gitTags` is not a semver | ||
if (index === -1) { | ||
context.currentTag = currentTag || null | ||
} else { | ||
const previousTag = context.previousTag = gitSemverTags[index + 1] | ||
if ((!context.currentTag || !context.previousTag) && keyCommit) { | ||
const match = /tag:\s*(.+?)[,)]/gi.exec(keyCommit.gitTags) | ||
const currentTag = context.currentTag | ||
context.currentTag = currentTag || match ? match[1] : null | ||
const index = gitSemverTags.indexOf(context.currentTag) | ||
if (!previousTag) { | ||
if (options.append) { | ||
context.previousTag = context.previousTag || firstCommitHash | ||
} else { | ||
context.previousTag = context.previousTag || lastCommitHash | ||
} | ||
} | ||
} | ||
} else { | ||
context.previousTag = context.previousTag || gitSemverTags[0] | ||
// if `keyCommit.gitTags` is not a semver | ||
if (index === -1) { | ||
context.currentTag = currentTag || null | ||
} else { | ||
const previousTag = context.previousTag = gitSemverTags[index + 1] | ||
if (context.version === 'Unreleased') { | ||
if (options.append) { | ||
context.currentTag = context.currentTag || lastCommitHash | ||
} else { | ||
context.currentTag = context.currentTag || firstCommitHash | ||
} | ||
} else if (!context.currentTag) { | ||
if (options.lernaPackage) { | ||
context.currentTag = options.lernaPackage + '@' + context.version | ||
} else if (options.tagPrefix) { | ||
context.currentTag = options.tagPrefix + context.version | ||
} else { | ||
context.currentTag = guessNextTag(gitSemverTags[0], context.version) | ||
} | ||
if (!previousTag) { | ||
if (options.append) { | ||
context.previousTag = context.previousTag || firstCommitHash | ||
} else { | ||
context.previousTag = context.previousTag || lastCommitHash | ||
} | ||
} | ||
} | ||
} else { | ||
context.previousTag = context.previousTag || gitSemverTags[0] | ||
if (!_.isBoolean(context.linkCompare) && context.previousTag && context.currentTag) { | ||
context.linkCompare = true | ||
if (context.version === 'Unreleased') { | ||
if (options.append) { | ||
context.currentTag = context.currentTag || lastCommitHash | ||
} else { | ||
context.currentTag = context.currentTag || firstCommitHash | ||
} | ||
} else if (!context.currentTag) { | ||
if (options.lernaPackage) { | ||
context.currentTag = options.lernaPackage + '@' + context.version | ||
} else if (options.tagPrefix) { | ||
context.currentTag = options.tagPrefix + context.version | ||
} else { | ||
context.currentTag = guessNextTag(gitSemverTags[0], context.version) | ||
} | ||
} | ||
} | ||
return context | ||
}, | ||
debug: options.debug | ||
}, | ||
config.writerOpts, { | ||
reverse: options.append, | ||
doFlush: options.outputUnreleased | ||
}, | ||
writerOpts | ||
) | ||
if (typeof context.linkCompare !== 'boolean' && context.previousTag && context.currentTag) { | ||
context.linkCompare = true | ||
} | ||
return { | ||
options: options, | ||
context: context, | ||
gitRawCommitsOpts: gitRawCommitsOpts, | ||
parserOpts: parserOpts, | ||
writerOpts: writerOpts, | ||
gitRawExecOpts: gitRawExecOpts | ||
} | ||
}) | ||
return context | ||
}, | ||
debug: options.debug, | ||
...config.writerOpts, | ||
reverse: options.append, | ||
doFlush: options.outputUnreleased, | ||
...writerOpts | ||
} | ||
return { | ||
options: options, | ||
context: context, | ||
gitRawCommitsOpts: gitRawCommitsOpts, | ||
parserOpts: parserOpts, | ||
writerOpts: writerOpts, | ||
gitRawExecOpts: gitRawExecOpts | ||
} | ||
} | ||
module.exports = mergeConfig |
{ | ||
"name": "conventional-changelog-core", | ||
"version": "4.2.4", | ||
"version": "5.0.0", | ||
"description": "conventional-changelog core", | ||
@@ -16,3 +16,3 @@ "repository": { | ||
"engines": { | ||
"node": ">=10" | ||
"node": ">=14" | ||
}, | ||
@@ -31,22 +31,19 @@ "license": "MIT", | ||
"add-stream": "^1.0.0", | ||
"conventional-changelog-writer": "^5.0.0", | ||
"conventional-commits-parser": "^3.2.0", | ||
"dateformat": "^3.0.0", | ||
"get-pkg-repo": "^4.0.0", | ||
"git-raw-commits": "^2.0.8", | ||
"conventional-changelog-writer": "^5.0.1", | ||
"conventional-commits-parser": "^3.2.4", | ||
"dateformat": "^3.0.3", | ||
"get-pkg-repo": "^4.2.1", | ||
"git-raw-commits": "^2.0.11", | ||
"git-remote-origin-url": "^2.0.0", | ||
"git-semver-tags": "^4.1.1", | ||
"lodash": "^4.17.15", | ||
"normalize-package-data": "^3.0.0", | ||
"q": "^1.5.1", | ||
"normalize-package-data": "^3.0.3", | ||
"read-pkg": "^3.0.0", | ||
"read-pkg-up": "^3.0.0", | ||
"through2": "^4.0.0" | ||
"read-pkg-up": "^3.0.0" | ||
}, | ||
"devDependencies": { | ||
"conventional-changelog-angular": "^5.0.13" | ||
}, | ||
"scripts": { | ||
"test-windows": "mocha --timeout 30000" | ||
}, | ||
"devDependencies": { | ||
"conventional-changelog-angular": "^5.0.12" | ||
} | ||
} | ||
} |
@@ -1,2 +0,2 @@ | ||
# [![NPM version][npm-image]][npm-url] [![Build Status: Linux][travis-image]][travis-url] [![Build Status: Windows][appveyor-image]][appveyor-url] [![Dependency Status][daviddm-image]][daviddm-url] [![Coverage Status][coveralls-image]][coveralls-url] | ||
# [![NPM version][npm-image]][npm-url] [![Build Status: Linux][travis-image]][travis-url] [![Build Status: Windows][appveyor-image]][appveyor-url] [![Dependency Status][daviddm-image]][daviddm-url] [![Coverage Status][coverage-image]][coverage-url] | ||
@@ -105,3 +105,3 @@ > [conventional-changelog](https://github.com/conventional-changelog/conventional-changelog) core | ||
`this` arg of through2. | ||
`this` arg of transform handler of a stream. | ||
@@ -255,3 +255,3 @@ ##### outputUnreleased | ||
[daviddm-url]: https://david-dm.org/conventional-changelog/conventional-changelog-core | ||
[coveralls-image]: https://coveralls.io/repos/conventional-changelog/conventional-changelog-core/badge.svg | ||
[coveralls-url]: https://coveralls.io/r/conventional-changelog/conventional-changelog-core | ||
[coverage-image]: https://coveralls.io/repos/github/conventional-changelog/conventional-changelog/badge.svg?branch=master | ||
[coverage-url]: https://coveralls.io/github/conventional-changelog/conventional-changelog?branch=master |
11
-21.43%497
4.63%25794
-47.63%8
-11.11%- Removed
- Removed
- Removed
- Removed
Updated
Updated
Updated