tegami 0.1.0-beta.0 → 0.1.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,14 +1,10 @@
1
1
  import { n as handlePluginError } from "./error-DBK-9uBa.js";
2
- import { n as jsonCodec } from "./schemas-Cc4h6bq5.js";
2
+ import { n as jsonCodec, t as bumpTypeSchema } from "./schemas-CurBAaW5.js";
3
3
  import z$1 from "zod";
4
4
  import { readFile } from "fs/promises";
5
5
  //#region src/plans/store.ts
6
6
  const packagePlanStoreSchema = z$1.object({
7
- type: z$1.enum([
8
- "major",
9
- "minor",
10
- "patch"
11
- ]).optional(),
7
+ type: bumpTypeSchema.optional(),
12
8
  changelogIds: z$1.array(z$1.string()).optional(),
13
9
  bumpReasons: z$1.array(z$1.string()).optional(),
14
10
  npm: z$1.object({ distTag: z$1.string().optional() }).optional(),
@@ -23,14 +19,11 @@ const planStoreSchema = jsonCodec(z$1.object({
23
19
  changelogs: z$1.record(z$1.string(), z$1.object({
24
20
  filename: z$1.string(),
25
21
  subject: z$1.string().optional(),
26
- packages: z$1.array(z$1.string()),
27
- type: z$1.enum([
28
- "major",
29
- "minor",
30
- "patch"
31
- ]),
32
- title: z$1.string(),
33
- content: z$1.string()
22
+ packages: z$1.record(z$1.string(), bumpTypeSchema),
23
+ sections: z$1.array(z$1.object({
24
+ title: z$1.string(),
25
+ content: z$1.string()
26
+ }))
34
27
  })),
35
28
  /** package id -> package info */
36
29
  packages: z$1.record(z$1.string(), packagePlanStoreSchema)
@@ -46,10 +39,8 @@ function createPlanStore(draft, context) {
46
39
  for (const entry of draft.getChangelogs()) store.changelogs[entry.id] = {
47
40
  filename: entry.filename,
48
41
  subject: entry.subject,
49
- packages: Array.from(entry.packages),
50
- type: entry.type,
51
- title: entry.title,
52
- content: entry.content
42
+ packages: Object.fromEntries(entry.packages.entries()),
43
+ sections: entry.sections
53
44
  };
54
45
  for (const pkg of context.graph.getPackages()) {
55
46
  const plan = draft.getPackagePlan(pkg.id);
@@ -1,4 +1,4 @@
1
- import { C as PublishResult, a as Awaitable, t as Tegami, w as DraftPlan } from "../index-Bhh2dJZp.js";
1
+ import { C as PublishResult, O as DraftPlan, _ as Tegami, t as Awaitable } from "../types-BNhcu4-X.js";
2
2
  import { Command } from "commander";
3
3
 
4
4
  //#region src/cli/index.d.ts
package/dist/cli/index.js CHANGED
@@ -1,9 +1,11 @@
1
1
  import { n as handlePluginError } from "../error-DBK-9uBa.js";
2
- import { t as assertPublishPlanFinished } from "../checks-CKBRRjgQ.js";
2
+ import { t as bumpDepth } from "../semver-CPtl0XNq.js";
3
+ import { t as assertPublishPlanFinished } from "../checks-Fz8-N09y.js";
3
4
  import { t as isCI } from "../constants-B9qjNfvr.js";
4
5
  import { mkdir, writeFile } from "node:fs/promises";
5
6
  import { join } from "node:path";
6
- import { confirm, intro, isCancel, multiselect, note, outro, select, spinner, text } from "@clack/prompts";
7
+ import { dump } from "js-yaml";
8
+ import { autocompleteMultiselect, confirm, intro, isCancel, multiline, note, outro, select, spinner } from "@clack/prompts";
7
9
  import { Command } from "commander";
8
10
  //#region src/cli/index.ts
9
11
  var CancelledError = class extends Error {
@@ -17,14 +19,22 @@ function createCli(tegami, options = {}) {
17
19
  ...commandOptions,
18
20
  cli: options
19
21
  })));
20
- program.command("version").description("draft and apply a publish plan").action((commandOptions) => runAction(tegami, () => versionPackages(tegami, {
21
- ...commandOptions,
22
- cli: options
23
- })));
24
- program.command("publish").description("publish packages from the applied publish plan").option("--dry-run", "validate the publish plan without publishing packages").action((commandOptions) => runAction(tegami, () => publishPackages(tegami, {
25
- ...commandOptions,
26
- cli: options
27
- })));
22
+ program.command("version").description("draft and apply a publish plan").action((commandOptions) => runAction(tegami, async () => {
23
+ await versionPackages(tegami, {
24
+ ...commandOptions,
25
+ cli: options
26
+ });
27
+ }));
28
+ program.command("ci").description("version and publish packages").action(() => runAction(tegami, async () => {
29
+ if (await versionPackages(tegami, { cli: options })) return;
30
+ await publishPackages(tegami, { cli: options });
31
+ }));
32
+ program.command("publish").description("publish packages from the applied publish plan").option("--dry-run", "validate the publish plan without publishing packages").action((commandOptions) => runAction(tegami, async () => {
33
+ await publishPackages(tegami, {
34
+ ...commandOptions,
35
+ cli: options
36
+ });
37
+ }));
28
38
  program.command("cleanup").description("remove the publish plan after all packages have been published").action(() => runAction(tegami, () => runCleanup(tegami)));
29
39
  return program;
30
40
  }
@@ -32,18 +42,29 @@ async function createChangelogs(tegami, _options) {
32
42
  const context = await tegami._internal.context();
33
43
  await assertPublishPlanFinished(context);
34
44
  intro("Create changelogs");
35
- const packages = context.graph.getPackages();
36
45
  let selectedPackages = [];
37
- if (isCI()) selectedPackages = [];
38
- else {
39
- const selected = await multiselect({
46
+ if (!isCI()) {
47
+ const packages = context.graph.getPackages();
48
+ const useShortname = /* @__PURE__ */ new Map();
49
+ for (const pkg of packages) if (useShortname.has(pkg.name)) useShortname.set(pkg.name, false);
50
+ else useShortname.set(pkg.name, true);
51
+ const getPackageLabel = (pkg) => {
52
+ return useShortname.get(pkg.name) ? pkg.name : pkg.id;
53
+ };
54
+ const selectOptions = [];
55
+ for (const group of context.graph.getGroups()) selectOptions.push({
56
+ label: `Group ${group.name}`,
57
+ value: `group:${group.name}`,
58
+ hint: group.packages.map(getPackageLabel).join(", ")
59
+ });
60
+ for (const pkg of packages) selectOptions.push({
61
+ label: getPackageLabel(pkg),
62
+ value: pkg.id
63
+ });
64
+ const selected = await autocompleteMultiselect({
40
65
  message: "Select packages (leave empty to auto-generate from commits)",
41
66
  required: false,
42
- options: packages.map((pkg) => ({
43
- value: pkg.id,
44
- label: pkg.id,
45
- hint: pkg.version
46
- }))
67
+ options: selectOptions
47
68
  });
48
69
  if (isCancel(selected)) throw new CancelledError();
49
70
  selectedPackages = selected;
@@ -87,9 +108,10 @@ async function createChangelogs(tegami, _options) {
87
108
  ]
88
109
  });
89
110
  if (isCancel(type)) throw new CancelledError();
90
- const message = await text({
91
- message: "Change message",
92
- placeholder: "Add a concise release note",
111
+ const message = await multiline({
112
+ message: "Describe change (Markdown supported, press tab then enter to exit)",
113
+ placeholder: "The first line is heading\n\nAdditional description.",
114
+ showSubmit: true,
93
115
  validate(value) {
94
116
  if (!value?.trim()) return "Enter a message.";
95
117
  }
@@ -114,7 +136,7 @@ async function versionPackages(tegami, options) {
114
136
  if (!draft.hasPending()) {
115
137
  note("No pending changelog entries matched workspace packages.", "Nothing to version");
116
138
  outro("No versions changed.");
117
- return;
139
+ return false;
118
140
  }
119
141
  const planEntries = [];
120
142
  for (const pkg of context.graph.getPackages()) {
@@ -135,6 +157,7 @@ async function versionPackages(tegami, options) {
135
157
  s.stop("Package versions updated");
136
158
  for (const plugin of context.plugins) await handlePluginError(plugin, "cli.publishPlanApplied", () => plugin.cli?.publishPlanApplied?.call(context, draft));
137
159
  outro("Publish plan applied.");
160
+ return true;
138
161
  }
139
162
  async function publishPackages(tegami, options) {
140
163
  const dryRun = options.dryRun ?? false;
@@ -147,7 +170,7 @@ async function publishPackages(tegami, options) {
147
170
  const { planPath } = await tegami._internal.context();
148
171
  s.stop(dryRun ? "No publish plan to validate" : "Nothing to publish");
149
172
  outro(`No publishable packages were found in ${planPath}.`);
150
- return;
173
+ return false;
151
174
  }
152
175
  s.stop(dryRun ? "Publish plan validated" : "Publish complete");
153
176
  note(result.packages.map((pkg) => {
@@ -158,9 +181,10 @@ async function publishPackages(tegami, options) {
158
181
  if (result.state === "failed") {
159
182
  process.exitCode = 1;
160
183
  outro("Some packages failed to publish.");
161
- return;
184
+ return false;
162
185
  }
163
186
  outro(dryRun ? "Publish plan is valid." : "Packages published.");
187
+ return true;
164
188
  }
165
189
  async function runCleanup(tegami) {
166
190
  intro("Cleanup publish plan");
@@ -180,13 +204,15 @@ async function runCleanup(tegami) {
180
204
  outro(`Publish plan at ${planPath} is still pending. Publish it before cleanup.`);
181
205
  }
182
206
  function renderManualChangelog(packages, type, message) {
183
- const heading = "#".repeat(type === "major" ? 1 : type === "minor" ? 2 : 3);
207
+ const prefix = "#".repeat(bumpDepth(type));
208
+ const packageMap = {};
209
+ for (const name of packages) packageMap[name] = type;
184
210
  return [
185
211
  "---",
186
- `packages: ${JSON.stringify(packages)}`,
212
+ dump({ packages: packageMap }).trim(),
187
213
  "---",
188
214
  "",
189
- `${heading} ${message}`,
215
+ `${prefix} ${message}`,
190
216
  ""
191
217
  ].join("\n");
192
218
  }
@@ -1,4 +1,4 @@
1
- import { s as LogGenerator } from "../index-Bhh2dJZp.js";
1
+ import { r as LogGenerator } from "../types-BNhcu4-X.js";
2
2
 
3
3
  //#region src/generators/simple.d.ts
4
4
  declare function simpleGenerator(): LogGenerator;
@@ -1,17 +1,18 @@
1
- import { r as formatPackageVersion } from "../semver-mWK2Khi2.js";
1
+ import { i as formatPackageVersion } from "../semver-CPtl0XNq.js";
2
2
  //#region src/generators/simple.ts
3
3
  function simpleGenerator() {
4
4
  return { generate({ changelogs, version, packageName, plan }) {
5
- return [
6
- `## ${formatPackageVersion(packageName, version, plan.npm?.distTag)}`,
7
- "",
8
- ...changelogs.flatMap((entry) => [
9
- `### ${entry.title}`,
10
- "",
11
- entry.content,
12
- ""
13
- ])
14
- ].join("\n").trim();
5
+ const lines = [`## ${formatPackageVersion(packageName, version, plan.npm?.distTag)}`, ""];
6
+ for (const entry of changelogs) {
7
+ let sectionDepth = 4;
8
+ if (entry.subject) lines.push(`### ${entry.subject}`, "");
9
+ else sectionDepth--;
10
+ for (const section of entry.sections) {
11
+ const prefix = "#".repeat(sectionDepth);
12
+ lines.push(`${prefix} ${section.title}`, "", section.content, "");
13
+ }
14
+ }
15
+ return lines.join("\n").trim();
15
16
  } };
16
17
  }
17
18
  //#endregion
@@ -1,4 +1,4 @@
1
- import { t as bumpVersion } from "./semver-mWK2Khi2.js";
1
+ import { n as bumpVersion } from "./semver-CPtl0XNq.js";
2
2
  //#region src/graph.ts
3
3
  /** Package discovered in the workspace. */
4
4
  var WorkspacePackage = class {
package/dist/index.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { C as PublishResult, D as PackageGroup, E as PackageGraph, O as WorkspacePackage, S as PublishOptions, T as PackagePlan, c as PackageOptions, d as TegamiPlugin, f as TegamiPluginOption, i as CreatedChangelog, l as RegistryClient, n as tegami, o as GroupOptions, r as CreateChangelogOptions, s as LogGenerator, t as Tegami, u as TegamiOptions, w as DraftPlan, x as PackagePublishResult } from "./index-Bhh2dJZp.js";
1
+ import { C as PublishResult, D as WorkspacePackage, E as PackageGroup, O as DraftPlan, S as PublishOptions, T as PackageGraph, _ as Tegami, a as RegistryClient, b as CreatedChangelog, c as TegamiPluginOption, i as PackageOptions, k as PackagePlan, n as GroupOptions, o as TegamiOptions, r as LogGenerator, s as TegamiPlugin, v as tegami, x as PackagePublishResult, y as CreateChangelogOptions } from "./types-BNhcu4-X.js";
2
2
  export { type CreateChangelogOptions, type CreatedChangelog, type DraftPlan, type GroupOptions, type LogGenerator, type PackageGraph, type PackageGroup, type PackageOptions, type PackagePlan, type PackagePublishResult, type PublishOptions, type PublishResult, type RegistryClient, Tegami, type TegamiOptions, type TegamiPlugin, type TegamiPluginOption, type WorkspacePackage, tegami };
package/dist/index.js CHANGED
@@ -1,15 +1,16 @@
1
1
  import { n as handlePluginError } from "./error-DBK-9uBa.js";
2
- import { i as maxBump } from "./semver-mWK2Khi2.js";
3
- import { t as PackageGraph } from "./graph-CUgwuRW5.js";
2
+ import { a as maxBump } from "./semver-CPtl0XNq.js";
3
+ import { t as PackageGraph } from "./graph-B22NBRUG.js";
4
4
  import { cargo } from "./providers/cargo.js";
5
- import { t as changelogFrontmatterSchema } from "./schemas-Cc4h6bq5.js";
5
+ import { t as bumpTypeSchema } from "./schemas-CurBAaW5.js";
6
6
  import { npm } from "./providers/npm.js";
7
7
  import { simpleGenerator } from "./generators/simple.js";
8
- import { i as readPlanStore, n as publishPlanStatus, r as createPlanStore, t as assertPublishPlanFinished } from "./checks-CKBRRjgQ.js";
8
+ import { i as readPlanStore, n as publishPlanStatus, r as createPlanStore, t as assertPublishPlanFinished } from "./checks-Fz8-N09y.js";
9
9
  import { mkdir, readFile, readdir, rm, writeFile } from "node:fs/promises";
10
10
  import path, { basename, dirname, join } from "node:path";
11
11
  import { x } from "tinyexec";
12
12
  import { load } from "js-yaml";
13
+ import z$1 from "zod";
13
14
  import { fromMarkdown } from "mdast-util-from-markdown";
14
15
  import { toMarkdown } from "mdast-util-to-markdown";
15
16
  //#region src/changelog/create.ts
@@ -268,10 +269,10 @@ var DraftPlan = class {
268
269
  addChangelog(entry) {
269
270
  this.changelogs.set(entry.id, entry);
270
271
  const { graph } = this.context;
271
- const groupPackages = /* @__PURE__ */ new Set();
272
- for (const name of entry.packages) for (const pkg of graph.getByName(name)) groupPackages.add(pkg);
273
- for (const pkg of groupPackages) {
274
- const plan = this.bumpPackage(pkg, { type: entry.type });
272
+ const groupPackages = /* @__PURE__ */ new Map();
273
+ for (const [name, bumpType] of entry.packages) for (const pkg of graph.getByName(name)) groupPackages.set(pkg, bumpType);
274
+ for (const [pkg, bumpType] of groupPackages) {
275
+ const plan = this.bumpPackage(pkg, { type: bumpType });
275
276
  plan.changelogs ??= [];
276
277
  plan.changelogs.push(entry);
277
278
  }
@@ -381,6 +382,10 @@ function frontmatter(input) {
381
382
  }
382
383
  //#endregion
383
384
  //#region src/changelog/parse.ts
385
+ const changelogFrontmatterSchema = z$1.object({
386
+ subject: z$1.string().optional(),
387
+ packages: z$1.union([z$1.array(z$1.string()), z$1.record(z$1.string(), bumpTypeSchema.or(z$1.null()))]).optional()
388
+ });
384
389
  async function getChangelogFiles(context) {
385
390
  return (await readdir(context.changelogDir).catch(() => [])).filter((file) => file.endsWith(".md"));
386
391
  }
@@ -390,29 +395,37 @@ async function readChangelogEntries(context) {
390
395
  return (await Promise.all(files.map(async (file) => {
391
396
  const filePath = join(dir, file);
392
397
  return parseChangelogFile(filePath, await readFile(filePath, "utf8"));
393
- }))).flat();
398
+ }))).filter((v) => v !== void 0);
394
399
  }
395
400
  /** Parse one changelog markdown file into release entries. */
396
401
  function parseChangelogFile(file, content) {
397
402
  const parsed = frontmatter(content);
398
403
  const data = changelogFrontmatterSchema.parse(parsed.data);
404
+ if (!data.packages) return;
399
405
  const tree = fromMarkdown(parsed.content);
400
- const entries = [];
406
+ let bumpType;
407
+ const packages = /* @__PURE__ */ new Map();
408
+ const sections = [];
409
+ const filename = basename(file);
401
410
  for (const section of getHeadingSections(tree)) {
402
- const type = headingToBump(section.heading.depth);
403
- if (!type) continue;
404
- const filename = basename(file);
405
- entries.push({
406
- id: `${filename}:${entries.length}`,
407
- filename,
408
- subject: data.subject,
409
- packages: new Set(data.packages),
410
- type,
411
+ const sectionBumpType = headingToBump(section.heading.depth);
412
+ if (sectionBumpType) bumpType = bumpType ? maxBump(bumpType, sectionBumpType) : sectionBumpType;
413
+ sections.push({
414
+ depth: section.heading.depth,
411
415
  title: headingText(section.heading),
412
416
  content: sectionToMarkdown(section.children)
413
417
  });
414
418
  }
415
- return entries;
419
+ if (!bumpType) return;
420
+ if (Array.isArray(data.packages)) for (const pkg of data.packages) packages.set(pkg, bumpType);
421
+ else for (const [k, v] of Object.entries(data.packages)) packages.set(k, v ?? bumpType);
422
+ return {
423
+ id: filename,
424
+ filename,
425
+ subject: data.subject,
426
+ packages,
427
+ sections
428
+ };
416
429
  }
417
430
  function getHeadingSections(tree) {
418
431
  const sections = [];
@@ -468,7 +481,7 @@ async function publishFromPlan(context, store, options) {
468
481
  const entry = store.changelogs[id];
469
482
  if (entry) changelogs.push({
470
483
  ...entry,
471
- packages: new Set(entry.packages),
484
+ packages: new Map(Object.entries(entry.packages)),
472
485
  id
473
486
  });
474
487
  }
@@ -486,10 +499,13 @@ async function publishFromPlan(context, store, options) {
486
499
  }
487
500
  }
488
501
  try {
489
- if (!dryRun) await context.getRegistryClient(pkg).publish(pkg, {
490
- packageStore: plan,
491
- store
492
- });
502
+ if (!dryRun) {
503
+ for (const plugin of context.plugins) await handlePluginError(plugin, "willPublish", () => plugin.willPublish?.call(context, { pkg }));
504
+ await context.getRegistryClient(pkg).publish(pkg, {
505
+ packageStore: plan,
506
+ store
507
+ });
508
+ }
493
509
  packages.push({
494
510
  id: pkg.id,
495
511
  name: pkg.name,
@@ -1,4 +1,4 @@
1
- import { d as TegamiPlugin } from "../index-Bhh2dJZp.js";
1
+ import { s as TegamiPlugin } from "../types-BNhcu4-X.js";
2
2
 
3
3
  //#region src/plugins/git.d.ts
4
4
  interface GitPluginOptions {
@@ -1,4 +1,4 @@
1
- import { a as Awaitable, d as TegamiPlugin, w as DraftPlan, x as PackagePublishResult } from "../index-Bhh2dJZp.js";
1
+ import { O as DraftPlan, s as TegamiPlugin, t as Awaitable, w as TegamiContext, x as PackagePublishResult } from "../types-BNhcu4-X.js";
2
2
  import { GitPluginOptions } from "./git.js";
3
3
 
4
4
  //#region src/plugins/github.d.ts
@@ -34,12 +34,14 @@ interface VersionPullRequestOptions {
34
34
  interface GitHubPluginOptions extends GitPluginOptions {
35
35
  /** GitHub repository. */
36
36
  repo?: string;
37
+ /** Optional GitHub token for Git & GitHub operations. */
38
+ token?: string;
37
39
  /** Override release details for a single package, return `false` to skip. */
38
- onCreateRelease?: (result: PackagePublishResult) => Awaitable<GithubRelease | false>;
40
+ onCreateRelease?: (this: TegamiContext, result: PackagePublishResult) => Awaitable<GithubRelease | false>;
39
41
  /** Override release details when multiple packages share a git tag, return `false` to skip. */
40
- onCreateGroupedRelease?: (packages: PackagePublishResult[]) => Awaitable<GithubRelease | false>;
42
+ onCreateGroupedRelease?: (this: TegamiContext, packages: PackagePublishResult[]) => Awaitable<GithubRelease | false>;
41
43
  /** Override details for "Version Packages" PR. */
42
- onCreateVersionPullRequest?: (publishPlan: DraftPlan) => Awaitable<VersionPullRequest | false>;
44
+ onCreateVersionPullRequest?: (this: TegamiContext, publishPlan: DraftPlan) => Awaitable<VersionPullRequest | false>;
43
45
  cli?: {
44
46
  /**
45
47
  * Open a version pull request after versioning.
@@ -1,7 +1,8 @@
1
1
  import { t as execFailure } from "../error-DBK-9uBa.js";
2
- import { n as formatNpmDistTag, r as formatPackageVersion } from "../semver-mWK2Khi2.js";
2
+ import { i as formatPackageVersion, r as formatNpmDistTag } from "../semver-CPtl0XNq.js";
3
3
  import { t as isCI } from "../constants-B9qjNfvr.js";
4
4
  import { git } from "./git.js";
5
+ import { join, relative } from "node:path";
5
6
  import { x } from "tinyexec";
6
7
  import { prerelease } from "semver";
7
8
  //#region src/plugins/github.ts
@@ -22,18 +23,18 @@ function github(options = {}) {
22
23
  const result = await x("gh", args);
23
24
  if (result.exitCode !== 0) throw execFailure(`Failed to create GitHub release for ${gitTag}.`, result);
24
25
  }
25
- async function createRelease(pkg) {
26
+ async function createRelease(context, pkg) {
26
27
  if (!pkg.gitTag) return;
27
- const release = await options.onCreateRelease?.(pkg) ?? {};
28
+ const release = await options.onCreateRelease?.call(context, pkg) ?? {};
28
29
  if (release === false) return;
29
- await runGithubRelease(pkg.gitTag, release.title ?? defaultTitle(pkg), release.notes ?? defaultNotes(pkg), release.prerelease ?? prerelease(pkg.version) !== null);
30
+ await runGithubRelease(pkg.gitTag, release.title ?? defaultTitle(pkg), release.notes ?? await defaultNotes(context, pkg), release.prerelease ?? prerelease(pkg.version) !== null);
30
31
  }
31
- async function createGroupedRelease(packages) {
32
+ async function createGroupedRelease(context, packages) {
32
33
  const primary = packages[0];
33
34
  if (!primary?.gitTag) return;
34
- const release = await options.onCreateGroupedRelease?.(packages) ?? {};
35
+ const release = await options.onCreateGroupedRelease?.call(context, packages) ?? {};
35
36
  if (release === false) return;
36
- await runGithubRelease(primary.gitTag, release.title ?? defaultGroupedTitle(packages), release.notes ?? defaultGroupedNotes(packages), release.prerelease ?? packages.some((pkg) => prerelease(pkg.version) !== null));
37
+ await runGithubRelease(primary.gitTag, release.title ?? defaultGroupedTitle(packages), release.notes ?? await defaultGroupedNotes(context, packages), release.prerelease ?? packages.some((pkg) => prerelease(pkg.version) !== null));
37
38
  }
38
39
  function resolvePROptions() {
39
40
  const setting = options.cli?.versionPr ?? isCI();
@@ -49,20 +50,41 @@ function github(options = {}) {
49
50
  const distTagTxt = formatNpmDistTag(packagePlan.npm?.distTag);
50
51
  packageLines.push(`- ${pkg.name}@${cliOriginalPackageVersions.get(pkg.id) ?? pkg.version} → ${pkg.name}@${pkg.version}${distTagTxt}${publishTxt}`);
51
52
  }
52
- const changelogLines = draft.getChangelogs().map((entry) => `- ${entry.title}`);
53
- const sections = ["## Summary", ...packageLines];
53
+ const changelogLines = [];
54
+ for (const entry of draft.getChangelogs()) {
55
+ changelogLines.push(`### ${entry.subject ?? `\`${entry.filename}\``}`, "");
56
+ for (const section of entry.sections) {
57
+ changelogLines.push(`#### ${section.title}`, "");
58
+ changelogLines.push(section.content);
59
+ }
60
+ }
61
+ const sections = [
62
+ "## Summary",
63
+ "",
64
+ "Merge this PR to publish the versioned packages.",
65
+ "",
66
+ ...packageLines
67
+ ];
54
68
  if (changelogLines.length > 0) sections.push("", "## Changelogs", ...changelogLines);
55
- sections.push("", "Merge this PR to publish the versioned packages.");
69
+ sections.push("");
56
70
  return sections.join("\n");
57
71
  }
58
72
  const cliOriginalPackageVersions = /* @__PURE__ */ new Map();
59
73
  return [git(options), {
60
74
  name: "github",
75
+ init() {
76
+ const repository = options.repo ?? process.env.GITHUB_REPOSITORY;
77
+ const token = options.token ?? process.env.GITHUB_TOKEN ?? process.env.GH_TOKEN;
78
+ this.github = {
79
+ repo: repository,
80
+ token
81
+ };
82
+ },
61
83
  cli: {
62
84
  async init() {
63
85
  if (!isCI()) return;
64
- const token = process.env.GITHUB_TOKEN ?? process.env.GH_TOKEN;
65
- const repository = options.repo ?? process.env.GITHUB_REPOSITORY;
86
+ const repository = this.github?.repo;
87
+ const token = this.github?.token;
66
88
  if (!token || !repository) return;
67
89
  const result = await x("git", [
68
90
  "remote",
@@ -80,7 +102,7 @@ function github(options = {}) {
80
102
  const [enabled, config] = resolvePROptions();
81
103
  if (!enabled || !await hasGitChanges(cwd)) return;
82
104
  const { branch = "tegami/version-packages", base = "main" } = config;
83
- const basePR = await options.onCreateVersionPullRequest?.(draft);
105
+ const basePR = await options.onCreateVersionPullRequest?.call(this, draft);
84
106
  if (basePR === false) return;
85
107
  const pr = {
86
108
  title: basePR?.title ?? "Version Packages",
@@ -109,7 +131,22 @@ function github(options = {}) {
109
131
  branch
110
132
  ], gitOptions);
111
133
  if (result.exitCode !== 0) throw execFailure("Failed to push the version branch to origin. Ensure `origin` is configured and you have push access.", result);
112
- if (await hasOpenPullRequest(branch, options.repo)) return;
134
+ const openPr = await findOpenPullRequest(branch, options.repo);
135
+ if (openPr !== void 0) {
136
+ const editArgs = [
137
+ "pr",
138
+ "edit",
139
+ String(openPr),
140
+ "--title",
141
+ pr.title,
142
+ "--body",
143
+ pr.body
144
+ ];
145
+ if (options.repo) editArgs.push("--repo", options.repo);
146
+ const editResult = await x("gh", editArgs);
147
+ if (editResult.exitCode !== 0) throw execFailure("Failed to update the version pull request.", editResult);
148
+ return;
149
+ }
113
150
  const args = [
114
151
  "pr",
115
152
  "create",
@@ -129,15 +166,15 @@ function github(options = {}) {
129
166
  },
130
167
  async afterPublish(result) {
131
168
  if (result.state !== "created") return;
132
- for (const packages of groupPackagesByGitTag(result.packages).values()) if (packages.length > 1) await createGroupedRelease(packages);
133
- else await createRelease(packages[0]);
169
+ for (const packages of groupPackagesByGitTag(result.packages).values()) if (packages.length > 1) await createGroupedRelease(this, packages);
170
+ else await createRelease(this, packages[0]);
134
171
  }
135
172
  }];
136
173
  }
137
174
  async function hasGitChanges(cwd) {
138
175
  return (await x("git", ["status", "--porcelain"], { nodeOptions: { cwd } })).stdout.trim().length > 0;
139
176
  }
140
- async function hasOpenPullRequest(branch, repo) {
177
+ async function findOpenPullRequest(branch, repo) {
141
178
  const args = [
142
179
  "pr",
143
180
  "list",
@@ -151,7 +188,7 @@ async function hasOpenPullRequest(branch, repo) {
151
188
  if (repo) args.push("--repo", repo);
152
189
  const result = await x("gh", args);
153
190
  if (result.exitCode !== 0) throw execFailure("Failed to check for an existing version pull request.", result);
154
- return result.stdout.trim() !== "[]";
191
+ return JSON.parse(result.stdout)[0]?.number;
155
192
  }
156
193
  function groupPackagesByGitTag(packages) {
157
194
  const groups = /* @__PURE__ */ new Map();
@@ -171,16 +208,46 @@ function defaultGroupedTitle(packages) {
171
208
  const distTag = packages.every((pkg) => pkg.npm?.distTag === primary.npm?.distTag) ? primary.npm?.distTag : void 0;
172
209
  return formatPackageVersion(primary.gitTag.slice(0, primary.gitTag.lastIndexOf("@")), primary.version, distTag);
173
210
  }
174
- function defaultNotes(pkg) {
175
- if (pkg.changelogs.length > 0) return pkg.changelogs.map((entry) => [`### ${entry.title}`, entry.content].filter(Boolean).join("\n\n")).join("\n\n");
211
+ function formatCommitLink(commit, repo) {
212
+ const short = commit.slice(0, 7);
213
+ if (!repo) return `\`${short}\``;
214
+ return `[${short}](https://github.com/${repo}/commit/${commit})`;
215
+ }
216
+ async function resolveChangelogEntryCommit(context, filename) {
217
+ const result = await x("git", [
218
+ "log",
219
+ "--diff-filter=A",
220
+ "-1",
221
+ "--format=%H",
222
+ "--",
223
+ relative(context.cwd, join(context.changelogDir, filename))
224
+ ], { nodeOptions: { cwd: context.cwd } });
225
+ if (result.exitCode !== 0) return;
226
+ return result.stdout.trim() || void 0;
227
+ }
228
+ async function renderChangelogEntryNotes(context, entry) {
229
+ const repo = context.github?.repo;
230
+ const commit = await resolveChangelogEntryCommit(context, entry.filename);
231
+ const commitSuffix = commit ? ` (${formatCommitLink(commit, repo)})` : "";
232
+ const lines = [];
233
+ for (const section of entry.sections) {
234
+ lines.push(`### ${section.title}${commitSuffix}`, "");
235
+ if (section.content) lines.push(section.content, "");
236
+ }
237
+ return lines.join("\n").trim();
238
+ }
239
+ async function defaultNotes(context, pkg) {
240
+ if (pkg.changelogs.length > 0) return (await Promise.all(pkg.changelogs.map(async (entry) => renderChangelogEntryNotes(context, entry)))).join("\n\n");
176
241
  return `Published ${formatPackageVersion(pkg.name, pkg.version, pkg.npm?.distTag)}.`;
177
242
  }
178
- function defaultGroupedNotes(packages) {
243
+ async function defaultGroupedNotes(context, packages) {
179
244
  const changelogs = /* @__PURE__ */ new Map();
180
245
  for (const pkg of packages) for (const entry of pkg.changelogs) changelogs.set(entry.id, entry);
181
246
  const sections = [packages.map((pkg) => `- ${formatPackageVersion(pkg.name, pkg.version, pkg.npm?.distTag)}`).join("\n")];
182
- if (changelogs.size > 0) sections.push("", Array.from(changelogs.values()).map((entry) => [`### ${entry.title}`, entry.content].filter(Boolean).join("\n\n")).join("\n\n"));
183
- else sections.push("", `Published ${packages[0].gitTag}.`);
247
+ if (changelogs.size > 0) {
248
+ const notes = await Promise.all(Array.from(changelogs.values()).map((entry) => renderChangelogEntryNotes(context, entry)));
249
+ sections.push("", notes.join("\n\n"));
250
+ } else sections.push("", `Published ${packages[0].gitTag}.`);
184
251
  return sections.join("\n");
185
252
  }
186
253
  //#endregion
@@ -1,2 +1,2 @@
1
- import { g as cargo, h as CargoRegistryClient, m as CargoPluginOptions, p as CargoPackage } from "../index-Bhh2dJZp.js";
1
+ import { d as CargoRegistryClient, f as cargo, l as CargoPackage, u as CargoPluginOptions } from "../types-BNhcu4-X.js";
2
2
  export { CargoPackage, CargoPluginOptions, CargoRegistryClient, cargo };
@@ -1,5 +1,5 @@
1
1
  import { r as isNodeError } from "../error-DBK-9uBa.js";
2
- import { n as WorkspacePackage } from "../graph-CUgwuRW5.js";
2
+ import { n as WorkspacePackage } from "../graph-B22NBRUG.js";
3
3
  import { readFile, writeFile } from "node:fs/promises";
4
4
  import { join, normalize } from "node:path";
5
5
  import { x } from "tinyexec";
@@ -1,2 +1,2 @@
1
- import { _ as NpmPackage, b as npm, v as NpmPluginOptions, y as NpmRegistryClient } from "../index-Bhh2dJZp.js";
1
+ import { g as npm, h as NpmRegistryClient, m as NpmPluginOptions, p as NpmPackage } from "../types-BNhcu4-X.js";
2
2
  export { NpmPackage, NpmPluginOptions, NpmRegistryClient, npm };
@@ -1,6 +1,6 @@
1
1
  import { r as isNodeError, t as execFailure } from "../error-DBK-9uBa.js";
2
- import { n as WorkspacePackage } from "../graph-CUgwuRW5.js";
3
- import { i as pnpmWorkspaceSchema, r as packageManifestSchema } from "../schemas-Cc4h6bq5.js";
2
+ import { n as WorkspacePackage } from "../graph-B22NBRUG.js";
3
+ import { i as pnpmWorkspaceSchema, r as packageManifestSchema } from "../schemas-CurBAaW5.js";
4
4
  import { readFile, writeFile } from "node:fs/promises";
5
5
  import { join } from "node:path";
6
6
  import { x } from "tinyexec";
@@ -68,7 +68,7 @@ var NpmRegistryClient = class {
68
68
  "--json"
69
69
  ];
70
70
  if (registry) args.push("--registry", registry);
71
- const result = await x(this.client, args, { nodeOptions: { cwd: this.cwd } });
71
+ const result = await x(this.client === "pnpm" ? "pnpm" : "npm", args, { nodeOptions: { cwd: this.cwd } });
72
72
  if (result.exitCode === 0) return true;
73
73
  const output = commandOutput(result);
74
74
  if (isMissingRegistryEntry(output)) return false;
@@ -83,8 +83,9 @@ var NpmRegistryClient = class {
83
83
  const args = ["publish"];
84
84
  const distTag = packageStore.npm?.distTag;
85
85
  if (distTag) args.push("--tag", distTag);
86
- if (this.client === "pnpm") args.push("--no-git-checks");
87
- const result = await x(this.client, args, { nodeOptions: { cwd: pkg.path } });
86
+ const client = this.client === "pnpm" ? "pnpm" : "npm";
87
+ if (client === "pnpm") args.push("--no-git-checks");
88
+ const result = await x(client, args, { nodeOptions: { cwd: pkg.path } });
88
89
  if (result.exitCode !== 0) throw execFailure(`Failed to publish ${pkg.name}@${pkg.version}${distTag ? ` with dist-tag "${distTag}"` : ""}.`, result);
89
90
  }
90
91
  };
@@ -124,7 +125,7 @@ function formatDependencySpec(spec) {
124
125
  if (spec.protocol === "npm") return `npm:${spec.alias}@${spec.range}`;
125
126
  return spec.range;
126
127
  }
127
- function npm({ client: defaultClient, onBreakPeerDep = "set", bumpDep: getBumpDepType = ({ kind }) => {
128
+ function npm({ client: defaultClient, onBreakPeerDep = "set", updateLockFile = false, bumpDep: getBumpDepType = ({ kind }) => {
128
129
  switch (kind) {
129
130
  case "dependencies":
130
131
  case "optionalDependencies": return "patch";
@@ -235,7 +236,16 @@ function npm({ client: defaultClient, onBreakPeerDep = "set", bumpDep: getBumpDe
235
236
  writes.push(pkg.write());
236
237
  }
237
238
  await Promise.all(writes);
238
- }
239
+ },
240
+ cli: { async publishPlanApplied() {
241
+ if (!updateLockFile) return;
242
+ let args;
243
+ if (client === "npm") args = ["ci"];
244
+ else if (client === "yarn") args = ["install", "--immutable"];
245
+ else args = ["install", "--frozen-lockfile"];
246
+ const result = await x(client, args, { nodeOptions: { cwd: this.cwd } });
247
+ if (result.exitCode !== 0) throw execFailure("Failed to update lockfile.", result);
248
+ } }
239
249
  };
240
250
  }
241
251
  async function discoverNpmPackages(cwd, add) {
@@ -1,10 +1,11 @@
1
1
  import { z } from "zod";
2
2
  //#region src/schemas.ts
3
- const changelogFrontmatterSchema = z.object({
4
- subject: z.string().optional(),
5
- packages: z.array(z.string()).default([])
6
- });
7
3
  const stringRecordSchema = z.record(z.string(), z.string());
4
+ const bumpTypeSchema = z.enum([
5
+ "major",
6
+ "minor",
7
+ "patch"
8
+ ]);
8
9
  const jsonCodec = (schema) => z.codec(z.string(), schema, {
9
10
  decode: (jsonString, ctx) => {
10
11
  try {
@@ -38,4 +39,4 @@ const packageManifestSchema = z.looseObject({
38
39
  optionalDependencies: stringRecordSchema.optional()
39
40
  });
40
41
  //#endregion
41
- export { pnpmWorkspaceSchema as i, jsonCodec as n, packageManifestSchema as r, changelogFrontmatterSchema as t };
42
+ export { pnpmWorkspaceSchema as i, jsonCodec as n, packageManifestSchema as r, bumpTypeSchema as t };
@@ -11,6 +11,11 @@ const WEIGHTS = {
11
11
  minor: 2,
12
12
  patch: 1
13
13
  };
14
+ const DEPTH = {
15
+ major: 1,
16
+ minor: 2,
17
+ patch: 3
18
+ };
14
19
  const PRE = {
15
20
  major: "premajor",
16
21
  minor: "preminor",
@@ -20,6 +25,9 @@ function maxBump(a, b) {
20
25
  if (WEIGHTS[a] > WEIGHTS[b]) return a;
21
26
  return b;
22
27
  }
28
+ function bumpDepth(type) {
29
+ return DEPTH[type];
30
+ }
23
31
  function bumpVersion(version, type, prerelease) {
24
32
  let next = version;
25
33
  if (prerelease) {
@@ -30,4 +38,4 @@ function bumpVersion(version, type, prerelease) {
30
38
  return next;
31
39
  }
32
40
  //#endregion
33
- export { maxBump as i, formatNpmDistTag as n, formatPackageVersion as r, bumpVersion as t };
41
+ export { maxBump as a, formatPackageVersion as i, bumpVersion as n, formatNpmDistTag as r, bumpDepth as t };
@@ -1,61 +1,23 @@
1
1
  import { TomlTable } from "smol-toml";
2
2
  import z$1, { z } from "zod";
3
+ import { AgentName } from "package-manager-detector";
3
4
 
4
5
  //#region src/utils/semver.d.ts
5
6
  type BumpType = "major" | "minor" | "patch";
6
7
  //#endregion
7
- //#region src/graph.d.ts
8
- /** Package discovered in the workspace. */
9
- declare abstract class WorkspacePackage {
10
- abstract readonly name: string;
11
- abstract readonly path: string;
12
- abstract readonly manager: string;
13
- abstract readonly version: string;
14
- get id(): string;
15
- private opts;
16
- /** note: this will only be available after package graph is resolved */
17
- getPackageOptions(): PackageOptions;
18
- setPackageOptions(options: PackageOptions): void;
19
- /** create an empty draft plan. */
20
- onPlan(_context: TegamiContext): PackagePlan;
21
- }
22
- interface PackageGroup {
23
- name: string;
24
- options: GroupOptions;
25
- packages: WorkspacePackage[];
26
- }
27
- /** Dependency graph for discovered workspace packages. */
28
- declare class PackageGraph {
29
- private readonly packages;
30
- private readonly groups;
31
- constructor(packages?: WorkspacePackage[]);
32
- getPackages(): WorkspacePackage[];
33
- /** Get a package by exact id. */
34
- get(id: string): WorkspacePackage | undefined;
35
- /** Get packages by id, `group:name`, or every package matching a name. */
36
- getByName(nameOrId: string): WorkspacePackage[];
37
- /** scan package into graph, if the package id already exists, replace the existing one in graph */
38
- add(pkg: WorkspacePackage): void;
39
- delete(id: string): void;
40
- getPackageGroup(pkgId: string): PackageGroup | undefined;
41
- getGroups(): PackageGroup[];
42
- getGroup(name: string): PackageGroup | undefined;
43
- registerGroup(name: string, options: GroupOptions): PackageGroup;
44
- addGroupMember(groupId: string, id: string): void;
45
- removeGroupMember(group: string, id: string): void;
46
- unregisterGroup(name: string): void;
47
- }
48
- //#endregion
49
8
  //#region src/changelog/parse.d.ts
50
9
  interface ChangelogEntry {
51
10
  id: string;
52
11
  /** file name like `my-change.md` */
53
12
  filename: string;
54
13
  subject?: string;
55
- packages: Set<string>;
56
- type: BumpType;
57
- title: string;
58
- content: string;
14
+ packages: Map<string, BumpType>;
15
+ /** will not be empty */
16
+ sections: {
17
+ depth: number;
18
+ title: string;
19
+ content: string;
20
+ }[];
59
21
  }
60
22
  //#endregion
61
23
  //#region src/plans/draft.d.ts
@@ -116,6 +78,68 @@ type CleanupResult = {
116
78
  reason: "missing" | "pending";
117
79
  };
118
80
  //#endregion
81
+ //#region src/graph.d.ts
82
+ /** Package discovered in the workspace. */
83
+ declare abstract class WorkspacePackage {
84
+ abstract readonly name: string;
85
+ abstract readonly path: string;
86
+ abstract readonly manager: string;
87
+ abstract readonly version: string;
88
+ get id(): string;
89
+ private opts;
90
+ /** note: this will only be available after package graph is resolved */
91
+ getPackageOptions(): PackageOptions;
92
+ setPackageOptions(options: PackageOptions): void;
93
+ /** create an empty draft plan. */
94
+ onPlan(_context: TegamiContext): PackagePlan;
95
+ }
96
+ interface PackageGroup {
97
+ name: string;
98
+ options: GroupOptions;
99
+ packages: WorkspacePackage[];
100
+ }
101
+ /** Dependency graph for discovered workspace packages. */
102
+ declare class PackageGraph {
103
+ private readonly packages;
104
+ private readonly groups;
105
+ constructor(packages?: WorkspacePackage[]);
106
+ getPackages(): WorkspacePackage[];
107
+ /** Get a package by exact id. */
108
+ get(id: string): WorkspacePackage | undefined;
109
+ /** Get packages by id, `group:name`, or every package matching a name. */
110
+ getByName(nameOrId: string): WorkspacePackage[];
111
+ /** scan package into graph, if the package id already exists, replace the existing one in graph */
112
+ add(pkg: WorkspacePackage): void;
113
+ delete(id: string): void;
114
+ getPackageGroup(pkgId: string): PackageGroup | undefined;
115
+ getGroups(): PackageGroup[];
116
+ getGroup(name: string): PackageGroup | undefined;
117
+ registerGroup(name: string, options: GroupOptions): PackageGroup;
118
+ addGroupMember(groupId: string, id: string): void;
119
+ removeGroupMember(group: string, id: string): void;
120
+ unregisterGroup(name: string): void;
121
+ }
122
+ //#endregion
123
+ //#region src/context.d.ts
124
+ interface TegamiContext {
125
+ /** absolute path */
126
+ cwd: string;
127
+ /** absolute path */
128
+ changelogDir: string;
129
+ /** absolute path */
130
+ planPath: string;
131
+ options: TegamiOptions;
132
+ plugins: TegamiPlugin[];
133
+ graph: PackageGraph;
134
+ /** error if doesn't exist */
135
+ getRegistryClient(pkgOrId: WorkspacePackage | string): RegistryClient;
136
+ /** additional context when GitHub plugin is configured */
137
+ github?: {
138
+ repo?: string;
139
+ token?: string;
140
+ };
141
+ }
142
+ //#endregion
119
143
  //#region src/plans/store.d.ts
120
144
  declare const packagePlanStoreSchema: z$1.ZodObject<{
121
145
  type: z$1.ZodOptional<z$1.ZodEnum<{
@@ -138,14 +162,15 @@ declare const planStoreSchema: z$1.ZodCodec<z$1.ZodString, z$1.ZodObject<{
138
162
  changelogs: z$1.ZodRecord<z$1.ZodString, z$1.ZodObject<{
139
163
  filename: z$1.ZodString;
140
164
  subject: z$1.ZodOptional<z$1.ZodString>;
141
- packages: z$1.ZodArray<z$1.ZodString>;
142
- type: z$1.ZodEnum<{
165
+ packages: z$1.ZodRecord<z$1.ZodString, z$1.ZodEnum<{
143
166
  major: "major";
144
167
  minor: "minor";
145
168
  patch: "patch";
146
- }>;
147
- title: z$1.ZodString;
148
- content: z$1.ZodString;
169
+ }>>;
170
+ sections: z$1.ZodArray<z$1.ZodObject<{
171
+ title: z$1.ZodString;
172
+ content: z$1.ZodString;
173
+ }, z$1.core.$strip>>;
149
174
  }, z$1.core.$strip>>;
150
175
  packages: z$1.ZodRecord<z$1.ZodString, z$1.ZodObject<{
151
176
  type: z$1.ZodOptional<z$1.ZodEnum<{
@@ -197,6 +222,40 @@ type PackagePublishResult = ({
197
222
  changelogs: ChangelogEntry[];
198
223
  };
199
224
  //#endregion
225
+ //#region src/changelog/create.d.ts
226
+ interface CreateChangelogOptions {
227
+ /** Start revision. Defaults to the latest reachable git tag, or all history if none exists. */
228
+ from?: string;
229
+ /** End revision. Defaults to HEAD. */
230
+ to?: string;
231
+ }
232
+ interface CreatedChangelog {
233
+ filename: string;
234
+ path: string;
235
+ packages: string[];
236
+ changes: number;
237
+ }
238
+ //#endregion
239
+ //#region src/index.d.ts
240
+ interface Tegami {
241
+ /** Create pending changelog files from git commit history. */
242
+ generateChangelog(options?: CreateChangelogOptions): Promise<CreatedChangelog[]>;
243
+ /** Build a draft from pending changelog files. */
244
+ draft(): Promise<DraftPlan>;
245
+ /** Publish the current publish plan. */
246
+ publish(options?: PublishOptions): Promise<PublishResult>;
247
+ /** Remove the publish plan file after it has finished successfully. */
248
+ cleanup(): Promise<CleanupResult>;
249
+ /** Internal APIs, do not use it unless you know what you are doing */
250
+ _internal: {
251
+ context(): Promise<TegamiContext>;
252
+ graph(): Promise<PackageGraph>;
253
+ options: TegamiOptions;
254
+ };
255
+ }
256
+ /** Create a Tegami project handle. */
257
+ declare function tegami<const Groups extends string = string>(options?: TegamiOptions<Groups>): Tegami;
258
+ //#endregion
200
259
  //#region src/schemas.d.ts
201
260
  declare const packageManifestSchema: z.ZodObject<{
202
261
  name: z.ZodString;
@@ -230,13 +289,12 @@ declare class NpmPackage extends WorkspacePackage {
230
289
  write(): Promise<void>;
231
290
  onPlan(context: TegamiContext): PackagePlan;
232
291
  }
233
- type NpmClient = "npm" | "pnpm";
234
292
  declare class NpmRegistryClient implements RegistryClient {
235
293
  #private;
236
294
  private readonly cwd;
237
295
  private readonly client;
238
296
  readonly id = "npm";
239
- constructor(cwd: string, client: NpmClient, _graph: PackageGraph);
297
+ constructor(cwd: string, client: AgentName, _graph: PackageGraph);
240
298
  supports(pkg: WorkspacePackage): boolean;
241
299
  isPackagePublished(pkg: NpmPackage): Promise<boolean>;
242
300
  publish(pkg: NpmPackage, {
@@ -258,7 +316,7 @@ type DependencySpec = {
258
316
  };
259
317
  interface NpmPluginOptions {
260
318
  /** Package manager command used for npm registry operations. */
261
- client?: NpmClient;
319
+ client?: AgentName;
262
320
  /**
263
321
  * Decide how to bump the dependents of a bumped package.
264
322
  */
@@ -277,10 +335,13 @@ interface NpmPluginOptions {
277
335
  * Note: `workspace:` protocols are not included.
278
336
  */
279
337
  onBreakPeerDep?: "set" | "error" | "ignore";
338
+ /** update lockfile after appling publish plan */
339
+ updateLockFile?: boolean;
280
340
  }
281
341
  declare function npm({
282
342
  client: defaultClient,
283
343
  onBreakPeerDep,
344
+ updateLockFile,
284
345
  bumpDep: getBumpDepType
285
346
  }?: NpmPluginOptions): TegamiPlugin;
286
347
  //#endregion
@@ -386,6 +447,10 @@ interface TegamiPlugin {
386
447
  resolvePlanStatus?(this: TegamiContext, status: PublishPlanStatus, env: {
387
448
  plan: PlanStore;
388
449
  }): Awaitable<PublishPlanStatus>;
450
+ /** Called before a package will be published. */
451
+ willPublish?(this: TegamiContext, opts: {
452
+ pkg: WorkspacePackage;
453
+ }): Awaitable<PublishResult | void | undefined>;
389
454
  /** Called after publishing finishes. */
390
455
  afterPublish?(this: TegamiContext & {
391
456
  publishOptions: PublishOptions;
@@ -411,50 +476,4 @@ interface RegistryClient {
411
476
  }): Promise<void>;
412
477
  }
413
478
  //#endregion
414
- //#region src/context.d.ts
415
- interface TegamiContext {
416
- cwd: string;
417
- changelogDir: string;
418
- planPath: string;
419
- options: TegamiOptions;
420
- plugins: TegamiPlugin[];
421
- graph: PackageGraph;
422
- /** error if doesn't exist */
423
- getRegistryClient(pkgOrId: WorkspacePackage | string): RegistryClient;
424
- }
425
- //#endregion
426
- //#region src/changelog/create.d.ts
427
- interface CreateChangelogOptions {
428
- /** Start revision. Defaults to the latest reachable git tag, or all history if none exists. */
429
- from?: string;
430
- /** End revision. Defaults to HEAD. */
431
- to?: string;
432
- }
433
- interface CreatedChangelog {
434
- filename: string;
435
- path: string;
436
- packages: string[];
437
- changes: number;
438
- }
439
- //#endregion
440
- //#region src/index.d.ts
441
- interface Tegami {
442
- /** Create pending changelog files from git commit history. */
443
- generateChangelog(options?: CreateChangelogOptions): Promise<CreatedChangelog[]>;
444
- /** Build a draft from pending changelog files. */
445
- draft(): Promise<DraftPlan>;
446
- /** Publish the current publish plan. */
447
- publish(options?: PublishOptions): Promise<PublishResult>;
448
- /** Remove the publish plan file after it has finished successfully. */
449
- cleanup(): Promise<CleanupResult>;
450
- /** Internal APIs, do not use it unless you know what you are doing */
451
- _internal: {
452
- context(): Promise<TegamiContext>;
453
- graph(): Promise<PackageGraph>;
454
- options: TegamiOptions;
455
- };
456
- }
457
- /** Create a Tegami project handle. */
458
- declare function tegami<const Groups extends string = string>(options?: TegamiOptions<Groups>): Tegami;
459
- //#endregion
460
- export { PublishResult as C, PackageGroup as D, PackageGraph as E, WorkspacePackage as O, PublishOptions as S, PackagePlan as T, NpmPackage as _, Awaitable as a, npm as b, PackageOptions as c, TegamiPlugin as d, TegamiPluginOption as f, cargo as g, CargoRegistryClient as h, CreatedChangelog as i, RegistryClient as l, CargoPluginOptions as m, tegami as n, GroupOptions as o, CargoPackage as p, CreateChangelogOptions as r, LogGenerator as s, Tegami as t, TegamiOptions as u, NpmPluginOptions as v, DraftPlan as w, PackagePublishResult as x, NpmRegistryClient as y };
479
+ export { PublishResult as C, WorkspacePackage as D, PackageGroup as E, DraftPlan as O, PublishOptions as S, PackageGraph as T, Tegami as _, RegistryClient as a, CreatedChangelog as b, TegamiPluginOption as c, CargoRegistryClient as d, cargo as f, npm as g, NpmRegistryClient as h, PackageOptions as i, PackagePlan as k, CargoPackage as l, NpmPluginOptions as m, GroupOptions as n, TegamiOptions as o, NpmPackage as p, LogGenerator as r, TegamiPlugin as s, Awaitable as t, CargoPluginOptions as u, tegami as v, TegamiContext as w, PackagePublishResult as x, CreateChangelogOptions as y };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tegami",
3
- "version": "0.1.0-beta.0",
3
+ "version": "0.1.0-beta.2",
4
4
  "description": "Utility for package versioning & publish",
5
5
  "license": "MIT",
6
6
  "author": "Fuma Nama",