@aligndottech/connector-core 0.5.0 → 0.6.1
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/dist/fetchers/confluence.d.ts +2 -1
- package/dist/fetchers/confluence.d.ts.map +1 -1
- package/dist/fetchers/confluence.js +14 -9
- package/dist/fetchers/confluence.js.map +1 -1
- package/dist/fetchers/errors.d.ts +43 -5
- package/dist/fetchers/errors.d.ts.map +1 -1
- package/dist/fetchers/errors.js +115 -6
- package/dist/fetchers/errors.js.map +1 -1
- package/dist/fetchers/git.d.ts +2 -1
- package/dist/fetchers/git.d.ts.map +1 -1
- package/dist/fetchers/git.js +8 -1
- package/dist/fetchers/git.js.map +1 -1
- package/dist/fetchers/github.d.ts +2 -1
- package/dist/fetchers/github.d.ts.map +1 -1
- package/dist/fetchers/github.js +12 -2
- package/dist/fetchers/github.js.map +1 -1
- package/dist/fetchers/gitlab.d.ts +4 -2
- package/dist/fetchers/gitlab.d.ts.map +1 -1
- package/dist/fetchers/gitlab.js +35 -5
- package/dist/fetchers/gitlab.js.map +1 -1
- package/dist/fetchers/index.d.ts +1 -1
- package/dist/fetchers/index.d.ts.map +1 -1
- package/dist/fetchers/index.js +1 -1
- package/dist/fetchers/index.js.map +1 -1
- package/dist/fetchers/jira.d.ts +2 -1
- package/dist/fetchers/jira.d.ts.map +1 -1
- package/dist/fetchers/jira.js +14 -11
- package/dist/fetchers/jira.js.map +1 -1
- package/dist/fetchers/linear.d.ts +2 -1
- package/dist/fetchers/linear.d.ts.map +1 -1
- package/dist/fetchers/linear.js +22 -4
- package/dist/fetchers/linear.js.map +1 -1
- package/dist/fetchers/notion.d.ts +4 -1
- package/dist/fetchers/notion.d.ts.map +1 -1
- package/dist/fetchers/notion.js +64 -30
- package/dist/fetchers/notion.js.map +1 -1
- package/dist/fetchers/slack.d.ts +12 -3
- package/dist/fetchers/slack.d.ts.map +1 -1
- package/dist/fetchers/slack.js +232 -30
- package/dist/fetchers/slack.js.map +1 -1
- package/dist/fetchers/teams.d.ts +2 -1
- package/dist/fetchers/teams.d.ts.map +1 -1
- package/dist/fetchers/teams.js +21 -4
- package/dist/fetchers/teams.js.map +1 -1
- package/dist/fetchers/util/time.d.ts +15 -0
- package/dist/fetchers/util/time.d.ts.map +1 -0
- package/dist/fetchers/util/time.js +24 -0
- package/dist/fetchers/util/time.js.map +1 -0
- package/dist/fetchers/zoom.d.ts +6 -1
- package/dist/fetchers/zoom.d.ts.map +1 -1
- package/dist/fetchers/zoom.js +105 -35
- package/dist/fetchers/zoom.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/types/fetcher.d.ts +54 -0
- package/dist/types/fetcher.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ConnectorFetcher, ConnectorFetcherOptions, FetcherItem } from '../types/fetcher.js';
|
|
1
|
+
import type { ConnectorFetcher, ConnectorFetcherOptions, FetcherItem, FetchResult } from '../types/fetcher.js';
|
|
2
2
|
/**
|
|
3
3
|
* Read-only personal Confluence fetcher (API v2): pages the token can read.
|
|
4
4
|
* OAuth (cloudId) or basic-auth (domain+email). Author = the page author.
|
|
@@ -6,5 +6,6 @@ import type { ConnectorFetcher, ConnectorFetcherOptions, FetcherItem } from '../
|
|
|
6
6
|
*/
|
|
7
7
|
export declare class ConfluenceFetcher implements ConnectorFetcher {
|
|
8
8
|
fetch(opts: ConnectorFetcherOptions): Promise<FetcherItem[]>;
|
|
9
|
+
fetchWithReport(opts: ConnectorFetcherOptions): Promise<FetchResult>;
|
|
9
10
|
}
|
|
10
11
|
//# sourceMappingURL=confluence.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"confluence.d.ts","sourceRoot":"","sources":["../../src/fetchers/confluence.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"confluence.d.ts","sourceRoot":"","sources":["../../src/fetchers/confluence.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAyD/G;;;;GAIG;AACH,qBAAa,iBAAkB,YAAW,gBAAgB;IAClD,KAAK,CAAC,IAAI,EAAE,uBAAuB,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAI5D,eAAe,CAAC,IAAI,EAAE,uBAAuB,GAAG,OAAO,CAAC,WAAW,CAAC;CAqE3E"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { fetch } from 'undici';
|
|
2
|
-
import {
|
|
2
|
+
import { providerError } from './errors.js';
|
|
3
|
+
import { toIsoOrUndefined } from './util/time.js';
|
|
3
4
|
// Confluence v2 caps page size at 250 and paginates via _links.next (a cursor).
|
|
4
5
|
const CONFLUENCE_PAGE_MAX = 250;
|
|
5
6
|
function stripHtml(html) {
|
|
@@ -50,6 +51,9 @@ function makeConfluenceUserResolver(base, headers) {
|
|
|
50
51
|
*/
|
|
51
52
|
export class ConfluenceFetcher {
|
|
52
53
|
async fetch(opts) {
|
|
54
|
+
return (await this.fetchWithReport(opts)).items;
|
|
55
|
+
}
|
|
56
|
+
async fetchWithReport(opts) {
|
|
53
57
|
const cloudId = opts.cloudId;
|
|
54
58
|
const siteBase = opts.siteBase;
|
|
55
59
|
const email = opts.email;
|
|
@@ -70,6 +74,7 @@ export class ConfluenceFetcher {
|
|
|
70
74
|
: `https://${domain}`;
|
|
71
75
|
const resolveUser = makeConfluenceUserResolver(base, headers);
|
|
72
76
|
const items = [];
|
|
77
|
+
let scanned = 0;
|
|
73
78
|
let cursor;
|
|
74
79
|
let linkBase;
|
|
75
80
|
while (items.length < limit) {
|
|
@@ -78,29 +83,29 @@ export class ConfluenceFetcher {
|
|
|
78
83
|
(cursor ? `&cursor=${encodeURIComponent(cursor)}` : '');
|
|
79
84
|
const res = await fetch(url, { headers });
|
|
80
85
|
if (!res.ok) {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
"Re-auth won't help - check the Atlassian app's Confluence API permissions (or skip Confluence).");
|
|
86
|
-
}
|
|
87
|
-
throw new Error(`Confluence API failed (${res.status}). ${isOAuth ? 'Check your OAuth token.' : 'Check your email, token, and domain.'}`);
|
|
86
|
+
throw await providerError('Confluence', res, {
|
|
87
|
+
forbidden: 'The token lacks Confluence scopes or this site has no Confluence. ' +
|
|
88
|
+
"Re-auth won't help - check the Atlassian app's Confluence API permissions (or skip Confluence).",
|
|
89
|
+
});
|
|
88
90
|
}
|
|
89
91
|
const data = (await res.json());
|
|
90
92
|
linkBase = linkBase ?? data._links?.base ?? `${humanBase}/wiki`;
|
|
91
93
|
for (const page of data.results ?? []) {
|
|
92
94
|
if (items.length >= limit)
|
|
93
95
|
break;
|
|
96
|
+
scanned += 1;
|
|
94
97
|
const bodyHtml = page.body?.storage?.value ?? '';
|
|
95
98
|
const bodyText = stripHtml(bodyHtml).slice(0, 2000);
|
|
96
99
|
const webui = page._links?.webui ?? '';
|
|
97
100
|
const pageUrl = webui.startsWith('http') ? webui : `${linkBase}${webui}`;
|
|
98
101
|
const author = await resolveUser(page.authorId);
|
|
102
|
+
const createdAt = toIsoOrUndefined(page.version?.createdAt);
|
|
99
103
|
items.push({
|
|
100
104
|
source_url: pageUrl,
|
|
101
105
|
platform: 'confluence',
|
|
102
106
|
raw_text: [page.title, bodyText].filter(Boolean).join('\n\n'),
|
|
103
107
|
title: page.title,
|
|
108
|
+
...(createdAt ? { created_at: createdAt } : {}),
|
|
104
109
|
...(author ? { author } : {}),
|
|
105
110
|
});
|
|
106
111
|
}
|
|
@@ -108,7 +113,7 @@ export class ConfluenceFetcher {
|
|
|
108
113
|
if (!cursor)
|
|
109
114
|
break;
|
|
110
115
|
}
|
|
111
|
-
return items;
|
|
116
|
+
return { items, report: { platform: 'confluence', scanned, requested: limit, skips: [] } };
|
|
112
117
|
}
|
|
113
118
|
}
|
|
114
119
|
//# sourceMappingURL=confluence.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"confluence.js","sourceRoot":"","sources":["../../src/fetchers/confluence.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AAE/B,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"confluence.js","sourceRoot":"","sources":["../../src/fetchers/confluence.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,11 +1,49 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Thrown by a fetcher when the provider
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
2
|
+
* Thrown by a fetcher when the provider answered 401: the credential itself was refused,
|
|
3
|
+
* so re-authenticating (or pasting a fresh token) would help. Callers (the CLI) catch this
|
|
4
|
+
* by type to offer a reconnect and to forget a saved token that is dead, vs. a generic
|
|
5
|
+
* Error (403 / lacking scopes / a rejected request) where a new token won't help.
|
|
6
|
+
*
|
|
7
|
+
* `detail` is the provider's own words, read from the response body, so the message
|
|
8
|
+
* says WHY rather than guessing.
|
|
6
9
|
*/
|
|
7
10
|
export declare class FetcherAuthError extends Error {
|
|
8
11
|
readonly connector: string;
|
|
9
|
-
constructor(connector: string);
|
|
12
|
+
constructor(connector: string, detail?: string);
|
|
10
13
|
}
|
|
14
|
+
/** The subset of a fetch Response a refused request needs. Both readers optional: some
|
|
15
|
+
* test doubles offer only `json()`. */
|
|
16
|
+
export interface RefusedResponse {
|
|
17
|
+
status: number;
|
|
18
|
+
text?(): Promise<string>;
|
|
19
|
+
json?(): Promise<unknown>;
|
|
20
|
+
}
|
|
21
|
+
/** The body as text, reading `text()` first and `json()` when text is absent or empty. A
|
|
22
|
+
* real Response can be read once, so the json fallback after an empty text() simply
|
|
23
|
+
* fails and yields '' there; it exists for test doubles that carry the payload in json(). */
|
|
24
|
+
export declare function refusedBody(res: RefusedResponse): Promise<string>;
|
|
25
|
+
/**
|
|
26
|
+
* The provider's own words for a refused request, or '' when it gave none.
|
|
27
|
+
*
|
|
28
|
+
* Reads the body once, pulls the message out of the envelope the provider uses, and
|
|
29
|
+
* falls back to the raw body. Capped at 200 characters so an HTML error page or a stack
|
|
30
|
+
* trace does not become the error message. Never the string "null": an empty body is
|
|
31
|
+
* silence, not a word.
|
|
32
|
+
*/
|
|
33
|
+
export declare function providerErrorText(res: RefusedResponse): Promise<string>;
|
|
34
|
+
/**
|
|
35
|
+
* The error a fetcher throws for a non-OK provider response. One rule for every fetcher:
|
|
36
|
+
*
|
|
37
|
+
* 401 -> FetcherAuthError with the provider's words (the token was refused)
|
|
38
|
+
* 403 -> Error with the provider's words, then the connector's own scope hint
|
|
39
|
+
* anything else -> Error with the provider's words and nothing else
|
|
40
|
+
*
|
|
41
|
+
* The token hint lives ONLY on 401. Until 2026-09-03 four fetchers said "check your token"
|
|
42
|
+
* for any non-OK status, so a Linear 400 (a request Linear rejected: over its complexity
|
|
43
|
+
* limit) sent a user chasing a token that was fine. A 400 is the provider refusing the
|
|
44
|
+
* REQUEST; a new key changes nothing, and saying so is the whole value of this function.
|
|
45
|
+
*/
|
|
46
|
+
export declare function providerError(connector: string, res: RefusedResponse, opts?: {
|
|
47
|
+
forbidden?: string;
|
|
48
|
+
}): Promise<Error>;
|
|
11
49
|
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/fetchers/errors.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/fetchers/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,qBAAa,gBAAiB,SAAQ,KAAK;aAEvB,SAAS,EAAE,MAAM;gBAAjB,SAAS,EAAE,MAAM,EACjC,MAAM,CAAC,EAAE,MAAM;CAQlB;AAED;wCACwC;AACxC,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IACzB,IAAI,CAAC,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;CAC3B;AAsCD;;8FAE8F;AAC9F,wBAAsB,WAAW,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAgBvE;AAED;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAW7E;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,aAAa,CACjC,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,eAAe,EACpB,IAAI,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAO,GAChC,OAAO,CAAC,KAAK,CAAC,CAKhB"}
|
package/dist/fetchers/errors.js
CHANGED
|
@@ -1,15 +1,124 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Thrown by a fetcher when the provider
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
2
|
+
* Thrown by a fetcher when the provider answered 401: the credential itself was refused,
|
|
3
|
+
* so re-authenticating (or pasting a fresh token) would help. Callers (the CLI) catch this
|
|
4
|
+
* by type to offer a reconnect and to forget a saved token that is dead, vs. a generic
|
|
5
|
+
* Error (403 / lacking scopes / a rejected request) where a new token won't help.
|
|
6
|
+
*
|
|
7
|
+
* `detail` is the provider's own words, read from the response body, so the message
|
|
8
|
+
* says WHY rather than guessing.
|
|
6
9
|
*/
|
|
7
10
|
export class FetcherAuthError extends Error {
|
|
8
11
|
connector;
|
|
9
|
-
constructor(connector) {
|
|
10
|
-
super(`${connector} authentication
|
|
12
|
+
constructor(connector, detail) {
|
|
13
|
+
super(`${connector} authentication failed (401)${detail ? `: ${sentence(detail)}` : '.'} ` +
|
|
14
|
+
'Check your token: it may be invalid, expired or revoked.');
|
|
11
15
|
this.connector = connector;
|
|
12
16
|
this.name = 'FetcherAuthError';
|
|
13
17
|
}
|
|
14
18
|
}
|
|
19
|
+
const MAX_DETAIL = 200;
|
|
20
|
+
function sentence(s) {
|
|
21
|
+
return s.endsWith('.') ? s : `${s}.`;
|
|
22
|
+
}
|
|
23
|
+
/** The message inside whichever envelope the provider uses, or '' when there is none. */
|
|
24
|
+
function wordsOf(v) {
|
|
25
|
+
if (typeof v === 'string')
|
|
26
|
+
return v;
|
|
27
|
+
if (!v || typeof v !== 'object')
|
|
28
|
+
return '';
|
|
29
|
+
const o = v;
|
|
30
|
+
// GraphQL (Linear) and REST APIs that list several problems.
|
|
31
|
+
if (Array.isArray(o.errors)) {
|
|
32
|
+
const msgs = o.errors
|
|
33
|
+
.map((e) => (e && typeof e === 'object' ? e.message : e))
|
|
34
|
+
.filter((m) => typeof m === 'string' && m.length > 0);
|
|
35
|
+
if (msgs.length)
|
|
36
|
+
return msgs.join('; ');
|
|
37
|
+
}
|
|
38
|
+
// Atlassian.
|
|
39
|
+
if (Array.isArray(o.errorMessages)) {
|
|
40
|
+
const msgs = o.errorMessages.filter((m) => typeof m === 'string' && m.length > 0);
|
|
41
|
+
if (msgs.length)
|
|
42
|
+
return msgs.join('; ');
|
|
43
|
+
}
|
|
44
|
+
// GitHub, GitLab, Notion, Zoom.
|
|
45
|
+
if (typeof o.message === 'string' && o.message)
|
|
46
|
+
return o.message;
|
|
47
|
+
// Microsoft Graph: { error: { code, message } }.
|
|
48
|
+
if (o.error && typeof o.error === 'object') {
|
|
49
|
+
const m = o.error.message;
|
|
50
|
+
if (typeof m === 'string' && m)
|
|
51
|
+
return m;
|
|
52
|
+
}
|
|
53
|
+
// OAuth-style { error: 'invalid_token', error_description }.
|
|
54
|
+
if (typeof o.error_description === 'string' && o.error_description)
|
|
55
|
+
return o.error_description;
|
|
56
|
+
if (typeof o.error === 'string' && o.error)
|
|
57
|
+
return o.error;
|
|
58
|
+
return '';
|
|
59
|
+
}
|
|
60
|
+
/** The body as text, reading `text()` first and `json()` when text is absent or empty. A
|
|
61
|
+
* real Response can be read once, so the json fallback after an empty text() simply
|
|
62
|
+
* fails and yields '' there; it exists for test doubles that carry the payload in json(). */
|
|
63
|
+
export async function refusedBody(res) {
|
|
64
|
+
let raw = '';
|
|
65
|
+
try {
|
|
66
|
+
if (typeof res.text === 'function')
|
|
67
|
+
raw = (await res.text()) ?? '';
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
raw = '';
|
|
71
|
+
}
|
|
72
|
+
if (!raw.trim() && typeof res.json === 'function') {
|
|
73
|
+
try {
|
|
74
|
+
const j = await res.json();
|
|
75
|
+
raw = j == null ? '' : typeof j === 'string' ? j : JSON.stringify(j);
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
raw = '';
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return raw;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* The provider's own words for a refused request, or '' when it gave none.
|
|
85
|
+
*
|
|
86
|
+
* Reads the body once, pulls the message out of the envelope the provider uses, and
|
|
87
|
+
* falls back to the raw body. Capped at 200 characters so an HTML error page or a stack
|
|
88
|
+
* trace does not become the error message. Never the string "null": an empty body is
|
|
89
|
+
* silence, not a word.
|
|
90
|
+
*/
|
|
91
|
+
export async function providerErrorText(res) {
|
|
92
|
+
let raw = await refusedBody(res);
|
|
93
|
+
raw = (raw ?? '').trim();
|
|
94
|
+
if (!raw || raw === 'null')
|
|
95
|
+
return '';
|
|
96
|
+
let parsed;
|
|
97
|
+
try {
|
|
98
|
+
parsed = JSON.parse(raw);
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
return raw.slice(0, MAX_DETAIL);
|
|
102
|
+
}
|
|
103
|
+
return (wordsOf(parsed) || raw).slice(0, MAX_DETAIL);
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* The error a fetcher throws for a non-OK provider response. One rule for every fetcher:
|
|
107
|
+
*
|
|
108
|
+
* 401 -> FetcherAuthError with the provider's words (the token was refused)
|
|
109
|
+
* 403 -> Error with the provider's words, then the connector's own scope hint
|
|
110
|
+
* anything else -> Error with the provider's words and nothing else
|
|
111
|
+
*
|
|
112
|
+
* The token hint lives ONLY on 401. Until 2026-09-03 four fetchers said "check your token"
|
|
113
|
+
* for any non-OK status, so a Linear 400 (a request Linear rejected: over its complexity
|
|
114
|
+
* limit) sent a user chasing a token that was fine. A 400 is the provider refusing the
|
|
115
|
+
* REQUEST; a new key changes nothing, and saying so is the whole value of this function.
|
|
116
|
+
*/
|
|
117
|
+
export async function providerError(connector, res, opts = {}) {
|
|
118
|
+
const detail = await providerErrorText(res);
|
|
119
|
+
if (res.status === 401)
|
|
120
|
+
return new FetcherAuthError(connector, detail);
|
|
121
|
+
const hint = res.status === 403 && opts.forbidden ? ` ${opts.forbidden}` : '';
|
|
122
|
+
return new Error(`${connector} API failed (${res.status})${detail ? `: ${sentence(detail)}` : '.'}${hint}`);
|
|
123
|
+
}
|
|
15
124
|
//# sourceMappingURL=errors.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/fetchers/errors.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/fetchers/errors.ts"],"names":[],"mappings":"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"}
|
package/dist/fetchers/git.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ConnectorFetcher, ConnectorFetcherOptions, FetcherItem } from '../types/fetcher.js';
|
|
1
|
+
import type { ConnectorFetcher, ConnectorFetcherOptions, FetcherItem, FetchResult } from '../types/fetcher.js';
|
|
2
2
|
import { type GitCommit } from './util/git.js';
|
|
3
3
|
export type { GitCommit } from './util/git.js';
|
|
4
4
|
/**
|
|
@@ -19,5 +19,6 @@ export declare class GitFetcher implements ConnectorFetcher {
|
|
|
19
19
|
private readonly source;
|
|
20
20
|
constructor(source: GitCommitSource);
|
|
21
21
|
fetch(opts: ConnectorFetcherOptions): Promise<FetcherItem[]>;
|
|
22
|
+
fetchWithReport(opts: ConnectorFetcherOptions): Promise<FetchResult>;
|
|
22
23
|
}
|
|
23
24
|
//# sourceMappingURL=git.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../src/fetchers/git.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../src/fetchers/git.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAC/G,OAAO,EAAsC,KAAK,SAAS,EAAE,MAAM,eAAe,CAAC;AAGnF,YAAY,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE/C;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,gBAAgB,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;IAChE,YAAY,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;CACpD;AAED;;;GAGG;AACH,qBAAa,UAAW,YAAW,gBAAgB;IACrC,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,eAAe;IAE9C,KAAK,CAAC,IAAI,EAAE,uBAAuB,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAI5D,eAAe,CAAC,IAAI,EAAE,uBAAuB,GAAG,OAAO,CAAC,WAAW,CAAC;CAkB3E"}
|
package/dist/fetchers/git.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { buildCommitUrl, formatCommitAsText } from './util/git.js';
|
|
2
|
+
import { toIsoOrUndefined } from './util/time.js';
|
|
2
3
|
/**
|
|
3
4
|
* Read-only local-git fetcher: maps decision-relevant commits to FetcherItems.
|
|
4
5
|
* Author = the commit author ("who to talk to"). `token` is unused (local).
|
|
@@ -9,19 +10,25 @@ export class GitFetcher {
|
|
|
9
10
|
this.source = source;
|
|
10
11
|
}
|
|
11
12
|
async fetch(opts) {
|
|
13
|
+
return (await this.fetchWithReport(opts)).items;
|
|
14
|
+
}
|
|
15
|
+
async fetchWithReport(opts) {
|
|
12
16
|
const limit = opts.limit ?? 100;
|
|
13
17
|
const commits = await this.source.getCommitHistory({ limit });
|
|
14
18
|
const remoteUrl = await this.source.getRemoteUrl();
|
|
15
|
-
|
|
19
|
+
const items = commits.map((c) => {
|
|
16
20
|
const url = buildCommitUrl(remoteUrl, c.sha);
|
|
21
|
+
const createdAt = toIsoOrUndefined(c.date);
|
|
17
22
|
return {
|
|
18
23
|
source_url: url,
|
|
19
24
|
platform: 'git',
|
|
20
25
|
raw_text: formatCommitAsText(c, url),
|
|
21
26
|
title: c.subject,
|
|
27
|
+
...(createdAt ? { created_at: createdAt } : {}),
|
|
22
28
|
...(c.author ? { author: { name: c.author } } : {}),
|
|
23
29
|
};
|
|
24
30
|
});
|
|
31
|
+
return { items, report: { platform: 'git', scanned: commits.length, requested: limit, skips: [] } };
|
|
25
32
|
}
|
|
26
33
|
}
|
|
27
34
|
//# sourceMappingURL=git.js.map
|
package/dist/fetchers/git.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"git.js","sourceRoot":"","sources":["../../src/fetchers/git.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAkB,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"git.js","sourceRoot":"","sources":["../../src/fetchers/git.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAkB,MAAM,eAAe,CAAC;AACnF,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAalD;;;GAGG;AACH,MAAM,OAAO,UAAU;IACQ;IAA7B,YAA6B,MAAuB;QAAvB,WAAM,GAAN,MAAM,CAAiB;IAAG,CAAC;IAExD,KAAK,CAAC,KAAK,CAAC,IAA6B;QACvC,OAAO,CAAC,MAAM,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC;IAClD,CAAC;IAED,KAAK,CAAC,eAAe,CAAC,IAA6B;QACjD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,GAAG,CAAC;QAChC,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;QAC9D,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE,CAAC;QACnD,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;YAC9B,MAAM,GAAG,GAAG,cAAc,CAAC,SAAS,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC;YAC7C,MAAM,SAAS,GAAG,gBAAgB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YAC3C,OAAO;gBACL,UAAU,EAAE,GAAG;gBACf,QAAQ,EAAE,KAAK;gBACf,QAAQ,EAAE,kBAAkB,CAAC,CAAC,EAAE,GAAG,CAAC;gBACpC,KAAK,EAAE,CAAC,CAAC,OAAO;gBAChB,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC/C,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC9B,CAAC;QAC1B,CAAC,CAAC,CAAC;QACH,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,CAAC;IACtG,CAAC;CACF"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ConnectorFetcher, ConnectorFetcherOptions, FetcherItem } from '../types/fetcher.js';
|
|
1
|
+
import type { ConnectorFetcher, ConnectorFetcherOptions, FetcherItem, FetchResult } from '../types/fetcher.js';
|
|
2
2
|
/**
|
|
3
3
|
* Read-only personal GitHub fetcher.
|
|
4
4
|
*
|
|
@@ -18,5 +18,6 @@ import type { ConnectorFetcher, ConnectorFetcherOptions, FetcherItem } from '../
|
|
|
18
18
|
*/
|
|
19
19
|
export declare class GitHubFetcher implements ConnectorFetcher {
|
|
20
20
|
fetch(opts: ConnectorFetcherOptions): Promise<FetcherItem[]>;
|
|
21
|
+
fetchWithReport(opts: ConnectorFetcherOptions): Promise<FetchResult>;
|
|
21
22
|
}
|
|
22
23
|
//# sourceMappingURL=github.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"github.d.ts","sourceRoot":"","sources":["../../src/fetchers/github.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"github.d.ts","sourceRoot":"","sources":["../../src/fetchers/github.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AA2L/G;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,aAAc,YAAW,gBAAgB;IAC9C,KAAK,CAAC,IAAI,EAAE,uBAAuB,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAI5D,eAAe,CAAC,IAAI,EAAE,uBAAuB,GAAG,OAAO,CAAC,WAAW,CAAC;CAkC3E"}
|
package/dist/fetchers/github.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { fetch } from 'undici';
|
|
2
|
+
import { toIsoOrUndefined } from './util/time.js';
|
|
3
|
+
import { providerError } from './errors.js';
|
|
2
4
|
// GitHub's Search API returns at most 100 results/page and 1000 total (10 pages).
|
|
3
5
|
const GH_PER_PAGE_MAX = 100;
|
|
4
6
|
const GH_SEARCH_MAX_PAGES = 10;
|
|
@@ -112,11 +114,13 @@ async function buildPrItem(pr, headers) {
|
|
|
112
114
|
rawText += await fetchSection(`https://api.github.com/repos/${repo}/pulls/${pr.number}/reviews?per_page=20`, headers, 'Code Reviews', true);
|
|
113
115
|
rawText += await fetchSection(`https://api.github.com/repos/${repo}/pulls/${pr.number}/comments?per_page=20`, headers, 'Review Comments', false);
|
|
114
116
|
}
|
|
117
|
+
const createdAt = toIsoOrUndefined(pr.created_at);
|
|
115
118
|
return {
|
|
116
119
|
source_url: pr.html_url,
|
|
117
120
|
platform: 'github',
|
|
118
121
|
raw_text: rawText,
|
|
119
122
|
title: pr.title,
|
|
123
|
+
...(createdAt ? { created_at: createdAt } : {}),
|
|
120
124
|
...(pr.user ? { author: { name: pr.user.login, handle: pr.user.login, url: pr.user.html_url } } : {}),
|
|
121
125
|
};
|
|
122
126
|
}
|
|
@@ -126,11 +130,13 @@ async function buildIssueItem(issue, headers) {
|
|
|
126
130
|
if (repo && issue.number != null) {
|
|
127
131
|
rawText += await fetchSection(`https://api.github.com/repos/${repo}/issues/${issue.number}/comments?per_page=20`, headers, 'Comments', false);
|
|
128
132
|
}
|
|
133
|
+
const createdAt = toIsoOrUndefined(issue.created_at);
|
|
129
134
|
return {
|
|
130
135
|
source_url: issue.html_url,
|
|
131
136
|
platform: 'github',
|
|
132
137
|
raw_text: rawText,
|
|
133
138
|
title: issue.title,
|
|
139
|
+
...(createdAt ? { created_at: createdAt } : {}),
|
|
134
140
|
...(issue.user ? { author: { name: issue.user.login, handle: issue.user.login, url: issue.user.html_url } } : {}),
|
|
135
141
|
};
|
|
136
142
|
}
|
|
@@ -153,6 +159,9 @@ async function buildIssueItem(issue, headers) {
|
|
|
153
159
|
*/
|
|
154
160
|
export class GitHubFetcher {
|
|
155
161
|
async fetch(opts) {
|
|
162
|
+
return (await this.fetchWithReport(opts)).items;
|
|
163
|
+
}
|
|
164
|
+
async fetchWithReport(opts) {
|
|
156
165
|
const headers = {
|
|
157
166
|
Authorization: `Bearer ${opts.token}`,
|
|
158
167
|
Accept: 'application/vnd.github+json',
|
|
@@ -160,7 +169,7 @@ export class GitHubFetcher {
|
|
|
160
169
|
};
|
|
161
170
|
const userRes = await fetch('https://api.github.com/user', { headers });
|
|
162
171
|
if (!userRes.ok) {
|
|
163
|
-
throw
|
|
172
|
+
throw await providerError('GitHub', userRes, { forbidden: 'Check the token has the repo scope, or read access to the repositories.' });
|
|
164
173
|
}
|
|
165
174
|
const user = (await userRes.json());
|
|
166
175
|
const limit = opts.limit ?? 100;
|
|
@@ -176,7 +185,8 @@ export class GitHubFetcher {
|
|
|
176
185
|
for (const pr of [...involvesPrs, ...reviewedPrs])
|
|
177
186
|
prByUrl.set(pr.html_url, pr);
|
|
178
187
|
const rows = interleave([...prByUrl.values()], issues, limit);
|
|
179
|
-
|
|
188
|
+
const items = await mapWithConcurrency(rows, PARALLEL_DISCUSSION_FETCHES, (r) => r.kind === 'pr' ? buildPrItem(r.row, headers) : buildIssueItem(r.row, headers));
|
|
189
|
+
return { items, report: { platform: 'github', scanned: rows.length, requested: limit, skips: [] } };
|
|
180
190
|
}
|
|
181
191
|
}
|
|
182
192
|
//# sourceMappingURL=github.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"github.js","sourceRoot":"","sources":["../../src/fetchers/github.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"github.js","sourceRoot":"","sources":["../../src/fetchers/github.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import type { ConnectorFetcher, ConnectorFetcherOptions, FetcherItem } from '../types/fetcher.js';
|
|
1
|
+
import type { ConnectorFetcher, ConnectorFetcherOptions, FetcherItem, FetchResult } from '../types/fetcher.js';
|
|
2
2
|
/**
|
|
3
|
-
* Read-only personal GitLab fetcher: the caller's merged merge requests
|
|
3
|
+
* Read-only personal GitLab fetcher: the caller's merged merge requests, paged
|
|
4
|
+
* by page number up to `limit` (a page shorter than requested is the last).
|
|
4
5
|
* `domain` (default gitlab.com) rides on the options index signature.
|
|
5
6
|
*/
|
|
6
7
|
export declare class GitLabFetcher implements ConnectorFetcher {
|
|
7
8
|
fetch(opts: ConnectorFetcherOptions): Promise<FetcherItem[]>;
|
|
9
|
+
fetchWithReport(opts: ConnectorFetcherOptions): Promise<FetchResult>;
|
|
8
10
|
}
|
|
9
11
|
//# sourceMappingURL=gitlab.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gitlab.d.ts","sourceRoot":"","sources":["../../src/fetchers/gitlab.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"gitlab.d.ts","sourceRoot":"","sources":["../../src/fetchers/gitlab.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,WAAW,EAAE,WAAW,EAAa,MAAM,qBAAqB,CAAC;AAgB1H;;;;GAIG;AACH,qBAAa,aAAc,YAAW,gBAAgB;IAC9C,KAAK,CAAC,IAAI,EAAE,uBAAuB,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAI5D,eAAe,CAAC,IAAI,EAAE,uBAAuB,GAAG,OAAO,CAAC,WAAW,CAAC;CAkD3E"}
|
package/dist/fetchers/gitlab.js
CHANGED
|
@@ -1,33 +1,63 @@
|
|
|
1
1
|
import { fetch } from 'undici';
|
|
2
|
+
import { toIsoOrUndefined } from './util/time.js';
|
|
3
|
+
import { providerError } from './errors.js';
|
|
4
|
+
// GitLab's own per-page maximum. Before ALI-828 the read was one page of at
|
|
5
|
+
// most 50, a cap nobody had chosen, whatever the caller asked for.
|
|
6
|
+
const GITLAB_PAGE_MAX = 100;
|
|
2
7
|
/**
|
|
3
|
-
* Read-only personal GitLab fetcher: the caller's merged merge requests
|
|
8
|
+
* Read-only personal GitLab fetcher: the caller's merged merge requests, paged
|
|
9
|
+
* by page number up to `limit` (a page shorter than requested is the last).
|
|
4
10
|
* `domain` (default gitlab.com) rides on the options index signature.
|
|
5
11
|
*/
|
|
6
12
|
export class GitLabFetcher {
|
|
7
13
|
async fetch(opts) {
|
|
14
|
+
return (await this.fetchWithReport(opts)).items;
|
|
15
|
+
}
|
|
16
|
+
async fetchWithReport(opts) {
|
|
8
17
|
const domain = opts.domain ?? 'gitlab.com';
|
|
9
18
|
const base = `https://${domain}/api/v4`;
|
|
10
19
|
const headers = { Authorization: `Bearer ${opts.token}` };
|
|
11
20
|
const userRes = await fetch(`${base}/user`, { headers });
|
|
12
21
|
if (!userRes.ok) {
|
|
13
|
-
throw
|
|
22
|
+
throw await providerError('GitLab', userRes, { forbidden: 'Check the token has the read_api scope.' });
|
|
14
23
|
}
|
|
15
24
|
const user = (await userRes.json());
|
|
16
25
|
const limit = opts.limit ?? 100;
|
|
17
26
|
const items = [];
|
|
18
|
-
|
|
19
|
-
|
|
27
|
+
let scanned = 0;
|
|
28
|
+
let pagesUnreadable = 0;
|
|
29
|
+
// Constant for the whole run: `page` is an offset in units of per_page, so
|
|
30
|
+
// shrinking per_page on a later page moves the window backwards and re-reads
|
|
31
|
+
// rows already returned. The limit is enforced by stopping, not by the page.
|
|
32
|
+
const perPage = Math.min(limit, GITLAB_PAGE_MAX);
|
|
33
|
+
for (let page = 1; items.length < limit; page++) {
|
|
34
|
+
const mrRes = await fetch(`${base}/merge_requests?author_id=${user.id}&state=merged&per_page=${perPage}&page=${page}&order_by=updated_at`, { headers });
|
|
35
|
+
if (!mrRes.ok) {
|
|
36
|
+
// Before ALI-828 this returned nothing and said nothing.
|
|
37
|
+
pagesUnreadable += 1;
|
|
38
|
+
break;
|
|
39
|
+
}
|
|
20
40
|
const mrs = (await mrRes.json());
|
|
41
|
+
scanned += mrs.length;
|
|
21
42
|
for (const mr of mrs) {
|
|
43
|
+
if (items.length >= limit)
|
|
44
|
+
break;
|
|
45
|
+
const createdAt = toIsoOrUndefined(mr.created_at);
|
|
22
46
|
items.push({
|
|
23
47
|
source_url: mr.web_url,
|
|
24
48
|
platform: 'gitlab',
|
|
25
49
|
raw_text: `${mr.title}\n\n${mr.description ?? ''}\n\nStatus: ${mr.state}`.trim(),
|
|
26
50
|
title: mr.title,
|
|
51
|
+
...(createdAt ? { created_at: createdAt } : {}),
|
|
27
52
|
});
|
|
28
53
|
}
|
|
54
|
+
if (mrs.length < perPage)
|
|
55
|
+
break; // last page
|
|
29
56
|
}
|
|
30
|
-
|
|
57
|
+
const skips = [];
|
|
58
|
+
if (pagesUnreadable > 0)
|
|
59
|
+
skips.push({ kind: 'error', count: pagesUnreadable, detail: 'merge request pages the token could not read' });
|
|
60
|
+
return { items, report: { platform: 'gitlab', scanned, requested: limit, skips } };
|
|
31
61
|
}
|
|
32
62
|
}
|
|
33
63
|
//# sourceMappingURL=gitlab.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gitlab.js","sourceRoot":"","sources":["../../src/fetchers/gitlab.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"gitlab.js","sourceRoot":"","sources":["../../src/fetchers/gitlab.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AAE/B,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAU5C,4EAA4E;AAC5E,mEAAmE;AACnE,MAAM,eAAe,GAAG,GAAG,CAAC;AAE5B;;;;GAIG;AACH,MAAM,OAAO,aAAa;IACxB,KAAK,CAAC,KAAK,CAAC,IAA6B;QACvC,OAAO,CAAC,MAAM,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC;IAClD,CAAC;IAED,KAAK,CAAC,eAAe,CAAC,IAA6B;QACjD,MAAM,MAAM,GAAI,IAAI,CAAC,MAA6B,IAAI,YAAY,CAAC;QACnE,MAAM,IAAI,GAAG,WAAW,MAAM,SAAS,CAAC;QACxC,MAAM,OAAO,GAAG,EAAE,aAAa,EAAE,UAAU,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC;QAE1D,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,OAAO,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;QACzD,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC;YAChB,MAAM,MAAM,aAAa,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,SAAS,EAAE,yCAAyC,EAAE,CAAC,CAAC;QACzG,CAAC;QACD,MAAM,IAAI,GAAG,CAAC,MAAM,OAAO,CAAC,IAAI,EAAE,CAAmB,CAAC;QAEtD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,GAAG,CAAC;QAChC,MAAM,KAAK,GAAkB,EAAE,CAAC;QAChC,IAAI,OAAO,GAAG,CAAC,CAAC;QAChB,IAAI,eAAe,GAAG,CAAC,CAAC;QAExB,2EAA2E;QAC3E,6EAA6E;QAC7E,6EAA6E;QAC7E,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC;QACjD,KAAK,IAAI,IAAI,GAAG,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC;YAChD,MAAM,KAAK,GAAG,MAAM,KAAK,CACvB,GAAG,IAAI,6BAA6B,IAAI,CAAC,EAAE,0BAA0B,OAAO,SAAS,IAAI,sBAAsB,EAC/G,EAAE,OAAO,EAAE,CACZ,CAAC;YACF,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC;gBACd,yDAAyD;gBACzD,eAAe,IAAI,CAAC,CAAC;gBACrB,MAAM;YACR,CAAC;YACD,MAAM,GAAG,GAAG,CAAC,MAAM,KAAK,CAAC,IAAI,EAAE,CAAyB,CAAC;YACzD,OAAO,IAAI,GAAG,CAAC,MAAM,CAAC;YACtB,KAAK,MAAM,EAAE,IAAI,GAAG,EAAE,CAAC;gBACrB,IAAI,KAAK,CAAC,MAAM,IAAI,KAAK;oBAAE,MAAM;gBACjC,MAAM,SAAS,GAAG,gBAAgB,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC;gBAClD,KAAK,CAAC,IAAI,CAAC;oBACT,UAAU,EAAE,EAAE,CAAC,OAAO;oBACtB,QAAQ,EAAE,QAAQ;oBAClB,QAAQ,EAAE,GAAG,EAAE,CAAC,KAAK,OAAO,EAAE,CAAC,WAAW,IAAI,EAAE,eAAe,EAAE,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE;oBAChF,KAAK,EAAE,EAAE,CAAC,KAAK;oBACf,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;iBAChD,CAAC,CAAC;YACL,CAAC;YACD,IAAI,GAAG,CAAC,MAAM,GAAG,OAAO;gBAAE,MAAM,CAAC,YAAY;QAC/C,CAAC;QAED,MAAM,KAAK,GAAgB,EAAE,CAAC;QAC9B,IAAI,eAAe,GAAG,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,EAAE,8CAA8C,EAAE,CAAC,CAAC;QACvI,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC;IACrF,CAAC;CACF"}
|
package/dist/fetchers/index.d.ts
CHANGED
|
@@ -10,7 +10,7 @@ export { LinearFetcher } from './linear.js';
|
|
|
10
10
|
export { NotionFetcher } from './notion.js';
|
|
11
11
|
export { GitFetcher, type GitCommitSource, type GitCommit } from './git.js';
|
|
12
12
|
export { buildCommitUrl, formatCommitAsText } from './util/git.js';
|
|
13
|
-
export { FetcherAuthError } from './errors.js';
|
|
13
|
+
export { FetcherAuthError, providerError, providerErrorText, type RefusedResponse } from './errors.js';
|
|
14
14
|
/**
|
|
15
15
|
* Registry of token-based read-only fetchers, keyed by platform. The CLI and the
|
|
16
16
|
* gateway discover scan both resolve fetchers from here. `git` is not registered
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/fetchers/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAW5D,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,KAAK,SAAS,EAAE,MAAM,UAAU,CAAC;AAC5E,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/fetchers/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAW5D,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,KAAK,SAAS,EAAE,MAAM,UAAU,CAAC;AAC5E,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACnE,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,iBAAiB,EAAE,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AAEvG;;;;GAIG;AACH,eAAO,MAAM,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,gBAAgB,CAU3D,CAAC"}
|