@forge-glance/sdk 0.1.1 → 0.2.1

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.
@@ -2,11 +2,13 @@ import type {
2
2
  BranchProtectionRule,
3
3
  CreatePullRequestInput,
4
4
  Discussion,
5
+ MergePullRequestInput,
5
6
  MRDetail,
7
+ ProviderCapabilities,
6
8
  PullRequest,
7
9
  UpdatePullRequestInput,
8
- UserRef,
9
- } from "./types.ts";
10
+ UserRef
11
+ } from './types.ts';
10
12
 
11
13
  /**
12
14
  * Provider-agnostic interface for a Git hosting service.
@@ -39,7 +41,7 @@ export interface GitProvider {
39
41
  fetchSingleMR(
40
42
  projectPath: string,
41
43
  mrIid: number,
42
- currentUserNumericId: number | null,
44
+ currentUserNumericId: number | null
43
45
  ): Promise<PullRequest | null>;
44
46
 
45
47
  /**
@@ -48,7 +50,7 @@ export interface GitProvider {
48
50
  */
49
51
  fetchPullRequestByBranch(
50
52
  projectPath: string,
51
- sourceBranch: string,
53
+ sourceBranch: string
52
54
  ): Promise<PullRequest | null>;
53
55
 
54
56
  /**
@@ -64,7 +66,7 @@ export interface GitProvider {
64
66
  updatePullRequest(
65
67
  projectPath: string,
66
68
  mrIid: number,
67
- input: UpdatePullRequestInput,
69
+ input: UpdatePullRequestInput
68
70
  ): Promise<PullRequest>;
69
71
 
70
72
  /**
@@ -72,26 +74,120 @@ export interface GitProvider {
72
74
  * Returns an array of rules (one per protected branch/pattern).
73
75
  */
74
76
  fetchBranchProtectionRules(
75
- projectPath: string,
77
+ projectPath: string
76
78
  ): Promise<BranchProtectionRule[]>;
77
79
 
78
80
  /**
79
81
  * Delete a branch from the repository.
80
82
  * @throws if the branch doesn't exist or is protected.
81
83
  */
82
- deleteBranch(
83
- projectPath: string,
84
- branch: string,
85
- ): Promise<void>;
84
+ deleteBranch(projectPath: string, branch: string): Promise<void>;
86
85
 
87
86
  /**
88
87
  * Fetch discussions (comments, threads) for a specific MR/PR.
89
88
  * Returns the MRDetail with discussions populated.
90
89
  */
91
- fetchMRDiscussions(
92
- repositoryId: string,
90
+ fetchMRDiscussions(repositoryId: string, mrIid: number): Promise<MRDetail>;
91
+
92
+ // ── Mutation capabilities ───────────────────────────────────────────────
93
+
94
+ /**
95
+ * Reports which mutation operations this provider supports.
96
+ * Callers should check these flags to conditionally show/hide UI
97
+ * affordances without knowing which provider they're talking to.
98
+ */
99
+ readonly capabilities: ProviderCapabilities;
100
+
101
+ // ── MR lifecycle mutations ──────────────────────────────────────────────
102
+
103
+ /**
104
+ * Merge (accept) a pull request / merge request.
105
+ * All input fields are optional — omitting them defers to the project's
106
+ * configured defaults (merge method, squash policy, delete-source-branch).
107
+ */
108
+ mergePullRequest(
109
+ projectPath: string,
110
+ mrIid: number,
111
+ input?: MergePullRequestInput
112
+ ): Promise<PullRequest>;
113
+
114
+ /**
115
+ * Approve a pull request / merge request.
116
+ * On GitLab: POST /merge_requests/:iid/approve
117
+ * On GitHub: POST /pulls/:number/reviews with event "APPROVE"
118
+ */
119
+ approvePullRequest(projectPath: string, mrIid: number): Promise<void>;
120
+
121
+ /**
122
+ * Revoke an existing approval.
123
+ * GitLab-only — GitHub does not support unapproving via API.
124
+ * Check `capabilities.canUnapprove` before calling.
125
+ */
126
+ unapprovePullRequest(projectPath: string, mrIid: number): Promise<void>;
127
+
128
+ /**
129
+ * Rebase the MR source branch onto the target branch.
130
+ * GitLab-only — GitHub does not have a native rebase API.
131
+ * Check `capabilities.canRebase` before calling.
132
+ */
133
+ rebasePullRequest(projectPath: string, mrIid: number): Promise<void>;
134
+
135
+ /**
136
+ * Enable auto-merge: the MR will be merged automatically when the
137
+ * pipeline succeeds and all approval rules are met.
138
+ * GitLab-only — check `capabilities.canAutoMerge` before calling.
139
+ */
140
+ setAutoMerge(projectPath: string, mrIid: number): Promise<void>;
141
+
142
+ /**
143
+ * Cancel a previously enabled auto-merge.
144
+ * GitLab-only — check `capabilities.canAutoMerge` before calling.
145
+ */
146
+ cancelAutoMerge(projectPath: string, mrIid: number): Promise<void>;
147
+
148
+ // ── Discussion mutations ────────────────────────────────────────────────
149
+
150
+ /**
151
+ * Resolve a discussion thread on an MR.
152
+ * GitLab-only — check `capabilities.canResolveDiscussions` before calling.
153
+ */
154
+ resolveDiscussion(
155
+ projectPath: string,
156
+ mrIid: number,
157
+ discussionId: string
158
+ ): Promise<void>;
159
+
160
+ /**
161
+ * Unresolve a previously resolved discussion thread.
162
+ * GitLab-only — check `capabilities.canResolveDiscussions` before calling.
163
+ */
164
+ unresolveDiscussion(
165
+ projectPath: string,
93
166
  mrIid: number,
94
- ): Promise<MRDetail>;
167
+ discussionId: string
168
+ ): Promise<void>;
169
+
170
+ // ── Pipeline mutations ──────────────────────────────────────────────────
171
+
172
+ /**
173
+ * Retry a failed or canceled pipeline.
174
+ * On GitLab: POST /pipelines/:id/retry
175
+ * On GitHub: POST re-run for the workflow run.
176
+ */
177
+ retryPipeline(projectPath: string, pipelineId: number): Promise<void>;
178
+
179
+ // ── Review mutations ────────────────────────────────────────────────────
180
+
181
+ /**
182
+ * Re-request review attention on an MR from its reviewers.
183
+ * If `reviewerUsernames` is provided, only those reviewers are pinged;
184
+ * otherwise all current reviewers are re-requested.
185
+ */
186
+ requestReReview(
187
+ projectPath: string,
188
+ mrIid: number,
189
+ reviewerUsernames?: string[]
190
+ ): Promise<void>;
95
191
 
