relion 0.29.0 → 0.31.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -114,6 +114,7 @@ interface Context {
114
114
  package?: PackageInfo;
115
115
  commitRefLinks?: boolean;
116
116
  footerChangelogUrl?: boolean;
117
+ isMonorepo?: boolean;
117
118
  [key: string]: unknown;
118
119
  }
119
120
  interface ResolvedContext extends Required<Context> {
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import{existsSync as e,readFileSync as t,writeFileSync as n}from"node:fs";import r from"handlebars";import i from"semver";import{createHash as a}from"node:crypto";import{execSync as o}from"node:child_process";import s from"node:readline";const c=/(?<version>\d+\.\d+\.\d+.*)/,l={breaking:{title:`⚠️ BREAKING CHANGES`,commitType:`breaking`},feat:{title:`✨ Features`,commitType:`feat`},fix:{title:`🩹 Fixes`,commitType:`fix`},perf:{title:`⚡ Performance`,commitType:`perf`},revert:{title:`♻️ Reverts`,commitType:`revert`},refactor:{title:`🚜 Refactoring`,commitType:`refactor`},build:{title:`📦 Build`,commitType:`build`},docs:{title:`📚 Documentation`,commitType:`docs`},style:{title:`🎨 Style`,commitType:`style`},test:{title:`🧪 Tests`,commitType:`test`},ci:{title:`🚀 CI`,commitType:`ci`},types:{title:`🏷️ Types`,commitType:`types`},deps:{title:`🧩 Dependencies`,commitType:`chore`,filter:e=>!!e.scope?.includes(`deps`)},chore:{title:`🛠️ Chores`,commitType:`chore`},misc:{title:`⚙️ Miscellaneous`,commitType:`*`,filter:e=>e.type!==`release`&&e.scope!==`release`}},u={file:`CHANGELOG.md`,output:`file`,commitRange:`unreleased`,extractFromFile:!1,sections:l,header:`# Changelog
2
2
 
3
3
 
4
- `,releasePattern:/(?<header>## [^\n]*?\[[^\n]*?{{version}}[^\n]*?\].*?\n+)(?<body>.*?)(?<footer>##### .*?(?:\n+|$))/s,commitRefLinkPattern:/\[`?(#?\w+?)`?\]\(.+?\)/g,groupCommitsByScope:!0,review:!1,helpers:{eq:(e,t)=>e===t,repeat:(e,t)=>e.repeat(t),isArray:e=>Array.isArray(e),isSingle:e=>e.length===1,or:(...e)=>e.slice(0,-1).some(Boolean),not:e=>!e,tagToUrlFragment:e=>`--${e.replace(` `,`-`).replace(/(\.|@)/g,``)}-`,getChangelogUrl:e=>{let t=e.replace(/#.*/,``);return t.includes(`/blob/main`)||(t+=`/blob/main`),`${t}/CHANGELOG.md`},toSentenceCase:function(e){let t=e.fn(this);return`${t.charAt(0).toUpperCase()}${t.slice(1)}${t.endsWith(`.`)?``:`.`}`}},partials:{br:`
5
- `,scope:`{{#if scope}}**{{scope}}**: {{/if}}`,commit:`{{{subject}}} {{" "}}
4
+ `,releasePattern:/(?<header>## [^\n]*?\[[^\n]*?{{version}}[^\n]*?\].*?\n+)(?<body>.*?)(?<footer>##### .*?(?:\n+|$))/s,commitRefLinkPattern:/\[`?(#?\w+?)`?\]\(.+?\)/g,groupCommitsByScope:!0,review:!1,helpers:{eq:(e,t)=>e===t,repeat:(e,t)=>e.repeat(t),replace:(e,t,n)=>n.replace(new RegExp(e),t),isArray:e=>Array.isArray(e),isSingle:e=>e.length===1,or:(...e)=>e.slice(0,-1).some(Boolean),not:e=>!e,tagToUrlFragment:e=>`--${e.replace(` `,`-`).replace(/(\.|@)/g,``)}-`,getChangelogUrl:e=>{let t=e.replace(/#.*/,``);return t.includes(`/blob/main`)||(t+=`/blob/main`),`${t}/CHANGELOG.md`},toSentenceCase:function(e){let t=e.fn(this);return`${t.charAt(0).toUpperCase()}${t.slice(1)}${t.endsWith(`.`)?``:`.`}`}},partials:{br:`
5
+ `,releaseTitle:`{{tag}}`,scope:`{{#if scope}}**{{scope}}**: {{/if}}`,commit:`{{{subject}}} {{" "}}
6
6
  {{~#if @root.commitRefLinks~}}
7
7
  [\`{{hash}}\`]({{@root.repo.homepage}}/commit/{{hash}})
8
8
  {{~else~}}
@@ -22,7 +22,7 @@ import{existsSync as e,readFileSync as t,writeFileSync as n}from"node:fs";import
22
22
  {{raw}}
23
23
  {{~/if}}
24
24
  {{~#if @last}}){{else}}, {{/if}}
25
- {{~/each}}`,changelogUrl:`{{getChangelogUrl package.homepage}}`,releaseChangelogUrl:`{{>changelogUrl}}#{{tagToUrlFragment tag}}`,breakingChangesIndicator:`<sup>[{{breakingChangeIndex}}]</sup>`}},d={message:`chore(release): {{newTag}}`,signOff:!1,gpgSign:!1,stageAll:!0,extraArgs:null},f={name:`{{newTag}}`,message:`{{commitMessage}}`,gpgSign:!1,force:!1,extraArgs:null},p=[...[{file:/package\.json$/,pattern:/(^.*?"name": "(?<name>.*?)".*"version": ")(?<version>.*?)(".*?"homepage": "(?<homepage>.*?)")/s,replacement:`$1{{newVersion}}$4`}],{file:/package-lock\.json$/,pattern:/(^.*?"version": "|"packages".*?"".*"version": ")(.*?)(")/gs,replacement:`$1{{newVersion}}$3`}],m={lifecycle:[`bump`,`changelog`,`commit`,`tag`],bump:[`package.json`],versionSource:`manifestFile`,manifestFile:`./package.json`,tagFormat:`v{{version}}`,commitsScope:`.`,prevReleaseTagPattern:`{{newTagFormat}}`,zeroMajorBreakingIsMinor:!0,dryRun:!1,logLevel:`info`,context:{commitRefLinks:!0,footerChangelogUrl:!1},commitsParser:{headerPattern:/^(?<type>\w+)(?:\((?<scope>.+)\))?(?<bang>!)?: (?<subject>.+)/s,breakingChangesPattern:/^BREAKING CHANGES?:\s*(?<content>.+)/ms,breakingChangeListPattern:/- (.+)/g,tagPattern:/tag: (?<tag>.*?)[,)]/g,coAuthorPattern:/Co-authored-by: (?<name>.+?) <(?<email>.+)>/g,signerPattern:/Signed-off-by: (?<name>.+?) <(?<email>.+)>/g,ghEmailPattern:/^(?:\d+\+)?(?<username>.+)@users\.noreply\.github\.com$/,remoteUrlPattern:/^(https:\/\/|git@)(?<host>[^/:]+)[/:](?<owner>.+?)\/(?<name>.+?)(?:\..*)?$/,refPattern:/^(?<action>.+?) (?<labels>.+)$/gm,refLabelPattern:/(?:(?<owner>\S+?)\/(?<repo>\S+?))?#(?<number>\d+)/g,refActionPattern:/^(Fixes|Closes|Refs)/i,dateSource:`authorDate`,dateFormat:`US`,revertCommitBodyPattern:/^This reverts commit (?<hash>.{7})/m}},h=e=>C(v(_(ie(g(e))))),g=e=>{let t=e.profile??`default`,n=e[`_${t}`];if(!n){if(e.profile===void 0)return e;throw Error(`Profile "${t}" not found in configuration.`)}let r=(t,...r)=>{let i=e=>Object.prototype.toString.call(e)===`[object Object]`,a=(e,t)=>{let n=i(e),r=i(t);return n&&r?{...e,...t}:t??e},o=e[t],s=n[t],c=a(o,s);if(c!==void 0)return r.forEach(e=>{c[e]=a(o?.[e],s?.[e])}),c};return{...e,...n,commitsParser:r(`commitsParser`),changelog:r(`changelog`,`partials`,`helpers`),commit:r(`commit`),tag:r(`tag`),context:r(`context`)}},_=e=>{let t=e=>{if(typeof e==`object`)return e;let t=p.find(t=>t.file.test(e));if(t)return{...t,file:e};throw Error(`File ${e} doesn't match any default versioned files. Please provide a custom pattern for this file.`)},n=t(e.manifestFile),r=e.changelog?.releasePattern,i=e.tag?.message,a=e.prevReleaseTagPattern===`{{newTagFormat}}`?e.tagPrefix===void 0?new RegExp(e.tagFormat.replace(`{{version}}`,c.source)):RegExp(`${e.tagPrefix}${c.source}`):e.prevReleaseTagPattern;return{...e,manifestFile:n,bump:e.lifecycle.includes(`bump`)?e.bump?e.bump.map(t):[n]:void 0,changelog:e.changelog?{...e.changelog,compiledPartials:X(e.changelog,e.context),latestReleasePattern:new RegExp(r.source.replace(`{{version}}`,``),r.flags)}:void 0,tag:e.tag?{...e.tag,message:i===`{{commitMessage}}`?e.commit?.message??i:i}:void 0,prevReleaseTagPattern:a}},v=e=>{let n=e.context,r=B(e.commitsParser.remoteUrlPattern),i=e.manifestFile.pattern.exec(t(e.manifestFile.file,`utf-8`))?.groups,a=n.currentVersion??(e.versionSource===`latest-release-tag`?T(U(e.prevReleaseTagPattern)[0],e.prevReleaseTagPattern)??`0.0.0`:w(e.manifestFile));K(`Current version (from ${e.versionSource===`latest-release-tag`?`latest release tag`:`'${e.manifestFile.file}'`}): '${a}'`);let o=n.currentTag??U(e.prevReleaseTagPattern)[0],s=n.newVersion??E(e,a,e.commitsScope),c=n.newTag??(e.tagPrefix===void 0?e.tagFormat.replace(`{{version}}`,s):e.tagPrefix+s),l=e.changelog?e.changelog.commitRange:`unreleased`,u=y(n.commits?n.commits.map(t=>typeof t==`object`&&`message`in t||typeof t==`string`?N(t,e.commitsParser,e.prevReleaseTagPattern):t).filter(e=>e!=null):M(l,e.commitsParser,e.prevReleaseTagPattern,e.commitsScope),c,e.commitsParser.revertCommitBodyPattern),d=e.changelog?b(u,e.changelog.sections,e.prevReleaseTagPattern,e.changelog.groupCommitsByScope):null,{commits:f,...p}=n;return{...e,context:{currentVersion:a,currentTag:o,newVersion:s,newTag:c,commits:u,releases:d,commitRefLinks:n.commitRefLinks??!0,footerChangelogUrl:n.footerChangelogUrl??!1,...p,repo:{...r,...e.context.repo},package:{...i,...e.context.package}}}},y=(e,t,n)=>{let r=0,i=[];return e.map(a=>{let o=null,s=e.findIndex(e=>e.type===`revert`&&n.exec(e.body??``)?.groups?.hash===a.hash),c=s===-1?void 0:e[s];if(c&&(o=c.associatedReleaseTag===a.associatedReleaseTag?`inTheSameRelease`:`inOtherRelease`),o===`inTheSameRelease`){i.push(s);return}return{...a,associatedReleaseTag:a.associatedReleaseTag??t,isReverted:a.isReverted??o,breakingChangeIndex:a.breakingChanges?++r:void 0}}).filter((e,t)=>!!e&&!i.includes(t))},b=(e,t,n,r)=>{let i={};return e.forEach(e=>{let t=e.associatedReleaseTag;t in i?i[t].commits.push(e):i[t]={tag:t,version:T(t,n),date:e.date,commits:[e]}}),Object.values(i).map(({commits:e,...n})=>{let i=x(e,t,r);if(Object.keys(i).length===0)return;let a={};for(let[e,t]of Object.entries(i))if(t.show===`never`)continue;else t.show===`only-breaking`?(t.commits=t.commits.filter(e=>!!e.breakingChanges),t.commits.length&&(t.scopeGroups=S(t.commits),a[e]=t)):a[e]=t;return{...n,commitTypeGroups:a}}).filter(e=>!!e)},x=(e,t,n)=>{let r=Object.fromEntries(Object.entries(t).map(([e,{filter:t,...n}])=>[e,{...n,commits:[]}]));e.forEach(e=>{let n=!!e.breakingChanges,i=!1,a=!1;for(let o in t){if(t[o].filter&&!t[o].filter(e))continue;let s=[t[o].commitType].flat();if(n&&!a&&s.includes(`breaking`)){r[o].commits.push(e),a=!0;continue}if(!i&&(s.includes(e.type)||s.includes(`*`))&&(r[o].commits.push(e),i=!0),i&&(!n||a))return}});let i=Object.entries(r).filter(([e,t])=>t.commits.length);return Object.fromEntries(n?i.map(([e,t])=>[e,{...t,scopeGroups:S(t.commits)}]):i)},S=e=>{let t={};return e.forEach(e=>{let n=e.scope??``;t[n]??=[],t[n].push(e)}),Object.entries(t).map(([e,t])=>({scope:e,commits:t}))},C=e=>({...e,commit:e.commit?{...e.commit,message:r.compile(e.commit.message)(e.context)}:e.commit,tag:e.tag?{...e.tag,name:r.compile(e.tag.name)(e.context),message:r.compile(e.tag.message)(e.context)}:e.tag}),w=e=>{let n=t(e.file,`utf8`),r=e.pattern.exec(n)?.groups?.version;if(!r)throw Error(`Version not found in '${e.file}' with pattern '${e.pattern}'`);if(!i.valid(r))throw Error(`Invalid version format in '${e.file}': '${r}'`);return r},T=(e,t)=>t.exec(e)?.groups?.version,E=(e,t,n)=>{if(e.context.newVersion){if(!i.valid(e.context.newVersion))throw Error(`Invalid release version format: '${e.context.newVersion}'`);return e.context.newVersion}let r;r=e.releaseType?e.releaseType:D(M(`unreleased`,e.commitsParser,e.prevReleaseTagPattern,n),t,e.zeroMajorBreakingIsMinor);let a=O(t,r);return K(`Determined new version: '${a}' (release type: '${r}')`),a},D=(e,t,n)=>{let r=`patch`;return e.some(e=>e.breakingChanges)&&(r=`major`),e.some(e=>e.type===`feat`)&&(r=`minor`),r===`major`&&i.major(t??`1.0.0`)===0&&n?`minor`:r},O=(e,t)=>i.inc(e,t)??(()=>{throw Error(`Failed to calculate new version from '${e}' with release type '${t}'`)})();let k=function(e){return e.G=`valid`,e.B=`bad`,e.U=`valid, unknown validity`,e.X=`valid, expired`,e.Y=`valid, made by expired key`,e.R=`valid, made by revoked key`,e.E=`cannot check (missing key)`,e.N=`no signature`,e}({});const A=new Map;let j;const M=(e,t,n,r)=>{n??=c;let i=Array.isArray(e)?e:V(e,n,r),a=t??m.commitsParser,o=i.map(e=>N(e,a,n)).filter(e=>e!==null);return j=void 0,o},N=(e,t,n)=>{t??=m.commitsParser,n??=c,typeof e==`string`&&(e={message:e});let{tagRefs:r,hash:i=P(e.message)}=e;if(A.has(i))return A.get(i)??null;let a=e.message.trim();if(!a)throw Error(`Message is missing for commit: ${JSON.stringify(e)}`);let o;try{o=F(a,t)}catch(e){return q(`Error parsing commit '${i}':`,e.message),null}let{type:s,scope:l,subject:u,body:d,breakingChanges:f,footer:p}=o,h=r?[...r.matchAll(t.tagPattern)].map(e=>e.groups?.tag??``):[],g=p?[...p.matchAll(t.signerPattern)].map(e=>e.groups):[],_=[],v=e=>{_.some(t=>t.email===e.email)||_.push(e)},y=e.authorName&&e.authorEmail?L({name:e.authorName,email:e.authorEmail},g):void 0;y&&v(y);let b=e.committerName&&e.committerEmail?L({name:e.committerName,email:e.committerEmail},g):void 0;b&&v(b),(p?[...p.matchAll(t.coAuthorPattern)].map(e=>e.groups).map(e=>L(e,g)):[]).forEach(e=>v(e));let x=ee(p??``,t),S=e.gpgSigCode?{code:e.gpgSigCode,label:k[e.gpgSigCode],keyId:e.gpgSigKeyId}:void 0,C=e[t.dateSource===`committerDate`?`committerTs`:`authorTs`];typeof C==`string`&&(C=te(new Date(C*1e3),t.dateFormat));let w=h.find(e=>n.exec(e)),T=w??j;T&&(j=T);let E={hash:i,type:s,scope:l,subject:u,body:d,breakingChanges:f,footer:p,committer:b,gpgSig:S,date:C,releaseTag:w,associatedReleaseTag:T,tags:h.length?h:void 0,authors:_.length?_:void 0,refs:x.length?x:void 0};return i&&!A.has(i)&&A.set(i,E),E},P=e=>`fake_`+a(`sha256`).update(e,`utf8`).digest(`hex`).slice(0,7),F=(e,t)=>{let[n,...r]=e.split(`
25
+ {{~/each}}`,changelogUrl:`{{repo.homepage}}/blob/main/{{#if isMonorepo}}packages/{{package.name}}/{{/if}}CHANGELOG.md`,releaseChangelogUrl:`{{>changelogUrl}}#{{tagToUrlFragment tag}}`,breakingChangesIndicator:`<sup>[{{breakingChangeIndex}}]</sup>`}},d={message:`chore(release): {{newTag}}`,signOff:!1,gpgSign:!1,stageAll:!0,extraArgs:null},f={name:`{{newTag}}`,message:`{{commitMessage}}`,gpgSign:!1,force:!1,extraArgs:null},p=[...[{file:/package\.json$/,pattern:/(^.*?"name": "(?<name>.*?)".*"version": ")(?<version>.*?)(".*?"homepage": "(?<homepage>.*?)")/s,replacement:`$1{{newVersion}}$4`}],{file:/package-lock\.json$/,pattern:/(^.*?"version": "|"packages".*?"".*"version": ")(.*?)(")/gs,replacement:`$1{{newVersion}}$3`}],m={lifecycle:[`bump`,`changelog`,`commit`,`tag`],bump:[`package.json`],versionSource:`manifestFile`,manifestFile:`./package.json`,tagFormat:`v{{version}}`,commitsScope:`.`,prevReleaseTagPattern:`{{newTagFormat}}`,zeroMajorBreakingIsMinor:!0,dryRun:!1,logLevel:`info`,context:{commitRefLinks:!0,footerChangelogUrl:!1,isMonorepo:!1},commitsParser:{headerPattern:/^(?<type>\w+)(?:\((?<scope>.+)\))?(?<bang>!)?: (?<subject>.+)/s,breakingChangesPattern:/^BREAKING CHANGES?:\s*(?<content>.+)/ms,breakingChangeListPattern:/- (.+)/g,tagPattern:/tag: (?<tag>.*?)[,)]/g,coAuthorPattern:/Co-authored-by: (?<name>.+?) <(?<email>.+)>/g,signerPattern:/Signed-off-by: (?<name>.+?) <(?<email>.+)>/g,ghEmailPattern:/^(?:\d+\+)?(?<username>.+)@users\.noreply\.github\.com$/,remoteUrlPattern:/^(https:\/\/|git@)(?<host>[^/:]+)[/:](?<owner>.+?)\/(?<name>.+?)(?:\..*)?$/,refPattern:/^(?<action>.+?) (?<labels>.+)$/gm,refLabelPattern:/(?:(?<owner>\S+?)\/(?<repo>\S+?))?#(?<number>\d+)/g,refActionPattern:/^(Fixes|Closes|Refs)/i,dateSource:`authorDate`,dateFormat:`US`,revertCommitBodyPattern:/^This reverts commit (?<hash>.{7})/m}},h=e=>C(v(_(ie(g(e))))),g=e=>{let t=e.profile??`default`,n=e[`_${t}`];if(!n){if(e.profile===void 0)return e;throw Error(`Profile "${t}" not found in configuration.`)}let r=(t,...r)=>{let i=e=>Object.prototype.toString.call(e)===`[object Object]`,a=(e,t)=>{let n=i(e),r=i(t);return n&&r?{...e,...t}:t??e},o=e[t],s=n[t],c=a(o,s);if(c!==void 0)return r.forEach(e=>{c[e]=a(o?.[e],s?.[e])}),c};return{...e,...n,commitsParser:r(`commitsParser`),changelog:r(`changelog`,`partials`,`helpers`),commit:r(`commit`),tag:r(`tag`),context:r(`context`)}},_=e=>{let t=e=>{if(typeof e==`object`)return e;let t=p.find(t=>t.file.test(e));if(t)return{...t,file:e};throw Error(`File ${e} doesn't match any default versioned files. Please provide a custom pattern for this file.`)},n=t(e.manifestFile),r=e.changelog?.releasePattern,i=e.tag?.message,a=e.prevReleaseTagPattern===`{{newTagFormat}}`?e.tagPrefix===void 0?new RegExp(e.tagFormat.replace(`{{version}}`,c.source)):RegExp(`${e.tagPrefix}${c.source}`):e.prevReleaseTagPattern;return{...e,manifestFile:n,bump:e.lifecycle.includes(`bump`)?e.bump?e.bump.map(t):[n]:void 0,changelog:e.changelog?{...e.changelog,compiledPartials:X(e.changelog,e.context),latestReleasePattern:new RegExp(r.source.replace(`{{version}}`,``),r.flags)}:void 0,tag:e.tag?{...e.tag,message:i===`{{commitMessage}}`?e.commit?.message??i:i}:void 0,prevReleaseTagPattern:a}},v=e=>{let n=e.context,r=B(e.commitsParser.remoteUrlPattern),i=e.manifestFile.pattern.exec(t(e.manifestFile.file,`utf-8`))?.groups,a=n.currentVersion??(e.versionSource===`latest-release-tag`?T(U(e.prevReleaseTagPattern)[0],e.prevReleaseTagPattern)??`0.0.0`:w(e.manifestFile));K(`Current version (from ${e.versionSource===`latest-release-tag`?`latest release tag`:`'${e.manifestFile.file}'`}): '${a}'`);let o=n.currentTag??U(e.prevReleaseTagPattern)[0],s=n.newVersion??E(e,a,e.commitsScope),c=n.newTag??(e.tagPrefix===void 0?e.tagFormat.replace(`{{version}}`,s):e.tagPrefix+s),l=e.changelog?e.changelog.commitRange:`unreleased`,u=y(n.commits?n.commits.map(t=>typeof t==`object`&&`message`in t||typeof t==`string`?N(t,e.commitsParser,e.prevReleaseTagPattern):t).filter(e=>e!=null):M(l,e.commitsParser,e.prevReleaseTagPattern,e.commitsScope),c,e.commitsParser.revertCommitBodyPattern),d=e.changelog?b(u,e.changelog.sections,e.prevReleaseTagPattern,e.changelog.groupCommitsByScope):null,{commits:f,...p}=n;return{...e,context:{currentVersion:a,currentTag:o,newVersion:s,newTag:c,commits:u,releases:d,commitRefLinks:n.commitRefLinks??!0,footerChangelogUrl:n.footerChangelogUrl??!1,isMonorepo:n.isMonorepo??!1,...p,repo:{...r,...e.context.repo},package:{...i,...e.context.package}}}},y=(e,t,n)=>{let r=0,i=[];return e.map(a=>{let o=null,s=e.findIndex(e=>e.type===`revert`&&n.exec(e.body??``)?.groups?.hash===a.hash),c=s===-1?void 0:e[s];if(c&&(o=c.associatedReleaseTag===a.associatedReleaseTag?`inTheSameRelease`:`inOtherRelease`),o===`inTheSameRelease`){i.push(s);return}return{...a,associatedReleaseTag:a.associatedReleaseTag??t,isReverted:a.isReverted??o,breakingChangeIndex:a.breakingChanges?++r:void 0}}).filter((e,t)=>!!e&&!i.includes(t))},b=(e,t,n,r)=>{let i={};return e.forEach(e=>{let t=e.associatedReleaseTag;t in i?i[t].commits.push(e):i[t]={tag:t,version:T(t,n),date:e.date,commits:[e]}}),Object.values(i).map(({commits:e,...n})=>{let i=x(e,t,r);if(Object.keys(i).length===0)return;let a={};for(let[e,t]of Object.entries(i))if(t.show===`never`)continue;else t.show===`only-breaking`?(t.commits=t.commits.filter(e=>!!e.breakingChanges),t.commits.length&&(t.scopeGroups=S(t.commits),a[e]=t)):a[e]=t;return{...n,commitTypeGroups:a}}).filter(e=>!!e)},x=(e,t,n)=>{let r=Object.fromEntries(Object.entries(t).map(([e,{filter:t,...n}])=>[e,{...n,commits:[]}]));e.forEach(e=>{let n=!!e.breakingChanges,i=!1,a=!1;for(let o in t){if(t[o].filter&&!t[o].filter(e))continue;let s=[t[o].commitType].flat();if(n&&!a&&s.includes(`breaking`)){r[o].commits.push(e),a=!0;continue}if(!i&&(s.includes(e.type)||s.includes(`*`))&&(r[o].commits.push(e),i=!0),i&&(!n||a))return}});let i=Object.entries(r).filter(([e,t])=>t.commits.length);return Object.fromEntries(n?i.map(([e,t])=>[e,{...t,scopeGroups:S(t.commits)}]):i)},S=e=>{let t={};return e.forEach(e=>{let n=e.scope??``;t[n]??=[],t[n].push(e)}),Object.entries(t).map(([e,t])=>({scope:e,commits:t}))},C=e=>({...e,commit:e.commit?{...e.commit,message:r.compile(e.commit.message)(e.context)}:e.commit,tag:e.tag?{...e.tag,name:r.compile(e.tag.name)(e.context),message:r.compile(e.tag.message)(e.context)}:e.tag}),w=e=>{let n=t(e.file,`utf8`),r=e.pattern.exec(n)?.groups?.version;if(!r)throw Error(`Version not found in '${e.file}' with pattern '${e.pattern}'`);if(!i.valid(r))throw Error(`Invalid version format in '${e.file}': '${r}'`);return r},T=(e,t)=>t.exec(e)?.groups?.version,E=(e,t,n)=>{if(e.context.newVersion){if(!i.valid(e.context.newVersion))throw Error(`Invalid release version format: '${e.context.newVersion}'`);return e.context.newVersion}let r;r=e.releaseType?e.releaseType:D(M(`unreleased`,e.commitsParser,e.prevReleaseTagPattern,n),t,e.zeroMajorBreakingIsMinor);let a=O(t,r);return K(`Determined new version: '${a}' (release type: '${r}')`),a},D=(e,t,n)=>{let r=`patch`;return e.some(e=>e.breakingChanges)&&(r=`major`),e.some(e=>e.type===`feat`)&&(r=`minor`),r===`major`&&i.major(t??`1.0.0`)===0&&n?`minor`:r},O=(e,t)=>i.inc(e,t)??(()=>{throw Error(`Failed to calculate new version from '${e}' with release type '${t}'`)})();let k=function(e){return e.G=`valid`,e.B=`bad`,e.U=`valid, unknown validity`,e.X=`valid, expired`,e.Y=`valid, made by expired key`,e.R=`valid, made by revoked key`,e.E=`cannot check (missing key)`,e.N=`no signature`,e}({});const A=new Map;let j;const M=(e,t,n,r)=>{n??=c;let i=Array.isArray(e)?e:V(e,n,r),a=t??m.commitsParser,o=i.map(e=>N(e,a,n)).filter(e=>e!==null);return j=void 0,o},N=(e,t,n)=>{t??=m.commitsParser,n??=c,typeof e==`string`&&(e={message:e});let{tagRefs:r,hash:i=P(e.message)}=e;if(A.has(i))return A.get(i)??null;let a=e.message.trim();if(!a)throw Error(`Message is missing for commit: ${JSON.stringify(e)}`);let o;try{o=F(a,t)}catch(e){return q(`Error parsing commit '${i}':`,e.message),null}let{type:s,scope:l,subject:u,body:d,breakingChanges:f,footer:p}=o,h=r?[...r.matchAll(t.tagPattern)].map(e=>e.groups?.tag??``):[],g=p?[...p.matchAll(t.signerPattern)].map(e=>e.groups):[],_=[],v=e=>{_.some(t=>t.email===e.email)||_.push(e)},y=e.authorName&&e.authorEmail?L({name:e.authorName,email:e.authorEmail},g):void 0;y&&v(y);let b=e.committerName&&e.committerEmail?L({name:e.committerName,email:e.committerEmail},g):void 0;b&&v(b),(p?[...p.matchAll(t.coAuthorPattern)].map(e=>e.groups).map(e=>L(e,g)):[]).forEach(e=>v(e));let x=ee(p??``,t),S=e.gpgSigCode?{code:e.gpgSigCode,label:k[e.gpgSigCode],keyId:e.gpgSigKeyId}:void 0,C=e[t.dateSource===`committerDate`?`committerTs`:`authorTs`];typeof C==`string`&&(C=te(new Date(C*1e3),t.dateFormat));let w=h.find(e=>n.exec(e)),T=w??j;T&&(j=T);let E={hash:i,type:s,scope:l,subject:u,body:d,breakingChanges:f,footer:p,committer:b,gpgSig:S,date:C,releaseTag:w,associatedReleaseTag:T,tags:h.length?h:void 0,authors:_.length?_:void 0,refs:x.length?x:void 0};return i&&!A.has(i)&&A.set(i,E),E},P=e=>`fake_`+a(`sha256`).update(e,`utf8`).digest(`hex`).slice(0,7),F=(e,t)=>{let[n,...r]=e.split(`
26
26
 
27
27
  `),i=t.headerPattern.exec(n);if(!i?.groups)throw Error(`Commit header '${n}' doesn't match expected format`);let{type:a,scope:o,bang:s,subject:c}=i.groups,l,u=r.find(e=>t.breakingChangesPattern.test(e));u?(l=I(u,t),r.splice(r.indexOf(u),1)):s&&(l=c);let d=r.findIndex(e=>e.match(t.refActionPattern)??e.match(t.coAuthorPattern)??e.match(t.signerPattern)),[f,p]=d===-1?[r.join(`
28
28
 
@@ -32,7 +32,7 @@ import{existsSync as e,readFileSync as t,writeFileSync as n}from"node:fs";import
32
32
 
33
33
  `)];return{type:a,scope:o||void 0,subject:c,body:f||void 0,breakingChanges:l,footer:p||void 0}},I=(e,t)=>{let n=t.breakingChangesPattern.exec(e)?.groups?.content;if(!n)throw Error(`Failed to extract breaking changes content from '${e}' using pattern "${t.breakingChangesPattern}"`);let r=[...n.matchAll(t.breakingChangeListPattern)];return r.length?r.map(e=>e[1]):n},L=(e,t)=>{let n=t.some(t=>t.email===e.email&&t.name===e.name);return{...e,hasSignedOff:n,ghLogin:e.name,ghUrl:`https://github.com/${e.name}`}},ee=(e,t)=>[...e.matchAll(t.refPattern)].map(e=>e.groups).filter(e=>t.refActionPattern.test(e.action)).flatMap(e=>[...e.labels.matchAll(t.refLabelPattern)].map(e=>({label:e.groups,raw:e.input})).filter(({label:e})=>!!e.number).map(({label:t,raw:n})=>({raw:n,action:e.action,owner:t.owner,repo:t.repo,number:t.number}))),te=(e,t)=>{let n=e=>e.toString().padStart(2,`0`);if(t===`US`)return e.toLocaleString(`en-US`,{month:`short`,day:`numeric`,year:`numeric`});if(t===`ISO`)return e.toISOString().split(`T`)[0];let r={YYYY:e.getUTCFullYear().toString(),MM:n(e.getUTCMonth()+1),DD:n(e.getUTCDate()),HH:n(e.getUTCHours()),mm:n(e.getUTCMinutes()),ss:n(e.getUTCSeconds())};return t.replace(/YYYY|MM|DD|HH|mm|ss/g,e=>r[e])},R=/##COMMIT##\n#HASH# (?<hash>.+)?\n#MSG# (?<message>[\s\S]*?)\n#REFS#\s+(?<tagRefs>.+)?\n#AUTHOR-NAME# (?<authorName>.+)?\n#AUTHOR-EMAIL# (?<authorEmail>.+)?\n#AUTHOR-DATE# (?<authorTs>.+)?\n#COMMITTER-NAME# (?<committerName>.+)?\n#COMMITTER-EMAIL# (?<committerEmail>.+)?\n#COMMITTER-DATE# (?<committerTs>.+)?\n#GPGSIG-CODE# (?<gpgSigCode>.+)?\n#GPGSIG-KEYID# (?<gpgSigKeyId>.+)?/g,z=new Map,B=e=>{let t=o(`git remote get-url origin`,{encoding:`utf8`}).trim(),n=e.exec(t);if(!n?.groups)throw Error(`Couldn't parse remote URL: `+t);let{host:r,owner:i,name:a}=n.groups;return{host:r,owner:i,name:a,homepage:`https://${r}/${i}/${a}`}},V=(e,t,n)=>{let r=H(),i=U(t),a=``,s=``,c=``;if(e===`all`)a=`{{firstCommit}}`,s=`HEAD`;else if(e===`unreleased`)a=i[0]??`{{firstCommit}}`,s=`HEAD`;else if(e===`latest-release`)a=i[1]??`{{firstCommit}}`,s=i[0]??`HEAD`;else if(typeof e==`object`){let t=i.indexOf(e.releaseTag);if(t===-1)throw Error(`Release tag '${e.releaseTag}' not found`);a=i[t+1]??`{{firstCommit}}`,s=i[t]}else c=e;return a&&s&&(c=a===`{{firstCommit}}`?`"${a}^!" ${s}`:`"${a}..${s}"`),c=c.replace(`{{firstCommit}}`,r),[...o(`git log ${c} --pretty="##COMMIT##%n#HASH# %h%n#MSG# %B%n#REFS# %d%n#AUTHOR-NAME# %an%n#AUTHOR-EMAIL# %ae%n#AUTHOR-DATE# %at%n#COMMITTER-NAME# %cn%n#COMMITTER-EMAIL# %ce%n#COMMITTER-DATE# %ct%n#GPGSIG-CODE# %G?%n#GPGSIG-KEYID# %GK%n" -- ${n??`.`}`,{encoding:`utf8`}).matchAll(R)].map(e=>e.groups)},H=()=>o(`git rev-list --max-parents=0 HEAD`,{encoding:`utf8`}).trim(),U=e=>{e??=c;let t=e.toString();if(z.has(t))return z.get(t)??[];let n=o(`git tag --sort=-creatordate`,{encoding:`utf8`}).split(`
34
34
  `).filter(t=>e.test(t));return z.set(t,n),n};let W=`info`;const G=e=>W=e,K=(...e)=>{W!==`silent`&&console.log(...e)},q=(...e)=>{W===`info`&&console.warn(...e)},J={...l,pick(...e){return Object.fromEntries(e.map(e=>[e,this[e]]))},omit(...e){let t=new Set(e);return Object.fromEntries(Object.entries(this).filter(([e])=>!t.has(e)))},modify(e,t){return{...this,[e]:t(this[e])}}};var Y=`{{~#>header~}}
35
- ## &ensp; [\` 📦 {{tag}} \`]({{>compareLink}}){{>br}}
35
+ ## &ensp; [\` 📦 {{>releaseTitle}} \`]({{>compareLink}}){{>br}}
36
36
  {{/header}}
37
37
 
38
38
  {{~#>body~}}
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "relion",
3
- "version": "0.29.0",
3
+ "version": "0.31.0",
4
4
  "description": "Release workflow helper.",
5
5
  "author": "Kh4f <kh4f.dev@gmail.com>",
6
6
  "license": "MIT",
7
7
  "engines": {
8
- "node": "^24.10.0"
8
+ "node": "^24.11.0"
9
9
  },
10
10
  "repository": "https://github.com/kh4f/relion",
11
11
  "bugs": "https://github.com/kh4f/relion/issues",
@@ -38,17 +38,17 @@
38
38
  "devDependencies": {
39
39
  "@eslint/js": "^9.38.0",
40
40
  "@stylistic/eslint-plugin": "^5.5.0",
41
- "@types/node": "^24.9.1",
41
+ "@types/node": "^24.9.2",
42
42
  "@types/semver": "^7.7.1",
43
43
  "eslint": "^9.38.0",
44
44
  "globals": "^16.4.0",
45
45
  "lint-staged": "^16.2.6",
46
46
  "simple-git-hooks": "^2.13.1",
47
- "tsdown": "^0.15.10",
47
+ "tsdown": "^0.15.11",
48
48
  "typescript": "^5.9.3",
49
49
  "tsx": "^4.20.6",
50
50
  "typescript-eslint": "^8.46.2",
51
- "vitest": "^4.0.3"
51
+ "vitest": "^4.0.5"
52
52
  },
53
53
  "simple-git-hooks": {
54
54
  "pre-commit": "pnpm lint-staged"