tegami 1.0.0-beta.0 → 1.0.0-beta.2

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.
@@ -1,5 +1,5 @@
1
- import { p as PublishPlan, t as Awaitable, w as Draft } from "../types-DnCUr2dB.js";
2
- import { n as Tegami } from "../index-B4ehnvrS.js";
1
+ import { p as PublishPlan, t as Awaitable, w as Draft } from "../types-DKeF_CDv.js";
2
+ import { n as Tegami } from "../index-CQXmwyLn.js";
3
3
  import { Command } from "commander";
4
4
 
5
5
  //#region src/cli/index.d.ts
package/dist/cli/index.js CHANGED
@@ -1,6 +1,6 @@
1
- import { r as formatNpmDistTag } from "../semver-jcIUAvbl.js";
2
- import { i as renderChangelog, n as generateFromCommits, t as changelogFilename } from "../generate-OZFKzXnu.js";
3
- import { a as isCI, n as execFailure, r as handlePluginError, t as CancelledError } from "../error-DNy8R5ue.js";
1
+ import { r as formatNpmDistTag } from "../semver-EKJ8yK5U.js";
2
+ import { i as renderChangelog, n as generateFromCommits, t as changelogFilename } from "../generate-CaCDNfVk.js";
3
+ import { a as isCI, n as execFailure, r as handlePluginError, t as CancelledError } from "../error-D3dwQnwR.js";
4
4
  import { c as updateIssueComment, i as findIssueCommentByPrefix, o as getPullRequest, t as createIssueComment } from "../api-D-jf_8xY.js";
5
5
  import { mkdir, readFile, writeFile } from "node:fs/promises";
6
6
  import path, { basename, join, relative } from "node:path";