96
192
  // ── REST pass-through (used by note mutations, job traces, etc.) ────────
97
193
 
@@ -102,11 +198,7 @@ export interface GitProvider {
102
198
  *
103
199
  * Implementations translate the path to the provider's API URL format.
104
200
  */
105
- restRequest(
106
- method: string,
107
- path: string,
108
- body?: unknown,
109
- ): Promise<Response>;
201
+ restRequest(method: string, path: string, body?: unknown): Promise<Response>;
110
202
  }
111
203
 
112
204
  /**
@@ -114,8 +206,8 @@ export interface GitProvider {
114
206
  * e.g. "gitlab:42" → 42, "github:12345" → 12345
115
207
  */
116
208
  export function parseRepoId(repositoryId: string): number {
117
- const parts = repositoryId.split(":");
118
- return parseInt(parts.at(-1) ?? "0", 10);
209
+ const parts = repositoryId.split(':');
210
+ return parseInt(parts.at(-1) ?? '0', 10);
119
211
  }
120
212
 
121
213
  /**
@@ -123,5 +215,5 @@ export function parseRepoId(repositoryId: string): number {
123
215
  * e.g. "gitlab:42" → "gitlab", "github:12345" → "github"
124
216
  */
125
217
  export function repoIdProvider(repositoryId: string): string {
126
- return repositoryId.split(":")[0] ?? "unknown";
218
+ return repositoryId.split(':')[0] ?? 'unknown';
127
219
  }
package/src/index.ts CHANGED
@@ -18,6 +18,9 @@ export type {
18
18
  PullRequestsSnapshot,
19
19
  CreatePullRequestInput,
20
20
  UpdatePullRequestInput,
21
+ MergePullRequestInput,
22
+ MergeMethod,
23
+ ProviderCapabilities,
21
24
  BranchProtectionRule,
22
25
  Pipeline,
23
26
  PipelineJob,
@@ -30,28 +33,32 @@ export type {
30
33
  MRDetail,
31
34
  FeedEvent,
32
35
  FeedSnapshot,
33
- ServerNotification,
34
- } from "./types.ts";
36
+ ServerNotification
37
+ } from './types.ts';
35
38
 
36
39
  // ── Provider interface ────────────────────────────────────────────────────────
37
- export type { GitProvider } from "./GitProvider.ts";
38
- export { parseRepoId, repoIdProvider } from "./GitProvider.ts";
40
+ export type { GitProvider } from './GitProvider.ts';
41
+ export { parseRepoId, repoIdProvider } from './GitProvider.ts';
39
42
 
40
43
  // ── Logger ────────────────────────────────────────────────────────────────────
41
- export type { ForgeLogger } from "./logger.ts";
42
- export { noopLogger } from "./logger.ts";
44
+ export type { ForgeLogger } from './logger.ts';
45
+ export { noopLogger } from './logger.ts';
43
46
 
44
47
  // ── Providers ─────────────────────────────────────────────────────────────────
45
- export { GitLabProvider, parseGitLabRepoId, MR_DASHBOARD_FRAGMENT } from "./GitLabProvider.ts";
46
- export { GitHubProvider } from "./GitHubProvider.ts";
47
- export { createProvider, SUPPORTED_PROVIDERS } from "./providers.ts";
48
- export type { ProviderSlug } from "./providers.ts";
48
+ export {
49
+ GitLabProvider,
50
+ parseGitLabRepoId,
51
+ MR_DASHBOARD_FRAGMENT
52
+ } from './GitLabProvider.ts';
53
+ export { GitHubProvider } from './GitHubProvider.ts';
54
+ export { createProvider, SUPPORTED_PROVIDERS } from './providers.ts';
55
+ export type { ProviderSlug } from './providers.ts';
49
56
 
