@stoneforge/quarry 1.10.2 → 1.13.0
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.
- package/README.md +3 -1
- package/dist/cli/commands/admin.d.ts.map +1 -1
- package/dist/cli/commands/admin.js +313 -3
- package/dist/cli/commands/admin.js.map +1 -1
- package/dist/cli/commands/auto-link-helper.d.ts +33 -0
- package/dist/cli/commands/auto-link-helper.d.ts.map +1 -0
- package/dist/cli/commands/auto-link-helper.js +73 -0
- package/dist/cli/commands/auto-link-helper.js.map +1 -0
- package/dist/cli/commands/crud.d.ts +1 -0
- package/dist/cli/commands/crud.d.ts.map +1 -1
- package/dist/cli/commands/crud.js +44 -5
- package/dist/cli/commands/crud.js.map +1 -1
- package/dist/cli/commands/docs.d.ts +1 -0
- package/dist/cli/commands/docs.d.ts.map +1 -1
- package/dist/cli/commands/docs.js +81 -1
- package/dist/cli/commands/docs.js.map +1 -1
- package/dist/cli/commands/external-sync.d.ts +17 -0
- package/dist/cli/commands/external-sync.d.ts.map +1 -0
- package/dist/cli/commands/external-sync.js +1647 -0
- package/dist/cli/commands/external-sync.js.map +1 -0
- package/dist/cli/commands/log.d.ts +18 -0
- package/dist/cli/commands/log.d.ts.map +1 -0
- package/dist/cli/commands/log.js +282 -0
- package/dist/cli/commands/log.js.map +1 -0
- package/dist/cli/commands/metrics.d.ts +9 -0
- package/dist/cli/commands/metrics.d.ts.map +1 -0
- package/dist/cli/commands/metrics.js +219 -0
- package/dist/cli/commands/metrics.js.map +1 -0
- package/dist/cli/runner.d.ts.map +1 -1
- package/dist/cli/runner.js +8 -0
- package/dist/cli/runner.js.map +1 -1
- package/dist/config/config.d.ts.map +1 -1
- package/dist/config/config.js +28 -0
- package/dist/config/config.js.map +1 -1
- package/dist/config/defaults.d.ts +13 -1
- package/dist/config/defaults.d.ts.map +1 -1
- package/dist/config/defaults.js +21 -0
- package/dist/config/defaults.js.map +1 -1
- package/dist/config/file.d.ts.map +1 -1
- package/dist/config/file.js +61 -0
- package/dist/config/file.js.map +1 -1
- package/dist/config/index.d.ts +3 -3
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +2 -2
- package/dist/config/index.js.map +1 -1
- package/dist/config/merge.d.ts.map +1 -1
- package/dist/config/merge.js +46 -1
- package/dist/config/merge.js.map +1 -1
- package/dist/config/types.d.ts +63 -1
- package/dist/config/types.d.ts.map +1 -1
- package/dist/config/types.js +30 -0
- package/dist/config/types.js.map +1 -1
- package/dist/config/validation.d.ts.map +1 -1
- package/dist/config/validation.js +51 -1
- package/dist/config/validation.js.map +1 -1
- package/dist/external-sync/adapters/task-sync-adapter.d.ts +177 -0
- package/dist/external-sync/adapters/task-sync-adapter.d.ts.map +1 -0
- package/dist/external-sync/adapters/task-sync-adapter.js +353 -0
- package/dist/external-sync/adapters/task-sync-adapter.js.map +1 -0
- package/dist/external-sync/auto-link.d.ts +66 -0
- package/dist/external-sync/auto-link.d.ts.map +1 -0
- package/dist/external-sync/auto-link.js +98 -0
- package/dist/external-sync/auto-link.js.map +1 -0
- package/dist/external-sync/conflict-resolver.d.ts +170 -0
- package/dist/external-sync/conflict-resolver.d.ts.map +1 -0
- package/dist/external-sync/conflict-resolver.js +580 -0
- package/dist/external-sync/conflict-resolver.js.map +1 -0
- package/dist/external-sync/index.d.ts +20 -0
- package/dist/external-sync/index.d.ts.map +1 -0
- package/dist/external-sync/index.js +20 -0
- package/dist/external-sync/index.js.map +1 -0
- package/dist/external-sync/provider-registry.d.ts +109 -0
- package/dist/external-sync/provider-registry.d.ts.map +1 -0
- package/dist/external-sync/provider-registry.js +188 -0
- package/dist/external-sync/provider-registry.js.map +1 -0
- package/dist/external-sync/providers/github/github-api.d.ts +271 -0
- package/dist/external-sync/providers/github/github-api.d.ts.map +1 -0
- package/dist/external-sync/providers/github/github-api.js +366 -0
- package/dist/external-sync/providers/github/github-api.js.map +1 -0
- package/dist/external-sync/providers/github/github-field-map.d.ts +76 -0
- package/dist/external-sync/providers/github/github-field-map.d.ts.map +1 -0
- package/dist/external-sync/providers/github/github-field-map.js +157 -0
- package/dist/external-sync/providers/github/github-field-map.js.map +1 -0
- package/dist/external-sync/providers/github/github-provider.d.ts +36 -0
- package/dist/external-sync/providers/github/github-provider.d.ts.map +1 -0
- package/dist/external-sync/providers/github/github-provider.js +212 -0
- package/dist/external-sync/providers/github/github-provider.js.map +1 -0
- package/dist/external-sync/providers/github/github-task-adapter.d.ts +135 -0
- package/dist/external-sync/providers/github/github-task-adapter.d.ts.map +1 -0
- package/dist/external-sync/providers/github/github-task-adapter.js +374 -0
- package/dist/external-sync/providers/github/github-task-adapter.js.map +1 -0
- package/dist/external-sync/providers/github/index.d.ts +12 -0
- package/dist/external-sync/providers/github/index.d.ts.map +1 -0
- package/dist/external-sync/providers/github/index.js +15 -0
- package/dist/external-sync/providers/github/index.js.map +1 -0
- package/dist/external-sync/providers/index.d.ts +9 -0
- package/dist/external-sync/providers/index.d.ts.map +1 -0
- package/dist/external-sync/providers/index.js +10 -0
- package/dist/external-sync/providers/index.js.map +1 -0
- package/dist/external-sync/providers/linear/index.d.ts +19 -0
- package/dist/external-sync/providers/linear/index.d.ts.map +1 -0
- package/dist/external-sync/providers/linear/index.js +19 -0
- package/dist/external-sync/providers/linear/index.js.map +1 -0
- package/dist/external-sync/providers/linear/linear-api.d.ts +252 -0
- package/dist/external-sync/providers/linear/linear-api.d.ts.map +1 -0
- package/dist/external-sync/providers/linear/linear-api.js +522 -0
- package/dist/external-sync/providers/linear/linear-api.js.map +1 -0
- package/dist/external-sync/providers/linear/linear-field-map.d.ts +135 -0
- package/dist/external-sync/providers/linear/linear-field-map.d.ts.map +1 -0
- package/dist/external-sync/providers/linear/linear-field-map.js +338 -0
- package/dist/external-sync/providers/linear/linear-field-map.js.map +1 -0
- package/dist/external-sync/providers/linear/linear-provider.d.ts +52 -0
- package/dist/external-sync/providers/linear/linear-provider.d.ts.map +1 -0
- package/dist/external-sync/providers/linear/linear-provider.js +169 -0
- package/dist/external-sync/providers/linear/linear-provider.js.map +1 -0
- package/dist/external-sync/providers/linear/linear-task-adapter.d.ts +190 -0
- package/dist/external-sync/providers/linear/linear-task-adapter.d.ts.map +1 -0
- package/dist/external-sync/providers/linear/linear-task-adapter.js +521 -0
- package/dist/external-sync/providers/linear/linear-task-adapter.js.map +1 -0
- package/dist/external-sync/providers/linear/linear-types.d.ts +114 -0
- package/dist/external-sync/providers/linear/linear-types.d.ts.map +1 -0
- package/dist/external-sync/providers/linear/linear-types.js +10 -0
- package/dist/external-sync/providers/linear/linear-types.js.map +1 -0
- package/dist/external-sync/sync-engine.d.ts +298 -0
- package/dist/external-sync/sync-engine.d.ts.map +1 -0
- package/dist/external-sync/sync-engine.js +785 -0
- package/dist/external-sync/sync-engine.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/services/inbox.js +1 -1
- package/dist/sync/hash.d.ts +5 -0
- package/dist/sync/hash.d.ts.map +1 -1
- package/dist/sync/hash.js +21 -2
- package/dist/sync/hash.js.map +1 -1
- package/package.json +11 -5
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHub REST API Client
|
|
3
|
+
*
|
|
4
|
+
* Pure fetch-based client for GitHub issue operations.
|
|
5
|
+
* Supports Personal Access Token (PAT) auth, rate limit handling,
|
|
6
|
+
* and configurable base URL for GitHub Enterprise.
|
|
7
|
+
*
|
|
8
|
+
* No external dependencies — uses only the standard fetch API.
|
|
9
|
+
*/
|
|
10
|
+
// ============================================================================
|
|
11
|
+
// Error Types
|
|
12
|
+
// ============================================================================
|
|
13
|
+
/**
|
|
14
|
+
* Typed error for GitHub API failures.
|
|
15
|
+
* Wraps fetch errors with status code, message, and rate limit info.
|
|
16
|
+
*/
|
|
17
|
+
export class GitHubApiError extends Error {
|
|
18
|
+
/** HTTP status code from GitHub's response */
|
|
19
|
+
status;
|
|
20
|
+
/** Human-readable error message from GitHub */
|
|
21
|
+
statusText;
|
|
22
|
+
/** Rate limit information at the time of the error */
|
|
23
|
+
rateLimit;
|
|
24
|
+
/** Parsed error body from GitHub (if available) */
|
|
25
|
+
responseBody;
|
|
26
|
+
constructor(message, status, statusText, rateLimit = null, responseBody = null, cause) {
|
|
27
|
+
super(message);
|
|
28
|
+
this.name = 'GitHubApiError';
|
|
29
|
+
this.status = status;
|
|
30
|
+
this.statusText = statusText;
|
|
31
|
+
this.rateLimit = rateLimit;
|
|
32
|
+
this.responseBody = responseBody;
|
|
33
|
+
this.cause = cause;
|
|
34
|
+
if (Error.captureStackTrace) {
|
|
35
|
+
Error.captureStackTrace(this, GitHubApiError);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Whether this error is due to rate limiting
|
|
40
|
+
*/
|
|
41
|
+
get isRateLimited() {
|
|
42
|
+
return this.status === 403 && this.rateLimit !== null && this.rateLimit.remaining === 0;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Whether this error is due to authentication failure
|
|
46
|
+
*/
|
|
47
|
+
get isAuthError() {
|
|
48
|
+
return this.status === 401;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Whether this error is a not-found response
|
|
52
|
+
*/
|
|
53
|
+
get isNotFound() {
|
|
54
|
+
return this.status === 404;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Returns a JSON-serializable representation of the error
|
|
58
|
+
*/
|
|
59
|
+
toJSON() {
|
|
60
|
+
return {
|
|
61
|
+
name: this.name,
|
|
62
|
+
message: this.message,
|
|
63
|
+
status: this.status,
|
|
64
|
+
statusText: this.statusText,
|
|
65
|
+
rateLimit: this.rateLimit,
|
|
66
|
+
responseBody: this.responseBody,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Type guard for GitHubApiError
|
|
72
|
+
*/
|
|
73
|
+
export function isGitHubApiError(error) {
|
|
74
|
+
return error instanceof GitHubApiError;
|
|
75
|
+
}
|
|
76
|
+
// ============================================================================
|
|
77
|
+
// Rate Limit Warning Threshold
|
|
78
|
+
// ============================================================================
|
|
79
|
+
/** Default threshold of remaining requests before logging a warning */
|
|
80
|
+
const DEFAULT_RATE_LIMIT_WARNING_THRESHOLD = 10;
|
|
81
|
+
// ============================================================================
|
|
82
|
+
// Client Implementation
|
|
83
|
+
// ============================================================================
|
|
84
|
+
/**
|
|
85
|
+
* Fetch-based GitHub REST API client for issue operations.
|
|
86
|
+
*
|
|
87
|
+
* Features:
|
|
88
|
+
* - Personal Access Token (PAT) authentication
|
|
89
|
+
* - Rate limit tracking with warnings when approaching limit
|
|
90
|
+
* - Configurable base URL for GitHub Enterprise
|
|
91
|
+
* - Typed errors with status code and rate limit info
|
|
92
|
+
* - Automatic pagination for listing issues
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* ```typescript
|
|
96
|
+
* const client = new GitHubApiClient({ token: 'ghp_...' });
|
|
97
|
+
* const issue = await client.getIssue('owner', 'repo', 42);
|
|
98
|
+
* const issues = await client.listIssues('owner', 'repo', { state: 'open' });
|
|
99
|
+
* ```
|
|
100
|
+
*/
|
|
101
|
+
export class GitHubApiClient {
|
|
102
|
+
token;
|
|
103
|
+
apiBaseUrl;
|
|
104
|
+
rateLimitWarningThreshold;
|
|
105
|
+
/** Most recently observed rate limit info (updated after each request) */
|
|
106
|
+
lastRateLimit = null;
|
|
107
|
+
constructor(options) {
|
|
108
|
+
if (!options.token) {
|
|
109
|
+
throw new Error('GitHub API token is required');
|
|
110
|
+
}
|
|
111
|
+
this.token = options.token;
|
|
112
|
+
this.apiBaseUrl = (options.apiBaseUrl ?? 'https://api.github.com').replace(/\/$/, '');
|
|
113
|
+
this.rateLimitWarningThreshold =
|
|
114
|
+
options.rateLimitWarningThreshold ?? DEFAULT_RATE_LIMIT_WARNING_THRESHOLD;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Returns the most recently observed rate limit info, or null if no requests have been made.
|
|
118
|
+
*/
|
|
119
|
+
getRateLimit() {
|
|
120
|
+
return this.lastRateLimit;
|
|
121
|
+
}
|
|
122
|
+
// --------------------------------------------------------------------------
|
|
123
|
+
// Public API Methods
|
|
124
|
+
// --------------------------------------------------------------------------
|
|
125
|
+
/**
|
|
126
|
+
* Fetch a single issue by number.
|
|
127
|
+
*
|
|
128
|
+
* GET /repos/{owner}/{repo}/issues/{issue_number}
|
|
129
|
+
*/
|
|
130
|
+
async getIssue(owner, repo, issueNumber) {
|
|
131
|
+
return this.request('GET', `/repos/${enc(owner)}/${enc(repo)}/issues/${issueNumber}`);
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* List issues for a repository.
|
|
135
|
+
*
|
|
136
|
+
* GET /repos/{owner}/{repo}/issues?since=...&state=all
|
|
137
|
+
*
|
|
138
|
+
* When no explicit `page` is provided, this method automatically iterates
|
|
139
|
+
* through all pages using the Link header and returns every matching issue.
|
|
140
|
+
* When a `page` is specified, only that single page is returned.
|
|
141
|
+
*/
|
|
142
|
+
async listIssues(owner, repo, options = {}) {
|
|
143
|
+
const params = new URLSearchParams();
|
|
144
|
+
if (options.since)
|
|
145
|
+
params.set('since', options.since);
|
|
146
|
+
if (options.state)
|
|
147
|
+
params.set('state', options.state);
|
|
148
|
+
if (options.per_page)
|
|
149
|
+
params.set('per_page', String(options.per_page));
|
|
150
|
+
// If a specific page was requested, fetch only that page
|
|
151
|
+
if (options.page !== undefined) {
|
|
152
|
+
params.set('page', String(options.page));
|
|
153
|
+
const path = `/repos/${enc(owner)}/${enc(repo)}/issues`;
|
|
154
|
+
const queryString = params.toString();
|
|
155
|
+
const url = queryString ? `${path}?${queryString}` : path;
|
|
156
|
+
return this.request('GET', url);
|
|
157
|
+
}
|
|
158
|
+
// Otherwise, auto-paginate through all pages
|
|
159
|
+
return this.paginatedRequest(`/repos/${enc(owner)}/${enc(repo)}/issues`, params);
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Create a new issue.
|
|
163
|
+
*
|
|
164
|
+
* POST /repos/{owner}/{repo}/issues
|
|
165
|
+
*/
|
|
166
|
+
async createIssue(owner, repo, input) {
|
|
167
|
+
return this.request('POST', `/repos/${enc(owner)}/${enc(repo)}/issues`, input);
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Update an existing issue.
|
|
171
|
+
*
|
|
172
|
+
* PATCH /repos/{owner}/{repo}/issues/{issue_number}
|
|
173
|
+
*/
|
|
174
|
+
async updateIssue(owner, repo, issueNumber, updates) {
|
|
175
|
+
return this.request('PATCH', `/repos/${enc(owner)}/${enc(repo)}/issues/${issueNumber}`, updates);
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* List all labels for a repository.
|
|
179
|
+
*
|
|
180
|
+
* GET /repos/{owner}/{repo}/labels
|
|
181
|
+
*
|
|
182
|
+
* Auto-paginates through all pages to return the complete label set.
|
|
183
|
+
*/
|
|
184
|
+
async getLabels(owner, repo) {
|
|
185
|
+
return this.paginatedRequest(`/repos/${enc(owner)}/${enc(repo)}/labels`, new URLSearchParams());
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Create a new label on a repository.
|
|
189
|
+
*
|
|
190
|
+
* POST /repos/{owner}/{repo}/labels
|
|
191
|
+
*/
|
|
192
|
+
async createLabel(owner, repo, input) {
|
|
193
|
+
return this.request('POST', `/repos/${enc(owner)}/${enc(repo)}/labels`, input);
|
|
194
|
+
}
|
|
195
|
+
// --------------------------------------------------------------------------
|
|
196
|
+
// Internal: HTTP Request Handling
|
|
197
|
+
// --------------------------------------------------------------------------
|
|
198
|
+
/**
|
|
199
|
+
* Performs a single HTTP request to the GitHub API.
|
|
200
|
+
*/
|
|
201
|
+
async request(method, path, body) {
|
|
202
|
+
const url = `${this.apiBaseUrl}${path}`;
|
|
203
|
+
const headers = {
|
|
204
|
+
Authorization: `Bearer ${this.token}`,
|
|
205
|
+
Accept: 'application/vnd.github+json',
|
|
206
|
+
'X-GitHub-Api-Version': '2022-11-28',
|
|
207
|
+
};
|
|
208
|
+
if (body !== undefined) {
|
|
209
|
+
headers['Content-Type'] = 'application/json';
|
|
210
|
+
}
|
|
211
|
+
let response;
|
|
212
|
+
try {
|
|
213
|
+
response = await fetch(url, {
|
|
214
|
+
method,
|
|
215
|
+
headers,
|
|
216
|
+
body: body !== undefined ? JSON.stringify(body) : undefined,
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
catch (err) {
|
|
220
|
+
throw new GitHubApiError(`Network error requesting ${method} ${path}: ${err instanceof Error ? err.message : String(err)}`, 0, 'Network Error', null, null, err instanceof Error ? err : undefined);
|
|
221
|
+
}
|
|
222
|
+
// Parse rate limit headers from every response
|
|
223
|
+
const rateLimit = parseRateLimitHeaders(response.headers);
|
|
224
|
+
if (rateLimit) {
|
|
225
|
+
this.lastRateLimit = rateLimit;
|
|
226
|
+
this.checkRateLimitWarning(rateLimit, method, path);
|
|
227
|
+
}
|
|
228
|
+
if (!response.ok) {
|
|
229
|
+
await this.handleErrorResponse(response, rateLimit, method, path);
|
|
230
|
+
}
|
|
231
|
+
return (await response.json());
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Performs a paginated request, following Link headers to collect all pages.
|
|
235
|
+
*/
|
|
236
|
+
async paginatedRequest(basePath, params) {
|
|
237
|
+
const allItems = [];
|
|
238
|
+
// Start at page 1 if not set
|
|
239
|
+
if (!params.has('page')) {
|
|
240
|
+
params.set('page', '1');
|
|
241
|
+
}
|
|
242
|
+
// Default to 100 per page for efficiency if not set
|
|
243
|
+
if (!params.has('per_page')) {
|
|
244
|
+
params.set('per_page', '100');
|
|
245
|
+
}
|
|
246
|
+
let nextUrl = `${this.apiBaseUrl}${basePath}?${params.toString()}`;
|
|
247
|
+
while (nextUrl) {
|
|
248
|
+
const headers = {
|
|
249
|
+
Authorization: `Bearer ${this.token}`,
|
|
250
|
+
Accept: 'application/vnd.github+json',
|
|
251
|
+
'X-GitHub-Api-Version': '2022-11-28',
|
|
252
|
+
};
|
|
253
|
+
let response;
|
|
254
|
+
try {
|
|
255
|
+
response = await fetch(nextUrl, { method: 'GET', headers });
|
|
256
|
+
}
|
|
257
|
+
catch (err) {
|
|
258
|
+
throw new GitHubApiError(`Network error during paginated request to ${nextUrl}: ${err instanceof Error ? err.message : String(err)}`, 0, 'Network Error', null, null, err instanceof Error ? err : undefined);
|
|
259
|
+
}
|
|
260
|
+
const rateLimit = parseRateLimitHeaders(response.headers);
|
|
261
|
+
if (rateLimit) {
|
|
262
|
+
this.lastRateLimit = rateLimit;
|
|
263
|
+
this.checkRateLimitWarning(rateLimit, 'GET', basePath);
|
|
264
|
+
}
|
|
265
|
+
if (!response.ok) {
|
|
266
|
+
await this.handleErrorResponse(response, rateLimit, 'GET', basePath);
|
|
267
|
+
}
|
|
268
|
+
const items = (await response.json());
|
|
269
|
+
allItems.push(...items);
|
|
270
|
+
// Parse Link header for next page
|
|
271
|
+
nextUrl = parseLinkHeaderNext(response.headers.get('Link'));
|
|
272
|
+
}
|
|
273
|
+
return allItems;
|
|
274
|
+
}
|
|
275
|
+
// --------------------------------------------------------------------------
|
|
276
|
+
// Internal: Error and Rate Limit Handling
|
|
277
|
+
// --------------------------------------------------------------------------
|
|
278
|
+
/**
|
|
279
|
+
* Handles non-OK responses by throwing a GitHubApiError.
|
|
280
|
+
*/
|
|
281
|
+
async handleErrorResponse(response, rateLimit, method, path) {
|
|
282
|
+
let responseBody = null;
|
|
283
|
+
let errorMessage;
|
|
284
|
+
try {
|
|
285
|
+
responseBody = (await response.json());
|
|
286
|
+
errorMessage =
|
|
287
|
+
typeof responseBody.message === 'string'
|
|
288
|
+
? responseBody.message
|
|
289
|
+
: `GitHub API error: ${response.status} ${response.statusText}`;
|
|
290
|
+
}
|
|
291
|
+
catch {
|
|
292
|
+
errorMessage = `GitHub API error: ${response.status} ${response.statusText}`;
|
|
293
|
+
}
|
|
294
|
+
// Special messaging for rate limit exhaustion
|
|
295
|
+
if (response.status === 403 && rateLimit && rateLimit.remaining === 0) {
|
|
296
|
+
const resetDate = new Date(rateLimit.reset * 1000);
|
|
297
|
+
errorMessage = `GitHub API rate limit exhausted. Resets at ${resetDate.toISOString()} (${rateLimit.reset}). ${errorMessage}`;
|
|
298
|
+
}
|
|
299
|
+
throw new GitHubApiError(`${method} ${path} failed: ${errorMessage}`, response.status, response.statusText, rateLimit, responseBody);
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Logs a warning when rate limit is approaching exhaustion.
|
|
303
|
+
*/
|
|
304
|
+
checkRateLimitWarning(rateLimit, method, path) {
|
|
305
|
+
if (rateLimit.remaining <= this.rateLimitWarningThreshold && rateLimit.remaining > 0) {
|
|
306
|
+
const resetDate = new Date(rateLimit.reset * 1000);
|
|
307
|
+
console.warn(`[GitHubApiClient] Rate limit warning: ${rateLimit.remaining}/${rateLimit.limit} requests remaining. ` +
|
|
308
|
+
`Resets at ${resetDate.toISOString()}. ` +
|
|
309
|
+
`Triggered by ${method} ${path}`);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
// ============================================================================
|
|
314
|
+
// Utility Functions
|
|
315
|
+
// ============================================================================
|
|
316
|
+
/**
|
|
317
|
+
* URI-encodes a path segment for safe inclusion in URLs.
|
|
318
|
+
*/
|
|
319
|
+
function enc(value) {
|
|
320
|
+
return encodeURIComponent(value);
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Parses rate limit information from GitHub response headers.
|
|
324
|
+
* Returns null if the headers are not present.
|
|
325
|
+
*/
|
|
326
|
+
function parseRateLimitHeaders(headers) {
|
|
327
|
+
const limit = headers.get('X-RateLimit-Limit');
|
|
328
|
+
const remaining = headers.get('X-RateLimit-Remaining');
|
|
329
|
+
const reset = headers.get('X-RateLimit-Reset');
|
|
330
|
+
if (limit === null || remaining === null || reset === null) {
|
|
331
|
+
return null;
|
|
332
|
+
}
|
|
333
|
+
const parsedLimit = parseInt(limit, 10);
|
|
334
|
+
const parsedRemaining = parseInt(remaining, 10);
|
|
335
|
+
const parsedReset = parseInt(reset, 10);
|
|
336
|
+
if (isNaN(parsedLimit) || isNaN(parsedRemaining) || isNaN(parsedReset)) {
|
|
337
|
+
return null;
|
|
338
|
+
}
|
|
339
|
+
return {
|
|
340
|
+
limit: parsedLimit,
|
|
341
|
+
remaining: parsedRemaining,
|
|
342
|
+
reset: parsedReset,
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
/**
|
|
346
|
+
* Parses the GitHub Link header to find the "next" page URL.
|
|
347
|
+
* Returns null if there is no next page.
|
|
348
|
+
*
|
|
349
|
+
* The Link header format is:
|
|
350
|
+
* <https://api.github.com/...?page=2>; rel="next", <https://api.github.com/...?page=5>; rel="last"
|
|
351
|
+
*/
|
|
352
|
+
function parseLinkHeaderNext(linkHeader) {
|
|
353
|
+
if (!linkHeader)
|
|
354
|
+
return null;
|
|
355
|
+
const links = linkHeader.split(',');
|
|
356
|
+
for (const link of links) {
|
|
357
|
+
const match = link.match(/<([^>]+)>;\s*rel="next"/);
|
|
358
|
+
if (match) {
|
|
359
|
+
return match[1];
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
return null;
|
|
363
|
+
}
|
|
364
|
+
// Export utility functions for testing
|
|
365
|
+
export { parseRateLimitHeaders, parseLinkHeaderNext };
|
|
366
|
+
//# sourceMappingURL=github-api.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github-api.js","sourceRoot":"","sources":["../../../../src/external-sync/providers/github/github-api.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHub Field Map Configuration
|
|
3
|
+
*
|
|
4
|
+
* Defines how Stoneforge task fields map to GitHub issue fields.
|
|
5
|
+
* Used by the GitHubTaskAdapter and the shared task sync adapter utilities.
|
|
6
|
+
*
|
|
7
|
+
* Key mappings:
|
|
8
|
+
* - Priority (1-5) -> labels with 'priority:' prefix
|
|
9
|
+
* - TaskType (bug/feature/task/chore) -> labels with 'type:' prefix
|
|
10
|
+
* - Status -> GitHub issue state ('open' or 'closed')
|
|
11
|
+
* - Tags -> labels (user-managed, no prefix)
|
|
12
|
+
* - Sync-managed labels use the 'sf:' prefix
|
|
13
|
+
*/
|
|
14
|
+
import type { TaskStatus, Priority, TaskTypeValue } from '@stoneforge/core';
|
|
15
|
+
import type { TaskSyncFieldMapConfig } from '../../adapters/task-sync-adapter.js';
|
|
16
|
+
/**
|
|
17
|
+
* Maps Stoneforge priority values (1-5) to GitHub label names.
|
|
18
|
+
* These labels are prefixed with 'sf:' when pushed to GitHub to
|
|
19
|
+
* distinguish sync-managed labels from user-created labels.
|
|
20
|
+
*/
|
|
21
|
+
export declare const GITHUB_PRIORITY_LABELS: Record<Priority, string>;
|
|
22
|
+
/**
|
|
23
|
+
* Maps Stoneforge task type values to GitHub label names.
|
|
24
|
+
* These labels are prefixed with 'sf:' when pushed to GitHub.
|
|
25
|
+
*/
|
|
26
|
+
export declare const GITHUB_TASK_TYPE_LABELS: Record<TaskTypeValue, string>;
|
|
27
|
+
/**
|
|
28
|
+
* Prefix for Stoneforge-managed labels on GitHub issues.
|
|
29
|
+
* Labels with this prefix are created and managed by the sync system.
|
|
30
|
+
* User labels without this prefix are preserved during sync.
|
|
31
|
+
*/
|
|
32
|
+
export declare const GITHUB_SYNC_LABEL_PREFIX = "sf:";
|
|
33
|
+
/**
|
|
34
|
+
* Maps Stoneforge TaskStatus values to GitHub label names.
|
|
35
|
+
* These labels are prefixed with 'sf:' when pushed to GitHub to
|
|
36
|
+
* provide granular status visibility beyond GitHub's binary open/closed state.
|
|
37
|
+
*/
|
|
38
|
+
export declare const GITHUB_STATUS_LABELS: Record<TaskStatus, string>;
|
|
39
|
+
/**
|
|
40
|
+
* Maps Stoneforge TaskStatus to GitHub issue state.
|
|
41
|
+
*
|
|
42
|
+
* GitHub only supports two issue states: 'open' and 'closed'.
|
|
43
|
+
* Most Stoneforge statuses map to 'open' since GitHub can't
|
|
44
|
+
* distinguish between open, in_progress, review, blocked, etc.
|
|
45
|
+
*
|
|
46
|
+
* Mapping:
|
|
47
|
+
* - open, in_progress, review, blocked, deferred, backlog -> 'open'
|
|
48
|
+
* - closed, tombstone -> 'closed'
|
|
49
|
+
*/
|
|
50
|
+
export declare function statusToGitHubState(status: TaskStatus): 'open' | 'closed';
|
|
51
|
+
/**
|
|
52
|
+
* Maps GitHub issue state + labels back to Stoneforge TaskStatus.
|
|
53
|
+
*
|
|
54
|
+
* Uses sf:status:* labels for granular status inference when available.
|
|
55
|
+
* If a status label is found, it takes precedence over the basic
|
|
56
|
+
* open/closed state mapping. Falls back to the simple state mapping
|
|
57
|
+
* when no status label is present.
|
|
58
|
+
*
|
|
59
|
+
* Mapping with labels:
|
|
60
|
+
* - 'sf:status:in-progress' → 'in_progress'
|
|
61
|
+
* - 'sf:status:blocked' → 'blocked'
|
|
62
|
+
* - etc.
|
|
63
|
+
*
|
|
64
|
+
* Fallback mapping (no status label):
|
|
65
|
+
* - 'open' → 'open'
|
|
66
|
+
* - 'closed' → 'closed'
|
|
67
|
+
*/
|
|
68
|
+
export declare function gitHubStateToStatus(state: 'open' | 'closed', labels: string[]): TaskStatus;
|
|
69
|
+
/**
|
|
70
|
+
* Complete GitHub-specific field mapping configuration.
|
|
71
|
+
*
|
|
72
|
+
* Used by the shared task sync adapter utilities to convert between
|
|
73
|
+
* Stoneforge tasks and GitHub issues (in both push and pull directions).
|
|
74
|
+
*/
|
|
75
|
+
export declare const GITHUB_FIELD_MAP_CONFIG: TaskSyncFieldMapConfig;
|
|
76
|
+
//# sourceMappingURL=github-field-map.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github-field-map.d.ts","sourceRoot":"","sources":["../../../../src/external-sync/providers/github/github-field-map.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAC5E,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,qCAAqC,CAAC;AAMlF;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAM/B,CAAC;AAM9B;;;GAGG;AACH,eAAO,MAAM,uBAAuB,EAAE,MAAM,CAAC,aAAa,EAAE,MAAM,CAKhC,CAAC;AAMnC;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,QAAQ,CAAC;AAM9C;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM,CAS3D,CAAC;AAMF;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,GAAG,QAAQ,CAczE;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,MAAM,GAAG,QAAQ,EACxB,MAAM,EAAE,MAAM,EAAE,GACf,UAAU,CA0BZ;AAMD;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,EAAE,sBAOrC,CAAC"}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHub Field Map Configuration
|
|
3
|
+
*
|
|
4
|
+
* Defines how Stoneforge task fields map to GitHub issue fields.
|
|
5
|
+
* Used by the GitHubTaskAdapter and the shared task sync adapter utilities.
|
|
6
|
+
*
|
|
7
|
+
* Key mappings:
|
|
8
|
+
* - Priority (1-5) -> labels with 'priority:' prefix
|
|
9
|
+
* - TaskType (bug/feature/task/chore) -> labels with 'type:' prefix
|
|
10
|
+
* - Status -> GitHub issue state ('open' or 'closed')
|
|
11
|
+
* - Tags -> labels (user-managed, no prefix)
|
|
12
|
+
* - Sync-managed labels use the 'sf:' prefix
|
|
13
|
+
*/
|
|
14
|
+
// ============================================================================
|
|
15
|
+
// Priority Label Mapping
|
|
16
|
+
// ============================================================================
|
|
17
|
+
/**
|
|
18
|
+
* Maps Stoneforge priority values (1-5) to GitHub label names.
|
|
19
|
+
* These labels are prefixed with 'sf:' when pushed to GitHub to
|
|
20
|
+
* distinguish sync-managed labels from user-created labels.
|
|
21
|
+
*/
|
|
22
|
+
export const GITHUB_PRIORITY_LABELS = {
|
|
23
|
+
1: 'priority:critical',
|
|
24
|
+
2: 'priority:high',
|
|
25
|
+
3: 'priority:medium',
|
|
26
|
+
4: 'priority:low',
|
|
27
|
+
5: 'priority:minimal',
|
|
28
|
+
};
|
|
29
|
+
// ============================================================================
|
|
30
|
+
// Task Type Label Mapping
|
|
31
|
+
// ============================================================================
|
|
32
|
+
/**
|
|
33
|
+
* Maps Stoneforge task type values to GitHub label names.
|
|
34
|
+
* These labels are prefixed with 'sf:' when pushed to GitHub.
|
|
35
|
+
*/
|
|
36
|
+
export const GITHUB_TASK_TYPE_LABELS = {
|
|
37
|
+
bug: 'type:bug',
|
|
38
|
+
feature: 'type:feature',
|
|
39
|
+
task: 'type:task',
|
|
40
|
+
chore: 'type:chore',
|
|
41
|
+
};
|
|
42
|
+
// ============================================================================
|
|
43
|
+
// Sync Label Prefix
|
|
44
|
+
// ============================================================================
|
|
45
|
+
/**
|
|
46
|
+
* Prefix for Stoneforge-managed labels on GitHub issues.
|
|
47
|
+
* Labels with this prefix are created and managed by the sync system.
|
|
48
|
+
* User labels without this prefix are preserved during sync.
|
|
49
|
+
*/
|
|
50
|
+
export const GITHUB_SYNC_LABEL_PREFIX = 'sf:';
|
|
51
|
+
// ============================================================================
|
|
52
|
+
// Status Label Mapping
|
|
53
|
+
// ============================================================================
|
|
54
|
+
/**
|
|
55
|
+
* Maps Stoneforge TaskStatus values to GitHub label names.
|
|
56
|
+
* These labels are prefixed with 'sf:' when pushed to GitHub to
|
|
57
|
+
* provide granular status visibility beyond GitHub's binary open/closed state.
|
|
58
|
+
*/
|
|
59
|
+
export const GITHUB_STATUS_LABELS = {
|
|
60
|
+
open: 'status:open',
|
|
61
|
+
in_progress: 'status:in-progress',
|
|
62
|
+
blocked: 'status:blocked',
|
|
63
|
+
deferred: 'status:deferred',
|
|
64
|
+
backlog: 'status:backlog',
|
|
65
|
+
review: 'status:review',
|
|
66
|
+
closed: 'status:closed',
|
|
67
|
+
tombstone: 'status:tombstone',
|
|
68
|
+
};
|
|
69
|
+
// ============================================================================
|
|
70
|
+
// Status <-> State Mapping
|
|
71
|
+
// ============================================================================
|
|
72
|
+
/**
|
|
73
|
+
* Maps Stoneforge TaskStatus to GitHub issue state.
|
|
74
|
+
*
|
|
75
|
+
* GitHub only supports two issue states: 'open' and 'closed'.
|
|
76
|
+
* Most Stoneforge statuses map to 'open' since GitHub can't
|
|
77
|
+
* distinguish between open, in_progress, review, blocked, etc.
|
|
78
|
+
*
|
|
79
|
+
* Mapping:
|
|
80
|
+
* - open, in_progress, review, blocked, deferred, backlog -> 'open'
|
|
81
|
+
* - closed, tombstone -> 'closed'
|
|
82
|
+
*/
|
|
83
|
+
export function statusToGitHubState(status) {
|
|
84
|
+
switch (status) {
|
|
85
|
+
case 'closed':
|
|
86
|
+
case 'tombstone':
|
|
87
|
+
return 'closed';
|
|
88
|
+
case 'open':
|
|
89
|
+
case 'in_progress':
|
|
90
|
+
case 'review':
|
|
91
|
+
case 'blocked':
|
|
92
|
+
case 'deferred':
|
|
93
|
+
case 'backlog':
|
|
94
|
+
default:
|
|
95
|
+
return 'open';
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Maps GitHub issue state + labels back to Stoneforge TaskStatus.
|
|
100
|
+
*
|
|
101
|
+
* Uses sf:status:* labels for granular status inference when available.
|
|
102
|
+
* If a status label is found, it takes precedence over the basic
|
|
103
|
+
* open/closed state mapping. Falls back to the simple state mapping
|
|
104
|
+
* when no status label is present.
|
|
105
|
+
*
|
|
106
|
+
* Mapping with labels:
|
|
107
|
+
* - 'sf:status:in-progress' → 'in_progress'
|
|
108
|
+
* - 'sf:status:blocked' → 'blocked'
|
|
109
|
+
* - etc.
|
|
110
|
+
*
|
|
111
|
+
* Fallback mapping (no status label):
|
|
112
|
+
* - 'open' → 'open'
|
|
113
|
+
* - 'closed' → 'closed'
|
|
114
|
+
*/
|
|
115
|
+
export function gitHubStateToStatus(state, labels) {
|
|
116
|
+
// Build a reverse lookup from status labels: 'status:open' → 'open', etc.
|
|
117
|
+
const statusByLabel = new Map();
|
|
118
|
+
for (const [status, label] of Object.entries(GITHUB_STATUS_LABELS)) {
|
|
119
|
+
statusByLabel.set(label, status);
|
|
120
|
+
}
|
|
121
|
+
// Check labels for a status label (strip the sync prefix first)
|
|
122
|
+
for (const label of labels) {
|
|
123
|
+
if (label.startsWith(GITHUB_SYNC_LABEL_PREFIX)) {
|
|
124
|
+
const value = label.slice(GITHUB_SYNC_LABEL_PREFIX.length);
|
|
125
|
+
const matchedStatus = statusByLabel.get(value);
|
|
126
|
+
if (matchedStatus !== undefined) {
|
|
127
|
+
return matchedStatus;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
// Fallback: basic open/closed mapping
|
|
132
|
+
switch (state) {
|
|
133
|
+
case 'closed':
|
|
134
|
+
return 'closed';
|
|
135
|
+
case 'open':
|
|
136
|
+
default:
|
|
137
|
+
return 'open';
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
// ============================================================================
|
|
141
|
+
// Combined Field Map Config
|
|
142
|
+
// ============================================================================
|
|
143
|
+
/**
|
|
144
|
+
* Complete GitHub-specific field mapping configuration.
|
|
145
|
+
*
|
|
146
|
+
* Used by the shared task sync adapter utilities to convert between
|
|
147
|
+
* Stoneforge tasks and GitHub issues (in both push and pull directions).
|
|
148
|
+
*/
|
|
149
|
+
export const GITHUB_FIELD_MAP_CONFIG = {
|
|
150
|
+
priorityLabels: GITHUB_PRIORITY_LABELS,
|
|
151
|
+
taskTypeLabels: GITHUB_TASK_TYPE_LABELS,
|
|
152
|
+
statusLabels: GITHUB_STATUS_LABELS,
|
|
153
|
+
syncLabelPrefix: GITHUB_SYNC_LABEL_PREFIX,
|
|
154
|
+
statusToState: statusToGitHubState,
|
|
155
|
+
stateToStatus: gitHubStateToStatus,
|
|
156
|
+
};
|
|
157
|
+
//# sourceMappingURL=github-field-map.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github-field-map.js","sourceRoot":"","sources":["../../../../src/external-sync/providers/github/github-field-map.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHub Provider
|
|
3
|
+
*
|
|
4
|
+
* Full implementation of the GitHub ExternalProvider.
|
|
5
|
+
* Handles connection testing via the GitHub API and provides
|
|
6
|
+
* a TaskSyncAdapter for bidirectional task/issue synchronization.
|
|
7
|
+
*
|
|
8
|
+
* The provider uses a lazy-initialized GitHubTaskAdapter that
|
|
9
|
+
* requires a ProviderConfig with a valid token before use.
|
|
10
|
+
*
|
|
11
|
+
* Also exports the placeholder provider for backward compatibility
|
|
12
|
+
* with systems that register the provider before configuration.
|
|
13
|
+
*/
|
|
14
|
+
import type { ExternalProvider, ProviderConfig } from '@stoneforge/core';
|
|
15
|
+
/**
|
|
16
|
+
* Create a configured GitHub provider.
|
|
17
|
+
*
|
|
18
|
+
* The provider is ready to use for sync operations when a valid
|
|
19
|
+
* token is provided in the config. The task adapter is initialized
|
|
20
|
+
* immediately with the provided credentials.
|
|
21
|
+
*
|
|
22
|
+
* @param config - Provider configuration with token and optional apiBaseUrl
|
|
23
|
+
* @returns A fully configured GitHub ExternalProvider
|
|
24
|
+
*/
|
|
25
|
+
export declare function createGitHubProvider(config: ProviderConfig): ExternalProvider;
|
|
26
|
+
/**
|
|
27
|
+
* Create a placeholder GitHub provider.
|
|
28
|
+
*
|
|
29
|
+
* The provider is registered by default in the provider registry so that
|
|
30
|
+
* the system knows GitHub is an available provider. Connection testing
|
|
31
|
+
* always returns false and all adapter methods throw until configured.
|
|
32
|
+
*
|
|
33
|
+
* @returns A placeholder GitHub ExternalProvider
|
|
34
|
+
*/
|
|
35
|
+
export declare function createGitHubPlaceholderProvider(): ExternalProvider;
|
|
36
|
+
//# sourceMappingURL=github-provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github-provider.d.ts","sourceRoot":"","sources":["../../../../src/external-sync/providers/github/github-provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EACV,gBAAgB,EAChB,cAAc,EAMf,MAAM,kBAAkB,CAAC;AA4M1B;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,cAAc,GAAG,gBAAgB,CAE7E;AAED;;;;;;;;GAQG;AACH,wBAAgB,+BAA+B,IAAI,gBAAgB,CAElE"}
|