@stoneforge/quarry 1.12.0 → 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 (122) hide show
  1. package/README.md +2 -0
  2. package/dist/cli/commands/auto-link-helper.d.ts +33 -0
  3. package/dist/cli/commands/auto-link-helper.d.ts.map +1 -0
  4. package/dist/cli/commands/auto-link-helper.js +73 -0
  5. package/dist/cli/commands/auto-link-helper.js.map +1 -0
  6. package/dist/cli/commands/crud.d.ts +1 -0
  7. package/dist/cli/commands/crud.d.ts.map +1 -1
  8. package/dist/cli/commands/crud.js +44 -5
  9. package/dist/cli/commands/crud.js.map +1 -1
  10. package/dist/cli/commands/external-sync.d.ts +17 -0
  11. package/dist/cli/commands/external-sync.d.ts.map +1 -0
  12. package/dist/cli/commands/external-sync.js +1647 -0
  13. package/dist/cli/commands/external-sync.js.map +1 -0
  14. package/dist/cli/runner.d.ts.map +1 -1
  15. package/dist/cli/runner.js +3 -0
  16. package/dist/cli/runner.js.map +1 -1
  17. package/dist/config/config.d.ts.map +1 -1
  18. package/dist/config/config.js +28 -0
  19. package/dist/config/config.js.map +1 -1
  20. package/dist/config/defaults.d.ts +13 -1
  21. package/dist/config/defaults.d.ts.map +1 -1
  22. package/dist/config/defaults.js +21 -0
  23. package/dist/config/defaults.js.map +1 -1
  24. package/dist/config/file.d.ts.map +1 -1
  25. package/dist/config/file.js +61 -0
  26. package/dist/config/file.js.map +1 -1
  27. package/dist/config/index.d.ts +3 -3
  28. package/dist/config/index.d.ts.map +1 -1
  29. package/dist/config/index.js +2 -2
  30. package/dist/config/index.js.map +1 -1
  31. package/dist/config/merge.d.ts.map +1 -1
  32. package/dist/config/merge.js +46 -1
  33. package/dist/config/merge.js.map +1 -1
  34. package/dist/config/types.d.ts +63 -1
  35. package/dist/config/types.d.ts.map +1 -1
  36. package/dist/config/types.js +30 -0
  37. package/dist/config/types.js.map +1 -1
  38. package/dist/config/validation.d.ts.map +1 -1
  39. package/dist/config/validation.js +51 -1
  40. package/dist/config/validation.js.map +1 -1
  41. package/dist/external-sync/adapters/task-sync-adapter.d.ts +177 -0
  42. package/dist/external-sync/adapters/task-sync-adapter.d.ts.map +1 -0
  43. package/dist/external-sync/adapters/task-sync-adapter.js +353 -0
  44. package/dist/external-sync/adapters/task-sync-adapter.js.map +1 -0
  45. package/dist/external-sync/auto-link.d.ts +66 -0
  46. package/dist/external-sync/auto-link.d.ts.map +1 -0
  47. package/dist/external-sync/auto-link.js +98 -0
  48. package/dist/external-sync/auto-link.js.map +1 -0
  49. package/dist/external-sync/conflict-resolver.d.ts +170 -0
  50. package/dist/external-sync/conflict-resolver.d.ts.map +1 -0
  51. package/dist/external-sync/conflict-resolver.js +580 -0
  52. package/dist/external-sync/conflict-resolver.js.map +1 -0
  53. package/dist/external-sync/index.d.ts +20 -0
  54. package/dist/external-sync/index.d.ts.map +1 -0
  55. package/dist/external-sync/index.js +20 -0
  56. package/dist/external-sync/index.js.map +1 -0
  57. package/dist/external-sync/provider-registry.d.ts +109 -0
  58. package/dist/external-sync/provider-registry.d.ts.map +1 -0
  59. package/dist/external-sync/provider-registry.js +188 -0
  60. package/dist/external-sync/provider-registry.js.map +1 -0
  61. package/dist/external-sync/providers/github/github-api.d.ts +271 -0
  62. package/dist/external-sync/providers/github/github-api.d.ts.map +1 -0
  63. package/dist/external-sync/providers/github/github-api.js +366 -0
  64. package/dist/external-sync/providers/github/github-api.js.map +1 -0
  65. package/dist/external-sync/providers/github/github-field-map.d.ts +76 -0
  66. package/dist/external-sync/providers/github/github-field-map.d.ts.map +1 -0
  67. package/dist/external-sync/providers/github/github-field-map.js +157 -0
  68. package/dist/external-sync/providers/github/github-field-map.js.map +1 -0
  69. package/dist/external-sync/providers/github/github-provider.d.ts +36 -0
  70. package/dist/external-sync/providers/github/github-provider.d.ts.map +1 -0
  71. package/dist/external-sync/providers/github/github-provider.js +212 -0
  72. package/dist/external-sync/providers/github/github-provider.js.map +1 -0
  73. package/dist/external-sync/providers/github/github-task-adapter.d.ts +135 -0
  74. package/dist/external-sync/providers/github/github-task-adapter.d.ts.map +1 -0
  75. package/dist/external-sync/providers/github/github-task-adapter.js +374 -0
  76. package/dist/external-sync/providers/github/github-task-adapter.js.map +1 -0
  77. package/dist/external-sync/providers/github/index.d.ts +12 -0
  78. package/dist/external-sync/providers/github/index.d.ts.map +1 -0
  79. package/dist/external-sync/providers/github/index.js +15 -0
  80. package/dist/external-sync/providers/github/index.js.map +1 -0
  81. package/dist/external-sync/providers/index.d.ts +9 -0
  82. package/dist/external-sync/providers/index.d.ts.map +1 -0
  83. package/dist/external-sync/providers/index.js +10 -0
  84. package/dist/external-sync/providers/index.js.map +1 -0
  85. package/dist/external-sync/providers/linear/index.d.ts +19 -0
  86. package/dist/external-sync/providers/linear/index.d.ts.map +1 -0
  87. package/dist/external-sync/providers/linear/index.js +19 -0
  88. package/dist/external-sync/providers/linear/index.js.map +1 -0
  89. package/dist/external-sync/providers/linear/linear-api.d.ts +252 -0
  90. package/dist/external-sync/providers/linear/linear-api.d.ts.map +1 -0
  91. package/dist/external-sync/providers/linear/linear-api.js +522 -0
  92. package/dist/external-sync/providers/linear/linear-api.js.map +1 -0
  93. package/dist/external-sync/providers/linear/linear-field-map.d.ts +135 -0
  94. package/dist/external-sync/providers/linear/linear-field-map.d.ts.map +1 -0
  95. package/dist/external-sync/providers/linear/linear-field-map.js +338 -0
  96. package/dist/external-sync/providers/linear/linear-field-map.js.map +1 -0
  97. package/dist/external-sync/providers/linear/linear-provider.d.ts +52 -0
  98. package/dist/external-sync/providers/linear/linear-provider.d.ts.map +1 -0
  99. package/dist/external-sync/providers/linear/linear-provider.js +169 -0
  100. package/dist/external-sync/providers/linear/linear-provider.js.map +1 -0
  101. package/dist/external-sync/providers/linear/linear-task-adapter.d.ts +190 -0
  102. package/dist/external-sync/providers/linear/linear-task-adapter.d.ts.map +1 -0
  103. package/dist/external-sync/providers/linear/linear-task-adapter.js +521 -0
  104. package/dist/external-sync/providers/linear/linear-task-adapter.js.map +1 -0
  105. package/dist/external-sync/providers/linear/linear-types.d.ts +114 -0
  106. package/dist/external-sync/providers/linear/linear-types.d.ts.map +1 -0
  107. package/dist/external-sync/providers/linear/linear-types.js +10 -0
  108. package/dist/external-sync/providers/linear/linear-types.js.map +1 -0
  109. package/dist/external-sync/sync-engine.d.ts +298 -0
  110. package/dist/external-sync/sync-engine.d.ts.map +1 -0
  111. package/dist/external-sync/sync-engine.js +785 -0
  112. package/dist/external-sync/sync-engine.js.map +1 -0
  113. package/dist/index.d.ts +1 -0
  114. package/dist/index.d.ts.map +1 -1
  115. package/dist/index.js +2 -0
  116. package/dist/index.js.map +1 -1
  117. package/dist/services/inbox.js +1 -1
  118. package/dist/sync/hash.d.ts +5 -0
  119. package/dist/sync/hash.d.ts.map +1 -1
  120. package/dist/sync/hash.js +21 -2
  121. package/dist/sync/hash.js.map +1 -1
  122. package/package.json +11 -5
