tegami 1.0.0-beta.2 → 1.0.0-beta.4

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.
@@ -138,6 +138,12 @@ declare class PackageGraph {
138
138
  unregisterGroup(name: string): void;
139
139
  }
140
140
  //#endregion
141
+ //#region src/plugins/gitlab/api.d.ts
142
+ interface GitLabToken {
143
+ value: string;
144
+ type: "private-token" | "job-token";
145
+ }
146
+ //#endregion
141
147
  //#region src/context.d.ts
142
148
  interface TegamiContext {
143
149
  /** absolute path */
@@ -154,6 +160,13 @@ interface TegamiContext {
154
160
  repo?: string;
155
161
  token?: string;
156
162
  };
163
+ /** additional context when GitLab plugin is configured */
164
+ gitlab?: {
165
+ repo?: string;
166
+ token?: GitLabToken;
167
+ apiUrl?: string;
168
+ webUrl?: string;
169
+ };
157
170
  /** additional context when npm plugin is configured */
158
171
  npm?: {
159
172
  client: AgentName;
@@ -341,6 +354,95 @@ declare class PublishLock {
341
354
  serialize(): string;
342
355
  }
343
356
  //#endregion
357
+ //#region src/changelog/generate.d.ts
358
+ interface GenerateFromCommitsOptions {
359
+ /** Start revision. Defaults to the latest reachable git tag, or all history if none exists. */
360
+ from?: string;
361
+ /** End revision. Defaults to HEAD. */
362
+ to?: string;
363
+ }
364
+ interface CommitChangelog {
365
+ filename: string;
366
+ content: string;
367
+ packages: Record<string, BumpType | ChangelogPackageConfig>;
368
+ changes: CommitChange[];
369
+ }
370
+ interface CommitChange {
371
+ hash: string;
372
+ subject: string;
373
+ body: string;
374
+ packages: string[];
375
+ type: BumpType;
376
+ title: string;
377
+ }
378
+ //#endregion
379
+ //#region src/index.d.ts
380
+ interface GenerateChangelogOptions extends GenerateFromCommitsOptions {
381
+ /**
382
+ * Write changelog files to disk.
383
+ *
384
+ * @default true
385
+ */
386
+ write?: boolean;
387
+ }
388
+ interface Tegami {
389
+ /** Create pending changelog files from git commit history. */
390
+ generateChangelog(options?: GenerateChangelogOptions): Promise<CommitChangelog[]>;
391
+ /** Build a draft from pending changelog files. */
392
+ draft(): Promise<Draft>;
393
+ /** Publish packages from the publish lock. */
394
+ publish(options?: PublishOptions): Promise<PublishPlan | "skipped">;
395
+ /**
396
+ * Check publish status.
397
+ *
398
+ * Prefer `publish()` over this if you are publishing packages, it will also check the publish status.
399
+ */
400
+ publishStatus(): Promise<"pending" | "success" | "idle">;
401
+ /** Remove the publish lock file after publishing has finished successfully. */
402
+ cleanup(): Promise<{
403
+ state: "removed";
404
+ } | {
405
+ state: "skipped";
406
+ reason: "no-plan" | "pending";
407
+ }>;
408
+ /** Internal APIs, do not use it unless you know what you are doing */
409
+ _internal: {
410
+ context(): Promise<TegamiContext>; /** access context without requiring graph resolution */
411
+ contextUnresolved(): Promise<TegamiContext>;
412
+ options: TegamiOptions;
413
+ };
414
+ }
415
+ /** Create a Tegami project handle. */
416
+ declare function tegami<const Groups extends string = string>(options?: TegamiOptions<Groups>): Tegami;
417
+ //#endregion
418
+ //#region src/cli/core.d.ts
419
+ interface TegamiCliCommand<Values extends Record<string, boolean | string | undefined>, Positionals extends Record<string, string | undefined>> {
420
+ option<const Name extends string, const T extends "string" | "boolean">(name: Name, opts: {
421
+ type: T;
422
+ short?: string;
423
+ description?: string;
424
+ }): TegamiCliCommand<Values & { [k in Name]?: T extends "string" ? string : boolean }, Positionals>;
425
+ 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 }>;
426
+ action(fn: (options: {
427
+ context: TegamiContext;
428
+ values: Values;
429
+ positionals: Positionals;
430
+ }) => Awaitable<void>): void;
431
+ }
432
+ interface TegamiCliRegistry {
433
+ command(path: string, options?: {
434
+ description?: string;
435
+ /**
436
+ * If the package graph must be resolved to run this action.
437
+ *
438
+ * @default true
439
+ */
440
+ resolve?: boolean;
441
+ }): TegamiCliCommand<Record<never, never>, Record<never, never>>;
442
+ help(): string;
443
+ parse(argv: string[]): Promise<void>;
444
+ }
445
+ //#endregion
344
446
  //#region src/types.d.ts
345
447
  /** Generates changelog content for a package release. */
346
448
  interface LogGenerator {
@@ -376,6 +478,18 @@ interface TegamiOptions<Groups extends string = string> {
376
478
  npm?: NpmPluginOptions;
377
479
  cargo?: CargoPluginOptions;
378
480
  }
481
+ interface SharedGoOptions {
482
+ /**
483
+ * Whether to publish this module (create git tags).
484
+ *
485
+ * @default true
486
+ */
487
+ publish?: boolean;
488
+ }
489
+ interface SharedNpmOptions {
490
+ /** npm dist-tag used when publishing. */
491
+ distTag?: string;
492
+ }
379
493
  interface GroupOptions {
380
494
  /** Prerelease identifier appended to bumped versions (e.g. `alpha` → `1.1.0-alpha.0`). */
381
495
  prerelease?: string;
@@ -384,9 +498,9 @@ interface GroupOptions {
384
498
  /** when multiple packages in the group are published, only one git tag will be created (as well as GitHub release) */
385
499
  syncGitTag?: boolean;
386
500
  /** npm-specific options. */
387
- npm?: {
388
- /** npm dist-tag used when publishing. */distTag?: string;
389
- };
501
+ npm?: SharedNpmOptions;
502
+ /** go-specific options. */
503
+ go?: SharedGoOptions;
390
504
  }
391
505
  interface PackageOptions<Group extends string = string> {
392
506
  /** Prerelease identifier appended to bumped versions (e.g. `alpha` → `1.1.0-alpha.0`). */
@@ -394,16 +508,18 @@ interface PackageOptions<Group extends string = string> {
394
508
  /** the group of this package, ignored if the group doesn't exist */
395
509
  group?: Group;
396
510
  /** npm-specific options. */
397
- npm?: {
398
- /** npm dist-tag used when publishing. */distTag?: string;
399
- };
511
+ npm?: SharedNpmOptions;
512
+ /** go-specific options. */
513
+ go?: SharedGoOptions;
400
514
  }
401
515
  type TegamiPluginOption = TegamiPlugin | TegamiPluginOption[];
402
516
  interface TegamiPlugin {
403
517
  name: string;
404
518
  enforce?: "pre" | "default" | "post";
405
- /** When Tegami initializes */
519
+ /** When Tegami initializes. */
406
520
  init?(this: TegamiContext): Awaitable<void>;
521
+ /** When Tegami CLI initializes, this runs before `resolve()`. */
522
+ initCli?(this: TegamiContext, cli: TegamiCliRegistry): Awaitable<void>;
407
523
  /** Resolve workspace packages and dependency metadata into the shared graph. */
408
524
  resolve?(this: TegamiContext): Awaitable<void>;
409
525
  /** Called when Tegami creates an empty draft. */
@@ -455,12 +571,10 @@ interface TegamiPlugin {
455
571
  afterPublishAll?(this: TegamiContext, opts: {
456
572
  plan: PublishPlan;
457
573
  }): Awaitable<void>;
458
- /** CLI lifecycle hooks. */
459
- cli?: {
460
- /** Called once before a CLI command runs. */init?(this: TegamiContext): Awaitable<void>; /** Called after `tegami version` returns a draft. */
461
- draftCreated?(this: TegamiContext, draft: Draft): Awaitable<void>; /** Called after `tegami version` applies a draft. */
462
- draftApplied?(this: TegamiContext, draft: Draft): Awaitable<void>;
463
- };
574
+ /** Called after `tegami version` returns a draft. */
575
+ initCliDraft?(this: TegamiContext, draft: Draft): Awaitable<void>;
576
+ /** Called after `tegami version` applies a draft. */
577
+ applyCliDraft?(this: TegamiContext, draft: Draft): Awaitable<void>;
464
578
  }
465
579
  type Awaitable<T> = T | Promise<T>;
466
580
  interface PublishPreflight {
@@ -478,4 +592,4 @@ interface PublishPreflight {
478
592
  wait?: string[];
479
593
  }
480
594
  //#endregion
481
- export { WorkspacePackage as C, ChangelogPackageConfig as D, PackageDraft as E, BumpType as O, PackageGroup as S, DraftPolicy as T, NpmPackage as _, PublishPreflight as a, TegamiContext as b, TegamiPluginOption as c, PackagePublishResult as d, PublishOptions as f, cargo as g, CargoPluginOptions as h, PackageOptions as i, PublishLock as l, CargoPackage as m, GroupOptions as n, TegamiOptions as o, PublishPlan as p, LogGenerator as r, TegamiPlugin as s, Awaitable as t, PackagePublishPlan as u, NpmPluginOptions as v, Draft as w, PackageGraph as x, npm as y };
595
+ export { PackageDraft as A, npm as C, WorkspacePackage as D, PackageGroup as E, Draft as O, NpmPluginOptions as S, PackageGraph as T, PublishPlan as _, PublishPreflight as a, cargo as b, TegamiPluginOption as c, tegami as d, CommitChangelog as f, PublishOptions as g, PackagePublishResult as h, PackageOptions as i, BumpType as j, DraftPolicy as k, GenerateChangelogOptions as l, PackagePublishPlan as m, GroupOptions as n, TegamiOptions as o, PublishLock as p, LogGenerator as r, TegamiPlugin as s, Awaitable as t, Tegami as u, CargoPackage as v, TegamiContext as w, NpmPackage as x, CargoPluginOptions as y };
@@ -0,0 +1,69 @@
1
+ import { r as formatNpmDistTag } from "./semver-EKJ8yK5U.js";
2
+ import { n as execFailure } from "./error-We7chQVJ.js";
3
+ import { x } from "tinyexec";
4
+ //#region src/utils/version-request.ts
5
+ async function hasGitChanges(cwd) {
6
+ return (await x("git", ["status", "--porcelain"], { nodeOptions: { cwd } })).stdout.trim().length > 0;
7
+ }
8
+ async function commitVersionBranchChanges(cwd, branch, title) {
9
+ const gitOptions = { nodeOptions: { cwd } };
10
+ let result = await x("git", [
11
+ "checkout",
12
+ "-B",
13
+ branch
14
+ ], gitOptions);
15
+ if (result.exitCode !== 0) throw execFailure("Failed to create the version branch.", result);
16
+ result = await x("git", ["add", "-A"], gitOptions);
17
+ if (result.exitCode !== 0) throw execFailure("Failed to stage version changes.", result);
18
+ result = await x("git", [
19
+ "commit",
20
+ "-m",
21
+ title
22
+ ], gitOptions);
23
+ if (result.exitCode !== 0) throw execFailure("Failed to commit version changes.", result);
24
+ result = await x("git", [
25
+ "push",
26
+ "--force",
27
+ "-u",
28
+ "origin",
29
+ branch
30
+ ], gitOptions);
31
+ if (result.exitCode !== 0) throw execFailure("Failed to push the version branch to origin. Ensure `origin` is configured and you have push access.", result);
32
+ }
33
+ function createVersionRequestBody(draft, context, snapshots, summary) {
34
+ const packageLines = [];
35
+ const changesets = /* @__PURE__ */ new Map();
36
+ for (const [id, packageDraft] of draft.getPackageDrafts()) {
37
+ const pkg = context.graph.get(id);
38
+ if (!pkg) continue;
39
+ for (const entry of packageDraft.changelogs ?? []) {
40
+ const list = changesets.get(entry);
41
+ if (list) list.push(pkg);
42
+ else changesets.set(entry, [pkg]);
43
+ }
44
+ const originalVersion = snapshots.get(pkg.id);
45
+ if (!originalVersion || originalVersion === pkg.version) continue;
46
+ packageLines.push(`| \`${pkg.name}\` | \`${originalVersion}\` | \`${pkg.version}\`${formatNpmDistTag(packageDraft.npm?.distTag)} |`);
47
+ }
48
+ const changelogLines = [];
49
+ for (const [entry, linkedPackages] of changesets) {
50
+ changelogLines.push(`### ${entry.subject ?? `\`${entry.filename}\``}`, "");
51
+ changelogLines.push("<details>", `<summary>Show Bumped Packages (${linkedPackages.length})</summary>`, "", ...linkedPackages.map((pkg) => `- \`${pkg.id}\``), "", "</details>", "");
52
+ for (const section of entry.sections) {
53
+ changelogLines.push(`#### ${section.title}`, "");
54
+ if (section.content) changelogLines.push(section.content);
55
+ }
56
+ }
57
+ const sections = [
58
+ "## Summary",
59
+ "",
60
+ summary,
61
+ ""
62
+ ];
63
+ if (packageLines.length > 0) sections.push("| Package | From | To |", "| --- | --- | --- |", ...packageLines);
64
+ if (changelogLines.length > 0) sections.push("", "## Changelogs", ...changelogLines);
65
+ sections.push("");
66
+ return sections.join("\n");
67
+ }
68
+ //#endregion
69
+ export { createVersionRequestBody as n, hasGitChanges as r, commitVersionBranchChanges as t };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tegami",
3
- "version": "1.0.0-beta.2",
3
+ "version": "1.0.0-beta.4",
4
4
  "description": "Utility for package versioning & publish",
5
5
  "license": "MIT",
6
6
  "author": "Fuma Nama",
@@ -18,6 +18,7 @@
18
18
  "./generators/simple": "./dist/generators/simple.js",
19
19
  "./plugins/git": "./dist/plugins/git.js",
20
20
  "./plugins/github": "./dist/plugins/github.js",
21
+ "./plugins/gitlab": "./dist/plugins/gitlab.js",
21
22
  "./plugins/go": "./dist/plugins/go.js",
22
23
  "./providers/cargo": "./dist/providers/cargo.js",
23
24
  "./providers/npm": "./dist/providers/npm.js",
@@ -29,10 +30,7 @@
29
30
  "dependencies": {
30
31
  "@clack/prompts": "^1.6.0",
31
32
  "@rainbowatcher/toml-edit-js": "^0.6.5",
32
- "commander": "^15.0.0",
33
33
  "js-yaml": "^5.1.0",
34
- "mdast-util-from-markdown": "^2.0.3",
35
- "mdast-util-to-markdown": "^2.1.2",
36
34
  "package-manager-detector": "^1.6.0",
37
35
  "semver": "^7.8.5",
38
36
  "tinyexec": "^1.2.4",
@@ -40,7 +38,6 @@
40
38
  "zod": "^4.4.3"
41
39
  },
42
40
  "devDependencies": {
43
- "@types/mdast": "^4.0.4",
44
41
  "@types/node": "^26.0.0",
45
42
  "@types/semver": "^7.7.1",
46
43
  "tsdown": "^0.22.3",
@@ -1,116 +0,0 @@
1
- //#region src/plugins/github/api.ts
2
- function parseGitHubRepo(repo) {
3
- const [owner, name] = repo.split("/", 2);
4
- if (!owner || !name) throw new Error(`Invalid GitHub repository: ${repo}`);
5
- return {
6
- owner,
7
- repo: name
8
- };
9
- }
10
- async function githubRequest(path, token, init = {}) {
11
- const headers = new Headers(init.headers);
12
- headers.set("Accept", "application/vnd.github+json");
13
- headers.set("X-GitHub-Api-Version", "2022-11-28");
14
- if (token) headers.set("Authorization", `Bearer ${token}`);
15
- return fetch(`https://api.github.com${path}`, {
16
- ...init,
17
- headers
18
- });
19
- }
20
- async function releaseExistsByTag(repo, tag, token) {
21
- const { owner, repo: name } = parseGitHubRepo(repo);
22
- const response = await githubRequest(`/repos/${owner}/${name}/releases/tags/${encodeURIComponent(tag)}`, token, { method: "HEAD" });
23
- if (response.status === 404) return false;
24
- if (!response.ok) throw new Error(`Failed to get GitHub release for ${tag}.`);
25
- return true;
26
- }
27
- async function createRelease(repo, options) {
28
- const { owner, repo: name } = parseGitHubRepo(repo);
29
- if (!(await githubRequest(`/repos/${owner}/${name}/releases`, options.token, {
30
- method: "POST",
31
- headers: { "Content-Type": "application/json" },
32
- body: JSON.stringify({
33
- tag_name: options.tag,
34
- name: options.title,
35
- body: options.notes,
36
- prerelease: options.prerelease ?? false
37
- })
38
- })).ok) throw new Error(`Failed to create GitHub release for ${options.tag}.`);
39
- }
40
- async function findOpenPullRequest(repo, headBranch, token) {
41
- const { owner, repo: name } = parseGitHubRepo(repo);
42
- const response = await githubRequest(`/repos/${owner}/${name}/pulls?${new URLSearchParams({
43
- head: `${owner}:${headBranch}`,
44
- state: "open"
45
- })}`, token);
46
- if (!response.ok) throw new Error("Failed to check for an existing version pull request.");
47
- return (await response.json())[0]?.number;
48
- }
49
- async function updatePullRequest(repo, number, options) {
50
- const { owner, repo: name } = parseGitHubRepo(repo);
51
- if (!(await githubRequest(`/repos/${owner}/${name}/pulls/${number}`, options.token, {
52
- method: "PATCH",
53
- headers: { "Content-Type": "application/json" },
54
- body: JSON.stringify({
55
- title: options.title,
56
- body: options.body
57
- })
58
- })).ok) throw new Error("Failed to update the version pull request.");
59
- }
60
- async function createPullRequest(repo, options) {
61
- const { owner, repo: name } = parseGitHubRepo(repo);
62
- if (!(await githubRequest(`/repos/${owner}/${name}/pulls`, options.token, {
63
- method: "POST",
64
- headers: { "Content-Type": "application/json" },
65
- body: JSON.stringify({
66
- title: options.title,
67
- body: options.body,
68
- head: options.head,
69
- base: options.base
70
- })
71
- })).ok) throw new Error("Failed to create the version pull request.");
72
- }
73
- async function getPullRequest(repo, number, token) {
74
- const { owner, repo: name } = parseGitHubRepo(repo);
75
- const response = await githubRequest(`/repos/${owner}/${name}/pulls/${number}`, token);
76
- if (!response.ok) throw new Error(`Failed to resolve pull request #${number}.`);
77
- const data = await response.json();
78
- return {
79
- headRefName: data.head.ref,
80
- baseRefOid: data.base.sha,
81
- headRefOid: data.head.sha,
82
- headRepository: data.head.repo
83
- };
84
- }
85
- async function findIssueCommentByPrefix(repo, issueNumber, prefix, token) {
86
- const { owner, repo: name } = parseGitHubRepo(repo);
87
- let page = 1;
88
- while (true) {
89
- const response = await githubRequest(`/repos/${owner}/${name}/issues/${issueNumber}/comments?per_page=100&page=${page}`, token);
90
- if (!response.ok) throw new Error("Failed to list pull request comments.");
91
- const batch = await response.json();
92
- if (batch.length === 0) break;
93
- const comment = batch.find((comment) => comment.body.startsWith(prefix));
94
- if (comment) return comment.id;
95
- if (batch.length < 100) break;
96
- page += 1;
97
- }
98
- }
99
- async function updateIssueComment(repo, commentId, body, token) {
100
- const { owner, repo: name } = parseGitHubRepo(repo);
101
- if (!(await githubRequest(`/repos/${owner}/${name}/issues/comments/${commentId}`, token, {
102
- method: "PATCH",
103
- headers: { "Content-Type": "application/json" },
104
- body: JSON.stringify({ body })
105
- })).ok) throw new Error("Failed to update pull request comment.");
106
- }
107
- async function createIssueComment(repo, issueNumber, body, token) {
108
- const { owner, repo: name } = parseGitHubRepo(repo);
109
- if (!(await githubRequest(`/repos/${owner}/${name}/issues/${issueNumber}/comments`, token, {
110
- method: "POST",
111
- headers: { "Content-Type": "application/json" },
112
- body: JSON.stringify({ body })
113
- })).ok) throw new Error("Failed to create pull request comment.");
114
- }
115
- //#endregion
116
- export { findOpenPullRequest as a, updateIssueComment as c, findIssueCommentByPrefix as i, updatePullRequest as l, createPullRequest as n, getPullRequest as o, createRelease as r, releaseExistsByTag as s, createIssueComment as t };
@@ -1,64 +0,0 @@
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
-
3
- //#region src/changelog/generate.d.ts
4
- interface GenerateFromCommitsOptions {
5
- /** Start revision. Defaults to the latest reachable git tag, or all history if none exists. */
6
- from?: string;
7
- /** End revision. Defaults to HEAD. */
8
- to?: string;
9
- }
10
- interface CommitChangelog {
11
- filename: string;
12
- content: string;
13
- packages: Record<string, BumpType | ChangelogPackageConfig>;
14
- changes: CommitChange[];
15
- }
16
- interface CommitChange {
17
- hash: string;
18
- subject: string;
19
- body: string;
20
- packages: string[];
21
- type: BumpType;
22
- title: string;
23
- }
24
- //#endregion
25
- //#region src/index.d.ts
26
- interface GenerateChangelogOptions extends GenerateFromCommitsOptions {
27
- /**
28
- * Write changelog files to disk.
29
- *
30
- * @default true
31
- */
32
- write?: boolean;
33
- }
34
- interface Tegami {
35
- /** Create pending changelog files from git commit history. */
36
- generateChangelog(options?: GenerateChangelogOptions): Promise<CommitChangelog[]>;
37
- /** Build a draft from pending changelog files. */
38
- draft(): Promise<Draft>;
39
- /** Publish packages from the publish lock. */
40
- publish(options?: PublishOptions): Promise<PublishPlan | "skipped">;
41
- /**
42
- * Check publish status.
43
- *
44
- * Prefer `publish()` over this if you are publishing packages, it will also check the publish status.
45
- */
46
- publishStatus(): Promise<"pending" | "success" | "idle">;
47
- /** Remove the publish lock file after publishing has finished successfully. */
48
- cleanup(): Promise<{
49
- state: "removed";
50
- } | {
51
- state: "skipped";
52
- reason: "no-plan" | "pending";
53
- }>;
54
- /** Internal APIs, do not use it unless you know what you are doing */
55
- _internal: {
56
- context(): Promise<TegamiContext>;
57
- graph(): Promise<PackageGraph>;
58
- options: TegamiOptions;
59
- };
60
- }
61
- /** Create a Tegami project handle. */
62
- declare function tegami<const Groups extends string = string>(options?: TegamiOptions<Groups>): Tegami;
63
- //#endregion
64
- export { CommitChangelog as i, Tegami as n, tegami as r, GenerateChangelogOptions as t };