relizy 0.2.6 → 0.2.8

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/cli.mjs CHANGED
@@ -5,7 +5,7 @@ import process from 'node:process';
5
5
  import { fileURLToPath } from 'node:url';
6
6
  import { printBanner, logger } from '@maz-ui/node';
7
7
  import { Command } from 'commander';
8
- import { W as isInCI, X as getCIName, b as bump, c as changelog, e as publish, a as providerRelease, r as release } from './shared/relizy.Xd9rFefa.mjs';
8
+ import { W as isInCI, X as getCIName, b as bump, c as changelog, e as publish, a as providerRelease, r as release } from './shared/relizy.DwP99Z7x.mjs';
9
9
  import 'changelogen';
10
10
  import 'fast-glob';
11
11
  import '@inquirer/prompts';
@@ -79,7 +79,8 @@ program.command("bump").description("Bump package versions").option("--major", "
79
79
  suffix: options.suffix,
80
80
  configName: program.opts().config
81
81
  });
82
- } catch {
82
+ } catch (error) {
83
+ logger.error("Failed to bump packages -", error);
83
84
  process.exit(1);
84
85
  }
85
86
  });
@@ -94,7 +95,8 @@ program.command("changelog").description("Generate changelogs for all packages")
94
95
  logLevel: program.opts().logLevel,
95
96
  configName: program.opts().config
96
97
  });
97
- } catch {
98
+ } catch (error) {
99
+ logger.error("Failed to generate changelog -", error);
98
100
  process.exit(1);
99
101
  }
100
102
  });
@@ -111,7 +113,8 @@ program.command("publish").description("Publish packages to registry").option("-
111
113
  logLevel: program.opts().logLevel,
112
114
  configName: program.opts().config
113
115
  });
114
- } catch {
116
+ } catch (error) {
117
+ logger.error("Failed to publish packages -", error);
115
118
  process.exit(1);
116
119
  }
117
120
  });
@@ -127,7 +130,8 @@ program.command("provider-release").description("Publish release to git provider
127
130
  configName: program.opts().config,
128
131
  safetyCheck: hasCliFlag("--no-safety-check") ? false : void 0
129
132
  });
130
- } catch {
133
+ } catch (error) {
134
+ logger.error("Failed to publish release -", error);
131
135
  process.exit(1);
132
136
  }
133
137
  });
@@ -163,7 +167,8 @@ program.command("release").description("Complete release workflow (bump + change
163
167
  configName: program.opts().config,
164
168
  safetyCheck: hasCliFlag("--no-safety-check") ? false : void 0
165
169
  });
166
- } catch {
170
+ } catch (error) {
171
+ logger.error("Failed to release -", error);
167
172
  process.exit(1);
168
173
  }
169
174
  });
