relizy 1.5.0-beta.1 → 1.5.0-beta.3

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 { aD as isInCI, aE as getCIName, b as bump, c as changelog, g as publish, e as providerRelease, h as social, p as prComment, r as release } from './shared/relizy.wrrRuBuo.mjs';
8
+ import { as as isInCI, S as getCIName, f as bump, h as changelog, aJ as publish, aH as providerRelease, a$ as social, aG as prComment, aS as release } from './shared/relizy.CdiXgxMk.mjs';
9
9
  import 'node:child_process';
10
10
  import '@maz-ui/utils/helpers/formatJson';
11
11
  import 'c12';
@@ -21,10 +21,10 @@ import 'convert-gitmoji';
21
21
  import 'node-fetch-native';
22
22
 
23
23
  const hasSilentFlag = process.argv.includes("--log-level") && process.argv.includes("silent");
24
- const __filename = fileURLToPath(import.meta.url);
25
- const __dirname = dirname(__filename);
24
+ const __filename$1 = fileURLToPath(import.meta.url);
25
+ const __dirname$1 = dirname(__filename$1);
26
26
  const packageJson = JSON.parse(
27
- readFileSync(join(__dirname, "../package.json"), "utf-8")
27
+ readFileSync(join(__dirname$1, "../package.json"), "utf-8")
28
28
  );
29
29
  const version = packageJson.version;
30
30
  if (!hasSilentFlag) {
@@ -109,7 +109,7 @@ program.command("changelog").description("Generate changelogs for all packages")
109
109
  process.exit(1);
110
110
  }
111
111
  });
