@sascha384/tic 4.1.0 → 4.3.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/dist/app.js +4 -2
- package/dist/app.js.map +1 -1
- package/dist/auth/ado.js +76 -28
- package/dist/auth/ado.js.map +1 -1
- package/dist/auth/github.js +57 -24
- package/dist/auth/github.js.map +1 -1
- package/dist/auth/gitlab.js +54 -23
- package/dist/auth/gitlab.js.map +1 -1
- package/dist/auth/jira.d.ts +8 -0
- package/dist/auth/jira.js +24 -0
- package/dist/auth/jira.js.map +1 -0
- package/dist/backends/ado/api.d.ts +1 -0
- package/dist/backends/ado/api.js +66 -16
- package/dist/backends/ado/api.js.map +1 -1
- package/dist/backends/ado/index.js +4 -1
- package/dist/backends/ado/index.js.map +1 -1
- package/dist/backends/factory.js +1 -1
- package/dist/backends/factory.js.map +1 -1
- package/dist/backends/files/index.js +1 -0
- package/dist/backends/files/index.js.map +1 -1
- package/dist/backends/github/api.js +61 -17
- package/dist/backends/github/api.js.map +1 -1
- package/dist/backends/github/index.js +1 -0
- package/dist/backends/github/index.js.map +1 -1
- package/dist/backends/github/mappers.d.ts +1 -1
- package/dist/backends/github/mappers.js +1 -1
- package/dist/backends/github/mappers.js.map +1 -1
- package/dist/backends/gitlab/api.js +22 -8
- package/dist/backends/gitlab/api.js.map +1 -1
- package/dist/backends/gitlab/index.js +1 -0
- package/dist/backends/gitlab/index.js.map +1 -1
- package/dist/backends/jira/api.d.ts +9 -0
- package/dist/backends/jira/api.js +89 -0
- package/dist/backends/jira/api.js.map +1 -0
- package/dist/backends/jira/index.d.ts +10 -2
- package/dist/backends/jira/index.js +140 -161
- package/dist/backends/jira/index.js.map +1 -1
- package/dist/backends/jira/mappers.d.ts +8 -2
- package/dist/backends/jira/mappers.js +20 -5
- package/dist/backends/jira/mappers.js.map +1 -1
- package/dist/backends/shared/api-client.d.ts +1 -0
- package/dist/backends/shared/api-client.js +18 -3
- package/dist/backends/shared/api-client.js.map +1 -1
- package/dist/backends/types.d.ts +1 -0
- package/dist/backends/types.js.map +1 -1
- package/dist/cli/commands/auth.js +34 -2
- package/dist/cli/commands/auth.js.map +1 -1
- package/dist/cli/commands/item.js +2 -2
- package/dist/cli/commands/item.js.map +1 -1
- package/dist/components/AuthPrompt.js +36 -4
- package/dist/components/AuthPrompt.js.map +1 -1
- package/dist/components/ErrorBoundary.d.ts +14 -0
- package/dist/components/ErrorBoundary.js +30 -0
- package/dist/components/ErrorBoundary.js.map +1 -0
- package/dist/components/Settings.js +82 -17
- package/dist/components/Settings.js.map +1 -1
- package/dist/components/StatusScreen.js +3 -1
- package/dist/components/StatusScreen.js.map +1 -1
- package/dist/components/WorkItemForm.js +57 -14
- package/dist/components/WorkItemForm.js.map +1 -1
- package/dist/components/WorkItemList.js +141 -35
- package/dist/components/WorkItemList.js.map +1 -1
- package/dist/components/getMarkedDistribution.d.ts +6 -0
- package/dist/components/getMarkedDistribution.js +17 -0
- package/dist/components/getMarkedDistribution.js.map +1 -0
- package/dist/editor.js +0 -1
- package/dist/editor.js.map +1 -1
- package/dist/hooks/useFormValidation.d.ts +20 -0
- package/dist/hooks/useFormValidation.js +146 -0
- package/dist/hooks/useFormValidation.js.map +1 -0
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/storage/index.js +15 -12
- package/dist/storage/index.js.map +1 -1
- package/dist/stores/backendDataStore.d.ts +2 -1
- package/dist/stores/backendDataStore.js +78 -6
- package/dist/stores/backendDataStore.js.map +1 -1
- package/dist/stores/recentCommandsStore.js +3 -1
- package/dist/stores/recentCommandsStore.js.map +1 -1
- package/dist/sync/SyncManager.d.ts +1 -1
- package/dist/sync/SyncManager.js +51 -10
- package/dist/sync/SyncManager.js.map +1 -1
- package/dist/update-checker.js +5 -3
- package/dist/update-checker.js.map +1 -1
- package/package.json +1 -1
- package/dist/backends/jira/acli.d.ts +0 -6
- package/dist/backends/jira/acli.js +0 -35
- package/dist/backends/jira/acli.js.map +0 -1
package/dist/app.js
CHANGED
|
@@ -31,10 +31,12 @@ export function App() {
|
|
|
31
31
|
// Update check on mount
|
|
32
32
|
useEffect(() => {
|
|
33
33
|
if (autoUpdate !== false) {
|
|
34
|
-
void import('./update-checker.js')
|
|
34
|
+
void import('./update-checker.js')
|
|
35
|
+
.then(({ checkForUpdate }) => checkForUpdate().then((info) => {
|
|
35
36
|
if (info)
|
|
36
37
|
navigationStore.getState().setUpdateInfo(info);
|
|
37
|
-
}))
|
|
38
|
+
}))
|
|
39
|
+
.catch(() => { });
|
|
38
40
|
}
|
|
39
41
|
}, [autoUpdate]);
|
|
40
42
|
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Header, {}), authPrompt ? (_jsx(Suspense, { fallback: null, children: _jsx(AuthPrompt, {}) })) : (_jsxs(_Fragment, { children: [screen === 'list' && _jsx(WorkItemList, {}), _jsxs(Suspense, { fallback: null, children: [screen === 'form' && _jsx(WorkItemForm, {}), screen === 'iteration-picker' && _jsx(IterationPicker, {}), screen === 'settings' && _jsx(Settings, {}), screen === 'status' && _jsx(StatusScreen, {}), screen === 'help' && _jsx(HelpScreen, { sourceScreen: previousScreen })] })] }))] }));
|
package/dist/app.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAClD,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAC1B,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,EACL,eAAe,EACf,kBAAkB,GACnB,MAAM,6BAA6B,CAAC;AAKrC,8CAA8C;AAC9C,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,EAAE,CAC7B,MAAM,CAAC,8BAA8B,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAClD,OAAO,EAAE,CAAC,CAAC,YAAY;CACxB,CAAC,CAAC,CACJ,CAAC;AACF,MAAM,eAAe,GAAG,IAAI,CAAC,GAAG,EAAE,CAChC,MAAM,CAAC,iCAAiC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACrD,OAAO,EAAE,CAAC,CAAC,eAAe;CAC3B,CAAC,CAAC,CACJ,CAAC;AACF,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,CACzB,MAAM,CAAC,0BAA0B,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAC1E,CAAC;AACF,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,EAAE,CAC7B,MAAM,CAAC,8BAA8B,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAClD,OAAO,EAAE,CAAC,CAAC,YAAY;CACxB,CAAC,CAAC,CACJ,CAAC;AACF,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,CAC3B,MAAM,CAAC,4BAA4B,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAChD,OAAO,EAAE,CAAC,CAAC,UAAU;CACtB,CAAC,CAAC,CACJ,CAAC;AACF,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,CAC3B,MAAM,CAAC,4BAA4B,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAChD,OAAO,EAAE,CAAC,CAAC,UAAU;CACtB,CAAC,CAAC,CACJ,CAAC;AAEF,MAAM,UAAU,GAAG;IACjB,MAAM,MAAM,GAAG,kBAAkB,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IACnD,MAAM,cAAc,GAAG,kBAAkB,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC;IACnE,MAAM,UAAU,GAAG,cAAc,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAC9D,MAAM,UAAU,GAAG,mBAAmB,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;IAE5D,wBAAwB;IACxB,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,UAAU,KAAK,KAAK,EAAE,CAAC;YACzB,KAAK,MAAM,CAAC,qBAAqB,CAAC,
|
|
1
|
+
{"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.tsx"],"names":[],"mappings":"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"}
|
package/dist/auth/ado.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { getToken, setToken, deleteToken } from './keychain.js';
|
|
2
|
+
import { DEFAULT_TIMEOUT_MS } from '../backends/shared/api-client.js';
|
|
2
3
|
export const ADO_ACCOUNT = 'dev.azure.com';
|
|
3
4
|
export const ADO_REFRESH_ACCOUNT = 'dev.azure.com:refresh';
|
|
4
5
|
export const ADO_PAT_ACCOUNT = 'dev.azure.com:pat';
|
|
@@ -40,16 +41,31 @@ function urlEncode(params) {
|
|
|
40
41
|
*/
|
|
41
42
|
export async function refreshAdoToken(refreshToken) {
|
|
42
43
|
try {
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
44
|
+
const controller = new AbortController();
|
|
45
|
+
const timeout = setTimeout(() => controller.abort(), DEFAULT_TIMEOUT_MS);
|
|
46
|
+
let response;
|
|
47
|
+
try {
|
|
48
|
+
response = await fetch(`${AUTHORITY}/oauth2/v2.0/token`, {
|
|
49
|
+
method: 'POST',
|
|
50
|
+
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
51
|
+
body: urlEncode({
|
|
52
|
+
client_id: AZURE_CLI_CLIENT_ID,
|
|
53
|
+
grant_type: 'refresh_token',
|
|
54
|
+
refresh_token: refreshToken,
|
|
55
|
+
scope: ADO_SCOPE,
|
|
56
|
+
}),
|
|
57
|
+
signal: controller.signal,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
if (error instanceof DOMException && error.name === 'AbortError') {
|
|
62
|
+
throw new Error('Request timed out');
|
|
63
|
+
}
|
|
64
|
+
throw error;
|
|
65
|
+
}
|
|
66
|
+
finally {
|
|
67
|
+
clearTimeout(timeout);
|
|
68
|
+
}
|
|
53
69
|
if (!response.ok)
|
|
54
70
|
return null;
|
|
55
71
|
const data = (await response.json());
|
|
@@ -80,14 +96,29 @@ export async function refreshAdoToken(refreshToken) {
|
|
|
80
96
|
*/
|
|
81
97
|
export async function authenticateAdo(options) {
|
|
82
98
|
// Step 1: Request device code
|
|
83
|
-
const
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
99
|
+
const codeController = new AbortController();
|
|
100
|
+
const codeTimeout = setTimeout(() => codeController.abort(), DEFAULT_TIMEOUT_MS);
|
|
101
|
+
let codeResponse;
|
|
102
|
+
try {
|
|
103
|
+
codeResponse = await fetch(`${AUTHORITY}/oauth2/v2.0/devicecode`, {
|
|
104
|
+
method: 'POST',
|
|
105
|
+
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
106
|
+
body: urlEncode({
|
|
107
|
+
client_id: AZURE_CLI_CLIENT_ID,
|
|
108
|
+
scope: ADO_SCOPE,
|
|
109
|
+
}),
|
|
110
|
+
signal: codeController.signal,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
catch (error) {
|
|
114
|
+
if (error instanceof DOMException && error.name === 'AbortError') {
|
|
115
|
+
throw new Error('Request timed out');
|
|
116
|
+
}
|
|
117
|
+
throw error;
|
|
118
|
+
}
|
|
119
|
+
finally {
|
|
120
|
+
clearTimeout(codeTimeout);
|
|
121
|
+
}
|
|
91
122
|
if (!codeResponse.ok) {
|
|
92
123
|
throw new Error(`Failed to request device code: ${codeResponse.status} ${codeResponse.statusText}`);
|
|
93
124
|
}
|
|
@@ -96,17 +127,33 @@ export async function authenticateAdo(options) {
|
|
|
96
127
|
options?.onCode?.(deviceCode.user_code, deviceCode.verification_uri);
|
|
97
128
|
// Step 3: Poll for access token
|
|
98
129
|
let interval = deviceCode.interval * 1000;
|
|
99
|
-
|
|
130
|
+
const deadline = Date.now() + deviceCode.expires_in * 1000;
|
|
131
|
+
while (Date.now() < deadline) {
|
|
100
132
|
await sleep(interval);
|
|
101
|
-
const
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
133
|
+
const tokenController = new AbortController();
|
|
134
|
+
const tokenTimeout = setTimeout(() => tokenController.abort(), DEFAULT_TIMEOUT_MS);
|
|
135
|
+
let tokenResponse;
|
|
136
|
+
try {
|
|
137
|
+
tokenResponse = await fetch(`${AUTHORITY}/oauth2/v2.0/token`, {
|
|
138
|
+
method: 'POST',
|
|
139
|
+
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
140
|
+
body: urlEncode({
|
|
141
|
+
client_id: AZURE_CLI_CLIENT_ID,
|
|
142
|
+
grant_type: 'urn:ietf:params:oauth:grant-type:device_code',
|
|
143
|
+
device_code: deviceCode.device_code,
|
|
144
|
+
}),
|
|
145
|
+
signal: tokenController.signal,
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
catch (error) {
|
|
149
|
+
if (error instanceof DOMException && error.name === 'AbortError') {
|
|
150
|
+
throw new Error('Request timed out');
|
|
151
|
+
}
|
|
152
|
+
throw error;
|
|
153
|
+
}
|
|
154
|
+
finally {
|
|
155
|
+
clearTimeout(tokenTimeout);
|
|
156
|
+
}
|
|
110
157
|
// Entra ID returns 400 for pending/slow_down/declined/expired errors
|
|
111
158
|
if (!tokenResponse.ok) {
|
|
112
159
|
const data = (await tokenResponse.json());
|
|
@@ -132,5 +179,6 @@ export async function authenticateAdo(options) {
|
|
|
132
179
|
}
|
|
133
180
|
return data.access_token;
|
|
134
181
|
}
|
|
182
|
+
throw new Error('Device code has expired. Please restart the authentication flow.');
|
|
135
183
|
}
|
|
136
184
|
//# sourceMappingURL=ado.js.map
|
package/dist/auth/ado.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ado.js","sourceRoot":"","sources":["../../src/auth/ado.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"ado.js","sourceRoot":"","sources":["../../src/auth/ado.ts"],"names":[],"mappings":"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"}
|
package/dist/auth/github.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { getToken, setToken, deleteToken } from './keychain.js';
|
|
2
|
+
import { DEFAULT_TIMEOUT_MS } from '../backends/shared/api-client.js';
|
|
2
3
|
export const GITHUB_ACCOUNT = 'github.com';
|
|
3
4
|
export const DEFAULT_CLIENT_ID = 'Ov23lizRXsY0iSURg1he';
|
|
4
5
|
/**
|
|
@@ -34,28 +35,11 @@ function sleep(ms) {
|
|
|
34
35
|
export async function authenticateGitHub(options) {
|
|
35
36
|
const clientId = options?.clientId ?? DEFAULT_CLIENT_ID;
|
|
36
37
|
// Step 1: Request device code
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
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', {
|
|
38
|
+
const codeController = new AbortController();
|
|
39
|
+
const codeTimeout = setTimeout(() => codeController.abort(), DEFAULT_TIMEOUT_MS);
|
|
40
|
+
let codeResponse;
|
|
41
|
+
try {
|
|
42
|
+
codeResponse = await fetch('https://github.com/login/device/code', {
|
|
59
43
|
method: 'POST',
|
|
60
44
|
headers: {
|
|
61
45
|
Accept: 'application/json',
|
|
@@ -63,10 +47,58 @@ export async function authenticateGitHub(options) {
|
|
|
63
47
|
},
|
|
64
48
|
body: JSON.stringify({
|
|
65
49
|
client_id: clientId,
|
|
66
|
-
|
|
67
|
-
grant_type: 'urn:ietf:params:oauth:grant-type:device_code',
|
|
50
|
+
scope: 'repo',
|
|
68
51
|
}),
|
|
52
|
+
signal: codeController.signal,
|
|
69
53
|
});
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
if (error instanceof DOMException && error.name === 'AbortError') {
|
|
57
|
+
throw new Error('Request timed out');
|
|
58
|
+
}
|
|
59
|
+
throw error;
|
|
60
|
+
}
|
|
61
|
+
finally {
|
|
62
|
+
clearTimeout(codeTimeout);
|
|
63
|
+
}
|
|
64
|
+
if (!codeResponse.ok) {
|
|
65
|
+
throw new Error(`Failed to request device code: ${codeResponse.status} ${codeResponse.statusText}`);
|
|
66
|
+
}
|
|
67
|
+
const deviceCode = (await codeResponse.json());
|
|
68
|
+
// Step 2: Notify caller with user code and verification URL
|
|
69
|
+
options?.onCode?.(deviceCode.user_code, deviceCode.verification_uri);
|
|
70
|
+
// Step 3: Poll for access token
|
|
71
|
+
let interval = deviceCode.interval * 1000; // Convert to ms
|
|
72
|
+
const deadline = Date.now() + deviceCode.expires_in * 1000;
|
|
73
|
+
while (Date.now() < deadline) {
|
|
74
|
+
await sleep(interval);
|
|
75
|
+
const tokenController = new AbortController();
|
|
76
|
+
const tokenTimeout = setTimeout(() => tokenController.abort(), DEFAULT_TIMEOUT_MS);
|
|
77
|
+
let tokenResponse;
|
|
78
|
+
try {
|
|
79
|
+
tokenResponse = await fetch('https://github.com/login/oauth/access_token', {
|
|
80
|
+
method: 'POST',
|
|
81
|
+
headers: {
|
|
82
|
+
Accept: 'application/json',
|
|
83
|
+
'Content-Type': 'application/json',
|
|
84
|
+
},
|
|
85
|
+
body: JSON.stringify({
|
|
86
|
+
client_id: clientId,
|
|
87
|
+
device_code: deviceCode.device_code,
|
|
88
|
+
grant_type: 'urn:ietf:params:oauth:grant-type:device_code',
|
|
89
|
+
}),
|
|
90
|
+
signal: tokenController.signal,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
if (error instanceof DOMException && error.name === 'AbortError') {
|
|
95
|
+
throw new Error('Request timed out');
|
|
96
|
+
}
|
|
97
|
+
throw error;
|
|
98
|
+
}
|
|
99
|
+
finally {
|
|
100
|
+
clearTimeout(tokenTimeout);
|
|
101
|
+
}
|
|
70
102
|
if (!tokenResponse.ok) {
|
|
71
103
|
throw new Error(`Failed to poll for token: ${tokenResponse.status} ${tokenResponse.statusText}`);
|
|
72
104
|
}
|
|
@@ -92,5 +124,6 @@ export async function authenticateGitHub(options) {
|
|
|
92
124
|
setToken(GITHUB_ACCOUNT, data.access_token);
|
|
93
125
|
return data.access_token;
|
|
94
126
|
}
|
|
127
|
+
throw new Error('Device code has expired. Please restart the authentication flow.');
|
|
95
128
|
}
|
|
96
129
|
//# sourceMappingURL=github.js.map
|
package/dist/auth/github.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"github.js","sourceRoot":"","sources":["../../src/auth/github.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"github.js","sourceRoot":"","sources":["../../src/auth/github.ts"],"names":[],"mappings":"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"}
|
package/dist/auth/gitlab.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { getToken, setToken, deleteToken } from './keychain.js';
|
|
2
|
+
import { DEFAULT_TIMEOUT_MS } from '../backends/shared/api-client.js';
|
|
2
3
|
export const GITLAB_ACCOUNT = 'gitlab.com';
|
|
3
4
|
export const GITLAB_PAT_ACCOUNT = 'gitlab.com:pat';
|
|
4
5
|
export const DEFAULT_GITLAB_CLIENT_ID = 'cdcaceeece0df785f6df0e8b94fce6669ec8521787844faed02a5605b29e05bd';
|
|
@@ -49,17 +50,32 @@ function sleep(ms) {
|
|
|
49
50
|
export async function authenticateGitLab(options) {
|
|
50
51
|
const clientId = options?.clientId ?? DEFAULT_GITLAB_CLIENT_ID;
|
|
51
52
|
// Step 1: Request device code
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
53
|
+
const codeController = new AbortController();
|
|
54
|
+
const codeTimeout = setTimeout(() => codeController.abort(), DEFAULT_TIMEOUT_MS);
|
|
55
|
+
let codeResponse;
|
|
56
|
+
try {
|
|
57
|
+
codeResponse = await fetch('https://gitlab.com/oauth/authorize_device', {
|
|
58
|
+
method: 'POST',
|
|
59
|
+
headers: {
|
|
60
|
+
Accept: 'application/json',
|
|
61
|
+
'Content-Type': 'application/json',
|
|
62
|
+
},
|
|
63
|
+
body: JSON.stringify({
|
|
64
|
+
client_id: clientId,
|
|
65
|
+
scope: 'api',
|
|
66
|
+
}),
|
|
67
|
+
signal: codeController.signal,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
if (error instanceof DOMException && error.name === 'AbortError') {
|
|
72
|
+
throw new Error('Request timed out');
|
|
73
|
+
}
|
|
74
|
+
throw error;
|
|
75
|
+
}
|
|
76
|
+
finally {
|
|
77
|
+
clearTimeout(codeTimeout);
|
|
78
|
+
}
|
|
63
79
|
if (!codeResponse.ok) {
|
|
64
80
|
throw new Error(`Failed to request device code: ${codeResponse.status} ${codeResponse.statusText}`);
|
|
65
81
|
}
|
|
@@ -70,18 +86,33 @@ export async function authenticateGitLab(options) {
|
|
|
70
86
|
let interval = deviceCode.interval * 1000; // Convert to ms
|
|
71
87
|
while (true) {
|
|
72
88
|
await sleep(interval);
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
89
|
+
const tokenController = new AbortController();
|
|
90
|
+
const tokenTimeout = setTimeout(() => tokenController.abort(), DEFAULT_TIMEOUT_MS);
|
|
91
|
+
let tokenResponse;
|
|
92
|
+
try {
|
|
93
|
+
tokenResponse = await fetch('https://gitlab.com/oauth/token', {
|
|
94
|
+
method: 'POST',
|
|
95
|
+
headers: {
|
|
96
|
+
Accept: 'application/json',
|
|
97
|
+
'Content-Type': 'application/json',
|
|
98
|
+
},
|
|
99
|
+
body: JSON.stringify({
|
|
100
|
+
client_id: clientId,
|
|
101
|
+
device_code: deviceCode.device_code,
|
|
102
|
+
grant_type: 'urn:ietf:params:oauth:grant-type:device_code',
|
|
103
|
+
}),
|
|
104
|
+
signal: tokenController.signal,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
catch (error) {
|
|
108
|
+
if (error instanceof DOMException && error.name === 'AbortError') {
|
|
109
|
+
throw new Error('Request timed out');
|
|
110
|
+
}
|
|
111
|
+
throw error;
|
|
112
|
+
}
|
|
113
|
+
finally {
|
|
114
|
+
clearTimeout(tokenTimeout);
|
|
115
|
+
}
|
|
85
116
|
if (!tokenResponse.ok) {
|
|
86
117
|
throw new Error(`Failed to poll for token: ${tokenResponse.status} ${tokenResponse.statusText}`);
|
|
87
118
|
}
|
package/dist/auth/gitlab.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gitlab.js","sourceRoot":"","sources":["../../src/auth/gitlab.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"gitlab.js","sourceRoot":"","sources":["../../src/auth/gitlab.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare const JIRA_ACCOUNT_PREFIX = "jira:";
|
|
2
|
+
export interface JiraCredentials {
|
|
3
|
+
email: string;
|
|
4
|
+
token: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function getJiraCredentials(site: string): JiraCredentials | null;
|
|
7
|
+
export declare function setJiraCredentials(site: string, email: string, token: string): void;
|
|
8
|
+
export declare function removeJiraCredentials(site: string): void;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { getToken, setToken, deleteToken } from './keychain.js';
|
|
2
|
+
export const JIRA_ACCOUNT_PREFIX = 'jira:';
|
|
3
|
+
export function getJiraCredentials(site) {
|
|
4
|
+
const stored = getToken(`${JIRA_ACCOUNT_PREFIX}${site}`);
|
|
5
|
+
if (!stored)
|
|
6
|
+
return null;
|
|
7
|
+
let idx = stored.indexOf('\0');
|
|
8
|
+
if (idx < 0) {
|
|
9
|
+
idx = stored.indexOf(':');
|
|
10
|
+
}
|
|
11
|
+
if (idx < 0)
|
|
12
|
+
return null;
|
|
13
|
+
return {
|
|
14
|
+
email: stored.slice(0, idx),
|
|
15
|
+
token: stored.slice(idx + 1),
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
export function setJiraCredentials(site, email, token) {
|
|
19
|
+
setToken(`${JIRA_ACCOUNT_PREFIX}${site}`, `${email}\0${token}`);
|
|
20
|
+
}
|
|
21
|
+
export function removeJiraCredentials(site) {
|
|
22
|
+
deleteToken(`${JIRA_ACCOUNT_PREFIX}${site}`);
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=jira.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jira.js","sourceRoot":"","sources":["../../src/auth/jira.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEhE,MAAM,CAAC,MAAM,mBAAmB,GAAG,OAAO,CAAC;AAO3C,MAAM,UAAU,kBAAkB,CAAC,IAAY;IAC7C,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,mBAAmB,GAAG,IAAI,EAAE,CAAC,CAAC;IACzD,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IAEzB,IAAI,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,IAAI,GAAG,GAAG,CAAC,EAAE,CAAC;QACZ,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC5B,CAAC;IACD,IAAI,GAAG,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IAEzB,OAAO;QACL,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;QAC3B,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC;KAC7B,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,kBAAkB,CAChC,IAAY,EACZ,KAAa,EACb,KAAa;IAEb,QAAQ,CAAC,GAAG,mBAAmB,GAAG,IAAI,EAAE,EAAE,GAAG,KAAK,KAAK,KAAK,EAAE,CAAC,CAAC;AAClE,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,IAAY;IAChD,WAAW,CAAC,GAAG,mBAAmB,GAAG,IAAI,EAAE,CAAC,CAAC;AAC/C,CAAC"}
|
package/dist/backends/ado/api.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { BaseApiClient, AuthError } from '../shared/api-client.js';
|
|
1
|
+
import { BaseApiClient, AuthError, DEFAULT_TIMEOUT_MS, } from '../shared/api-client.js';
|
|
2
2
|
import { getAdoRefreshToken, refreshAdoToken } from '../../auth/ado.js';
|
|
3
3
|
const ADO_API_VERSION = '7.1';
|
|
4
4
|
export class AdoApiClient extends BaseApiClient {
|
|
5
5
|
auth;
|
|
6
|
+
refreshPromise = null;
|
|
6
7
|
constructor(auth, org) {
|
|
7
8
|
const token = auth.type === 'bearer' ? auth.token : auth.pat;
|
|
8
9
|
super(token, `https://dev.azure.com/${org}`);
|
|
@@ -29,22 +30,58 @@ export class AdoApiClient extends BaseApiClient {
|
|
|
29
30
|
headers['Content-Type'] = contentType ?? 'application/json';
|
|
30
31
|
init.body = JSON.stringify(body);
|
|
31
32
|
}
|
|
32
|
-
|
|
33
|
+
const controller = new AbortController();
|
|
34
|
+
const timeout = setTimeout(() => controller.abort(), DEFAULT_TIMEOUT_MS);
|
|
35
|
+
let response;
|
|
36
|
+
try {
|
|
37
|
+
response = await globalThis.fetch(url, {
|
|
38
|
+
...init,
|
|
39
|
+
signal: controller.signal,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
if (error instanceof DOMException && error.name === 'AbortError') {
|
|
44
|
+
throw new Error('Request timed out');
|
|
45
|
+
}
|
|
46
|
+
throw error;
|
|
47
|
+
}
|
|
48
|
+
finally {
|
|
49
|
+
clearTimeout(timeout);
|
|
50
|
+
}
|
|
33
51
|
this.checkRateLimit(response.headers);
|
|
34
52
|
// Try token refresh on 401 for OAuth auth
|
|
35
53
|
if (response.status === 401 && this.auth.type === 'bearer') {
|
|
36
54
|
const refreshToken = getAdoRefreshToken();
|
|
37
55
|
if (refreshToken) {
|
|
38
|
-
|
|
56
|
+
if (!this.refreshPromise) {
|
|
57
|
+
this.refreshPromise = refreshAdoToken(refreshToken).finally(() => {
|
|
58
|
+
this.refreshPromise = null;
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
const newToken = await this.refreshPromise;
|
|
39
62
|
if (newToken) {
|
|
40
63
|
this.auth = { type: 'bearer', token: newToken };
|
|
41
64
|
this.token = newToken;
|
|
42
65
|
headers['Authorization'] = `Bearer ${newToken}`;
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
66
|
+
const retryController = new AbortController();
|
|
67
|
+
const retryTimeout = setTimeout(() => retryController.abort(), DEFAULT_TIMEOUT_MS);
|
|
68
|
+
try {
|
|
69
|
+
response = await globalThis.fetch(url, {
|
|
70
|
+
method,
|
|
71
|
+
headers,
|
|
72
|
+
body: init.body,
|
|
73
|
+
signal: retryController.signal,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
if (error instanceof DOMException && error.name === 'AbortError') {
|
|
78
|
+
throw new Error('Request timed out');
|
|
79
|
+
}
|
|
80
|
+
throw error;
|
|
81
|
+
}
|
|
82
|
+
finally {
|
|
83
|
+
clearTimeout(retryTimeout);
|
|
84
|
+
}
|
|
48
85
|
}
|
|
49
86
|
}
|
|
50
87
|
}
|
|
@@ -52,8 +89,7 @@ export class AdoApiClient extends BaseApiClient {
|
|
|
52
89
|
throw new AuthError();
|
|
53
90
|
}
|
|
54
91
|
if (!response.ok) {
|
|
55
|
-
|
|
56
|
-
throw new Error(`HTTP ${response.status}: ${text}`);
|
|
92
|
+
throw new Error(`HTTP ${response.status}: Request failed`);
|
|
57
93
|
}
|
|
58
94
|
return (await response.json());
|
|
59
95
|
}
|
|
@@ -80,17 +116,31 @@ export class AdoApiClient extends BaseApiClient {
|
|
|
80
116
|
Authorization: this.getAuthHeader(),
|
|
81
117
|
Accept: 'application/json',
|
|
82
118
|
};
|
|
83
|
-
const
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
119
|
+
const controller = new AbortController();
|
|
120
|
+
const timeout = setTimeout(() => controller.abort(), DEFAULT_TIMEOUT_MS);
|
|
121
|
+
let response;
|
|
122
|
+
try {
|
|
123
|
+
response = await globalThis.fetch(url, {
|
|
124
|
+
method: 'GET',
|
|
125
|
+
headers,
|
|
126
|
+
signal: controller.signal,
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
catch (error) {
|
|
130
|
+
if (error instanceof DOMException && error.name === 'AbortError') {
|
|
131
|
+
throw new Error('Request timed out');
|
|
132
|
+
}
|
|
133
|
+
throw error;
|
|
134
|
+
}
|
|
135
|
+
finally {
|
|
136
|
+
clearTimeout(timeout);
|
|
137
|
+
}
|
|
87
138
|
this.checkRateLimit(response.headers);
|
|
88
139
|
if (response.status === 401) {
|
|
89
140
|
throw new AuthError();
|
|
90
141
|
}
|
|
91
142
|
if (!response.ok) {
|
|
92
|
-
|
|
93
|
-
throw new Error(`HTTP ${response.status}: ${text}`);
|
|
143
|
+
throw new Error(`HTTP ${response.status}: Request failed`);
|
|
94
144
|
}
|
|
95
145
|
const json = (await response.json());
|
|
96
146
|
yield json.value;
|