@sascha384/tic 2.0.0 → 2.1.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 (50) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/README.md +17 -63
  3. package/dist/auth/github.d.ts +27 -0
  4. package/dist/auth/github.js +96 -0
  5. package/dist/auth/github.js.map +1 -0
  6. package/dist/auth/index.d.ts +3 -0
  7. package/dist/auth/index.js +3 -0
  8. package/dist/auth/index.js.map +1 -0
  9. package/dist/auth/keychain.d.ts +14 -0
  10. package/dist/auth/keychain.js +36 -0
  11. package/dist/auth/keychain.js.map +1 -0
  12. package/dist/backends/factory.d.ts +5 -2
  13. package/dist/backends/factory.js +4 -4
  14. package/dist/backends/factory.js.map +1 -1
  15. package/dist/backends/github/api.d.ts +9 -0
  16. package/dist/backends/github/api.js +117 -0
  17. package/dist/backends/github/api.js.map +1 -0
  18. package/dist/backends/github/index.d.ts +9 -5
  19. package/dist/backends/github/index.js +119 -81
  20. package/dist/backends/github/index.js.map +1 -1
  21. package/dist/backends/github/mappers.d.ts +1 -0
  22. package/dist/backends/github/mappers.js.map +1 -1
  23. package/dist/backends/shared/api-client.d.ts +16 -0
  24. package/dist/backends/shared/api-client.js +73 -0
  25. package/dist/backends/shared/api-client.js.map +1 -0
  26. package/dist/cli/commands/auth.d.ts +17 -0
  27. package/dist/cli/commands/auth.js +47 -0
  28. package/dist/cli/commands/auth.js.map +1 -0
  29. package/dist/cli/commands/mcp.js +32 -9
  30. package/dist/cli/commands/mcp.js.map +1 -1
  31. package/dist/cli/index.js +58 -0
  32. package/dist/cli/index.js.map +1 -1
  33. package/dist/components/AutocompleteInput.d.ts +2 -1
  34. package/dist/components/AutocompleteInput.js +5 -1
  35. package/dist/components/AutocompleteInput.js.map +1 -1
  36. package/dist/components/MultiAutocompleteInput.d.ts +2 -1
  37. package/dist/components/MultiAutocompleteInput.js +5 -1
  38. package/dist/components/MultiAutocompleteInput.js.map +1 -1
  39. package/dist/components/WorkItemForm.js +12 -0
  40. package/dist/components/WorkItemForm.js.map +1 -1
  41. package/dist/stores/backendDataStore.js +12 -1
  42. package/dist/stores/backendDataStore.js.map +1 -1
  43. package/drizzle/0000_next_vance_astro.sql +183 -0
  44. package/drizzle/meta/0000_snapshot.json +1188 -0
  45. package/drizzle/meta/_journal.json +13 -0
  46. package/package.json +4 -1
  47. package/skills/config/SKILL.md +2 -2
  48. package/dist/backends/github/gh.d.ts +0 -9
  49. package/dist/backends/github/gh.js +0 -95
  50. package/dist/backends/github/gh.js.map +0 -1
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "tic",
3
3
  "description": "Issue tracking skills for Claude Code",
4
- "version": "2.0.0",
4
+ "version": "2.1.0",
5
5
  "author": {
6
6
  "name": "Sascha Krug"
7
7
  },
package/README.md CHANGED
@@ -1,15 +1,15 @@
1
1
  # tic
2
2
 
3
- A terminal UI for issue tracking, built for developers who live in the terminal. Track work items across multiple backends — local markdown files, GitHub Issues, GitLab Issues, Azure DevOps Work Items, and Jira.
3
+ A terminal UI for issue tracking, built for developers who live in the terminal. Track work items across multiple backends — GitHub Issues, GitLab Issues, Azure DevOps Work Items, and Jira — with local SQLite storage.
4
4
 