50
57
  // ── GitLab real-time ──────────────────────────────────────────────────────────
51
- export { ActionCableClient } from "./ActionCableClient.ts";
52
- export type { ActionCableCallbacks } from "./ActionCableClient.ts";
58
+ export { ActionCableClient } from './ActionCableClient.ts';
59
+ export type { ActionCableCallbacks } from './ActionCableClient.ts';
53
60
 
54
61
  // ── GitLab detail + mutations ─────────────────────────────────────────────────
55
- export { MRDetailFetcher } from "./MRDetailFetcher.ts";
56
- export { NoteMutator } from "./NoteMutator.ts";
57
- export type { CreatedNote } from "./NoteMutator.ts";
62
+ export { MRDetailFetcher } from './MRDetailFetcher.ts';
63
+ export { NoteMutator } from './NoteMutator.ts';
64
+ export type { CreatedNote } from './NoteMutator.ts';
package/src/types.ts CHANGED
@@ -82,6 +82,17 @@ export interface PullRequest {
82
82
  * "not_approved", "discussions_not_resolved". Null for non-GitLab providers.
83
83
  */
84
84
  detailedMergeStatus: string | null;
85
+
86
+ // ── Auto-merge status ────────────────────────────────────────────────
87
+
88
+ /** Whether auto-merge (merge when pipeline succeeds) is currently enabled. */
89
+ autoMergeEnabled: boolean;
90
+ /** The merge strategy that will be used when auto-merge fires, e.g. "merge", "squash", "rebase_merge". */
91
+ autoMergeStrategy: string | null;
92
+ /** The user who merged or enabled auto-merge. */
93
+ mergeUser: UserRef | null;
94
+ /** ISO timestamp after which the MR is eligible to merge (scheduled merge). */
95
+ mergeAfter: string | null;
85
96
  }
86
97
 
87
98
  // ── MR/PR mutation inputs ─────────────────────────────────────────────────────
@@ -118,7 +129,65 @@ export interface UpdatePullRequestInput {
118
129
  /** Labels (replaces current set). */
119
130
  labels?: string[];
120
131
  /** Set MR state: "close" or "reopen". */
121
- stateEvent?: "close" | "reopen";
132
+ stateEvent?: 'close' | 'reopen';
133
+ }
134
+
135
+ /**
136
+ * Merge strategy override.
137
+ * - "merge" — Standard merge commit.
138
+ * - "squash" — Squash all commits into one before merging.
139
+ * - "rebase" — Rebase the source branch onto the target (fast-forward).
140
+ *
141
+ * When omitted, the provider uses the project's configured default merge method.
142
+ */
143
+ export type MergeMethod = 'merge' | 'squash' | 'rebase';
144
+
145
+ /**
146
+ * Input for merging (accepting) a pull request / merge request.
147
+ *
148
+ * All fields are **optional**. Omitting them defers to the project-level
149
+ * settings configured in the forge UI (merge method, squash policy,
150
+ * delete-source-branch, etc.). This matches how the web UI works.
151
+ */
152
+ export interface MergePullRequestInput {
153
+ /** Merge commit message. Omit to use the provider/project default. */
154
+ commitMessage?: string;
155
+ /** Squash commit message (when merge method is "squash"). */
156
+ squashCommitMessage?: string;
157
+ /** Whether to squash commits. Omit to use the MR / project default. */
158
+ squash?: boolean;
159
+ /** Merge strategy override. Omit to use the project's default merge method. */
160
+ mergeMethod?: MergeMethod;
161
+ /** Delete source branch after merge. Omit to use project default. */
162
+ shouldRemoveSourceBranch?: boolean;
163
+ /** SHA that HEAD must match for the merge to proceed (optimistic locking). */
164
+ sha?: string;
165
+ }
166
+
167
+ /**
168
+ * Reports which mutation operations a provider supports.
169
+ *
170
+ * Callers should check these flags before invoking vendor-specific methods
171
+ * so they can conditionally show/hide UI affordances without
172
+ * knowing which provider they're talking to.
173
+ */
174
+ export interface ProviderCapabilities {
175
+ /** Can merge / accept a pull request. */
176
+ canMerge: boolean;
177
+ /** Can approve a pull request. */
178
+ canApprove: boolean;
179
+ /** Can revoke an existing approval. */
180
+ canUnapprove: boolean;
181
+ /** Can rebase the source branch onto the target. */
182
+ canRebase: boolean;
183
+ /** Can enable automatic merge when pipeline succeeds. */
184
+ canAutoMerge: boolean;
185
+ /** Can resolve / unresolve discussion threads. */
186
+ canResolveDiscussions: boolean;
187
+ /** Can retry a pipeline. */
188
+ canRetryPipeline: boolean;
189
+ /** Can re-request review attention from reviewers. */
190
+ canRequestReReview: boolean;
122
191
  }
123
192
 
124
193
  /** Branch protection rule (provider-agnostic). */