@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.
Files changed (137) hide show
  1. package/README.md +3 -1
  2. package/dist/cli/commands/admin.d.ts.map +1 -1
  3. package/dist/cli/commands/admin.js +313 -3
  4. package/dist/cli/commands/admin.js.map +1 -1
  5. package/dist/cli/commands/auto-link-helper.d.ts +33 -0
  6. package/dist/cli/commands/auto-link-helper.d.ts.map +1 -0
  7. package/dist/cli/commands/auto-link-helper.js +73 -0
  8. package/dist/cli/commands/auto-link-helper.js.map +1 -0
  9. package/dist/cli/commands/crud.d.ts +1 -0
  10. package/dist/cli/commands/crud.d.ts.map +1 -1
  11. package/dist/cli/commands/crud.js +44 -5
  12. package/dist/cli/commands/crud.js.map +1 -1
  13. package/dist/cli/commands/docs.d.ts +1 -0
  14. package/dist/cli/commands/docs.d.ts.map +1 -1
  15. package/dist/cli/commands/docs.js +81 -1
  16. package/dist/cli/commands/docs.js.map +1 -1
  17. package/dist/cli/commands/external-sync.d.ts +17 -0
  18. package/dist/cli/commands/external-sync.d.ts.map +1 -0
  19. package/dist/cli/commands/external-sync.js +1647 -0
  20. package/dist/cli/commands/external-sync.js.map +1 -0
  21. package/dist/cli/commands/log.d.ts +18 -0
  22. package/dist/cli/commands/log.d.ts.map +1 -0
  23. package/dist/cli/commands/log.js +282 -0
  24. package/dist/cli/commands/log.js.map +1 -0
  25. package/dist/cli/commands/metrics.d.ts +9 -0
  26. package/dist/cli/commands/metrics.d.ts.map +1 -0
  27. package/dist/cli/commands/metrics.js +219 -0
  28. package/dist/cli/commands/metrics.js.map +1 -0
  29. package/dist/cli/runner.d.ts.map +1 -1
  30. package/dist/cli/runner.js +8 -0
  31. package/dist/cli/runner.js.map +1 -1
  32. package/dist/config/config.d.ts.map +1 -1
  33. package/dist/config/config.js +28 -0
  34. package/dist/config/config.js.map +1 -1
  35. package/dist/config/defaults.d.ts +13 -1
  36. package/dist/config/defaults.d.ts.map +1 -1
  37. package/dist/config/defaults.js +21 -0
  38. package/dist/config/defaults.js.map +1 -1
  39. package/dist/config/file.d.ts.map +1 -1
  40. package/dist/config/file.js +61 -0
  41. package/dist/config/file.js.map +1 -1
  42. package/dist/config/index.d.ts +3 -3
  43. package/dist/config/index.d.ts.map +1 -1
  44. package/dist/config/index.js +2 -2
  45. package/dist/config/index.js.map +1 -1
  46. package/dist/config/merge.d.ts.map +1 -1
  47. package/dist/config/merge.js +46 -1
  48. package/dist/config/merge.js.map +1 -1
  49. package/dist/config/types.d.ts +63 -1
  50. package/dist/config/types.d.ts.map +1 -1
  51. package/dist/config/types.js +30 -0
  52. package/dist/config/types.js.map +1 -1
  53. package/dist/config/validation.d.ts.map +1 -1
  54. package/dist/config/validation.js +51 -1
  55. package/dist/config/validation.js.map +1 -1
  56. package/dist/external-sync/adapters/task-sync-adapter.d.ts +177 -0
  57. package/dist/external-sync/adapters/task-sync-adapter.d.ts.map +1 -0
  58. package/dist/external-sync/adapters/task-sync-adapter.js +353 -0
  59. package/dist/external-sync/adapters/task-sync-adapter.js.map +1 -0
  60. package/dist/external-sync/auto-link.d.ts +66 -0
  61. package/dist/external-sync/auto-link.d.ts.map +1 -0
  62. package/dist/external-sync/auto-link.js +98 -0
  63. package/dist/external-sync/auto-link.js.map +1 -0
  64. package/dist/external-sync/conflict-resolver.d.ts +170 -0
  65. package/dist/external-sync/conflict-resolver.d.ts.map +1 -0
  66. package/dist/external-sync/conflict-resolver.js +580 -0
  67. package/dist/external-sync/conflict-resolver.js.map +1 -0
  68. package/dist/external-sync/index.d.ts +20 -0
  69. package/dist/external-sync/index.d.ts.map +1 -0
  70. package/dist/external-sync/index.js +20 -0
  71. package/dist/external-sync/index.js.map +1 -0
  72. package/dist/external-sync/provider-registry.d.ts +109 -0
  73. package/dist/external-sync/provider-registry.d.ts.map +1 -0
  74. package/dist/external-sync/provider-registry.js +188 -0
  75. package/dist/external-sync/provider-registry.js.map +1 -0
  76. package/dist/external-sync/providers/github/github-api.d.ts +271 -0
  77. package/dist/external-sync/providers/github/github-api.d.ts.map +1 -0
  78. package/dist/external-sync/providers/github/github-api.js +366 -0
  79. package/dist/external-sync/providers/github/github-api.js.map +1 -0
  80. package/dist/external-sync/providers/github/github-field-map.d.ts +76 -0
  81. package/dist/external-sync/providers/github/github-field-map.d.ts.map +1 -0
  82. package/dist/external-sync/providers/github/github-field-map.js +157 -0
  83. package/dist/external-sync/providers/github/github-field-map.js.map +1 -0
  84. package/dist/external-sync/providers/github/github-provider.d.ts +36 -0
  85. package/dist/external-sync/providers/github/github-provider.d.ts.map +1 -0
  86. package/dist/external-sync/providers/github/github-provider.js +212 -0
  87. package/dist/external-sync/providers/github/github-provider.js.map +1 -0
  88. package/dist/external-sync/providers/github/github-task-adapter.d.ts +135 -0
  89. package/dist/external-sync/providers/github/github-task-adapter.d.ts.map +1 -0
  90. package/dist/external-sync/providers/github/github-task-adapter.js +374 -0
  91. package/dist/external-sync/providers/github/github-task-adapter.js.map +1 -0
  92. package/dist/external-sync/providers/github/index.d.ts +12 -0
  93. package/dist/external-sync/providers/github/index.d.ts.map +1 -0
  94. package/dist/external-sync/providers/github/index.js +15 -0
  95. package/dist/external-sync/providers/github/index.js.map +1 -0
  96. package/dist/external-sync/providers/index.d.ts +9 -0
  97. package/dist/external-sync/providers/index.d.ts.map +1 -0
  98. package/dist/external-sync/providers/index.js +10 -0
  99. package/dist/external-sync/providers/index.js.map +1 -0
  100. package/dist/external-sync/providers/linear/index.d.ts +19 -0
  101. package/dist/external-sync/providers/linear/index.d.ts.map +1 -0
  102. package/dist/external-sync/providers/linear/index.js +19 -0
  103. package/dist/external-sync/providers/linear/index.js.map +1 -0
  104. package/dist/external-sync/providers/linear/linear-api.d.ts +252 -0
  105. package/dist/external-sync/providers/linear/linear-api.d.ts.map +1 -0
  106. package/dist/external-sync/providers/linear/linear-api.js +522 -0
  107. package/dist/external-sync/providers/linear/linear-api.js.map +1 -0
  108. package/dist/external-sync/providers/linear/linear-field-map.d.ts +135 -0
  109. package/dist/external-sync/providers/linear/linear-field-map.d.ts.map +1 -0
  110. package/dist/external-sync/providers/linear/linear-field-map.js +338 -0
  111. package/dist/external-sync/providers/linear/linear-field-map.js.map +1 -0
  112. package/dist/external-sync/providers/linear/linear-provider.d.ts +52 -0
  113. package/dist/external-sync/providers/linear/linear-provider.d.ts.map +1 -0
  114. package/dist/external-sync/providers/linear/linear-provider.js +169 -0
  115. package/dist/external-sync/providers/linear/linear-provider.js.map +1 -0
  116. package/dist/external-sync/providers/linear/linear-task-adapter.d.ts +190 -0
  117. package/dist/external-sync/providers/linear/linear-task-adapter.d.ts.map +1 -0
  118. package/dist/external-sync/providers/linear/linear-task-adapter.js +521 -0
  119. package/dist/external-sync/providers/linear/linear-task-adapter.js.map +1 -0
  120. package/dist/external-sync/providers/linear/linear-types.d.ts +114 -0
  121. package/dist/external-sync/providers/linear/linear-types.d.ts.map +1 -0
  122. package/dist/external-sync/providers/linear/linear-types.js +10 -0
  123. package/dist/external-sync/providers/linear/linear-types.js.map +1 -0
  124. package/dist/external-sync/sync-engine.d.ts +298 -0
  125. package/dist/external-sync/sync-engine.d.ts.map +1 -0
  126. package/dist/external-sync/sync-engine.js +785 -0
  127. package/dist/external-sync/sync-engine.js.map +1 -0
  128. package/dist/index.d.ts +1 -0
  129. package/dist/index.d.ts.map +1 -1
  130. package/dist/index.js +2 -0
  131. package/dist/index.js.map +1 -1
  132. package/dist/services/inbox.js +1 -1
  133. package/dist/sync/hash.d.ts +5 -0
  134. package/dist/sync/hash.d.ts.map +1 -1
  135. package/dist/sync/hash.js +21 -2
  136. package/dist/sync/hash.js.map +1 -1
  137. 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"}