@@ -0,0 +1,109 @@
1
+ /**
2
+ * Provider Registry — manages ExternalProvider registrations
3
+ *
4
+ * Provides a central registry for external sync providers (GitHub, Linear, etc.).
5
+ * Supports registration, lookup by name, listing all providers, and querying
6
+ * providers by adapter type.
7
+ *
8
+ * Usage:
9
+ * ```typescript
10
+ * import { createProviderRegistry } from '@stoneforge/quarry';
11
+ *
12
+ * const registry = createProviderRegistry();
13
+ * registry.register(myProvider);
14
+ * const github = registry.get('github');
15
+ * const taskProviders = registry.getAdaptersOfType('task');
16
+ * ```
17
+ */
18
+ import type { ExternalProvider, ProviderConfig, SyncAdapterType, TaskSyncAdapter, DocumentSyncAdapter, MessageSyncAdapter } from '@stoneforge/core';
19
+ /**
20
+ * Result from getAdaptersOfType — a provider and its adapter for the requested type
21
+ */
22
+ export interface ProviderAdapterEntry {
23
+ readonly provider: ExternalProvider;
24
+ readonly adapter: TaskSyncAdapter | DocumentSyncAdapter | MessageSyncAdapter;
25
+ }
26
+ /**
27
+ * Registry for external sync providers.
28
+ *
29
+ * Manages registration and lookup of ExternalProvider instances.
30
+ * Providers are keyed by their `name` property (e.g., 'github', 'linear').
31
+ */
32
+ export declare class ProviderRegistry {
33
+ private readonly providers;
34
+ /**
35
+ * Register a provider.
36
+ *
37
+ * @param provider - The provider to register
38
+ * @throws Error if a provider with the same name is already registered
39
+ */
40
+ register(provider: ExternalProvider): void;
41
+ /**
42
+ * Look up a provider by name.
43
+ *
44
+ * @param name - The provider name (e.g., 'github')
45
+ * @returns The provider, or undefined if not found
46
+ */
47
+ get(name: string): ExternalProvider | undefined;
48
+ /**
49
+ * List all registered providers.
50
+ *
51
+ * @returns Array of all registered providers
52
+ */
53
+ list(): ExternalProvider[];
54
+ /**
55
+ * Find all providers that support a given adapter type, and return
56
+ * the provider paired with its adapter for that type.
57
+ *
58
+ * @param type - The adapter type to filter by ('task', 'document', 'message')
59
+ * @returns Array of { provider, adapter } for all matching providers
60
+ */
61
+ getAdaptersOfType(type: SyncAdapterType): ProviderAdapterEntry[];
62
+ /**
63
+ * Check if a provider is registered.
64
+ *
65
+ * @param name - The provider name
66
+ * @returns true if the provider is registered
67
+ */
68
+ has(name: string): boolean;
69
+ /**
70
+ * Unregister a provider by name.
71
+ *
72
+ * @param name - The provider name to remove
73
+ * @returns true if the provider was removed, false if not found
74
+ */
75
+ unregister(name: string): boolean;
76
+ /**
77
+ * Remove all registered providers.
78
+ */
79
+ clear(): void;
80
+ }
81
+ /**
82
+ * Create a new ProviderRegistry instance.
83
+ *
84
+ * @returns A new, empty ProviderRegistry
85
+ */
86
+ export declare function createProviderRegistry(): ProviderRegistry;
87
+ /**
88
+ * Create a ProviderRegistry with default providers registered.
89
+ *
90
+ * Registers placeholder providers for GitHub and Linear by default.
91
+ * The actual provider implementations replace these when configured with API keys.
92
+ *
93
+ * @returns A ProviderRegistry with default providers
94
+ */
95
+ export declare function createDefaultProviderRegistry(): ProviderRegistry;
96
+ /**
97
+ * Create a ProviderRegistry with real configured providers.
98
+ *
99
+ * Starts with placeholder providers for all known providers (GitHub, Linear),
100
+ * then replaces placeholders with real configured providers for any configs
101
+ * that have a token set. This ensures providers without tokens remain as
102
+ * placeholders (which throw descriptive errors), while configured providers
103
+ * are ready for actual sync operations.
104
+ *
105
+ * @param providerConfigs - Array of provider configurations (from settings)
106
+ * @returns A ProviderRegistry with configured providers replacing placeholders
107
+ */
108
+ export declare function createConfiguredProviderRegistry(providerConfigs: readonly ProviderConfig[]): ProviderRegistry;
109
+ //# sourceMappingURL=provider-registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider-registry.d.ts","sourceRoot":"","sources":["../../src/external-sync/provider-registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EACV,gBAAgB,EAChB,cAAc,EACd,eAAe,EACf,eAAe,EACf,mBAAmB,EACnB,kBAAkB,EACnB,MAAM,kBAAkB,CAAC;AAQ1B;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,CAAC;IACpC,QAAQ,CAAC,OAAO,EAAE,eAAe,GAAG,mBAAmB,GAAG,kBAAkB,CAAC;CAC9E;AAMD;;;;;GAKG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAuC;IAEjE;;;;;OAKG;IACH,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,GAAG,IAAI;IAU1C;;;;;OAKG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS;IAI/C;;;;OAIG;IACH,IAAI,IAAI,gBAAgB,EAAE;IAI1B;;;;;;OAMG;IACH,iBAAiB,CAAC,IAAI,EAAE,eAAe,GAAG,oBAAoB,EAAE;IAiBhE;;;;;OAKG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAI1B;;;;;OAKG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAIjC;;OAEG;IACH,KAAK,IAAI,IAAI;CAGd;AA6BD;;;;GAIG;AACH,wBAAgB,sBAAsB,IAAI,gBAAgB,CAEzD;AAED;;;;;;;GAOG;AACH,wBAAgB,6BAA6B,IAAI,gBAAgB,CAKhE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,gCAAgC,CAC9C,eAAe,EAAE,SAAS,cAAc,EAAE,GACzC,gBAAgB,CAkClB"}
@@ -0,0 +1,188 @@
1
+ /**
2
+ * Provider Registry — manages ExternalProvider registrations
3
+ *
4
+ * Provides a central registry for external sync providers (GitHub, Linear, etc.).
5
+ * Supports registration, lookup by name, listing all providers, and querying
6
+ * providers by adapter type.
7
+ *
8
+ * Usage:
9
+ * ```typescript
10
+ * import { createProviderRegistry } from '@stoneforge/quarry';
11
+ *
12
+ * const registry = createProviderRegistry();
13
+ * registry.register(myProvider);
14
+ * const github = registry.get('github');
15
+ * const taskProviders = registry.getAdaptersOfType('task');
16
+ * ```
17
+ */
18
+ import { createGitHubProvider, createGitHubPlaceholderProvider } from './providers/github/index.js';
19
+ import { createLinearProvider, createLinearPlaceholderProvider } from './providers/linear/index.js';
20
+ // ============================================================================
21
+ // ProviderRegistry
22
+ // ============================================================================
23
+ /**
24
+ * Registry for external sync providers.
25
+ *
26
+ * Manages registration and lookup of ExternalProvider instances.
27
+ * Providers are keyed by their `name` property (e.g., 'github', 'linear').
28
+ */
29
+ export class ProviderRegistry {
30
+ providers = new Map();
31
+ /**
32
+ * Register a provider.
33
+ *
34
+ * @param provider - The provider to register
35
+ * @throws Error if a provider with the same name is already registered
36
+ */
37
+ register(provider) {
38
+ if (this.providers.has(provider.name)) {
39
+ throw new Error(`Provider '${provider.name}' is already registered. ` +
40
+ `Unregister it first or use a different name.`);
41
+ }
42
+ this.providers.set(provider.name, provider);
43
+ }
44
+ /**
45
+ * Look up a provider by name.
46
+ *
47
+ * @param name - The provider name (e.g., 'github')
48
+ * @returns The provider, or undefined if not found
49
+ */
50
+ get(name) {
51
+ return this.providers.get(name);
52
+ }
53
+ /**
54
+ * List all registered providers.
55
+ *
56
+ * @returns Array of all registered providers
57
+ */
58
+ list() {
59
+ return Array.from(this.providers.values());
60
+ }
61
+ /**
62
+ * Find all providers that support a given adapter type, and return
63
+ * the provider paired with its adapter for that type.
64
+ *
65
+ * @param type - The adapter type to filter by ('task', 'document', 'message')
66
+ * @returns Array of { provider, adapter } for all matching providers
67
+ */
68
+ getAdaptersOfType(type) {
69
+ const results = [];
70
+ for (const provider of this.providers.values()) {
71
+ if (!provider.supportedAdapters.includes(type)) {
72
+ continue;
73
+ }
74
+ const adapter = getAdapterByType(provider, type);
75
+ if (adapter) {
76
+ results.push({ provider, adapter });
77
+ }
78
+ }
79
+ return results;
80
+ }
81
+ /**
82
+ * Check if a provider is registered.
83
+ *
84
+ * @param name - The provider name
85
+ * @returns true if the provider is registered
86
+ */
87
+ has(name) {
88
+ return this.providers.has(name);
89
+ }
90
+ /**
91
+ * Unregister a provider by name.
92
+ *
93
+ * @param name - The provider name to remove
94
+ * @returns true if the provider was removed, false if not found
95
+ */
96
+ unregister(name) {
97
+ return this.providers.delete(name);
98
+ }
99
+ /**
100
+ * Remove all registered providers.
101
+ */
102
+ clear() {
103
+ this.providers.clear();
104
+ }
105
+ }
106
+ // ============================================================================
107
+ // Helper Functions
108
+ // ============================================================================
109
+ /**
110
+ * Get the adapter from a provider for a given adapter type.
111
+ */
112
+ function getAdapterByType(provider, type) {
113
+ switch (type) {
114
+ case 'task':
115
+ return provider.getTaskAdapter?.();
116
+ case 'document':
117
+ return provider.getDocumentAdapter?.();
118
+ case 'message':
119
+ return provider.getMessageAdapter?.();
120
+ default:
121
+ return undefined;
122
+ }
123
+ }
124
+ // ============================================================================
125
+ // Factory
126
+ // ============================================================================
127
+ /**
128
+ * Create a new ProviderRegistry instance.
129
+ *
130
+ * @returns A new, empty ProviderRegistry
131
+ */
132
+ export function createProviderRegistry() {
133
+ return new ProviderRegistry();
134
+ }
135
+ /**
136
+ * Create a ProviderRegistry with default providers registered.
137
+ *
138
+ * Registers placeholder providers for GitHub and Linear by default.
139
+ * The actual provider implementations replace these when configured with API keys.
140
+ *
141
+ * @returns A ProviderRegistry with default providers
142
+ */
143
+ export function createDefaultProviderRegistry() {
144
+ const registry = new ProviderRegistry();
145
+ registry.register(createGitHubPlaceholderProvider());
146
+ registry.register(createLinearPlaceholderProvider());
147
+ return registry;
148
+ }
149
+ /**
150
+ * Create a ProviderRegistry with real configured providers.
151
+ *
152
+ * Starts with placeholder providers for all known providers (GitHub, Linear),
153
+ * then replaces placeholders with real configured providers for any configs
154
+ * that have a token set. This ensures providers without tokens remain as
155
+ * placeholders (which throw descriptive errors), while configured providers
156
+ * are ready for actual sync operations.
157
+ *
158
+ * @param providerConfigs - Array of provider configurations (from settings)
159
+ * @returns A ProviderRegistry with configured providers replacing placeholders
160
+ */
161
+ export function createConfiguredProviderRegistry(providerConfigs) {
162
+ const registry = createDefaultProviderRegistry();
163
+ for (const config of providerConfigs) {
164
+ if (!config.token) {
165
+ continue;
166
+ }
167
+ // Replace the placeholder with a real configured provider
168
+ registry.unregister(config.provider);
169
+ switch (config.provider) {
170
+ case 'github':
171
+ registry.register(createGitHubProvider({
172
+ provider: 'github',
173
+ token: config.token,
174
+ apiBaseUrl: config.apiBaseUrl,
175
+ defaultProject: config.defaultProject,
176
+ }));
177
+ break;
178
+ case 'linear':
179
+ registry.register(createLinearProvider({
180
+ apiKey: config.token,
181
+ }));
182
+ break;
183
+ // Unknown providers are silently skipped — their placeholders remain
184
+ }
185
+ }
186
+ return registry;
187
+ }
188
+ //# sourceMappingURL=provider-registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider-registry.js","sourceRoot":"","sources":["../../src/external-sync/provider-registry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,271 @@
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
+ * Minimal type matching the fields we use from GitHub's issue response.
12
+ * Does not attempt to type the full GitHub API response.
13
+ */
14
+ export interface GitHubIssue {
15
+ /** GitHub's internal issue ID */
16
+ readonly id: number;
17
+ /** Issue number within the repository */
18
+ readonly number: number;
19
+ /** Issue title */
20
+ readonly title: string;
21
+ /** Issue body/description (markdown) */
22
+ readonly body: string | null;
23
+ /** Issue state */
24
+ readonly state: 'open' | 'closed';
25
+ /** Labels attached to the issue */
26
+ readonly labels: readonly GitHubLabel[];
27
+ /** Users assigned to the issue */
28
+ readonly assignees: readonly GitHubUser[];
29
+ /** URL to view the issue in a browser */
30
+ readonly html_url: string;
31
+ /** Creation timestamp (ISO 8601) */
32
+ readonly created_at: string;
33
+ /** Last update timestamp (ISO 8601) */
34
+ readonly updated_at: string;
35
+ /** Closure timestamp (ISO 8601), null if still open */
36
+ readonly closed_at: string | null;
37
+ }
38
+ /**
39
+ * Minimal GitHub label representation
40
+ */
41
+ export interface GitHubLabel {
42
+ readonly id: number;
43
+ readonly name: string;
44
+ readonly color: string;
45
+ readonly description: string | null;
46
+ }
47
+ /**
48
+ * Minimal GitHub user representation
49
+ */
50
+ export interface GitHubUser {
51
+ readonly login: string;
52
+ readonly id: number;
53
+ }
54
+ /**
55
+ * Options for listing issues
56
+ */
57
+ export interface ListIssuesOptions {
58
+ /** Only return issues updated after this ISO 8601 timestamp */
59
+ since?: string;
60
+ /** Filter by state */
61
+ state?: 'open' | 'closed' | 'all';
62
+ /** Results per page (max 100, default 30) */
63
+ per_page?: number;
64
+ /** Page number for manual pagination */
65
+ page?: number;
66
+ }
67
+ /**
68
+ * Input for creating a new label on a repository
69
+ */
70
+ export interface CreateLabelInput {
71
+ /** Label name (required) */
72
+ name: string;
73
+ /** Label color as hex string without '#' prefix (e.g. '0075ca') */
74
+ color: string;
75
+ /** Optional description for the label */
76
+ description?: string;
77
+ }
78
+ /**
79
+ * Input for creating a new issue
80
+ */
81
+ export interface CreateIssueInput {
82
+ /** Issue title (required) */
83
+ title: string;
84
+ /** Issue body/description */
85
+ body?: string;
86
+ /** Label names to attach */
87
+ labels?: string[];
88
+ /** Usernames to assign */
89
+ assignees?: string[];
90
+ }
91
+ /**
92
+ * Input for updating an existing issue
93
+ */
94
+ export interface UpdateIssueInput {
95
+ /** Updated title */
96
+ title?: string;
97
+ /** Updated body */
98
+ body?: string;
99
+ /** Updated state */
100
+ state?: 'open' | 'closed';
101
+ /** Updated label names (replaces all labels) */
102
+ labels?: string[];
103
+ /** Updated assignees (replaces all assignees) */
104
+ assignees?: string[];
105
+ }
106
+ /**
107
+ * Rate limit information parsed from GitHub response headers
108
+ */
109
+ export interface RateLimitInfo {
110
+ /** Total requests allowed per hour */
111
+ readonly limit: number;
112
+ /** Requests remaining in the current window */
113
+ readonly remaining: number;
114
+ /** UTC epoch timestamp when the rate limit resets */
115
+ readonly reset: number;
116
+ }
117
+ /**
118
+ * Configuration for creating a GitHubApiClient
119
+ */
120
+ export interface GitHubApiClientOptions {
121
+ /** Personal Access Token for authentication */
122
+ token: string;
123
+ /** Base URL for GitHub API (default: https://api.github.com) */
124
+ apiBaseUrl?: string;
125
+ /** Remaining requests threshold to trigger warnings (default: 10) */
126
+ rateLimitWarningThreshold?: number;
127
+ }
128
+ /**
129
+ * Typed error for GitHub API failures.
130
+ * Wraps fetch errors with status code, message, and rate limit info.
131
+ */
132
+ export declare class GitHubApiError extends Error {
133
+ /** HTTP status code from GitHub's response */
134
+ readonly status: number;
135
+ /** Human-readable error message from GitHub */
136
+ readonly statusText: string;
137
+ /** Rate limit information at the time of the error */
138
+ readonly rateLimit: RateLimitInfo | null;
139
+ /** Parsed error body from GitHub (if available) */
140
+ readonly responseBody: Record<string, unknown> | null;
141
+ constructor(message: string, status: number, statusText: string, rateLimit?: RateLimitInfo | null, responseBody?: Record<string, unknown> | null, cause?: Error);
142
+ /**
143
+ * Whether this error is due to rate limiting
144
+ */
145
+ get isRateLimited(): boolean;
146
+ /**
147
+ * Whether this error is due to authentication failure
148
+ */
149
+ get isAuthError(): boolean;
150
+ /**
151
+ * Whether this error is a not-found response
152
+ */
153
+ get isNotFound(): boolean;
154
+ /**
155
+ * Returns a JSON-serializable representation of the error
156
+ */
157
+ toJSON(): {
158
+ name: string;
159
+ message: string;
160
+ status: number;
161
+ statusText: string;
162
+ rateLimit: RateLimitInfo | null;
163
+ responseBody: Record<string, unknown> | null;
164
+ };
165
+ }
166
+ /**
167
+ * Type guard for GitHubApiError
168
+ */
169
+ export declare function isGitHubApiError(error: unknown): error is GitHubApiError;
170
+ /**
171
+ * Fetch-based GitHub REST API client for issue operations.
172
+ *
173
+ * Features:
174
+ * - Personal Access Token (PAT) authentication
175
+ * - Rate limit tracking with warnings when approaching limit
176
+ * - Configurable base URL for GitHub Enterprise
177
+ * - Typed errors with status code and rate limit info
178
+ * - Automatic pagination for listing issues
179
+ *
180
+ * @example
181
+ * ```typescript
182
+ * const client = new GitHubApiClient({ token: 'ghp_...' });
183
+ * const issue = await client.getIssue('owner', 'repo', 42);
184
+ * const issues = await client.listIssues('owner', 'repo', { state: 'open' });
185
+ * ```
186
+ */
187
+ export declare class GitHubApiClient {
188
+ private readonly token;
189
+ private readonly apiBaseUrl;
190
+ private readonly rateLimitWarningThreshold;
191
+ /** Most recently observed rate limit info (updated after each request) */
192
+ private lastRateLimit;
193
+ constructor(options: GitHubApiClientOptions);
194
+ /**
195
+ * Returns the most recently observed rate limit info, or null if no requests have been made.
196
+ */
197
+ getRateLimit(): RateLimitInfo | null;
198
+ /**
199
+ * Fetch a single issue by number.
200
+ *
201
+ * GET /repos/{owner}/{repo}/issues/{issue_number}
202
+ */
203
+ getIssue(owner: string, repo: string, issueNumber: number): Promise<GitHubIssue>;
204
+ /**
205
+ * List issues for a repository.
206
+ *
207
+ * GET /repos/{owner}/{repo}/issues?since=...&state=all
208
+ *
209
+ * When no explicit `page` is provided, this method automatically iterates
210
+ * through all pages using the Link header and returns every matching issue.
211
+ * When a `page` is specified, only that single page is returned.
212
+ */
213
+ listIssues(owner: string, repo: string, options?: ListIssuesOptions): Promise<GitHubIssue[]>;
214
+ /**
215
+ * Create a new issue.
216
+ *
217
+ * POST /repos/{owner}/{repo}/issues
218
+ */
219
+ createIssue(owner: string, repo: string, input: CreateIssueInput): Promise<GitHubIssue>;
220
+ /**
221
+ * Update an existing issue.
222
+ *
223
+ * PATCH /repos/{owner}/{repo}/issues/{issue_number}
224
+ */
225
+ updateIssue(owner: string, repo: string, issueNumber: number, updates: UpdateIssueInput): Promise<GitHubIssue>;
226
+ /**
227
+ * List all labels for a repository.
228
+ *
229
+ * GET /repos/{owner}/{repo}/labels
230
+ *
231
+ * Auto-paginates through all pages to return the complete label set.
232
+ */
233
+ getLabels(owner: string, repo: string): Promise<GitHubLabel[]>;
234
+ /**
235
+ * Create a new label on a repository.
236
+ *
237
+ * POST /repos/{owner}/{repo}/labels
238
+ */
239
+ createLabel(owner: string, repo: string, input: CreateLabelInput): Promise<GitHubLabel>;
240
+ /**
241
+ * Performs a single HTTP request to the GitHub API.
242
+ */
243
+ private request;
244
+ /**
245
+ * Performs a paginated request, following Link headers to collect all pages.
246
+ */
247
+ private paginatedRequest;
248
+ /**
249
+ * Handles non-OK responses by throwing a GitHubApiError.
250
+ */
251
+ private handleErrorResponse;
252
+ /**
253
+ * Logs a warning when rate limit is approaching exhaustion.
254
+ */
255
+ private checkRateLimitWarning;
256
+ }
257
+ /**
258
+ * Parses rate limit information from GitHub response headers.
259
+ * Returns null if the headers are not present.
260
+ */
261
+ declare function parseRateLimitHeaders(headers: Headers): RateLimitInfo | null;
262
+ /**
263
+ * Parses the GitHub Link header to find the "next" page URL.
264
+ * Returns null if there is no next page.
265
+ *
266
+ * The Link header format is:
267
+ * <https://api.github.com/...?page=2>; rel="next", <https://api.github.com/...?page=5>; rel="last"
268
+ */
269
+ declare function parseLinkHeaderNext(linkHeader: string | null): string | null;
270
+ export { parseRateLimitHeaders, parseLinkHeaderNext };
271
+ //# sourceMappingURL=github-api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github-api.d.ts","sourceRoot":"","sources":["../../../../src/external-sync/providers/github/github-api.ts"],"names":[],"mappings":"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"}