tegami 1.2.3 → 1.2.5

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.
@@ -44,7 +44,7 @@ declare namespace TagBase {
44
44
  * @template Exclusive Whether this tag conflicts with others
45
45
  * @template Schema Additional JSON Schema properties to output
46
46
  */
47
- interface IProps<Target extends "boolean" | "bigint" | "number" | "string" | "array" | "object", Kind extends string, Value extends boolean | bigint | number | string | undefined, Validate extends string | { [key in Target]?: string }, Exclusive extends boolean | string[], Schema extends object | undefined> {
47
+ interface IProps<Target extends "boolean" | "bigint" | "number" | "string" | "array" | "object", Kind extends string, Value extends boolean | bigint | number | string | undefined, Validate extends string | { [key in Target]?: string; }, Exclusive extends boolean | string[], Schema extends object | undefined> {
48
48
  /**
49
49
  * Target primitive type(s) this tag applies to.
50
50
  *
@@ -170,6 +170,17 @@ interface ChangelogEntry {
170
170
  virtual?: boolean;
171
171
  getRawContent: () => string;
172
172
  }
173
+ type ReplayCondition = {
174
+ on: "version";
175
+ name: string;
176
+ version: string;
177
+ } | {
178
+ on: "exit-prerelease";
179
+ name: string;
180
+ } | {
181
+ on: "enter-prerelease";
182
+ name: string;
183
+ };
173
184
  //#endregion
174
185
  //#region src/plans/draft.d.ts
175
186
  interface PackageDraft {
@@ -178,10 +189,11 @@ interface PackageDraft {
178
189
  bumpReasons?: Set<string>;
179
190
  changelogs?: ChangelogEntry[];
180
191
  npm?: {
181
- /** npm dist-tag used when publishing. */distTag?: string;
192
+ /** npm dist-tag used when publishing. */
193
+ distTag?: string;
182
194
  };
183
195
  /** get the bumped version of a package, return `undefined` if the package doesn't have a `version` field */
184
- bumpVersion: (pkg: WorkspacePackage$1) => string | undefined;
196
+ bumpVersion: (pkg: WorkspacePackage) => string | undefined;
185
197
  }
186
198
  /** a draft describes all operations to perform before the actual publishing, such as version bumps. */
187
199
  declare class Draft {
@@ -195,15 +207,12 @@ declare class Draft {
195
207
  constructor(context: TegamiContext);
196
208
  getPackageDrafts(): Map<string, PackageDraft>;
197
209
  getPackageDraft(id: string): PackageDraft | undefined;
198
- bumpPackage(pkg: WorkspacePackage$1, {
199
- type,
200
- reason
201
- }: {
210
+ bumpPackage(pkg: WorkspacePackage, { type, reason }: {
202
211
  type: BumpType;
203
212
  reason?: string;
204
213
  }): PackageDraft;
205
- dispatchPackage(pkg: WorkspacePackage$1, dispatch: (draft: PackageDraft) => void, onUpdate?: (draft: PackageDraft) => void): PackageDraft;
206
- getOrInitPackage(pkg: WorkspacePackage$1): PackageDraft;
214
+ dispatchPackage(pkg: WorkspacePackage, dispatch: (draft: PackageDraft) => void, onUpdate?: (draft: PackageDraft) => void): PackageDraft;
215
+ getOrInitPackage(pkg: WorkspacePackage): PackageDraft;
207
216
  hasPending(): boolean;
208
217
  /** get all changelogs, note that this includes replay-only changelogs, as long as they are in the `.tegami` folder. */
209
218
  getChangelogs(): ChangelogEntry[];
@@ -227,13 +236,13 @@ interface DraftPolicy {
227
236
  id: string;
228
237
  onUpdate?: (this: Draft, opts: {
229
238
  packageDraft: PackageDraft;
230
- pkg: WorkspacePackage$1;
239
+ pkg: WorkspacePackage;
231
240
  }) => void;
232
241
  }
233
242
  //#endregion
234
243
  //#region src/graph.d.ts
235
244
  /** Package discovered in the workspace. */
236
- declare abstract class WorkspacePackage$1 {
245
+ declare abstract class WorkspacePackage {
237
246
  abstract readonly name: string;
238
247
  /** absolute path */
239
248
  abstract readonly path: string;
@@ -247,16 +256,14 @@ declare abstract class WorkspacePackage$1 {
247
256
  /** create the initial draft. */
248
257
  initDraft(): PackageDraft;
249
258
  /** configure an initial draft to match script-level configs. */
250
- configureDraft({
251
- draft
252
- }: {
259
+ configureDraft({ draft }: {
253
260
  draft: PackageDraft;
254
261
  }): void;
255
262
  }
256
263
  interface PackageGroup {
257
264
  name: string;
258
265
  options: GroupOptions;
259
- packages: WorkspacePackage$1[];
266
+ packages: WorkspacePackage[];
260
267
  }
261
268
  /**
262
269
  * Unified graph for discovered workspace packages.
@@ -267,14 +274,14 @@ interface PackageGroup {
267
274
  declare class PackageGraph {
268
275
  private readonly packages;
269
276
  private readonly groups;
270
- constructor(packages?: WorkspacePackage$1[]);
271
- getPackages(): WorkspacePackage$1[];
277
+ constructor(packages?: WorkspacePackage[]);
278
+ getPackages(): WorkspacePackage[];
272
279
  /** Get a package by exact id. */
273
- get(id: string): WorkspacePackage$1 | undefined;
280
+ get(id: string): WorkspacePackage | undefined;
274
281
  /** Get packages by id, `group:name`, or every package matching a name. */
275
- getByName(nameOrId: string): WorkspacePackage$1[];
282
+ getByName(nameOrId: string): WorkspacePackage[];
276
283
  /** scan package into graph, if the package id already exists, replace the existing one in graph */
277
- add(pkg: WorkspacePackage$1): void;
284
+ add(pkg: WorkspacePackage): void;
278
285
  delete(id: string): void;
279
286
  getPackageGroup(pkgId: string): PackageGroup | undefined;
280
287
  getGroups(): PackageGroup[];
@@ -362,9 +369,11 @@ declare class CargoToml<Data extends CargoManifest = CargoManifest> {
362
369
  data: Data;
363
370
  private dependencies;
364
371
  workspace?: CargoToml<RequireFields<CargoManifest, "workspace">>;
372
+ private readonly originalContent;
365
373
  constructor(path: string, content: string, data: Data);
366
374
  listDependencies(graph: CargoGraph): ResolvedDependency[];
367
375
  patch(path: string, value: unknown): void;
376
+ write(): Promise<void>;
368
377
  }
369
378
  interface ResolvedDependency {
370
379
  path: [...string[], kind: DepKind, key: string];
@@ -373,14 +382,14 @@ interface ResolvedDependency {
373
382
  range?: string;
374
383
  setRange?: (v: string) => void;
375
384
  }
376
- declare class CargoPackage extends WorkspacePackage$1 {
385
+ declare class CargoPackage extends WorkspacePackage {
377
386
  readonly path: string;
378
387
  /** a crate must have `package` field defined, otherwise it is merely a virutal workspace file, and Tegami should not include it. */
379
388
  readonly file: CargoToml<RequireFields<CargoManifest, "package">>;
380
389
  readonly manager = "cargo";
381
390
  readonly manifest: RequireFields<CargoManifest, "package">;
382
- constructor(path: string, /** a crate must have `package` field defined, otherwise it is merely a virutal workspace file, and Tegami should not include it. */
383
-
391
+ constructor(path: string,
392
+ /** a crate must have `package` field defined, otherwise it is merely a virutal workspace file, and Tegami should not include it. */
384
393
  file: CargoToml<RequireFields<CargoManifest, "package">>);
385
394
  get name(): string;
386
395
  get version(): string;
@@ -405,10 +414,7 @@ interface CargoPluginOptions {
405
414
  */
406
415
  bumpDep?: (opts: DependentRef$1) => BumpType | false;
407
416
  }
408
- declare function cargo({
409
- updateLockFile,
410
- bumpDep: getBumpDepType
411
- }?: CargoPluginOptions): TegamiPlugin;
417
+ declare function cargo({ updateLockFile, bumpDep: getBumpDepType }?: CargoPluginOptions): TegamiPlugin;
412
418
  interface CargoGraph {
413
419
  /** path -> Cargo.toml */
414
420
  files: Map<string, CargoToml>;
@@ -417,7 +423,7 @@ interface CargoGraph {
417
423
  }
418
424
  //#endregion
419
425
  //#region src/providers/npm/graph.d.ts
420
- declare class NpmPackage extends WorkspacePackage$1 {
426
+ declare class NpmPackage extends WorkspacePackage {
421
427
  readonly path: string;
422
428
  readonly manifest: PackageManifest;
423
429
  readonly manager = "npm";
@@ -428,9 +434,7 @@ declare class NpmPackage extends WorkspacePackage$1 {
428
434
  write(): Promise<void>;
429
435
  initDraft(): PackageDraft;
430
436
  getRegistry(): string;
431
- configureDraft({
432
- draft
433
- }: {
437
+ configureDraft({ draft }: {
434
438
  draft: PackageDraft;
435
439
  }): void;
436
440
  listDependencies(graph: NpmGraph): ResolvedNpmDependency[];
@@ -526,7 +530,8 @@ interface TegamiContext {
526
530
  /** additional context when npm plugin is configured */
527
531
  npm?: {
528
532
  agent: Agent;
529
- client: AgentName; /** available after resolve */
533
+ client: AgentName;
534
+ /** available after resolve */
530
535
  graph?: NpmGraph;
531
536
  };
532
537
  cargo?: {
@@ -574,11 +579,14 @@ interface PackagePublishPlan {
574
579
  updated: boolean;
575
580
  /** generated by Git plugin */
576
581
  git?: {
577
- /** the associated Git tag of package */tag?: string;
582
+ /** the associated Git tag of package */
583
+ tag?: string;
578
584
  };
579
585
  /** generated by npm plugin */
580
586
  npm?: {
581
- /** dist tag to use if published */distTag?: string; /** point latest tag to it if published */
587
+ /** dist tag to use if published */
588
+ distTag?: string;
589
+ /** point latest tag to it if published */
582
590
  markLatest?: boolean;
583
591
  };
584
592
  /** publish result, generated for all packages in publish plan after publishing */
@@ -636,7 +644,6 @@ interface GenerateChangelogOptions extends GenerateFromCommitsOptions {
636
644
  */
637
645
  write?: boolean;
638
646
  }
639
- declare const WorkspacePackage: typeof WorkspacePackage$1;
640
647
  interface Tegami {
641
648
  /** Create pending changelog files from git commit history. */
642
649
  generateChangelog(options?: GenerateChangelogOptions): Promise<CommitChangelog[]>;
@@ -645,11 +652,22 @@ interface Tegami {
645
652
  /** Publish packages from the publish lock. */
646
653
  publish(options?: PublishOptions): Promise<PublishPlan | "skipped">;
647
654
  /**
648
- * Check publish status.
649
- *
650
- * Prefer `publish()` over this if you are publishing packages, it will also check the publish status.
655
+ * @deprecated use `getPublishStatus()` instead
651
656
  */
652
657
  publishStatus(options?: PublishOptions): Promise<"pending" | "success" | "idle">;
658
+ /**
659
+ * Check publish plan status.
660
+ *
661
+ * Prefer `publish()` over this if you are publishing packages, this is check-only and can lead to TOCTOU race.
662
+ */
663
+ getPublishStatus(options?: PublishOptions): Promise<{
664
+ /**
665
+ * - `pending`: has pending tasks.
666
+ * - `success`: all tasks finished.
667
+ * - `none`: there is no existing publish plans. */
668
+ status: "pending" | "success" | "none";
669
+ reason?: string;
670
+ }>;
653
671
  /** Remove the publish lock file after publishing has finished successfully. */
654
672
  cleanup(options?: PublishOptions): Promise<{
655
673
  state: "removed";
@@ -659,7 +677,8 @@ interface Tegami {
659
677
  }>;
660
678
  /** Internal APIs, do not use it unless you know what you are doing */
661
679
  _internal: {
662
- context(): Promise<TegamiContext>; /** access context without requiring graph resolution */
680
+ context(): Promise<TegamiContext>;
681
+ /** access context without requiring graph resolution */
663
682
  contextUnresolved(): Promise<TegamiContext>;
664
683
  options: TegamiOptions;
665
684
  };
@@ -676,9 +695,9 @@ interface TegamiCliCommand<Values extends Record<string, ArgValue | undefined>,
676
695
  short?: string;
677
696
  description?: string;
678
697
  multiple?: Multiple;
679
- }): TegamiCliCommand<Values & { [k in Name]?: Multiple extends true ? T extends "string" ? string[] : boolean[] : T extends "string" ? string : boolean }, Positionals>;
680
- positional<const Name extends string, const Required extends boolean = true>(name: Name, required?: Required): TegamiCliCommand<Values, Positionals & { [K in Name]: Required extends true ? string : string | undefined }>;
681
- positionals<const Name extends string>(name: Name): TegamiCliCommand<Values, Positionals & { [K in Name]: string[] }>;
698
+ }): TegamiCliCommand<Values & { [k in Name]?: Multiple extends true ? T extends "string" ? string[] : boolean[] : T extends "string" ? string : boolean; }, Positionals>;
699
+ positional<const Name extends string, const Required extends boolean = true>(name: Name, required?: Required): TegamiCliCommand<Values, Positionals & { [K in Name]: Required extends true ? string : string | undefined; }>;
700
+ positionals<const Name extends string>(name: Name): TegamiCliCommand<Values, Positionals & { [K in Name]: string[]; }>;
682
701
  action(fn: (options: {
683
702
  context: TegamiContext;
684
703
  values: Values;
@@ -701,10 +720,12 @@ interface TegamiCliRegistry {
701
720
  //#endregion
702
721
  //#region src/providers/npm/cli.d.ts
703
722
  type TrustedPublishOptions = {
704
- provider: "github"; /** CI workflow filename for publishing. */
723
+ provider: "github";
724
+ /** CI workflow filename for publishing. */
705
725
  workflow: string;
706
726
  } | {
707
- provider: "gitlab"; /** CI pipeline filename for publishing. */
727
+ provider: "gitlab";
728
+ /** CI pipeline filename for publishing. */
708
729
  workflow: string;
709
730
  };
710
731
  //#endregion
@@ -738,19 +759,13 @@ interface NpmPluginOptions {
738
759
  /** Configure `tegami npm pretrust`, disabled by default. */
739
760
  trustedPublish?: TrustedPublishOptions;
740
761
  }
741
- declare function npm({
742
- client: defaultClient,
743
- onBreakPeerDep,
744
- updateLockFile,
745
- trustedPublish,
746
- bumpDep: getBumpDepType
747
- }?: NpmPluginOptions): TegamiPlugin;
762
+ declare function npm({ client: defaultClient, onBreakPeerDep, updateLockFile, trustedPublish, bumpDep: getBumpDepType }?: NpmPluginOptions): TegamiPlugin;
748
763
  //#endregion
749
764
  //#region src/types.d.ts
750
765
  /** Generates changelog content for a package release. */
751
766
  interface LogGenerator {
752
767
  generate(this: TegamiContext, opts: {
753
- pkg: WorkspacePackage$1;
768
+ pkg: WorkspacePackage;
754
769
  packageDraft: PackageDraft;
755
770
  draft: Draft;
756
771
  }): string | Promise<string>;
@@ -765,7 +780,7 @@ interface TegamiOptions<Groups extends string = string> {
765
780
  /** Changelog generator used when applying a draft. */
766
781
  generator?: LogGenerator;
767
782
  /** Per-package options keyed by package name or a function. */
768
- packages?: Record<string, PackageOptions<NoInfer<Groups>>> | ((pkg: WorkspacePackage$1) => PackageOptions<NoInfer<Groups>> | undefined);
783
+ packages?: Record<string, PackageOptions<NoInfer<Groups>>> | ((pkg: WorkspacePackage) => PackageOptions<NoInfer<Groups>> | undefined);
769
784
  plugins?: TegamiPluginOption[];
770
785
  groups?: Record<Groups, GroupOptions>;
771
786
  /** Package names, ids, or regex patterns to exclude from the dependency graph. */
@@ -844,7 +859,7 @@ interface TegamiPlugin {
844
859
  * If multiple plugins return preflight data for the same package, only the first plugin will be considered.
845
860
  */
846
861
  publishPreflight?(this: TegamiContext, opts: {
847
- pkg: WorkspacePackage$1;
862
+ pkg: WorkspacePackage;
848
863
  plan: PublishPlan;
849
864
  }): Awaitable<PublishPreflight | void | undefined>;
850
865
  /** Called when all preflights finished */
@@ -853,7 +868,7 @@ interface TegamiPlugin {
853
868
  }): Awaitable<void>;
854
869
  /** Publish package, return a result object indicating if the package is published, skipped, or failed. Return `undefined` if the package is not handled by this plugin. */
855
870
  publish?(this: TegamiContext, opts: {
856
- pkg: WorkspacePackage$1;
871
+ pkg: WorkspacePackage;
857
872
  plan: PublishPlan;
858
873
  }): Promise<PackagePublishResult | undefined | void>;
859
874
  /**
@@ -870,11 +885,11 @@ interface TegamiPlugin {
870
885
  }): Awaitable<void>;
871
886
  /** Called before a package will be published, return `false` to prevent from publishing. */
872
887
  willPublish?(this: TegamiContext, opts: {
873
- pkg: WorkspacePackage$1;
888
+ pkg: WorkspacePackage;
874
889
  }): Awaitable<false | void | undefined>;
875
890
  /** Called after a package is published successfully, or failed. */
876
891
  afterPublish?(this: TegamiContext, opts: {
877
- pkg: WorkspacePackage$1;
892
+ pkg: WorkspacePackage;
878
893
  plan: PublishPlan;
879
894
  }): Awaitable<void>;
880
895
  /** Called after all publishing finishes. */
@@ -887,7 +902,7 @@ interface TegamiPlugin {
887
902
  applyCliDraft?(this: TegamiContext, draft: Draft): Awaitable<void>;
888
903
  }
889
904
  type Awaitable<T> = T | Promise<T>;
890
- type RequireFields<Obj, K extends keyof Obj> = Obj & { [R in K]-?: NonNullable<Obj[R]> };
905
+ type RequireFields<Obj, K extends keyof Obj> = Obj & { [R in K]-?: NonNullable<Obj[R]>; };
891
906
  interface PublishPreflight {
892
907
  /**
893
908
  * Whether the package should be published, the state **must only depend on local inputs** (e.g. local `package.json` or `publish-lock.yaml`).
@@ -909,4 +924,4 @@ interface PublishPreflight {
909
924
  optionalWait?: string[];
910
925
  }
911
926
  //#endregion
912
- export { type PackageGroup as A, type NpmGraph as C, type CargoPluginOptions as D, CargoPackage as E, BumpType as F, Draft as M, DraftPolicy as N, cargo as O, PackageDraft as P, DependencySpec as S, CargoGraph as T, PackagePublishResult as _, type PublishPreflight as a, type CommitChangelog as b, type TegamiPluginOption as c, type GenerateChangelogOptions as d, Tegami as f, PackagePublishPlan as g, PublishLock as h, PackageOptions as i, WorkspacePackage$1 as j, PackageGraph as k, NpmPluginOptions as l, tegami as m, GroupOptions as n, TegamiOptions as o, WorkspacePackage as p, LogGenerator as r, TegamiPlugin as s, Awaitable as t, npm as u, PublishOptions as v, NpmPackage as w, TegamiContext as x, PublishPlan as y };
927
+ export { type PackageGroup as A, type NpmGraph as C, type CargoPluginOptions as D, CargoPackage as E, ChangelogEntry as F, ReplayCondition as I, BumpType as L, Draft as M, DraftPolicy as N, cargo as O, PackageDraft as P, DependencySpec as S, CargoGraph as T, PublishOptions as _, type PublishPreflight as a, type GenerateFromCommitsOptions as b, type TegamiPluginOption as c, type GenerateChangelogOptions as d, Tegami as f, PackagePublishResult as g, PackagePublishPlan as h, PackageOptions as i, WorkspacePackage as j, PackageGraph as k, NpmPluginOptions as l, PublishLock as m, GroupOptions as n, TegamiOptions as o, tegami as p, LogGenerator as r, TegamiPlugin as s, Awaitable as t, npm as u, PublishPlan as v, NpmPackage as w, TegamiContext as x, CommitChangelog as y };
@@ -1,5 +1,4 @@
1
1
  import { Result } from "tinyexec";
2
-
3
2
  //#region src/utils/error.d.ts
4
3
  declare function execFailure(context: string, result: Awaited<Result>): Error;
5
4
  declare function fetchFailure(context: string, response: Response): Promise<Error>;
@@ -1,9 +1,9 @@
1
- import { i as formatNpmDistTag, r as diffWeight } from "./semver-DrtaCCZK.js";
2
- import { n as execFailure, s as isCI } from "./error-CAsrGb6e.js";
3
- import { t as _accessExpressionAsString } from "./_accessExpressionAsString-DW_6Xqcp.js";
4
- import { n as _validateReport, t as _createStandardSchema } from "./_createStandardSchema-CrRqJgaE.js";
5
- import { t as getPackageBumps } from "./shared-pTOZU5UZ.js";
6
- import { o as PublishLock, r as runPreflights, s as parsePublishLock, t as initPublishPlan } from "./publish-BEYIILK5.js";
1
+ import { a as formatPackageVersion, i as formatNpmDistTag, r as diffWeight } from "./semver-DrtaCCZK.js";
2
+ import { l as somePromise, n as execFailure, s as isCI } from "./error-CAsrGb6e.js";
3
+ import { t as _accessExpressionAsString } from "./_accessExpressionAsString-DAz6bHI_.js";
4
+ import { n as _validateReport, t as _createStandardSchema } from "./_createStandardSchema-DFfVlh8x.js";
5
+ import { t as getPackageBumps } from "./shared-BraxbVVG.js";
6
+ import { o as PublishLock, r as runPreflights, s as parsePublishLock, t as initPublishPlan } from "./publish-CQifflae.js";
7
7
  import { mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
8
8
  import { join, relative } from "node:path";
9
9
  import { x } from "tinyexec";
@@ -66,8 +66,8 @@ const validatePublishGroupStore = (() => {
66
66
  };
67
67
  });
68
68
  })();
69
- function onVersionRequest(provider) {
70
- const namespace = `${provider.name}:publish-group`;
69
+ function versionRequestPlugin(provider) {
70
+ const NamespacePublishGroup = `${provider.name}:publish-group`;
71
71
  /** package id -> version before applying the CLI draft */
72
72
  const snapshots = /* @__PURE__ */ new Map();
73
73
  function resolveConfig(graph) {
@@ -94,6 +94,19 @@ function onVersionRequest(provider) {
94
94
  ...rest
95
95
  };
96
96
  }
97
+ /** commit the working tree changes onto a detached HEAD */
98
+ async function createVersionCommit(ctx, config) {
99
+ const { title = "Version Packages", body } = await config.commit?.call(ctx, { type: "version-packages" }) ?? {};
100
+ await run(ctx.cwd, ["checkout", "--detach"], "Failed to detach HEAD for version branches.");
101
+ await run(ctx.cwd, ["add", "-A"], "Failed to stage version changes.");
102
+ const args = [
103
+ "commit",
104
+ "-m",
105
+ title
106
+ ];
107
+ if (body) args.push("-m", body);
108
+ await run(ctx.cwd, args, "Failed to commit version changes.");
109
+ }
97
110
  /**
98
111
  * Commit the group's lock state on top of `parent` and force-push its branch.
99
112
  *
@@ -101,8 +114,8 @@ function onVersionRequest(provider) {
101
114
  */
102
115
  async function syncGroupBranch(context, opts) {
103
116
  const lock = new PublishLock(opts.baseLock);
104
- while (lock.read(namespace));
105
- lock.write(namespace, opts.store);
117
+ while (lock.read(NamespacePublishGroup));
118
+ lock.write(NamespacePublishGroup, opts.store);
106
119
  const commit = await createLockCommit(context, opts.parent, lock.serialize(), await opts.config.commit?.call(context, {
107
120
  type: "update-lock",
108
121
  store: opts.store,
@@ -118,15 +131,16 @@ function onVersionRequest(provider) {
118
131
  return false;
119
132
  }
120
133
  return {
121
- /** snapshot package versions, hook into `initCliDraft` */
134
+ name: `${provider.name}:version-request`,
135
+ /** snapshot package versions */
122
136
  initCliDraft() {
123
137
  for (const pkg of this.graph.getPackages()) snapshots.set(pkg.id, pkg.version);
124
138
  },
125
- /** commit & push version branches, then upsert their requests, hook into `applyCliDraft` */
139
+ /** commit & push version branches, then upsert their requests */
126
140
  async applyCliDraft(draft) {
141
+ if (!provider.canCreate(this)) return;
127
142
  const config = resolveConfig(this.graph);
128
- if (!config || !provider.canCreate(this)) return;
129
- if (!(config.forceCreate || isCI()) || !await hasGitChanges(this.cwd)) return;
143
+ if (!config || !(config.forceCreate || isCI()) || !await hasGitChanges(this.cwd)) return;
130
144
  const requests = [];
131
145
  const updatedPackages = /* @__PURE__ */ new Map();
132
146
  for (const id of draft.getPackageDrafts().keys()) {
@@ -152,7 +166,7 @@ function onVersionRequest(provider) {
152
166
  packages: Array.from(updatedPackages.values())
153
167
  });
154
168
  if (requests.length === 0) return;
155
- await createVersionCommit(this.cwd, await config.commit?.call(this, { type: "version-packages" }));
169
+ await createVersionCommit(this, config);
156
170
  let baseLock;
157
171
  let parent;
158
172
  const tasks = [];
@@ -189,19 +203,30 @@ function onVersionRequest(provider) {
189
203
  tasks.push(provider.upsert(this, resolved, !inSync));
190
204
  continue;
191
205
  }
192
- await pushBranch(this.cwd, branch);
206
+ await run(this.cwd, [
207
+ "checkout",
208
+ "-B",
209
+ branch
210
+ ], "Failed to create the version branch.");
211
+ await run(this.cwd, [
212
+ "push",
213
+ "--force",
214
+ "-u",
215
+ "origin",
216
+ branch
217
+ ], "Failed to push the version branch to origin. Ensure `origin` is configured and you have push access.");
193
218
  await provider.upsert(this, resolved, true);
194
219
  }
195
220
  await Promise.all(tasks);
196
221
  },
197
- /** restore publish groups from the lock into the plan, hook into `initPublishPlan` */
222
+ /** restore publish groups from the lock into the plan */
198
223
  initPublishPlan({ lock, plan }) {
199
224
  const config = resolveConfig(this.graph);
200
225
  if (!config) return;
201
226
  let data;
202
227
  const publishGroups = /* @__PURE__ */ new Map();
203
228
  plan.$versionRequest = { publishGroups };
204
- while (data = lock.read(namespace)) {
229
+ while (data = lock.read(NamespacePublishGroup)) {
205
230
  const validated = validatePublishGroupStore(data);
206
231
  if (!validated.success) continue;
207
232
  const store = validated.data;
@@ -228,7 +253,7 @@ function onVersionRequest(provider) {
228
253
  if (!publishGroups) return;
229
254
  for (const s of publishGroups.values()) if (s === "pending") return "pending";
230
255
  },
231
- /** re-sync the version requests of pending publish groups, hook into `beforePublishAll` */
256
+ /** re-sync the version requests of pending publish groups */
232
257
  async beforePublishAll({ plan }) {
233
258
  if (plan.options.dryRun || !provider.canCreate(this)) return;
234
259
  const config = resolveConfig(this.graph);
@@ -388,32 +413,6 @@ async function resolveRemoteBranches(cwd, branches) {
388
413
  async function hasGitChanges(cwd) {
389
414
  return (await run(cwd, ["status", "--porcelain"], "Failed to check git status.")).length > 0;
390
415
  }
391
- /** commit the working tree changes onto a detached HEAD */
392
- async function createVersionCommit(cwd, { title = "Version Packages", body } = {}) {
393
- await run(cwd, ["checkout", "--detach"], "Failed to detach HEAD for version branches.");
394
- await run(cwd, ["add", "-A"], "Failed to stage version changes.");
395
- const args = [
396
- "commit",
397
- "-m",
398
- title
399
- ];
400
- if (body) args.push("-m", body);
401
- await run(cwd, args, "Failed to commit version changes.");
402
- }
403
- async function pushBranch(cwd, branch) {
404
- await run(cwd, [
405
- "checkout",
406
- "-B",
407
- branch
408
- ], "Failed to create the version branch.");
409
- await run(cwd, [
410
- "push",
411
- "--force",
412
- "-u",
413
- "origin",
414
- branch
415
- ], "Failed to push the version branch to origin. Ensure `origin` is configured and you have push access.");
416
- }
417
416
  async function run(cwd, args, message, env) {
418
417
  const result = await x("git", args, { nodeOptions: {
419
418
  cwd,
@@ -469,5 +468,96 @@ function formatPreview({ graph, npm }, draft, newChangelogNames, labels) {
469
468
  lines.push(`Run \`${npm?.client ?? "npm"} run tegami\` locally to create a changelog interactively.`, "", `<sub>Managed by [Tegami](https://tegami.fuma-nama.dev).</sub>`, "");
470
469
  return lines.join("\n");
471
470
  }
471
+ async function resolveFileCommit(ctx, filename) {
472
+ const result = await x("git", [
473
+ "log",
474
+ "--diff-filter=A",
475
+ "-1",
476
+ "--format=%H",
477
+ "--",
478
+ relative(ctx.cwd, join(ctx.changelogDir, filename))
479
+ ], { nodeOptions: { cwd: ctx.cwd } });
480
+ if (result.exitCode !== 0) return;
481
+ return result.stdout.trim() || void 0;
482
+ }
483
+ function createAutoRelease({ eager, create, override, overrideGroup, releaseExistsByTag, formatChangelog }) {
484
+ async function defaultNotes(ctx, pkg, packagePlan) {
485
+ if (packagePlan && packagePlan.changelogs.length > 0) return (await Promise.all(packagePlan.changelogs.map(formatChangelog.bind(ctx)))).join("\n\n");
486
+ return `Published ${formatPackageVersion(pkg.name, pkg.version, packagePlan?.npm?.distTag)}.`;
487
+ }
488
+ async function defaultGroupedNotes(ctx, plan, packages) {
489
+ const changelogs = /* @__PURE__ */ new Map();
490
+ for (const pkg of packages) {
491
+ const packagePlan = plan.packages.get(pkg.id);
492
+ if (!packagePlan) continue;
493
+ for (const entry of packagePlan.changelogs) changelogs.set(entry.id, entry);
494
+ }
495
+ const sections = [packages.map((pkg) => {
496
+ const packagePlan = plan.packages.get(pkg.id);
497
+ return `- ${formatPackageVersion(pkg.name, pkg.version, packagePlan?.npm?.distTag)}`;
498
+ }).join("\n")];
499
+ if (changelogs.size > 0) {
500
+ const notes = await Promise.all(Array.from(changelogs.values(), formatChangelog.bind(ctx)));
501
+ sections.push("", notes.join("\n\n"));
502
+ }
503
+ return sections.join("\n");
504
+ }
505
+ return {
506
+ async hasPending(plan) {
507
+ const requiredTags = /* @__PURE__ */ new Set();
508
+ for (const pkg of plan.packages.values()) if (pkg.preflight.shouldPublish && pkg.git?.tag) requiredTags.add(pkg.git.tag);
509
+ return somePromise(Array.from(requiredTags, (tag) => releaseExistsByTag.call(this, tag)), (exists) => !exists);
510
+ },
511
+ async create(plan) {
512
+ const groups = /* @__PURE__ */ new Map();
513
+ for (const [id, { preflight, publishResult, git }] of plan.packages) {
514
+ if (!eager && publishResult.type === "failed") return;
515
+ const tag = git?.tag;
516
+ if (!tag || !preflight.shouldPublish) continue;
517
+ const pkg = this.graph.get(id);
518
+ const group = groups.get(tag);
519
+ if (group) group.push(pkg);
520
+ else groups.set(tag, [pkg]);
521
+ }
522
+ await Promise.all(Array.from(groups, async ([tag, packages]) => {
523
+ for (const member of packages) if (plan.packages.get(member.id).publishResult.type === "failed") return;
524
+ if (await releaseExistsByTag.call(this, tag)) return;
525
+ if (packages.length > 1) {
526
+ const { title = tag, notes = await defaultGroupedNotes(this, plan, packages), ...rest } = await overrideGroup?.call(this, {
527
+ tag,
528
+ packages,
529
+ plan
530
+ }) ?? {};
531
+ await create({
532
+ input: {
533
+ title,
534
+ notes,
535
+ ...rest
536
+ },
537
+ tag,
538
+ packages
539
+ });
540
+ return;
541
+ }
542
+ const pkg = packages[0];
543
+ const packagePlan = plan.packages.get(pkg.id);
544
+ const { title = formatPackageVersion(pkg.name, pkg.version, packagePlan?.npm?.distTag), notes = await defaultNotes(this, pkg, packagePlan), ...rest } = await override?.call(this, {
545
+ tag,
546
+ pkg,
547
+ plan
548
+ }) ?? {};
549
+ await create({
550
+ input: {
551
+ title,
552
+ notes,
553
+ ...rest
554
+ },
555
+ tag,
556
+ packages
557
+ });
558
+ }));
559
+ }
560
+ };
561
+ }
472
562
  //#endregion
473
- export { onVersionRequest as n, formatPreview as t };
563
+ export { versionRequestPlugin as i, formatPreview as n, resolveFileCommit as r, createAutoRelease as t };
@@ -1,5 +1,4 @@
1
- import { M as Draft, h as PublishLock, t as Awaitable, x as TegamiContext, y as PublishPlan } from "./types-Kj7Nxbjz.js";
2
-
1
+ import { M as Draft, m as PublishLock, t as Awaitable, v as PublishPlan, x as TegamiContext } from "./types-Cn0Au3Kk.js";
3
2
  //#region src/utils/version-request.d.ts
4
3
  interface VersionRequestOptions {
5
4
  /**
@@ -45,7 +44,6 @@ interface VersionRequestContext {
45
44
  plan: PublishPlan | undefined;
46
45
  getPreviousVersion(packageId: string): string | undefined;
47
46
  }
48
- /** adapter over the version request API of a git provider */
49
47
  interface PublishGroupStore {
50
48
  /**
51
49
  * - active: groups whose version request was merged, they stay listed until the lock is removed
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tegami",
3
- "version": "1.2.3",
3
+ "version": "1.2.5",
4
4
  "description": "A tool to manage changelogs, versioning, and publishing in monorepo",
5
5
  "license": "MIT",
6
6
  "author": "Fuma Nama",
@@ -37,10 +37,10 @@
37
37
  "yaml": "^2.9.0"
38
38
  },
39
39
  "devDependencies": {
40
- "@types/node": "^26.1.0",
40
+ "@types/node": "^26.1.1",
41
41
  "@types/semver": "^7.7.1",
42
42
  "package-manager-detector": "^1.7.0",
43
- "tsdown": "^0.22.3",
43
+ "tsdown": "^0.22.4",
44
44
  "typescript": "6.0.3",
45
45
  "typia": "^12.1.1",
46
46
  "@repo/typescript-config": "0.0.0"