@@ -287,12 +287,14 @@ async function buildPrPreview(context, draft, options = {}) {
287
287
  const pendingPackages = [];
288
288
  for (const pkg of context.graph.getPackages()) {
289
289
  const plan = draft.getPackageDraft(pkg.id);
290
- if (!plan || plan.bumpVersion(pkg) === pkg.version) continue;
290
+ if (!plan) continue;
291
+ const bumped = plan.bumpVersion(pkg);
292
+ if (!bumped || !pkg.version || bumped === pkg.version) continue;
291
293
  pendingPackages.push({
292
294
  name: pkg.name,
293
295
  type: plan.type ?? "—",
294
296
  from: pkg.version,
295
- to: plan.bumpVersion(pkg),
297
+ to: bumped,
296
298
  distTag: plan.npm?.distTag
297
299
  });
298
300
  }
@@ -504,8 +506,10 @@ async function versionPackages(tegami, options) {
504
506
  const lines = [];
505
507
  for (const pkg of context.graph.getPackages()) {
506
508
  const plan = draft.getPackageDraft(pkg.id);
507
- if (!plan || plan.bumpVersion(pkg) === pkg.version) continue;
508
- lines.push(`${pkg.id}: ${pkg.version} ${plan.bumpVersion(pkg)} (${plan.changelogs?.length ?? 0} changelogs)`);
509
+ if (!plan) continue;
510
+ const bumped = plan.bumpVersion(pkg);
511
+ if (!pkg.version || !bumped || bumped === pkg.version) continue;
512
+ lines.push(`${pkg.id}: ${pkg.version} → ${bumped} (${plan.changelogs?.length ?? 0} changelogs)`);
509
513
  if (plan.bumpReasons) for (const reason of plan.bumpReasons) lines.push(` - ${reason}`);
510
514
  }
511
515
  note(lines.join("\n"), "Release plan");
@@ -539,7 +543,7 @@ async function publishPackages(tegami, options) {
539
543
  const lines = [];
540
544
  let hasFailed = false;
541
545
  for (const [id, packagePlan] of plan.packages) {
542
- if (!packagePlan.updated) continue;
546
+ if (!packagePlan.preflight.shouldPublish) continue;
543
547
  const result = packagePlan.publishResult;
544
548
  const pkg = context.graph.get(id);
545
549
  if (result.type === "failed") hasFailed = true;
@@ -1,5 +1,25 @@
1
- //#region src/utils/constants.ts
1
+ //#region src/utils/common.ts
2
2
  const isCI = () => Boolean(process.env.CI);
3
+ async function somePromise(promises, fn) {
4
+ return new Promise((res, reject) => {
5
+ const n = promises.length;
6
+ if (n === 0) res(false);
7
+ let i = 0;
8
+ for (const promise of promises) {
9
+ if (promise instanceof Promise) {
10
+ promise.then((v) => {
11
+ if (fn(v)) return res(true);
12
+ i++;
13
+ if (i === n) res(false);
14
+ }).catch(reject);
15
+ continue;
16
+ }
17
+ if (fn(promise)) return res(true);
18
+ i++;
19
+ if (i === n) res(false);
20
+ }
21
+ });
22
+ }
3
23
  //#endregion
4
24
  //#region src/utils/error.ts
5
25
  var CancelledError = class extends Error {
@@ -42,4 +62,4 @@ async function handlePluginError(plugin, hookName, callback) {
42
62
  }
43
63
  }
44
64
  //#endregion
45
- export { isCI as a, isNodeError as i, execFailure as n, handlePluginError as r, CancelledError as t };
65
+ export { isCI as a, isNodeError as i, execFailure as n, somePromise as o, handlePluginError as r, CancelledError as t };
@@ -1,5 +1,5 @@
1
- import { a as maxBump, t as bumpDepth } from "./semver-jcIUAvbl.js";
2
- import { n as execFailure } from "./error-DNy8R5ue.js";
1
+ import { a as maxBump, t as bumpDepth } from "./semver-EKJ8yK5U.js";
2
+ import { n as execFailure } from "./error-D3dwQnwR.js";
3
3
  import { x } from "tinyexec";
4
4
  import z from "zod";
5
5
  import { dump } from "js-yaml";
@@ -1,4 +1,4 @@
1
- import { r as LogGenerator } from "../types-DnCUr2dB.js";
1
+ import { r as LogGenerator } from "../types-DKeF_CDv.js";
2
2
 
3
3
  //#region src/generators/simple.d.ts
4
4
  declare function simpleGenerator(): LogGenerator;
@@ -1,4 +1,4 @@
1
- import { i as formatPackageVersion } from "../semver-jcIUAvbl.js";
1
+ import { i as formatPackageVersion } from "../semver-EKJ8yK5U.js";
2
2
  //#region src/generators/simple.ts
3
3
  function simpleGenerator() {
4
4
  return { generate({ pkg, packageDraft }) {
@@ -1,4 +1,4 @@
1
- import { n as bumpVersion } from "./semver-jcIUAvbl.js";
1
+ import { n as bumpVersion } from "./semver-EKJ8yK5U.js";
2
2
  //#region src/graph.ts
3
3
  /** Package discovered in the workspace. */
4
4
  var WorkspacePackage = class {
@@ -16,6 +16,7 @@ var WorkspacePackage = class {
16
16
  /** create the initial draft. */
17
17
  initDraft() {
18
18
  return { bumpVersion(pkg) {
19
+ if (!pkg.version) return;
19
20
  return bumpVersion(pkg.version, this.type, this.prerelease);
20
21
  } };
21
22
  }
@@ -1,4 +1,4 @@
1
- import { D as ChangelogPackageConfig, O as BumpType, b as TegamiContext, f as PublishOptions, o as TegamiOptions, p as PublishPlan, w as Draft, x as PackageGraph } from "./types-DnCUr2dB.js";
1
+ import { D as ChangelogPackageConfig, O as BumpType, b as TegamiContext, f as PublishOptions, o as TegamiOptions, p as PublishPlan, w as Draft, x as PackageGraph } from "./types-DKeF_CDv.js";
2
2
 
3
3
  //#region src/changelog/generate.d.ts
4
4
  interface GenerateFromCommitsOptions {
package/dist/index.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- import { C as WorkspacePackage, E as PackageDraft, S as PackageGroup, T as DraftPolicy, a as PublishPreflight, c as TegamiPluginOption, d as PackagePublishResult, f as PublishOptions, i as PackageOptions, l as PublishLock, n as GroupOptions, o as TegamiOptions, p as PublishPlan, r as LogGenerator, s as TegamiPlugin, u as PackagePublishPlan, w as Draft, x as PackageGraph } from "./types-DnCUr2dB.js";
2
- import { i as CommitChangelog, n as Tegami, r as tegami, t as GenerateChangelogOptions } from "./index-B4ehnvrS.js";
1
+ import { C as WorkspacePackage, E as PackageDraft, S as PackageGroup, T as DraftPolicy, a as PublishPreflight, c as TegamiPluginOption, d as PackagePublishResult, f as PublishOptions, i as PackageOptions, l as PublishLock, n as GroupOptions, o as TegamiOptions, p as PublishPlan, r as LogGenerator, s as TegamiPlugin, u as PackagePublishPlan, w as Draft, x as PackageGraph } from "./types-DKeF_CDv.js";
2
+ import { i as CommitChangelog, n as Tegami, r as tegami, t as GenerateChangelogOptions } from "./index-CQXmwyLn.js";
3
3
  export { type CommitChangelog, type Draft, type DraftPolicy, GenerateChangelogOptions, type GroupOptions, type LogGenerator, type PackageDraft, type PackageGraph, type PackageGroup, type PackageOptions, type PackagePublishPlan, type PackagePublishResult, type PublishLock, type PublishOptions, type PublishPlan, type PublishPreflight, Tegami, type TegamiOptions, type TegamiPlugin, type TegamiPluginOption, type WorkspacePackage, tegami };
package/dist/index.js CHANGED
@@ -1,13 +1,13 @@
1
- import { a as maxBump } from "./semver-jcIUAvbl.js";
2
- import { n as generateFromCommits, r as changelogFrontmatterSchema } from "./generate-OZFKzXnu.js";
3
- import { r as handlePluginError } from "./error-DNy8R5ue.js";
4
- import { t as PackageGraph } from "./graph-OnX9ncdQ.js";
1
+ import { a as maxBump } from "./semver-EKJ8yK5U.js";
2
+ import { n as generateFromCommits, r as changelogFrontmatterSchema } from "./generate-CaCDNfVk.js";
3
+ import { o as somePromise, r as handlePluginError } from "./error-D3dwQnwR.js";
4
+ import { t as PackageGraph } from "./graph-gThXu8Cz.js";
5
5
  import { cargo } from "./providers/cargo.js";
6
- import { n as npm } from "./npm-Q0qvAkIu.js";
6
+ import { n as npm } from "./npm-B_43doHi.js";
7
7
  import { simpleGenerator } from "./generators/simple.js";
8
8
  import fs, { mkdir, readFile, readdir, rm, writeFile } from "node:fs/promises";
9
9
  import path, { basename, dirname, join } from "node:path";
10
- import * as semver from "semver";
10
+ import * as semver$1 from "semver";
11
11
  import z from "zod";
12
12
  import { dump, load, visit } from "js-yaml";
13
13
  import { fromMarkdown } from "mdast-util-from-markdown";
@@ -335,6 +335,7 @@ var Draft = class {
335
335
  }
336
336
  return false;
337
337
  }
338
+ /** get all changelogs, note that this includes replay-only changelogs, as long as they are in the `.tegami` folder. */
338
339
  getChangelogs() {
339
340
  return Array.from(this.changelogs.values());
340
341
  }
@@ -381,20 +382,23 @@ var Draft = class {
381
382
  /** write persistent data to publish lock */
382
383
  async writeLockFile(snapshots) {
383
384
  const lock = new PublishLock();
384
- for (const entry of this.getChangelogs()) lock.write("core:changelogs", {
385
- v: "0.0.0",
386
- filename: entry.filename,
387
- content: entry.getRawContent()
388
- });
385
+ const changelogs = /* @__PURE__ */ new Set();
389
386
  for (const pkg of this.context.graph.getPackages()) {
390
387
  const draft = this.getPackageDraft(pkg.id);
391
388
  const snapshot = snapshots.get(pkg.id);
389
+ if (!snapshot) continue;
390
+ for (const entry of draft?.changelogs ?? []) changelogs.add(entry);
392
391
  lock.write("core:packages", {
393
392
  id: pkg.id,
394
- updated: draft !== void 0 && (snapshot === void 0 || snapshot.version !== pkg.version),
393
+ updated: draft !== void 0 && snapshot.version !== pkg.version,
395
394
  changelogIds: draft?.changelogs?.map((entry) => entry.id)
396
395
  });
397
396
  }
397
+ for (const entry of changelogs) lock.write("core:changelogs", {
398
+ v: "0.0.0",
399
+ filename: entry.filename,
400
+ content: entry.getRawContent()
401
+ });
398
402
  for (const plugin of this.context.plugins) await handlePluginError(plugin, "initPublishLock", () => plugin.initPublishLock?.call(this.context, {
399
403
  lock,
400
404
  draft: this
@@ -424,7 +428,7 @@ var Draft = class {
424
428
  const isMatch = (condition) => {
425
429
  if (condition.type === "on-exit-prerelease") return graph.getByName(condition.name).some((pkg) => {
426
430
  const previous = snapshots.get(pkg.id);
427
- return previous && semver.inc(previous.version, "release") === pkg.version;
431
+ return previous?.version && semver$1.inc(previous.version, "release") === pkg.version;
428
432
  });
429
433
  return graph.getByName(condition.name).some((pkg) => pkg.version === condition.version);
430
434
  };
@@ -539,7 +543,7 @@ function resolvePublishTargets(plan) {
539
543
  const ordered = [];
540
544
  function scan(id, stack = /* @__PURE__ */ new Set()) {
541
545
  const preflight = plan.packages.get(id)?.preflight;
542
- if (!preflight || !preflight.publish) return;
546
+ if (!preflight || !preflight.shouldPublish) return;
543
547
  if (stack.has(id)) throw new Error(`circular reference of deps: ${[...stack, id].join(" -> ")}`);
544
548
  if (ordered.includes(id)) return;
545
549
  if (preflight.wait) {
@@ -592,25 +596,19 @@ async function runPublishPlan(context, plan) {
592
596
  async function runPreflights(context, plan) {
593
597
  const promises = [];
594
598
  const runPreflight = async (pkg) => {
595
- const out = { publish: true };
596
599
  for (const plugin of context.plugins) {
597
600
  const res = await handlePluginError(plugin, "publishPreflight", () => plugin.publishPreflight?.call(context, {
598
601
  pkg,
599
602
  plan
600
603
  }));
601
- if (res === void 0) continue;
602
- out.publish = res.publish;
603
- if (res.wait) {
604
- out.wait ??= [];
605
- out.wait.push(...res.wait);
606
- }
604
+ if (res) return res;
607
605
  }
608
- return out;
606
+ return { shouldPublish: false };
609
607
  };
610
608
  for (const [id, packagePlan] of plan.packages) {
611
609
  const pkg = context.graph.get(id);
612
610
  if (!packagePlan.updated) {
613
- packagePlan.preflight = { publish: false };
611
+ packagePlan.preflight = { shouldPublish: false };
614
612
  continue;
615
613
  }
616
614
  promises.push(runPreflight(pkg).then((preflight) => {
@@ -620,19 +618,12 @@ async function runPreflights(context, plan) {
620
618
  await Promise.all(promises);
621
619
  }
622
620
  async function publishPlanStatus(plan, context) {
623
- for (const pkg of plan.packages.values()) {
624
- if (!pkg.preflight) throw new Error("Should perform preflight before checking plan status.");
625
- if (pkg.preflight.publish) return "pending";
626
- }
627
- try {
628
- await Promise.all(context.plugins.map(async (plugin) => {
629
- if (await handlePluginError(plugin, "resolvePlanStatus", () => plugin.resolvePlanStatus?.call(context, { plan })) === "pending") throw "pending";
630
- }));
631
- return "success";
632
- } catch (e) {
633
- if (e === "pending") return "pending";
634
- throw e;
621
+ for (const plugin of context.plugins) {
622
+ const status = await handlePluginError(plugin, "resolvePlanStatus", () => plugin.resolvePlanStatus?.call(context, { plan }));
623
+ if (Array.isArray(status) && await somePromise(status, (v) => v === "pending")) return "pending";
624
+ if (status === "pending") return "pending";
635
625
  }
626
+ return "success";
636
627
  }
637
628
  //#endregion
638
629
  //#region src/index.ts
@@ -1,9 +1,9 @@
1
- import { i as isNodeError, n as execFailure } from "./error-DNy8R5ue.js";
2
- import { n as WorkspacePackage } from "./graph-OnX9ncdQ.js";
1
+ import { i as isNodeError, n as execFailure } from "./error-D3dwQnwR.js";
2
+ import { n as WorkspacePackage } from "./graph-gThXu8Cz.js";
3
3
  import { readFile, writeFile } from "node:fs/promises";
4
4
  import path from "node:path";
5
5
  import { x } from "tinyexec";
6
- import * as semver from "semver";
6
+ import * as semver$1 from "semver";
7
7
  import z from "zod";
8
8
  import { load } from "js-yaml";
9
9
  import { glob } from "tinyglobby";
@@ -48,7 +48,7 @@ var NpmPackage = class extends WorkspacePackage {
48
48
  return this.manifest.name;
49
49
  }
50
50
  get version() {
51
- return this.manifest.version ?? "0.0.0";
51
+ return this.manifest.version;
52
52
  }
53
53
  async write() {
54
54
  await writeFile(path.join(this.path, "package.json"), `${JSON.stringify(this.manifest, null, 2)}\n`);
@@ -139,7 +139,15 @@ function npm({ client: defaultClient, onBreakPeerDep = "set", updateLockFile = t
139
139
  },
140
140
  async publishPreflight({ pkg }) {
141
141
  if (!(pkg instanceof NpmPackage)) return;
142
- return { publish: pkg.manifest.private !== true && !await isPackagePublished(pkg) };
142
+ return { shouldPublish: pkg.version !== void 0 && pkg.manifest.private !== true };
143
+ },
144
+ resolvePlanStatus({ plan }) {
145
+ return Array.from(plan.packages, async ([id, { preflight }]) => {
146
+ if (!preflight.shouldPublish) return;
147
+ const pkg = this.graph.get(id);
148
+ if (!(pkg instanceof NpmPackage) || !pkg.version) return;
149
+ if (!await isPackagePublished(pkg.name, pkg.version, pkg.manifest.publishConfig?.registry)) return "pending";
150
+ });
143
151
  },
144
152
  initPublishLock({ lock, draft }) {
145
153
  for (const [id, pkg] of draft.getPackageDrafts()) {
@@ -174,8 +182,8 @@ function npm({ client: defaultClient, onBreakPeerDep = "set", updateLockFile = t
174
182
  const writes = [];
175
183
  for (const pkg of graph.getPackages()) {
176
184
  if (!(pkg instanceof NpmPackage)) continue;
177
- const plan = draft.getPackageDraft(pkg.id);
178
- if (plan) pkg.manifest.version = plan.bumpVersion(pkg);
185
+ const bumped = draft.getPackageDraft(pkg.id)?.bumpVersion(pkg);
186
+ if (bumped) pkg.manifest.version = bumped;
179
187
  }
180
188
  for (const pkg of graph.getPackages()) {
181
189
  if (!(pkg instanceof NpmPackage)) continue;
@@ -185,8 +193,8 @@ function npm({ client: defaultClient, onBreakPeerDep = "set", updateLockFile = t
185
193
  for (const [k, v] of Object.entries(dependencies)) {
186
194
  const spec = parseDependencySpec(this, pkg, k, v);
187
195
  if (!spec?.linked || spec.protocol === "workspace" || spec.protocol === "file") continue;
188
- if (!semver.validRange(spec.range)) continue;
189
- if (semver.satisfies(spec.linked.version, spec.range)) continue;
196
+ if (!semver$1.validRange(spec.range)) continue;
197
+ if (!spec.linked.version || semver$1.satisfies(spec.linked.version, spec.range)) continue;
190
198
  let updatedRange;
191
199
  const isPeer = field === "peerDependencies";
192
200
  if (isPeer && onBreakPeerDep === "ignore") continue;
@@ -224,11 +232,11 @@ function depsPolicy(context, getBumpDepType) {
224
232
  case "":
225
233
  case "*": return true;
226
234
  case "^":
227
- case "~": return !semver.satisfies(target, `${spec.range}${spec.linked.version}`);
235
+ case "~": return !semver$1.satisfies(target, `${spec.range}${spec.linked.version}`);
228
236
  }
229
237
  if (spec.linked && spec.protocol === "file") return true;
230
- if (spec.protocol === "file" || !semver.validRange(spec.range)) return false;
231
- return !semver.satisfies(target, spec.range);
238
+ if (spec.protocol === "file" || !semver$1.validRange(spec.range)) return false;
239
+ return !semver$1.satisfies(target, spec.range);
232
240
  }
233
241
  return {
234
242
  id: "npm:deps",
@@ -244,7 +252,8 @@ function depsPolicy(context, getBumpDepType) {
244
252
  const spec = parseDependencySpec(context, dependent, k, v);
245
253
  if (!spec || spec.linked !== pkg) continue;
246
254
  if (group?.options.syncBump && graph.getPackageGroup(dependent.id) === group) continue;
247
- if (!needsUpdate(spec, plan.bumpVersion(pkg))) continue;
255
+ const bumped = plan.bumpVersion(pkg);
256
+ if (!bumped || !needsUpdate(spec, bumped)) continue;
248
257
  const bumpType = getBumpDepType({
249
258
  kind: field,
250
259
  dependent,
@@ -263,6 +272,7 @@ function depsPolicy(context, getBumpDepType) {
263
272
  };
264
273
  }
265
274
  async function publish(client, pkg, distTag) {
275
+ if (!pkg.version || await isPackagePublished(pkg.name, pkg.version, pkg.manifest.publishConfig?.registry)) return { type: "skipped" };
266
276
  if (client === "bun") {
267
277
  for (const script of [
268
278
  "prepublishOnly",
@@ -312,12 +322,11 @@ async function publish(client, pkg, distTag) {
312
322
  };
313
323
  return { type: "published" };
314
324
  }
315
- async function isPackagePublished(pkg) {
316
- const registry = pkg.manifest.publishConfig?.registry ?? "https://registry.npmjs.org";
325
+ async function isPackagePublished(name, version, registry = "https://registry.npmjs.org") {
317
326
  const base = registry.replace(/\/$/, "");
318
- const response = await fetch(`${base}/${pkg.name}/${pkg.version}`, { headers: { Accept: "application/json" } });
327
+ const response = await fetch(`${base}/${name}/${version}`, { headers: { Accept: "application/json" } });
319
328
  if (response.status === 404) return false;
320
- if (!response.ok) throw new Error(`Unable to validate ${pkg.name}@${pkg.version} against the npm registry${registry ? ` "${registry}"` : ""}.`);
329
+ if (!response.ok) throw new Error(`Unable to validate ${name}@${version} against the npm registry${registry ? ` "${registry}"` : ""}.`);
321
330
  return true;
322
331
  }
323
332
  async function discoverNpmPackages(cwd, add) {
@@ -1,4 +1,4 @@
1
- import { s as TegamiPlugin } from "../types-DnCUr2dB.js";
1
+ import { s as TegamiPlugin } from "../types-DKeF_CDv.js";
2
2
 
3
3
  //#region src/plugins/git.d.ts
4
4
  interface GitPluginOptions {
@@ -1,4 +1,4 @@
1
- import { a as isCI, n as execFailure } from "../error-DNy8R5ue.js";
1
+ import { a as isCI, n as execFailure } from "../error-D3dwQnwR.js";
2
2
  import { x } from "tinyexec";
3
3
  //#region src/plugins/git.ts
4
4
  /**
@@ -9,11 +9,12 @@ import { x } from "tinyexec";
9
9
  */
10
10
  function git(options = {}) {
11
11
  const { createTags = true, pushTags = isCI() } = options;
12
- function getPendingTags(plan, filterPackage) {
12
+ function getPendingTags(plan) {
13
13
  const pendingTags = /* @__PURE__ */ new Set();
14
14
  if ((plan.options.dryRun ?? false) || !createTags) return pendingTags;
15
15
  for (const pkg of plan.packages.values()) {
16
- if (filterPackage && !filterPackage(pkg)) continue;
16
+ if (!pkg.preflight.shouldPublish) continue;
17
+ if (pkg.publishResult && pkg.publishResult.type === "failed") continue;
17
18
  const tag = pkg.git?.tag;
18
19
  if (tag) pendingTags.add(tag);
19
20
  }
@@ -42,34 +43,29 @@ function git(options = {}) {
42
43
  const { graph } = this;
43
44
  for (const [id, packagePlan] of plan.packages) {
44
45
  const pkg = graph.get(id);
45
- const group = pkg && graph.getPackageGroup(pkg.id);
46
- let tag;
47
- if (group?.options.syncGitTag) tag = `${group.name}@${pkg.version}`;
48
- else tag = `${pkg.name}@${pkg.version}`;
49
- packagePlan.git = { tag };
46
+ const group = graph.getPackageGroup(pkg.id);
47
+ packagePlan.git ??= {};
48
+ if (group?.options.syncGitTag && pkg.version) packagePlan.git.tag = `${group.name}@${pkg.version}`;
49
+ else if (pkg.version) packagePlan.git.tag = `${pkg.name}@${pkg.version}`;
50
50
  }
51
51
  },
52
52
  async resolvePlanStatus({ plan }) {
53
- const pendingTags = getPendingTags(plan, (pkg) => pkg.preflight.publish);
54
- if (pendingTags.size === 0) return;
55
- try {
56
- await Promise.all(Array.from(pendingTags, async (tag) => {
57
- if (!await gitTagExists(this.cwd, tag)) throw "pending";
58
- }));
59
- } catch (e) {
60
- if (e === "pending") return "pending";
61
- throw e;
62
- }
53
+ const pendingTags = getPendingTags(plan);
54
+ return Array.from(pendingTags, async (tag) => {
55
+ if (!await gitTagExists(this.cwd, tag)) return "pending";
56
+ });
63
57
  },
64
58
  async afterPublishAll({ plan }) {
65
59
  const { cwd } = this;
66
60
  const createdTags = [];
67
- const pendingTags = getPendingTags(plan, (pkg) => pkg.publishResult.type === "published");
61
+ const pendingTags = getPendingTags(plan);
68
62
  if (pendingTags.size === 0) return;
69
63
  await Promise.all(Array.from(pendingTags, async (tag) => {
70
- if (await gitTagExists(cwd, tag)) return;
71
64
  const gitOut = await x("git", ["tag", tag], { nodeOptions: { cwd } });
72
- if (gitOut.exitCode !== 0) throw execFailure(`Failed to create Git tag "${tag}" for release`, gitOut);
65
+ if (gitOut.exitCode !== 0) {
66
+ if (/already exists/i.test(`${gitOut.stdout}\n${gitOut.stderr}`)) return;
67
+ throw execFailure(`Failed to create Git tag "${tag}" for release`, gitOut);
68
+ }
73
69
  createdTags.push(tag);
74
70
  }));
75
71
  if (pushTags && createdTags.length > 0) {
@@ -1,4 +1,4 @@
1
- import { C as WorkspacePackage, b as TegamiContext, p as PublishPlan, s as TegamiPlugin, t as Awaitable, w as Draft } from "../types-DnCUr2dB.js";
1
+ import { C as WorkspacePackage, b as TegamiContext, p as PublishPlan, s as TegamiPlugin, t as Awaitable, w as Draft } from "../types-DKeF_CDv.js";
2
2
  import { GitPluginOptions } from "./git.js";
3
3
 
4
4
  //#region src/plugins/github.d.ts
@@ -1,10 +1,10 @@
1
- import { i as formatPackageVersion, r as formatNpmDistTag } from "../semver-jcIUAvbl.js";
2
- import { a as isCI, n as execFailure } from "../error-DNy8R5ue.js";
1
+ import { i as formatPackageVersion, r as formatNpmDistTag } from "../semver-EKJ8yK5U.js";
2
+ import { a as isCI, n as execFailure } from "../error-D3dwQnwR.js";
3
3
  import { a as findOpenPullRequest, l as updatePullRequest, n as createPullRequest, r as createRelease, s as releaseExistsByTag } from "../api-D-jf_8xY.js";
4
4
  import { git } from "./git.js";
5
5
  import { join, relative } from "node:path";
6
6
  import { x } from "tinyexec";
7
- import { prerelease } from "semver";
7
+ import semver from "semver";
8
8
  //#region src/plugins/github.ts
9
9
  /** Create GitHub releases for successfully published packages after the whole plan succeeds. */
10
10
  function github(options = {}) {
@@ -21,16 +21,23 @@ function github(options = {}) {
21
21
  }
22
22
  function defaultVersionPRBody(draft, context) {
23
23
  const packageLines = [];
24
- for (const pkg of context.graph.getPackages()) {
25
- const packageDraft = draft.getPackageDraft(pkg.id);
26
- if (!packageDraft) continue;
27
- const originalVersion = cliOriginalPackageVersions.get(pkg.id) ?? pkg.version;
28
- if (originalVersion === pkg.version) continue;
24
+ const changesets = /* @__PURE__ */ new Map();
25
+ for (const [id, packageDraft] of draft.getPackageDrafts()) {
26
+ const pkg = context.graph.get(id);
27
+ if (!pkg) continue;
28
+ for (const entry of packageDraft.changelogs ?? []) {
29
+ const list = changesets.get(entry);
30
+ if (list) list.push(pkg);
31
+ else changesets.set(entry, [pkg]);
32
+ }
33
+ const originalVersion = cliOriginalPackageVersions.get(pkg.id);
34
+ if (!originalVersion || originalVersion === pkg.version) continue;
29
35
  packageLines.push(`| \`${pkg.name}\` | \`${originalVersion}\` | \`${pkg.version}\`${formatNpmDistTag(packageDraft.npm?.distTag)} |`);
30
36
  }
31
37
  const changelogLines = [];
32
- for (const entry of draft.getChangelogs()) {
38
+ for (const [entry, linkedPackages] of changesets) {
33
39
  changelogLines.push(`### ${entry.subject ?? `\`${entry.filename}\``}`, "");
40
+ changelogLines.push("<details>", `<summary>Show Bumped Packages (${linkedPackages.length})</summary>`, "", ...linkedPackages.map((pkg) => `- \`${pkg.id}\``), "", "</details>", "");
34
41
  for (const section of entry.sections) {
35
42
  changelogLines.push(`#### ${section.title}`, "");
36
43
  if (section.content) changelogLines.push(section.content);
@@ -60,42 +67,27 @@ function github(options = {}) {
60
67
  const { repo, token } = this.github;
61
68
  if (!repo || !token || releaseOptions === false) return;
62
69
  const requiredTags = /* @__PURE__ */ new Set();
63
- for (const pkg of plan.packages.values()) if (pkg.preflight.publish && pkg.git) requiredTags.add(pkg.git.tag);
64
- try {
65
- await Promise.all(Array.from(requiredTags, async (tag) => {
66
- if (!await releaseExistsByTag(repo, tag, token)) throw "pending";
67
- }));
68
- } catch (e) {
69
- if (e === "pending") return "pending";
70
- throw e;
71
- }
70
+ for (const pkg of plan.packages.values()) if (pkg.preflight.shouldPublish && pkg.git?.tag) requiredTags.add(pkg.git.tag);
71
+ return Array.from(requiredTags, async (tag) => {
72
+ if (!await releaseExistsByTag(repo, tag, token)) return "pending";
73
+ });
72
74
  },
73
75
  async afterPublishAll({ plan }) {
74
76
  const { repo, token } = this.github;
75
77
  if (!repo || !token || releaseOptions === false) return;
76
78
  const { eager = false, create, createGrouped } = releaseOptions === true ? {} : releaseOptions;
77
79
  const groups = /* @__PURE__ */ new Map();
78
- for (const [id, packagePlan] of plan.packages) {
80
+ for (const [id, { preflight, publishResult, git }] of plan.packages) {
81
+ if (!eager && publishResult.type === "failed") return;
82
+ const tag = git?.tag;
83
+ if (!tag || !preflight.shouldPublish) continue;
79
84
  const pkg = this.graph.get(id);
80
- if (!eager && packagePlan.publishResult.type === "failed") return;
81
- const tag = packagePlan.git?.tag;
82
- if (!tag) continue;
83
85
  const group = groups.get(tag);
84
86
  if (group) group.push(pkg);
85
87
  else groups.set(tag, [pkg]);
86
88
  }
87
89
  await Promise.all(Array.from(groups, async ([tag, packages]) => {
88
- let hasFailed = false;
89
- let hasPublished = false;
90
- for (const member of packages) switch (plan.packages.get(member.id).publishResult.type) {
91
- case "published":
92
- hasPublished = true;
93
- break;
94
- case "failed":
95
- hasFailed = true;
96
- break;
97
- }
98
- if (hasFailed || !hasPublished) return;
90
+ for (const member of packages) if (plan.packages.get(member.id).publishResult.type === "failed") return;
99
91
  if (await releaseExistsByTag(repo, tag, token)) return;
100
92
  let release;
101
93
  if (packages.length > 1) {
@@ -107,7 +99,7 @@ function github(options = {}) {
107
99
  release = {
108
100
  title: overrides.title ?? tag,
109
101
  notes: overrides.notes ?? await defaultGroupedNotes(getRenderer(this), plan, packages),
110
- prerelease: overrides.prerelease ?? packages.some((pkg) => prerelease(pkg.version) !== null)
102
+ prerelease: overrides.prerelease ?? packages.some((pkg) => pkg.version && semver.prerelease(pkg.version))
111
103
  };
112
104
  } else {
113
105
  const pkg = packages[0];
@@ -120,7 +112,7 @@ function github(options = {}) {
120
112
  release = {
121
113
  title: overrides.title ?? formatPackageVersion(pkg.name, pkg.version, packagePlan?.npm?.distTag),
122
114
  notes: overrides.notes ?? await defaultNotes(getRenderer(this), pkg, packagePlan),
123
- prerelease: overrides.prerelease ?? prerelease(pkg.version) !== null
115
+ prerelease: overrides.prerelease ?? (pkg.version !== void 0 && semver.prerelease(pkg.version) !== null)
124
116
  };
125
117
  }
126
118
  await createRelease(repo, {
@@ -1,4 +1,4 @@
1
- import { C as WorkspacePackage, O as BumpType, s as TegamiPlugin } from "../types-DnCUr2dB.js";
1
+ import { C as WorkspacePackage, O as BumpType, s as TegamiPlugin } from "../types-DKeF_CDv.js";
2
2
 
3
3
  //#region src/plugins/go.d.ts
4
4
  interface GoModFile {
@@ -1,8 +1,8 @@
1
- import { i as isNodeError, n as execFailure } from "../error-DNy8R5ue.js";
2
- import { n as WorkspacePackage } from "../graph-OnX9ncdQ.js";
1
+ import { i as isNodeError, n as execFailure } from "../error-D3dwQnwR.js";
2
+ import { n as WorkspacePackage } from "../graph-gThXu8Cz.js";
3
3
  import { relative, resolve } from "node:path";
4
4
  import { x } from "tinyexec";
5
- import * as semver from "semver";
5
+ import * as semver$1 from "semver";
6
6
  import z from "zod";
7
7
  //#region src/plugins/go.ts
8
8
  const goWorkJsonSchema = z.object({ Use: z.array(z.object({
@@ -91,15 +91,15 @@ function go({ updateLockFile = true, bumpDep: getBumpDepType } = {}) {
91
91
  const writes = [];
92
92
  for (const pkg of graph.getPackages()) {
93
93
  if (!(pkg instanceof GoPackage)) continue;
94
- const plan = draft.getPackageDraft(pkg.id);
95
- if (plan) pkg.setVersion(plan.bumpVersion(pkg));
94
+ const bumped = draft.getPackageDraft(pkg.id)?.bumpVersion(pkg);
95
+ if (bumped) pkg.setVersion(bumped);
96
96
  }
97
97
  for (const pkg of graph.getPackages()) {
98
98
  if (!(pkg instanceof GoPackage)) continue;
99
99
  for (const [moduleName, requireVersion] of pkg.mod.requires) {
100
100
  const linked = graph.get(`go:${moduleName}`);
101
101
  if (!linked || !(linked instanceof GoPackage)) continue;
102
- if (semver.satisfies(linked.version, stripGoVersion(requireVersion))) continue;
102
+ if (semver$1.satisfies(linked.version, stripGoVersion(requireVersion))) continue;
103
103
  pkg.setRequire(moduleName, linked.version);
104
104
  }
105
105
  writes.push(pkg.write());
@@ -129,7 +129,8 @@ function go({ updateLockFile = true, bumpDep: getBumpDepType } = {}) {
129
129
  for (const [id, packagePlan] of plan.packages) {
130
130
  const pkg = this.graph.get(id);
131
131
  if (!(pkg instanceof GoPackage)) continue;
132
- packagePlan.git = { tag: formatGoTag(this.cwd, pkg.path, pkg.version) };
132
+ packagePlan.git ??= {};
133
+ packagePlan.git.tag = formatGoTag(this.cwd, pkg.path, pkg.version);
133
134
  }
134
135
  },
135
136
  async publishPreflight({ pkg }) {
@@ -146,13 +147,21 @@ function go({ updateLockFile = true, bumpDep: getBumpDepType } = {}) {
146
147
  wait.push(linked.id);
147
148
  }
148
149
  return {
149
- publish: !await isModulePublished(pkg.name, pkg.version),
150
+ shouldPublish: true,
150
151
  wait
151
152
  };
152
153
  },
154
+ resolvePlanStatus({ plan }) {
155
+ return Array.from(plan.packages, async ([id, { preflight }]) => {
156
+ if (!preflight.shouldPublish) return;
157
+ const pkg = this.graph.get(id);
158
+ if (!(pkg instanceof GoPackage)) return;
159
+ if (!await isModulePublished(pkg.name, pkg.version)) return "pending";
160
+ });
161
+ },
153
162
  async publish({ pkg }) {
154
163
  if (!(pkg instanceof GoPackage)) return;
155
- return { type: "published" };
164
+ return { type: await isModulePublished(pkg.name, pkg.version) ? "skipped" : "published" };
156
165
  },
157
166
  cli: { async draftApplied() {
158
167
  if (!active || !updateLockFile) return;
@@ -180,7 +189,8 @@ function depsPolicy({ graph }, getBumpDepType = () => "patch") {
180
189
  for (const [moduleName, requireVersion] of dependent.mod.requires) {
181
190
  if (pkg.id !== `go:${moduleName}`) continue;
182
191
  if (group?.options.syncBump && graph.getPackageGroup(dependent.id) === group) continue;
183
- if (semver.satisfies(plan.bumpVersion(pkg), stripGoVersion(requireVersion))) continue;
192
+ const bumped = plan.bumpVersion(pkg);
193
+ if (!bumped || semver$1.satisfies(bumped, stripGoVersion(requireVersion))) continue;
184
194
  const bumpType = getBumpDepType?.({
185
195
  name: pkg.name,
186
196
  dependent,
@@ -267,7 +277,7 @@ async function readLatestVersion(cwd, modulePath) {
267
277
  }
268
278
  function parseTagVersion(tag) {
269
279
  const version = stripGoVersion(tag.slice(tag.lastIndexOf("/") + 1));
270
- if (semver.valid(version)) return version;
280
+ if (semver$1.valid(version)) return version;
271
281
  }
272
282
  function formatGoTag(cwd, modulePath, version) {
273
283
  const relativeDir = relative(cwd, modulePath).replaceAll("\\", "/");
@@ -1,2 +1,2 @@
1
- import { g as cargo, h as CargoPluginOptions, m as CargoPackage } from "../types-DnCUr2dB.js";
1
+ import { g as cargo, h as CargoPluginOptions, m as CargoPackage } from "../types-DKeF_CDv.js";
2
2
  export { CargoPackage, CargoPluginOptions, cargo };
@@ -1,9 +1,9 @@
1
- import { i as isNodeError, n as execFailure } from "../error-DNy8R5ue.js";
2
- import { n as WorkspacePackage } from "../graph-OnX9ncdQ.js";
1
+ import { i as isNodeError, n as execFailure } from "../error-D3dwQnwR.js";
2
+ import { n as WorkspacePackage } from "../graph-gThXu8Cz.js";
3
3
  import { readFile, writeFile } from "node:fs/promises";
4
4
  import { join, normalize } from "node:path";
5
5
  import { x } from "tinyexec";
6
- import * as semver from "semver";
6
+ import * as semver$1 from "semver";
7
7
  import initToml, { edit, parse as parse$1 } from "@rainbowatcher/toml-edit-js";
8
8
  import { glob } from "tinyglobby";
9
9
  //#region src/providers/cargo.ts
@@ -29,7 +29,7 @@ var CargoPackage = class extends WorkspacePackage {
29
29
  return this.packageInfo.name;
30
30
  }
31
31
  get version() {
32
- return stringValue(this.packageInfo.version) ?? this.workspaceVersion ?? "0.0.0";
32
+ return stringValue(this.packageInfo.version) ?? this.workspaceVersion;
33
33
  }
34
34
  setVersion(version) {
35
35
  this.packageInfo.version = version;
@@ -76,17 +76,28 @@ function cargo({ updateLockFile = true, bumpDep: getBumpDepType } = {}) {
76
76
  wait.push(id);
77
77
  }
78
78
  return {
79
- publish: pkg.packageInfo.publish !== false && !await isPackagePublished(pkg.name, pkg.version),
79
+ shouldPublish: pkg.version !== void 0 && pkg.packageInfo.publish !== false,
80
80
  wait
81
81
  };
82
82
  },
83
+ resolvePlanStatus({ plan }) {
84
+ return Array.from(plan.packages, async ([id, { preflight }]) => {
85
+ if (!preflight.shouldPublish) return;
86
+ const pkg = this.graph.get(id);
87
+ if (!(pkg instanceof CargoPackage) || !pkg.version) return;
88
+ if (!await isPackagePublished(pkg.name, pkg.version)) return "pending";
89
+ });
90
+ },
83
91
  async publish({ pkg }) {
84
92
  if (!(pkg instanceof CargoPackage)) return;
85
93
  const result = await x("cargo", ["publish"], { nodeOptions: { cwd: pkg.path } });
86
- if (result.exitCode !== 0) return {
87
- type: "failed",
88
- error: execFailure(`Failed to publish ${pkg.name}@${pkg.version}.`, result).message
89
- };
94
+ if (result.exitCode !== 0) {
95
+ if (/already exists|already published/i.test(`${result.stdout}\n${result.stderr}`)) return { type: "skipped" };
96
+ return {
97
+ type: "failed",
98
+ error: execFailure(`Failed to publish ${pkg.name}@${pkg.version}.`, result).message
99
+ };
100
+ }
90
101
  return { type: "published" };
91
102
  },
92
103
  async applyDraft(draft) {
@@ -95,18 +106,18 @@ function cargo({ updateLockFile = true, bumpDep: getBumpDepType } = {}) {
95
106
  const writes = [];
96
107
  for (const pkg of graph.getPackages()) {
97
108
  if (!(pkg instanceof CargoPackage)) continue;
98
- const plan = draft.getPackageDraft(pkg.id);
99
- if (plan) pkg.setVersion(plan.bumpVersion(pkg));
109
+ const bumped = draft.getPackageDraft(pkg.id)?.bumpVersion(pkg);
110
+ if (bumped) pkg.setVersion(bumped);
100
111
  }
101
112
  for (const pkg of graph.getPackages()) {
102
113
  if (!(pkg instanceof CargoPackage)) continue;
103
114
  for (const { table, path: tablePath } of dependencyTables(pkg.manifest, "")) for (const [rawName, rawSpec] of Object.entries(table)) {
104
115
  const spec = parseSpec(rawSpec);
105
- if (!spec || !semver.validRange(spec.version)) continue;
116
+ if (!spec || !semver$1.validRange(spec.version)) continue;
106
117
  const packageName = spec.package ?? rawName;
107
118
  const linked = graph.get(`cargo:${packageName}`);
108
119
  if (!linked || !(linked instanceof CargoPackage)) continue;
109
- if (semver.satisfies(linked.version, spec.version)) continue;
120
+ if (!linked.version || semver$1.satisfies(linked.version, spec.version)) continue;
110
121
  let updatedRange;
111
122
  if (spec.version.startsWith("^")) updatedRange = `^${linked.version}`;
112
123
  else if (spec.version.startsWith("~")) updatedRange = `~${linked.version}`;
@@ -141,10 +152,11 @@ function depsPolicy({ graph }, getBumpDepType = ({ kind }) => {
141
152
  if (!(dependent instanceof CargoPackage)) continue;
142
153
  for (const { table, kind } of dependencyTables(dependent.manifest, "")) for (const [rawName, rawSpec] of Object.entries(table)) {
143
154
  const spec = parseSpec(rawSpec);
144
- if (!spec || !semver.validRange(spec.version)) continue;
155
+ if (!spec || !semver$1.validRange(spec.version)) continue;
145
156
  if (pkg.id !== `cargo:${spec.package ?? rawName}`) continue;
146
157
  if (group?.options.syncBump && graph.getPackageGroup(dependent.id) === group) continue;
147
- if (semver.satisfies(plan.bumpVersion(pkg), spec.version)) continue;
158
+ const bumped = plan.bumpVersion(pkg);
159
+ if (!bumped || semver$1.satisfies(bumped, spec.version)) continue;
148
160
  const bumpType = getBumpDepType({
149
161
  kind,
150
162
  dependent,
@@ -1,2 +1,2 @@
1
- import { _ as NpmPackage, v as NpmPluginOptions, y as npm } from "../types-DnCUr2dB.js";
1
+ import { _ as NpmPackage, v as NpmPluginOptions, y as npm } from "../types-DKeF_CDv.js";
2
2
  export { NpmPackage, NpmPluginOptions, npm };
@@ -1,2 +1,2 @@
1
- import { n as npm, t as NpmPackage } from "../npm-Q0qvAkIu.js";
1
+ import { n as npm, t as NpmPackage } from "../npm-B_43doHi.js";
2
2
  export { NpmPackage, npm };
@@ -4,7 +4,10 @@ function formatNpmDistTag(distTag) {
4
4
  return distTag && distTag !== "latest" ? ` (${distTag})` : "";
5
5
  }
6
6
  function formatPackageVersion(name, version, distTag) {
7
- return `${name}@${version}${formatNpmDistTag(distTag)}`;
7
+ let out = name;
8
+ if (version) out += `@${version}`;
9
+ out += formatNpmDistTag(distTag);
10
+ return out;
8
11
  }
9
12
  const WEIGHTS = {
10
13
  major: 3,
@@ -42,8 +42,8 @@ interface PackageDraft {
42
42
  npm?: {
43
43
  /** npm dist-tag used when publishing. */distTag?: string;
44
44
  };
45
- /** get the bumped version of a package */
46
- bumpVersion: (pkg: WorkspacePackage) => string;
45
+ /** get the bumped version of a package, return `undefined` if the package doesn't have a `version` field */
46
+ bumpVersion: (pkg: WorkspacePackage) => string | undefined;
47
47
  }
48
48
  /** a draft describes all operations to perform before the actual publishing, such as version bumps. */
49
49
  declare class Draft {
@@ -67,6 +67,7 @@ declare class Draft {
67
67
  dispatchPackage(pkg: WorkspacePackage, dispatch: (draft: PackageDraft) => void, onUpdate?: (draft: PackageDraft) => void): PackageDraft;
68
68
  getOrInitPackage(pkg: WorkspacePackage): PackageDraft;
69
69
  hasPending(): boolean;
70
+ /** get all changelogs, note that this includes replay-only changelogs, as long as they are in the `.tegami` folder. */
70
71
  getChangelogs(): ChangelogEntry[];
71
72
  getChangelog(id: string): ChangelogEntry | undefined;
72
73
  addChangelog(entry: ChangelogEntry): void;
@@ -99,7 +100,7 @@ declare abstract class WorkspacePackage {
99
100
  /** absolute path */
100
101
  abstract readonly path: string;
101
102
  abstract readonly manager: string;
102
- abstract readonly version: string;
103
+ abstract readonly version: string | undefined;
103
104
  get id(): string;
104
105
  private opts;
105
106
  /** note: this will only be available after package graph is resolved */
@@ -189,7 +190,7 @@ declare class NpmPackage extends WorkspacePackage {
189
190
  readonly manager = "npm";
190
191
  constructor(path: string, manifest: PackageManifest);
191
192
  get name(): string;
192
- get version(): string;
193
+ get version(): string | undefined;
193
194
  write(): Promise<void>;
194
195
  initDraft(): PackageDraft;
195
196
  configureDraft(draft: PackageDraft, group?: PackageGroup): void;
@@ -258,7 +259,7 @@ declare class CargoPackage extends WorkspacePackage {
258
259
  readonly manager = "cargo";
259
260
  constructor(path: string, manifest: TomlTable, content: string, workspaceManifest?: TomlTable | undefined);
260
261
  get name(): string;
261
- get version(): string;
262
+ get version(): string | undefined;
262
263
  setVersion(version: string): void;
263
264
  write(): Promise<void>;
264
265
  patch(path: string, value: unknown): void;
@@ -301,7 +302,7 @@ interface PackagePublishPlan {
301
302
  updated: boolean;
302
303
  /** generated by Git plugin */
303
304
  git?: {
304
- /** the associated Git tag of package */tag: string;
305
+ /** the associated Git tag of package */tag?: string;
305
306
  };
306
307
  /** generated by npm plugin */
307
308
  npm?: {
@@ -419,7 +420,11 @@ interface TegamiPlugin {
419
420
  lock: PublishLock;
420
421
  plan: PublishPlan;
421
422
  }): Awaitable<void>;
422
- /** Collect data before publishing a package, will be merged if multiple plugins return preflight data for this package. */
423
+ /**
424
+ * Collect data before publishing a package.
425
+ *
426
+ * If multiple plugins return preflight data for the same package, only the first plugin will be considered.
427
+ */
423
428
  publishPreflight?(this: TegamiContext, opts: {
424
429
  pkg: WorkspacePackage;
425
430
  plan: PublishPlan;
@@ -436,7 +441,7 @@ interface TegamiPlugin {
436
441
  */
437
442
  resolvePlanStatus?(this: TegamiContext, opts: {
438
443
  plan: PublishPlan;
439
- }): Awaitable<"success" | "pending" | undefined | void>;
444
+ }): Awaitable<"success" | "pending" | undefined | void | Awaitable<"success" | "pending" | undefined>[]>;
440
445
  /** Called before a package will be published, return `false` to prevent from publishing. */
441
446
  willPublish?(this: TegamiContext, opts: {
442
447
  pkg: WorkspacePackage;
@@ -459,8 +464,12 @@ interface TegamiPlugin {
459
464
  }
460
465
  type Awaitable<T> = T | Promise<T>;
461
466
  interface PublishPreflight {
462
- /** if the package should be published. */
463
- publish: boolean;
467
+ /**
468
+ * Whether the package should be published, the state **must not** be changed across different runs.
469
+ *
470
+ * To note if the package is already published, hook `resolvePlanStatus` on plugins, or skip at publish-time.
471
+ */
472
+ shouldPublish: boolean;
464
473
  /**
465
474
  * Package ids that must be published before this one, this will automatically disallow circular dependency.
466
475
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tegami",
3
- "version": "1.0.0-beta.0",
3
+ "version": "1.0.0-beta.2",
4
4
  "description": "Utility for package versioning & publish",
5
5
  "license": "MIT",
6
6
  "author": "Fuma Nama",