reslop 0.2.7 → 0.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/CHANGELOG.md +17 -1
- package/README.md +16 -14
- package/bin/reslop.js +8 -5
- package/lib/agents/agents.js +504 -0
- package/lib/agents/allow.js +71 -0
- package/lib/agents/allow.json +16 -0
- package/lib/agents/models.js +460 -0
- package/lib/api.js +15 -12
- package/lib/cli.js +43 -68
- package/lib/{files.js → common/files.js} +48 -55
- package/lib/{find.js → common/find.js} +1 -1
- package/lib/common/format.js +101 -0
- package/lib/{utilities.js → common/process.js} +7 -95
- package/lib/common/tasks.json +27 -0
- package/lib/common/utilities.js +112 -0
- package/lib/dashboard/git.js +9 -16
- package/lib/dashboard/model.js +90 -49
- package/lib/dashboard/npm.js +17 -13
- package/lib/dashboard/tree.js +27 -30
- package/lib/{session → dashboard}/watch.js +36 -31
- package/lib/{workspace.js → dashboard/workspace.js} +23 -38
- package/lib/{deps.js → deps/deps.js} +31 -45
- package/lib/{deps-diff.js → deps/diff.js} +35 -25
- package/lib/{manifest.js → deps/manifest.js} +47 -30
- package/lib/diff/align.js +1 -2
- package/lib/diff/diff.js +2 -2
- package/lib/diff/display.js +29 -5
- package/lib/diff/inline.js +10 -14
- package/lib/diff/items.js +6 -4
- package/lib/diff/patch.js +39 -3
- package/lib/diff/unit.js +45 -16
- package/lib/{git-branches.js → git/branches.js} +53 -48
- package/lib/{git-deps.js → git/deps.js} +123 -96
- package/lib/git/git.js +71 -0
- package/lib/git/worktree.js +475 -0
- package/lib/highlight/bash.js +1 -2
- package/lib/highlight/csv.js +1 -2
- package/lib/highlight/dot.js +1 -2
- package/lib/{highlight.js → highlight/highlight.js} +42 -11
- package/lib/highlight/html.js +20 -18
- package/lib/highlight/json.js +1 -2
- package/lib/highlight/log.js +1 -2
- package/lib/highlight/txt.js +1 -2
- package/lib/{session → input}/actions.js +111 -48
- package/lib/{editor.js → input/editor.js} +7 -8
- package/lib/{keys.js → input/keys.js} +15 -43
- package/lib/input/line-edit.js +77 -0
- package/lib/input/menu-pick.js +70 -0
- package/lib/render/agents.js +640 -0
- package/lib/render/branches.js +4 -5
- package/lib/render/commits.js +54 -64
- package/lib/render/{dash-activity.js → dashboard/activity.js} +25 -40
- package/lib/render/{dash-blocks.js → dashboard/blocks.js} +131 -137
- package/lib/render/{dashboard.js → dashboard/dashboard.js} +25 -22
- package/lib/render/diff.js +166 -45
- package/lib/render/field.js +131 -0
- package/lib/render/files.js +9 -14
- package/lib/render/footer.js +383 -0
- package/lib/render/frame.js +123 -25
- package/lib/render/header.js +176 -0
- package/lib/render/log.js +319 -0
- package/lib/render/menu.js +60 -0
- package/lib/render/notes.js +16 -11
- package/lib/render/npm.js +322 -196
- package/lib/render/packages.js +9 -13
- package/lib/render/primitives.js +101 -15
- package/lib/render/render.js +7 -11
- package/lib/render/repos.js +13 -25
- package/lib/render/status.js +370 -0
- package/lib/render/status.json +85 -0
- package/lib/render/{dash-table.js → table.js} +13 -60
- package/lib/render/tiles.js +109 -48
- package/lib/render/unit.js +32 -13
- package/lib/{report-model.js → report/model.js} +4 -6
- package/lib/{report-parse.js → report/parse.js} +9 -14
- package/lib/{report-render.js → report/render.js} +46 -14
- package/lib/{report-run.js → report/run.js} +42 -30
- package/lib/{report-test.js → report/test.js} +56 -55
- package/lib/{report-tools.js → report/tools.js} +24 -33
- package/lib/review/agent-instructions.md +9 -0
- package/lib/review/format.js +426 -0
- package/lib/{review-merge.js → review/merge.js} +9 -8
- package/lib/review/review.js +190 -0
- package/lib/review/store.js +281 -0
- package/lib/review/templates.js +83 -0
- package/lib/runs/commands.js +14 -0
- package/lib/runs/logs.js +299 -0
- package/lib/runs/output.js +174 -0
- package/lib/runs/process.js +113 -0
- package/lib/{runs.js → runs/runs.js} +84 -36
- package/lib/runs/scripts.js +150 -0
- package/lib/session/agents/agents.js +958 -0
- package/lib/session/agents/job.js +320 -0
- package/lib/session/agents/jobs.js +355 -0
- package/lib/session/agents/options.js +153 -0
- package/lib/session/agents/plans.js +83 -0
- package/lib/session/branches.js +33 -39
- package/lib/session/change-actions.js +34 -100
- package/lib/session/commit.js +91 -52
- package/lib/session/compose.js +181 -145
- package/lib/session/dashboard.js +23 -22
- package/lib/session/dispatch.js +85 -21
- package/lib/session/files-pane.js +47 -26
- package/lib/session/find.js +16 -29
- package/lib/session/import.js +82 -0
- package/lib/session/items.js +8 -17
- package/lib/session/lifecycle.js +75 -72
- package/lib/session/load.js +2 -4
- package/lib/session/navigation.js +6 -3
- package/lib/session/npm/history.js +249 -0
- package/lib/session/npm/npm.js +815 -0
- package/lib/session/{packages.js → npm/packages.js} +21 -14
- package/lib/session/ops.js +125 -34
- package/lib/session/pointer.js +202 -10
- package/lib/session/prefs.js +112 -0
- package/lib/session/reads.js +109 -0
- package/lib/session/review.js +28 -10
- package/lib/session/run-panel.js +40 -0
- package/lib/{session.js → session/session.js} +156 -63
- package/lib/session/tasks.js +320 -65
- package/lib/session/templates.js +1 -1
- package/lib/session/terminal.js +94 -12
- package/lib/session/unit.js +35 -30
- package/lib/session/update.js +194 -6
- package/lib/session/view.js +65 -65
- package/lib/session/workspace.js +39 -78
- package/lib/{capabilities.js → source/capabilities.js} +3 -12
- package/lib/{github.js → source/github.js} +102 -32
- package/lib/{gitlab.js → source/gitlab.js} +87 -10
- package/lib/{remote.js → source/remote.js} +144 -40
- package/lib/source/review-threads.graphql +20 -0
- package/lib/source/source.js +74 -0
- package/lib/term/ansi.js +396 -0
- package/lib/{clipboard.js → term/clipboard.js} +3 -6
- package/lib/{select.js → term/select.js} +2 -2
- package/lib/term/themes/dark.json +122 -0
- package/lib/term/themes/light.json +122 -0
- package/lib/term/wide.txt +21 -0
- package/lib/{wrap.js → term/wrap.js} +4 -4
- package/package.json +2 -2
- package/lib/ansi.js +0 -545
- package/lib/detect.js +0 -34
- package/lib/diff/edit.js +0 -33
- package/lib/git-worktree.js +0 -455
- package/lib/git.js +0 -79
- package/lib/npm-commands.js +0 -522
- package/lib/render/chrome.js +0 -806
- package/lib/render/present.js +0 -19
- package/lib/render/report.js +0 -43
- package/lib/render/search.js +0 -25
- package/lib/review.js +0 -745
- package/lib/session/accessors.js +0 -26
- package/lib/session/edit-click.js +0 -57
- package/lib/session/npm.js +0 -452
- package/lib/session/progress.js +0 -41
- package/lib/source.js +0 -36
- package/lib/update.js +0 -192
- /package/lib/{git-reword-todo.js → git/reword-todo.js} +0 -0
|
@@ -1,15 +1,10 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
const {
|
|
5
|
-
const
|
|
6
|
-
const {
|
|
7
|
-
const
|
|
8
|
-
const { itemPath, isPathInScope } = files;
|
|
9
|
-
const diff = require('./diff/diff.js');
|
|
10
|
-
const { parseDiff, itemsFromFiles, isCtxType } = diff;
|
|
11
|
-
const deps = require('./deps.js');
|
|
12
|
-
const { foldDepItems } = deps;
|
|
3
|
+
const { delay, jsonParse, isHashObject } = require('metautil');
|
|
4
|
+
const { oneLine, trimText } = require('../common/utilities.js');
|
|
5
|
+
const { itemPath, isPathInScope, ISSUE_FILE } = require('../common/files.js');
|
|
6
|
+
const { parseDiff, itemsFromFiles, isCtxType } = require('../diff/diff.js');
|
|
7
|
+
const { foldDepItems } = require('../deps/deps.js');
|
|
13
8
|
|
|
14
9
|
const RETRY_ATTEMPTS = 3;
|
|
15
10
|
const RETRY_DELAY_MS = 200;
|
|
@@ -62,19 +57,18 @@ class RemoteClient {
|
|
|
62
57
|
throw this.error('PARSE', `${this.name} API: invalid ${label}`);
|
|
63
58
|
}
|
|
64
59
|
|
|
65
|
-
httpError(status, body, token) {
|
|
60
|
+
httpError(status, body, token, subject = this.subject) {
|
|
66
61
|
const { name, prefix } = this;
|
|
67
|
-
const text =
|
|
62
|
+
const text = trimText(body);
|
|
68
63
|
const parsed = jsonParse(text);
|
|
69
64
|
const fields = this.errorFields;
|
|
70
65
|
const field = fields.find((key) => typeof parsed?.[key] === 'string');
|
|
71
|
-
const
|
|
72
|
-
|
|
66
|
+
const fromField = isHashObject(parsed) && field;
|
|
67
|
+
const message = fromField ? parsed[field] : oneLine(text);
|
|
73
68
|
if (status === 404) {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
const notFound = `${name} ${this.subject} not found${hint}`;
|
|
69
|
+
let hint = '';
|
|
70
|
+
if (!token) hint = ` (set ${prefix}_TOKEN for private repositories)`;
|
|
71
|
+
const notFound = `${name} ${subject} not found${hint}`;
|
|
78
72
|
return this.error('NOT_FOUND', notFound, { status });
|
|
79
73
|
}
|
|
80
74
|
if (status === 401) {
|
|
@@ -101,18 +95,22 @@ class RemoteClient {
|
|
|
101
95
|
const init = { method: options.method || 'GET', headers };
|
|
102
96
|
if (options.body !== undefined) init.body = options.body;
|
|
103
97
|
if (signal) init.signal = signal;
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
98
|
+
const load = async () => {
|
|
99
|
+
try {
|
|
100
|
+
return await options.fetch(url, init);
|
|
101
|
+
} catch (cause) {
|
|
102
|
+
if (isAbortError(cause, signal)) throw cause;
|
|
103
|
+
const detail = oneLine(cause && cause.message);
|
|
104
|
+
const suffix = detail ? `: ${detail}` : '';
|
|
105
|
+
const message = `${this.name} request failed${suffix}`;
|
|
106
|
+
throw this.error('NETWORK', message, { cause });
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
const response = await load();
|
|
114
110
|
const text = await response.text();
|
|
115
|
-
if (!response.ok)
|
|
111
|
+
if (!response.ok) {
|
|
112
|
+
throw this.httpError(response.status, text, token, options.subject);
|
|
113
|
+
}
|
|
116
114
|
return { body: text, headers: response.headers };
|
|
117
115
|
}
|
|
118
116
|
|
|
@@ -183,7 +181,14 @@ const listUrl = (base) => {
|
|
|
183
181
|
return url.toString();
|
|
184
182
|
};
|
|
185
183
|
|
|
186
|
-
const commentBody = (value) =>
|
|
184
|
+
const commentBody = (value) => trimText(value);
|
|
185
|
+
|
|
186
|
+
const issueText = (title, body) => {
|
|
187
|
+
const head = trimText(title);
|
|
188
|
+
const rest = commentBody(body);
|
|
189
|
+
if (head && rest) return `${head}\n\n${rest}`;
|
|
190
|
+
return head || rest;
|
|
191
|
+
};
|
|
187
192
|
|
|
188
193
|
const sideLineNumber = (type, oldNo, newNo, side) => {
|
|
189
194
|
if (side === 'LEFT') return type === 'add' ? 0 : oldNo;
|
|
@@ -228,6 +233,21 @@ const importedTodo = (file, entry, host) => ({
|
|
|
228
233
|
done: entry.resolved === true,
|
|
229
234
|
});
|
|
230
235
|
|
|
236
|
+
const issueTodoText = (entry, host) => {
|
|
237
|
+
const reviewer = entry.reviewer || 'unknown';
|
|
238
|
+
const body = `@${reviewer} at ${host}: ${commentBody(entry.body)}`;
|
|
239
|
+
const url = trimText(entry.url);
|
|
240
|
+
if (!url) return body;
|
|
241
|
+
return `${body}\nIssue: ${url}`;
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
const issueTodo = (entry, host) => ({
|
|
245
|
+
kind: 'todo',
|
|
246
|
+
file: ISSUE_FILE,
|
|
247
|
+
text: issueTodoText(entry, host),
|
|
248
|
+
done: entry.resolved === true,
|
|
249
|
+
});
|
|
250
|
+
|
|
231
251
|
const importedFeedback = (item, path, entry, host) => {
|
|
232
252
|
const hunk = item.hunk;
|
|
233
253
|
return {
|
|
@@ -281,17 +301,100 @@ const changeFiles = (items) => {
|
|
|
281
301
|
return [...rels];
|
|
282
302
|
};
|
|
283
303
|
|
|
304
|
+
const requestOptions = (options) => ({
|
|
305
|
+
fetch: options.fetch ?? globalThis.fetch,
|
|
306
|
+
token: options.token ?? '',
|
|
307
|
+
retry: options.retry ?? {},
|
|
308
|
+
signal: options.signal,
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
const stateIs = (state, name) => `${state ?? ''}`.toLowerCase() === name;
|
|
312
|
+
|
|
313
|
+
const issueChange = (site, issue) => {
|
|
314
|
+
const number = issue.number || 0;
|
|
315
|
+
const tail = number ? `/${number}` : '';
|
|
316
|
+
return {
|
|
317
|
+
id: `${site.id}${tail}`,
|
|
318
|
+
source: 'issue',
|
|
319
|
+
title: issue.title || '',
|
|
320
|
+
author: issue.author || '',
|
|
321
|
+
base: '',
|
|
322
|
+
head: '',
|
|
323
|
+
url: issue.url || `${site.page}${tail}`,
|
|
324
|
+
repository: site.repository,
|
|
325
|
+
number,
|
|
326
|
+
};
|
|
327
|
+
};
|
|
328
|
+
|
|
329
|
+
const issueTasks = (source, issue, url, comments) => {
|
|
330
|
+
const { host, readComment } = source;
|
|
331
|
+
const tasks = [];
|
|
332
|
+
const body = issueText(issue.title, issue.body);
|
|
333
|
+
if (body) {
|
|
334
|
+
const resolved = stateIs(issue.state, 'closed');
|
|
335
|
+
const entry = { reviewer: issue.author, body, resolved, url };
|
|
336
|
+
tasks.push(issueTodo(entry, host));
|
|
337
|
+
}
|
|
338
|
+
for (const comment of comments) {
|
|
339
|
+
const entry = readComment(comment);
|
|
340
|
+
if (!entry || !commentBody(entry.body)) continue;
|
|
341
|
+
tasks.push(issueTodo(entry, host));
|
|
342
|
+
}
|
|
343
|
+
return tasks;
|
|
344
|
+
};
|
|
345
|
+
|
|
346
|
+
const loadIssue = async (ref, options, source) => {
|
|
347
|
+
const { client, site, issuesUrl, readIssue } = source;
|
|
348
|
+
const request = { ...requestOptions(options), subject: 'issue' };
|
|
349
|
+
const readComments = (number) => {
|
|
350
|
+
const url = `${issuesUrl}/${number}/${source.comments}`;
|
|
351
|
+
return client.list(listUrl(url), request);
|
|
352
|
+
};
|
|
353
|
+
const tasks = [];
|
|
354
|
+
let change = issueChange(site, {});
|
|
355
|
+
if (ref.list) {
|
|
356
|
+
const open = listUrl(`${issuesUrl}?state=${source.openState}`);
|
|
357
|
+
for (const data of await client.list(open, request)) {
|
|
358
|
+
if (!source.isOpen(data)) continue;
|
|
359
|
+
const issue = readIssue(data);
|
|
360
|
+
const quiet = issue.comments === 0;
|
|
361
|
+
const comments = quiet ? [] : await readComments(issue.number);
|
|
362
|
+
const { url } = issueChange(site, issue);
|
|
363
|
+
tasks.push(...issueTasks(source, issue, url, comments));
|
|
364
|
+
}
|
|
365
|
+
} else {
|
|
366
|
+
const [page, comments] = await Promise.all([
|
|
367
|
+
client.request(`${issuesUrl}/${ref.number}`, request),
|
|
368
|
+
readComments(ref.number),
|
|
369
|
+
]);
|
|
370
|
+
const data = client.parseJson(page.body, 'issue payload');
|
|
371
|
+
const issue = readIssue(data);
|
|
372
|
+
issue.number ||= ref.number;
|
|
373
|
+
change = issueChange(site, issue);
|
|
374
|
+
tasks.push(...issueTasks(source, issue, change.url, comments));
|
|
375
|
+
}
|
|
376
|
+
return {
|
|
377
|
+
top: options.cwd,
|
|
378
|
+
items: [],
|
|
379
|
+
sourceLabel: ref.list ? site.repository : `#${change.number}`,
|
|
380
|
+
change,
|
|
381
|
+
imported: { feedback: [], tasks },
|
|
382
|
+
};
|
|
383
|
+
};
|
|
384
|
+
|
|
284
385
|
const loadChange = async (ref, options, source) => {
|
|
285
386
|
const { client, url, diffUrl = url, diffAccept } = source;
|
|
286
|
-
const { cwd, paths = [],
|
|
287
|
-
const
|
|
288
|
-
const
|
|
289
|
-
|
|
387
|
+
const { cwd, paths = [], signal } = options;
|
|
388
|
+
const request = requestOptions(options);
|
|
389
|
+
const discussion = Promise.resolve().then(() =>
|
|
390
|
+
source.loadDiscussion(ref, request),
|
|
391
|
+
);
|
|
392
|
+
discussion.catch(() => {});
|
|
393
|
+
const [jsonPage, diffPage] = await Promise.all([
|
|
394
|
+
client.request(url, request),
|
|
395
|
+
client.request(diffUrl, { ...request, accept: diffAccept }),
|
|
396
|
+
]);
|
|
290
397
|
const data = client.parseJson(jsonPage.body, `${client.subject} payload`);
|
|
291
|
-
const diffPage = await client.request(diffUrl, {
|
|
292
|
-
...request,
|
|
293
|
-
accept: diffAccept,
|
|
294
|
-
});
|
|
295
398
|
const files = filterChangeFiles(parseDiff(diffPage.body), paths);
|
|
296
399
|
const items = foldDepItems(itemsFromFiles(files, 'pr'));
|
|
297
400
|
const change = {
|
|
@@ -302,8 +405,7 @@ const loadChange = async (ref, options, source) => {
|
|
|
302
405
|
const sourceLabel = `${source.prefix}${change.number}`;
|
|
303
406
|
let imported = { feedback: [], tasks: [] };
|
|
304
407
|
try {
|
|
305
|
-
|
|
306
|
-
imported = source.discussionToNotes(discussion, items, paths);
|
|
408
|
+
imported = source.discussionToNotes(await discussion, items, paths);
|
|
307
409
|
} catch (error) {
|
|
308
410
|
if (isAbortError(error, signal)) throw error;
|
|
309
411
|
}
|
|
@@ -320,6 +422,8 @@ module.exports = {
|
|
|
320
422
|
importedTodo,
|
|
321
423
|
noteFromLocation,
|
|
322
424
|
splitNotes,
|
|
425
|
+
stateIs,
|
|
323
426
|
filterChangeFiles,
|
|
427
|
+
loadIssue,
|
|
324
428
|
loadChange,
|
|
325
429
|
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
query ($owner: String!, $name: String!, $number: Int!, $after: String) {
|
|
2
|
+
repository(owner: $owner, name: $name) {
|
|
3
|
+
pullRequest(number: $number) {
|
|
4
|
+
reviewThreads(first: 100, after: $after) {
|
|
5
|
+
pageInfo {
|
|
6
|
+
hasNextPage
|
|
7
|
+
endCursor
|
|
8
|
+
}
|
|
9
|
+
nodes {
|
|
10
|
+
isResolved
|
|
11
|
+
comments(first: 100) {
|
|
12
|
+
nodes {
|
|
13
|
+
databaseId
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const github = require('./github.js');
|
|
4
|
+
const gitlab = require('./gitlab.js');
|
|
5
|
+
const { capabilitiesFor, attachCapabilities } = require('./capabilities.js');
|
|
6
|
+
const { parseGithubPrUrl, parseGithubIssueUrl } = github;
|
|
7
|
+
const { parseGithubIssueListUrl } = github;
|
|
8
|
+
const { parseGitlabMrUrl, parseGitlabIssueUrl } = gitlab;
|
|
9
|
+
const { parseGitlabIssueListUrl } = gitlab;
|
|
10
|
+
|
|
11
|
+
const REMOTE_KINDS = {
|
|
12
|
+
pr: {
|
|
13
|
+
option: 'loadPullRequest',
|
|
14
|
+
load: github.loadPullRequest,
|
|
15
|
+
token: github.githubToken,
|
|
16
|
+
target: (selected) => selected.pr,
|
|
17
|
+
},
|
|
18
|
+
mr: {
|
|
19
|
+
option: 'loadMergeRequest',
|
|
20
|
+
load: gitlab.loadMergeRequest,
|
|
21
|
+
token: gitlab.gitlabToken,
|
|
22
|
+
target: (selected) => selected.mr,
|
|
23
|
+
},
|
|
24
|
+
issue: {
|
|
25
|
+
option: 'loadGithubIssue',
|
|
26
|
+
load: github.loadGithubIssue,
|
|
27
|
+
token: github.githubToken,
|
|
28
|
+
target: (selected) => selected.issue,
|
|
29
|
+
},
|
|
30
|
+
'gl-issue': {
|
|
31
|
+
option: 'loadGitlabIssue',
|
|
32
|
+
load: gitlab.loadGitlabIssue,
|
|
33
|
+
token: gitlab.gitlabToken,
|
|
34
|
+
target: (selected) => selected.issue,
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const remoteKind = (selected) => REMOTE_KINDS[selected.kind] ?? null;
|
|
39
|
+
|
|
40
|
+
const selectChangeSource = (paths) => {
|
|
41
|
+
if (!paths.length) return { kind: 'local', paths };
|
|
42
|
+
const first = paths[0];
|
|
43
|
+
const rest = paths.slice(1);
|
|
44
|
+
const pr = parseGithubPrUrl(first);
|
|
45
|
+
if (pr) return { kind: 'pr', pr, paths: rest };
|
|
46
|
+
const githubIssue = parseGithubIssueUrl(first);
|
|
47
|
+
if (githubIssue) return { kind: 'issue', issue: githubIssue, paths: rest };
|
|
48
|
+
const githubIssues = parseGithubIssueListUrl(first);
|
|
49
|
+
if (githubIssues) return { kind: 'issue', issue: githubIssues, paths: rest };
|
|
50
|
+
const mr = parseGitlabMrUrl(first);
|
|
51
|
+
if (mr) return { kind: 'mr', mr, paths: rest };
|
|
52
|
+
const gitlabIssue = parseGitlabIssueUrl(first);
|
|
53
|
+
if (gitlabIssue) return { kind: 'gl-issue', issue: gitlabIssue, paths: rest };
|
|
54
|
+
const gitlabIssues = parseGitlabIssueListUrl(first);
|
|
55
|
+
if (gitlabIssues) {
|
|
56
|
+
return { kind: 'gl-issue', issue: gitlabIssues, paths: rest };
|
|
57
|
+
}
|
|
58
|
+
return { kind: 'local', paths };
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const createLoadedSource = (loaded, kind = 'pr', extra = {}) => {
|
|
62
|
+
const load = async () => {
|
|
63
|
+
const items = loaded.items ?? [];
|
|
64
|
+
return { ...loaded, items: [...items] };
|
|
65
|
+
};
|
|
66
|
+
const impl = { load: extra.load ?? load, resolveRev: () => null };
|
|
67
|
+
return attachCapabilities(impl, capabilitiesFor(kind));
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
module.exports = {
|
|
71
|
+
remoteKind,
|
|
72
|
+
selectChangeSource,
|
|
73
|
+
createLoadedSource,
|
|
74
|
+
};
|