relion 0.23.0 → 0.24.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
@@ -42,10 +42,10 @@ interface ChangelogOptions {
42
42
  file?: string;
43
43
  output?: 'file' | 'stdout';
44
44
  commitRange?: CommitRange;
45
- extractFromFile?: boolean;
45
+ extractFromFile?: boolean | 'latest-release' | (string & {});
46
46
  sections?: TypeGroupsMap;
47
47
  header?: string;
48
- latestReleasePattern?: RegExp;
48
+ releasePattern?: RegExp;
49
49
  commitRefLinkPattern?: RegExp;
50
50
  groupCommitsByScope?: boolean;
51
51
  maxLinesPerRelease?: number;
@@ -56,6 +56,7 @@ interface ChangelogOptions {
56
56
  type CompleteChangelogOptions = Required<ChangelogOptions>;
57
57
  interface ResolvedChangelogOptions extends Omit<CompleteChangelogOptions, 'partials'> {
58
58
  compiledPartials: Record<string, HandlebarsTemplateDelegate> | string;
59
+ latestReleasePattern: RegExp;
59
60
  }
60
61
  interface CommitOptions {
61
62
  message?: string;
@@ -105,6 +106,7 @@ interface Context {
105
106
  repo?: RepoInfo;
106
107
  commitRefLinks?: boolean;
107
108
  footerChangelogUrl?: boolean;
109
+ packageName?: string;
108
110
  [key: string]: unknown;
109
111
  }
110
112
  interface ResolvedContext extends Required<Context> {
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
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={breaking:{title:`⚠️ BREAKING CHANGES`,commitType:`breaking`,show:`always`},feat:{title:`✨ Features`,commitType:`feat`,show:`always`},fix:{title:`🩹 Fixes`,commitType:`fix`,show:`always`},perf:{title:`⚡ Performance`,commitType:`perf`,show:`always`},revert:{title:`♻️ Reverts`,commitType:`revert`,show:`always`},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`}},l={file:`CHANGELOG.md`,output:`file`,commitRange:`unreleased`,extractFromFile:!1,sections:c,header:`# Changelog
2
2
 
3
3
 
4
- `,latestReleasePattern:/(?<header>##.*?)(?<body>###.*?)(?<footer>####.*?)##/s,commitRefLinkPattern:/\[`?(#?\w+?)`?\]\(.+?\)/g,groupCommitsByScope:!0,maxLinesPerRelease:20,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,``)}-`,toSentenceCase:function(e){let t=e.fn(this);return`${t.charAt(0).toUpperCase()}${t.slice(1)}${t.endsWith(`.`)?``:`.`}`}},partials:{br:`
4
+ `,releasePattern:/(?<header>##[^\n]*?\[[^\n]*?{{version}}[^\n]*?\].*?\n\n)(?<body>.*?)(?<footer>####.*?\n\n\n)/s,commitRefLinkPattern:/\[`?(#?\w+?)`?\]\(.+?\)/g,groupCommitsByScope:!0,maxLinesPerRelease:20,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,``)}-`,toSentenceCase:function(e){let t=e.fn(this);return`${t.charAt(0).toUpperCase()}${t.slice(1)}${t.endsWith(`.`)?``:`.`}`}},partials:{br:`
5
5
  `,scope:`{{#if scope}}**{{scope}}**: {{/if}}`,commit:`{{{subject}}} {{" "}}
6
6
  {{~#if @root.commitRefLinks~}}
7
7
  [\`{{hash}}\`]({{@root.repo.homepage}}/commit/{{hash}})
@@ -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:`{{repo.homepage}}/blob/main/CHANGELOG.md#{{tagToUrlFragment tag}}`,breakingChangesIndicator:`<sup>[{{breakingChangeIndex}}]</sup>`}},u={message:`chore(release): {{newTag}}`,signOff:!1,gpgSign:!1,stageAll:!0,extraArgs:null},d={name:`{{newTag}}`,message:u.message,gpgSign:!1,force:!1,extraArgs:null},f=[{file:/package\.json$/,pattern:/(^.*?"version".*?")(.*?)(")/s,replacement:`$1{{newVersion}}$3`},{file:/package-lock\.json$/,pattern:/(^.*?"version".*?"|"packages".*?"".*"version".*?")(.*?)(")/gs,replacement:`$1{{newVersion}}$3`}],p={lifecycle:[`bump`,`changelog`,`commit`,`tag`],bump:[`package.json`],versionSource:`versionSourceFile`,versionSourceFile:`./package.json`,newTagFormat:`v{{version}}`,commitsScope:`.`,prevReleaseTagPattern:/^v?(?<version>\d+\.\d+\.\d+)/,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}},m=e=>C(v(_(g(h(e))))),h=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`)}},g=e=>{let t=e.lifecycle??p.lifecycle;return t=t===`all`?[`bump`,`changelog`,`commit`,`tag`]:[...new Set(t)],{...p,...e,lifecycle:t,commitsParser:{...p.commitsParser,...e.commitsParser},bump:t.includes(`bump`)?e.bump??p.bump:void 0,changelog:t.includes(`changelog`)?{...l,...e.changelog,partials:{...l.partials,...e.changelog?.partials},helpers:{...l.helpers,...e.changelog?.helpers}}:void 0,commit:t.includes(`commit`)?{...u,...e.commit}:void 0,tag:t.includes(`tag`)?{...d,...e.tag}:void 0,context:{...p.context,...e.context}}},_=e=>{let t=e=>{if(typeof e==`object`)return e;let t=f.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.versionSourceFile);return{...e,versionSourceFile:n,bump:e.lifecycle.includes(`bump`)?e.bump?e.bump.map(t):[n]:void 0,changelog:e.changelog?{...e.changelog,compiledPartials:Z(e.changelog,e.context)}:void 0}},v=e=>{let t=e.context,n=V(e.commitsParser.remoteUrlPattern),r=t.currentVersion??(e.versionSource===`latest-release-tag`?T(W(e.prevReleaseTagPattern)[0],e.prevReleaseTagPattern)??`0.0.0`:w(e.versionSourceFile));q(`Current version (from ${e.versionSource===`latest-release-tag`?`latest release tag`:`'${e.versionSourceFile.file}'`}): '${r}'`);let i=t.currentTag??W(e.prevReleaseTagPattern)[0],a=t.newVersion??ee(e,r,e.commitsScope),o=t.newTag??(e.newTagPrefix===void 0?e.newTagFormat.replace(`{{version}}`,a):e.newTagPrefix+a),s=e.changelog?e.changelog.commitRange:`unreleased`,c=y(t.commits?t.commits.map(t=>typeof t==`object`&&`message`in t||typeof t==`string`?M(t,e.commitsParser,e.prevReleaseTagPattern):t).filter(e=>e!=null):j(s,e.commitsParser,e.prevReleaseTagPattern,e.commitsScope),o,e.commitsParser.revertCommitBodyPattern),l=e.changelog?b(c,e.changelog.sections,e.prevReleaseTagPattern,e.changelog.groupCommitsByScope,e.changelog.maxLinesPerRelease):null,{commits:u,...d}=t;return{...e,context:{currentVersion:r,currentTag:i,newVersion:a,newTag:o,commits:c,releases:l,commitRefLinks:t.commitRefLinks??!0,footerChangelogUrl:t.footerChangelogUrl??!1,...d,repo:{...n,...e.context.repo}}}},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,i)=>{i??=l.maxLinesPerRelease;let a={};return e.forEach(e=>{let t=e.associatedReleaseTag;t in a?a[t].commits.push(e):a[t]={tag:t,version:T(t,n),date:e.date,commits:[e]}}),Object.values(a).map(({commits:e,...n})=>{let a=x(e,t,r);if(Object.keys(a).length===0)return;let o=0,s=!1,c={};for(let[e,t]of Object.entries(a))t.show??=`limit-or-breaking`,o+t.commits.length>i&&Object.keys(c).length&&(s=!0),t.show!==`never`&&(t.show===`only-breaking`||t.show===`limit-or-breaking`&&s?(t.commits=t.commits.filter(e=>!!e.breakingChanges),t.commits.length&&(t.scopeGroups=S(t.commits),c[e]=t,o+=t.commits.length)):(t.show===`always`||!s)&&(c[e]=t,o+=t.commits.length));return{...n,commitTypeGroups:c}}).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)?.[2];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,ee=(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;e.releaseType?r=e.releaseType:(r=E(j(`unreleased`,e.commitsParser,e.prevReleaseTagPattern,n)),e.zeroMajorBreakingIsMinor&&i.major(t)===0&&r===`major`&&(r=`minor`));let a=D(t,r);return q(`Determined new version: '${a}' (release type: '${r}')`),a},E=e=>e.some(e=>e.breakingChanges)?`major`:e.some(e=>e.type===`feat`)?`minor`:`patch`,D=(e,t)=>i.inc(e,t)??(()=>{throw Error(`Failed to calculate new version from '${e}' with release type '${t}'`)})();let O=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 k=new Map;let A;const j=(e,t,n,r)=>{n??=p.prevReleaseTagPattern;let i=Array.isArray(e)?e:H(e,n,r),a=t??p.commitsParser,o=i.map(e=>M(e,a,n)).filter(e=>e!==null);return A=void 0,o},M=(e,t,n)=>{t??=p.commitsParser,n??=p.prevReleaseTagPattern,typeof e==`string`&&(e={message:e});let{tagRefs:r,hash:i=N(e.message)}=e;if(k.has(i))return k.get(i)??null;let a=e.message.trim();if(!a)throw Error(`Message is missing for commit: ${JSON.stringify(e)}`);let o;try{o=P(a,t)}catch(e){return J(`Error parsing commit '${i}':`,e.message),null}let{type:s,scope:c,subject:l,body:u,breakingChanges:d,footer:f}=o,m=r?[...r.matchAll(t.tagPattern)].map(e=>e.groups?.tag??``):[],h=f?[...f.matchAll(t.signerPattern)].map(e=>e.groups):[],g=[],_=e=>{g.some(t=>t.email===e.email)||g.push(e)},v=e.authorName&&e.authorEmail?I({name:e.authorName,email:e.authorEmail},h):void 0;v&&_(v);let y=e.committerName&&e.committerEmail?I({name:e.committerName,email:e.committerEmail},h):void 0;y&&_(y),(f?[...f.matchAll(t.coAuthorPattern)].map(e=>e.groups).map(e=>I(e,h)):[]).forEach(e=>_(e));let b=L(f??``,t),x=e.gpgSigCode?{code:e.gpgSigCode,label:O[e.gpgSigCode],keyId:e.gpgSigKeyId}:void 0,S=e[t.dateSource===`committerDate`?`committerTs`:`authorTs`];typeof S==`string`&&(S=R(new Date(S*1e3),t.dateFormat));let C=m.find(e=>n.exec(e)),w=C??A;w&&(A=w);let T={hash:i,type:s,scope:c,subject:l,body:u,breakingChanges:d,footer:f,committer:y,gpgSig:x,date:S,releaseTag:C,associatedReleaseTag:w,tags:m.length?m:void 0,authors:g.length?g:void 0,refs:b.length?b:void 0};return i&&!k.has(i)&&k.set(i,T),T},N=e=>`fake_`+a(`sha256`).update(e,`utf8`).digest(`hex`).slice(0,7),P=(e,t)=>{let[n,...r]=e.split(`
25
+ {{~/each}}`,changelogUrl:`{{repo.homepage}}/blob/main/CHANGELOG.md#{{tagToUrlFragment tag}}`,breakingChangesIndicator:`<sup>[{{breakingChangeIndex}}]</sup>`}},u={message:`chore(release): {{newTag}}`,signOff:!1,gpgSign:!1,stageAll:!0,extraArgs:null},d={name:`{{newTag}}`,message:u.message,gpgSign:!1,force:!1,extraArgs:null},f=[{file:/package\.json$/,pattern:/(^.*?"version".*?")(.*?)(")/s,replacement:`$1{{newVersion}}$3`},{file:/package-lock\.json$/,pattern:/(^.*?"version".*?"|"packages".*?"".*"version".*?")(.*?)(")/gs,replacement:`$1{{newVersion}}$3`}],p={lifecycle:[`bump`,`changelog`,`commit`,`tag`],bump:[`package.json`],versionSource:`versionSourceFile`,versionSourceFile:`./package.json`,newTagFormat:`v{{version}}`,commitsScope:`.`,prevReleaseTagPattern:/^v?(?<version>\d+\.\d+\.\d+)/,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}},m=e=>C(v(_(g(h(e))))),h=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`)}},g=e=>{let t=e.lifecycle??p.lifecycle;return t=t===`all`?[`bump`,`changelog`,`commit`,`tag`]:[...new Set(t)],{...p,...e,lifecycle:t,commitsParser:{...p.commitsParser,...e.commitsParser},bump:t.includes(`bump`)?e.bump??p.bump:void 0,changelog:t.includes(`changelog`)?{...l,...e.changelog,partials:{...l.partials,...e.changelog?.partials},helpers:{...l.helpers,...e.changelog?.helpers}}:void 0,commit:t.includes(`commit`)?{...u,...e.commit}:void 0,tag:t.includes(`tag`)?{...d,...e.tag}:void 0,context:{...p.context,...e.context}}},_=e=>{let t=e=>{if(typeof e==`object`)return e;let t=f.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.versionSourceFile),r=e.changelog?.releasePattern;return{...e,versionSourceFile:n,bump:e.lifecycle.includes(`bump`)?e.bump?e.bump.map(t):[n]:void 0,changelog:e.changelog?{...e.changelog,compiledPartials:Z(e.changelog,e.context),latestReleasePattern:new RegExp(r.source.replace(`{{version}}`,``),r.flags)}:void 0}},v=e=>{let n=e.context,r=V(e.commitsParser.remoteUrlPattern),i=/"name": "(.*?)"/.exec(t(`package.json`,`utf-8`))?.[1],a=n.currentVersion??(e.versionSource===`latest-release-tag`?T(W(e.prevReleaseTagPattern)[0],e.prevReleaseTagPattern)??`0.0.0`:w(e.versionSourceFile));q(`Current version (from ${e.versionSource===`latest-release-tag`?`latest release tag`:`'${e.versionSourceFile.file}'`}): '${a}'`);let o=n.currentTag??W(e.prevReleaseTagPattern)[0],s=n.newVersion??ee(e,a,e.commitsScope),c=n.newTag??(e.newTagPrefix===void 0?e.newTagFormat.replace(`{{version}}`,s):e.newTagPrefix+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`?M(t,e.commitsParser,e.prevReleaseTagPattern):t).filter(e=>e!=null):j(l,e.commitsParser,e.prevReleaseTagPattern,e.commitsScope),c,e.commitsParser.revertCommitBodyPattern),d=e.changelog?b(u,e.changelog.sections,e.prevReleaseTagPattern,e.changelog.groupCommitsByScope,e.changelog.maxLinesPerRelease):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,packageName:n.packageName??i??`<unknown>`,...p,repo:{...r,...e.context.repo}}}},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,i)=>{i??=l.maxLinesPerRelease;let a={};return e.forEach(e=>{let t=e.associatedReleaseTag;t in a?a[t].commits.push(e):a[t]={tag:t,version:T(t,n),date:e.date,commits:[e]}}),Object.values(a).map(({commits:e,...n})=>{let a=x(e,t,r);if(Object.keys(a).length===0)return;let o=0,s=!1,c={};for(let[e,t]of Object.entries(a))t.show??=`limit-or-breaking`,o+t.commits.length>i&&Object.keys(c).length&&(s=!0),t.show!==`never`&&(t.show===`only-breaking`||t.show===`limit-or-breaking`&&s?(t.commits=t.commits.filter(e=>!!e.breakingChanges),t.commits.length&&(t.scopeGroups=S(t.commits),c[e]=t,o+=t.commits.length)):(t.show===`always`||!s)&&(c[e]=t,o+=t.commits.length));return{...n,commitTypeGroups:c}}).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)?.[2];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,ee=(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;e.releaseType?r=e.releaseType:(r=E(j(`unreleased`,e.commitsParser,e.prevReleaseTagPattern,n)),e.zeroMajorBreakingIsMinor&&i.major(t)===0&&r===`major`&&(r=`minor`));let a=D(t,r);return q(`Determined new version: '${a}' (release type: '${r}')`),a},E=e=>e.some(e=>e.breakingChanges)?`major`:e.some(e=>e.type===`feat`)?`minor`:`patch`,D=(e,t)=>i.inc(e,t)??(()=>{throw Error(`Failed to calculate new version from '${e}' with release type '${t}'`)})();let O=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 k=new Map;let A;const j=(e,t,n,r)=>{n??=p.prevReleaseTagPattern;let i=Array.isArray(e)?e:H(e,n,r),a=t??p.commitsParser,o=i.map(e=>M(e,a,n)).filter(e=>e!==null);return A=void 0,o},M=(e,t,n)=>{t??=p.commitsParser,n??=p.prevReleaseTagPattern,typeof e==`string`&&(e={message:e});let{tagRefs:r,hash:i=N(e.message)}=e;if(k.has(i))return k.get(i)??null;let a=e.message.trim();if(!a)throw Error(`Message is missing for commit: ${JSON.stringify(e)}`);let o;try{o=P(a,t)}catch(e){return J(`Error parsing commit '${i}':`,e.message),null}let{type:s,scope:c,subject:l,body:u,breakingChanges:d,footer:f}=o,m=r?[...r.matchAll(t.tagPattern)].map(e=>e.groups?.tag??``):[],h=f?[...f.matchAll(t.signerPattern)].map(e=>e.groups):[],g=[],_=e=>{g.some(t=>t.email===e.email)||g.push(e)},v=e.authorName&&e.authorEmail?I({name:e.authorName,email:e.authorEmail},h):void 0;v&&_(v);let y=e.committerName&&e.committerEmail?I({name:e.committerName,email:e.committerEmail},h):void 0;y&&_(y),(f?[...f.matchAll(t.coAuthorPattern)].map(e=>e.groups).map(e=>I(e,h)):[]).forEach(e=>_(e));let b=L(f??``,t),x=e.gpgSigCode?{code:e.gpgSigCode,label:O[e.gpgSigCode],keyId:e.gpgSigKeyId}:void 0,S=e[t.dateSource===`committerDate`?`committerTs`:`authorTs`];typeof S==`string`&&(S=R(new Date(S*1e3),t.dateFormat));let C=m.find(e=>n.exec(e)),w=C??A;w&&(A=w);let T={hash:i,type:s,scope:c,subject:l,body:u,breakingChanges:d,footer:f,committer:y,gpgSig:x,date:S,releaseTag:C,associatedReleaseTag:w,tags:m.length?m:void 0,authors:g.length?g:void 0,refs:b.length?b:void 0};return i&&!k.has(i)&&k.set(i,T),T},N=e=>`fake_`+a(`sha256`).update(e,`utf8`).digest(`hex`).slice(0,7),P=(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=F(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
 
@@ -73,4 +73,4 @@ import{existsSync as e,readFileSync as t,writeFileSync as n}from"node:fs";import
73
73
 
74
74
  {{~#>footer~}}
75
75
  ##### &emsp;&ensp;&nbsp;&nbsp; {{#if footerChangelogUrl}}[_Release Changelog_]({{>changelogUrl}}) &ensp;•&ensp; {{/if}}[_All Release Commits_]({{>compareLink}}) &ensp;•&ensp; _{{date}}_{{>br}}{{>br}}
76
- {{/footer}}`;const Z=(e,n)=>{let i,a,o=Object.keys(e.partials).find(t=>e.partials[t]===`from-file`);if((e.extractFromFile||o)&&(i=t(e.file,`utf-8`),a=e.latestReleasePattern.exec(i)?.groups??{},e.extractFromFile))return Q(Object.values(a).join(``),n,e.commitRefLinkPattern);let s=Object.fromEntries(Object.entries(e.partials).map(([t,r])=>{let i;if(typeof r==`function`)i=te(t,r);else if(r===`from-file`){if(i=a?.[t]??``,!i)throw Error(`Partial '${t}' not found in the latest release changelog.`);i=Q(i,n,e.commitRefLinkPattern)}else i=r;return[t,i]}));return Object.fromEntries(Object.entries(s).map(([e,t])=>[e,r.compile(t)]))},Q=(e,t,n)=>(t.commitRefLinks===!1&&(e=e.replace(n,`$1`)),e),te=(e,t)=>{let n=RegExp(`${e}.*?}}\\s*(.*?){{~?/${e}`,`s`).exec(X)?.[1];if(!n)throw Error(`Partial "${e}" not found in the release template.`);return t(n)},ne=async e=>{let t=s.createInterface({input:process.stdin,output:process.stdout});await new Promise(n=>{t.question(e,()=>{t.close(),n()})})},re=e=>{if(!e.bump)return null;let r=e.bump,i=e.context.newVersion;r.forEach(r=>{let a=t(r.file,`utf8`).replace(r.pattern,r.replacement.replace(`{{newVersion}}`,i));e.dryRun||n(r.file,a,`utf8`),q(`Updated version in '${r.file}' to '${i}'`)})},ie=async e=>{if(!e.changelog)return null;let t=e.changelog.extractFromFile?e.changelog.compiledPartials:ae(e);return t&&await oe(e.changelog,e,t),t},ae=e=>{let t=e.changelog,n=e.context.releases;if(!n)return null;let i=W(e.prevReleaseTagPattern),a=r.create();a.registerPartial(t.compiledPartials),a.registerHelper(t.helpers);let o=t.header;return n.forEach((t,r)=>{let s=n[r+1];if(!s){let n=i.indexOf(t.tag);if(n!==-1){let t=i[n+1];s={tag:t,version:t&&T(t,e.prevReleaseTagPattern)}}else s={tag:e.context.currentTag,version:e.context.currentVersion}}let c={...t,...e.context,prevRelease:s},l=a.compile(X)(c);o+=l}),o},oe=async(e,t,n)=>{e.output===`stdout`||t.dryRun?(q(`Generated changelog:`),console.log(n)):(q(`Writing changelog to file '${e.file}'`),$(e.file,n,e.latestReleasePattern)),e.review&&e.output===`file`&&(t.commit||t.tag)&&await ne(`Please review the changelog and press Enter to continue...`)},$=(r,i,a)=>{let o=e(r)?t(r,{encoding:`utf8`}):``,s=o.search(a);n(r,i+o.slice(s),{encoding:`utf8`})},se=e=>{if(!e.commit)return null;let t=e.commit,n=[t.stageAll&&`git add -A &&`,`git commit -m "${t.message}"`,t.signOff&&`-s`,t.gpgSign&&`-S`,t.extraArgs].filter(Boolean).join(` `);return q(`Committing with command: '${n}'`),e.dryRun||o(n,{stdio:`inherit`}),n},ce=e=>{if(!e.tag)return null;let t=e.tag,n=[`git tag -a ${t.name}`,`-m "${t.message}"`,t.gpgSign&&`-s`,t.force&&`-f`,t.extraArgs].filter(Boolean).join(` `);return q(`Tagging with command: '${n}'`),e.dryRun||o(n,{stdio:`inherit`}),n};async function le(e){K((e.logLevel??(!!e.profile&&e[`_${e.profile}`]?.logLevel))||`info`);let t=m(e),n,r,i;for(let e of t.lifecycle)await{bump:()=>re(t),changelog:async()=>n=await ie(t),commit:()=>r=se(t),tag:()=>i=ce(t)}[e]();return{resolvedConfig:t,generatedChangelog:n,commitCommand:r,tagCommand:i}}const ue=e=>e;export{le as default,ue as defineConfig,Y as sectionsSelector};
76
+ {{/footer}}`;const Z=(e,n)=>{let i,a,o=Object.keys(e.partials).find(t=>e.partials[t]===`from-file`);if(e.extractFromFile||o){i=t(e.file,`utf-8`);let r=typeof e.extractFromFile==`boolean`||e.extractFromFile===`latest-release`?``:e.extractFromFile;if(a=new RegExp(e.releasePattern.source.replace(`{{version}}`,r),e.releasePattern.flags).exec(i)?.groups??{},e.extractFromFile)return Q(Object.values(a).join(``),n,e.commitRefLinkPattern)}let s=Object.fromEntries(Object.entries(e.partials).map(([t,r])=>{let i;if(typeof r==`function`)i=te(t,r);else if(r===`from-file`){if(i=a?.[t]??``,!i)throw Error(`Partial '${t}' not found in the latest release changelog.`);i=Q(i,n,e.commitRefLinkPattern)}else i=r;return[t,i]}));return Object.fromEntries(Object.entries(s).map(([e,t])=>[e,r.compile(t)]))},Q=(e,t,n)=>(t.commitRefLinks===!1&&(e=e.replace(n,`$1`)),e),te=(e,t)=>{let n=RegExp(`${e}.*?}}\\s*(.*?){{~?/${e}`,`s`).exec(X)?.[1];if(!n)throw Error(`Partial "${e}" not found in the release template.`);return t(n)},ne=async e=>{let t=s.createInterface({input:process.stdin,output:process.stdout});await new Promise(n=>{t.question(e,()=>{t.close(),n()})})},re=e=>{if(!e.bump)return null;let r=e.bump,i=e.context.newVersion;r.forEach(r=>{let a=t(r.file,`utf8`).replace(r.pattern,r.replacement.replace(`{{newVersion}}`,i));e.dryRun||n(r.file,a,`utf8`),q(`Updated version in '${r.file}' to '${i}'`)})},ie=async e=>{if(!e.changelog)return null;let t=e.changelog.extractFromFile?e.changelog.compiledPartials:ae(e);return t&&await oe(e.changelog,e,t),t},ae=e=>{let t=e.changelog,n=e.context.releases;if(!n)return null;let i=W(e.prevReleaseTagPattern),a=r.create();a.registerPartial(t.compiledPartials),a.registerHelper(t.helpers);let o=t.header;return n.forEach((t,r)=>{let s=n[r+1];if(!s){let n=i.indexOf(t.tag);if(n!==-1){let t=i[n+1];s={tag:t,version:t&&T(t,e.prevReleaseTagPattern)}}else s={tag:e.context.currentTag,version:e.context.currentVersion}}let c={...t,...e.context,prevRelease:s},l=a.compile(X)(c);o+=l}),o},oe=async(e,t,n)=>{e.output===`stdout`||t.dryRun?(q(`Generated changelog:`),console.log(n)):(q(`Writing changelog to file '${e.file}'`),$(e.file,n,e.latestReleasePattern)),e.review&&e.output===`file`&&(t.commit||t.tag)&&await ne(`Please review the changelog and press Enter to continue...`)},$=(r,i,a)=>{let o=e(r)?t(r,{encoding:`utf8`}):``,s=o.search(a);n(r,i+o.slice(s),{encoding:`utf8`})},se=e=>{if(!e.commit)return null;let t=e.commit,n=[t.stageAll&&`git add -A &&`,`git commit -m "${t.message}"`,t.signOff&&`-s`,t.gpgSign&&`-S`,t.extraArgs].filter(Boolean).join(` `);return q(`Committing with command: '${n}'`),e.dryRun||o(n,{stdio:`inherit`}),n},ce=e=>{if(!e.tag)return null;let t=e.tag,n=[`git tag -a ${t.name}`,`-m "${t.message}"`,t.gpgSign&&`-s`,t.force&&`-f`,t.extraArgs].filter(Boolean).join(` `);return q(`Tagging with command: '${n}'`),e.dryRun||o(n,{stdio:`inherit`}),n};async function le(e){K((e.logLevel??(!!e.profile&&e[`_${e.profile}`]?.logLevel))||`info`);let t=m(e),n,r,i;for(let e of t.lifecycle)await{bump:()=>re(t),changelog:async()=>n=await ie(t),commit:()=>r=se(t),tag:()=>i=ce(t)}[e]();return{resolvedConfig:t,generatedChangelog:n,commitCommand:r,tagCommand:i}}const ue=e=>e;export{le as default,ue as defineConfig,Y as sectionsSelector};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "relion",
3
- "version": "0.23.0",
3
+ "version": "0.24.0",
4
4
  "description": "Release workflow helper.",
5
5
  "author": "Kh4f <kh4f.dev@gmail.com>",
6
6
  "license": "MIT",
@@ -36,18 +36,18 @@
36
36
  "semver": "^7.7.3"
37
37
  },
38
38
  "devDependencies": {
39
- "@eslint/js": "^9.37.0",
40
- "@stylistic/eslint-plugin": "^5.4.0",
41
- "@types/node": "^24.7.2",
39
+ "@eslint/js": "^9.38.0",
40
+ "@stylistic/eslint-plugin": "^5.5.0",
41
+ "@types/node": "^24.8.1",
42
42
  "@types/semver": "^7.7.1",
43
- "eslint": "^9.37.0",
43
+ "eslint": "^9.38.0",
44
44
  "globals": "^16.4.0",
45
45
  "lint-staged": "^16.2.4",
46
46
  "simple-git-hooks": "^2.13.1",
47
- "tsdown": "^0.15.6",
47
+ "tsdown": "^0.15.7",
48
48
  "tsx": "^4.20.6",
49
49
  "typescript": "^5.9.3",
50
- "typescript-eslint": "^8.46.0",
50
+ "typescript-eslint": "^8.46.1",
51
51
  "vitest": "^3.2.4"
52
52
  },
53
53
  "simple-git-hooks": {