5
5
  Built with TypeScript and [Ink](https://github.com/vadimdemedes/ink).
6
6
 
7
7
  ## Features
8
8
 
9
9
  - **Keyboard-driven TUI** — browse, create, edit, and manage work items without leaving the terminal
10
- - **Multiple backends** — local markdown, GitHub (via `gh`), GitLab (via `glab`), Azure DevOps (via `az`), Jira (via REST API)
10
+ - **Multiple backends** — GitHub (via `gh`), GitLab (via `glab`), Azure DevOps (via `az`), Jira (via REST API)
11
11
  - **Automatic backend detection** — selects backend based on git remote, or configure manually
12
- - **Local markdown storage** — work items stored as markdown files with YAML frontmatter in a `.tic/` directory
12
+ - **SQLite storage** — all data stored locally in `.tic/tic.db` with optional sync to remote backends
13
13
  - **CLI commands** — scriptable commands for all operations (`tic item list`, `tic item create`, etc.)
14
14
  - **Work item types** — organize by epic, issue, and task (configurable)
15
15
  - **Iterations** — group work into sprints or milestones
@@ -39,16 +39,18 @@ tic init # Initialize (auto-detects backend from git remote)
39
39
  tic # Launch the TUI
40
40
  ```
41
41
 
42
- For local storage, `tic init` creates a `.tic/` directory to store your work items. For GitHub, GitLab, or Azure DevOps projects, it detects the backend from the git remote automatically. You can also specify a backend explicitly:
42
+ `tic init` creates a `.tic/` directory with a SQLite database to store your work items. For GitHub, GitLab, or Azure DevOps projects, it detects the backend from the git remote automatically. You can also specify a backend explicitly:
43
43
 
44
44
  ```bash
45
45
  tic init --backend github
46
46
  tic init --backend gitlab
47
47
  tic init --backend azure
48
48
  tic init --backend jira
49
- tic init --backend local
49
+ tic init --backend none
50
50
  ```
51
51
 
52
+ The TUI also auto-initializes on first run if no `.tic/` directory exists.
53
+
52
54
  ## Usage
53
55
 
54
56
  ### List View
@@ -123,70 +125,22 @@ Deleting an item automatically cleans up references — children have their pare
123
125
 
124
126
  ## Storage
125
127
 
126
- Work items live in `.tic/` at the root of your project:
128
+ All data lives in `.tic/` at the root of your project:
127
129
 
128
130
  ```
129
131
  .tic/
130
- ├── config.yml # Types, statuses, iterations, settings
131
- ├── items/
132
- ├── 1.md # Work item #1
133
- ├── 2.md # Work item #2
134
- └── ...
135
- ├── templates/ # Work item templates
136
- │ └── bug-report.md # Template with YAML frontmatter
137
- └── trash/ # Soft-deleted items (for undo)
132
+ ├── tic.db # SQLite database (all items, config, undo log)
133
+ └── items/ # Markdown mirrors (for sync / human-readable export)
134
+ ├── 1.md
135
+ ├── 2.md
136
+ └── ...
138
137
  ```
139
138
 
140
- Each item is a markdown file with YAML frontmatter:
141
-
142
- ```markdown
143
- ---
144
- id: 1
145
- title: Implement user login
146
- type: task
147
- status: in-progress
148
- iteration: sprint-1
149
- priority: high
150
- assignee: alice
151
- labels: auth, backend
152
- parent: 3
153
- depends_on:
154
- - 2
155
- created: 2026-01-15T10:00:00.000Z
156
- updated: 2026-01-20T14:30:00.000Z
157
- ---
158
-
159
- Full description of the work item goes here.
160
-
161
- ## Comments
162
-
163
- ---
164
- author: alice
165
- date: 2026-01-18T09:00:00.000Z
166
-
167
- Decided to use JWT tokens for this.
168
- ```
139
+ The SQLite database (`.tic/tic.db`) is the single source of truth for work items, config, templates, and undo history. When a remote backend is configured, `SyncManager` also writes markdown mirrors to `.tic/items/` via `FilesBackend`.
169
140
 
170
- Configuration in `.tic/config.yml`:
171
-
172
- ```yaml
173
- types:
174
- - epic
175
- - issue
176
- - task
177
- statuses:
178
- - backlog
179
- - todo
180
- - in-progress
181
- - review
182
- - done
183
- iterations:
184
- - default
185
- current_iteration: default
186
- next_id: 1
187
- ```
141
+ Configuration (types, statuses, iterations, etc.) is stored in the `project_config` table and managed via the TUI settings screen or `tic config` CLI commands.
188
142
 
189
- You can edit these files directly they're plain text. Customize types, statuses, and iterations by editing `config.yml`.
143
+ If upgrading from a legacy `.tic/config.yml` setup, the database will automatically migrate the YAML config on first open.
190
144
 
191
145
  ## Claude Code Integration
192
146
 
@@ -240,7 +194,7 @@ Add `--json` to any command for machine-readable output, or `--quiet` to suppres
240
194
 
241
195
  | Backend | CLI Tool | Detection |
242
196
  |---------|----------|-----------|
243
- | Local markdown | — | Default fallback |
197
+ | Local only (SQLite) | — | Default fallback |
244
198
  | GitHub Issues | [`gh`](https://cli.github.com/) | `github.com` in git remote |
245
199
  | GitLab Issues | [`glab`](https://gitlab.com/gitlab-org/cli) | `gitlab.com` in git remote |
246
200
  | Azure DevOps Work Items | [`az`](https://learn.microsoft.com/en-us/cli/azure/) | `dev.azure.com` or `visualstudio.com` in git remote |
@@ -0,0 +1,27 @@
1
+ export declare const GITHUB_ACCOUNT = "github.com";
2
+ export declare const DEFAULT_CLIENT_ID = "Ov23lizRXsY0iSURg1he";
3
+ /**
4
+ * Retrieve the stored GitHub token from the system keychain.
5
+ * Returns null if no token is found.
6
+ */
7
+ export declare function getGitHubToken(): string | null;
8
+ /**
9
+ * Remove the stored GitHub token from the system keychain.
10
+ */
11
+ export declare function clearGitHubToken(): void;
12
+ export interface AuthenticateGitHubOptions {
13
+ clientId?: string;
14
+ onCode?: (userCode: string, verificationUri: string) => void;
15
+ }
16
+ /**
17
+ * Run the GitHub OAuth device flow to authenticate the user.
18
+ *
19
+ * 1. Requests a device code from GitHub
20
+ * 2. Calls onCode callback so the caller can display the code/URL to the user
21
+ * 3. Polls GitHub for the access token at the specified interval
22
+ * 4. Stores the token in the system keychain on success
23
+ *
24
+ * @returns The access token
25
+ * @throws On access_denied, expired_token, or unexpected errors
26
+ */
27
+ export declare function authenticateGitHub(options?: AuthenticateGitHubOptions): Promise<string>;
@@ -0,0 +1,96 @@
1
+ import { getToken, setToken, deleteToken } from './keychain.js';
2
+ export const GITHUB_ACCOUNT = 'github.com';
3
+ export const DEFAULT_CLIENT_ID = 'Ov23lizRXsY0iSURg1he';
4
+ /**
5
+ * Retrieve the stored GitHub token from the system keychain.
6
+ * Returns null if no token is found.
7
+ */
8
+ export function getGitHubToken() {
9
+ return getToken(GITHUB_ACCOUNT);
10
+ }
11
+ /**
12
+ * Remove the stored GitHub token from the system keychain.
13
+ */
14
+ export function clearGitHubToken() {
15
+ deleteToken(GITHUB_ACCOUNT);
16
+ }
17
+ function isTokenError(response) {
18
+ return 'error' in response;
19
+ }
20
+ function sleep(ms) {
21
+ return new Promise((resolve) => setTimeout(resolve, ms));
22
+ }
23
+ /**
24
+ * Run the GitHub OAuth device flow to authenticate the user.
25
+ *
26
+ * 1. Requests a device code from GitHub
27
+ * 2. Calls onCode callback so the caller can display the code/URL to the user
28
+ * 3. Polls GitHub for the access token at the specified interval
29
+ * 4. Stores the token in the system keychain on success
30
+ *
31
+ * @returns The access token
32
+ * @throws On access_denied, expired_token, or unexpected errors
33
+ */
34
+ export async function authenticateGitHub(options) {
35
+ const clientId = options?.clientId ?? DEFAULT_CLIENT_ID;
36
+ // Step 1: Request device code
37
+ const codeResponse = await fetch('https://github.com/login/device/code', {
38
+ method: 'POST',
39
+ headers: {
40
+ Accept: 'application/json',
41
+ 'Content-Type': 'application/json',
42
+ },
43
+ body: JSON.stringify({
44
+ client_id: clientId,
45
+ scope: 'repo',
46
+ }),
47
+ });
48
+ if (!codeResponse.ok) {
49
+ throw new Error(`Failed to request device code: ${codeResponse.status} ${codeResponse.statusText}`);
50
+ }
51
+ const deviceCode = (await codeResponse.json());
52
+ // Step 2: Notify caller with user code and verification URL
53
+ options?.onCode?.(deviceCode.user_code, deviceCode.verification_uri);
54
+ // Step 3: Poll for access token
55
+ let interval = deviceCode.interval * 1000; // Convert to ms
56
+ while (true) {
57
+ await sleep(interval);
58
+ const tokenResponse = await fetch('https://github.com/login/oauth/access_token', {
59
+ method: 'POST',
60
+ headers: {
61
+ Accept: 'application/json',
62
+ 'Content-Type': 'application/json',
63
+ },
64
+ body: JSON.stringify({
65
+ client_id: clientId,
66
+ device_code: deviceCode.device_code,
67
+ grant_type: 'urn:ietf:params:oauth:grant-type:device_code',
68
+ }),
69
+ });
70
+ if (!tokenResponse.ok) {
71
+ throw new Error(`Failed to poll for token: ${tokenResponse.status} ${tokenResponse.statusText}`);
72
+ }
73
+ const data = (await tokenResponse.json());
74
+ if (isTokenError(data)) {
75
+ switch (data.error) {
76
+ case 'authorization_pending':
77
+ // User hasn't authorized yet, keep polling
78
+ continue;
79
+ case 'slow_down':
80
+ // GitHub wants us to increase the polling interval by 5 seconds
81
+ interval += 5000;
82
+ continue;
83
+ case 'access_denied':
84
+ throw new Error('Authorization was denied by the user');
85
+ case 'expired_token':
86
+ throw new Error('Device code has expired. Please restart the authentication flow.');
87
+ default:
88
+ throw new Error(`Authentication failed: ${data.error}${data.error_description ? ` - ${data.error_description}` : ''}`);
89
+ }
90
+ }
91
+ // Success - store token and return
92
+ setToken(GITHUB_ACCOUNT, data.access_token);
93
+ return data.access_token;
94
+ }
95
+ }
96
+ //# sourceMappingURL=github.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github.js","sourceRoot":"","sources":["../../src/auth/github.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export { getToken, setToken, deleteToken } from './keychain.js';
2
+ export { GITHUB_ACCOUNT, DEFAULT_CLIENT_ID, getGitHubToken, clearGitHubToken, authenticateGitHub, } from './github.js';
3
+ export type { AuthenticateGitHubOptions } from './github.js';
@@ -0,0 +1,3 @@
1
+ export { getToken, setToken, deleteToken } from './keychain.js';
2
+ export { GITHUB_ACCOUNT, DEFAULT_CLIENT_ID, getGitHubToken, clearGitHubToken, authenticateGitHub, } from './github.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAChE,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,cAAc,EACd,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,aAAa,CAAC"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Retrieve a token from the system keychain.
3
+ * Returns null if no token is found for the given account.
4
+ */
5
+ export declare function getToken(account: string): string | null;
6
+ /**
7
+ * Store a token in the system keychain.
8
+ */
9
+ export declare function setToken(account: string, token: string): void;
10
+ /**
11
+ * Remove a token from the system keychain.
12
+ * No-op if no token is found for the given account.
13
+ */
14
+ export declare function deleteToken(account: string): void;
@@ -0,0 +1,36 @@
1
+ import { Entry } from '@napi-rs/keyring';
2
+ const SERVICE = 'tic';
3
+ /**
4
+ * Retrieve a token from the system keychain.
5
+ * Returns null if no token is found for the given account.
6
+ */
7
+ export function getToken(account) {
8
+ const entry = new Entry(SERVICE, account);
9
+ try {
10
+ return entry.getPassword();
11
+ }
12
+ catch {
13
+ return null;
14
+ }
15
+ }
16
+ /**
17
+ * Store a token in the system keychain.
18
+ */
19
+ export function setToken(account, token) {
20
+ const entry = new Entry(SERVICE, account);
21
+ entry.setPassword(token);
22
+ }
23
+ /**
24
+ * Remove a token from the system keychain.
25
+ * No-op if no token is found for the given account.
26
+ */
27
+ export function deleteToken(account) {
28
+ const entry = new Entry(SERVICE, account);
29
+ try {
30
+ entry.deletePassword();
31
+ }
32
+ catch {
33
+ // No-op if not found
34
+ }
35
+ }
36
+ //# sourceMappingURL=keychain.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keychain.js","sourceRoot":"","sources":["../../src/auth/keychain.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAEzC,MAAM,OAAO,GAAG,KAAK,CAAC;AAEtB;;;GAGG;AACH,MAAM,UAAU,QAAQ,CAAC,OAAe;IACtC,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC1C,IAAI,CAAC;QACH,OAAO,KAAK,CAAC,WAAW,EAAE,CAAC;IAC7B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,QAAQ,CAAC,OAAe,EAAE,KAAa;IACrD,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC1C,KAAK,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;AAC3B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,OAAe;IACzC,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC1C,IAAI,CAAC;QACH,KAAK,CAAC,cAAc,EAAE,CAAC;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,qBAAqB;IACvB,CAAC;AACH,CAAC"}
@@ -3,12 +3,15 @@ import type { SyncQueueAdapter } from '../sync/types.js';
3
3
  import { SyncManager } from '../sync/SyncManager.js';
4
4
  export declare const VALID_BACKENDS: readonly ["none", "filesystem", "github", "gitlab", "azure", "jira"];
5
5
  export type BackendType = (typeof VALID_BACKENDS)[number];
6
+ export interface RemoteBackendOptions {
7
+ skipAuth?: boolean;
8
+ }
6
9
  export declare function detectBackend(root: string): BackendType;
7
10
  export declare function createBackend(root: string): Promise<Backend>;
8
- export declare function createRemoteBackend(root: string, backendType: string): Promise<Backend | null>;
11
+ export declare function createRemoteBackend(root: string, backendType: string, options?: RemoteBackendOptions): Promise<Backend | null>;
9
12
  export interface BackendSetup {
10
13
  backend: Backend;
11
14
  syncManager: SyncManager | null;
12
15
  queue: SyncQueueAdapter | null;
13
16
  }
14
- export declare function createBackendWithSync(root: string): Promise<BackendSetup>;
17
+ export declare function createBackendWithSync(root: string, options?: RemoteBackendOptions): Promise<BackendSetup>;
@@ -40,7 +40,7 @@ export async function createBackend(root) {
40
40
  }
41
41
  return primary;
42
42
  }
43
- export async function createRemoteBackend(root, backendType) {
43
+ export async function createRemoteBackend(root, backendType, options) {
44
44
  switch (backendType) {
45
45
  case 'none':
46
46
  return null;
@@ -50,7 +50,7 @@ export async function createRemoteBackend(root, backendType) {
50
50
  }
51
51
  case 'github': {
52
52
  const { GitHubBackend } = await import('./github/index.js');
53
- return new GitHubBackend(root);
53
+ return GitHubBackend.create(root, options);
54
54
  }
55
55
  case 'gitlab': {
56
56
  const { GitLabBackend } = await import('./gitlab/index.js');
@@ -68,14 +68,14 @@ export async function createRemoteBackend(root, backendType) {
68
68
  return null;
69
69
  }
70
70
  }
71
- export async function createBackendWithSync(root) {
71
+ export async function createBackendWithSync(root, options) {
72
72
  const primary = Storage.create(root);
73
73
  configStore.getState().setDatabase(primary.getDatabase());
74
74
  if (!configStore.getState().loaded) {
75
75
  await configStore.getState().init(root);
76
76
  }
77
77
  const config = configStore.getState().config;
78
- const remote = await createRemoteBackend(root, config.backend ?? 'none');
78
+ const remote = await createRemoteBackend(root, config.backend ?? 'none', options);
79
79
  let syncManager = null;
80
80
  let queue = null;
81
81
  if (remote) {
@@ -1 +1 @@
1
- {"version":3,"file":"factory.js","sourceRoot":"","sources":["../../src/backends/factory.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"factory.js","sourceRoot":"","sources":["../../src/backends/factory.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import { BaseApiClient } from '../shared/api-client.js';
2
+ export declare class GitHubApiClient extends BaseApiClient {
3
+ constructor(token: string);
4
+ protected fetch<T>(method: string, path: string, body?: unknown): Promise<T>;
5
+ rest<T>(method: string, path: string, body?: unknown): Promise<T>;
6
+ graphql<T>(query: string, variables?: Record<string, unknown>): Promise<T>;
7
+ private graphqlFetch;
8
+ paginate<T>(path: string): AsyncGenerator<T[]>;
9
+ }
@@ -0,0 +1,117 @@
1
+ import { AuthError, RateLimitError, BaseApiClient, } from '../shared/api-client.js';
2
+ const GITHUB_API_VERSION = '2022-11-28';
3
+ export class GitHubApiClient extends BaseApiClient {
4
+ constructor(token) {
5
+ super(token, 'https://api.github.com');
6
+ }
7
+ async fetch(method, path, body) {
8
+ const url = this.baseUrl + path;
9
+ const headers = {
10
+ Authorization: `Bearer ${this.token}`,
11
+ Accept: 'application/json',
12
+ 'X-GitHub-Api-Version': GITHUB_API_VERSION,
13
+ };
14
+ const init = { method, headers };
15
+ if (body !== undefined && ['POST', 'PATCH', 'PUT'].includes(method)) {
16
+ headers['Content-Type'] = 'application/json';
17
+ init.body = JSON.stringify(body);
18
+ }
19
+ const response = await globalThis.fetch(url, init);
20
+ this.checkRateLimit(response.headers);
21
+ if (response.status === 401) {
22
+ throw new AuthError();
23
+ }
24
+ if (response.status === 403) {
25
+ const remaining = response.headers.get('X-RateLimit-Remaining');
26
+ const reset = response.headers.get('X-RateLimit-Reset');
27
+ if (remaining === '0' && reset) {
28
+ throw new RateLimitError(new Date(Number(reset) * 1000));
29
+ }
30
+ }
31
+ if (!response.ok) {
32
+ const text = await response.text();
33
+ throw new Error(`HTTP ${response.status}: ${text}`);
34
+ }
35
+ return (await response.json());
36
+ }
37
+ async rest(method, path, body) {
38
+ return this.retry(() => this.fetch(method, path, body));
39
+ }
40
+ async graphql(query, variables) {
41
+ return this.retry(() => this.graphqlFetch(query, variables));
42
+ }
43
+ async graphqlFetch(query, variables) {
44
+ const url = this.baseUrl + '/graphql';
45
+ const headers = {
46
+ Authorization: `Bearer ${this.token}`,
47
+ 'Content-Type': 'application/json',
48
+ 'X-GitHub-Api-Version': GITHUB_API_VERSION,
49
+ 'GraphQL-Features': 'sub_issues',
50
+ };
51
+ const response = await globalThis.fetch(url, {
52
+ method: 'POST',
53
+ headers,
54
+ body: JSON.stringify({ query, variables }),
55
+ });
56
+ this.checkRateLimit(response.headers);
57
+ if (response.status === 401) {
58
+ throw new AuthError();
59
+ }
60
+ if (response.status === 403) {
61
+ const remaining = response.headers.get('X-RateLimit-Remaining');
62
+ const reset = response.headers.get('X-RateLimit-Reset');
63
+ if (remaining === '0' && reset) {
64
+ throw new RateLimitError(new Date(Number(reset) * 1000));
65
+ }
66
+ }
67
+ if (!response.ok) {
68
+ const text = await response.text();
69
+ throw new Error(`HTTP ${response.status}: ${text}`);
70
+ }
71
+ const json = (await response.json());
72
+ const firstError = json.errors?.[0];
73
+ if (firstError) {
74
+ throw new Error(`GraphQL error: ${firstError.message}`);
75
+ }
76
+ return json.data;
77
+ }
78
+ async *paginate(path) {
79
+ let url = this.baseUrl + path;
80
+ while (url) {
81
+ const headers = {
82
+ Authorization: `Bearer ${this.token}`,
83
+ Accept: 'application/json',
84
+ 'X-GitHub-Api-Version': GITHUB_API_VERSION,
85
+ };
86
+ const response = await globalThis.fetch(url, {
87
+ method: 'GET',
88
+ headers,
89
+ });
90
+ this.checkRateLimit(response.headers);
91
+ if (response.status === 401) {
92
+ throw new AuthError();
93
+ }
94
+ if (!response.ok) {
95
+ const text = await response.text();
96
+ throw new Error(`HTTP ${response.status}: ${text}`);
97
+ }
98
+ const data = (await response.json());
99
+ yield data;
100
+ const linkHeader = response.headers.get('Link');
101
+ url = parseLinkNext(linkHeader);
102
+ }
103
+ }
104
+ }
105
+ function parseLinkNext(linkHeader) {
106
+ if (!linkHeader)
107
+ return null;
108
+ const parts = linkHeader.split(',');
109
+ for (const part of parts) {
110
+ const match = part.match(/<([^>]+)>;\s*rel="next"/);
111
+ if (match?.[1]) {
112
+ return match[1];
113
+ }
114
+ }
115
+ return null;
116
+ }
117
+ //# sourceMappingURL=api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../../../src/backends/github/api.ts"],"names":[],"mappings":"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"}
@@ -1,11 +1,17 @@
1
1
  import { BaseBackend } from '../types.js';
2
2
  import type { BackendCapabilities } from '../types.js';
3
3
  import type { WorkItem, NewWorkItem, NewComment, Comment, Template } from '../../types.js';
4
+ export interface GitHubBackendOptions {
5
+ skipAuth?: boolean;
6
+ }
4
7
  export declare class GitHubBackend extends BaseBackend {
5
- private cwd;
6
- private ownerRepo;
8
+ private api;
9
+ private owner;
10
+ private repo;
7
11
  private cachedMilestones;
8
- constructor(cwd: string);
12
+ private constructor();
13
+ static create(cwd: string, options?: GitHubBackendOptions): Promise<GitHubBackend>;
14
+ private static detectOwnerRepo;
9
15
  protected onCacheInvalidate(): void;
10
16
  getCapabilities(): BackendCapabilities;
11
17
  getStatuses(): Promise<string[]>;
@@ -32,8 +38,6 @@ export declare class GitHubBackend extends BaseBackend {
32
38
  private getIssueNodeId;
33
39
  private addSubIssue;
34
40
  private removeSubIssue;
35
- private getOwnerRepo;
36
41
  private fetchMilestones;
37
42
  private fetchOpenMilestones;
38
- private getRepoNwo;
39
43
  }