@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.
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +17 -63
- package/dist/auth/github.d.ts +27 -0
- package/dist/auth/github.js +96 -0
- package/dist/auth/github.js.map +1 -0
- package/dist/auth/index.d.ts +3 -0
- package/dist/auth/index.js +3 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/keychain.d.ts +14 -0
- package/dist/auth/keychain.js +36 -0
- package/dist/auth/keychain.js.map +1 -0
- package/dist/backends/factory.d.ts +5 -2
- package/dist/backends/factory.js +4 -4
- package/dist/backends/factory.js.map +1 -1
- package/dist/backends/github/api.d.ts +9 -0
- package/dist/backends/github/api.js +117 -0
- package/dist/backends/github/api.js.map +1 -0
- package/dist/backends/github/index.d.ts +9 -5
- package/dist/backends/github/index.js +119 -81
- package/dist/backends/github/index.js.map +1 -1
- package/dist/backends/github/mappers.d.ts +1 -0
- package/dist/backends/github/mappers.js.map +1 -1
- package/dist/backends/shared/api-client.d.ts +16 -0
- package/dist/backends/shared/api-client.js +73 -0
- package/dist/backends/shared/api-client.js.map +1 -0
- package/dist/cli/commands/auth.d.ts +17 -0
- package/dist/cli/commands/auth.js +47 -0
- package/dist/cli/commands/auth.js.map +1 -0
- package/dist/cli/commands/mcp.js +32 -9
- package/dist/cli/commands/mcp.js.map +1 -1
- package/dist/cli/index.js +58 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/components/AutocompleteInput.d.ts +2 -1
- package/dist/components/AutocompleteInput.js +5 -1
- package/dist/components/AutocompleteInput.js.map +1 -1
- package/dist/components/MultiAutocompleteInput.d.ts +2 -1
- package/dist/components/MultiAutocompleteInput.js +5 -1
- package/dist/components/MultiAutocompleteInput.js.map +1 -1
- package/dist/components/WorkItemForm.js +12 -0
- package/dist/components/WorkItemForm.js.map +1 -1
- package/dist/stores/backendDataStore.js +12 -1
- package/dist/stores/backendDataStore.js.map +1 -1
- package/drizzle/0000_next_vance_astro.sql +183 -0
- package/drizzle/meta/0000_snapshot.json +1188 -0
- package/drizzle/meta/_journal.json +13 -0
- package/package.json +4 -1
- package/skills/config/SKILL.md +2 -2
- package/dist/backends/github/gh.d.ts +0 -9
- package/dist/backends/github/gh.js +0 -95
- package/dist/backends/github/gh.js.map +0 -1
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 —
|
|
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** —
|
|
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
|
-
- **
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
128
|
+
All data lives in `.tic/` at the root of your project:
|
|
127
129
|
|
|
128
130
|
```
|
|
129
131
|
.tic/
|
|
130
|
-
├──
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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 @@
|
|
|
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>;
|
package/dist/backends/factory.js
CHANGED
|
@@ -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
|
|
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":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAG9C,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAErD,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,MAAM;IACN,YAAY;IACZ,QAAQ;IACR,QAAQ;IACR,OAAO;IACP,MAAM;CACE,CAAC;
|
|
1
|
+
{"version":3,"file":"factory.js","sourceRoot":"","sources":["../../src/backends/factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAG9C,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAErD,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,MAAM;IACN,YAAY;IACZ,QAAQ;IACR,QAAQ;IACR,OAAO;IACP,MAAM;CACE,CAAC;AAOX,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,QAAQ,CAAC,eAAe,EAAE;YACvC,GAAG,EAAE,IAAI;YACT,QAAQ,EAAE,OAAO;YACjB,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;SAChC,CAAC,CAAC;QACH,IAAI,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC;YAAE,OAAO,QAAQ,CAAC;QACnD,IAAI,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC;YAAE,OAAO,QAAQ,CAAC;QACnD,IACE,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAC;YAChC,MAAM,CAAC,QAAQ,CAAC,mBAAmB,CAAC;YACpC,wBAAwB,CAAC,IAAI,CAAC,MAAM,CAAC;YAErC,OAAO,OAAO,CAAC;IACnB,CAAC;IAAC,MAAM,CAAC;QACP,sCAAsC;IACxC,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAAY;IAC9C,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACrC,WAAW,CAAC,QAAQ,EAAE,CAAC,WAAW,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IAC1D,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,CAAC;QACnC,MAAM,WAAW,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1C,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,IAAY,EACZ,WAAmB,EACnB,OAA8B;IAE9B,QAAQ,WAAW,EAAE,CAAC;QACpB,KAAK,MAAM;YACT,OAAO,IAAI,CAAC;QACd,KAAK,YAAY,CAAC,CAAC,CAAC;YAClB,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAC;YAC1D,OAAO,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC;QAChC,CAAC;QACD,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,MAAM,CAAC,mBAAmB,CAAC,CAAC;YAC5D,OAAO,aAAa,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC7C,CAAC;QACD,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,MAAM,CAAC,mBAAmB,CAAC,CAAC;YAC5D,OAAO,IAAI,aAAa,CAAC,IAAI,CAAC,CAAC;QACjC,CAAC;QACD,KAAK,OAAO,CAAC,CAAC,CAAC;YACb,MAAM,EAAE,kBAAkB,EAAE,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAC;YAC9D,OAAO,IAAI,kBAAkB,CAAC,IAAI,CAAC,CAAC;QACtC,CAAC;QACD,KAAK,MAAM,CAAC,CAAC,CAAC;YACZ,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,MAAM,CAAC,iBAAiB,CAAC,CAAC;YACxD,OAAO,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAClC,CAAC;QACD;YACE,OAAO,IAAI,CAAC;IAChB,CAAC;AACH,CAAC;AAQD,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,IAAY,EACZ,OAA8B;IAE9B,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACrC,WAAW,CAAC,QAAQ,EAAE,CAAC,WAAW,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IAE1D,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,CAAC;QACnC,MAAM,WAAW,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1C,CAAC;IAED,MAAM,MAAM,GAAG,WAAW,CAAC,QAAQ,EAAE,CAAC,MAAM,CAAC;IAC7C,MAAM,MAAM,GAAG,MAAM,mBAAmB,CACtC,IAAI,EACJ,MAAM,CAAC,OAAO,IAAI,MAAM,EACxB,OAAO,CACR,CAAC;IAEF,IAAI,WAAW,GAAuB,IAAI,CAAC;IAC3C,IAAI,KAAK,GAA4B,IAAI,CAAC;IAC1C,IAAI,MAAM,EAAE,CAAC;QACX,KAAK,GAAG,IAAI,SAAS,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;QAC7C,WAAW,GAAG,IAAI,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;IACxD,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC;AAClD,CAAC"}
|
|
@@ -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
|
|
6
|
-
private
|
|
8
|
+
private api;
|
|
9
|
+
private owner;
|
|
10
|
+
private repo;
|
|
7
11
|
private cachedMilestones;
|
|
8
|
-
constructor(
|
|
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
|
}
|