@pubm/core 0.5.2 → 0.5.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/index.js CHANGED
@@ -14330,6 +14330,8 @@ var init_de = __esm(() => {
14330
14330
  "task.release.resolvingMetadata": "Repository-Metadaten für den Release-Entwurf werden aufgelöst...",
14331
14331
  "task.release.openingDraft": "Release-Entwurf für {tag} wird geöffnet...",
14332
14332
  "task.release.collectedCommits": "{count} Commits für {tag} gesammelt.",
14333
+ "task.release.copiedToClipboard": "Release-Notizen in die Zwischenablage kopiert — in den Release-Text einfügen",
14334
+ "task.release.truncated": "Release-Notizen wurden aufgrund der URL-Längenbeschränkung gekürzt",
14333
14335
  "task.publish.registryLabel": "In {registry} veröffentlichen",
14334
14336
  "task.dryRun.registryLabel": "Dry-run {registry}",
14335
14337
  "output.ciPrepareComplete": "CI-Vorbereitung abgeschlossen. Release-Tags gepusht — CI sollte die Veröffentlichung übernehmen.",
@@ -14499,6 +14501,7 @@ Token von {url} generieren`,
14499
14501
  "prompt.add.bumpMinor": "minor — Neue Funktionen, rückwärtskompatibel",
14500
14502
  "prompt.add.bumpMajor": "major — Nicht rückwärtskompatible Änderungen",
14501
14503
  "prompt.add.selectBump": "Hochstufungstyp für {name} auswählen",
14504
+ "prompt.add.selectBumpAll": "Hochstufungstyp für alle Pakete auswählen",
14502
14505
  "prompt.add.summary": "Zusammenfassung der Änderungen",
14503
14506
  "cmd.status.description": "Status der ausstehenden Changesets anzeigen",
14504
14507
  "cmd.status.optionVerbose": "Vollständige Changeset-Inhalte anzeigen",
@@ -14755,6 +14758,8 @@ var init_en = __esm(() => {
14755
14758
  "task.release.resolvingMetadata": "Resolving repository metadata for the release draft...",
14756
14759
  "task.release.openingDraft": "Opening release draft for {tag}...",
14757
14760
  "task.release.collectedCommits": "Collected {count} commits for {tag}.",
14761
+ "task.release.copiedToClipboard": "Release notes copied to clipboard — paste into the release body",
14762
+ "task.release.truncated": "Release notes were truncated due to URL length limit",
14758
14763
  "task.publish.registryLabel": "Publish to {registry}",
14759
14764
  "task.dryRun.registryLabel": "Dry-run {registry}",
14760
14765
  "output.ciPrepareComplete": "CI prepare completed. Release tags pushed — CI should pick up the publish.",
@@ -14924,6 +14929,7 @@ Generate a token from {url}`,
14924
14929
  "prompt.add.bumpMinor": "minor — New features, backward compatible",
14925
14930
  "prompt.add.bumpMajor": "major — Breaking changes",
14926
14931
  "prompt.add.selectBump": "Select bump type for {name}",
14932
+ "prompt.add.selectBumpAll": "Select bump type for all packages",
14927
14933
  "prompt.add.summary": "Summary of changes",
14928
14934
  "cmd.status.description": "Show pending changeset status",
14929
14935
  "cmd.status.optionVerbose": "Show full changeset contents",
@@ -15180,6 +15186,8 @@ var init_es = __esm(() => {
15180
15186
  "task.release.resolvingMetadata": "Resolviendo metadatos del repositorio para el borrador de publicación...",
15181
15187
  "task.release.openingDraft": "Abriendo borrador de publicación para {tag}...",
15182
15188
  "task.release.collectedCommits": "{count} commits recopilados para {tag}.",
15189
+ "task.release.copiedToClipboard": "Notas de la versión copiadas al portapapeles — pégalas en el cuerpo del release",
15190
+ "task.release.truncated": "Las notas de la versión fueron truncadas debido al límite de longitud de la URL",
15183
15191
  "task.publish.registryLabel": "Publicar en {registry}",
15184
15192
  "task.dryRun.registryLabel": "Dry-run {registry}",
15185
15193
  "output.ciPrepareComplete": "Preparación de CI completada. Etiquetas de publicación enviadas — CI debería encargarse de la publicación.",
@@ -15349,6 +15357,7 @@ Generar un token desde {url}`,
15349
15357
  "prompt.add.bumpMinor": "minor — Nuevas características, compatible con versiones anteriores",
15350
15358
  "prompt.add.bumpMajor": "major — Cambios incompatibles con versiones anteriores",
15351
15359
  "prompt.add.selectBump": "Seleccionar tipo de incremento para {name}",
15360
+ "prompt.add.selectBumpAll": "Seleccionar tipo de incremento para todos los paquetes",
15352
15361
  "prompt.add.summary": "Resumen de los cambios",
15353
15362
  "cmd.status.description": "Mostrar el estado de los changesets pendientes",
15354
15363
  "cmd.status.optionVerbose": "Mostrar el contenido completo del changeset",
@@ -15605,6 +15614,8 @@ var init_fr = __esm(() => {
15605
15614
  "task.release.resolvingMetadata": "Résolution des métadonnées du dépôt pour le brouillon de publication...",
15606
15615
  "task.release.openingDraft": "Ouverture du brouillon de publication pour {tag}...",
15607
15616
  "task.release.collectedCommits": "{count} commits collectés pour {tag}.",
15617
+ "task.release.copiedToClipboard": "Notes de version copiées dans le presse-papiers — collez-les dans le corps de la release",
15618
+ "task.release.truncated": "Les notes de version ont été tronquées en raison de la limite de longueur de l'URL",
15608
15619
  "task.publish.registryLabel": "Publier vers {registry}",
15609
15620
  "task.dryRun.registryLabel": "Dry-run {registry}",
15610
15621
  "output.ciPrepareComplete": "Préparation CI terminée. Tags de publication poussés — CI devrait prendre en charge la publication.",
@@ -15774,6 +15785,7 @@ Générer un token depuis {url}`,
15774
15785
  "prompt.add.bumpMinor": "minor — Nouvelles fonctionnalités, rétrocompatible",
15775
15786
  "prompt.add.bumpMajor": "major — Changements non rétrocompatibles",
15776
15787
  "prompt.add.selectBump": "Sélectionner le type d'incrément pour {name}",
15788
+ "prompt.add.selectBumpAll": "Sélectionner le type d'incrément pour tous les paquets",
15777
15789
  "prompt.add.summary": "Résumé des modifications",
15778
15790
  "cmd.status.description": "Afficher le statut des changesets en attente",
15779
15791
  "cmd.status.optionVerbose": "Afficher le contenu complet des changesets",
@@ -16030,6 +16042,8 @@ var init_ko = __esm(() => {
16030
16042
  "task.release.resolvingMetadata": "릴리스 초안을 위한 저장소 메타데이터 확인 중...",
16031
16043
  "task.release.openingDraft": "{tag} 릴리스 초안 열기 중...",
16032
16044
  "task.release.collectedCommits": "{tag}에 대한 {count}개 커밋 수집됨.",
16045
+ "task.release.copiedToClipboard": "릴리즈 노트가 클립보드에 복사되었습니다 — 릴리즈 본문에 붙여넣기 하세요",
16046
+ "task.release.truncated": "URL 길이 제한으로 릴리즈 노트가 잘렸습니다",
16033
16047
  "task.publish.registryLabel": "{registry}에 배포",
16034
16048
  "task.dryRun.registryLabel": "{registry} Dry-run",
16035
16049
  "output.ciPrepareComplete": "CI 준비 완료. 릴리스 태그가 푸시되었습니다 — CI가 배포를 처리합니다.",
@@ -16199,6 +16213,7 @@ var init_ko = __esm(() => {
16199
16213
  "prompt.add.bumpMinor": "minor — 새 기능, 하위 호환",
16200
16214
  "prompt.add.bumpMajor": "major — 호환성이 깨지는 변경",
16201
16215
  "prompt.add.selectBump": "{name}의 버전 업 유형 선택",
16216
+ "prompt.add.selectBumpAll": "모든 패키지의 버전 업 유형 선택",
16202
16217
  "prompt.add.summary": "변경사항 요약",
16203
16218
  "cmd.status.description": "대기 중인 changeset 상태 표시",
16204
16219
  "cmd.status.optionVerbose": "전체 changeset 내용 표시",
@@ -16455,6 +16470,8 @@ var init_zh_cn = __esm(() => {
16455
16470
  "task.release.resolvingMetadata": "正在解析发布草稿的仓库元数据...",
16456
16471
  "task.release.openingDraft": "正在打开 {tag} 的发布草稿...",
16457
16472
  "task.release.collectedCommits": "已为 {tag} 收集 {count} 个提交。",
16473
+ "task.release.copiedToClipboard": "发布说明已复制到剪贴板 — 请粘贴到发布正文中",
16474
+ "task.release.truncated": "由于URL长度限制,发布说明已被截断",
16458
16475
  "task.publish.registryLabel": "发布到 {registry}",
16459
16476
  "task.dryRun.registryLabel": "{registry} Dry-run",
16460
16477
  "output.ciPrepareComplete": "CI 准备完成。发布标签已推送 — CI 应处理发布。",
@@ -16624,6 +16641,7 @@ var init_zh_cn = __esm(() => {
16624
16641
  "prompt.add.bumpMinor": "minor — 新功能,向后兼容",
16625
16642
  "prompt.add.bumpMajor": "major — 破坏性变更",
16626
16643
  "prompt.add.selectBump": "选择 {name} 的升级类型",
16644
+ "prompt.add.selectBumpAll": "选择所有包的升级类型",
16627
16645
  "prompt.add.summary": "变更摘要",
16628
16646
  "cmd.status.description": "显示待处理的 changeset 状态",
16629
16647
  "cmd.status.optionVerbose": "显示完整的 changeset 内容",
@@ -17614,7 +17632,7 @@ var package_default;
17614
17632
  var init_package = __esm(() => {
17615
17633
  package_default = {
17616
17634
  name: "@pubm/core",
17617
- version: "0.5.2",
17635
+ version: "0.5.3",
17618
17636
  type: "module",
17619
17637
  description: "Core SDK for pubm - publish manager for multiple registries",
17620
17638
  types: "./dist/index.d.ts",
@@ -17693,7 +17711,7 @@ var coreEngines, PUBM_VERSION, PUBM_ENGINES;
17693
17711
  var init_pubm_metadata = __esm(() => {
17694
17712
  init_package();
17695
17713
  coreEngines = package_default.engines ?? {};
17696
- PUBM_VERSION = resolveDefine("0.5.2", package_default.version);
17714
+ PUBM_VERSION = resolveDefine("0.5.3", package_default.version);
17697
17715
  PUBM_ENGINES = {
17698
17716
  node: resolveDefine(">=24", coreEngines.node ?? ">=18"),
17699
17717
  git: resolveDefine(">=2.11.0", coreEngines.git ?? ">=2.11.0"),
@@ -22352,9 +22370,11 @@ function createNpmPublishTask(packagePath) {
22352
22370
  task.output = t("task.npm.publishing");
22353
22371
  try {
22354
22372
  if (ctx.runtime.promptEnabled) {
22355
- const result = await npm.publish(ctx.runtime.npmOtp);
22373
+ const result = await npm.publish(ctx.runtime.npmOtp, ctx.runtime.tag);
22356
22374
  if (!result) {
22375
+ let isOtpCreator = false;
22357
22376
  if (!ctx.runtime.npmOtpPromise) {
22377
+ isOtpCreator = true;
22358
22378
  ctx.runtime.npmOtpPromise = (async () => {
22359
22379
  task.title = t("task.npm.otpTitle", { name: npm.packageName });
22360
22380
  const maxAttempts = 3;
@@ -22368,7 +22388,7 @@ function createNpmPublishTask(packagePath) {
22368
22388
  }) : ""
22369
22389
  })
22370
22390
  });
22371
- const success2 = await npm.publish(otp2);
22391
+ const success2 = await npm.publish(otp2, ctx.runtime.tag);
22372
22392
  if (success2) {
22373
22393
  ctx.runtime.npmOtp = otp2;
22374
22394
  task.title = t("task.npm.otpPassed", {
@@ -22384,8 +22404,8 @@ function createNpmPublishTask(packagePath) {
22384
22404
  })();
22385
22405
  }
22386
22406
  const otp = await ctx.runtime.npmOtpPromise;
22387
- if (!ctx.runtime.npmOtp || ctx.runtime.npmOtp !== otp) {
22388
- await npm.publish(otp);
22407
+ if (!isOtpCreator) {
22408
+ await npm.publish(otp, ctx.runtime.tag);
22389
22409
  }
22390
22410
  }
22391
22411
  } else {
@@ -22393,7 +22413,7 @@ function createNpmPublishTask(packagePath) {
22393
22413
  if (!npmTokenEnv) {
22394
22414
  throw new NpmAvailableError(t("error.npm.noAuthToken"));
22395
22415
  }
22396
- const result = await npm.publishProvenance();
22416
+ const result = await npm.publishProvenance(ctx.runtime.tag);
22397
22417
  if (!result) {
22398
22418
  throw new NpmAvailableError(t("error.npm.2faInCi", { name: npm.packageName }));
22399
22419
  }
@@ -22520,7 +22540,7 @@ function createNpmDryRunPublishTask(packagePath) {
22520
22540
  }
22521
22541
  task.output = t("task.dryRun.npm.running");
22522
22542
  await withTokenRetry("npm", ctx, task, async () => {
22523
- await npm.dryRunPublish();
22543
+ await npm.dryRunPublish(ctx.runtime.tag);
22524
22544
  });
22525
22545
  }
22526
22546
  };
@@ -23121,6 +23141,43 @@ import { readFile as readFile4 } from "node:fs/promises";
23121
23141
  import { tmpdir } from "node:os";
23122
23142
  import { join as join3 } from "node:path";
23123
23143
  import process14 from "node:process";
23144
+ function validateNpmLoginUrl(rawUrl) {
23145
+ let parsed;
23146
+ try {
23147
+ parsed = new URL(rawUrl);
23148
+ } catch {
23149
+ return null;
23150
+ }
23151
+ if (parsed.origin !== "https://www.npmjs.com") {
23152
+ return null;
23153
+ }
23154
+ if (parsed.pathname.startsWith("/auth/cli/")) {
23155
+ const authPath2 = parsed.pathname.slice("/auth/cli/".length);
23156
+ return authPath2 ? rawUrl : null;
23157
+ }
23158
+ if (parsed.pathname !== "/login") {
23159
+ return null;
23160
+ }
23161
+ const next = parsed.searchParams.get("next");
23162
+ if (!next?.startsWith("/login/cli/")) {
23163
+ return null;
23164
+ }
23165
+ const authPath = next.slice("/login/cli/".length);
23166
+ return authPath ? rawUrl : null;
23167
+ }
23168
+ function extractNpmLoginUrl(text) {
23169
+ const matches = text.match(/https:\/\/www\.npmjs\.com\/[^\s"'`<>]+/g);
23170
+ if (!matches) {
23171
+ return null;
23172
+ }
23173
+ for (const match of matches) {
23174
+ const validUrl = validateNpmLoginUrl(match);
23175
+ if (validUrl) {
23176
+ return validUrl;
23177
+ }
23178
+ }
23179
+ return null;
23180
+ }
23124
23181
  async function runNpm(args, cwd) {
23125
23182
  const { stdout } = await exec3("npm", args, {
23126
23183
  throwOnError: true,
@@ -23135,7 +23192,7 @@ async function npmPackageRegistry(packagePath) {
23135
23192
  const manifest = await NpmPackageRegistry.reader.read(packagePath);
23136
23193
  return new NpmPackageRegistry(manifest.name, packagePath);
23137
23194
  }
23138
- var NpmError, NpmConnector, NpmPackageRegistry;
23195
+ var NpmError, NPM_OFFICIAL_REGISTRY = "https://registry.npmjs.org", NpmConnector, NpmPackageRegistry;
23139
23196
  var init_npm2 = __esm(() => {
23140
23197
  init_dist();
23141
23198
  init_error4();
@@ -23323,8 +23380,11 @@ var init_npm2 = __esm(() => {
23323
23380
  throw new NpmError(`Failed to run \`npm view ${this.packageName} dist-tags --json\``, { cause: error4 });
23324
23381
  }
23325
23382
  }
23326
- async publish(otp) {
23383
+ async publish(otp, tag) {
23327
23384
  const args = otp ? ["publish", "--otp", otp] : ["publish"];
23385
+ if (tag && tag !== "latest") {
23386
+ args.push("--tag", tag);
23387
+ }
23328
23388
  try {
23329
23389
  await this.npm(args, this.packagePath);
23330
23390
  return true;
@@ -23335,16 +23395,20 @@ var init_npm2 = __esm(() => {
23335
23395
  throw this.classifyPublishError(error4);
23336
23396
  }
23337
23397
  }
23338
- async publishProvenance() {
23398
+ async publishProvenance(tag) {
23399
+ const args = ["publish", "--provenance", "--access", "public"];
23400
+ if (tag && tag !== "latest") {
23401
+ args.push("--tag", tag);
23402
+ }
23339
23403
  try {
23340
- await this.npm(["publish", "--provenance", "--access", "public"], this.packagePath);
23404
+ await this.npm(args, this.packagePath);
23341
23405
  return true;
23342
23406
  } catch (error4) {
23343
23407
  if (error4 instanceof NonZeroExitError && error4.output?.stderr.includes("EOTP")) {
23344
23408
  return false;
23345
23409
  }
23346
23410
  if (this.isProvenanceError(error4)) {
23347
- return this.publish();
23411
+ return this.publish(undefined, tag);
23348
23412
  }
23349
23413
  throw this.classifyPublishError(error4);
23350
23414
  }
@@ -23355,9 +23419,13 @@ var init_npm2 = __esm(() => {
23355
23419
  async unpublish(packageName, version) {
23356
23420
  await this.npm(["unpublish", `${packageName}@${version}`], this.packagePath);
23357
23421
  }
23358
- async dryRunPublish() {
23422
+ async dryRunPublish(tag) {
23423
+ const args = ["publish", "--dry-run"];
23424
+ if (tag && tag !== "latest") {
23425
+ args.push("--tag", tag);
23426
+ }
23359
23427
  try {
23360
- await exec3("npm", ["publish", "--dry-run"], {
23428
+ await exec3("npm", args, {
23361
23429
  throwOnError: true,
23362
23430
  nodeOptions: {
23363
23431
  cwd: this.packagePath,
@@ -23389,44 +23457,21 @@ ${stderr}` : ""}`, { cause: error4 });
23389
23457
  if (!await this.isLoggedIn()) {
23390
23458
  if (ctx.runtime.promptEnabled) {
23391
23459
  try {
23392
- task.output = "Launching npm login...";
23393
- const { spawnInteractive: spawnInteractive2 } = await Promise.resolve().then(() => exports_spawn_interactive);
23394
- const child = spawnInteractive2(["npm", "login"]);
23395
- let opened = false;
23396
- const readStream = async (stream, onData) => {
23397
- const reader = stream.getReader();
23398
- const decoder = new TextDecoder;
23399
- try {
23400
- while (true) {
23401
- const { done, value } = await reader.read();
23402
- if (done)
23403
- break;
23404
- onData(decoder.decode(value));
23460
+ let loginPromise = ctx.runtime.npmLoginPromise;
23461
+ if (!loginPromise) {
23462
+ loginPromise = this.runInteractiveLogin(task).finally(() => {
23463
+ if (ctx.runtime.npmLoginPromise === loginPromise) {
23464
+ ctx.runtime.npmLoginPromise = undefined;
23405
23465
  }
23406
- } finally {
23407
- reader.releaseLock();
23408
- }
23409
- };
23410
- await new Promise((resolve, reject) => {
23411
- const onData = (text) => {
23412
- const urlMatch = text.match(/https:\/\/www\.npmjs\.com\/login[^\s]*/);
23413
- if (urlMatch && !opened) {
23414
- opened = true;
23415
- task.output = `Login at: ${color.cyan(urlMatch[0])}`;
23416
- Promise.resolve().then(() => (init_open_url(), exports_open_url)).then(({ openUrl: openUrl2 }) => openUrl2(urlMatch[0]));
23417
- child.stdin.write(`
23418
- `);
23419
- child.stdin.flush();
23420
- }
23421
- };
23422
- Promise.all([
23423
- readStream(child.stdout, onData),
23424
- readStream(child.stderr, onData)
23425
- ]).catch(reject);
23426
- child.exited.then((code) => code === 0 ? resolve() : reject(new Error(`npm login exited with code ${code}`))).catch(reject);
23427
- });
23466
+ });
23467
+ ctx.runtime.npmLoginPromise = loginPromise;
23468
+ } else {
23469
+ task.output = "Waiting for npm login...";
23470
+ }
23471
+ await loginPromise;
23428
23472
  } catch (error4) {
23429
- throw new NpmError("npm login failed. Please run `npm login` manually and try again.", { cause: error4 });
23473
+ const detail = error4 instanceof Error ? `: ${error4.message}` : "";
23474
+ throw new NpmError(`npm login failed${detail}. Please run \`npm login\` manually and try again.`, { cause: error4 });
23430
23475
  }
23431
23476
  if (!await this.isLoggedIn()) {
23432
23477
  throw new NpmError("Still not logged in after npm login. Please verify your credentials.");
@@ -23456,6 +23501,11 @@ ${stderr}` : ""}`, { cause: error4 });
23456
23501
  requiredManifest: "package.json"
23457
23502
  };
23458
23503
  }
23504
+ isOfficialNpmRegistry() {
23505
+ if (!this.registry)
23506
+ return true;
23507
+ return normalizeRegistryUrl(this.registry) === "registry.npmjs.org";
23508
+ }
23459
23509
  isProvenanceError(error4) {
23460
23510
  if (!(error4 instanceof NonZeroExitError))
23461
23511
  return false;
@@ -23481,6 +23531,110 @@ ${stderr}` : ""}`, { cause: error4 });
23481
23531
  }
23482
23532
  return new NpmError("Failed to publish to npm", { cause: error4 });
23483
23533
  }
23534
+ async runDirectWebLogin(task) {
23535
+ task.output = "Launching npm login...";
23536
+ const isValidUrl = (url) => {
23537
+ try {
23538
+ return /^https?:$/.test(new URL(url).protocol);
23539
+ } catch {
23540
+ return false;
23541
+ }
23542
+ };
23543
+ const loginEndpoint = `${NPM_OFFICIAL_REGISTRY}/-/v1/login`;
23544
+ const res = await fetch(loginEndpoint, {
23545
+ method: "POST",
23546
+ headers: { "content-type": "application/json" },
23547
+ body: JSON.stringify({})
23548
+ });
23549
+ if (!res.ok) {
23550
+ throw new NpmError(`npm web login initiation failed (HTTP ${res.status})`);
23551
+ }
23552
+ const body = await res.json();
23553
+ const { loginUrl, doneUrl } = body;
23554
+ if (!loginUrl || !doneUrl || !isValidUrl(loginUrl) || !isValidUrl(doneUrl)) {
23555
+ throw new NpmError("npm web login response missing valid loginUrl or doneUrl");
23556
+ }
23557
+ task.output = `Login at: ${color.cyan(loginUrl)}`;
23558
+ const { openUrl: openUrl2 } = await Promise.resolve().then(() => (init_open_url(), exports_open_url));
23559
+ openUrl2(loginUrl).catch(() => {});
23560
+ while (true) {
23561
+ const pollRes = await fetch(doneUrl);
23562
+ if (pollRes.status === 200) {
23563
+ const pollBody = await pollRes.json();
23564
+ if (!pollBody.token) {
23565
+ throw new NpmError("npm web login completed but no token received");
23566
+ }
23567
+ try {
23568
+ await exec3("npm", [
23569
+ "config",
23570
+ "set",
23571
+ "//registry.npmjs.org/:_authToken",
23572
+ pollBody.token,
23573
+ "--location=user"
23574
+ ], { throwOnError: true });
23575
+ } catch (error4) {
23576
+ throw new NpmError("Failed to save npm auth token", { cause: error4 });
23577
+ }
23578
+ return;
23579
+ }
23580
+ if (pollRes.status === 202) {
23581
+ const retryAfter = Number(pollRes.headers.get("retry-after")) * 1000;
23582
+ const delay2 = retryAfter > 0 ? retryAfter : 1000;
23583
+ await new Promise((resolve) => setTimeout(resolve, delay2));
23584
+ continue;
23585
+ }
23586
+ throw new NpmError(`npm web login polling failed (HTTP ${pollRes.status})`);
23587
+ }
23588
+ }
23589
+ async runInteractiveLogin(task) {
23590
+ if (this.isOfficialNpmRegistry()) {
23591
+ return this.runDirectWebLogin(task);
23592
+ }
23593
+ task.output = "Launching npm login...";
23594
+ const [{ spawnInteractive: spawnInteractive2 }, { openUrl: openUrl2 }] = await Promise.all([
23595
+ Promise.resolve().then(() => exports_spawn_interactive),
23596
+ Promise.resolve().then(() => (init_open_url(), exports_open_url))
23597
+ ]);
23598
+ const child = spawnInteractive2(["npm", "login"]);
23599
+ let openedUrl = null;
23600
+ let bufferedText = "";
23601
+ const onData = (text) => {
23602
+ bufferedText = `${bufferedText}${text}`.slice(-4096);
23603
+ const canonicalUrl = extractNpmLoginUrl(bufferedText);
23604
+ if (!canonicalUrl || openedUrl) {
23605
+ return;
23606
+ }
23607
+ openedUrl = canonicalUrl;
23608
+ task.output = `Login at: ${color.cyan(canonicalUrl)}`;
23609
+ openUrl2(canonicalUrl);
23610
+ };
23611
+ await Promise.all([
23612
+ this.readInteractiveStream(child.stdout, onData),
23613
+ this.readInteractiveStream(child.stderr, onData),
23614
+ child.exited.then((code) => {
23615
+ if (code !== 0) {
23616
+ throw new Error(`npm login exited with code ${code}`);
23617
+ }
23618
+ })
23619
+ ]);
23620
+ if (!openedUrl) {
23621
+ throw new Error("npm login did not provide a supported web login URL.");
23622
+ }
23623
+ }
23624
+ async readInteractiveStream(stream, onData) {
23625
+ const reader = stream.getReader();
23626
+ const decoder = new TextDecoder;
23627
+ try {
23628
+ while (true) {
23629
+ const { done, value } = await reader.read();
23630
+ if (done)
23631
+ break;
23632
+ onData(decoder.decode(value));
23633
+ }
23634
+ } finally {
23635
+ reader.releaseLock();
23636
+ }
23637
+ }
23484
23638
  };
23485
23639
  });
23486
23640
 
@@ -33518,7 +33672,7 @@ var require_dist = __commonJS((exports) => {
33518
33672
  init_runner();
33519
33673
 
33520
33674
  // src/tasks/runner.ts
33521
- import process21 from "node:process";
33675
+ import process22 from "node:process";
33522
33676
 
33523
33677
  // ../../node_modules/.bun/std-env@4.0.0/node_modules/std-env/dist/index.mjs
33524
33678
  var e2 = globalThis.process?.env || Object.create(null);
@@ -35861,29 +36015,11 @@ function createPublishTasks(hasPublish, dryRun, skipPublish) {
35861
36015
 
35862
36016
  // src/tasks/phases/push-release.ts
35863
36017
  init_dist2();
35864
- var import_semver4 = __toESM(require_semver2(), 1);
35865
- import { existsSync as existsSync6, readFileSync as readFileSync9, rmSync } from "node:fs";
35866
- import { join as join9 } from "node:path";
35867
- import process19 from "node:process";
35868
-
35869
- // src/changeset/changelog-parser.ts
35870
- function parseChangelogSection(changelog, version) {
35871
- const normalizedVersion = version.replace(/^v/, "");
35872
- const escapedVersion = normalizedVersion.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
35873
- const headerPattern = new RegExp(`^## v?${escapedVersion}\\b[^\\n]*\\n`, "m");
35874
- const headerMatch = headerPattern.exec(changelog);
35875
- if (!headerMatch)
35876
- return null;
35877
- const start = headerMatch.index + headerMatch[0].length;
35878
- const nextHeader = changelog.indexOf(`
35879
- ## `, start);
35880
- const end = nextHeader === -1 ? changelog.length : nextHeader;
35881
- return changelog.slice(start, end).trim();
35882
- }
35883
-
35884
- // src/tasks/phases/push-release.ts
35885
36018
  init_git();
35886
36019
  init_i18n();
36020
+ var import_semver4 = __toESM(require_semver2(), 1);
36021
+ import { rmSync } from "node:fs";
36022
+ import process20 from "node:process";
35887
36023
 
35888
36024
  // src/utils/github-token.ts
35889
36025
  init_secure_store();
@@ -35920,13 +36056,6 @@ var { prerelease } = import_semver3.default;
35920
36056
  class GitHubReleaseError extends AbstractError {
35921
36057
  name = t("error.githubRelease.name");
35922
36058
  }
35923
- function formatReleaseNotes(commits, repositoryUrl, previousTag, latestTag) {
35924
- const lines = commits.map(({ id, message }) => `- ${message.replace(/#(\d+)/g, `[#$1](${repositoryUrl}/issues/$1)`)} ([${id.slice(0, 7)}](${repositoryUrl}/commit/${id}))`);
35925
- lines.push("");
35926
- lines.push(`**Full Changelog**: ${repositoryUrl}/compare/${previousTag}...${latestTag}`);
35927
- return lines.join(`
35928
- `);
35929
- }
35930
36059
  async function createGitHubRelease(_ctx, options) {
35931
36060
  const token = process.env.GITHUB_TOKEN;
35932
36061
  if (!token) {
@@ -35934,16 +36063,7 @@ async function createGitHubRelease(_ctx, options) {
35934
36063
  }
35935
36064
  const git = new Git;
35936
36065
  const remoteUrl = await git.repository();
35937
- const repositoryUrl = remoteUrl.replace(/^git@github\.com:/, "https://github.com/").replace(/\.git$/, "");
35938
36066
  const { owner, repo } = parseOwnerRepo(remoteUrl);
35939
- const previousTag = await git.previousTag(options.tag) || await git.firstCommit();
35940
- let body;
35941
- if (options.changelogBody) {
35942
- body = options.changelogBody;
35943
- } else {
35944
- const commits = (await git.commits(previousTag, options.tag)).slice(1);
35945
- body = formatReleaseNotes(commits, repositoryUrl, previousTag, options.tag);
35946
- }
35947
36067
  const createResponse = await fetch(`https://api.github.com/repos/${owner}/${repo}/releases`, {
35948
36068
  method: "POST",
35949
36069
  headers: {
@@ -35954,7 +36074,7 @@ async function createGitHubRelease(_ctx, options) {
35954
36074
  body: JSON.stringify({
35955
36075
  tag_name: options.tag,
35956
36076
  name: options.tag,
35957
- body,
36077
+ body: options.body,
35958
36078
  draft: !!options.draft,
35959
36079
  prerelease: !!prerelease(options.version)
35960
36080
  })
@@ -36036,67 +36156,448 @@ async function deleteGitHubRelease(releaseId) {
36036
36156
  }
36037
36157
  }
36038
36158
 
36039
- // src/tasks/runner-utils/version-pr.ts
36159
+ // src/tasks/release-notes.ts
36040
36160
  import { existsSync as existsSync5, readFileSync as readFileSync8 } from "node:fs";
36041
- import path13 from "node:path";
36042
- import process18 from "node:process";
36043
- init_error4();
36044
- init_git();
36045
- init_i18n();
36161
+ import { join as join9 } from "node:path";
36046
36162
 
36047
- // src/tasks/create-version-pr.ts
36048
- init_error4();
36049
- init_i18n();
36050
- init_exec();
36163
+ // src/conventional-commit/types.ts
36164
+ var DEFAULT_TYPE_BUMP_MAP = {
36165
+ feat: "minor",
36166
+ fix: "patch",
36167
+ perf: "patch",
36168
+ chore: false,
36169
+ docs: false,
36170
+ test: false,
36171
+ ci: false,
36172
+ style: false,
36173
+ refactor: false
36174
+ };
36175
+ var COMMIT_TYPE_CATEGORY_MAP = {
36176
+ feat: "Features",
36177
+ fix: "Bug Fixes",
36178
+ perf: "Performance",
36179
+ refactor: "Refactoring",
36180
+ docs: "Documentation"
36181
+ };
36182
+ var DEFAULT_CATEGORY = "Other Changes";
36051
36183
 
36052
- class VersionPrError extends AbstractError {
36053
- name = "Version PR Error";
36054
- }
36055
- async function createVersionPr(options) {
36056
- try {
36057
- return await createPrViaGhCli(options);
36058
- } catch {
36059
- return await createPrViaApi(options);
36184
+ // src/changelog/conventional-commit-writer.ts
36185
+ var CATEGORY_ORDER = [
36186
+ "Features",
36187
+ "Bug Fixes",
36188
+ "Performance",
36189
+ "Refactoring",
36190
+ "Documentation",
36191
+ "Other Changes"
36192
+ ];
36193
+
36194
+ class ConventionalCommitChangelogWriter {
36195
+ formatEntries(entries) {
36196
+ if (entries.length === 0)
36197
+ return [];
36198
+ const groups = new Map;
36199
+ for (const entry of entries) {
36200
+ const category = entry.type && COMMIT_TYPE_CATEGORY_MAP[entry.type] || DEFAULT_CATEGORY;
36201
+ const hashSuffix = entry.hash ? ` (${entry.hash})` : "";
36202
+ const item = `- ${entry.summary}${hashSuffix}`;
36203
+ const existing = groups.get(category);
36204
+ if (existing) {
36205
+ existing.push(item);
36206
+ } else {
36207
+ groups.set(category, [item]);
36208
+ }
36209
+ }
36210
+ const sections = [];
36211
+ for (const category of CATEGORY_ORDER) {
36212
+ const items = groups.get(category);
36213
+ if (items)
36214
+ sections.push({ category, items });
36215
+ }
36216
+ return sections;
36060
36217
  }
36061
36218
  }
36062
- async function closeVersionPr(options) {
36063
- try {
36064
- await closePrViaGhCli(options);
36065
- } catch {
36066
- await closePrViaApi(options);
36067
- }
36219
+
36220
+ // src/changeset/changelog-parser.ts
36221
+ function parseChangelogSection(changelog, version) {
36222
+ const normalizedVersion = version.replace(/^v/, "");
36223
+ const escapedVersion = normalizedVersion.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
36224
+ const headerPattern = new RegExp(`^## v?${escapedVersion}\\b[^\\n]*\\n`, "m");
36225
+ const headerMatch = headerPattern.exec(changelog);
36226
+ if (!headerMatch)
36227
+ return null;
36228
+ const start = headerMatch.index + headerMatch[0].length;
36229
+ const nextHeader = changelog.indexOf(`
36230
+ ## `, start);
36231
+ const end = nextHeader === -1 ? changelog.length : nextHeader;
36232
+ return changelog.slice(start, end).trim();
36068
36233
  }
36069
- async function createPrViaGhCli(options) {
36070
- const args = [
36071
- "pr",
36072
- "create",
36073
- "--title",
36074
- options.title,
36075
- "--body",
36076
- options.body,
36077
- "--base",
36078
- options.base,
36079
- "--head",
36080
- options.branch
36081
- ];
36082
- if (options.labels && options.labels.length > 0) {
36083
- args.push("--label", options.labels.join(","));
36234
+
36235
+ // src/conventional-commit/git-log.ts
36236
+ import { execFileSync } from "node:child_process";
36237
+ var COMMIT_START_MARKER = "COMMIT_START";
36238
+ var COMMIT_FILES_MARKER = "COMMIT_FILES";
36239
+ function findLastReleaseRef(cwd, packageName) {
36240
+ if (packageName) {
36241
+ const scopedTags = execGit(cwd, [
36242
+ "tag",
36243
+ "--list",
36244
+ `${packageName}@[0-9]*.[0-9]*.[0-9]*`,
36245
+ "--sort=-v:refname"
36246
+ ]);
36247
+ if (scopedTags.length > 0)
36248
+ return scopedTags[0];
36084
36249
  }
36085
- const { stdout } = await exec3("gh", args, { throwOnError: true });
36086
- const url = stdout.trim();
36087
- const numberMatch = url.match(/\/pull\/(\d+)/);
36088
- const number2 = numberMatch ? Number.parseInt(numberMatch[1], 10) : 0;
36089
- return { url, number: number2 };
36250
+ const vTags = execGit(cwd, [
36251
+ "tag",
36252
+ "--list",
36253
+ "v[0-9]*.[0-9]*.[0-9]*",
36254
+ "--sort=-v:refname"
36255
+ ]);
36256
+ if (vTags.length > 0)
36257
+ return vTags[0];
36258
+ const versionCommit = execGit(cwd, [
36259
+ "log",
36260
+ "--format=%H",
36261
+ "--grep=^Version Packages$",
36262
+ "-1"
36263
+ ]);
36264
+ if (versionCommit.length > 0)
36265
+ return versionCommit[0];
36266
+ return;
36090
36267
  }
36091
- async function createPrViaApi(options) {
36092
- const response = await fetch(`https://api.github.com/repos/${options.owner}/${options.repo}/pulls`, {
36093
- method: "POST",
36094
- headers: {
36095
- Authorization: `Bearer ${options.token}`,
36096
- Accept: "application/vnd.github+json",
36097
- "X-GitHub-Api-Version": "2022-11-28"
36098
- },
36099
- body: JSON.stringify({
36268
+ function getCommitsSinceRef(cwd, ref, toRef) {
36269
+ const range = ref ? `${ref}..${toRef ?? "HEAD"}` : toRef ?? "HEAD";
36270
+ const format3 = `${COMMIT_START_MARKER} %h%n%B%n${COMMIT_FILES_MARKER}`;
36271
+ const output = execGitRaw(cwd, [
36272
+ "log",
36273
+ `--format=${format3}`,
36274
+ "--name-only",
36275
+ range
36276
+ ]);
36277
+ if (!output.trim())
36278
+ return [];
36279
+ const commits = [];
36280
+ const lines = output.split(`
36281
+ `);
36282
+ let i2 = 0;
36283
+ while (i2 < lines.length) {
36284
+ if (!lines[i2].startsWith(COMMIT_START_MARKER)) {
36285
+ i2++;
36286
+ continue;
36287
+ }
36288
+ const hash = lines[i2].slice(COMMIT_START_MARKER.length + 1).trim();
36289
+ i2++;
36290
+ const messageLines = [];
36291
+ while (i2 < lines.length && !lines[i2].startsWith(COMMIT_FILES_MARKER)) {
36292
+ if (lines[i2].startsWith(COMMIT_START_MARKER))
36293
+ break;
36294
+ messageLines.push(lines[i2]);
36295
+ i2++;
36296
+ }
36297
+ if (i2 < lines.length && lines[i2].startsWith(COMMIT_FILES_MARKER)) {
36298
+ i2++;
36299
+ }
36300
+ const files = [];
36301
+ while (i2 < lines.length && !lines[i2].startsWith(COMMIT_START_MARKER)) {
36302
+ const file = lines[i2].trim();
36303
+ if (file)
36304
+ files.push(file);
36305
+ i2++;
36306
+ }
36307
+ const message = messageLines.join(`
36308
+ `).trim();
36309
+ if (hash && message) {
36310
+ commits.push({ hash, message, files });
36311
+ }
36312
+ }
36313
+ return commits;
36314
+ }
36315
+ function execGit(cwd, args) {
36316
+ return execGitRaw(cwd, args).split(`
36317
+ `).map((l3) => l3.trim()).filter(Boolean);
36318
+ }
36319
+ function execGitRaw(cwd, args) {
36320
+ try {
36321
+ return execFileSync("git", args, { cwd, encoding: "utf-8" });
36322
+ } catch {
36323
+ return "";
36324
+ }
36325
+ }
36326
+
36327
+ // src/conventional-commit/parser.ts
36328
+ var HEADER_REGEX = /^(\w+)(?:\(([^)]+)\))?(!)?\s*:\s*(.+)$/;
36329
+ var FOOTER_REGEX = /^([\w-]+|BREAKING CHANGE)\s*:\s*(.+)$/;
36330
+ function parseConventionalCommit(hash, message, files = []) {
36331
+ const lines = message.split(`
36332
+ `);
36333
+ const firstLine = lines[0];
36334
+ const headerMatch = firstLine.match(HEADER_REGEX);
36335
+ if (!headerMatch)
36336
+ return null;
36337
+ const [, type, scope, bang, description] = headerMatch;
36338
+ let body;
36339
+ const footers = new Map;
36340
+ let breaking = bang === "!";
36341
+ if (lines.length > 1) {
36342
+ const rest = lines.slice(1);
36343
+ let footerStartIndex = rest.length;
36344
+ for (let i2 = rest.length - 1;i2 >= 0; i2--) {
36345
+ if (rest[i2] === "") {
36346
+ footerStartIndex = i2 + 1;
36347
+ break;
36348
+ }
36349
+ }
36350
+ const bodyStartIndex = rest.findIndex((line) => line !== "");
36351
+ if (bodyStartIndex !== -1 && bodyStartIndex < footerStartIndex) {
36352
+ const bodyLines = rest.slice(bodyStartIndex, footerStartIndex - 1);
36353
+ const bodyText = bodyLines.join(`
36354
+ `).trim();
36355
+ if (bodyText)
36356
+ body = bodyText;
36357
+ }
36358
+ let currentFooterKey;
36359
+ for (let i2 = footerStartIndex;i2 < rest.length; i2++) {
36360
+ const footerMatch = rest[i2].match(FOOTER_REGEX);
36361
+ if (footerMatch) {
36362
+ const [, key, value] = footerMatch;
36363
+ footers.set(key, value);
36364
+ currentFooterKey = key;
36365
+ if (key === "BREAKING CHANGE" || key === "BREAKING-CHANGE") {
36366
+ breaking = true;
36367
+ }
36368
+ } else if (currentFooterKey && rest[i2].startsWith(" ")) {
36369
+ const existing = footers.get(currentFooterKey) ?? "";
36370
+ footers.set(currentFooterKey, `${existing}
36371
+ ${rest[i2].trimStart()}`);
36372
+ }
36373
+ }
36374
+ }
36375
+ return { hash, type, scope, breaking, description, body, footers, files };
36376
+ }
36377
+
36378
+ // src/conventional-commit/scope-resolver.ts
36379
+ import path13 from "node:path";
36380
+ function resolveCommitPackages(commit, packagePaths) {
36381
+ const matched = new Set;
36382
+ if (commit.scope) {
36383
+ for (const pkgPath of packagePaths) {
36384
+ const dirName = path13.basename(pkgPath);
36385
+ if (dirName === commit.scope) {
36386
+ matched.add(pkgPath);
36387
+ }
36388
+ }
36389
+ if (matched.size > 0)
36390
+ return [...matched];
36391
+ }
36392
+ for (const file of commit.files) {
36393
+ const normalized = file.replace(/\\/g, "/");
36394
+ for (const pkgPath of packagePaths) {
36395
+ if (pkgPath === ".") {
36396
+ matched.add(pkgPath);
36397
+ continue;
36398
+ }
36399
+ const normalizedPkg = pkgPath.replace(/\\/g, "/");
36400
+ if (normalized.startsWith(`${normalizedPkg}/`) || normalized === normalizedPkg) {
36401
+ matched.add(pkgPath);
36402
+ }
36403
+ }
36404
+ }
36405
+ return [...matched];
36406
+ }
36407
+
36408
+ // src/tasks/release-notes.ts
36409
+ init_git();
36410
+
36411
+ // src/utils/clipboard.ts
36412
+ import process18 from "node:process";
36413
+ async function copyToClipboard(text) {
36414
+ const commands = getClipboardCommands();
36415
+ for (const cmd of commands) {
36416
+ try {
36417
+ const proc = Bun.spawn(cmd, {
36418
+ stdin: "pipe",
36419
+ stdout: "ignore",
36420
+ stderr: "ignore"
36421
+ });
36422
+ proc.stdin.write(text);
36423
+ proc.stdin.end();
36424
+ const exitCode = await proc.exited;
36425
+ if (exitCode === 0)
36426
+ return true;
36427
+ } catch {}
36428
+ }
36429
+ return false;
36430
+ }
36431
+ function getClipboardCommands() {
36432
+ switch (process18.platform) {
36433
+ case "darwin":
36434
+ return [["pbcopy"]];
36435
+ case "win32":
36436
+ return [["clip"]];
36437
+ default:
36438
+ return [["xclip", "-selection", "clipboard"], ["wl-copy"]];
36439
+ }
36440
+ }
36441
+
36442
+ // src/tasks/release-notes.ts
36443
+ function renderReleaseNoteSections(sections) {
36444
+ if (sections.length === 0)
36445
+ return "";
36446
+ const parts = [];
36447
+ for (const section of sections) {
36448
+ if (section.category) {
36449
+ parts.push(`### ${section.category}
36450
+
36451
+ ${section.items.join(`
36452
+ `)}`);
36453
+ } else {
36454
+ parts.push(section.items.join(`
36455
+ `));
36456
+ }
36457
+ }
36458
+ return parts.join(`
36459
+
36460
+ `);
36461
+ }
36462
+ async function buildReleaseBody(ctx, options) {
36463
+ const { pkgPath, version, tag, repositoryUrl } = options;
36464
+ const appendCompareLink = options.appendCompareLink ?? true;
36465
+ const git = new Git;
36466
+ const previousTag = options.previousTag ?? (await git.previousTag(tag) || await git.firstCommit());
36467
+ const compareLink = `**Full Changelog**: ${repositoryUrl}/compare/${previousTag}...${tag}`;
36468
+ const changelogBody = extractChangelog(ctx, pkgPath, version);
36469
+ if (changelogBody) {
36470
+ return appendCompareLink ? `${changelogBody}
36471
+
36472
+ ${compareLink}` : changelogBody;
36473
+ }
36474
+ const commits = await git.commits(previousTag, tag);
36475
+ if (commits.length === 0) {
36476
+ return appendCompareLink ? compareLink : "";
36477
+ }
36478
+ const rawCommits = getCommitsSinceRef(ctx.cwd, previousTag, tag);
36479
+ const parsed = rawCommits.map((c2) => parseConventionalCommit(c2.hash, c2.message, c2.files)).filter((c2) => c2 !== null);
36480
+ const filtered = pkgPath ? parsed.filter((c2) => {
36481
+ const packages = resolveCommitPackages(c2, [pkgPath]);
36482
+ return packages.length > 0;
36483
+ }) : parsed;
36484
+ if (filtered.length > 0) {
36485
+ const entries = filtered.map((c2) => ({
36486
+ summary: c2.description,
36487
+ type: c2.type,
36488
+ hash: c2.hash.slice(0, 7)
36489
+ }));
36490
+ const writer = new ConventionalCommitChangelogWriter;
36491
+ const sections = writer.formatEntries(entries);
36492
+ const body2 = renderReleaseNoteSections(sections);
36493
+ return appendCompareLink ? `${body2}
36494
+
36495
+ ${compareLink}` : body2;
36496
+ }
36497
+ const lines = commits.map(({ id, message }) => `- ${message} (${id.slice(0, 7)})`);
36498
+ const body = lines.join(`
36499
+ `);
36500
+ return appendCompareLink ? `${body}
36501
+
36502
+ ${compareLink}` : body;
36503
+ }
36504
+ function extractChangelog(ctx, pkgPath, version) {
36505
+ const changelogPath = pkgPath ? join9(ctx.cwd, pkgPath, "CHANGELOG.md") : join9(ctx.cwd, "CHANGELOG.md");
36506
+ if (!existsSync5(changelogPath))
36507
+ return null;
36508
+ return parseChangelogSection(readFileSync8(changelogPath, "utf-8"), version);
36509
+ }
36510
+ var MAX_URL_LENGTH = 8000;
36511
+ async function truncateForUrl(body, baseUrl) {
36512
+ const testUrl = `${baseUrl}${encodeURIComponent(body)}`;
36513
+ if (testUrl.length <= MAX_URL_LENGTH) {
36514
+ return { body, truncated: false, clipboardCopied: false };
36515
+ }
36516
+ const clipboardCopied = await copyToClipboard(body);
36517
+ const suffix = clipboardCopied ? `
36518
+
36519
+ ... (truncated, full notes copied to clipboard)` : `
36520
+
36521
+ ... (truncated)`;
36522
+ const availableLength = MAX_URL_LENGTH - baseUrl.length - encodeURIComponent(suffix).length;
36523
+ let lo = 0;
36524
+ let hi = body.length;
36525
+ while (lo < hi) {
36526
+ const mid = Math.ceil((lo + hi) / 2);
36527
+ if (encodeURIComponent(body.slice(0, mid)).length <= availableLength) {
36528
+ lo = mid;
36529
+ } else {
36530
+ hi = mid - 1;
36531
+ }
36532
+ }
36533
+ return {
36534
+ body: body.slice(0, lo) + suffix,
36535
+ truncated: true,
36536
+ clipboardCopied
36537
+ };
36538
+ }
36539
+
36540
+ // src/tasks/runner-utils/version-pr.ts
36541
+ import { existsSync as existsSync6, readFileSync as readFileSync9 } from "node:fs";
36542
+ import path14 from "node:path";
36543
+ import process19 from "node:process";
36544
+ init_error4();
36545
+ init_git();
36546
+ init_i18n();
36547
+
36548
+ // src/tasks/create-version-pr.ts
36549
+ init_error4();
36550
+ init_i18n();
36551
+ init_exec();
36552
+
36553
+ class VersionPrError extends AbstractError {
36554
+ name = "Version PR Error";
36555
+ }
36556
+ async function createVersionPr(options) {
36557
+ try {
36558
+ return await createPrViaGhCli(options);
36559
+ } catch {
36560
+ return await createPrViaApi(options);
36561
+ }
36562
+ }
36563
+ async function closeVersionPr(options) {
36564
+ try {
36565
+ await closePrViaGhCli(options);
36566
+ } catch {
36567
+ await closePrViaApi(options);
36568
+ }
36569
+ }
36570
+ async function createPrViaGhCli(options) {
36571
+ const args = [
36572
+ "pr",
36573
+ "create",
36574
+ "--title",
36575
+ options.title,
36576
+ "--body",
36577
+ options.body,
36578
+ "--base",
36579
+ options.base,
36580
+ "--head",
36581
+ options.branch
36582
+ ];
36583
+ if (options.labels && options.labels.length > 0) {
36584
+ args.push("--label", options.labels.join(","));
36585
+ }
36586
+ const { stdout } = await exec3("gh", args, { throwOnError: true });
36587
+ const url = stdout.trim();
36588
+ const numberMatch = url.match(/\/pull\/(\d+)/);
36589
+ const number2 = numberMatch ? Number.parseInt(numberMatch[1], 10) : 0;
36590
+ return { url, number: number2 };
36591
+ }
36592
+ async function createPrViaApi(options) {
36593
+ const response = await fetch(`https://api.github.com/repos/${options.owner}/${options.repo}/pulls`, {
36594
+ method: "POST",
36595
+ headers: {
36596
+ Authorization: `Bearer ${options.token}`,
36597
+ Accept: "application/vnd.github+json",
36598
+ "X-GitHub-Api-Version": "2022-11-28"
36599
+ },
36600
+ body: JSON.stringify({
36100
36601
  title: options.title,
36101
36602
  body: options.body,
36102
36603
  head: options.branch,
@@ -36191,7 +36692,7 @@ async function pushViaPr(ctx, git, task) {
36191
36692
  const prBody = buildPrBodyFromContext(ctx, plan);
36192
36693
  const remoteUrl = await git.repository();
36193
36694
  const { owner, repo } = parseOwnerRepo(remoteUrl);
36194
- const token = process18.env.GITHUB_TOKEN;
36695
+ const token = process19.env.GITHUB_TOKEN;
36195
36696
  if (!token) {
36196
36697
  throw new AbstractError(t("error.githubRelease.tokenRequired"));
36197
36698
  }
@@ -36223,10 +36724,10 @@ function buildPrBodyFromContext(ctx, plan) {
36223
36724
  const pkgConfig = ctx.config.packages.find((p2) => p2.path === pkgPath);
36224
36725
  const name = pkgConfig?.name ?? pkgPath;
36225
36726
  packages.push({ name, version: pkgVersion, bump: "" });
36226
- const changelogDir = pkgConfig ? path13.resolve(ctx.cwd, pkgConfig.path) : ctx.cwd;
36227
- const changelogPath = path13.join(changelogDir, "CHANGELOG.md");
36228
- if (existsSync5(changelogPath)) {
36229
- const section = parseChangelogSection(readFileSync8(changelogPath, "utf-8"), pkgVersion);
36727
+ const changelogDir = pkgConfig ? path14.resolve(ctx.cwd, pkgConfig.path) : ctx.cwd;
36728
+ const changelogPath = path14.join(changelogDir, "CHANGELOG.md");
36729
+ if (existsSync6(changelogPath)) {
36730
+ const section = parseChangelogSection(readFileSync9(changelogPath, "utf-8"), pkgVersion);
36230
36731
  if (section)
36231
36732
  changelogs.set(name, section);
36232
36733
  }
@@ -36237,17 +36738,17 @@ function buildPrBodyFromContext(ctx, plan) {
36237
36738
  packages.push({ name: pkg.name, version, bump: "" });
36238
36739
  }
36239
36740
  if (plan.mode === "single") {
36240
- const changelogPath = path13.join(ctx.cwd, "CHANGELOG.md");
36241
- if (existsSync5(changelogPath)) {
36242
- const section = parseChangelogSection(readFileSync8(changelogPath, "utf-8"), version);
36741
+ const changelogPath = path14.join(ctx.cwd, "CHANGELOG.md");
36742
+ if (existsSync6(changelogPath)) {
36743
+ const section = parseChangelogSection(readFileSync9(changelogPath, "utf-8"), version);
36243
36744
  if (section)
36244
36745
  changelogs.set(packages[0]?.name ?? "", section);
36245
36746
  }
36246
36747
  } else {
36247
36748
  for (const pkg of ctx.config.packages) {
36248
- const changelogPath = path13.join(ctx.cwd, pkg.path, "CHANGELOG.md");
36249
- if (existsSync5(changelogPath)) {
36250
- const section = parseChangelogSection(readFileSync8(changelogPath, "utf-8"), version);
36749
+ const changelogPath = path14.join(ctx.cwd, pkg.path, "CHANGELOG.md");
36750
+ if (existsSync6(changelogPath)) {
36751
+ const section = parseChangelogSection(readFileSync9(changelogPath, "utf-8"), version);
36251
36752
  if (section)
36252
36753
  changelogs.set(pkg.name, section);
36253
36754
  }
@@ -36305,7 +36806,7 @@ function createReleaseTask(hasPublish, dryRun, mode, skipReleaseDraft) {
36305
36806
  const tokenResult = resolveGitHubToken();
36306
36807
  let hasToken = !!tokenResult;
36307
36808
  if (tokenResult) {
36308
- process19.env.GITHUB_TOKEN = tokenResult.token;
36809
+ process20.env.GITHUB_TOKEN = tokenResult.token;
36309
36810
  } else if (mode !== "ci") {
36310
36811
  const answer = await task.prompt(ListrEnquirerPromptAdapter).run({
36311
36812
  type: "select",
@@ -36325,7 +36826,7 @@ function createReleaseTask(hasPublish, dryRun, mode, skipReleaseDraft) {
36325
36826
  message: t("task.release.tokenPrompt")
36326
36827
  });
36327
36828
  if (token) {
36328
- process19.env.GITHUB_TOKEN = token;
36829
+ process20.env.GITHUB_TOKEN = token;
36329
36830
  saveGitHubToken(token);
36330
36831
  hasToken = true;
36331
36832
  }
@@ -36345,22 +36846,20 @@ function createReleaseTask(hasPublish, dryRun, mode, skipReleaseDraft) {
36345
36846
  const pkgName = getPackageName(ctx, pkgPath);
36346
36847
  const tag = `${pkgName}@${pkgVersion}`;
36347
36848
  task.output = t("task.release.creating", { tag });
36348
- let changelogBody;
36349
- const pkgConfig = ctx.config.packages.find((p2) => p2.path === pkgPath);
36350
- if (pkgConfig) {
36351
- const changelogPath = join9(ctx.cwd, pkgConfig.path, "CHANGELOG.md");
36352
- if (existsSync6(changelogPath)) {
36353
- const section = parseChangelogSection(readFileSync9(changelogPath, "utf-8"), pkgVersion);
36354
- if (section)
36355
- changelogBody = section;
36356
- }
36357
- }
36849
+ const git = new Git;
36850
+ const repositoryUrl = (await git.repository()).replace(/^git@github\.com:/, "https://github.com/").replace(/\.git$/, "");
36851
+ const body = await buildReleaseBody(ctx, {
36852
+ pkgPath,
36853
+ version: pkgVersion,
36854
+ tag,
36855
+ repositoryUrl
36856
+ });
36358
36857
  const { assets: preparedAssets, tempDir } = await prepareReleaseAssets(ctx, pkgName, pkgVersion, pkgPath);
36359
36858
  const result = await createGitHubRelease(ctx, {
36360
36859
  displayLabel: pkgName,
36361
36860
  version: pkgVersion,
36362
36861
  tag,
36363
- changelogBody,
36862
+ body,
36364
36863
  assets: preparedAssets,
36365
36864
  draft: !!ctx.options.releaseDraft
36366
36865
  });
@@ -36398,39 +36897,14 @@ function createReleaseTask(hasPublish, dryRun, mode, skipReleaseDraft) {
36398
36897
  const version = plan.version;
36399
36898
  const tag = `v${version}`;
36400
36899
  task.output = t("task.release.creating", { tag });
36401
- let changelogBody;
36402
- if (plan.mode === "fixed") {
36403
- const sections = [];
36404
- for (const [pkgPath2, pkgVersion] of plan.packages) {
36405
- const pkgName = getPackageName(ctx, pkgPath2);
36406
- const pkgConfig = ctx.config.packages.find((p2) => p2.path === pkgPath2);
36407
- if (!pkgConfig)
36408
- continue;
36409
- const changelogPath = join9(ctx.cwd, pkgConfig.path, "CHANGELOG.md");
36410
- if (existsSync6(changelogPath)) {
36411
- const section = parseChangelogSection(readFileSync9(changelogPath, "utf-8"), pkgVersion);
36412
- if (section) {
36413
- sections.push(`## ${pkgName} v${pkgVersion}
36414
-
36415
- ${section}`);
36416
- }
36417
- }
36418
- }
36419
- if (sections.length > 0) {
36420
- changelogBody = sections.join(`
36421
-
36422
- ---
36423
-
36424
- `);
36425
- }
36426
- } else {
36427
- const changelogPath = join9(ctx.cwd, "CHANGELOG.md");
36428
- if (existsSync6(changelogPath)) {
36429
- const section = parseChangelogSection(readFileSync9(changelogPath, "utf-8"), version);
36430
- if (section)
36431
- changelogBody = section;
36432
- }
36433
- }
36900
+ const git = new Git;
36901
+ const repositoryUrl = (await git.repository()).replace(/^git@github\.com:/, "https://github.com/").replace(/\.git$/, "");
36902
+ const body = await buildReleaseBody(ctx, {
36903
+ pkgPath: plan.mode === "single" ? plan.packagePath : undefined,
36904
+ version,
36905
+ tag,
36906
+ repositoryUrl
36907
+ });
36434
36908
  const packageName = plan.mode === "single" ? getPackageName(ctx, plan.packagePath) : ctx.config.packages[0]?.name ?? "";
36435
36909
  const pkgPath = plan.mode === "single" ? plan.packagePath : ctx.config.packages[0]?.path;
36436
36910
  const { assets: preparedAssets, tempDir } = await prepareReleaseAssets(ctx, packageName, version, pkgPath);
@@ -36438,7 +36912,7 @@ ${section}`);
36438
36912
  displayLabel: packageName,
36439
36913
  version,
36440
36914
  tag,
36441
- changelogBody,
36915
+ body,
36442
36916
  assets: preparedAssets,
36443
36917
  draft: !!ctx.options.releaseDraft
36444
36918
  });
@@ -36484,21 +36958,31 @@ ${section}`);
36484
36958
  continue;
36485
36959
  const pkgName = getPackageName(ctx, pkgPath);
36486
36960
  const tag = `${pkgName}@${pkgVersion}`;
36487
- const lastRev = await git.previousTag(tag) || await git.firstCommit();
36488
- const commits = (await git.commits(lastRev, tag)).slice(1);
36489
- let body = commits.map(({ id, message }) => `- ${message.replace(/#/g, `${repositoryUrl}/issues/`)} ${repositoryUrl}/commit/${id}`).join(`
36490
- `);
36491
- body += `
36492
-
36493
- ${repositoryUrl}/compare/${lastRev}...${tag}`;
36961
+ const body = await buildReleaseBody(ctx, {
36962
+ pkgPath,
36963
+ version: pkgVersion,
36964
+ tag,
36965
+ repositoryUrl
36966
+ });
36494
36967
  const releaseDraftUrl = new URL(`${repositoryUrl}/releases/new`);
36495
36968
  releaseDraftUrl.searchParams.set("tag", tag);
36496
- releaseDraftUrl.searchParams.set("body", body);
36497
36969
  releaseDraftUrl.searchParams.set("prerelease", `${!!prerelease2(pkgVersion)}`);
36970
+ const baseUrl = `${releaseDraftUrl.toString()}&body=`;
36971
+ const truncated = await truncateForUrl(body, baseUrl);
36972
+ releaseDraftUrl.searchParams.set("body", truncated.body);
36498
36973
  const linkUrl = ui.link(tag, releaseDraftUrl.toString());
36499
36974
  task.title += ` ${linkUrl}`;
36500
36975
  if (first) {
36501
- task.output = t("task.release.openingDraft", { tag });
36976
+ const openingMsg = t("task.release.openingDraft", { tag });
36977
+ if (truncated.clipboardCopied) {
36978
+ task.output = `${t("task.release.copiedToClipboard")}
36979
+ ${openingMsg}`;
36980
+ } else if (truncated.truncated) {
36981
+ task.output = `${t("task.release.truncated")}
36982
+ ${openingMsg}`;
36983
+ } else {
36984
+ task.output = openingMsg;
36985
+ }
36502
36986
  await openUrl(releaseDraftUrl.toString());
36503
36987
  first = false;
36504
36988
  }
@@ -36506,24 +36990,30 @@ ${repositoryUrl}/compare/${lastRev}...${tag}`;
36506
36990
  } else {
36507
36991
  const version = plan.version;
36508
36992
  const tag = `v${version}`;
36509
- const lastRev = await git.previousTag(tag) || await git.firstCommit();
36510
- const commits = (await git.commits(lastRev, tag)).slice(1);
36511
- task.output = t("task.release.collectedCommits", {
36512
- count: commits.length,
36513
- tag
36993
+ const body = await buildReleaseBody(ctx, {
36994
+ pkgPath: plan.mode === "single" ? plan.packagePath : undefined,
36995
+ version,
36996
+ tag,
36997
+ repositoryUrl
36514
36998
  });
36515
- let body = commits.map(({ id, message }) => `- ${message.replace(/#/g, `${repositoryUrl}/issues/`)} ${repositoryUrl}/commit/${id}`).join(`
36516
- `);
36517
- body += `
36518
-
36519
- ${repositoryUrl}/compare/${lastRev}...${tag}`;
36520
36999
  const releaseDraftUrl = new URL(`${repositoryUrl}/releases/new`);
36521
37000
  releaseDraftUrl.searchParams.set("tag", tag);
36522
- releaseDraftUrl.searchParams.set("body", body);
36523
37001
  releaseDraftUrl.searchParams.set("prerelease", `${!!prerelease2(version)}`);
37002
+ const baseUrl = `${releaseDraftUrl.toString()}&body=`;
37003
+ const truncated = await truncateForUrl(body, baseUrl);
37004
+ releaseDraftUrl.searchParams.set("body", truncated.body);
36524
37005
  const linkUrl = ui.link("Link", releaseDraftUrl.toString());
36525
37006
  task.title += ` ${linkUrl}`;
36526
- task.output = t("task.release.openingDraft", { tag });
37007
+ const openingMsg = t("task.release.openingDraft", { tag });
37008
+ if (truncated.clipboardCopied) {
37009
+ task.output = `${t("task.release.copiedToClipboard")}
37010
+ ${openingMsg}`;
37011
+ } else if (truncated.truncated) {
37012
+ task.output = `${t("task.release.truncated")}
37013
+ ${openingMsg}`;
37014
+ } else {
37015
+ task.output = openingMsg;
37016
+ }
36527
37017
  await openUrl(releaseDraftUrl.toString());
36528
37018
  }
36529
37019
  }
@@ -36535,7 +37025,7 @@ ${repositoryUrl}/compare/${lastRev}...${tag}`;
36535
37025
  init_catalog2();
36536
37026
  init_error4();
36537
37027
  init_i18n();
36538
- import path14 from "node:path";
37028
+ import path15 from "node:path";
36539
37029
  init_exec();
36540
37030
  var JS_WORKSPACE_TYPES = new Set(["pnpm", "npm", "yarn", "bun", "deno"]);
36541
37031
  var ECOSYSTEM_DEFAULTS = {
@@ -36620,7 +37110,7 @@ async function resolveExecutions(ctx, type) {
36620
37110
  });
36621
37111
  } else {
36622
37112
  for (const pkg of group.groupPackages) {
36623
- const pkgCwd = path14.resolve(ctx.cwd, pkg.path);
37113
+ const pkgCwd = path15.resolve(ctx.cwd, pkg.path);
36624
37114
  executions.push({
36625
37115
  label: `${resolved.command} (${pkg.path})`,
36626
37116
  cmd: "sh",
@@ -36641,7 +37131,7 @@ async function resolveExecutions(ctx, type) {
36641
37131
  });
36642
37132
  } else {
36643
37133
  for (const pkg of group.groupPackages) {
36644
- const pkgCwd = path14.resolve(ctx.cwd, pkg.path);
37134
+ const pkgCwd = path15.resolve(ctx.cwd, pkg.path);
36645
37135
  const instance = new descriptor.ecosystemClass(pkgCwd);
36646
37136
  const { cmd, args } = type === "test" ? await instance.resolveTestCommand(resolved.script) : await instance.resolveBuildCommand(resolved.script);
36647
37137
  executions.push({
@@ -36655,7 +37145,7 @@ async function resolveExecutions(ctx, type) {
36655
37145
  }
36656
37146
  }
36657
37147
  for (const pkg of group.individualPackages) {
36658
- const pkgCwd = path14.resolve(ctx.cwd, pkg.path);
37148
+ const pkgCwd = path15.resolve(ctx.cwd, pkg.path);
36659
37149
  const resolved = resolveScript(pkg, group.ecosystemKey, ctx, type);
36660
37150
  if (resolved.command) {
36661
37151
  executions.push({
@@ -36753,13 +37243,13 @@ function createBuildTask(hasPrepare, skipBuild) {
36753
37243
 
36754
37244
  // src/tasks/phases/version.ts
36755
37245
  init_dist2();
36756
- import path17 from "node:path";
37246
+ import path18 from "node:path";
36757
37247
 
36758
37248
  // src/changelog/file.ts
36759
37249
  import { existsSync as existsSync7, readFileSync as readFileSync10, writeFileSync as writeFileSync8 } from "node:fs";
36760
- import path15 from "node:path";
37250
+ import path16 from "node:path";
36761
37251
  function writeChangelogToFile(cwd, newContent) {
36762
- const changelogPath = path15.join(cwd, "CHANGELOG.md");
37252
+ const changelogPath = path16.join(cwd, "CHANGELOG.md");
36763
37253
  let existing = "";
36764
37254
  if (existsSync7(changelogPath)) {
36765
37255
  existing = readFileSync10(changelogPath, "utf-8");
@@ -36806,6 +37296,21 @@ function generateChangelog(version, entries, depUpdates) {
36806
37296
  `)}
36807
37297
  `;
36808
37298
  }
37299
+ var BUMP_PRIORITY = {
37300
+ major: 3,
37301
+ minor: 2,
37302
+ patch: 1
37303
+ };
37304
+ function deduplicateEntries(entries) {
37305
+ const map = new Map;
37306
+ for (const entry of entries) {
37307
+ const existing = map.get(entry.id);
37308
+ if (!existing || (BUMP_PRIORITY[entry.type] ?? 0) > (BUMP_PRIORITY[existing.type] ?? 0)) {
37309
+ map.set(entry.id, entry);
37310
+ }
37311
+ }
37312
+ return [...map.values()];
37313
+ }
36809
37314
  function buildChangelogEntries(changesets, packagePath) {
36810
37315
  const entries = [];
36811
37316
  for (const changeset of changesets) {
@@ -36824,8 +37329,8 @@ function buildChangelogEntries(changesets, packagePath) {
36824
37329
 
36825
37330
  // src/changeset/reader.ts
36826
37331
  import { existsSync as existsSync8, readdirSync as readdirSync3, readFileSync as readFileSync11, rmSync as rmSync2 } from "node:fs";
36827
- import path16 from "node:path";
36828
- import process20 from "node:process";
37332
+ import path17 from "node:path";
37333
+ import process21 from "node:process";
36829
37334
 
36830
37335
  // src/changeset/parser.ts
36831
37336
  var import_yaml2 = __toESM(require_dist(), 1);
@@ -36845,8 +37350,8 @@ function parseChangeset(content, fileName, resolveKey) {
36845
37350
  if (!VALID_BUMP_TYPES.has(type)) {
36846
37351
  throw new Error(`Invalid bump type "${type}" for package "${key}" in "${fileName}". Expected: patch, minor, or major.`);
36847
37352
  }
36848
- const path16 = resolveKey ? resolveKey(key) : key;
36849
- releases.push({ path: path16, type });
37353
+ const path17 = resolveKey ? resolveKey(key) : key;
37354
+ releases.push({ path: path17, type });
36850
37355
  }
36851
37356
  }
36852
37357
  const id = fileName.replace(/\.md$/, "");
@@ -36858,8 +37363,8 @@ function parseChangeset(content, fileName, resolveKey) {
36858
37363
  }
36859
37364
 
36860
37365
  // src/changeset/reader.ts
36861
- function readChangesets(cwd = process20.cwd(), resolveKey) {
36862
- const changesetsDir = path16.join(cwd, ".pubm", "changesets");
37366
+ function readChangesets(cwd = process21.cwd(), resolveKey) {
37367
+ const changesetsDir = path17.join(cwd, ".pubm", "changesets");
36863
37368
  if (!existsSync8(changesetsDir)) {
36864
37369
  return [];
36865
37370
  }
@@ -36869,16 +37374,16 @@ function readChangesets(cwd = process20.cwd(), resolveKey) {
36869
37374
  if (!file.endsWith(".md") || file === "README.md") {
36870
37375
  continue;
36871
37376
  }
36872
- const filePath = path16.join(changesetsDir, file);
37377
+ const filePath = path17.join(changesetsDir, file);
36873
37378
  const content = readFileSync11(filePath, "utf-8");
36874
37379
  changesets.push(parseChangeset(content, file, resolveKey));
36875
37380
  }
36876
37381
  return changesets;
36877
37382
  }
36878
37383
  function deleteChangesetFiles(cwd, changesets) {
36879
- const changesetsDir = path16.join(cwd, ".pubm", "changesets");
37384
+ const changesetsDir = path17.join(cwd, ".pubm", "changesets");
36880
37385
  for (const changeset of changesets) {
36881
- const filePath = path16.join(changesetsDir, `${changeset.id}.md`);
37386
+ const filePath = path17.join(changesetsDir, `${changeset.id}.md`);
36882
37387
  if (existsSync8(filePath)) {
36883
37388
  rmSync2(filePath);
36884
37389
  }
@@ -36935,7 +37440,7 @@ function createVersionTask(hasPrepare, dryRun) {
36935
37440
  const changesets = readChangesets(ctx.cwd, resolver);
36936
37441
  if (changesets.length > 0) {
36937
37442
  registerChangesetBackups(ctx, changesets);
36938
- const changelogPath = path17.join(ctx.cwd, "CHANGELOG.md");
37443
+ const changelogPath = path18.join(ctx.cwd, "CHANGELOG.md");
36939
37444
  registerChangelogBackup(ctx, changelogPath);
36940
37445
  const pkgPath = ctx.config.packages[0]?.path ?? "";
36941
37446
  const entries = buildChangelogEntries(changesets, pkgPath);
@@ -36992,9 +37497,9 @@ ${ctx.config.packages.map((pkg) => `- ${pkg.name}: ${plan.version}`).join(`
36992
37497
  const changesets = readChangesets(ctx.cwd, resolver);
36993
37498
  if (changesets.length > 0) {
36994
37499
  registerChangesetBackups(ctx, changesets);
36995
- const changelogPath = path17.join(ctx.cwd, "CHANGELOG.md");
37500
+ const changelogPath = path18.join(ctx.cwd, "CHANGELOG.md");
36996
37501
  registerChangelogBackup(ctx, changelogPath);
36997
- const allEntries = [...plan.packages.keys()].flatMap((pkgPath) => buildChangelogEntries(changesets, pkgPath));
37502
+ const allEntries = deduplicateEntries([...plan.packages.keys()].flatMap((pkgPath) => buildChangelogEntries(changesets, pkgPath)));
36998
37503
  if (allEntries.length > 0) {
36999
37504
  const changelogContent = generateChangelog(plan.version, allEntries);
37000
37505
  writeChangelogToFile(ctx.cwd, changelogContent);
@@ -37052,15 +37557,15 @@ ${[...plan.packages].map(([pkgPath]) => `- ${getPackageName(ctx, pkgPath)}: ${pl
37052
37557
  registerChangesetBackups(ctx, changesets);
37053
37558
  for (const [pkgPath] of plan.packages) {
37054
37559
  const pkgConfig = ctx.config.packages.find((p2) => p2.path === pkgPath);
37055
- const changelogDir = pkgConfig ? path17.resolve(ctx.cwd, pkgConfig.path) : ctx.cwd;
37056
- const changelogPath = path17.join(changelogDir, "CHANGELOG.md");
37560
+ const changelogDir = pkgConfig ? path18.resolve(ctx.cwd, pkgConfig.path) : ctx.cwd;
37561
+ const changelogPath = path18.join(changelogDir, "CHANGELOG.md");
37057
37562
  registerChangelogBackup(ctx, changelogPath);
37058
37563
  }
37059
37564
  for (const [pkgPath, pkgVersion] of plan.packages) {
37060
37565
  const entries = buildChangelogEntries(changesets, pkgPath);
37061
37566
  if (entries.length > 0) {
37062
37567
  const pkgConfig = ctx.config.packages.find((p2) => p2.path === pkgPath);
37063
- const changelogDir = pkgConfig ? path17.resolve(ctx.cwd, pkgConfig.path) : ctx.cwd;
37568
+ const changelogDir = pkgConfig ? path18.resolve(ctx.cwd, pkgConfig.path) : ctx.cwd;
37064
37569
  writeChangelogToFile(changelogDir, generateChangelog(pkgVersion, entries));
37065
37570
  }
37066
37571
  }
@@ -37123,7 +37628,7 @@ function chainCleanup(existing, next) {
37123
37628
  };
37124
37629
  }
37125
37630
  async function run(ctx) {
37126
- ctx.runtime.promptEnabled = !m && process21.stdin.isTTY;
37631
+ ctx.runtime.promptEnabled = !m && process22.stdin.isTTY;
37127
37632
  const mode = ctx.options.mode ?? "local";
37128
37633
  const phases = resolvePhases(ctx.options);
37129
37634
  const dryRun = !!ctx.options.dryRun;
@@ -37138,12 +37643,12 @@ async function run(ctx) {
37138
37643
  interactive: false,
37139
37644
  sigint: true
37140
37645
  });
37141
- process21.exit(130);
37646
+ process22.exit(130);
37142
37647
  };
37143
- process21.on("SIGINT", onSigint);
37648
+ process22.on("SIGINT", onSigint);
37144
37649
  try {
37145
37650
  if (ctx.options.contents)
37146
- process21.chdir(ctx.options.contents);
37651
+ process22.chdir(ctx.options.contents);
37147
37652
  if (mode === "ci" && hasPrepare)
37148
37653
  await runCiPreparePreflight(ctx, chainCleanup, cleanupRef);
37149
37654
  if (mode === "local" && hasPrepare)
@@ -37171,7 +37676,7 @@ async function run(ctx) {
37171
37676
  parts.push(`${ui.chalk.bold(name)} on ${descriptor.label}`);
37172
37677
  }
37173
37678
  }
37174
- process21.removeListener("SIGINT", onSigint);
37679
+ process22.removeListener("SIGINT", onSigint);
37175
37680
  if (mode === "ci" && hasPrepare && !hasPublish) {
37176
37681
  cleanupRef.current?.();
37177
37682
  console.log(`
@@ -37191,83 +37696,27 @@ async function run(ctx) {
37191
37696
  }
37192
37697
  await ctx.runtime.pluginRunner.runHook("onSuccess", ctx);
37193
37698
  } catch (e3) {
37194
- process21.removeListener("SIGINT", onSigint);
37699
+ process22.removeListener("SIGINT", onSigint);
37195
37700
  cleanupRef.current?.();
37196
37701
  await ctx.runtime.pluginRunner.runErrorHook(ctx, e3);
37197
37702
  consoleError(e3);
37198
37703
  await ctx.runtime.rollback.execute(ctx, {
37199
- interactive: ctx.runtime.promptEnabled
37200
- });
37201
- process21.exit(1);
37202
- }
37203
- }
37204
-
37205
- // src/index.ts
37206
- init_dist();
37207
- // src/changelog/changeset-writer.ts
37208
- class ChangesetChangelogWriter {
37209
- formatEntries(entries) {
37210
- if (entries.length === 0)
37211
- return [];
37212
- return [
37213
- { category: undefined, items: entries.map((e3) => `- ${e3.summary}`) }
37214
- ];
37215
- }
37216
- }
37217
- // src/conventional-commit/types.ts
37218
- var DEFAULT_TYPE_BUMP_MAP = {
37219
- feat: "minor",
37220
- fix: "patch",
37221
- perf: "patch",
37222
- chore: false,
37223
- docs: false,
37224
- test: false,
37225
- ci: false,
37226
- style: false,
37227
- refactor: false
37228
- };
37229
- var COMMIT_TYPE_CATEGORY_MAP = {
37230
- feat: "Features",
37231
- fix: "Bug Fixes",
37232
- perf: "Performance",
37233
- refactor: "Refactoring",
37234
- docs: "Documentation"
37235
- };
37236
- var DEFAULT_CATEGORY = "Other Changes";
37237
-
37238
- // src/changelog/conventional-commit-writer.ts
37239
- var CATEGORY_ORDER = [
37240
- "Features",
37241
- "Bug Fixes",
37242
- "Performance",
37243
- "Refactoring",
37244
- "Documentation",
37245
- "Other Changes"
37246
- ];
37247
-
37248
- class ConventionalCommitChangelogWriter {
37249
- formatEntries(entries) {
37250
- if (entries.length === 0)
37251
- return [];
37252
- const groups = new Map;
37253
- for (const entry of entries) {
37254
- const category = entry.type && COMMIT_TYPE_CATEGORY_MAP[entry.type] || DEFAULT_CATEGORY;
37255
- const hashSuffix = entry.hash ? ` (${entry.hash})` : "";
37256
- const item = `- ${entry.summary}${hashSuffix}`;
37257
- const existing = groups.get(category);
37258
- if (existing) {
37259
- existing.push(item);
37260
- } else {
37261
- groups.set(category, [item]);
37262
- }
37263
- }
37264
- const sections = [];
37265
- for (const category of CATEGORY_ORDER) {
37266
- const items = groups.get(category);
37267
- if (items)
37268
- sections.push({ category, items });
37269
- }
37270
- return sections;
37704
+ interactive: ctx.runtime.promptEnabled
37705
+ });
37706
+ process22.exit(1);
37707
+ }
37708
+ }
37709
+
37710
+ // src/index.ts
37711
+ init_dist();
37712
+ // src/changelog/changeset-writer.ts
37713
+ class ChangesetChangelogWriter {
37714
+ formatEntries(entries) {
37715
+ if (entries.length === 0)
37716
+ return [];
37717
+ return [
37718
+ { category: undefined, items: entries.map((e3) => `- ${e3.summary}`) }
37719
+ ];
37271
37720
  }
37272
37721
  }
37273
37722
  // src/changelog/renderer.ts
@@ -37312,11 +37761,11 @@ function maxBump(a3, b2) {
37312
37761
  }
37313
37762
  // src/changeset/migrate.ts
37314
37763
  import { copyFileSync, existsSync as existsSync9, mkdirSync as mkdirSync3, readdirSync as readdirSync4 } from "node:fs";
37315
- import path18 from "node:path";
37316
- import process22 from "node:process";
37764
+ import path19 from "node:path";
37765
+ import process23 from "node:process";
37317
37766
  var SKIPPED_FILES = new Set(["config.json", "README.md"]);
37318
- function migrateFromChangesets(cwd = process22.cwd()) {
37319
- const changesetDir = path18.join(cwd, ".changeset");
37767
+ function migrateFromChangesets(cwd = process23.cwd()) {
37768
+ const changesetDir = path19.join(cwd, ".changeset");
37320
37769
  if (!existsSync9(changesetDir)) {
37321
37770
  return {
37322
37771
  success: false,
@@ -37325,7 +37774,7 @@ function migrateFromChangesets(cwd = process22.cwd()) {
37325
37774
  configMigrated: false
37326
37775
  };
37327
37776
  }
37328
- const pubmDir = path18.join(cwd, ".pubm", "changesets");
37777
+ const pubmDir = path19.join(cwd, ".pubm", "changesets");
37329
37778
  mkdirSync3(pubmDir, { recursive: true });
37330
37779
  const files = readdirSync4(changesetDir);
37331
37780
  const migratedFiles = [];
@@ -37339,13 +37788,13 @@ function migrateFromChangesets(cwd = process22.cwd()) {
37339
37788
  continue;
37340
37789
  }
37341
37790
  if (file === "pre.json") {
37342
- copyFileSync(path18.join(changesetDir, file), path18.resolve(cwd, ".pubm", "pre.json"));
37791
+ copyFileSync(path19.join(changesetDir, file), path19.resolve(cwd, ".pubm", "pre.json"));
37343
37792
  migratedFiles.push(file);
37344
37793
  continue;
37345
37794
  }
37346
37795
  if (file.endsWith(".md")) {
37347
- const src = path18.join(changesetDir, file);
37348
- const dest = path18.join(pubmDir, file);
37796
+ const src = path19.join(changesetDir, file);
37797
+ const dest = path19.join(pubmDir, file);
37349
37798
  copyFileSync(src, dest);
37350
37799
  migratedFiles.push(file);
37351
37800
  }
@@ -37357,8 +37806,8 @@ function migrateFromChangesets(cwd = process22.cwd()) {
37357
37806
  };
37358
37807
  }
37359
37808
  // src/changeset/status.ts
37360
- import process23 from "node:process";
37361
- function getStatus(cwd = process23.cwd(), resolveKey) {
37809
+ import process24 from "node:process";
37810
+ function getStatus(cwd = process24.cwd(), resolveKey) {
37362
37811
  const changesets = readChangesets(cwd, resolveKey);
37363
37812
  const packages = new Map;
37364
37813
  for (const changeset of changesets) {
@@ -37385,8 +37834,8 @@ function getStatus(cwd = process23.cwd(), resolveKey) {
37385
37834
  }
37386
37835
  // src/changeset/version.ts
37387
37836
  var import_semver5 = __toESM(require_semver2(), 1);
37388
- import process24 from "node:process";
37389
- function calculateVersionBumps(currentVersions, cwd = process24.cwd(), resolveKey) {
37837
+ import process25 from "node:process";
37838
+ function calculateVersionBumps(currentVersions, cwd = process25.cwd(), resolveKey) {
37390
37839
  const changesets = readChangesets(cwd, resolveKey);
37391
37840
  const bumpTypes = new Map;
37392
37841
  for (const changeset of changesets) {
@@ -37420,8 +37869,8 @@ function calculateVersionBumps(currentVersions, cwd = process24.cwd(), resolveKe
37420
37869
  // src/changeset/writer.ts
37421
37870
  var import_yaml3 = __toESM(require_dist(), 1);
37422
37871
  import { mkdirSync as mkdirSync4, writeFileSync as writeFileSync9 } from "node:fs";
37423
- import path19 from "node:path";
37424
- import process25 from "node:process";
37872
+ import path20 from "node:path";
37873
+ import process26 from "node:process";
37425
37874
  var adjectives = [
37426
37875
  "brave",
37427
37876
  "calm",
@@ -37515,12 +37964,12 @@ ${summary}
37515
37964
  }
37516
37965
  return content;
37517
37966
  }
37518
- function writeChangeset(releases, summary, cwd = process25.cwd()) {
37519
- const changesetsDir = path19.join(cwd, ".pubm", "changesets");
37967
+ function writeChangeset(releases, summary, cwd = process26.cwd()) {
37968
+ const changesetsDir = path20.join(cwd, ".pubm", "changesets");
37520
37969
  mkdirSync4(changesetsDir, { recursive: true });
37521
37970
  const id = generateChangesetId();
37522
37971
  const fileName = `${id}.md`;
37523
- const filePath = path19.join(changesetsDir, fileName);
37972
+ const filePath = path20.join(changesetsDir, fileName);
37524
37973
  const content = generateChangesetContent(releases, summary);
37525
37974
  writeFileSync9(filePath, content, "utf-8");
37526
37975
  return filePath;
@@ -37529,7 +37978,7 @@ function writeChangeset(releases, summary, cwd = process25.cwd()) {
37529
37978
  init_catalog2();
37530
37979
  init_i18n();
37531
37980
  var import_micromatch4 = __toESM(require_micromatch(), 1);
37532
- import path20 from "node:path";
37981
+ import path21 from "node:path";
37533
37982
  init_catalog();
37534
37983
  var defaultValidate = {
37535
37984
  cleanInstall: true,
@@ -37613,7 +38062,7 @@ async function resolveConfig(config, cwd) {
37613
38062
  if (import_micromatch4.default.scan(normalized).isGlob) {
37614
38063
  return import_micromatch4.default.isMatch(pkgPathForward, normalized);
37615
38064
  }
37616
- return path20.normalize(cp.path) === pkg.path;
38065
+ return path21.normalize(cp.path) === pkg.path;
37617
38066
  });
37618
38067
  return {
37619
38068
  path: pkg.path,
@@ -37673,7 +38122,7 @@ import {
37673
38122
  } from "node:fs/promises";
37674
38123
  import { createRequire as createRequire2 } from "node:module";
37675
38124
  import { tmpdir as tmpdir3 } from "node:os";
37676
- import path21 from "node:path";
38125
+ import path22 from "node:path";
37677
38126
  import { pathToFileURL } from "node:url";
37678
38127
  import vm from "node:vm";
37679
38128
  var CONFIG_FILES = [
@@ -37726,7 +38175,7 @@ var CONFIG_MODULE_SHIMS = {
37726
38175
  };
37727
38176
  async function findConfigFile(cwd) {
37728
38177
  for (const file of CONFIG_FILES) {
37729
- const filePath = path21.join(cwd, file);
38178
+ const filePath = path22.join(cwd, file);
37730
38179
  try {
37731
38180
  if ((await stat6(filePath)).isFile()) {
37732
38181
  return filePath;
@@ -37747,15 +38196,15 @@ function isBareSpecifier(specifier) {
37747
38196
  return !specifier.startsWith(".") && !specifier.startsWith("/") && !specifier.startsWith("file:") && !specifier.startsWith("node:");
37748
38197
  }
37749
38198
  async function findClosestPackageManifest(filePath) {
37750
- let current = path21.dirname(filePath);
38199
+ let current = path22.dirname(filePath);
37751
38200
  while (true) {
37752
- const manifestPath = path21.join(current, "package.json");
38201
+ const manifestPath = path22.join(current, "package.json");
37753
38202
  try {
37754
38203
  if ((await stat6(manifestPath)).isFile()) {
37755
38204
  return manifestPath;
37756
38205
  }
37757
38206
  } catch {}
37758
- const parent = path21.dirname(current);
38207
+ const parent = path22.dirname(current);
37759
38208
  if (parent === current) {
37760
38209
  return null;
37761
38210
  }
@@ -37857,13 +38306,13 @@ async function collectOptionalDependenciesForInputs(inputPaths) {
37857
38306
  async function findInstalledPackagePath(startDir, dependency) {
37858
38307
  let current = startDir;
37859
38308
  while (true) {
37860
- const packageDir = path21.join(current, "node_modules", dependency);
38309
+ const packageDir = path22.join(current, "node_modules", dependency);
37861
38310
  try {
37862
38311
  if ((await stat6(packageDir)).isDirectory()) {
37863
38312
  return packageDir;
37864
38313
  }
37865
38314
  } catch {}
37866
- const parent = path21.dirname(current);
38315
+ const parent = path22.dirname(current);
37867
38316
  if (parent === current) {
37868
38317
  return null;
37869
38318
  }
@@ -37871,19 +38320,19 @@ async function findInstalledPackagePath(startDir, dependency) {
37871
38320
  }
37872
38321
  }
37873
38322
  async function writeOptionalDependencyStubs(moduleDir, resolveFromDir, optionalDependencies) {
37874
- const nodeModulesDir = path21.join(moduleDir, "node_modules");
38323
+ const nodeModulesDir = path22.join(moduleDir, "node_modules");
37875
38324
  for (const dependency of optionalDependencies) {
37876
38325
  if (await findInstalledPackagePath(resolveFromDir, dependency)) {
37877
38326
  continue;
37878
38327
  }
37879
- const packageDir = path21.join(nodeModulesDir, dependency);
38328
+ const packageDir = path22.join(nodeModulesDir, dependency);
37880
38329
  await mkdir(packageDir, { recursive: true });
37881
- await writeFile3(path21.join(packageDir, "package.json"), JSON.stringify({
38330
+ await writeFile3(path22.join(packageDir, "package.json"), JSON.stringify({
37882
38331
  name: dependency,
37883
38332
  private: true,
37884
38333
  main: "./index.js"
37885
38334
  }, null, 2), "utf8");
37886
- await writeFile3(path21.join(packageDir, "index.js"), createOptionalDependencyProxyPackage(dependency), "utf8");
38335
+ await writeFile3(path22.join(packageDir, "index.js"), createOptionalDependencyProxyPackage(dependency), "utf8");
37887
38336
  }
37888
38337
  }
37889
38338
  function createOptionalDependencyPlugin(specifiers) {
@@ -37995,10 +38444,10 @@ async function buildConfigWithFormat(entrypoint, format3) {
37995
38444
  }
37996
38445
  async function buildConfigWithChildProcess(entrypoint, format3 = "esm") {
37997
38446
  const extension = format3 === "esm" ? "mjs" : "cjs";
37998
- const tempDir = await mkdtemp(path21.join(tmpdir3(), "pubm-config-"));
37999
- const buildScript = path21.join(tempDir, "build-config.mjs");
38000
- const outfile = path21.join(tempDir, `pubm.config.${extension}`);
38001
- const resultFile = path21.join(tempDir, "build-result.json");
38447
+ const tempDir = await mkdtemp(path22.join(tmpdir3(), "pubm-config-"));
38448
+ const buildScript = path22.join(tempDir, "build-config.mjs");
38449
+ const outfile = path22.join(tempDir, `pubm.config.${extension}`);
38450
+ const resultFile = path22.join(tempDir, "build-result.json");
38002
38451
  try {
38003
38452
  await writeFile3(buildScript, [
38004
38453
  'import { readFile, stat, writeFile } from "node:fs/promises";',
@@ -38274,11 +38723,11 @@ async function buildConfigWithChildProcess(entrypoint, format3 = "esm") {
38274
38723
  }
38275
38724
  function rewriteImportMeta(source, configPath) {
38276
38725
  const replacements = [
38277
- ["import.meta.dirname", JSON.stringify(path21.dirname(configPath))],
38726
+ ["import.meta.dirname", JSON.stringify(path22.dirname(configPath))],
38278
38727
  ["import.meta.filename", JSON.stringify(configPath)],
38279
38728
  ["import.meta.path", JSON.stringify(configPath)],
38280
38729
  ["import.meta.url", JSON.stringify(pathToFileURL(configPath).href)],
38281
- ["import.meta.dir", JSON.stringify(path21.dirname(configPath))]
38730
+ ["import.meta.dir", JSON.stringify(path22.dirname(configPath))]
38282
38731
  ];
38283
38732
  let rewritten = source;
38284
38733
  for (const [pattern, value] of replacements) {
@@ -38294,10 +38743,10 @@ async function importConfigModule(configPath) {
38294
38743
  return normalizeConfigNamespace(namespace);
38295
38744
  }
38296
38745
  async function importBundledConfig(source, configPath, optionalDependencies) {
38297
- const tempDir = await mkdtemp(path21.join(path21.dirname(configPath), ".pubm-config-module-"));
38298
- const tempFile = path21.join(tempDir, "pubm.config.mjs");
38746
+ const tempDir = await mkdtemp(path22.join(path22.dirname(configPath), ".pubm-config-module-"));
38747
+ const tempFile = path22.join(tempDir, "pubm.config.mjs");
38299
38748
  try {
38300
- await writeOptionalDependencyStubs(tempDir, path21.dirname(configPath), optionalDependencies);
38749
+ await writeOptionalDependencyStubs(tempDir, path22.dirname(configPath), optionalDependencies);
38301
38750
  await writeFile3(tempFile, source, "utf8");
38302
38751
  return importConfigModule(tempFile);
38303
38752
  } finally {
@@ -38312,7 +38761,7 @@ async function executeBundledConfigInVm(source, configPath) {
38312
38761
  exports: module.exports,
38313
38762
  require: require2,
38314
38763
  __filename: configPath,
38315
- __dirname: path21.dirname(configPath),
38764
+ __dirname: path22.dirname(configPath),
38316
38765
  console,
38317
38766
  process,
38318
38767
  Buffer,
@@ -38343,7 +38792,7 @@ function formatStageError(stage, error4) {
38343
38792
  async function loadConfig(cwd = process.cwd(), configPath) {
38344
38793
  let resolvedConfigPath;
38345
38794
  if (configPath) {
38346
- resolvedConfigPath = path21.resolve(cwd, configPath);
38795
+ resolvedConfigPath = path22.resolve(cwd, configPath);
38347
38796
  try {
38348
38797
  if (!(await stat6(resolvedConfigPath)).isFile()) {
38349
38798
  throw new Error(`Config path is not a file: ${resolvedConfigPath}`);
@@ -38422,36 +38871,6 @@ function defineConfig(config) {
38422
38871
  // src/index.ts
38423
38872
  init_context();
38424
38873
 
38425
- // src/conventional-commit/scope-resolver.ts
38426
- import path22 from "node:path";
38427
- function resolveCommitPackages(commit, packagePaths) {
38428
- const matched = new Set;
38429
- if (commit.scope) {
38430
- for (const pkgPath of packagePaths) {
38431
- const dirName = path22.basename(pkgPath);
38432
- if (dirName === commit.scope) {
38433
- matched.add(pkgPath);
38434
- }
38435
- }
38436
- if (matched.size > 0)
38437
- return [...matched];
38438
- }
38439
- for (const file of commit.files) {
38440
- const normalized = file.replace(/\\/g, "/");
38441
- for (const pkgPath of packagePaths) {
38442
- if (pkgPath === ".") {
38443
- matched.add(pkgPath);
38444
- continue;
38445
- }
38446
- const normalizedPkg = pkgPath.replace(/\\/g, "/");
38447
- if (normalized.startsWith(`${normalizedPkg}/`) || normalized === normalizedPkg) {
38448
- matched.add(pkgPath);
38449
- }
38450
- }
38451
- }
38452
- return [...matched];
38453
- }
38454
-
38455
38874
  // src/conventional-commit/commit-analyzer.ts
38456
38875
  function analyzeCommits(commits, packagePaths, typeOverrides) {
38457
38876
  const typeMap = {
@@ -38492,147 +38911,6 @@ function resolveBumpType(commit, typeMap) {
38492
38911
  return null;
38493
38912
  return mapped;
38494
38913
  }
38495
- // src/conventional-commit/git-log.ts
38496
- import { execFileSync } from "node:child_process";
38497
- var COMMIT_START_MARKER = "COMMIT_START";
38498
- var COMMIT_FILES_MARKER = "COMMIT_FILES";
38499
- function findLastReleaseRef(cwd, packageName) {
38500
- if (packageName) {
38501
- const scopedTags = execGit(cwd, [
38502
- "tag",
38503
- "--list",
38504
- `${packageName}@[0-9]*.[0-9]*.[0-9]*`,
38505
- "--sort=-v:refname"
38506
- ]);
38507
- if (scopedTags.length > 0)
38508
- return scopedTags[0];
38509
- }
38510
- const vTags = execGit(cwd, [
38511
- "tag",
38512
- "--list",
38513
- "v[0-9]*.[0-9]*.[0-9]*",
38514
- "--sort=-v:refname"
38515
- ]);
38516
- if (vTags.length > 0)
38517
- return vTags[0];
38518
- const versionCommit = execGit(cwd, [
38519
- "log",
38520
- "--format=%H",
38521
- "--grep=^Version Packages$",
38522
- "-1"
38523
- ]);
38524
- if (versionCommit.length > 0)
38525
- return versionCommit[0];
38526
- return;
38527
- }
38528
- function getCommitsSinceRef(cwd, ref) {
38529
- const range = ref ? `${ref}..HEAD` : "HEAD";
38530
- const format3 = `${COMMIT_START_MARKER} %h%n%B%n${COMMIT_FILES_MARKER}`;
38531
- const output = execGitRaw(cwd, [
38532
- "log",
38533
- `--format=${format3}`,
38534
- "--name-only",
38535
- range
38536
- ]);
38537
- if (!output.trim())
38538
- return [];
38539
- const commits = [];
38540
- const lines = output.split(`
38541
- `);
38542
- let i2 = 0;
38543
- while (i2 < lines.length) {
38544
- if (!lines[i2].startsWith(COMMIT_START_MARKER)) {
38545
- i2++;
38546
- continue;
38547
- }
38548
- const hash = lines[i2].slice(COMMIT_START_MARKER.length + 1).trim();
38549
- i2++;
38550
- const messageLines = [];
38551
- while (i2 < lines.length && !lines[i2].startsWith(COMMIT_FILES_MARKER)) {
38552
- if (lines[i2].startsWith(COMMIT_START_MARKER))
38553
- break;
38554
- messageLines.push(lines[i2]);
38555
- i2++;
38556
- }
38557
- if (i2 < lines.length && lines[i2].startsWith(COMMIT_FILES_MARKER)) {
38558
- i2++;
38559
- }
38560
- const files = [];
38561
- while (i2 < lines.length && !lines[i2].startsWith(COMMIT_START_MARKER)) {
38562
- const file = lines[i2].trim();
38563
- if (file)
38564
- files.push(file);
38565
- i2++;
38566
- }
38567
- const message = messageLines.join(`
38568
- `).trim();
38569
- if (hash && message) {
38570
- commits.push({ hash, message, files });
38571
- }
38572
- }
38573
- return commits;
38574
- }
38575
- function execGit(cwd, args) {
38576
- return execGitRaw(cwd, args).split(`
38577
- `).map((l3) => l3.trim()).filter(Boolean);
38578
- }
38579
- function execGitRaw(cwd, args) {
38580
- try {
38581
- return execFileSync("git", args, { cwd, encoding: "utf-8" });
38582
- } catch {
38583
- return "";
38584
- }
38585
- }
38586
- // src/conventional-commit/parser.ts
38587
- var HEADER_REGEX = /^(\w+)(?:\(([^)]+)\))?(!)?\s*:\s*(.+)$/;
38588
- var FOOTER_REGEX = /^([\w-]+|BREAKING CHANGE)\s*:\s*(.+)$/;
38589
- function parseConventionalCommit(hash, message, files = []) {
38590
- const lines = message.split(`
38591
- `);
38592
- const firstLine = lines[0];
38593
- const headerMatch = firstLine.match(HEADER_REGEX);
38594
- if (!headerMatch)
38595
- return null;
38596
- const [, type, scope, bang, description] = headerMatch;
38597
- let body;
38598
- const footers = new Map;
38599
- let breaking = bang === "!";
38600
- if (lines.length > 1) {
38601
- const rest = lines.slice(1);
38602
- let footerStartIndex = rest.length;
38603
- for (let i2 = rest.length - 1;i2 >= 0; i2--) {
38604
- if (rest[i2] === "") {
38605
- footerStartIndex = i2 + 1;
38606
- break;
38607
- }
38608
- }
38609
- const bodyStartIndex = rest.findIndex((line) => line !== "");
38610
- if (bodyStartIndex !== -1 && bodyStartIndex < footerStartIndex) {
38611
- const bodyLines = rest.slice(bodyStartIndex, footerStartIndex - 1);
38612
- const bodyText = bodyLines.join(`
38613
- `).trim();
38614
- if (bodyText)
38615
- body = bodyText;
38616
- }
38617
- let currentFooterKey;
38618
- for (let i2 = footerStartIndex;i2 < rest.length; i2++) {
38619
- const footerMatch = rest[i2].match(FOOTER_REGEX);
38620
- if (footerMatch) {
38621
- const [, key, value] = footerMatch;
38622
- footers.set(key, value);
38623
- currentFooterKey = key;
38624
- if (key === "BREAKING CHANGE" || key === "BREAKING-CHANGE") {
38625
- breaking = true;
38626
- }
38627
- } else if (currentFooterKey && rest[i2].startsWith(" ")) {
38628
- const existing = footers.get(currentFooterKey) ?? "";
38629
- footers.set(currentFooterKey, `${existing}
38630
- ${rest[i2].trimStart()}`);
38631
- }
38632
- }
38633
- }
38634
- return { hash, type, scope, breaking, description, body, footers, files };
38635
- }
38636
38914
  // src/index.ts
38637
38915
  init_catalog2();
38638
38916
  init_js_descriptor();
@@ -40504,6 +40782,7 @@ var requiredMissingInformationTasks = (options) => createListr({
40504
40782
  ])
40505
40783
  });
40506
40784
  // src/tasks/snapshot-runner.ts
40785
+ import process27 from "node:process";
40507
40786
  init_error4();
40508
40787
  init_git();
40509
40788
  init_i18n();
@@ -40527,7 +40806,8 @@ function generateSnapshotVersion(options) {
40527
40806
  const now2 = new Date;
40528
40807
  const timestamp = formatTimestamp(now2);
40529
40808
  if (options.template) {
40530
- return options.template.replace(/\{base\}/g, base2).replace(/\{tag\}/g, tag).replace(/\{timestamp\}/g, timestamp).replace(/\{commit\}/g, options.commit ?? "");
40809
+ const suffix = options.template.replace(/\{tag\}/g, tag).replace(/\{timestamp\}/g, timestamp).replace(/\{commit\}/g, options.commit ?? "");
40810
+ return `${base2}-${suffix}`;
40531
40811
  }
40532
40812
  return `${base2}-${tag}-${timestamp}`;
40533
40813
  }
@@ -40588,6 +40868,7 @@ function buildSnapshotVersionPlan(packages, versioning, tag, template) {
40588
40868
  }
40589
40869
  async function runSnapshotPipeline(ctx, options) {
40590
40870
  const { tag, filter, dryRun = false } = options;
40871
+ ctx.runtime.promptEnabled = !m && !!process27.stdin.isTTY;
40591
40872
  const targetPackages = applySnapshotFilter(ctx.config.packages, filter);
40592
40873
  const versioning = ctx.config.versioning ?? "fixed";
40593
40874
  const plan = buildSnapshotVersionPlan(targetPackages, versioning, tag, ctx.config.snapshotTemplate);
@@ -40598,88 +40879,90 @@ async function runSnapshotPipeline(ctx, options) {
40598
40879
  const pipelineListrOptions = m ? createCiListrOptions() : undefined;
40599
40880
  const snapshotVersions = plan.mode === "single" ? new Map([[plan.packagePath, plan.version]]) : plan.packages;
40600
40881
  const originalVersions = new Map(targetPackages.map((p2) => [p2.path, p2.version || "0.0.0"]));
40601
- await createListr([
40602
- {
40603
- skip: options.skipTests,
40604
- title: t("task.test.title"),
40605
- task: async (ctx2, task) => {
40606
- const packageManager = await getPackageManager();
40607
- const command = `${packageManager} run ${ctx2.options.testScript}`;
40608
- task.title = t("task.test.titleWithCommand", { command });
40609
- task.output = `Executing \`${command}\``;
40610
- try {
40611
- await exec3(packageManager, ["run", ctx2.options.testScript], {
40612
- throwOnError: true
40613
- });
40614
- } catch (error4) {
40615
- throw new AbstractError(t("error.test.failed", { script: ctx2.options.testScript }), { cause: error4 });
40882
+ try {
40883
+ await createListr([
40884
+ {
40885
+ skip: options.skipTests,
40886
+ title: t("task.test.title"),
40887
+ task: async (ctx2, task) => {
40888
+ const packageManager = await getPackageManager();
40889
+ const command = `${packageManager} run ${ctx2.options.testScript}`;
40890
+ task.title = t("task.test.titleWithCommand", { command });
40891
+ task.output = `Executing \`${command}\``;
40892
+ try {
40893
+ await exec3(packageManager, ["run", ctx2.options.testScript], {
40894
+ throwOnError: true
40895
+ });
40896
+ } catch (error4) {
40897
+ throw new AbstractError(t("error.test.failed", { script: ctx2.options.testScript }), { cause: error4 });
40898
+ }
40616
40899
  }
40617
- }
40618
- },
40619
- {
40620
- skip: options.skipBuild,
40621
- title: t("task.build.title"),
40622
- task: async (ctx2, task) => {
40623
- const packageManager = await getPackageManager();
40624
- const command = `${packageManager} run ${ctx2.options.buildScript}`;
40625
- task.title = t("task.build.titleWithCommand", { command });
40626
- task.output = `Executing \`${command}\``;
40627
- try {
40628
- await exec3(packageManager, ["run", ctx2.options.buildScript], {
40629
- throwOnError: true
40630
- });
40631
- } catch (error4) {
40632
- throw new AbstractError(t("error.build.failed", { script: ctx2.options.buildScript }), { cause: error4 });
40900
+ },
40901
+ {
40902
+ skip: options.skipBuild,
40903
+ title: t("task.build.title"),
40904
+ task: async (ctx2, task) => {
40905
+ const packageManager = await getPackageManager();
40906
+ const command = `${packageManager} run ${ctx2.options.buildScript}`;
40907
+ task.title = t("task.build.titleWithCommand", { command });
40908
+ task.output = `Executing \`${command}\``;
40909
+ try {
40910
+ await exec3(packageManager, ["run", ctx2.options.buildScript], {
40911
+ throwOnError: true
40912
+ });
40913
+ } catch (error4) {
40914
+ throw new AbstractError(t("error.build.failed", { script: ctx2.options.buildScript }), { cause: error4 });
40915
+ }
40633
40916
  }
40634
- }
40635
- },
40636
- {
40637
- title: t("task.snapshot.title"),
40638
- task: async (ctx2, task) => {
40639
- const versionLabel = plan.mode !== "independent" ? plan.version : `${snapshotVersions.size} packages`;
40640
- task.title = t("task.snapshot.titleWithVersion", {
40641
- version: versionLabel
40642
- });
40643
- await writeVersions(ctx2, snapshotVersions);
40644
- try {
40917
+ },
40918
+ {
40919
+ title: t("task.snapshot.title"),
40920
+ task: async (ctx2, task) => {
40921
+ const versionLabel = plan.mode !== "independent" ? plan.version : `${snapshotVersions.size} packages`;
40922
+ task.title = t("task.snapshot.titleWithVersion", {
40923
+ version: versionLabel
40924
+ });
40925
+ await writeVersions(ctx2, snapshotVersions);
40926
+ await resolveWorkspaceProtocols(ctx2);
40645
40927
  task.output = t("task.snapshot.publishing", { tag });
40646
40928
  const publishTasks = await collectPublishTasks(ctx2);
40647
- await createListr(publishTasks, {
40929
+ return task.newListr(publishTasks, {
40648
40930
  concurrent: true
40649
- }).run(ctx2);
40650
- } finally {
40651
- await writeVersions(ctx2, originalVersions);
40931
+ });
40652
40932
  }
40653
- task.output = t("task.snapshot.published", {
40654
- version: versionLabel
40655
- });
40656
- }
40657
- },
40658
- {
40659
- title: t("task.snapshot.createTag"),
40660
- enabled: !dryRun,
40661
- task: async (ctx2, task) => {
40662
- const git = new Git;
40663
- const headCommit = await git.latestCommit();
40664
- if (plan.mode === "independent") {
40665
- for (const [pkgPath, pkgVersion] of plan.packages) {
40666
- const pkgName = ctx2.config.packages.find((p2) => p2.path === pkgPath)?.name ?? pkgPath;
40667
- const tagName = `${pkgName}@${pkgVersion}`;
40933
+ },
40934
+ {
40935
+ title: t("task.snapshot.createTag"),
40936
+ enabled: !dryRun,
40937
+ task: async (ctx2, task) => {
40938
+ const git = new Git;
40939
+ const headCommit = await git.latestCommit();
40940
+ if (plan.mode === "independent") {
40941
+ for (const [pkgPath, pkgVersion] of plan.packages) {
40942
+ const pkgName = ctx2.config.packages.find((p2) => p2.path === pkgPath)?.name ?? pkgPath;
40943
+ const tagName = `${pkgName}@${pkgVersion}`;
40944
+ task.output = t("task.snapshot.creatingTag", { tag: tagName });
40945
+ await git.createTag(tagName, headCommit);
40946
+ }
40947
+ } else {
40948
+ const version = plan.version;
40949
+ const tagName = `v${version}`;
40668
40950
  task.output = t("task.snapshot.creatingTag", { tag: tagName });
40669
40951
  await git.createTag(tagName, headCommit);
40670
40952
  }
40671
- } else {
40672
- const version = plan.version;
40673
- const tagName = `v${version}`;
40674
- task.output = t("task.snapshot.creatingTag", { tag: tagName });
40675
- await git.createTag(tagName, headCommit);
40953
+ task.output = t("task.snapshot.pushingTag", { tag: "tags" });
40954
+ await git.push("--tags");
40955
+ task.output = t("task.snapshot.tagPushed", { tag: "tags" });
40676
40956
  }
40677
- task.output = t("task.snapshot.pushingTag", { tag: "tags" });
40678
- await git.push("--tags");
40679
- task.output = t("task.snapshot.tagPushed", { tag: "tags" });
40680
40957
  }
40958
+ ], pipelineListrOptions).run(ctx);
40959
+ } finally {
40960
+ if (ctx.runtime.workspaceBackups?.size) {
40961
+ restoreManifests(ctx.runtime.workspaceBackups);
40962
+ ctx.runtime.workspaceBackups = undefined;
40681
40963
  }
40682
- ], pipelineListrOptions).run(ctx);
40964
+ await writeVersions(ctx, originalVersions);
40965
+ }
40683
40966
  const registries = collectRegistries(ctx.config);
40684
40967
  const parts = [];
40685
40968
  for (const registryKey of registries) {
@@ -40691,7 +40974,7 @@ async function runSnapshotPipeline(ctx, options) {
40691
40974
  parts.push(`${ui.chalk.bold(name)} on ${descriptor.label}`);
40692
40975
  }
40693
40976
  }
40694
- const versionDisplay = plan.mode !== "independent" ? ui.chalk.blueBright(plan.version) : "";
40977
+ const versionDisplay = ui.chalk.blueBright(formatVersionSummary(ctx));
40695
40978
  console.log(`
40696
40979
 
40697
40980
  \uD83D\uDCF8 ${t("task.snapshot.success", { parts: parts.join(", "), version: versionDisplay })} \uD83D\uDCF8