relion 0.32.1 → 0.33.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/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2025 Kh4f
3
+ Copyright (c) 2025-2026 kh4f
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/dist/cli.js CHANGED
@@ -1 +1,11 @@
1
- import{resolve as e}from"node:path";import{pathToFileURL as t}from"node:url";import n from"./index.js";import{cli as r}from"cleye";import{register as i}from"module";const a=async n=>{try{return(await import(t(e(process.cwd(),n)).href)).default}catch(e){throw Error(`Error loading config: ${e.message}`)}},o=e=>{if(e===`all`)return`all`;let t={b:`bump`,l:`changelog`,m:`commit`,t:`tag`};return e.split(``).map(e=>{if(!(e in t))throw Error(`Invalid lifecycle step alias: '${e}'`);return t[e]})};import.meta.main&&(i(`./resolver.js`,import.meta.url),await s());async function s(e,t){typeof e==`string`&&(e=e.split(` `)),e=e?[e].flat():process.argv.slice(2);let i=r({name:`relion`,flags:{lifecycle:{alias:`f`,type:String,description:`Lifecycle steps to run in order ((b)ump, change(l)og, co(m)mit, (t)ag, or "all").`},config:{alias:`c`,type:String,description:`Path to the config file`,default:`relion.config.ts`},profile:{alias:`p`,type:String,description:`Use config profile`},dry:{alias:`d`,type:Boolean,description:`Run without making any changes`},latest:{alias:`L`,type:Boolean,description:`Use the latest-release commit range in changelog`,default:!1}}},void 0,[...e]);if(!i)return;t=t?structuredClone(t):await a(i.flags.config);let s,c=i.flags.profile??t.profile;if(c){let e=t[`_${c}`];if(!e)throw Error(`Profile '${c}' not found in config`);t.profile=c,s=e}else s=t._default??={};return i.flags.lifecycle&&(s.lifecycle=o(i.flags.lifecycle)),i.flags.dry&&(s.dryRun=!0),i.flags.latest&&(s.changelog??={},s.changelog.commitRange=`latest-release`),{inputConfig:t,...await n(t)}}export{s as runCli};
1
+ import e from"./index.js";const t=process.argv.slice(2).join(` `);t||(console.log(`Usage: relion [options]
2
+
3
+ Options:
4
+ -b Run bump step
5
+ -f [file] Run context step (default file: 'RELEASE.md')
6
+ -c [message] Run commit step (default message: 'chore(release): {{tag}}')
7
+ -t [prefix] Run tag step (default prefix: 'v')
8
+ -v <version> Specify new version
9
+ --gpg Sign commit and tag with GPG
10
+ -d Dry run
11
+ `),process.exit(0));const n=/-v (\S+)/.exec(t)?.[1],r=/-f (\S+)/.exec(t)?.[1],i=/-c "(.+?)"/.exec(t)?.[1],a=/-t (\S+)/.exec(t)?.[1],o=t.includes(`--gpg`),s=/-\w*d/.test(t);e({flow:[/-\w*b/.test(t)&&`bump`,/-\w*f/.test(t)&&`context`,/-\w*c/.test(t)&&`commit`,/-\w*t/.test(t)&&`tag`].filter(Boolean),...n&&{newVersion:n},...r&&{contextFile:r},...i&&{commitMessage:i},...a&&{tagPrefix:a},...o&&{gpgSign:o},...s&&{dryRun:s}});export{};
package/dist/index.d.ts CHANGED
@@ -1,344 +1,30 @@
1
- import { HelperDeclareSpec } from "handlebars";
2
-
3
- //#region src/types/config.d.ts
4
- interface UserConfig {
5
- lifecycle?: LifecycleStep[] | 'all';
6
- bump?: (string | Bumper)[];
7
- changelog?: ChangelogOptions;
8
- commit?: CommitOptions;
9
- tag?: TagOptions;
1
+ //#region src/types.d.ts
2
+ interface Config {
3
+ flow?: Step[];
4
+ newVersion?: string;
5
+ bumpFiles?: (Bumper | string)[];
6
+ contextFile?: string;
7
+ commitMessage?: string;
10
8
  tagPrefix?: string;
11
- tagFormat?: string;
12
- versionSource?: 'manifestFile' | 'latest-release-tag';
13
- manifestFile?: string | Bumper;
14
- commitsScope?: string;
15
- releaseType?: ReleaseType;
16
- zeroMajorBreakingIsMinor?: boolean;
17
- context?: Context;
18
- commitsParser?: CommitsParser;
19
- prevReleaseTagPattern?: '{{newTagFormat}}' | RegExp;
20
- dryRun?: boolean;
21
- profile?: string;
22
- logLevel?: 'info' | 'info-clean' | 'silent';
23
- [profile: `_${string}`]: UserConfig | undefined;
24
- }
25
- type OptionalKeys = LifecycleStep | 'releaseType' | 'profile' | 'tagPrefix';
26
- interface MergedConfig extends Omit<Required<UserConfig>, OptionalKeys>, Pick<UserConfig, OptionalKeys> {
27
- lifecycle: LifecycleStep[];
28
- changelog?: CompleteChangelogOptions;
29
- commit?: CompleteCommitOptions;
30
- tag?: CompleteTagOptions;
31
- commitsParser: CompleteCommitsParser;
32
- }
33
- interface TransformedConfig extends Omit<MergedConfig, 'changelog'> {
34
- manifestFile: Bumper;
35
- bump?: Required<Bumper[]>;
36
- changelog?: ResolvedChangelogOptions;
37
- prevReleaseTagPattern: RegExp;
38
- }
39
- interface ResolvedConfig extends TransformedConfig {
40
- context: ResolvedContext;
41
- }
42
- interface ChangelogOptions {
43
- file?: string;
44
- output?: 'file' | 'stdout';
45
- commitRange?: CommitRange;
46
- extractFromFile?: boolean | 'latest-release' | (string & {});
47
- sections?: TypeGroupsMap;
48
- header?: string;
49
- releasePattern?: RegExp;
50
- commitRefLinkPattern?: RegExp;
51
- groupCommitsByScope?: boolean;
52
- helpers?: HelperDeclareSpec;
53
- partials?: Record<string, string | ((fallback: string) => string)>;
54
- review?: boolean;
55
- }
56
- type CompleteChangelogOptions = Required<ChangelogOptions>;
57
- interface ResolvedChangelogOptions extends Omit<CompleteChangelogOptions, 'partials'> {
58
- compiledPartials: Record<string, HandlebarsTemplateDelegate> | string;
59
- latestReleasePattern: RegExp;
60
- }
61
- interface CommitOptions {
62
- message?: string;
63
- signOff?: boolean;
64
9
  gpgSign?: boolean;
65
- stageAll?: boolean;
66
- extraArgs?: string | null;
67
- }
68
- type CompleteCommitOptions = Required<CommitOptions>;
69
- interface TagOptions {
70
- name?: string;
71
- message?: '{{commitMessage}}' | (string & {});
72
- gpgSign?: boolean;
73
- force?: boolean;
74
- extraArgs?: string | null;
75
- }
76
- type CompleteTagOptions = Required<TagOptions>;
77
- interface CommitsParser {
78
- breakingChangesPattern?: RegExp;
79
- breakingChangeListPattern?: RegExp;
80
- headerPattern?: RegExp;
81
- tagPattern?: RegExp;
82
- coAuthorPattern?: RegExp;
83
- ghEmailPattern?: RegExp;
84
- refPattern?: RegExp;
85
- refActionPattern?: RegExp;
86
- refLabelPattern?: RegExp;
87
- remoteUrlPattern?: RegExp;
88
- signerPattern?: RegExp;
89
- dateSource?: 'authorDate' | 'committerDate';
90
- dateFormat?: 'US' | 'ISO' | (string & {});
91
- revertCommitBodyPattern?: RegExp;
92
- }
93
- type CompleteCommitsParser = Required<CommitsParser>;
94
- interface RepoInfo {
95
- host?: string;
96
- owner?: string;
97
- name?: string;
98
- homepage?: string;
99
- [key: string]: unknown;
100
- }
101
- interface PackageInfo {
102
- name?: string;
103
- version?: string;
104
- homepage?: string;
105
- [key: string]: unknown;
106
- }
107
- interface Context {
108
- commits?: (ParsedCommit | RawCommit | string)[];
109
- currentVersion?: string;
110
- currentTag?: string;
111
- newVersion?: string;
112
- newTag?: string;
113
- repo?: RepoInfo;
114
- package?: PackageInfo;
115
- commitRefLinks?: boolean;
116
- footerChangelogUrl?: boolean;
117
- isMonorepo?: boolean;
118
- [key: string]: unknown;
119
- }
120
- interface ResolvedContext extends Required<Context> {
121
- commits: ResolvedCommit[];
122
- releases: ReleaseWithTypeGroups[] | null;
10
+ commitFilters?: ((commit: Commit) => boolean)[];
11
+ dryRun?: boolean;
123
12
  }
124
- type LifecycleStep = 'bump' | 'changelog' | 'commit' | 'tag';
125
- type LogLevel = 'info' | 'info-clean' | 'silent';
126
- type CommitRange = 'all' | 'unreleased' | 'latest-release' | {
127
- releaseTag: string;
128
- } | (string & {});
129
- type ReleaseType = 'major' | 'minor' | 'patch';
13
+ type Step = 'bump' | 'context' | 'commit' | 'tag';
130
14
  interface Bumper {
131
15
  file: string;
132
16
  pattern: RegExp;
133
17
  replacement: string;
134
18
  }
135
- interface DefaultBumper extends Omit<Bumper, 'file'> {
136
- file: RegExp;
137
- }
138
- //#endregion
139
- //#region src/enums.d.ts
140
- declare enum GpgSigLabel {
141
- G = "valid",
142
- B = "bad",
143
- U = "valid, unknown validity",
144
- X = "valid, expired",
145
- Y = "valid, made by expired key",
146
- R = "valid, made by revoked key",
147
- E = "cannot check (missing key)",
148
- N = "no signature",
149
- }
150
- declare enum RefType {
151
- issue = "issue",
152
- pr = "PR",
153
- }
154
- //#endregion
155
- //#region src/types/commit.d.ts
156
- interface RawCommit {
157
- hash?: string;
158
- message: string;
159
- tagRefs?: string;
160
- authorName?: string;
161
- authorEmail?: string;
162
- authorTs?: string;
163
- committerName?: string;
164
- committerEmail?: string;
165
- committerTs?: string;
166
- gpgSigCode?: GpgSigCode;
167
- gpgSigKeyId?: string;
168
- }
169
- interface ParsedCommit extends CommitMessage {
19
+ interface Commit {
170
20
  hash: string;
171
- tags?: string[];
172
- authors?: Contributor[];
173
- committer?: Contributor;
174
- refs?: Reference[];
175
- gpgSig?: GpgSig;
176
- date?: string;
177
- releaseTag?: string;
178
- associatedReleaseTag?: string;
179
- isReverted?: 'inTheSameRelease' | 'inOtherRelease' | null;
180
- }
181
- interface ResolvedCommit extends ParsedCommit {
182
- associatedReleaseTag: NonNullable<ParsedCommit['associatedReleaseTag']>;
183
- isReverted: NonNullable<ParsedCommit['isReverted']> | null;
184
- breakingChangeIndex?: number;
185
- }
186
- interface CommitMessage {
187
- type: string;
188
- scope?: string;
189
- subject: string;
190
- body?: string;
191
- breakingChanges?: string | string[];
192
- footer?: string;
193
- }
194
- interface Reference {
195
- action: string;
196
- raw: string;
197
- number: string;
198
- type?: RefType;
199
- owner?: string;
200
- repo?: string;
201
- }
202
- type RefLabel = Pick<Reference, 'owner' | 'repo' | 'number'>;
203
- interface Contributor {
204
- name: string;
205
- email: string;
206
- hasSignedOff?: boolean;
207
- ghLogin?: string;
208
- ghUrl?: string;
209
- }
210
- type GithubUserInfo = Pick<Contributor, 'ghLogin' | 'ghUrl'>;
211
- interface GpgSig {
212
- code: GpgSigCode;
213
- label: GpgSigLabel;
214
- keyId?: string;
215
- }
216
- type GpgSigCode = 'G' | 'B' | 'U' | 'X' | 'Y' | 'R' | 'E' | 'N';
217
- interface RawReference {
218
- action: string;
219
- labels: string;
220
- }
221
- //#endregion
222
- //#region src/defaults.d.ts
223
- declare const defaultChangelogSections: {
224
- readonly breaking: {
225
- readonly title: "⚠️ BREAKING CHANGES";
226
- readonly commitType: "breaking";
227
- };
228
- readonly feat: {
229
- readonly title: "✨ Features";
230
- readonly commitType: "feat";
231
- };
232
- readonly fix: {
233
- readonly title: "🩹 Fixes";
234
- readonly commitType: "fix";
235
- };
236
- readonly perf: {
237
- readonly title: "⚡ Performance";
238
- readonly commitType: "perf";
239
- };
240
- readonly revert: {
241
- readonly title: "♻️ Reverts";
242
- readonly commitType: "revert";
243
- };
244
- readonly refactor: {
245
- readonly title: "🚜 Refactoring";
246
- readonly commitType: "refactor";
247
- };
248
- readonly build: {
249
- readonly title: "📦 Build";
250
- readonly commitType: "build";
251
- };
252
- readonly docs: {
253
- readonly title: "📚 Documentation";
254
- readonly commitType: "docs";
255
- };
256
- readonly style: {
257
- readonly title: "🎨 Style";
258
- readonly commitType: "style";
259
- };
260
- readonly test: {
261
- readonly title: "🧪 Tests";
262
- readonly commitType: "test";
263
- };
264
- readonly ci: {
265
- readonly title: "🚀 CI";
266
- readonly commitType: "ci";
267
- };
268
- readonly types: {
269
- readonly title: "🏷️ Types";
270
- readonly commitType: "types";
271
- };
272
- readonly deps: {
273
- readonly title: "🧩 Dependencies";
274
- readonly commitType: "chore";
275
- readonly filter: (commit: ResolvedCommit) => boolean;
276
- };
277
- readonly chore: {
278
- readonly title: "🛠️ Chores";
279
- readonly commitType: "chore";
280
- };
281
- readonly misc: {
282
- readonly title: "⚙️ Miscellaneous";
283
- readonly commitType: "*";
284
- readonly filter: (commit: ResolvedCommit) => boolean;
285
- };
286
- };
287
- //#endregion
288
- //#region src/types/changelog.d.ts
289
- interface TypeGroupDefinition {
290
- title: string;
291
- commitType: 'breaking' | '*' | (string & {}) | string[];
292
- filter?: (commit: ResolvedCommit) => boolean;
293
- show?: 'only-breaking' | 'never';
294
- }
295
- type TypeGroupsMap = Record<string, TypeGroupDefinition>;
296
- interface ScopeGroup {
297
- scope: string;
298
- commits: ResolvedCommit[];
299
- }
300
- interface FilledTypeGroup extends Omit<TypeGroupDefinition, 'filter'> {
301
- commits: ResolvedCommit[];
302
- scopeGroups?: ScopeGroup[];
303
- }
304
- type FilledTypeGroupMap = Record<string, FilledTypeGroup>;
305
- interface ReleaseWithFlatCommits {
306
- tag: string;
307
- version?: string;
308
- date?: string;
309
- commits: ResolvedCommit[];
310
- }
311
- interface ReleaseWithTypeGroups extends Omit<ReleaseWithFlatCommits, 'commits'> {
312
- commitTypeGroups: FilledTypeGroupMap;
313
- }
314
- interface ReleaseContext extends ReleaseWithTypeGroups, ResolvedContext {
315
- prevRelease: Partial<ReleaseWithTypeGroups>;
316
- }
317
- type DefaultChangelogSections = typeof defaultChangelogSections;
318
- interface SectionsSelector extends DefaultChangelogSections {
319
- pick(...keys: (keyof DefaultChangelogSections)[]): Partial<DefaultChangelogSections>;
320
- omit(...keys: (keyof this)[]): SectionsSelector;
321
- modify(key: keyof DefaultChangelogSections, modify: (section: TypeGroupDefinition) => TypeGroupDefinition): Partial<DefaultChangelogSections>;
322
- }
323
- //#endregion
324
- //#region src/types/result.d.ts
325
- interface RelionResult {
326
- resolvedConfig: ResolvedConfig;
327
- generatedChangelog?: string;
328
- commitCommand?: string;
329
- tagCommand?: string;
21
+ message: string;
330
22
  }
331
23
  //#endregion
332
24
  //#region src/relion.d.ts
333
- declare function relion(userConfig: UserConfig): Promise<RelionResult>;
334
- //#endregion
335
- //#region src/utils/sections-selector.d.ts
336
- declare const sectionsSelector: SectionsSelector;
337
- //#endregion
338
- //#region src/utils/config-merger.d.ts
339
- declare const mergeConfigs: (baseConfig: UserConfig, overrideConfig: UserConfig) => UserConfig;
25
+ declare function relion(userCfg?: Config): void;
340
26
  //#endregion
341
27
  //#region src/index.d.ts
342
- declare const defineConfig: (config: UserConfig) => UserConfig;
28
+ declare const defineConfig: (config: Config) => Config;
343
29
  //#endregion
344
- export { Bumper, ChangelogOptions, CommitMessage, CommitOptions, CommitRange, CommitsParser, CompleteChangelogOptions, CompleteCommitOptions, CompleteCommitsParser, CompleteTagOptions, Context, Contributor, DefaultBumper, DefaultChangelogSections, FilledTypeGroup, FilledTypeGroupMap, GithubUserInfo, GpgSig, GpgSigCode, LifecycleStep, LogLevel, MergedConfig, PackageInfo, ParsedCommit, RawCommit, RawReference, RefLabel, Reference, ReleaseContext, ReleaseType, ReleaseWithFlatCommits, ReleaseWithTypeGroups, RelionResult, RepoInfo, ResolvedChangelogOptions, ResolvedCommit, ResolvedConfig, ResolvedContext, ScopeGroup, SectionsSelector, TagOptions, TransformedConfig, TypeGroupDefinition, TypeGroupsMap, UserConfig, relion as default, defineConfig, mergeConfigs, sectionsSelector };
30
+ export { relion as default, defineConfig };
package/dist/index.js CHANGED
@@ -1,76 +1,4 @@
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
-
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),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,partial:function(e,t){return t.data._handlebars.partials[e](this)},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
- {{~#if @root.commitRefLinks~}}
7
- [\`{{hash}}\`]({{@root.repo.homepage}}/commit/{{hash}})
8
- {{~else~}}
9
- {{hash}}
10
- {{~/if~}}
11
- {{~#if breakingChanges}} ⚠️{{>breakingChangesIndicator}}{{/if}}
12
- {{~#if refs}} {{>refs}}{{/if}}`,compareLink:`{{repo.homepage~}}
13
- {{#if prevRelease.tag~}}
14
- /compare/{{prevRelease.tag}}...
15
- {{~else~}}
16
- /commits/
17
- {{~/if}}
18
- {{~tag}}`,refs:`({{#each refs~}}
19
- {{#if @root.commitRefLinks~}}
20
- [{{raw}}]({{@root.repo.homepage}}/issues/{{number}})
21
- {{~else~}}
22
- {{raw}}
23
- {{~/if}}
24
- {{~#if @last}}){{else}}, {{/if}}
25
- {{~/each}}`,changelogUrl:`{{repo.homepage}}/blob/main/{{#if isMonorepo}}packages/{{package.name}}/{{/if}}CHANGELOG.md`,releaseChangelogUrl:`{{>changelogUrl}}#{{tagToUrlFragment (partial 'releaseTitle')}}`,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?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.type===`feat`)&&(r=`minor`),e.some(e=>e.breakingChanges)&&(r=`major`),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
-
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
-
29
- `),``]:[r.slice(0,d).join(`
30
-
31
- `),r.slice(d).join(`
32
-
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
- `).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; [\` 📦 {{>releaseTitle}} \`]({{>compareLink}}){{>br}}
36
- {{/header}}
37
-
38
- {{~#>body~}}
39
- {{#each commitTypeGroups~}}
40
- ### {{{repeat '&nbsp;' 5}}}{{title}}
41
- {{#if (eq @key 'breaking')}}
42
- {{#each commits}}
43
- {{#if (isArray breakingChanges)}}
44
- {{~#each breakingChanges~}}
45
- - {{#toSentenceCase}}{{{this}}}{{/toSentenceCase}} {{>breakingChangesIndicator ../this}}
46
- {{/each}}
47
- {{else~}}
48
- - {{#toSentenceCase}}{{{breakingChanges}}}{{/toSentenceCase}} {{>breakingChangesIndicator}}
49
- {{/if}}
50
- {{/each}}
51
- {{else}}
52
- {{#if scopeGroups}}
53
- {{#each scopeGroups~}}
54
- {{~#if (or (isSingle commits) (not scope))}}
55
- {{#each commits~}}
56
- - {{>scope}}{{>commit}}
57
- {{/each}}
58
- {{else~}}
59
- - {{>scope}}{{>br}}{{~#each commits}} {{" "~}}
60
- - {{>commit}}
61
- {{/each}}
62
- {{/if}}
63
- {{/each}}
64
- {{else}}
65
- {{#each commits~}}
66
- - {{>scope}}{{>commit}}
67
- {{/each}}
68
- {{/if}}
69
- {{/if}}
70
-
71
- {{/each}}
72
- {{/body}}
73
-
74
- {{~#>footer~}}
75
- ##### &emsp;&ensp;&nbsp;&nbsp; {{#if footerChangelogUrl}}[_Release Changelog_]({{>releaseChangelogUrl}}) &ensp;•&ensp; {{/if}}[_All Release Commits_]({{>compareLink}}) &ensp;•&ensp; _{{date}}_{{>br}}{{>br}}
76
- {{/footer}}`;const X=(e,n)=>{let i,a,o=Object.keys(e.partials).find(t=>typeof e.partials[t]==`string`&&e.partials[t].includes(`{{fromFile}}`));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 Z(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=ne(t,r);else if(r.includes(`{{fromFile}}`)){let o=a?.[t]??``;if(!o)throw Error(`Partial '${t}' not found in the changelog file for the specified release.`);i=r.replace(`{{fromFile}}`,o).replace(/{{/g,`\\$&`),i=Z(i,n,e.commitRefLinkPattern)}else i=r;return[t,i]}));return Object.fromEntries(Object.entries(s).map(([e,t])=>[e,r.compile(t)]))},Z=(e,t,n)=>(t.commitRefLinks===!1&&(e=e.replace(n,`$1`)),e),ne=(e,t)=>{let n=RegExp(`${e}.*?}}\\s*(.*?){{~?/${e}`,`s`).exec(Y)?.[1];if(!n)throw Error(`Partial "${e}" not found in the release template.`);return t(n)},re=async e=>{let t=s.createInterface({input:process.stdin,output:process.stdout});await new Promise(n=>{t.question(e,()=>{t.close(),n()})})},ie=e=>{let t=e.lifecycle??m.lifecycle;return t=t===`all`?[`bump`,`changelog`,`commit`,`tag`]:[...new Set(t)],{...m,...e,lifecycle:t,commitsParser:{...m.commitsParser,...e.commitsParser},bump:t.includes(`bump`)?e.bump??m.bump:void 0,changelog:t.includes(`changelog`)?{...u,...e.changelog,partials:{...u.partials,...e.changelog?.partials},helpers:{...u.helpers,...e.changelog?.helpers}}:void 0,commit:t.includes(`commit`)?{...d,...e.commit}:void 0,tag:t.includes(`tag`)?{...f,...e.tag}:void 0,context:{...m.context,...e.context}}},Q=(e,t)=>({...e,...t,commitsParser:{...e.commitsParser,...t.commitsParser},changelog:{...e.changelog,...t.changelog,partials:{...e.changelog?.partials,...t.changelog?.partials},helpers:{...e.changelog?.helpers,...t.changelog?.helpers}},commit:{...e.commit,...t.commit},tag:{...e.tag,...t.tag},context:{...e.context,...t.context}}),ae=(e,t)=>{let n=Q(e,t);for(let r of Object.keys(e))if(r.startsWith(`_`)){let i=r;n[i]=Q(e[i]??{},t[i]??{})}return n},oe=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`),K(`Updated version in '${r.file}' to '${i}'`)})},$=async e=>{if(!e.changelog)return null;let t=e.changelog.extractFromFile?e.changelog.compiledPartials:se(e);return t&&await ce(e.changelog,e,t),t},se=e=>{let t=e.changelog,n=e.context.releases;if(!n)return null;let i=U(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(Y)(c,{data:{_handlebars:a}});o+=l}),o},ce=async(e,t,n)=>{e.output===`stdout`||t.dryRun?(K(`Generated changelog:`),console.log(n)):(K(`Writing changelog to file '${e.file}'`),le(e.file,n,e.latestReleasePattern)),e.review&&e.output===`file`&&(t.commit||t.tag)&&await re(`Please review the changelog and press Enter to continue...`)},le=(r,i,a)=>{let o=e(r)?t(r,{encoding:`utf8`}):``,s=o.search(a),c=o.slice(s).trim();c||(i=i.trim()),n(r,i+c,{encoding:`utf8`})},ue=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 K(`Committing with command: '${n}'`),e.dryRun||o(n,{stdio:`inherit`}),n},de=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 K(`Tagging with command: '${n}'`),e.dryRun||o(n,{stdio:`inherit`}),n};async function fe(e){G((e.logLevel??(!!e.profile&&e[`_${e.profile}`]?.logLevel))||`info`);let t=h(e),n,r,i;for(let e of t.lifecycle)await{bump:()=>oe(t),changelog:async()=>n=await $(t),commit:()=>r=ue(t),tag:()=>i=de(t)}[e]();return{resolvedConfig:t,generatedChangelog:n,commitCommand:r,tagCommand:i}}const pe=e=>e;export{fe as default,pe as defineConfig,ae as mergeConfigs,J as sectionsSelector};
1
+ import{readFileSync as e,writeFileSync as t}from"node:fs";import{execSync as n}from"node:child_process";import r from"semver";const i=[{file:`package.json`,pattern:/("version": )".*"/,replacement:`$1"{{newVersion}}"`}],a={flow:[],newVersion:``,bumpFiles:i,contextFile:`RELEASE.md`,commitMessage:`chore(release): {{tag}}`,tagPrefix:`v`,gpgSign:!1,commitFilters:[e=>/^feat|^fix|^perf|^style|^docs/.test(e.message),e=>e.message.includes(`BREAKING CHANGE`)],dryRun:!1},o=n=>{n.bumpFiles.forEach(r=>{let a=typeof r==`string`?i.find(e=>e.file===r)??(()=>{throw Error(`No default bumper found for file '${r}'`)})():r,o=e(a.file,`utf8`).replace(a.pattern,a.replacement.replace(`{{newVersion}}`,n.newVersion));console.log(`Updating version in '${a.file}'`),!n.dryRun&&t(a.file,o,`utf8`)})},s=(e,n,r,i,a)=>{if(console.log(`Outputting release context to '${e.contextFile}'`),e.dryRun)return;let o=``,s=`---\nversion: ${e.newVersion}\ntag: ${i}\ndate: ${new Date().toLocaleString(`en-US`,{month:`short`,day:`numeric`,year:`numeric`})}\nprevTag: ${r}\nrepoURL: ${a}
2
+ ---
3
+ `;o+=s+`
4
+ `;let c=n.map(e=>`[${e.hash}] ${e.message}`).join(`\n${`-`.repeat(30)}\n`);o+=`## Git Log\n\n\`\`\`\n${c}\n\`\`\``,t(e.contextFile,o,`utf8`)},c=e=>{let t=`git add -A && git reset ${e.contextFile} && git commit -m "${e.commitMessage}"${e.gpgSign?` -S`:``}`;console.log(`Committing changes: '${t}'`),!e.dryRun&&n(t,{stdio:`inherit`})},l=(e,t)=>{let r=`git tag ${t} -m "${e.commitMessage}"${e.gpgSign?` -s`:``}`;console.log(`Creating a tag: '${r}'`),!e.dryRun&&n(r,{stdio:`inherit`})},u=e=>n(`git log ${e}.. --format="%h %B---"`,{encoding:`utf8`}).trim().split(`---`).filter(Boolean).map(e=>/^(.+?) (.+)/s.exec(e.trim())).map(e=>({hash:e?.[1]??``,message:e?.[2].trim()??``})),d=(e,t)=>{let n=e.some(e=>e.message.includes(`BREAKING CHANGE`))?t.startsWith(`0.`)?`minor`:`major`:e.some(e=>/feat(\(.*?\))?:/.test(e.message))?`minor`:`patch`;return r.inc(t,n)??(()=>{throw Error(`Failed to increment version '${t}' with release type '${n}'`)})()};function f(t){let r={...a,...t};console.log(`-`.repeat(30));let i=JSON.parse(e(`package.json`,`utf8`)),f=i.version;console.log(`Current version: ${f}`);let p=n(`git describe --match "${r.tagPrefix}*" --abbrev=0`,{encoding:`utf8`}).trim();console.log(`Current tag: ${p}`);let m=u(p).filter(e=>r.commitFilters.some(t=>t(e)));console.log(`Filtered commits: ${m.length}`),r.newVersion||=d(m,f),console.log(`New version: ${r.newVersion}`);let h=`${r.tagPrefix}${r.newVersion}`;console.log(`New tag: ${h}`),r.commitMessage=r.commitMessage.replace(`{{tag}}`,h),console.log(`Commit message: '${r.commitMessage}'`);let g=i.repository;console.log(`Repo URL: ${g}`),console.log(`-`.repeat(30));for(let e of r.flow)({bump:()=>o(r),context:()=>s(r,m,p,h,g),commit:()=>c(r),tag:()=>l(r,h)})[e]()}const p=e=>e;export{f as default,p as defineConfig};
package/package.json CHANGED
@@ -1,71 +1,50 @@
1
1
  {
2
2
  "name": "relion",
3
- "version": "0.32.1",
4
- "description": "Release workflow helper.",
5
- "author": "Kh4f <kh4f.dev@gmail.com>",
3
+ "version": "0.33.0",
4
+ "description": "Release Workflow Helper",
5
+ "author": "kh4f <kh4f.dev@gmail.com>",
6
6
  "license": "MIT",
7
- "engines": {
8
- "node": "^25.1.0"
9
- },
10
7
  "repository": "https://github.com/kh4f/relion",
11
8
  "bugs": "https://github.com/kh4f/relion/issues",
12
9
  "homepage": "https://github.com/kh4f/relion#readme",
13
10
  "keywords": [
14
11
  "relion",
15
12
  "release",
13
+ "release-automation",
16
14
  "release-workflow",
17
15
  "release-helper",
18
- "semantic-release",
19
- "conventional-changelog",
20
- "standard-version",
21
- "commit-and-tag-version"
16
+ "release-workflow-helper"
22
17
  ],
23
18
  "files": [
24
- "dist",
25
- "package.json",
26
- "LICENSE",
27
- "README.md"
19
+ "dist"
28
20
  ],
29
21
  "type": "module",
30
22
  "main": "dist/index.js",
31
- "types": "dist/index.d.ts",
32
23
  "bin": "dist/cli.js",
24
+ "types": "dist/index.d.ts",
33
25
  "dependencies": {
34
- "handlebars": "^4.7.8",
35
- "semver": "^7.7.3",
36
- "cleye": "^1.3.4"
26
+ "semver": "^7.7.3"
37
27
  },
38
28
  "devDependencies": {
39
- "@eslint/js": "^9.39.0",
40
- "@stylistic/eslint-plugin": "^5.5.0",
41
- "@types/node": "^24.10.0",
29
+ "@eslint/js": "^9.39.2",
30
+ "@stylistic/eslint-plugin": "^5.7.0",
31
+ "@types/node": "^25.0.6",
42
32
  "@types/semver": "^7.7.1",
43
- "eslint": "^9.39.0",
44
- "globals": "^16.5.0",
45
- "lint-staged": "^16.2.6",
46
- "simple-git-hooks": "^2.13.1",
47
- "tsdown": "^0.15.12",
33
+ "eslint": "^9.39.2",
34
+ "globals": "^17.0.0",
35
+ "jiti": "^2.6.1",
36
+ "tsdown": "^0.19.0",
37
+ "tsx": "^4.21.0",
48
38
  "typescript": "^5.9.3",
49
- "tsx": "^4.20.6",
50
- "typescript-eslint": "^8.46.2",
51
- "vitest": "^4.0.6"
52
- },
53
- "simple-git-hooks": {
54
- "pre-commit": "pnpm lint-staged"
55
- },
56
- "lint-staged": {
57
- "*.ts": "pnpm lint:fix"
39
+ "typescript-eslint": "^8.52.0"
58
40
  },
59
41
  "scripts": {
60
42
  "build": "tsdown",
61
43
  "build:watch": "tsdown --watch",
62
- "build:prod": "tsdown --production",
44
+ "build:prod": "tsdown --prod",
63
45
  "lint": "eslint",
64
- "lint:fix": "eslint --fix",
65
- "test": "vitest run",
66
- "test:watch": "vitest",
67
- "release": "pnpm relion",
68
- "release:github": "pnpm relion -p github",
69
- "relion": "tsx scripts/relion-runner"
46
+ "release:context": "pnpm relion -f",
47
+ "release": "pnpm relion -bct --gpg",
48
+ "relion": "tsx src/cli"
70
49
  }
71
50
  }
package/dist/resolver.js DELETED
@@ -1 +0,0 @@
1
- import{dirname as e,resolve as t}from"node:path";import{fileURLToPath as n,pathToFileURL as r}from"node:url";const i=(i,a,o)=>{if(!/^\.{1,2}\//.test(i)||!a.parentURL)return o(i,a);let s=r(t(e(n(a.parentURL)),i+`.ts`)).href;return o(s,a)};export{i as resolve};