112
- program.command("publish").description("Publish packages to registry").option("--registry <url>", "Custom registry URL").option("--tag <tag>", "Publish with specific tag (default: latest for stable, next for prerelease)").option("--access <type>", "Package access level (public or restricted)").option("--otp <code>", "One-time password for 2FA").option("--build-cmd <cmd>", 'Command to build packages before publish (e.g. "pnpm build")').option("--publish-token <token>", 'NPM token (e.g. "123456") - only supported for pnpm and npm').action(async (options) => {
112
+ program.command("publish").description("Publish packages to registry").option("--registry <url>", "Custom registry URL").option("--tag <tag>", "Publish with specific tag (default: latest for stable, next for prerelease)").option("--access <type>", "Package access level (public or restricted)").option("--otp <code>", "One-time password for 2FA").option("--build-cmd <cmd>", 'Command to build packages before publish (e.g. "pnpm build")').option("--publish-token <token>", 'NPM token (e.g. "123456") - only supported for pnpm and npm').option("--skip-existing-versions", "Skip packages whose version already exists on the registry instead of failing").action(async (options) => {
113
113
  try {
114
114
  await publish({
115
115
  registry: options.registry,
@@ -118,6 +118,7 @@ program.command("publish").description("Publish packages to registry").option("-
118
118
  otp: options.otp,
119
119
  buildCmd: options.buildCmd,
120
120
  token: options.publishToken,
121
+ skipExistingVersions: options.skipExistingVersions,
121
122
  dryRun: program.opts().dryRun,
122
123
  logLevel: program.opts().logLevel,
123
124
  configName: program.opts().config
@@ -173,7 +174,7 @@ program.command("pr-comment").description("Post or re-post a PR comment with rel
173
174
  process.exit(1);
174
175
  }
175
176
  });
176
- program.command("release").description("Complete release workflow (bump + changelog + commit + tag + push to remote + publish release)").option("--major", "Bump major version").option("--minor", "Bump minor version").option("--patch", "Bump patch version").option("--prerelease", "Bump prerelease version").option("--premajor", "Bump premajor version").option("--preminor", "Bump preminor version").option("--prepatch", "Bump prepatch version").option("--preid <id>", "Prerelease identifier (alpha, beta, rc, etc.)").option("--suffix <suffix>", "Custom suffix for prerelease versions - replace the last .X with .suffix (e.g. 1.0.0-beta.0 -> 1.0.0-beta.suffix)").option("--from <ref>", "Start commit reference").option("--to <ref>", "End commit reference").option("--no-push", "Skip push changes and tags to remote").option("--no-provider-release", "Skip release creation (GitHub/GitLab)").option("--no-publish", "Skip npm publish").option("--registry <url>", "Custom npm registry URL").option("--tag <tag>", "Publish with specific tag (default: latest for stable, next for prerelease)").option("--access <type>", "Package access level (public or restricted)").option("--otp <code>", "One-time password for 2FA").option("--no-verify", "Skip git hooks during commit").option("--format-cmd <cmd>", 'Command to format CHANGELOG files after generation (e.g. "pnpm lint")').option("--build-cmd <cmd>", 'Command to build packages before publish (e.g. "pnpm build")').option("--no-root-changelog", "Skip generation of root changelog file").option("--token <token>", "Git token (github or gitlab)").option("--force", "Bump even if there are no commits").option("--no-clean", "Skip check if the working directory is clean").option("--no-commit", "Skip commit and tag").option("--no-git-tag", "Skip tag creation").option("--no-changelog", "Skip changelog generation files").option("--provider <provider>", "Git provider (github or gitlab)").option("--no-social", "Skip social media posting").option("--no-pr-comment", "Skip PR comment posting").option("--yes", "Skip confirmation prompt about bumping packages").option("--publish-token <token>", 'NPM token (e.g. "123456") - only supported for pnpm and npm').option("--canary", "Publish a canary release from the current commit").option("--include-private", "Include private packages in bump and changelog phases").option("--ai", "Force-enable AI for release notes and social posts").option("--no-ai", "Force-disable AI for release notes and social posts").action(async (options) => {
177
+ program.command("release").description("Complete release workflow (bump + changelog + commit + tag + push to remote + publish release)").option("--major", "Bump major version").option("--minor", "Bump minor version").option("--patch", "Bump patch version").option("--prerelease", "Bump prerelease version").option("--premajor", "Bump premajor version").option("--preminor", "Bump preminor version").option("--prepatch", "Bump prepatch version").option("--preid <id>", "Prerelease identifier (alpha, beta, rc, etc.)").option("--suffix <suffix>", "Custom suffix for prerelease versions - replace the last .X with .suffix (e.g. 1.0.0-beta.0 -> 1.0.0-beta.suffix)").option("--from <ref>", "Start commit reference").option("--to <ref>", "End commit reference").option("--no-push", "Skip push changes and tags to remote").option("--no-provider-release", "Skip release creation (GitHub/GitLab)").option("--no-publish", "Skip npm publish").option("--registry <url>", "Custom npm registry URL").option("--tag <tag>", "Publish with specific tag (default: latest for stable, next for prerelease)").option("--access <type>", "Package access level (public or restricted)").option("--otp <code>", "One-time password for 2FA").option("--no-verify", "Skip git hooks during commit").option("--format-cmd <cmd>", 'Command to format CHANGELOG files after generation (e.g. "pnpm lint")').option("--build-cmd <cmd>", 'Command to build packages before publish (e.g. "pnpm build")').option("--no-root-changelog", "Skip generation of root changelog file").option("--token <token>", "Git token (github or gitlab)").option("--force", "Bump even if there are no commits").option("--no-clean", "Skip check if the working directory is clean").option("--no-commit", "Skip commit and tag").option("--no-git-tag", "Skip tag creation").option("--no-changelog", "Skip changelog generation files").option("--provider <provider>", "Git provider (github or gitlab)").option("--no-social", "Skip social media posting").option("--no-pr-comment", "Skip PR comment posting").option("--yes", "Skip confirmation prompt about bumping packages").option("--publish-token <token>", 'NPM token (e.g. "123456") - only supported for pnpm and npm').option("--skip-existing-versions", "Skip packages whose version already exists on the registry instead of failing").option("--canary", "Publish a canary release from the current commit").option("--include-private", "Include private packages in bump and changelog phases").option("--ai", "Force-enable AI for release notes and social posts").option("--no-ai", "Force-disable AI for release notes and social posts").action(async (options) => {
177
178
  try {
178
179
  await release({
179
180
  type: getReleaseType(options),
@@ -201,6 +202,7 @@ program.command("release").description("Complete release workflow (bump + change
201
202
  rootChangelog: hasCliFlag("--no-root-changelog") ? false : void 0,
202
203
  token: options.token,
203
204
  publishToken: options.publishToken,
205
+ skipExistingVersions: options.skipExistingVersions,
204
206
  logLevel: program.opts().logLevel,
205
207
  force: options.force,
206
208
  yes: options.yes,
package/dist/index.d.mts CHANGED
@@ -29,6 +29,7 @@ declare function getDefaultConfig(): {
29
29
  token: string | undefined;
30
30
  safetyCheck: true;
31
31
  safetyCheckTimeout: number;
32
+ skipExistingVersions: boolean;
32
33
  packageManager: PackageManager;
33
34
  };
34
35
  tokens: {
@@ -380,6 +381,66 @@ declare function resolveRegistryTargetsForPackage(pkg: PackageBase, config: Reso
380
381
  * scoped to packages that are not part of this release does not block it.
381
382
  */
382
383
  declare function resolveRegistryTargetsForPackages(packages: PackageBase[], config: ResolvedRelizyConfig): RegistryTarget[];
384
+ /**
385
+ * Run `fn` with the registry target's auth token and scope registry
386
+ * temporarily written to the project `.npmrc` (at `config.cwd`), then restore
387
+ * the original file - or remove it if it did not exist - ALWAYS, even on
388
+ * failure.
389
+ *
390
+ * This is the version-proof replacement for passing rc-options as CLI flags:
391
+ * the `.npmrc` contract is stable across npm/pnpm/bun and every version, so we
392
+ * never depend on the CLI argument parser (which pnpm changed in v10+). Only
393
+ * the keys relizy manages are overridden; every other line already in the
394
+ * user's `.npmrc` is preserved untouched. When there is nothing to inject (no
395
+ * token/scope, or a package manager that does not read `.npmrc` such as yarn),
396
+ * the `.npmrc` is left as-is and `fn` runs against the user's own config.
397
+ */
398
+ declare function withRegistryNpmrc<T>({ config, registryTarget, packageName, packageManager, fn, }: {
399
+ config: ResolvedRelizyConfig;
400
+ registryTarget: RegistryTarget;
401
+ packageName?: string;
402
+ packageManager: PackageManager;
403
+ fn: () => Promise<T>;
404
+ }): Promise<T>;
405
+ /**
406
+ * Detect whether a failed publish is caused by the version already existing on
407
+ * the registry (the registry refusing to overwrite an immutable asset), as
408
+ * opposed to any other publish failure. This is what makes a retry safe: the
409
+ * artifact is already there, so the failure is really a "nothing to do".
410
+ *
411
+ * Registries phrase this differently, so we match the known variants:
412
+ * - npm public registry / verdaccio: `EPUBLISHCONFLICT`, `cannot publish over
413
+ * the previously published versions`, `you cannot publish over ...`;
414
+ * - Nexus: `Repository does not allow updating assets` (HTTP 400);
415
+ * - Artifactory/JFrog and others: `already exists` / `version already exists`;
416
+ * - a bare HTTP 409 Conflict from a registry that returns no message body.
417
+ */
418
+ declare function isVersionAlreadyPublishedError(error: unknown): boolean;
419
+ /**
420
+ * Ask the registry whether `pkg@version` already exists. This is the primary,
421
+ * robust idempotency check: it relies on the standard registry metadata
422
+ * endpoint that every npm-compatible registry (npm, Nexus, JFrog, Verdaccio,
423
+ * GitHub/GitLab Packages) implements to serve `install`, rather than on the
424
+ * wording of a publish error - which varies per registry.
425
+ *
426
+ * Strategy: for npm/pnpm, use the `view` command first (it inherits the full
427
+ * `.npmrc` environment - proxy, CA, scoped auth). If that is inconclusive, or
428
+ * for yarn/bun (no usable `view`), fall back to a direct HTTP request to the
429
+ * packument endpoint so every package manager is covered.
430
+ *
431
+ * Returns:
432
+ * - `true` - the version is already published;
433
+ * - `false` - the package, or that specific version, is not on the registry;
434
+ * - `null` - the check was inconclusive (auth/network/registry error), so the
435
+ * caller should fall back to attempting the publish rather than skipping.
436
+ */
437
+ declare function isVersionPublished({ pkg, version, config, packageManager, registryTarget, }: {
438
+ pkg: PackageBase;
439
+ version: string;
440
+ config: ResolvedRelizyConfig;
441
+ packageManager: PackageManager;
442
+ registryTarget: RegistryTarget;
443
+ }): Promise<boolean | null>;
383
444
  declare function getAuthCommand({ packageManager, config, otp, registryTarget, }: {
384
445
  packageManager: PackageManager;
385
446
  config: ResolvedRelizyConfig;
@@ -1260,7 +1321,8 @@ interface RegistryTarget {
1260
1321
  */
1261
1322
  registry: string;
1262
1323
  /**
1263
- * Registry token - only supported for pnpm and npm
1324
+ * Registry token - supported for npm, pnpm and bun (injected via `.npmrc`).
1325
+ * Yarn is not supported (it uses `.yarnrc.yml`); configure its auth yourself.
1264
1326
  */
1265
1327
  token?: string;
1266
1328
  /**
@@ -1321,7 +1383,8 @@ type PublishConfig = ChangelogConfig$1['publish'] & {
1321
1383
  */
1322
1384
  buildCmd?: string;
1323
1385
  /**
1324
- * NPM token (e.g. `123456`) - only supported for pnpm and npm
1386
+ * NPM token (e.g. `123456`) - supported for npm, pnpm and bun (injected via
1387
+ * `.npmrc`). Yarn is not supported (it uses `.yarnrc.yml`).
1325
1388
  */
1326
1389
  token?: string;
1327
1390
  /**
@@ -1344,6 +1407,17 @@ type PublishConfig = ChangelogConfig$1['publish'] & {
1344
1407
  * single-registry behavior.
1345
1408
  */
1346
1409
  registries?: RegistryTarget[];
1410
+ /**
1411
+ * Skip a package (per registry) instead of failing when its version already
1412
+ * exists on the registry. Makes re-running a release idempotent: a retried
1413
+ * job whose version is already published (e.g. a canary rerun on the same
1414
+ * commit, or a partially completed publish) succeeds and only publishes what
1415
+ * is missing, rather than crashing on the registry's "cannot overwrite"
1416
+ * error. When disabled (the default), that situation still fails, but with a
1417
+ * clear error message instead of the raw registry error.
1418
+ * @default false
1419
+ */
1420
+ skipExistingVersions?: boolean;
1347
1421
  };
1348
1422
  interface PublishOptions extends PublishConfig {
1349
1423
  /**
@@ -2081,6 +2155,19 @@ interface CommentBodyParams {
2081
2155
  }
2082
2156
  declare function buildCommentBody(params: CommentBodyParams): string;
2083
2157
  declare function prComment(options?: PrCommentOptions): Promise<boolean>;
2158
+ /**
2159
+ * Best-effort wrapper around {@link prComment} for the release flow: honours the
2160
+ * `--no-pr-comment` gate and swallows errors so a failed PR comment never aborts
2161
+ * an otherwise successful release.
2162
+ */
2163
+ declare function tryPostPrComment({ config, releaseContext, prNumber, dryRun, logLevel, configName, }: {
2164
+ config: ResolvedRelizyConfig;
2165
+ releaseContext: ReleaseContext;
2166
+ prNumber?: number;
2167
+ dryRun: boolean;
2168
+ logLevel?: string;
2169
+ configName?: string;
2170
+ }): Promise<boolean>;
2084
2171
 
2085
2172
  declare function providerReleaseSafetyCheck({ config, provider }: {
2086
2173
  config: ResolvedRelizyConfig;
@@ -2096,6 +2183,22 @@ declare function publish(options?: Partial<PublishOptions>): Promise<{
2096
2183
  publishedPackages: PackageBase[];
2097
2184
  } | undefined>;
2098
2185
 
2186
+ /**
2187
+ * Build the final "Release workflow completed!" summary box from the outcome of
2188
+ * each release step. Pure formatting - no side effects - so it stays easy to read
2189
+ * and to test in isolation, and keeps the `release()` orchestration lean.
2190
+ */
2191
+ declare function buildReleaseSummary({ config, bumpResult, publishResponse, createdTags, provider, postedReleases, providerError, socialResults, prCommentPosted, }: {
2192
+ config: ResolvedRelizyConfig;
2193
+ bumpResult: BumpResultTruthy;
2194
+ publishResponse?: PublishResponse;
2195
+ createdTags: string[];
2196
+ provider?: GitProvider;
2197
+ postedReleases: PostedRelease[];
2198
+ providerError?: string;
2199
+ socialResults?: SocialResult;
2200
+ prCommentPosted: boolean;
2201
+ }): string;
2099
2202
  declare function release(options?: Partial<ReleaseOptions>): Promise<void>;
2100
2203
 
2101
2204
  declare function socialSafetyCheck({ config }: {
@@ -2103,5 +2206,5 @@ declare function socialSafetyCheck({ config }: {
2103
2206
  }): Promise<void>;
2104
2207
  declare function social(options?: Partial<SocialOptions>): Promise<SocialResult>;
2105
2208
 
2106
- export { NEW_PACKAGE_MARKER, PR_COMMENT_MARKER, buildChangelogBody, buildCommentBody, buildCompareLink, buildContributors, bump, capReleaseTypeForZeroMajor, changelog, checkGitStatusIfDirty, collectContributorNames, collectPackageBumps, confirmBump, createCommitAndTags, createGitlabRelease, defineConfig, detectGitProvider, detectPackageManager, detectPullRequest, determinePublishTag, determineReleaseType, determineSemverChange, executeBuildCmd, executeFormatCmd, executeHook, expandPackagesToBumpWithDependents, extractChangelogSummary, extractVersionFromPackageTag, extractVersionFromTag, fetchGitTags, filterOutPrivatePackages, findGitHubPR, findGitLabMR, findReachableCommitBySubject, formatChangelogForSlack, formatPackagesForSlack, formatSlackMessage, formatTweetMessage, generateChangelog, generateMarkDown, getAuthCommand, getBumpedIndependentPackages, getBumpedPackageIndependently, getCIName, getCanaryVersion, getCommitSubject, getCurrentGitBranch, getCurrentGitRef, getDefaultConfig, getDependentsOf, getFirstCommit, getGitStatus, getIndependentTag, getLastPackageTag, getLastRepoTag, getLastStableTag, getLastTag, getModifiedReleaseFilePatterns, getNpmRegistry, getPackageCommits, getPackageDependencies, getPackageNewVersion, getPackages, getPackagesOrBumpedPackages, getPackagesToPublishInIndependentMode, getPackagesToPublishInSelectiveMode, getPreid, getReleaseUrl, getRootPackage, getShortCommitSha, getSlackToken, getSlackWebhookUrl, getTwitterCredentials, github, gitlab, hasLernaJson, isAncestor, isBumpedPackage, isChangedPreid, isGraduating, isGraduatingToStableBetweenVersion, isInCI, isPrerelease, isPrereleaseReleaseType, isStableReleaseType, isTagVersionCompatibleWithCurrent, loadRelizyConfig, mergeTypes, parseChangelogMarkdown, parseGitRemoteUrl, postPrComment, postReleaseToSlack, postReleaseToTwitter, prComment, providerRelease, providerReleaseSafetyCheck, publish, publishPackage, publishSafetyCheck, pushCommitAndTags, pushTagForce, readPackageJson, readPackages, reconcileFromTag, redactSecrets, release, resetRewrittenTagCache, resolveAllConfiguredRegistryTargets, resolveRegistryTargetsForPackage, resolveRegistryTargetsForPackages, resolveTags, retagAnnotatedLocal, rollbackModifiedFiles, shouldFilterPrereleaseTags, social, socialSafetyCheck, tagExists, topologicalSort, updateLernaVersion, writeChangelogToFile, writeVersion };
2209
+ export { NEW_PACKAGE_MARKER, PR_COMMENT_MARKER, buildChangelogBody, buildCommentBody, buildCompareLink, buildContributors, buildReleaseSummary, bump, capReleaseTypeForZeroMajor, changelog, checkGitStatusIfDirty, collectContributorNames, collectPackageBumps, confirmBump, createCommitAndTags, createGitlabRelease, defineConfig, detectGitProvider, detectPackageManager, detectPullRequest, determinePublishTag, determineReleaseType, determineSemverChange, executeBuildCmd, executeFormatCmd, executeHook, expandPackagesToBumpWithDependents, extractChangelogSummary, extractVersionFromPackageTag, extractVersionFromTag, fetchGitTags, filterOutPrivatePackages, findGitHubPR, findGitLabMR, findReachableCommitBySubject, formatChangelogForSlack, formatPackagesForSlack, formatSlackMessage, formatTweetMessage, generateChangelog, generateMarkDown, getAuthCommand, getBumpedIndependentPackages, getBumpedPackageIndependently, getCIName, getCanaryVersion, getCommitSubject, getCurrentGitBranch, getCurrentGitRef, getDefaultConfig, getDependentsOf, getFirstCommit, getGitStatus, getIndependentTag, getLastPackageTag, getLastRepoTag, getLastStableTag, getLastTag, getModifiedReleaseFilePatterns, getNpmRegistry, getPackageCommits, getPackageDependencies, getPackageNewVersion, getPackages, getPackagesOrBumpedPackages, getPackagesToPublishInIndependentMode, getPackagesToPublishInSelectiveMode, getPreid, getReleaseUrl, getRootPackage, getShortCommitSha, getSlackToken, getSlackWebhookUrl, getTwitterCredentials, github, gitlab, hasLernaJson, isAncestor, isBumpedPackage, isChangedPreid, isGraduating, isGraduatingToStableBetweenVersion, isInCI, isPrerelease, isPrereleaseReleaseType, isStableReleaseType, isTagVersionCompatibleWithCurrent, isVersionAlreadyPublishedError, isVersionPublished, loadRelizyConfig, mergeTypes, parseChangelogMarkdown, parseGitRemoteUrl, postPrComment, postReleaseToSlack, postReleaseToTwitter, prComment, providerRelease, providerReleaseSafetyCheck, publish, publishPackage, publishSafetyCheck, pushCommitAndTags, pushTagForce, readPackageJson, readPackages, reconcileFromTag, redactSecrets, release, resetRewrittenTagCache, resolveAllConfiguredRegistryTargets, resolveRegistryTargetsForPackage, resolveRegistryTargetsForPackages, resolveTags, retagAnnotatedLocal, rollbackModifiedFiles, shouldFilterPrereleaseTags, social, socialSafetyCheck, tagExists, topologicalSort, tryPostPrComment, updateLernaVersion, withRegistryNpmrc, writeChangelogToFile, writeVersion };
2107
2210
  export type { AIConfig, AIPromptTarget, AIProviderName, AISocialConfig, AISystemPromptOverrides, AITargetConfig, BumpConfig, BumpOptions, BumpResult, BumpResultFalsy, BumpResultTruthy, ChangelogConfig, ChangelogInclude, ChangelogOptions, ClaudeCodeProviderOptions, ConfigType, GitProvider, GitlabRelease, GitlabReleaseResponse, HookConfig, HookStep, HookType, MonorepoConfig, OnRewrittenTag, PackageBase, PackageBumpEntry, PackageManager, PostedRelease, PrCommentConfig, PrCommentMode, PrCommentOptions, PrCommentStatus, ProviderReleaseOptions, ProviderReleaseResult, PublishConfig, PublishOptions, PublishResponse, PullRequestInfo, ReadPackage, Reference, RegistryTarget, ReleaseConfig, ReleaseContext, ReleaseOptions, RelizyConfig, RepoConfig, ResolvedConfig, ResolvedRelizyConfig, ResolvedTags, ResolvedTwitterCredentials, RootPackage, SlackCredentials, SlackOptions, SlackPackageEntry, SlackSocialConfig, SocialConfig, SocialNetworkResult, SocialOptions, SocialResult, Step, TemplatesConfig, TokensConfig, TwitterCredentials, TwitterOptions, TwitterSocialConfig, VersionMode };
package/dist/index.d.ts CHANGED
@@ -29,6 +29,7 @@ declare function getDefaultConfig(): {
29
29
  token: string | undefined;
30
30
  safetyCheck: true;
31
31
  safetyCheckTimeout: number;
32
+ skipExistingVersions: boolean;
32
33
  packageManager: PackageManager;
33
34
  };
34
35
  tokens: {
@@ -380,6 +381,66 @@ declare function resolveRegistryTargetsForPackage(pkg: PackageBase, config: Reso
380
381
  * scoped to packages that are not part of this release does not block it.
381
382
  */
382
383
  declare function resolveRegistryTargetsForPackages(packages: PackageBase[], config: ResolvedRelizyConfig): RegistryTarget[];
384
+ /**
385
+ * Run `fn` with the registry target's auth token and scope registry
386
+ * temporarily written to the project `.npmrc` (at `config.cwd`), then restore
387
+ * the original file - or remove it if it did not exist - ALWAYS, even on
388
+ * failure.
389
+ *
390
+ * This is the version-proof replacement for passing rc-options as CLI flags:
391
+ * the `.npmrc` contract is stable across npm/pnpm/bun and every version, so we
392
+ * never depend on the CLI argument parser (which pnpm changed in v10+). Only
393
+ * the keys relizy manages are overridden; every other line already in the
394
+ * user's `.npmrc` is preserved untouched. When there is nothing to inject (no
395
+ * token/scope, or a package manager that does not read `.npmrc` such as yarn),
396
+ * the `.npmrc` is left as-is and `fn` runs against the user's own config.
397
+ */
398
+ declare function withRegistryNpmrc<T>({ config, registryTarget, packageName, packageManager, fn, }: {
399
+ config: ResolvedRelizyConfig;
400
+ registryTarget: RegistryTarget;
401
+ packageName?: string;
402
+ packageManager: PackageManager;
403
+ fn: () => Promise<T>;
404
+ }): Promise<T>;
405
+ /**
406
+ * Detect whether a failed publish is caused by the version already existing on
407
+ * the registry (the registry refusing to overwrite an immutable asset), as
408
+ * opposed to any other publish failure. This is what makes a retry safe: the
409
+ * artifact is already there, so the failure is really a "nothing to do".
410
+ *
411
+ * Registries phrase this differently, so we match the known variants:
412
+ * - npm public registry / verdaccio: `EPUBLISHCONFLICT`, `cannot publish over
413
+ * the previously published versions`, `you cannot publish over ...`;
414
+ * - Nexus: `Repository does not allow updating assets` (HTTP 400);
415
+ * - Artifactory/JFrog and others: `already exists` / `version already exists`;
416
+ * - a bare HTTP 409 Conflict from a registry that returns no message body.
417
+ */
418
+ declare function isVersionAlreadyPublishedError(error: unknown): boolean;
419
+ /**
420
+ * Ask the registry whether `pkg@version` already exists. This is the primary,
421
+ * robust idempotency check: it relies on the standard registry metadata
422
+ * endpoint that every npm-compatible registry (npm, Nexus, JFrog, Verdaccio,
423
+ * GitHub/GitLab Packages) implements to serve `install`, rather than on the
424
+ * wording of a publish error - which varies per registry.
425
+ *
426
+ * Strategy: for npm/pnpm, use the `view` command first (it inherits the full
427
+ * `.npmrc` environment - proxy, CA, scoped auth). If that is inconclusive, or
428
+ * for yarn/bun (no usable `view`), fall back to a direct HTTP request to the
429
+ * packument endpoint so every package manager is covered.
430
+ *
431
+ * Returns:
432
+ * - `true` - the version is already published;
433
+ * - `false` - the package, or that specific version, is not on the registry;
434
+ * - `null` - the check was inconclusive (auth/network/registry error), so the
435
+ * caller should fall back to attempting the publish rather than skipping.
436
+ */
437
+ declare function isVersionPublished({ pkg, version, config, packageManager, registryTarget, }: {
438
+ pkg: PackageBase;
439
+ version: string;
440
+ config: ResolvedRelizyConfig;
441
+ packageManager: PackageManager;
442
+ registryTarget: RegistryTarget;
443
+ }): Promise<boolean | null>;
383
444
  declare function getAuthCommand({ packageManager, config, otp, registryTarget, }: {
384
445
  packageManager: PackageManager;
385
446
  config: ResolvedRelizyConfig;
@@ -1260,7 +1321,8 @@ interface RegistryTarget {
1260
1321
  */
1261
1322
  registry: string;
1262
1323
  /**
1263
- * Registry token - only supported for pnpm and npm
1324
+ * Registry token - supported for npm, pnpm and bun (injected via `.npmrc`).
1325
+ * Yarn is not supported (it uses `.yarnrc.yml`); configure its auth yourself.
1264
1326
  */
1265
1327
  token?: string;
1266
1328
  /**
@@ -1321,7 +1383,8 @@ type PublishConfig = ChangelogConfig$1['publish'] & {
1321
1383
  */
1322
1384
  buildCmd?: string;
1323
1385
  /**
1324
- * NPM token (e.g. `123456`) - only supported for pnpm and npm
1386
+ * NPM token (e.g. `123456`) - supported for npm, pnpm and bun (injected via
1387
+ * `.npmrc`). Yarn is not supported (it uses `.yarnrc.yml`).
1325
1388
  */
1326
1389
  token?: string;
1327
1390
  /**
@@ -1344,6 +1407,17 @@ type PublishConfig = ChangelogConfig$1['publish'] & {
1344
1407
  * single-registry behavior.
1345
1408
  */
1346
1409
  registries?: RegistryTarget[];
1410
+ /**
1411
+ * Skip a package (per registry) instead of failing when its version already
1412
+ * exists on the registry. Makes re-running a release idempotent: a retried
1413
+ * job whose version is already published (e.g. a canary rerun on the same
1414
+ * commit, or a partially completed publish) succeeds and only publishes what
1415
+ * is missing, rather than crashing on the registry's "cannot overwrite"
1416
+ * error. When disabled (the default), that situation still fails, but with a
1417
+ * clear error message instead of the raw registry error.
1418
+ * @default false
1419
+ */
1420
+ skipExistingVersions?: boolean;
1347
1421
  };
1348
1422
  interface PublishOptions extends PublishConfig {
1349
1423
  /**
@@ -2081,6 +2155,19 @@ interface CommentBodyParams {
2081
2155
  }
2082
2156
  declare function buildCommentBody(params: CommentBodyParams): string;
2083
2157
  declare function prComment(options?: PrCommentOptions): Promise<boolean>;
2158
+ /**
2159
+ * Best-effort wrapper around {@link prComment} for the release flow: honours the
2160
+ * `--no-pr-comment` gate and swallows errors so a failed PR comment never aborts
2161
+ * an otherwise successful release.
2162
+ */
2163
+ declare function tryPostPrComment({ config, releaseContext, prNumber, dryRun, logLevel, configName, }: {
2164
+ config: ResolvedRelizyConfig;
2165
+ releaseContext: ReleaseContext;
2166
+ prNumber?: number;
2167
+ dryRun: boolean;
2168
+ logLevel?: string;
2169
+ configName?: string;
2170
+ }): Promise<boolean>;
2084
2171
 
2085
2172
  declare function providerReleaseSafetyCheck({ config, provider }: {
2086
2173
  config: ResolvedRelizyConfig;
@@ -2096,6 +2183,22 @@ declare function publish(options?: Partial<PublishOptions>): Promise<{
2096
2183
  publishedPackages: PackageBase[];
2097
2184
  } | undefined>;
2098
2185
 
2186
+ /**
2187
+ * Build the final "Release workflow completed!" summary box from the outcome of
2188
+ * each release step. Pure formatting - no side effects - so it stays easy to read
2189
+ * and to test in isolation, and keeps the `release()` orchestration lean.
2190
+ */
2191
+ declare function buildReleaseSummary({ config, bumpResult, publishResponse, createdTags, provider, postedReleases, providerError, socialResults, prCommentPosted, }: {
2192
+ config: ResolvedRelizyConfig;
2193
+ bumpResult: BumpResultTruthy;
2194
+ publishResponse?: PublishResponse;
2195
+ createdTags: string[];
2196
+ provider?: GitProvider;
2197
+ postedReleases: PostedRelease[];
2198
+ providerError?: string;
2199
+ socialResults?: SocialResult;
2200
+ prCommentPosted: boolean;
2201
+ }): string;
2099
2202
  declare function release(options?: Partial<ReleaseOptions>): Promise<void>;
2100
2203
 
2101
2204
  declare function socialSafetyCheck({ config }: {
@@ -2103,5 +2206,5 @@ declare function socialSafetyCheck({ config }: {
2103
2206
  }): Promise<void>;
2104
2207
  declare function social(options?: Partial<SocialOptions>): Promise<SocialResult>;
2105
2208
 
2106
- export { NEW_PACKAGE_MARKER, PR_COMMENT_MARKER, buildChangelogBody, buildCommentBody, buildCompareLink, buildContributors, bump, capReleaseTypeForZeroMajor, changelog, checkGitStatusIfDirty, collectContributorNames, collectPackageBumps, confirmBump, createCommitAndTags, createGitlabRelease, defineConfig, detectGitProvider, detectPackageManager, detectPullRequest, determinePublishTag, determineReleaseType, determineSemverChange, executeBuildCmd, executeFormatCmd, executeHook, expandPackagesToBumpWithDependents, extractChangelogSummary, extractVersionFromPackageTag, extractVersionFromTag, fetchGitTags, filterOutPrivatePackages, findGitHubPR, findGitLabMR, findReachableCommitBySubject, formatChangelogForSlack, formatPackagesForSlack, formatSlackMessage, formatTweetMessage, generateChangelog, generateMarkDown, getAuthCommand, getBumpedIndependentPackages, getBumpedPackageIndependently, getCIName, getCanaryVersion, getCommitSubject, getCurrentGitBranch, getCurrentGitRef, getDefaultConfig, getDependentsOf, getFirstCommit, getGitStatus, getIndependentTag, getLastPackageTag, getLastRepoTag, getLastStableTag, getLastTag, getModifiedReleaseFilePatterns, getNpmRegistry, getPackageCommits, getPackageDependencies, getPackageNewVersion, getPackages, getPackagesOrBumpedPackages, getPackagesToPublishInIndependentMode, getPackagesToPublishInSelectiveMode, getPreid, getReleaseUrl, getRootPackage, getShortCommitSha, getSlackToken, getSlackWebhookUrl, getTwitterCredentials, github, gitlab, hasLernaJson, isAncestor, isBumpedPackage, isChangedPreid, isGraduating, isGraduatingToStableBetweenVersion, isInCI, isPrerelease, isPrereleaseReleaseType, isStableReleaseType, isTagVersionCompatibleWithCurrent, loadRelizyConfig, mergeTypes, parseChangelogMarkdown, parseGitRemoteUrl, postPrComment, postReleaseToSlack, postReleaseToTwitter, prComment, providerRelease, providerReleaseSafetyCheck, publish, publishPackage, publishSafetyCheck, pushCommitAndTags, pushTagForce, readPackageJson, readPackages, reconcileFromTag, redactSecrets, release, resetRewrittenTagCache, resolveAllConfiguredRegistryTargets, resolveRegistryTargetsForPackage, resolveRegistryTargetsForPackages, resolveTags, retagAnnotatedLocal, rollbackModifiedFiles, shouldFilterPrereleaseTags, social, socialSafetyCheck, tagExists, topologicalSort, updateLernaVersion, writeChangelogToFile, writeVersion };
2209
+ export { NEW_PACKAGE_MARKER, PR_COMMENT_MARKER, buildChangelogBody, buildCommentBody, buildCompareLink, buildContributors, buildReleaseSummary, bump, capReleaseTypeForZeroMajor, changelog, checkGitStatusIfDirty, collectContributorNames, collectPackageBumps, confirmBump, createCommitAndTags, createGitlabRelease, defineConfig, detectGitProvider, detectPackageManager, detectPullRequest, determinePublishTag, determineReleaseType, determineSemverChange, executeBuildCmd, executeFormatCmd, executeHook, expandPackagesToBumpWithDependents, extractChangelogSummary, extractVersionFromPackageTag, extractVersionFromTag, fetchGitTags, filterOutPrivatePackages, findGitHubPR, findGitLabMR, findReachableCommitBySubject, formatChangelogForSlack, formatPackagesForSlack, formatSlackMessage, formatTweetMessage, generateChangelog, generateMarkDown, getAuthCommand, getBumpedIndependentPackages, getBumpedPackageIndependently, getCIName, getCanaryVersion, getCommitSubject, getCurrentGitBranch, getCurrentGitRef, getDefaultConfig, getDependentsOf, getFirstCommit, getGitStatus, getIndependentTag, getLastPackageTag, getLastRepoTag, getLastStableTag, getLastTag, getModifiedReleaseFilePatterns, getNpmRegistry, getPackageCommits, getPackageDependencies, getPackageNewVersion, getPackages, getPackagesOrBumpedPackages, getPackagesToPublishInIndependentMode, getPackagesToPublishInSelectiveMode, getPreid, getReleaseUrl, getRootPackage, getShortCommitSha, getSlackToken, getSlackWebhookUrl, getTwitterCredentials, github, gitlab, hasLernaJson, isAncestor, isBumpedPackage, isChangedPreid, isGraduating, isGraduatingToStableBetweenVersion, isInCI, isPrerelease, isPrereleaseReleaseType, isStableReleaseType, isTagVersionCompatibleWithCurrent, isVersionAlreadyPublishedError, isVersionPublished, loadRelizyConfig, mergeTypes, parseChangelogMarkdown, parseGitRemoteUrl, postPrComment, postReleaseToSlack, postReleaseToTwitter, prComment, providerRelease, providerReleaseSafetyCheck, publish, publishPackage, publishSafetyCheck, pushCommitAndTags, pushTagForce, readPackageJson, readPackages, reconcileFromTag, redactSecrets, release, resetRewrittenTagCache, resolveAllConfiguredRegistryTargets, resolveRegistryTargetsForPackage, resolveRegistryTargetsForPackages, resolveTags, retagAnnotatedLocal, rollbackModifiedFiles, shouldFilterPrereleaseTags, social, socialSafetyCheck, tagExists, topologicalSort, tryPostPrComment, updateLernaVersion, withRegistryNpmrc, writeChangelogToFile, writeVersion };
2107
2210
  export type { AIConfig, AIPromptTarget, AIProviderName, AISocialConfig, AISystemPromptOverrides, AITargetConfig, BumpConfig, BumpOptions, BumpResult, BumpResultFalsy, BumpResultTruthy, ChangelogConfig, ChangelogInclude, ChangelogOptions, ClaudeCodeProviderOptions, ConfigType, GitProvider, GitlabRelease, GitlabReleaseResponse, HookConfig, HookStep, HookType, MonorepoConfig, OnRewrittenTag, PackageBase, PackageBumpEntry, PackageManager, PostedRelease, PrCommentConfig, PrCommentMode, PrCommentOptions, PrCommentStatus, ProviderReleaseOptions, ProviderReleaseResult, PublishConfig, PublishOptions, PublishResponse, PullRequestInfo, ReadPackage, Reference, RegistryTarget, ReleaseConfig, ReleaseContext, ReleaseOptions, RelizyConfig, RepoConfig, ResolvedConfig, ResolvedRelizyConfig, ResolvedTags, ResolvedTwitterCredentials, RootPackage, SlackCredentials, SlackOptions, SlackPackageEntry, SlackSocialConfig, SocialConfig, SocialNetworkResult, SocialOptions, SocialResult, Step, TemplatesConfig, TokensConfig, TwitterCredentials, TwitterOptions, TwitterSocialConfig, VersionMode };
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- export { ax as NEW_PACKAGE_MARKER, a9 as PR_COMMENT_MARKER, S as buildChangelogBody, a as buildCommentBody, R as buildCompareLink, U as buildContributors, b as bump, aL as capReleaseTypeForZeroMajor, c as changelog, v as checkGitStatusIfDirty, T as collectContributorNames, a5 as collectPackageBumps, aZ as confirmBump, B as createCommitAndTags, P as createGitlabRelease, k as defineConfig, y as detectGitProvider, Y as detectPackageManager, a8 as detectPullRequest, Z as determinePublishTag, aN as determineReleaseType, aM as determineSemverChange, aG as executeBuildCmd, aF as executeFormatCmd, aC as executeHook, q as expandPackagesToBumpWithDependents, aq as extractChangelogSummary, aR as extractVersionFromPackageTag, b0 as extractVersionFromTag, x as fetchGitTags, aI as filterOutPrivatePackages, a6 as findGitHubPR, a7 as findGitLabMR, K as findReachableCommitBySubject, am as formatChangelogForSlack, an as formatPackagesForSlack, ao as formatSlackMessage, aA as formatTweetMessage, i as generateChangelog, V as generateMarkDown, a3 as getAuthCommand, a_ as getBumpedIndependentPackages, aY as getBumpedPackageIndependently, aE as getCIName, b1 as getCanaryVersion, J as getCommitSubject, F as getCurrentGitBranch, G as getCurrentGitRef, j as getDefaultConfig, o as getDependentsOf, E as getFirstCommit, u as getGitStatus, as as getIndependentTag, aw as getLastPackageTag, av as getLastRepoTag, at as getLastStableTag, au as getLastTag, A as getModifiedReleaseFilePatterns, X as getNpmRegistry, ag as getPackageCommits, n as getPackageDependencies, aP as getPackageNewVersion, af as getPackages, aJ as getPackagesOrBumpedPackages, $ as getPackagesToPublishInIndependentMode, _ as getPackagesToPublishInSelectiveMode, aW as getPreid, ar as getReleaseUrl, ad as getRootPackage, H as getShortCommitSha, ak as getSlackToken, al as getSlackWebhookUrl, az as getTwitterCredentials, O as github, Q as gitlab, ah as hasLernaJson, I as isAncestor, aH as isBumpedPackage, aX as isChangedPreid, aV as isGraduating, aK as isGraduatingToStableBetweenVersion, aD as isInCI, aS as isPrerelease, aU as isPrereleaseReleaseType, aT as isStableReleaseType, b2 as isTagVersionCompatibleWithCurrent, l as loadRelizyConfig, m as mergeTypes, W as parseChangelogMarkdown, z as parseGitRemoteUrl, aa as postPrComment, ap as postReleaseToSlack, aB as postReleaseToTwitter, p as prComment, e as providerRelease, d as providerReleaseSafetyCheck, g as publish, a4 as publishPackage, f as publishSafetyCheck, C as pushCommitAndTags, N as pushTagForce, ac as readPackageJson, ae as readPackages, aj as reconcileFromTag, ab as redactSecrets, r as release, ai as resetRewrittenTagCache, a0 as resolveAllConfiguredRegistryTargets, a1 as resolveRegistryTargetsForPackage, a2 as resolveRegistryTargetsForPackages, ay as resolveTags, M as retagAnnotatedLocal, D as rollbackModifiedFiles, a$ as shouldFilterPrereleaseTags, h as social, s as socialSafetyCheck, L as tagExists, t as topologicalSort, aQ as updateLernaVersion, w as writeChangelogToFile, aO as writeVersion } from './shared/relizy.wrrRuBuo.mjs';
1
+ export { N as NEW_PACKAGE_MARKER, P as PR_COMMENT_MARKER, b as buildChangelogBody, a as buildCommentBody, c as buildCompareLink, d as buildContributors, e as buildReleaseSummary, f as bump, g as capReleaseTypeForZeroMajor, h as changelog, i as checkGitStatusIfDirty, j as collectContributorNames, k as collectPackageBumps, l as confirmBump, m as createCommitAndTags, n as createGitlabRelease, o as defineConfig, p as detectGitProvider, q as detectPackageManager, r as detectPullRequest, s as determinePublishTag, t as determineReleaseType, u as determineSemverChange, v as executeBuildCmd, w as executeFormatCmd, x as executeHook, y as expandPackagesToBumpWithDependents, z as extractChangelogSummary, A as extractVersionFromPackageTag, B as extractVersionFromTag, C as fetchGitTags, D as filterOutPrivatePackages, E as findGitHubPR, F as findGitLabMR, G as findReachableCommitBySubject, H as formatChangelogForSlack, I as formatPackagesForSlack, J as formatSlackMessage, K as formatTweetMessage, L as generateChangelog, M as generateMarkDown, O as getAuthCommand, Q as getBumpedIndependentPackages, R as getBumpedPackageIndependently, S as getCIName, T as getCanaryVersion, U as getCommitSubject, V as getCurrentGitBranch, W as getCurrentGitRef, X as getDefaultConfig, Y as getDependentsOf, Z as getFirstCommit, _ as getGitStatus, $ as getIndependentTag, a0 as getLastPackageTag, a1 as getLastRepoTag, a2 as getLastStableTag, a3 as getLastTag, a4 as getModifiedReleaseFilePatterns, a5 as getNpmRegistry, a6 as getPackageCommits, a7 as getPackageDependencies, a8 as getPackageNewVersion, a9 as getPackages, aa as getPackagesOrBumpedPackages, ab as getPackagesToPublishInIndependentMode, ac as getPackagesToPublishInSelectiveMode, ad as getPreid, ae as getReleaseUrl, af as getRootPackage, ag as getShortCommitSha, ah as getSlackToken, ai as getSlackWebhookUrl, aj as getTwitterCredentials, ak as github, al as gitlab, am as hasLernaJson, an as isAncestor, ao as isBumpedPackage, ap as isChangedPreid, aq as isGraduating, ar as isGraduatingToStableBetweenVersion, as as isInCI, at as isPrerelease, au as isPrereleaseReleaseType, av as isStableReleaseType, aw as isTagVersionCompatibleWithCurrent, ax as isVersionAlreadyPublishedError, ay as isVersionPublished, az as loadRelizyConfig, aA as mergeTypes, aB as parseChangelogMarkdown, aC as parseGitRemoteUrl, aD as postPrComment, aE as postReleaseToSlack, aF as postReleaseToTwitter, aG as prComment, aH as providerRelease, aI as providerReleaseSafetyCheck, aJ as publish, aK as publishPackage, aL as publishSafetyCheck, aM as pushCommitAndTags, aN as pushTagForce, aO as readPackageJson, aP as readPackages, aQ as reconcileFromTag, aR as redactSecrets, aS as release, aT as resetRewrittenTagCache, aU as resolveAllConfiguredRegistryTargets, aV as resolveRegistryTargetsForPackage, aW as resolveRegistryTargetsForPackages, aX as resolveTags, aY as retagAnnotatedLocal, aZ as rollbackModifiedFiles, a_ as shouldFilterPrereleaseTags, a$ as social, b0 as socialSafetyCheck, b1 as tagExists, b2 as topologicalSort, b3 as tryPostPrComment, b4 as updateLernaVersion, b5 as withRegistryNpmrc, b6 as writeChangelogToFile, b7 as writeVersion } from './shared/relizy.CdiXgxMk.mjs';
2
2
  import '@maz-ui/node';
3
3
  import 'node:child_process';
4
4
  import 'node:process';
@@ -5,7 +5,7 @@ import { formatJson } from '@maz-ui/utils/helpers/formatJson';
5
5
  import { setupDotenv, loadConfig } from 'c12';
6
6
  import { getGitDiff, parseCommits, resolveRepoConfig, getRepoConfig, formatCompareChanges, formatReference, createGithubRelease } from 'changelogen';
7
7
  import { defu } from 'defu';
8
- import { existsSync, readFileSync, statSync, writeFileSync } from 'node:fs';
8
+ import { existsSync, readFileSync, statSync, writeFileSync, rmSync } from 'node:fs';
9
9
  import path, { join, relative, sep } from 'node:path';
10
10
  import { select, confirm, input } from '@inquirer/prompts';
11
11
  import micromatch from 'micromatch';
@@ -1960,6 +1960,71 @@ function resolveRegistryTargetsForPackages(packages, config) {
1960
1960
  const allTargets = packages.flatMap((pkg) => resolveRegistryTargetsForPackage(pkg, config));
1961
1961
  return dedupRegistryTargets(allTargets);
1962
1962
  }
1963
+ function readsNpmrc(packageManager) {
1964
+ return packageManager === "npm" || packageManager === "pnpm" || packageManager === "bun";
1965
+ }
1966
+ function getPackageScope(packageName) {
1967
+ if (!packageName?.startsWith("@") || !packageName.includes("/")) {
1968
+ return void 0;
1969
+ }
1970
+ return packageName.slice(0, packageName.indexOf("/"));
1971
+ }
1972
+ function buildNpmrcEntries({
1973
+ registryTarget,
1974
+ scope,
1975
+ packageManager
1976
+ }) {
1977
+ const { registry, token } = registryTarget;
1978
+ const entries = [];
1979
+ if (registry && scope) {
1980
+ entries.push({ key: `${scope}:registry`, line: `${scope}:registry=${registry}` });
1981
+ }
1982
+ if (token) {
1983
+ if (!registry) {
1984
+ logger.warn("Publish token provided but no registry specified");
1985
+ } else if (!readsNpmrc(packageManager)) {
1986
+ logger.warn("Publish token only supported for npm, pnpm and bun");
1987
+ } else {
1988
+ const url = new URL(registry);
1989
+ const authKey = `//${url.host}${url.pathname}:_authToken`;
1990
+ entries.push({ key: authKey, line: `${authKey}=${token}` });
1991
+ }
1992
+ }
1993
+ return entries;
1994
+ }
1995
+ async function withRegistryNpmrc({
1996
+ config,
1997
+ registryTarget,
1998
+ packageName,
1999
+ packageManager,
2000
+ fn
2001
+ }) {
2002
+ const scope = getPackageScope(packageName);
2003
+ const entries = buildNpmrcEntries({ registryTarget, scope, packageManager });
2004
+ if (entries.length === 0) {
2005
+ return fn();
2006
+ }
2007
+ const npmrcPath = join(config.cwd, ".npmrc");
2008
+ const existed = existsSync(npmrcPath);
2009
+ const original = existed ? readFileSync(npmrcPath, "utf8") : "";
2010
+ const managedKeys = new Set(entries.map((entry) => entry.key));
2011
+ const preservedLines = original.split("\n").filter((line) => {
2012
+ const key = line.split("=")[0]?.trim();
2013
+ return !key || !managedKeys.has(key);
2014
+ });
2015
+ const nextContent = `${[...preservedLines, ...entries.map((entry) => entry.line)].filter(Boolean).join("\n")}
2016
+ `;
2017
+ try {
2018
+ writeFileSync(npmrcPath, nextContent);
2019
+ return await fn();
2020
+ } finally {
2021
+ if (existed) {
2022
+ writeFileSync(npmrcPath, original);
2023
+ } else {
2024
+ rmSync(npmrcPath, { force: true });
2025
+ }
2026
+ }
2027
+ }
1963
2028
  function getCommandArgs({
1964
2029
  packageManager,
1965
2030
  tag,
@@ -1973,19 +2038,6 @@ function getCommandArgs({
1973
2038
  if (registry) {
1974
2039
  args.push("--registry", registry);
1975
2040
  }
1976
- const isPnpmOrNpm = packageManager === "pnpm" || packageManager === "npm";
1977
- const publishToken = registryTarget.token;
1978
- if (publishToken) {
1979
- if (!registry) {
1980
- logger.warn("Publish token provided but no registry specified");
1981
- } else if (!isPnpmOrNpm) {
1982
- logger.warn("Publish token only supported for pnpm and npm");
1983
- } else {
1984
- const registryUrl = new URL(registry);
1985
- const authTokenKey = `--//${registryUrl.host}${registryUrl.pathname}:_authToken=${publishToken}`;
1986
- args.push(authTokenKey);
1987
- }
1988
- }
1989
2041
  const finalOtp = otp ?? sessionOtpByRegistry.get(normalizeRegistryKey(registry)) ?? registryTarget.otp;
1990
2042
  if (finalOtp) {
1991
2043
  args.push("--otp", finalOtp);
@@ -2027,6 +2079,127 @@ function isOtpError(error) {
2027
2079
  ];
2028
2080
  return otpPatterns.some((pattern) => searchText.includes(pattern));
2029
2081
  }
2082
+ function isVersionAlreadyPublishedError(error) {
2083
+ if (typeof error !== "object" || error === null) {
2084
+ return false;
2085
+ }
2086
+ const errorMessage = "message" in error && typeof error.message === "string" ? error.message.toLowerCase() : "";
2087
+ const searchText = `${errorMessage} ${String(error).toLowerCase()}`;
2088
+ const patterns = [
2089
+ "epublishconflict",
2090
+ "cannot publish over",
2091
+ "does not allow updating assets",
2092
+ "version already exists",
2093
+ "already exists in the repository",
2094
+ "status 409",
2095
+ "409 conflict"
2096
+ ];
2097
+ return patterns.some((pattern) => searchText.includes(pattern));
2098
+ }
2099
+ function canQueryVersionViaView(packageManager) {
2100
+ return packageManager === "npm" || packageManager === "pnpm";
2101
+ }
2102
+ function isPackageNotFoundError(error) {
2103
+ if (typeof error !== "object" || error === null) {
2104
+ return false;
2105
+ }
2106
+ const errorMessage = "message" in error && typeof error.message === "string" ? error.message.toLowerCase() : "";
2107
+ const searchText = `${errorMessage} ${String(error).toLowerCase()}`;
2108
+ return searchText.includes("e404") || searchText.includes("404 not found") || searchText.includes("is not in this registry") || searchText.includes("no match found");
2109
+ }
2110
+ async function queryVersionViaView({
2111
+ pkg,
2112
+ version,
2113
+ config,
2114
+ packageManager,
2115
+ registryTarget
2116
+ }) {
2117
+ const args = ["view", `${pkg.name}@${version}`, "version", "--json"];
2118
+ if (registryTarget.registry) {
2119
+ args.push("--registry", registryTarget.registry);
2120
+ }
2121
+ const command = `${packageManager} ${args.join(" ")}`;
2122
+ try {
2123
+ const { stdout } = await withRegistryNpmrc({
2124
+ config,
2125
+ registryTarget,
2126
+ packageName: pkg.name,
2127
+ packageManager,
2128
+ fn: () => execPromise(command, {
2129
+ cwd: pkg.path,
2130
+ noStdout: true,
2131
+ noStderr: true,
2132
+ noSuccess: true,
2133
+ noError: true,
2134
+ logLevel: config.logLevel
2135
+ })
2136
+ });
2137
+ const output = (stdout || "").trim();
2138
+ return output.length > 0 && output !== "undefined" && output !== "[]";
2139
+ } catch (error) {
2140
+ if (isPackageNotFoundError(error)) {
2141
+ return false;
2142
+ }
2143
+ logger.debug(`\`view\` check was inconclusive for ${pkg.name}@${version}: ${error instanceof Error ? error.message : String(error)}`);
2144
+ return null;
2145
+ }
2146
+ }
2147
+ function buildPackumentUrl(registry, packageName) {
2148
+ const base = registry.endsWith("/") ? registry : `${registry}/`;
2149
+ const encodedName = packageName.replace("/", "%2F");
2150
+ return `${base}${encodedName}`;
2151
+ }
2152
+ async function queryVersionViaHttp({
2153
+ pkg,
2154
+ version,
2155
+ config,
2156
+ registryTarget
2157
+ }) {
2158
+ const registry = registryTarget.registry || getNpmRegistry(config.cwd);
2159
+ if (!registry) {
2160
+ return null;
2161
+ }
2162
+ const token = registryTarget.token || config.publish.token || config.tokens.registry;
2163
+ const headers = { accept: "application/json" };
2164
+ if (token) {
2165
+ headers.authorization = `Bearer ${token}`;
2166
+ }
2167
+ const timeoutMs = config.publish.safetyCheckTimeout ?? 15e3;
2168
+ try {
2169
+ const response = await fetch(buildPackumentUrl(registry, pkg.name), {
2170
+ headers,
2171
+ signal: AbortSignal.timeout(timeoutMs)
2172
+ });
2173
+ if (response.status === 404) {
2174
+ return false;
2175
+ }
2176
+ if (!response.ok) {
2177
+ logger.debug(`Packument request for ${pkg.name} returned HTTP ${response.status} - treating as inconclusive`);
2178
+ return null;
2179
+ }
2180
+ const packument = await response.json();
2181
+ return Boolean(packument.versions && Object.hasOwn(packument.versions, version));
2182
+ } catch (error) {
2183
+ logger.debug(`Packument request for ${pkg.name} failed: ${error instanceof Error ? error.message : String(error)}`);
2184
+ return null;
2185
+ }
2186
+ }
2187
+ async function isVersionPublished({
2188
+ pkg,
2189
+ version,
2190
+ config,
2191
+ packageManager,
2192
+ registryTarget
2193
+ }) {
2194
+ if (canQueryVersionViaView(packageManager)) {
2195
+ const viaView = await queryVersionViaView({ pkg, version, config, packageManager, registryTarget });
2196
+ if (viaView !== null) {
2197
+ return viaView;
2198
+ }
2199
+ logger.debug(`Falling back to a direct registry request for ${pkg.name}@${version}`);
2200
+ }
2201
+ return queryVersionViaHttp({ pkg, version, config, registryTarget });
2202
+ }
2030
2203
  function promptOtpWithTimeout(timeout = 9e4) {
2031
2204
  return new Promise((resolve, reject) => {
2032
2205
  const timer = setTimeout(() => {
@@ -2125,7 +2298,15 @@ async function publishToRegistryTarget({
2125
2298
  packageNameAndVersion,
2126
2299
  registryLabel
2127
2300
  }) {
2128
- const tag = determinePublishTag(pkg.newVersion || pkg.version, registryTarget.tag);
2301
+ const tag = determinePublishTag(pkg.newVersion || pkg.version, registryTarget.tag ?? config.publish.tag);
2302
+ if (config.publish.skipExistingVersions && !dryRun) {
2303
+ const version = pkg.newVersion || pkg.version;
2304
+ const alreadyPublished = await isVersionPublished({ pkg, version, config, packageManager, registryTarget });
2305
+ if (alreadyPublished) {
2306
+ logger.warn(`Skipping ${packageNameAndVersion}${registryLabel}: version already exists on the registry (publish.skipExistingVersions enabled)`);
2307
+ return;
2308
+ }
2309
+ }
2129
2310
  let dynamicOtp;
2130
2311
  const maxAttempts = 2;
2131
2312
  for (let attempt = 0; attempt < maxAttempts; attempt++) {
@@ -2138,15 +2319,21 @@ async function publishToRegistryTarget({
2138
2319
  dryRun
2139
2320
  });
2140
2321
  process.chdir(pkg.path);
2141
- await executePublishCommand({
2142
- command,
2143
- packageNameAndVersion,
2144
- packageManager,
2145
- pkg,
2322
+ await withRegistryNpmrc({
2146
2323
  config,
2147
- dryRun,
2148
- tag,
2149
- registryLabel
2324
+ registryTarget,
2325
+ packageName: pkg.name,
2326
+ packageManager,
2327
+ fn: () => executePublishCommand({
2328
+ command,
2329
+ packageNameAndVersion,
2330
+ packageManager,
2331
+ pkg,
2332
+ config,
2333
+ dryRun,
2334
+ tag,
2335
+ registryLabel
2336
+ })
2150
2337
  });
2151
2338
  const registryKey = normalizeRegistryKey(registryTarget.registry);
2152
2339
  if (dynamicOtp && !sessionOtpByRegistry.has(registryKey)) {
@@ -2157,6 +2344,15 @@ async function publishToRegistryTarget({
2157
2344
  } catch (error) {
2158
2345
  if (isOtpError(error) && attempt < maxAttempts - 1) {
2159
2346
  dynamicOtp = await handleOtpError();
2347
+ } else if (isVersionAlreadyPublishedError(error)) {
2348
+ if (config.publish.skipExistingVersions) {
2349
+ logger.warn(`Skipping ${packageNameAndVersion}${registryLabel}: version already exists on the registry (publish.skipExistingVersions enabled)`);
2350
+ return;
2351
+ }
2352
+ throw new Error(
2353
+ `Version ${packageNameAndVersion} already exists on the registry${registryLabel} and cannot be overwritten. This usually happens when re-running a release on the same commit (e.g. a canary rerun). Enable publish.skipExistingVersions (or pass --skip-existing-versions) to skip already-published versions instead of failing.`,
2354
+ { cause: error }
2355
+ );
2160
2356
  } else {
2161
2357
  logger.error(`Failed to publish ${packageNameAndVersion}:`, error);
2162
2358
  throw error;
@@ -2314,6 +2510,9 @@ function getDefaultConfig() {
2314
2510
  // (e.g. a corporate proxy) is honored instead of forcing the public one.
2315
2511
  safetyCheck: true,
2316
2512
  safetyCheckTimeout: 15e3,
2513
+ // Annotated as `boolean` (not the inferred `false` literal) so the resolved
2514
+ // config type stays assignable to true when overridden by config/CLI.
2515
+ skipExistingVersions: false,
2317
2516
  packageManager: detectPackageManager(process$1.cwd())
2318
2517
  },
2319
2518
  tokens: {
@@ -3852,10 +4051,11 @@ function collectPackageBumps({
3852
4051
  }) {
3853
4052
  if (bumpedPackages && bumpedPackages.length > 0) {
3854
4053
  return bumpedPackages.map((pkg) => {
3855
- const hasTransition = Boolean(pkg.newVersion && pkg.oldVersion !== pkg.newVersion);
4054
+ const displayOldVersion = extractVersionFromTag(pkg.fromTag, pkg.name) || pkg.oldVersion;
4055
+ const hasTransition = Boolean(pkg.newVersion && displayOldVersion !== pkg.newVersion);
3856
4056
  return {
3857
4057
  name: pkg.name,
3858
- oldVersion: pkg.oldVersion,
4058
+ oldVersion: displayOldVersion,
3859
4059
  newVersion: pkg.newVersion,
3860
4060
  version: pkg.newVersion || pkg.version,
3861
4061
  hasTransition
@@ -5442,9 +5642,10 @@ function buildSuccessComment({
5442
5642
  const distTag = config.publish?.tag;
5443
5643
  const installCmd = getInstallCommand(config.publish?.packageManager);
5444
5644
  const lines = [PR_COMMENT_MARKER, "", "## \u{1F680} Release published", ""];
5645
+ const previousVersion = extractVersionFromTag(bumpResult?.fromTag ?? "") || bumpResult?.oldVersion;
5445
5646
  lines.push(...buildMetadataLines({
5446
5647
  version,
5447
- oldVersion: bumpResult?.oldVersion,
5648
+ oldVersion: previousVersion,
5448
5649
  tags,
5449
5650
  distTag,
5450
5651
  date,
@@ -5559,6 +5760,32 @@ ${body}`
5559
5760
  }
5560
5761
  return await postPrComment({ config, pr, body });
5561
5762
  }
5763
+ async function tryPostPrComment({
5764
+ config,
5765
+ releaseContext,
5766
+ prNumber,
5767
+ dryRun,
5768
+ logLevel,
5769
+ configName
5770
+ }) {
5771
+ if (!config.release.prComment) {
5772
+ logger.info("Skipping PR comment (--no-pr-comment)");
5773
+ return false;
5774
+ }
5775
+ try {
5776
+ return await prComment({
5777
+ prNumber,
5778
+ dryRun,
5779
+ logLevel,
5780
+ configName,
5781
+ config,
5782
+ releaseContext
5783
+ });
5784
+ } catch (error) {
5785
+ logger.warn("PR comment posting failed:", error);
5786
+ return false;
5787
+ }
5788
+ }
5562
5789
 
5563
5790
  async function providerReleaseSafetyCheck({ config, provider }) {
5564
5791
  if (!config.safetyCheck || !config.release.providerRelease) {
@@ -5686,14 +5913,19 @@ async function checkRegistryAuth({
5686
5913
  }, patienceDelay);
5687
5914
  try {
5688
5915
  logger.info(`Authenticating to package registry${registryLabel}...`);
5689
- await execPromise(authCommand, {
5690
- cwd: config.cwd,
5691
- timeout: timeoutMs,
5692
- noStdout: true,
5693
- noStderr: true,
5694
- noSuccess: true,
5695
- noError: true,
5696
- logLevel: config.logLevel
5916
+ await withRegistryNpmrc({
5917
+ config,
5918
+ registryTarget,
5919
+ packageManager: config.publish.packageManager,
5920
+ fn: () => execPromise(authCommand, {
5921
+ cwd: config.cwd,
5922
+ timeout: timeoutMs,
5923
+ noStdout: true,
5924
+ noStderr: true,
5925
+ noSuccess: true,
5926
+ noError: true,
5927
+ logLevel: config.logLevel
5928
+ })
5697
5929
  });
5698
5930
  logger.info(`Successfully authenticated to package registry${registryLabel}`);
5699
5931
  } catch (error) {
@@ -5738,7 +5970,8 @@ async function publish(options = {}) {
5738
5970
  registries: options.registries,
5739
5971
  tag: options.tag,
5740
5972
  buildCmd: options.buildCmd,
5741
- token: options.token
5973
+ token: options.token,
5974
+ skipExistingVersions: options.skipExistingVersions
5742
5975
  },
5743
5976
  logLevel: options.logLevel,
5744
5977
  safetyCheck: options.safetyCheck
@@ -6325,7 +6558,8 @@ function getReleaseConfig(options = {}) {
6325
6558
  registries: options.registries,
6326
6559
  tag: options.tag,
6327
6560
  buildCmd: options.buildCmd,
6328
- token: options.publishToken
6561
+ token: options.publishToken,
6562
+ skipExistingVersions: options.skipExistingVersions
6329
6563
  },
6330
6564
  release: {
6331
6565
  commit: options.commit,
@@ -6365,31 +6599,51 @@ async function releaseSafetyCheck({
6365
6599
  throw error;
6366
6600
  }
6367
6601
  }
6368
- async function tryPostPrComment({
6602
+ function buildReleaseSummary({
6369
6603
  config,
6370
- releaseContext,
6371
- prNumber,
6372
- dryRun,
6373
- logLevel,
6374
- configName
6604
+ bumpResult,
6605
+ publishResponse,
6606
+ createdTags,
6607
+ provider,
6608
+ postedReleases,
6609
+ providerError,
6610
+ socialResults,
6611
+ prCommentPosted
6375
6612
  }) {
6376
- if (!config.release.prComment) {
6377
- logger.info("Skipping PR comment (--no-pr-comment)");
6378
- return false;
6613
+ const publishedPackageCount = publishResponse?.publishedPackages.length ?? 0;
6614
+ const versionDisplay = config.monorepo?.versionMode === "independent" ? `${bumpResult.bumpedPackages.length} packages bumped independently` : bumpResult.newVersion || readPackageJson(config.cwd)?.version;
6615
+ let providerDisplay = "Disabled";
6616
+ if (config.release.providerRelease) {
6617
+ if (providerError) {
6618
+ providerDisplay = `Failed: ${providerError}`;
6619
+ } else {
6620
+ providerDisplay = `${postedReleases.length} release${postedReleases.length !== 1 ? "s" : ""}`;
6621
+ }
6379
6622
  }
6380
- try {
6381
- return await prComment({
6382
- prNumber,
6383
- dryRun,
6384
- logLevel,
6385
- configName,
6386
- config,
6387
- releaseContext
6388
- });
6389
- } catch (error) {
6390
- logger.warn("PR comment posting failed:", error);
6391
- return false;
6623
+ let socialDisplay = "Disabled";
6624
+ if (config.release.social && socialResults) {
6625
+ if (socialResults.hasErrors) {
6626
+ const failed = socialResults.results.filter((r) => !r.success).map((r) => r.platform);
6627
+ const succeeded = socialResults.results.filter((r) => r.success).map((r) => r.platform);
6628
+ socialDisplay = `${succeeded.length} succeeded, ${failed.length} failed (${failed.join(", ")})`;
6629
+ } else {
6630
+ socialDisplay = `${socialResults.results.length} succeeded`;
6631
+ }
6632
+ }
6633
+ let prCommentDisplay = "Disabled";
6634
+ if (config.release.prComment) {
6635
+ prCommentDisplay = prCommentPosted ? "Posted" : "Failed";
6392
6636
  }
6637
+ return `Release workflow completed!
6638
+
6639
+ Version: ${versionDisplay ?? "Unknown"}
6640
+ Tag(s): ${createdTags?.length ? createdTags.join(", ") : "None"}
6641
+ Pushed: ${config.release.push ? "Yes" : "Disabled"}
6642
+ Published packages: ${config.release.publish ? publishedPackageCount : "Disabled"}
6643
+ Provider release: ${providerDisplay}
6644
+ Social media: ${socialDisplay}
6645
+ PR comment: ${prCommentDisplay}
6646
+ Git provider: ${provider}`;
6393
6647
  }
6394
6648
  async function release(options = {}) {
6395
6649
  const isCanary = options.canary ?? false;
@@ -6578,40 +6832,17 @@ async function release(options = {}) {
6578
6832
  logLevel: config.logLevel,
6579
6833
  configName: options.configName
6580
6834
  });
6581
- const publishedPackageCount = publishResponse?.publishedPackages.length ?? 0;
6582
- const versionDisplay = config.monorepo?.versionMode === "independent" ? `${bumpResult.bumpedPackages.length} packages bumped independently` : bumpResult.newVersion || readPackageJson(config.cwd)?.version;
6583
- let providerDisplay = "Disabled";
6584
- if (config.release.providerRelease) {
6585
- if (providerError) {
6586
- providerDisplay = `Failed: ${providerError}`;
6587
- } else {
6588
- providerDisplay = `${postedReleases.length} release${postedReleases.length !== 1 ? "s" : ""}`;
6589
- }
6590
- }
6591
- let socialDisplay = "Disabled";
6592
- if (config.release.social && socialResults) {
6593
- if (socialResults.hasErrors) {
6594
- const failed = socialResults.results.filter((r) => !r.success).map((r) => r.platform);
6595
- const succeeded = socialResults.results.filter((r) => r.success).map((r) => r.platform);
6596
- socialDisplay = `${succeeded.length} succeeded, ${failed.length} failed (${failed.join(", ")})`;
6597
- } else {
6598
- socialDisplay = `${socialResults.results.length} succeeded`;
6599
- }
6600
- }
6601
- let prCommentDisplay = "Disabled";
6602
- if (config.release.prComment) {
6603
- prCommentDisplay = prCommentPosted ? "Posted" : "Failed";
6604
- }
6605
- logger.box(`Release workflow completed!
6606
-
6607
- Version: ${versionDisplay ?? "Unknown"}
6608
- Tag(s): ${createdTags?.length ? createdTags.join(", ") : "None"}
6609
- Pushed: ${config.release.push ? "Yes" : "Disabled"}
6610
- Published packages: ${config.release.publish ? publishedPackageCount : "Disabled"}
6611
- Provider release: ${providerDisplay}
6612
- Social media: ${socialDisplay}
6613
- PR comment: ${prCommentDisplay}
6614
- Git provider: ${provider}`);
6835
+ logger.box(buildReleaseSummary({
6836
+ config,
6837
+ bumpResult,
6838
+ publishResponse,
6839
+ createdTags,
6840
+ provider,
6841
+ postedReleases,
6842
+ providerError,
6843
+ socialResults,
6844
+ prCommentPosted
6845
+ }));
6615
6846
  await executeHook("success:release", config, dryRun);
6616
6847
  } catch (error) {
6617
6848
  logger.error("Error during release workflow!\n\n", error);
@@ -6632,4 +6863,4 @@ Git provider: ${provider}`);
6632
6863
  }
6633
6864
  }
6634
6865
 
6635
- export { getPackagesToPublishInIndependentMode as $, getModifiedReleaseFilePatterns as A, createCommitAndTags as B, pushCommitAndTags as C, rollbackModifiedFiles as D, getFirstCommit as E, getCurrentGitBranch as F, getCurrentGitRef as G, getShortCommitSha as H, isAncestor as I, getCommitSubject as J, findReachableCommitBySubject as K, tagExists as L, retagAnnotatedLocal as M, pushTagForce as N, github as O, createGitlabRelease as P, gitlab as Q, buildCompareLink as R, buildChangelogBody as S, collectContributorNames as T, buildContributors as U, generateMarkDown as V, parseChangelogMarkdown as W, getNpmRegistry as X, detectPackageManager as Y, determinePublishTag as Z, getPackagesToPublishInSelectiveMode as _, buildCommentBody as a, shouldFilterPrereleaseTags as a$, resolveAllConfiguredRegistryTargets as a0, resolveRegistryTargetsForPackage as a1, resolveRegistryTargetsForPackages as a2, getAuthCommand as a3, publishPackage as a4, collectPackageBumps as a5, findGitHubPR as a6, findGitLabMR as a7, detectPullRequest as a8, PR_COMMENT_MARKER as a9, formatTweetMessage as aA, postReleaseToTwitter as aB, executeHook as aC, isInCI as aD, getCIName as aE, executeFormatCmd as aF, executeBuildCmd as aG, isBumpedPackage as aH, filterOutPrivatePackages as aI, getPackagesOrBumpedPackages as aJ, isGraduatingToStableBetweenVersion as aK, capReleaseTypeForZeroMajor as aL, determineSemverChange as aM, determineReleaseType as aN, writeVersion as aO, getPackageNewVersion as aP, updateLernaVersion as aQ, extractVersionFromPackageTag as aR, isPrerelease as aS, isStableReleaseType as aT, isPrereleaseReleaseType as aU, isGraduating as aV, getPreid as aW, isChangedPreid as aX, getBumpedPackageIndependently as aY, confirmBump as aZ, getBumpedIndependentPackages as a_, postPrComment as aa, redactSecrets as ab, readPackageJson as ac, getRootPackage as ad, readPackages as ae, getPackages as af, getPackageCommits as ag, hasLernaJson as ah, resetRewrittenTagCache as ai, reconcileFromTag as aj, getSlackToken as ak, getSlackWebhookUrl as al, formatChangelogForSlack as am, formatPackagesForSlack as an, formatSlackMessage as ao, postReleaseToSlack as ap, extractChangelogSummary as aq, getReleaseUrl as ar, getIndependentTag as as, getLastStableTag as at, getLastTag as au, getLastRepoTag as av, getLastPackageTag as aw, NEW_PACKAGE_MARKER as ax, resolveTags as ay, getTwitterCredentials as az, bump as b, extractVersionFromTag as b0, getCanaryVersion as b1, isTagVersionCompatibleWithCurrent as b2, changelog as c, providerReleaseSafetyCheck as d, providerRelease as e, publishSafetyCheck as f, publish as g, social as h, generateChangelog as i, getDefaultConfig as j, defineConfig as k, loadRelizyConfig as l, mergeTypes as m, getPackageDependencies as n, getDependentsOf as o, prComment as p, expandPackagesToBumpWithDependents as q, release as r, socialSafetyCheck as s, topologicalSort as t, getGitStatus as u, checkGitStatusIfDirty as v, writeChangelogToFile as w, fetchGitTags as x, detectGitProvider as y, parseGitRemoteUrl as z };
6866
+ export { getIndependentTag as $, extractVersionFromPackageTag as A, extractVersionFromTag as B, fetchGitTags as C, filterOutPrivatePackages as D, findGitHubPR as E, findGitLabMR as F, findReachableCommitBySubject as G, formatChangelogForSlack as H, formatPackagesForSlack as I, formatSlackMessage as J, formatTweetMessage as K, generateChangelog as L, generateMarkDown as M, NEW_PACKAGE_MARKER as N, getAuthCommand as O, PR_COMMENT_MARKER as P, getBumpedIndependentPackages as Q, getBumpedPackageIndependently as R, getCIName as S, getCanaryVersion as T, getCommitSubject as U, getCurrentGitBranch as V, getCurrentGitRef as W, getDefaultConfig as X, getDependentsOf as Y, getFirstCommit as Z, getGitStatus as _, buildCommentBody as a, social as a$, getLastPackageTag as a0, getLastRepoTag as a1, getLastStableTag as a2, getLastTag as a3, getModifiedReleaseFilePatterns as a4, getNpmRegistry as a5, getPackageCommits as a6, getPackageDependencies as a7, getPackageNewVersion as a8, getPackages as a9, mergeTypes as aA, parseChangelogMarkdown as aB, parseGitRemoteUrl as aC, postPrComment as aD, postReleaseToSlack as aE, postReleaseToTwitter as aF, prComment as aG, providerRelease as aH, providerReleaseSafetyCheck as aI, publish as aJ, publishPackage as aK, publishSafetyCheck as aL, pushCommitAndTags as aM, pushTagForce as aN, readPackageJson as aO, readPackages as aP, reconcileFromTag as aQ, redactSecrets as aR, release as aS, resetRewrittenTagCache as aT, resolveAllConfiguredRegistryTargets as aU, resolveRegistryTargetsForPackage as aV, resolveRegistryTargetsForPackages as aW, resolveTags as aX, retagAnnotatedLocal as aY, rollbackModifiedFiles as aZ, shouldFilterPrereleaseTags as a_, getPackagesOrBumpedPackages as aa, getPackagesToPublishInIndependentMode as ab, getPackagesToPublishInSelectiveMode as ac, getPreid as ad, getReleaseUrl as ae, getRootPackage as af, getShortCommitSha as ag, getSlackToken as ah, getSlackWebhookUrl as ai, getTwitterCredentials as aj, github as ak, gitlab as al, hasLernaJson as am, isAncestor as an, isBumpedPackage as ao, isChangedPreid as ap, isGraduating as aq, isGraduatingToStableBetweenVersion as ar, isInCI as as, isPrerelease as at, isPrereleaseReleaseType as au, isStableReleaseType as av, isTagVersionCompatibleWithCurrent as aw, isVersionAlreadyPublishedError as ax, isVersionPublished as ay, loadRelizyConfig as az, buildChangelogBody as b, socialSafetyCheck as b0, tagExists as b1, topologicalSort as b2, tryPostPrComment as b3, updateLernaVersion as b4, withRegistryNpmrc as b5, writeChangelogToFile as b6, writeVersion as b7, buildCompareLink as c, buildContributors as d, buildReleaseSummary as e, bump as f, capReleaseTypeForZeroMajor as g, changelog as h, checkGitStatusIfDirty as i, collectContributorNames as j, collectPackageBumps as k, confirmBump as l, createCommitAndTags as m, createGitlabRelease as n, defineConfig as o, detectGitProvider as p, detectPackageManager as q, detectPullRequest as r, determinePublishTag as s, determineReleaseType as t, determineSemverChange as u, executeBuildCmd as v, executeFormatCmd as w, executeHook as x, expandPackagesToBumpWithDependents as y, extractChangelogSummary as z };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "relizy",
3
3
  "type": "module",
4
- "version": "1.5.0-beta.1",
4
+ "version": "1.5.0-beta.3",
5
5
  "description": "Changelogen adapter for monorepo management with unified and independent versioning",
6
6
  "author": "Louis Mazel <me@loicmazuel.com>",
7
7
  "license": "MIT",
@@ -55,7 +55,7 @@
55
55
  "node": ">=20.0.0"
56
56
  },
57
57
  "peerDependencies": {
58
- "@slack/web-api": "^7.0.0",
58
+ "@slack/web-api": "^7.0.0 || ^8.0.0",
59
59
  "@yoloship/claude-sdk": "^0.2.0-beta.6",
60
60
  "twitter-api-v2": "^1.20.0"
61
61
  },
@@ -73,7 +73,7 @@
73
73
  "dependencies": {
74
74
  "@inquirer/prompts": "^8.7.2",
75
75
  "@maz-ui/node": "5.0.0-beta.26",
76
- "@maz-ui/utils": "5.0.0-beta.25",
76
+ "@maz-ui/utils": "5.0.0-beta.39",
77
77
  "c12": "^3.3.3",
78
78
  "changelogen": "^0.6.2",
79
79
  "commander": "^15.0.0",
@@ -85,28 +85,28 @@
85
85
  "semver": "^7.8.5"
86
86
  },
87
87
  "devDependencies": {
88
- "@commitlint/cli": "^21.2.2",
89
- "@commitlint/config-conventional": "21.2.2",
90
- "@commitlint/cz-commitlint": "^21.2.2",
91
- "@commitlint/types": "^21.2.0",
92
- "@maz-ui/eslint-config": "5.0.0-beta.25",
93
- "@slack/web-api": "7.16.0",
88
+ "@commitlint/cli": "^21.2.3",
89
+ "@commitlint/config-conventional": "21.2.3",
90
+ "@commitlint/cz-commitlint": "^21.2.3",
91
+ "@commitlint/types": "^21.2.3",
92
+ "@maz-ui/eslint-config": "5.0.0-beta.43",
93
+ "@slack/web-api": "8.1.1",
94
94
  "@types/micromatch": "^4.0.10",
95
- "@types/node": "^25.9.2",
95
+ "@types/node": "^26.6.2",
96
96
  "@types/semver": "^7.8.0",
97
- "@vitest/coverage-v8": "^5.0.0",
97
+ "@vitest/coverage-v8": "^5.0.1",
98
98
  "@yoloship/claude-sdk": "0.2.0-beta.6",
99
99
  "cross-env": "10.1.0",
100
- "eslint": "^10.10.0",
100
+ "eslint": "^10.11.0",
101
101
  "husky": "9.1.7",
102
102
  "jiti": "2.7.0",
103
103
  "lint-staged": "^17.5.1",
104
- "memfs": "^4.78.0",
105
- "tsx": "^4.23.13",
104
+ "memfs": "^4.78.1",
105
+ "tsx": "^4.23.15",
106
106
  "twitter-api-v2": "^1.29.1",
107
- "typescript": "^6.0.3",
107
+ "typescript": "^6.0.0",
108
108
  "unbuild": "^3.6.1",
109
- "vitest": "^5.0.0"
109
+ "vitest": "^5.0.1"
110
110
  },
111
111
  "lint-staged": {
112
112
  "*.{js,jsx,ts,tsx,mjs,mts,cjs,md,yml,json}": [