package/dist/index.d.mts CHANGED
@@ -57,7 +57,7 @@ declare function getDefaultConfig(): {
57
57
  declare function loadRelizyConfig(options?: {
58
58
  baseConfig?: ResolvedRelizyConfig;
59
59
  overrides?: DeepPartial<RelizyConfig>;
60
- configName?: string;
60
+ configFile?: string;
61
61
  }): Promise<ResolvedRelizyConfig>;
62
62
  type ResolvedConfig = RelizyConfig & ReturnType<typeof getDefaultConfig>;
63
63
  type ResolvedRelizyConfig = ResolvedConfig & {
@@ -223,12 +223,14 @@ declare function getLastTag({ logLevel, cwd }: {
223
223
  }): Promise<string>;
224
224
  declare function getLastRepoTag(options?: {
225
225
  onlyStable?: boolean;
226
+ currentVersion?: string;
226
227
  logLevel?: LogLevel;
227
228
  cwd?: string;
228
229
  }): Promise<string | null>;
229
- declare function getLastPackageTag({ packageName, onlyStable, logLevel, cwd, }: {
230
+ declare function getLastPackageTag({ packageName, onlyStable, currentVersion, logLevel, cwd, }: {
230
231
  packageName: string;
231
232
  onlyStable?: boolean;
233
+ currentVersion?: string;
232
234
  logLevel?: LogLevel;
233
235
  cwd?: string;
234
236
  }): Promise<string | null>;
@@ -334,6 +336,48 @@ declare function getBumpedIndependentPackages({ packages, dryRun, }: {
334
336
  packages: PackageBase[];
335
337
  dryRun: boolean;
336
338
  }): PackageBase[];
339
+ /**
340
+ * Determines if prerelease tags should be filtered out when searching for tags.
341
+ * Returns true when the current version is stable AND we're not graduating to stable.
342
+ *
343
+ * This prevents beta/prerelease tags from being used as the base for stable version bumps.
344
+ *
345
+ * @example
346
+ * shouldFilterPrereleaseTags('4.1.1', false) // true - stable version, not graduating
347
+ * shouldFilterPrereleaseTags('4.1.1-beta.0', true) // false - graduating to stable
348
+ * shouldFilterPrereleaseTags('4.1.1-beta.0', false) // false - prerelease version
349
+ */
350
+ declare function shouldFilterPrereleaseTags(currentVersion: string, graduating: boolean): boolean;
351
+ /**
352
+ * Extracts a semantic version from a git tag.
353
+ * Supports multiple tag formats:
354
+ * - v1.2.3 → 1.2.3
355
+ * - 1.2.3 → 1.2.3
356
+ * - package-name@1.2.3 → 1.2.3
357
+ * - v1.2.3-beta.0 → 1.2.3-beta.0
358
+ *
359
+ * @param tag - The git tag to extract version from
360
+ * @param packageName - Optional package name for independent mode tags (e.g., "pkg-name@1.2.3")
361
+ * @returns The extracted version string or null if invalid
362
+ */
363
+ declare function extractVersionFromTag(tag: string, packageName?: string): string | null;
364
+ /**
365
+ * Checks if a tag's version is compatible with the current version.
366
+ * A tag is compatible if its major version is less than or equal to the current major version.
367
+ *
368
+ * This prevents accidentally using tags from future major versions (e.g., v5.0.0-beta.0)
369
+ * when bumping a current stable version (e.g., 4.1.1 → 4.1.2).
370
+ *
371
+ * @param tagVersion - The semantic version extracted from the tag
372
+ * @param currentVersion - The current package version
373
+ * @returns true if the tag version's major is <= current major version
374
+ *
375
+ * @example
376
+ * isTagVersionCompatibleWithCurrent('4.1.1', '4.1.0') // true - same major
377
+ * isTagVersionCompatibleWithCurrent('5.0.0-beta.0', '4.1.1') // false - newer major
378
+ * isTagVersionCompatibleWithCurrent('3.9.9', '4.1.1') // true - older major
379
+ */
380
+ declare function isTagVersionCompatibleWithCurrent(tagVersion: string, currentVersion: string): boolean;
337
381
 
338
382
  type VersionMode = 'unified' | 'independent' | 'selective';
339
383
  type GitProvider = 'github' | 'gitlab';
@@ -935,5 +979,5 @@ declare function publish(options?: Partial<PublishOptions>): Promise<{
935
979
 
936
980
  declare function release(options?: Partial<ReleaseOptions>): Promise<void>;
937
981
 
938
- export { bump, changelog, checkGitStatusIfDirty, confirmBump, createCommitAndTags, createGitlabRelease, defineConfig, detectGitProvider, detectPackageManager, determinePublishTag, determineReleaseType, determineSemverChange, executeBuildCmd, executeFormatCmd, executeHook, expandPackagesToBumpWithDependents, extractVersionFromPackageTag, fetchGitTags, generateChangelog, getAuthCommand, getBumpedIndependentPackages, getBumpedPackageIndependently, getCIName, getCurrentGitBranch, getCurrentGitRef, getDefaultConfig, getDependentsOf, getFirstCommit, getGitStatus, getIndependentTag, getLastPackageTag, getLastRepoTag, getLastStableTag, getLastTag, getPackageCommits, getPackageDependencies, getPackageNewVersion, getPackages, getPackagesOrBumpedPackages, getPackagesToPublishInIndependentMode, getPackagesToPublishInSelectiveMode, getPreid, getRootPackage, github, gitlab, hasLernaJson, isBumpedPackage, isChangedPreid, isGraduating, isGraduatingToStableBetweenVersion, isInCI, isPrerelease, isPrereleaseReleaseType, isStableReleaseType, loadRelizyConfig, parseGitRemoteUrl, providerRelease, providerReleaseSafetyCheck, publish, publishPackage, publishSafetyCheck, pushCommitAndTags, readPackageJson, readPackages, release, resolveTags, topologicalSort, updateLernaVersion, writeChangelogToFile, writeVersion };
982
+ export { bump, changelog, checkGitStatusIfDirty, confirmBump, createCommitAndTags, createGitlabRelease, defineConfig, detectGitProvider, detectPackageManager, determinePublishTag, determineReleaseType, determineSemverChange, executeBuildCmd, executeFormatCmd, executeHook, expandPackagesToBumpWithDependents, extractVersionFromPackageTag, extractVersionFromTag, fetchGitTags, generateChangelog, getAuthCommand, getBumpedIndependentPackages, getBumpedPackageIndependently, getCIName, getCurrentGitBranch, getCurrentGitRef, getDefaultConfig, getDependentsOf, getFirstCommit, getGitStatus, getIndependentTag, getLastPackageTag, getLastRepoTag, getLastStableTag, getLastTag, getPackageCommits, getPackageDependencies, getPackageNewVersion, getPackages, getPackagesOrBumpedPackages, getPackagesToPublishInIndependentMode, getPackagesToPublishInSelectiveMode, getPreid, getRootPackage, github, gitlab, hasLernaJson, isBumpedPackage, isChangedPreid, isGraduating, isGraduatingToStableBetweenVersion, isInCI, isPrerelease, isPrereleaseReleaseType, isStableReleaseType, isTagVersionCompatibleWithCurrent, loadRelizyConfig, parseGitRemoteUrl, providerRelease, providerReleaseSafetyCheck, publish, publishPackage, publishSafetyCheck, pushCommitAndTags, readPackageJson, readPackages, release, resolveTags, shouldFilterPrereleaseTags, topologicalSort, updateLernaVersion, writeChangelogToFile, writeVersion };
939
983
  export type { BumpConfig, BumpOptions, BumpResult, BumpResultFalsy, BumpResultTruthy, ChangelogConfig, ChangelogOptions, ConfigType, GitProvider, GitlabRelease, GitlabReleaseResponse, HookConfig, HookStep, HookType, MonorepoConfig, PackageBase, PackageManager, PostedRelease, ProviderReleaseOptions, PublishConfig, PublishOptions, PublishResponse, ReadPackage, ReleaseConfig, ReleaseOptions, RelizyConfig, RepoConfig, ResolvedConfig, ResolvedRelizyConfig, ResolvedTags, RootPackage, Step, TemplatesConfig, VersionMode };
package/dist/index.d.ts CHANGED
@@ -57,7 +57,7 @@ declare function getDefaultConfig(): {
57
57
  declare function loadRelizyConfig(options?: {
58
58
  baseConfig?: ResolvedRelizyConfig;
59
59
  overrides?: DeepPartial<RelizyConfig>;
60
- configName?: string;
60
+ configFile?: string;
61
61
  }): Promise<ResolvedRelizyConfig>;
62
62
  type ResolvedConfig = RelizyConfig & ReturnType<typeof getDefaultConfig>;
63
63
  type ResolvedRelizyConfig = ResolvedConfig & {
@@ -223,12 +223,14 @@ declare function getLastTag({ logLevel, cwd }: {
223
223
  }): Promise<string>;
224
224
  declare function getLastRepoTag(options?: {
225
225
  onlyStable?: boolean;
226
+ currentVersion?: string;
226
227
  logLevel?: LogLevel;
227
228
  cwd?: string;
228
229
  }): Promise<string | null>;
229
- declare function getLastPackageTag({ packageName, onlyStable, logLevel, cwd, }: {
230
+ declare function getLastPackageTag({ packageName, onlyStable, currentVersion, logLevel, cwd, }: {
230
231
  packageName: string;
231
232
  onlyStable?: boolean;
233
+ currentVersion?: string;
232
234
  logLevel?: LogLevel;
233
235
  cwd?: string;
234
236
  }): Promise<string | null>;
@@ -334,6 +336,48 @@ declare function getBumpedIndependentPackages({ packages, dryRun, }: {
334
336
  packages: PackageBase[];
335
337
  dryRun: boolean;
336
338
  }): PackageBase[];
339
+ /**
340
+ * Determines if prerelease tags should be filtered out when searching for tags.
341
+ * Returns true when the current version is stable AND we're not graduating to stable.
342
+ *
343
+ * This prevents beta/prerelease tags from being used as the base for stable version bumps.
344
+ *
345
+ * @example
346
+ * shouldFilterPrereleaseTags('4.1.1', false) // true - stable version, not graduating
347
+ * shouldFilterPrereleaseTags('4.1.1-beta.0', true) // false - graduating to stable
348
+ * shouldFilterPrereleaseTags('4.1.1-beta.0', false) // false - prerelease version
349
+ */
350
+ declare function shouldFilterPrereleaseTags(currentVersion: string, graduating: boolean): boolean;
351
+ /**
352
+ * Extracts a semantic version from a git tag.
353
+ * Supports multiple tag formats:
354
+ * - v1.2.3 → 1.2.3
355
+ * - 1.2.3 → 1.2.3
356
+ * - package-name@1.2.3 → 1.2.3
357
+ * - v1.2.3-beta.0 → 1.2.3-beta.0
358
+ *
359
+ * @param tag - The git tag to extract version from
360
+ * @param packageName - Optional package name for independent mode tags (e.g., "pkg-name@1.2.3")
361
+ * @returns The extracted version string or null if invalid
362
+ */
363
+ declare function extractVersionFromTag(tag: string, packageName?: string): string | null;
364
+ /**
365
+ * Checks if a tag's version is compatible with the current version.
366
+ * A tag is compatible if its major version is less than or equal to the current major version.
367
+ *
368
+ * This prevents accidentally using tags from future major versions (e.g., v5.0.0-beta.0)
369
+ * when bumping a current stable version (e.g., 4.1.1 → 4.1.2).
370
+ *
371
+ * @param tagVersion - The semantic version extracted from the tag
372
+ * @param currentVersion - The current package version
373
+ * @returns true if the tag version's major is <= current major version
374
+ *
375
+ * @example
376
+ * isTagVersionCompatibleWithCurrent('4.1.1', '4.1.0') // true - same major
377
+ * isTagVersionCompatibleWithCurrent('5.0.0-beta.0', '4.1.1') // false - newer major
378
+ * isTagVersionCompatibleWithCurrent('3.9.9', '4.1.1') // true - older major
379
+ */
380
+ declare function isTagVersionCompatibleWithCurrent(tagVersion: string, currentVersion: string): boolean;
337
381
 
338
382
  type VersionMode = 'unified' | 'independent' | 'selective';
339
383
  type GitProvider = 'github' | 'gitlab';
@@ -935,5 +979,5 @@ declare function publish(options?: Partial<PublishOptions>): Promise<{
935
979
 
936
980
  declare function release(options?: Partial<ReleaseOptions>): Promise<void>;
937
981
 
938
- export { bump, changelog, checkGitStatusIfDirty, confirmBump, createCommitAndTags, createGitlabRelease, defineConfig, detectGitProvider, detectPackageManager, determinePublishTag, determineReleaseType, determineSemverChange, executeBuildCmd, executeFormatCmd, executeHook, expandPackagesToBumpWithDependents, extractVersionFromPackageTag, fetchGitTags, generateChangelog, getAuthCommand, getBumpedIndependentPackages, getBumpedPackageIndependently, getCIName, getCurrentGitBranch, getCurrentGitRef, getDefaultConfig, getDependentsOf, getFirstCommit, getGitStatus, getIndependentTag, getLastPackageTag, getLastRepoTag, getLastStableTag, getLastTag, getPackageCommits, getPackageDependencies, getPackageNewVersion, getPackages, getPackagesOrBumpedPackages, getPackagesToPublishInIndependentMode, getPackagesToPublishInSelectiveMode, getPreid, getRootPackage, github, gitlab, hasLernaJson, isBumpedPackage, isChangedPreid, isGraduating, isGraduatingToStableBetweenVersion, isInCI, isPrerelease, isPrereleaseReleaseType, isStableReleaseType, loadRelizyConfig, parseGitRemoteUrl, providerRelease, providerReleaseSafetyCheck, publish, publishPackage, publishSafetyCheck, pushCommitAndTags, readPackageJson, readPackages, release, resolveTags, topologicalSort, updateLernaVersion, writeChangelogToFile, writeVersion };
982
+ export { bump, changelog, checkGitStatusIfDirty, confirmBump, createCommitAndTags, createGitlabRelease, defineConfig, detectGitProvider, detectPackageManager, determinePublishTag, determineReleaseType, determineSemverChange, executeBuildCmd, executeFormatCmd, executeHook, expandPackagesToBumpWithDependents, extractVersionFromPackageTag, extractVersionFromTag, fetchGitTags, generateChangelog, getAuthCommand, getBumpedIndependentPackages, getBumpedPackageIndependently, getCIName, getCurrentGitBranch, getCurrentGitRef, getDefaultConfig, getDependentsOf, getFirstCommit, getGitStatus, getIndependentTag, getLastPackageTag, getLastRepoTag, getLastStableTag, getLastTag, getPackageCommits, getPackageDependencies, getPackageNewVersion, getPackages, getPackagesOrBumpedPackages, getPackagesToPublishInIndependentMode, getPackagesToPublishInSelectiveMode, getPreid, getRootPackage, github, gitlab, hasLernaJson, isBumpedPackage, isChangedPreid, isGraduating, isGraduatingToStableBetweenVersion, isInCI, isPrerelease, isPrereleaseReleaseType, isStableReleaseType, isTagVersionCompatibleWithCurrent, loadRelizyConfig, parseGitRemoteUrl, providerRelease, providerReleaseSafetyCheck, publish, publishPackage, publishSafetyCheck, pushCommitAndTags, readPackageJson, readPackages, release, resolveTags, shouldFilterPrereleaseTags, topologicalSort, updateLernaVersion, writeChangelogToFile, writeVersion };
939
983
  export type { BumpConfig, BumpOptions, BumpResult, BumpResultFalsy, BumpResultTruthy, ChangelogConfig, ChangelogOptions, ConfigType, GitProvider, GitlabRelease, GitlabReleaseResponse, HookConfig, HookStep, HookType, MonorepoConfig, PackageBase, PackageManager, PostedRelease, ProviderReleaseOptions, PublishConfig, PublishOptions, PublishResponse, ReadPackage, ReleaseConfig, ReleaseOptions, RelizyConfig, RepoConfig, ResolvedConfig, ResolvedRelizyConfig, ResolvedTags, RootPackage, Step, TemplatesConfig, VersionMode };
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- export { b as bump, c as changelog, n as checkGitStatusIfDirty, ae as confirmBump, u as createCommitAndTags, B as createGitlabRelease, h as defineConfig, q as detectGitProvider, D as detectPackageManager, E as determinePublishTag, a2 as determineReleaseType, a1 as determineSemverChange, Z as executeBuildCmd, Y as executeFormatCmd, V as executeHook, k as expandPackagesToBumpWithDependents, a6 as extractVersionFromPackageTag, o as fetchGitTags, g as generateChangelog, H as getAuthCommand, af as getBumpedIndependentPackages, ad as getBumpedPackageIndependently, X as getCIName, y as getCurrentGitBranch, z as getCurrentGitRef, f as getDefaultConfig, j as getDependentsOf, x as getFirstCommit, m as getGitStatus, P as getIndependentTag, T as getLastPackageTag, S as getLastRepoTag, Q as getLastStableTag, R as getLastTag, N as getPackageCommits, i as getPackageDependencies, a4 as getPackageNewVersion, M as getPackages, $ as getPackagesOrBumpedPackages, G as getPackagesToPublishInIndependentMode, F as getPackagesToPublishInSelectiveMode, ab as getPreid, K as getRootPackage, A as github, C as gitlab, O as hasLernaJson, _ as isBumpedPackage, ac as isChangedPreid, aa as isGraduating, a0 as isGraduatingToStableBetweenVersion, W as isInCI, a7 as isPrerelease, a9 as isPrereleaseReleaseType, a8 as isStableReleaseType, l as loadRelizyConfig, s as parseGitRemoteUrl, a as providerRelease, p as providerReleaseSafetyCheck, e as publish, I as publishPackage, d as publishSafetyCheck, v as pushCommitAndTags, J as readPackageJson, L as readPackages, r as release, U as resolveTags, t as topologicalSort, a5 as updateLernaVersion, w as writeChangelogToFile, a3 as writeVersion } from './shared/relizy.Xd9rFefa.mjs';
1
+ export { b as bump, c as changelog, n as checkGitStatusIfDirty, ae as confirmBump, u as createCommitAndTags, B as createGitlabRelease, h as defineConfig, q as detectGitProvider, D as detectPackageManager, E as determinePublishTag, a2 as determineReleaseType, a1 as determineSemverChange, Z as executeBuildCmd, Y as executeFormatCmd, V as executeHook, k as expandPackagesToBumpWithDependents, a6 as extractVersionFromPackageTag, ah as extractVersionFromTag, o as fetchGitTags, g as generateChangelog, H as getAuthCommand, af as getBumpedIndependentPackages, ad as getBumpedPackageIndependently, X as getCIName, y as getCurrentGitBranch, z as getCurrentGitRef, f as getDefaultConfig, j as getDependentsOf, x as getFirstCommit, m as getGitStatus, P as getIndependentTag, T as getLastPackageTag, S as getLastRepoTag, Q as getLastStableTag, R as getLastTag, N as getPackageCommits, i as getPackageDependencies, a4 as getPackageNewVersion, M as getPackages, $ as getPackagesOrBumpedPackages, G as getPackagesToPublishInIndependentMode, F as getPackagesToPublishInSelectiveMode, ab as getPreid, K as getRootPackage, A as github, C as gitlab, O as hasLernaJson, _ as isBumpedPackage, ac as isChangedPreid, aa as isGraduating, a0 as isGraduatingToStableBetweenVersion, W as isInCI, a7 as isPrerelease, a9 as isPrereleaseReleaseType, a8 as isStableReleaseType, ai as isTagVersionCompatibleWithCurrent, l as loadRelizyConfig, s as parseGitRemoteUrl, a as providerRelease, p as providerReleaseSafetyCheck, e as publish, I as publishPackage, d as publishSafetyCheck, v as pushCommitAndTags, J as readPackageJson, L as readPackages, r as release, U as resolveTags, ag as shouldFilterPrereleaseTags, t as topologicalSort, a5 as updateLernaVersion, w as writeChangelogToFile, a3 as writeVersion } from './shared/relizy.DwP99Z7x.mjs';
2
2
  import '@maz-ui/node';
3
3
  import 'node:fs';
4
4
  import 'node:path';
@@ -216,7 +216,7 @@ function readPackages({
216
216
  const patternsSet = new Set(patterns);
217
217
  if (!patterns)
218
218
  patternsSet.add(".");
219
- logger.debug(`Read package.json files from patterns: ${patternsSet.values()}`);
219
+ logger.debug(`Read package.json files from patterns: ${[...patternsSet].join(", ")}`);
220
220
  for (const pattern of patternsSet) {
221
221
  try {
222
222
  const matches = fastGlob.sync(pattern, {
@@ -1177,21 +1177,22 @@ async function resolveConfig(config, cwd) {
1177
1177
  }
1178
1178
  async function loadRelizyConfig(options) {
1179
1179
  const cwd = options?.overrides?.cwd ?? process$1.cwd();
1180
- const configName = options?.configName ?? "relizy";
1181
1180
  await setupDotenv({ cwd });
1181
+ const configFile = options?.configFile ?? "relizy";
1182
1182
  const defaultConfig = getDefaultConfig();
1183
1183
  const overridesConfig = defu(options?.overrides, options?.baseConfig);
1184
1184
  const results = await loadConfig({
1185
+ dotenv: true,
1185
1186
  cwd,
1186
- name: configName,
1187
+ name: configFile,
1187
1188
  packageJson: true,
1188
1189
  defaults: defaultConfig,
1189
1190
  overrides: overridesConfig
1190
1191
  });
1191
- if (!results._configFile) {
1192
- logger.debug(`No config file found with name "${configName}" - using standalone mode`);
1193
- if (options?.configName) {
1194
- logger.error(`No config file found with name "${configName}"`);
1192
+ if (typeof results._configFile !== "string") {
1193
+ logger.debug(`No config file found with name "${configFile}"`);
1194
+ if (options?.configFile) {
1195
+ logger.error(`No config file found with name "${configFile}"`);
1195
1196
  process$1.exit(1);
1196
1197
  }
1197
1198
  }
@@ -1342,7 +1343,7 @@ async function github(options) {
1342
1343
  const dryRun = options.dryRun ?? false;
1343
1344
  logger.debug(`Dry run: ${dryRun}`);
1344
1345
  const config = await loadRelizyConfig({
1345
- configName: options.configName,
1346
+ configFile: options.configName,
1346
1347
  baseConfig: options.config,
1347
1348
  overrides: {
1348
1349
  from: options.from,
@@ -1586,7 +1587,7 @@ async function gitlab(options = {}) {
1586
1587
  const dryRun = options.dryRun ?? false;
1587
1588
  logger.debug(`Dry run: ${dryRun}`);
1588
1589
  const config = await loadRelizyConfig({
1589
- configName: options.configName,
1590
+ configFile: options.configName,
1590
1591
  baseConfig: options.config,
1591
1592
  overrides: {
1592
1593
  from: options.from,
@@ -2094,6 +2095,40 @@ function getBumpedIndependentPackages({
2094
2095
  }
2095
2096
  return bumpedPackages;
2096
2097
  }
2098
+ function shouldFilterPrereleaseTags(currentVersion, graduating) {
2099
+ return !isPrerelease(currentVersion) && !graduating;
2100
+ }
2101
+ function extractVersionFromTag(tag, packageName) {
2102
+ if (!tag) {
2103
+ return null;
2104
+ }
2105
+ if (packageName) {
2106
+ const prefix = `${packageName}@`;
2107
+ if (tag.startsWith(prefix)) {
2108
+ return tag.slice(prefix.length);
2109
+ }
2110
+ }
2111
+ const atIndex = tag.lastIndexOf("@");
2112
+ if (atIndex !== -1) {
2113
+ return tag.slice(atIndex + 1);
2114
+ }
2115
+ if (tag.startsWith("v") && /^v\d/.test(tag)) {
2116
+ return tag.slice(1);
2117
+ }
2118
+ if (/^\d+\.\d+\.\d+/.test(tag)) {
2119
+ return tag;
2120
+ }
2121
+ return null;
2122
+ }
2123
+ function isTagVersionCompatibleWithCurrent(tagVersion, currentVersion) {
2124
+ try {
2125
+ const tagMajor = semver.major(tagVersion);
2126
+ const currentMajor = semver.major(currentVersion);
2127
+ return tagMajor <= currentMajor;
2128
+ } catch {
2129
+ return false;
2130
+ }
2131
+ }
2097
2132
 
2098
2133
  function getIndependentTag({ version, name }) {
2099
2134
  return `${name}@${version}`;
@@ -2125,18 +2160,131 @@ async function getLastTag({ logLevel, cwd }) {
2125
2160
  logger.debug("Last tag:", lastTag || "No tags found");
2126
2161
  return lastTag;
2127
2162
  }
2163
+ async function getAllRecentRepoTags(options) {
2164
+ const limit = options?.limit;
2165
+ try {
2166
+ const { stdout } = await execPromise(
2167
+ `git tag --sort=-creatordate | head -n ${limit}`,
2168
+ {
2169
+ logLevel: options?.logLevel,
2170
+ noStderr: true,
2171
+ noStdout: true,
2172
+ noSuccess: true,
2173
+ cwd: options?.cwd
2174
+ }
2175
+ );
2176
+ const tags = stdout.trim().split("\n").filter((tag) => tag.length > 0);
2177
+ logger.debug(`Retrieved ${tags.length} recent repo tags`);
2178
+ return tags;
2179
+ } catch {
2180
+ return [];
2181
+ }
2182
+ }
2183
+ async function getAllRecentPackageTags({
2184
+ packageName,
2185
+ limit = 50,
2186
+ logLevel,
2187
+ cwd
2188
+ }) {
2189
+ try {
2190
+ const escapedPackageName = packageName.replace(/[@/]/g, "\\$&");
2191
+ const { stdout } = await execPromise(
2192
+ `git tag --sort=-creatordate | grep -E '^${escapedPackageName}@' | head -n ${limit}`,
2193
+ {
2194
+ logLevel,
2195
+ noStderr: true,
2196
+ noStdout: true,
2197
+ noSuccess: true,
2198
+ cwd
2199
+ }
2200
+ );
2201
+ const tags = stdout.trim().split("\n").filter((tag) => tag.length > 0);
2202
+ logger.debug(`Retrieved ${tags.length} recent tags for package ${packageName}`);
2203
+ return tags;
2204
+ } catch {
2205
+ return [];
2206
+ }
2207
+ }
2208
+ function filterCompatibleTags({
2209
+ tags,
2210
+ currentVersion,
2211
+ onlyStable,
2212
+ packageName
2213
+ }) {
2214
+ const filtered = tags.filter((tag) => {
2215
+ const tagVersion = extractVersionFromTag(tag, packageName);
2216
+ if (!tagVersion) {
2217
+ logger.debug(`Skipping tag ${tag}: cannot extract version`);
2218
+ return false;
2219
+ }
2220
+ if (onlyStable && isPrerelease(tagVersion)) {
2221
+ logger.debug(`Skipping tag ${tag}: prerelease version ${tagVersion} (onlyStable=${onlyStable})`);
2222
+ return false;
2223
+ }
2224
+ if (!isTagVersionCompatibleWithCurrent(tagVersion, currentVersion)) {
2225
+ logger.debug(`Skipping tag ${tag}: version ${tagVersion} has higher major than current ${currentVersion}`);
2226
+ return false;
2227
+ }
2228
+ logger.debug(`Tag ${tag} with version ${tagVersion} is compatible`);
2229
+ return true;
2230
+ });
2231
+ logger.debug(`Filtered ${tags.length} tags down to ${filtered.length} compatible tags`);
2232
+ return filtered;
2233
+ }
2128
2234
  function getLastRepoTag(options) {
2235
+ if (options?.currentVersion) {
2236
+ return getLastRepoTagWithFiltering({
2237
+ currentVersion: options.currentVersion,
2238
+ onlyStable: options.onlyStable ?? false,
2239
+ logLevel: options.logLevel,
2240
+ cwd: options.cwd
2241
+ });
2242
+ }
2129
2243
  if (options?.onlyStable) {
2130
2244
  return getLastStableTag({ logLevel: options?.logLevel, cwd: options?.cwd });
2131
2245
  }
2132
2246
  return getLastTag({ logLevel: options?.logLevel, cwd: options?.cwd });
2133
2247
  }
2248
+ async function getLastRepoTagWithFiltering({
2249
+ currentVersion,
2250
+ onlyStable,
2251
+ logLevel,
2252
+ cwd
2253
+ }) {
2254
+ const recentTags = await getAllRecentRepoTags({ limit: 50, logLevel, cwd });
2255
+ if (recentTags.length === 0) {
2256
+ logger.debug("No tags found in repository");
2257
+ return null;
2258
+ }
2259
+ const compatibleTags = filterCompatibleTags({
2260
+ tags: recentTags,
2261
+ currentVersion,
2262
+ onlyStable
2263
+ });
2264
+ if (compatibleTags.length === 0) {
2265
+ logger.debug("No compatible tags found");
2266
+ return null;
2267
+ }
2268
+ const lastTag = compatibleTags[0];
2269
+ logger.debug(`Last compatible repo tag: ${lastTag}`);
2270
+ return lastTag;
2271
+ }
2134
2272
  async function getLastPackageTag({
2135
2273
  packageName,
2136
2274
  onlyStable,
2275
+ currentVersion,
2137
2276
  logLevel,
2138
2277
  cwd
2139
2278
  }) {
2279
+ if (currentVersion) {
2280
+ return getLastPackageTagWithFiltering({
2281
+ packageName,
2282
+ currentVersion,
2283
+ onlyStable: onlyStable ?? false,
2284
+ logLevel,
2285
+ cwd
2286
+ });
2287
+ }
2140
2288
  try {
2141
2289
  const escapedPackageName = packageName.replace(/[@/]/g, "\\$&");
2142
2290
  let grepPattern;
@@ -2161,16 +2309,52 @@ async function getLastPackageTag({
2161
2309
  return null;
2162
2310
  }
2163
2311
  }
2312
+ async function getLastPackageTagWithFiltering({
2313
+ packageName,
2314
+ currentVersion,
2315
+ onlyStable,
2316
+ logLevel,
2317
+ cwd
2318
+ }) {
2319
+ const recentTags = await getAllRecentPackageTags({
2320
+ packageName,
2321
+ limit: 50,
2322
+ logLevel,
2323
+ cwd
2324
+ });
2325
+ if (recentTags.length === 0) {
2326
+ logger.debug(`No tags found for package ${packageName}`);
2327
+ return null;
2328
+ }
2329
+ const compatibleTags = filterCompatibleTags({
2330
+ tags: recentTags,
2331
+ currentVersion,
2332
+ onlyStable,
2333
+ packageName
2334
+ });
2335
+ if (compatibleTags.length === 0) {
2336
+ logger.debug(`No compatible tags found for package ${packageName}`);
2337
+ return null;
2338
+ }
2339
+ const lastTag = compatibleTags[0];
2340
+ logger.debug(`Last compatible package tag for ${packageName}: ${lastTag}`);
2341
+ return lastTag;
2342
+ }
2164
2343
  async function resolveFromTagIndependent({
2165
2344
  cwd,
2166
2345
  packageName,
2346
+ currentVersion,
2167
2347
  graduating,
2168
2348
  logLevel
2169
2349
  }) {
2350
+ const filterPrereleases = shouldFilterPrereleaseTags(currentVersion, graduating);
2351
+ const onlyStable = graduating || filterPrereleases;
2170
2352
  const lastPackageTag = await getLastPackageTag({
2171
2353
  packageName,
2172
- onlyStable: graduating,
2173
- logLevel
2354
+ currentVersion,
2355
+ onlyStable,
2356
+ logLevel,
2357
+ cwd
2174
2358
  });
2175
2359
  if (!lastPackageTag) {
2176
2360
  return getFirstCommit(cwd);
@@ -2179,10 +2363,18 @@ async function resolveFromTagIndependent({
2179
2363
  }
2180
2364
  async function resolveFromTagUnified({
2181
2365
  config,
2366
+ currentVersion,
2182
2367
  graduating,
2183
2368
  logLevel
2184
2369
  }) {
2185
- const from = await getLastRepoTag({ onlyStable: graduating, logLevel }) || getFirstCommit(config.cwd);
2370
+ const filterPrereleases = shouldFilterPrereleaseTags(currentVersion, graduating);
2371
+ const onlyStable = graduating || filterPrereleases;
2372
+ const from = await getLastRepoTag({
2373
+ currentVersion,
2374
+ onlyStable,
2375
+ logLevel,
2376
+ cwd: config.cwd
2377
+ }) || getFirstCommit(config.cwd);
2186
2378
  return from;
2187
2379
  }
2188
2380
  async function resolveFromTag({
@@ -2190,6 +2382,7 @@ async function resolveFromTag({
2190
2382
  versionMode,
2191
2383
  step,
2192
2384
  packageName,
2385
+ currentVersion,
2193
2386
  graduating,
2194
2387
  logLevel
2195
2388
  }) {
@@ -2201,12 +2394,14 @@ async function resolveFromTag({
2201
2394
  from = await resolveFromTagIndependent({
2202
2395
  cwd: config.cwd,
2203
2396
  packageName,
2397
+ currentVersion,
2204
2398
  graduating,
2205
2399
  logLevel
2206
2400
  });
2207
2401
  } else {
2208
2402
  from = await resolveFromTagUnified({
2209
2403
  config,
2404
+ currentVersion,
2210
2405
  graduating,
2211
2406
  logLevel
2212
2407
  });
@@ -2255,6 +2450,7 @@ async function resolveTags({
2255
2450
  versionMode,
2256
2451
  step,
2257
2452
  packageName: pkg.name,
2453
+ currentVersion: pkg.version,
2258
2454
  graduating,
2259
2455
  logLevel
2260
2456
  });
@@ -2786,7 +2982,7 @@ async function bumpIndependentMode({
2786
2982
  }
2787
2983
  async function bump(options = {}) {
2788
2984
  const config = await loadRelizyConfig({
2789
- configName: options.configName,
2985
+ configFile: options.configName,
2790
2986
  baseConfig: options.config,
2791
2987
  overrides: {
2792
2988
  bump: {
@@ -2944,7 +3140,7 @@ async function generateSimpleRootChangelog({
2944
3140
  }
2945
3141
  async function changelog(options = {}) {
2946
3142
  const config = await loadRelizyConfig({
2947
- configName: options.configName,
3143
+ configFile: options.configName,
2948
3144
  baseConfig: options.config,
2949
3145
  overrides: {
2950
3146
  from: options.from,
@@ -3059,7 +3255,7 @@ function providerReleaseSafetyCheck({ config, provider }) {
3059
3255
  }
3060
3256
  async function providerRelease(options = {}) {
3061
3257
  const config = await loadRelizyConfig({
3062
- configName: options.configName,
3258
+ configFile: options.configName,
3063
3259
  baseConfig: options.config,
3064
3260
  overrides: {
3065
3261
  from: options.from,
@@ -3156,7 +3352,7 @@ async function publishSafetyCheck({ config }) {
3156
3352
  }
3157
3353
  async function publish(options = {}) {
3158
3354
  const config = await loadRelizyConfig({
3159
- configName: options.configName,
3355
+ configFile: options.configName,
3160
3356
  baseConfig: options.config,
3161
3357
  overrides: {
3162
3358
  publish: {
@@ -3252,7 +3448,7 @@ async function publish(options = {}) {
3252
3448
 
3253
3449
  function getReleaseConfig(options = {}) {
3254
3450
  return loadRelizyConfig({
3255
- configName: options.configName,
3451
+ configFile: options.configName,
3256
3452
  overrides: {
3257
3453
  logLevel: options.logLevel,
3258
3454
  from: options.from,
@@ -3442,4 +3638,4 @@ Git provider: ${provider}`);
3442
3638
  }
3443
3639
  }
3444
3640
 
3445
- export { getPackagesOrBumpedPackages as $, github as A, createGitlabRelease as B, gitlab as C, detectPackageManager as D, determinePublishTag as E, getPackagesToPublishInSelectiveMode as F, getPackagesToPublishInIndependentMode as G, getAuthCommand as H, publishPackage as I, readPackageJson as J, getRootPackage as K, readPackages as L, getPackages as M, getPackageCommits as N, hasLernaJson as O, getIndependentTag as P, getLastStableTag as Q, getLastTag as R, getLastRepoTag as S, getLastPackageTag as T, resolveTags as U, executeHook as V, isInCI as W, getCIName as X, executeFormatCmd as Y, executeBuildCmd as Z, isBumpedPackage as _, providerRelease as a, isGraduatingToStableBetweenVersion as a0, determineSemverChange as a1, determineReleaseType as a2, writeVersion as a3, getPackageNewVersion as a4, updateLernaVersion as a5, extractVersionFromPackageTag as a6, isPrerelease as a7, isStableReleaseType as a8, isPrereleaseReleaseType as a9, isGraduating as aa, getPreid as ab, isChangedPreid as ac, getBumpedPackageIndependently as ad, confirmBump as ae, getBumpedIndependentPackages as af, bump as b, changelog as c, publishSafetyCheck as d, publish as e, getDefaultConfig as f, generateChangelog as g, defineConfig as h, getPackageDependencies as i, getDependentsOf as j, expandPackagesToBumpWithDependents as k, loadRelizyConfig as l, getGitStatus as m, checkGitStatusIfDirty as n, fetchGitTags as o, providerReleaseSafetyCheck as p, detectGitProvider as q, release as r, parseGitRemoteUrl as s, topologicalSort as t, createCommitAndTags as u, pushCommitAndTags as v, writeChangelogToFile as w, getFirstCommit as x, getCurrentGitBranch as y, getCurrentGitRef as z };
3641
+ export { getPackagesOrBumpedPackages as $, github as A, createGitlabRelease as B, gitlab as C, detectPackageManager as D, determinePublishTag as E, getPackagesToPublishInSelectiveMode as F, getPackagesToPublishInIndependentMode as G, getAuthCommand as H, publishPackage as I, readPackageJson as J, getRootPackage as K, readPackages as L, getPackages as M, getPackageCommits as N, hasLernaJson as O, getIndependentTag as P, getLastStableTag as Q, getLastTag as R, getLastRepoTag as S, getLastPackageTag as T, resolveTags as U, executeHook as V, isInCI as W, getCIName as X, executeFormatCmd as Y, executeBuildCmd as Z, isBumpedPackage as _, providerRelease as a, isGraduatingToStableBetweenVersion as a0, determineSemverChange as a1, determineReleaseType as a2, writeVersion as a3, getPackageNewVersion as a4, updateLernaVersion as a5, extractVersionFromPackageTag as a6, isPrerelease as a7, isStableReleaseType as a8, isPrereleaseReleaseType as a9, isGraduating as aa, getPreid as ab, isChangedPreid as ac, getBumpedPackageIndependently as ad, confirmBump as ae, getBumpedIndependentPackages as af, shouldFilterPrereleaseTags as ag, extractVersionFromTag as ah, isTagVersionCompatibleWithCurrent as ai, bump as b, changelog as c, publishSafetyCheck as d, publish as e, getDefaultConfig as f, generateChangelog as g, defineConfig as h, getPackageDependencies as i, getDependentsOf as j, expandPackagesToBumpWithDependents as k, loadRelizyConfig as l, getGitStatus as m, checkGitStatusIfDirty as n, fetchGitTags as o, providerReleaseSafetyCheck as p, detectGitProvider as q, release as r, parseGitRemoteUrl as s, topologicalSort as t, createCommitAndTags as u, pushCommitAndTags as v, writeChangelogToFile as w, getFirstCommit as x, getCurrentGitBranch as y, getCurrentGitRef as z };
package/package.json CHANGED
@@ -1,8 +1,7 @@
1
1
  {
2
2
  "name": "relizy",
3
3
  "type": "module",
4
- "version": "0.2.6",
5
- "packageManager": "pnpm@10.22.0",
4
+ "version": "0.2.8",
6
5
  "description": "Changelogen adapter for monorepo management with unified and independent versioning",
7
6
  "author": "Louis Mazel <me@loicmazuel.com>",
8
7
  "license": "MIT",
@@ -55,26 +54,11 @@
55
54
  "engines": {
56
55
  "node": ">=20.0.0"
57
56
  },
58
- "scripts": {
59
- "preinstall": "npx only-allow pnpm",
60
- "postinstall": "npx husky",
61
- "build": "unbuild",
62
- "dev": "unbuild --stub",
63
- "relizy": "node bin/relizy.mjs",
64
- "rly": "node bin/relizy.mjs",
65
- "typecheck": "tsc --noEmit --skipLibCheck",
66
- "lint": "cross-env NODE_ENV=production eslint .",
67
- "lint:fix": "pnpm lint --fix",
68
- "test:unit": "vitest run",
69
- "test:unit:watch": "vitest watch",
70
- "test:unit:coverage": "vitest run --coverage",
71
- "pre-commit": "lint-staged"
72
- },
73
57
  "dependencies": {
74
- "@inquirer/prompts": "^8.0.1",
75
- "@maz-ui/node": "4.3.2-beta.1",
58
+ "@inquirer/prompts": "^8.1.0",
59
+ "@maz-ui/node": "4.3.2",
76
60
  "@maz-ui/utils": "^4.3.0",
77
- "c12": "^3.3.2",
61
+ "c12": "^3.3.3",
78
62
  "changelogen": "^0.6.2",
79
63
  "commander": "^14.0.2",
80
64
  "convert-gitmoji": "^0.1.5",
@@ -84,27 +68,42 @@
84
68
  "semver": "^7.7.2"
85
69
  },
86
70
  "devDependencies": {
87
- "@commitlint/cli": "^20.1.0",
88
- "@commitlint/config-conventional": "^20.0.0",
89
- "@commitlint/cz-commitlint": "^20.1.0",
90
- "@commitlint/types": "^20.0.0",
91
- "@maz-ui/eslint-config": "4.3.2-beta.1",
92
- "@types/node": "^25.0.2",
71
+ "@commitlint/cli": "^20.2.0",
72
+ "@commitlint/config-conventional": "^20.2.0",
73
+ "@commitlint/cz-commitlint": "^20.2.0",
74
+ "@commitlint/types": "^20.2.0",
75
+ "@maz-ui/eslint-config": "4.3.2",
76
+ "@types/node": "^25.0.3",
93
77
  "@types/semver": "^7.7.1",
94
- "@vitest/coverage-v8": "^4.0.10",
78
+ "@vitest/coverage-v8": "^4.0.16",
95
79
  "cross-env": "^10.1.0",
96
- "eslint": "^9.39.1",
80
+ "eslint": "^9.39.2",
97
81
  "husky": "^9.1.7",
98
82
  "jiti": "^2.6.1",
99
- "lint-staged": "^16.2.6",
100
- "memfs": "^4.51.0",
83
+ "lint-staged": "^16.2.7",
84
+ "memfs": "^4.51.1",
101
85
  "typescript": "^5.9.3",
102
86
  "unbuild": "^3.6.1",
103
- "vitest": "^4.0.10"
87
+ "vitest": "^4.0.16"
104
88
  },
105
89
  "lint-staged": {
106
90
  "*.{js,jsx,ts,tsx,mjs,mts,cjs,md,yml,json}": [
107
91
  "eslint --fix"
108
92
  ]
93
+ },
94
+ "scripts": {
95
+ "preinstall": "npx only-allow pnpm",
96
+ "postinstall": "npx husky",
97
+ "build": "unbuild",
98
+ "dev": "unbuild --stub",
99
+ "relizy": "node bin/relizy.mjs",
100
+ "rly": "node bin/relizy.mjs",
101
+ "typecheck": "tsc --noEmit --skipLibCheck",
102
+ "lint": "cross-env NODE_ENV=production eslint .",
103
+ "lint:fix": "pnpm lint --fix",
104
+ "test:unit": "vitest run",
105
+ "test:unit:watch": "vitest watch",
106
+ "test:unit:coverage": "vitest run --coverage",
107
+ "pre-commit": "lint-staged"
109
108
  }
110
- }
109
+ }