@smwb/onreel-git-mcp 0.13.0 → 0.14.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/README.md +90 -32
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/tracker/declarative/declarative.const.d.ts +1 -1
- package/dist/tracker/gitverse-ci.lib.d.ts +2 -0
- package/dist/tracker/gitverse-pull.lib.d.ts +2 -0
- package/dist/tracker/gitverse-repo.lib.d.ts +2 -0
- package/dist/tracker/gitverse.const.d.ts +10 -0
- package/dist/tracker/gitverse.lib.d.ts +2 -0
- package/dist/tracker/http.lib.d.ts +21 -0
- package/dist/tracker/index.d.ts +5 -0
- package/dist/tracker/index.js +978 -137
- package/dist/tracker/index.js.map +1 -1
- package/dist/tracker/mapping.const.d.ts +18 -0
- package/dist/tracker/tracker.types.d.ts +2 -0
- package/package.json +3 -2
package/dist/tracker/index.js
CHANGED
|
@@ -231,6 +231,15 @@ var GITHUB_PRIORITY_LABELS = {
|
|
|
231
231
|
"priority: blocker": "blocker"
|
|
232
232
|
};
|
|
233
233
|
var ALL_STATUSES = ["open", "in_progress", "done", "declined"];
|
|
234
|
+
var GITVERSE_ISSUE_STATES = {
|
|
235
|
+
open: "open",
|
|
236
|
+
closed: "done"
|
|
237
|
+
};
|
|
238
|
+
var GITVERSE_ISSUE_STATE_NAMES = {
|
|
239
|
+
open: "open",
|
|
240
|
+
done: "closed"
|
|
241
|
+
};
|
|
242
|
+
var GITVERSE_DONE_COLUMN = /^(?:done|closed|complete|completed|resolved|готово|выполнено|завершено|закрыто|сделано)$/i;
|
|
234
243
|
var GITLAB_MERGE_REQUEST_STATES = {
|
|
235
244
|
opened: "open",
|
|
236
245
|
locked: "open",
|
|
@@ -239,6 +248,10 @@ var GITLAB_MERGE_REQUEST_STATES = {
|
|
|
239
248
|
};
|
|
240
249
|
var GITLAB_DRAFT_PREFIX = "Draft: ";
|
|
241
250
|
var GITLAB_DRAFT_PATTERN = /^\s*(?:\[draft\]|\(draft\)|draft:)\s*/i;
|
|
251
|
+
var GITVERSE_PULL_STATES = {
|
|
252
|
+
open: "open",
|
|
253
|
+
closed: "closed"
|
|
254
|
+
};
|
|
242
255
|
var SOURCECRAFT_PULL_STATUSES = {
|
|
243
256
|
draft: "draft",
|
|
244
257
|
open: "open",
|
|
@@ -324,10 +337,35 @@ var SOURCECRAFT_RUN_EVENTS = {
|
|
|
324
337
|
schedule: "schedule",
|
|
325
338
|
repository_event: "trigger"
|
|
326
339
|
};
|
|
340
|
+
var GITVERSE_CI_STATUSES = {
|
|
341
|
+
queued: "queued",
|
|
342
|
+
pending: "queued",
|
|
343
|
+
waiting: "queued",
|
|
344
|
+
blocked: "waiting",
|
|
345
|
+
running: "running",
|
|
346
|
+
in_progress: "running",
|
|
347
|
+
success: "success",
|
|
348
|
+
failure: "failed",
|
|
349
|
+
failed: "failed",
|
|
350
|
+
timeout: "failed",
|
|
351
|
+
cancelled: "canceled",
|
|
352
|
+
canceled: "canceled",
|
|
353
|
+
skipped: "skipped"
|
|
354
|
+
};
|
|
355
|
+
var GITVERSE_RUN_EVENTS = {
|
|
356
|
+
push: "push",
|
|
357
|
+
pull_request: "pull_request",
|
|
358
|
+
pull_request_target: "pull_request",
|
|
359
|
+
workflow_dispatch: "manual",
|
|
360
|
+
schedule: "schedule",
|
|
361
|
+
repository_dispatch: "trigger",
|
|
362
|
+
workflow_run: "trigger",
|
|
363
|
+
workflow_call: "trigger"
|
|
364
|
+
};
|
|
327
365
|
|
|
328
366
|
// src/tracker/http.lib.ts
|
|
329
367
|
async function requestJson(url, request) {
|
|
330
|
-
const accept = { accept: "application/json" };
|
|
368
|
+
const accept = { accept: request.accept ?? "application/json" };
|
|
331
369
|
const { response, url: final } = await send(url, request, AbortSignal.timeout(TRACKER_TIMEOUT_MS), accept, {
|
|
332
370
|
method: request.method ?? "GET",
|
|
333
371
|
headers: { ...accept, ...request.body === void 0 ? {} : { "content-type": "application/json" }, ...request.headers },
|
|
@@ -536,6 +574,9 @@ function decodeUtf8(bytes) {
|
|
|
536
574
|
function notAnswered(url, error) {
|
|
537
575
|
return new TrackerError("failed", redactSecretText(`\u0422\u0440\u0435\u043A\u0435\u0440 \u043D\u0435 \u043E\u0442\u0432\u0435\u0442\u0438\u043B (${hostOf(url)}): ${error instanceof Error ? error.message : String(error)}`));
|
|
538
576
|
}
|
|
577
|
+
var RATE_LIMIT_REMAINING_HEADERS = ["x-ratelimit-remaining", "gitverse-ratelimit-remaining", "gitverse-ratelimit-user-remaining"];
|
|
578
|
+
var RETRY_AFTER_HEADERS = ["retry-after", "gitverse-ratelimit-retry-after"];
|
|
579
|
+
var RATE_LIMIT_RESET_HEADERS = ["x-ratelimit-reset", "ratelimit-reset", "gitverse-ratelimit-reset"];
|
|
539
580
|
function failureOf(url, response, raw, request) {
|
|
540
581
|
const status = response.status;
|
|
541
582
|
if (status === 404 && request.missing !== void 0) return new TrackerError(request.missing.failure, request.missing.message);
|
|
@@ -543,7 +584,8 @@ function failureOf(url, response, raw, request) {
|
|
|
543
584
|
const detail = redactSecretText(raw.replace(/\s+/g, " ").trim()).slice(0, TRACKER_ERROR_BODY_MAX);
|
|
544
585
|
const answered = `\u0422\u0440\u0435\u043A\u0435\u0440 ${hostOf(url)} \u043E\u0442\u0432\u0435\u0442\u0438\u043B ${String(status)}${detail === "" ? "" : `: ${detail}`}.`;
|
|
545
586
|
if (request.conflictOn?.includes(status) === true) return new TrackerError("conflict", answered);
|
|
546
|
-
const
|
|
587
|
+
const exhausted = RATE_LIMIT_REMAINING_HEADERS.some((name) => response.headers.get(name)?.trim() === "0");
|
|
588
|
+
const secondaryLimit = status === 403 && (exhausted || retryAfterHeaderOf(response.headers, Date.now()) !== void 0);
|
|
547
589
|
if (status === 429 || secondaryLimit) {
|
|
548
590
|
const delay = retryDelayOf(response.headers);
|
|
549
591
|
return new TrackerError("rate_limited", `\u0422\u0440\u0435\u043A\u0435\u0440 ${hostOf(url)} \u043E\u0433\u0440\u0430\u043D\u0438\u0447\u0438\u043B \u0447\u0430\u0441\u0442\u043E\u0442\u0443 \u0437\u0430\u043F\u0440\u043E\u0441\u043E\u0432${delay === void 0 ? "" : `, \u043F\u043E\u0432\u0442\u043E\u0440 \u0447\u0435\u0440\u0435\u0437 ${String(delay)} \u0441`}.`);
|
|
@@ -551,14 +593,21 @@ function failureOf(url, response, raw, request) {
|
|
|
551
593
|
return new TrackerError("failed", answered);
|
|
552
594
|
}
|
|
553
595
|
function retryDelayOf(headers, now = Date.now()) {
|
|
554
|
-
const retryAfter =
|
|
596
|
+
const retryAfter = retryAfterHeaderOf(headers, now);
|
|
555
597
|
if (retryAfter !== void 0) return retryAfter;
|
|
556
|
-
for (const name of
|
|
598
|
+
for (const name of RATE_LIMIT_RESET_HEADERS) {
|
|
557
599
|
const reset = headers.get(name)?.trim();
|
|
558
600
|
if (reset !== void 0 && /^\d+$/.test(reset)) return resetDelay(Number(reset), now);
|
|
559
601
|
}
|
|
560
602
|
return void 0;
|
|
561
603
|
}
|
|
604
|
+
function retryAfterHeaderOf(headers, now) {
|
|
605
|
+
for (const name of RETRY_AFTER_HEADERS) {
|
|
606
|
+
const delay = retryAfterOf(headers.get(name)?.trim(), now);
|
|
607
|
+
if (delay !== void 0) return delay;
|
|
608
|
+
}
|
|
609
|
+
return void 0;
|
|
610
|
+
}
|
|
562
611
|
function retryAfterOf(value, now) {
|
|
563
612
|
if (value === void 0 || value === "") return void 0;
|
|
564
613
|
if (/^\d+$/.test(value)) return Number(value);
|
|
@@ -586,6 +635,31 @@ function baseUrl(value, fallback) {
|
|
|
586
635
|
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") throw new TrackerError("invalid_request", "\u0410\u0434\u0440\u0435\u0441 \u0442\u0440\u0435\u043A\u0435\u0440\u0430 \u0434\u043E\u043B\u0436\u0435\u043D \u0431\u044B\u0442\u044C http \u0438\u043B\u0438 https.");
|
|
587
636
|
return raw;
|
|
588
637
|
}
|
|
638
|
+
function linkNextPage(link2) {
|
|
639
|
+
if (link2 === null || link2 === void 0) return void 0;
|
|
640
|
+
for (const [, target, params] of link2.matchAll(/<([^>]*)>([^<]*)/g)) {
|
|
641
|
+
const rel = /;\s*rel\s*=\s*"?([^";,]*)"?/i.exec(params ?? "")?.[1];
|
|
642
|
+
if (rel === void 0 || !rel.toLowerCase().split(/\s+/).includes("next")) continue;
|
|
643
|
+
let page;
|
|
644
|
+
try {
|
|
645
|
+
page = new URL(target ?? "", "http://link.invalid").searchParams.get("page");
|
|
646
|
+
} catch {
|
|
647
|
+
return void 0;
|
|
648
|
+
}
|
|
649
|
+
return page !== null && /^[1-9]\d{0,8}$/.test(page) ? Number(page) : void 0;
|
|
650
|
+
}
|
|
651
|
+
return void 0;
|
|
652
|
+
}
|
|
653
|
+
function nextPageCursor(input) {
|
|
654
|
+
const { headers, page, perPage, count } = input;
|
|
655
|
+
const linked = linkNextPage(headers.get("link"));
|
|
656
|
+
if (linked !== void 0) return linked > page ? { nextCursor: String(linked) } : {};
|
|
657
|
+
const rawTotal = headers.get("x-total-count")?.trim() ?? input.total;
|
|
658
|
+
const total = typeof rawTotal === "string" && /^\d{1,15}$/.test(rawTotal) ? Number(rawTotal) : typeof rawTotal === "number" && Number.isSafeInteger(rawTotal) ? rawTotal : void 0;
|
|
659
|
+
if (total !== void 0) return page * perPage < total ? { nextCursor: String(page + 1) } : {};
|
|
660
|
+
if (headers.has("link")) return {};
|
|
661
|
+
return count >= perPage ? { nextCursor: String(page + 1) } : {};
|
|
662
|
+
}
|
|
589
663
|
|
|
590
664
|
// src/tracker/ci.schema.ts
|
|
591
665
|
import { z } from "zod";
|
|
@@ -1590,6 +1664,258 @@ function concat(head, tail) {
|
|
|
1590
1664
|
return merged;
|
|
1591
1665
|
}
|
|
1592
1666
|
|
|
1667
|
+
// src/tracker/gitverse.const.ts
|
|
1668
|
+
var GITVERSE_API = "https://api.gitverse.ru";
|
|
1669
|
+
var GITVERSE_WEB = "https://gitverse.ru";
|
|
1670
|
+
var GITVERSE_ACCEPT = "application/vnd.gitverse.object+json;version=1";
|
|
1671
|
+
var GITVERSE_REMOTE_HOSTS = ["gitverse.ru"];
|
|
1672
|
+
var GITVERSE_TOKEN_ENV = "GITVERSE_TOKEN";
|
|
1673
|
+
|
|
1674
|
+
// src/tracker/gitverse-ci.lib.ts
|
|
1675
|
+
var TARGET4 = /^[\w.-]+\/[\w.-]+$/;
|
|
1676
|
+
var ID3 = /^[1-9]\d{0,19}$/;
|
|
1677
|
+
var SHA2 = /^[0-9a-f]{7,64}$/;
|
|
1678
|
+
var PAGE_SIZE_MAX = 30;
|
|
1679
|
+
var RUN_FILTERS4 = ciRunFilterSchema.options;
|
|
1680
|
+
var JOB_FILTERS4 = ciJobFilterSchema.options;
|
|
1681
|
+
var RUNS_SUBJECT2 = "\u041F\u0440\u043E\u0433\u043E\u043D\u044B CI GitVerse";
|
|
1682
|
+
var JOBS_SUBJECT2 = "\u0417\u0430\u0434\u0430\u043D\u0438\u044F CI GitVerse";
|
|
1683
|
+
var WORKFLOWS_SUBJECT2 = "\u0421\u043F\u0438\u0441\u043E\u043A workflow GitVerse";
|
|
1684
|
+
var TRIGGER_SUBJECT2 = "\u0417\u0430\u043F\u0443\u0441\u043A CI GitVerse";
|
|
1685
|
+
var CAPABILITIES4 = {
|
|
1686
|
+
workflows: true,
|
|
1687
|
+
runs: { filters: ["status", "ref", "sha", "event", "workflow", "actor", "pullRequest"], clientSide: ["status", "ref", "sha", "event", "pullRequest"], sorts: [] },
|
|
1688
|
+
jobs: { filters: ["status"], clientSide: ["status"], sorts: [] },
|
|
1689
|
+
log: { live: false, cursor: true },
|
|
1690
|
+
trigger: { supported: true, workflows: "one", inputs: true, tags: true },
|
|
1691
|
+
rerun: { all: true, failedOnly: false, job: true, debug: false },
|
|
1692
|
+
cancel: { run: true, job: false }
|
|
1693
|
+
};
|
|
1694
|
+
function gitverseCi() {
|
|
1695
|
+
return { capabilities: CAPABILITIES4, create: (context) => createGitverseCiAdapter(context) };
|
|
1696
|
+
}
|
|
1697
|
+
function createGitverseCiAdapter({ connection, fetch }) {
|
|
1698
|
+
const target = requireTarget(connection.target, "owner/repo \u0440\u0435\u043F\u043E\u0437\u0438\u0442\u043E\u0440\u0438\u044F GitVerse");
|
|
1699
|
+
if (!TARGET4.test(target)) throw new TrackerError("invalid_request", "target GitVerse \u2014 owner/repo.");
|
|
1700
|
+
const api = baseUrl(connection.url, GITVERSE_API);
|
|
1701
|
+
const origin = new URL(api).origin;
|
|
1702
|
+
const repo = `${api}/repos/${target}`;
|
|
1703
|
+
const actions = `${repo}/actions`;
|
|
1704
|
+
const headers = connection.token === void 0 || connection.token === "" ? {} : { authorization: `Bearer ${connection.token}` };
|
|
1705
|
+
const call = (extra = {}) => ({ fetch, origin, headers, accept: GITVERSE_ACCEPT, ...extra });
|
|
1706
|
+
const runKey = (key) => {
|
|
1707
|
+
if (!ID3.test(key)) throw new TrackerError("not_found", `\u0412 GitVerse \u043D\u0435\u0442 \u043F\u0440\u043E\u0433\u043E\u043D\u0430 ${key}.`);
|
|
1708
|
+
return key;
|
|
1709
|
+
};
|
|
1710
|
+
const jobKey = (key) => {
|
|
1711
|
+
if (!ID3.test(key)) throw new TrackerError("not_found", `\u0412 GitVerse \u043D\u0435\u0442 \u0437\u0430\u0434\u0430\u043D\u0438\u044F ${key}.`);
|
|
1712
|
+
return key;
|
|
1713
|
+
};
|
|
1714
|
+
const missingRun = (key) => ({ failure: "not_found", message: `\u0412 GitVerse \u043D\u0435\u0442 \u043F\u0440\u043E\u0433\u043E\u043D\u0430 ${key}.` });
|
|
1715
|
+
const missingJob = (key) => ({ failure: "not_found", message: `\u0412 GitVerse \u043D\u0435\u0442 \u0437\u0430\u0434\u0430\u043D\u0438\u044F ${key}.` });
|
|
1716
|
+
const getRun = async (key) => runOf4((await requestJson(`${actions}/runs/${runKey(key)}`, call({ missing: missingRun(key) }))).body);
|
|
1717
|
+
const rawJob = async (key) => {
|
|
1718
|
+
const id = jobKey(key);
|
|
1719
|
+
const { body } = await requestJson(`${actions}/jobs/${id}`, call({ missing: missingJob(id) }));
|
|
1720
|
+
return isRecord(body) ? body : {};
|
|
1721
|
+
};
|
|
1722
|
+
const headShaOf = async (query) => {
|
|
1723
|
+
if (query.pullRequest === void 0) return query.sha?.toLowerCase();
|
|
1724
|
+
if (query.sha !== void 0) throw new TrackerError("invalid_request", `${RUNS_SUBJECT2}: sha \u0438 pullRequest \u0437\u0430\u0434\u0430\u044E\u0442\u0441\u044F \u043F\u043E \u043E\u0442\u0434\u0435\u043B\u044C\u043D\u043E\u0441\u0442\u0438 \u2014 \u043F\u0440\u043E\u0433\u043E\u043D\u044B PR \u0431\u0435\u0440\u0443\u0442\u0441\u044F \u043F\u043E \u0435\u0433\u043E \u0433\u043E\u043B\u043E\u0432\u0435.`);
|
|
1725
|
+
const pull = query.pullRequest;
|
|
1726
|
+
if (!ID3.test(pull)) throw new TrackerError("not_found", `\u0412 GitVerse \u043D\u0435\u0442 PR ${pull}.`);
|
|
1727
|
+
const { body } = await requestJson(`${repo}/pulls/${pull}`, call({ missing: { failure: "not_found", message: `\u0412 GitVerse \u043D\u0435\u0442 PR ${pull}.` } }));
|
|
1728
|
+
const head = isRecord(body) && isRecord(body.head) ? text(body.head.sha) : void 0;
|
|
1729
|
+
if (head === void 0) throw new TrackerError("failed", "GitVerse \u043D\u0435 \u0432\u0435\u0440\u043D\u0443\u043B \u0433\u043E\u043B\u043E\u0432\u0443 PR.");
|
|
1730
|
+
return head.toLowerCase();
|
|
1731
|
+
};
|
|
1732
|
+
return {
|
|
1733
|
+
listWorkflows: async (query) => {
|
|
1734
|
+
assertListQuery(WORKFLOWS_SUBJECT2, { filters: [], clientSide: [], sorts: [] }, query, []);
|
|
1735
|
+
const page = pageOf3(query.cursor, WORKFLOWS_SUBJECT2);
|
|
1736
|
+
const perPage = Math.min(query.limit, PAGE_SIZE_MAX);
|
|
1737
|
+
const { body, headers: responseHeaders } = await requestJson(`${actions}/workflows?page=${String(page)}&per_page=${String(perPage)}`, call());
|
|
1738
|
+
const rows = rowsOf2(body, "workflows");
|
|
1739
|
+
return { items: rows.map(workflowOf2), ...nextPageCursor({ headers: responseHeaders, page, perPage, count: rows.length, total: isRecord(body) ? body.total_count : void 0 }) };
|
|
1740
|
+
},
|
|
1741
|
+
listRuns: async (query) => {
|
|
1742
|
+
assertListQuery(RUNS_SUBJECT2, CAPABILITIES4.runs, query, RUN_FILTERS4);
|
|
1743
|
+
const page = pageOf3(query.cursor, RUNS_SUBJECT2);
|
|
1744
|
+
const perPage = Math.min(query.limit, PAGE_SIZE_MAX);
|
|
1745
|
+
const sha = await headShaOf(query);
|
|
1746
|
+
const params = new URLSearchParams({ page: String(page), per_page: String(perPage) });
|
|
1747
|
+
if (query.ref !== void 0 && !query.ref.includes("/")) params.set("branch", query.ref);
|
|
1748
|
+
if (query.actor !== void 0) params.set("actor", query.actor);
|
|
1749
|
+
const path = query.workflow === void 0 ? `${actions}/runs` : `${actions}/workflows/${encodeURIComponent(query.workflow)}/runs`;
|
|
1750
|
+
const { body, headers: responseHeaders } = await requestJson(`${path}?${params.toString()}`, call());
|
|
1751
|
+
const rows = rowsOf2(body, "workflow_runs");
|
|
1752
|
+
const items = rows.map(runOf4).filter(
|
|
1753
|
+
(run) => (query.status === void 0 || query.status.length === 0 || query.status.includes(run.status.category)) && (query.event === void 0 || query.event.length === 0 || run.event !== void 0 && query.event.includes(run.event.category)) && (query.ref === void 0 || run.ref === query.ref) && (sha === void 0 || run.sha !== void 0 && run.sha.startsWith(sha))
|
|
1754
|
+
);
|
|
1755
|
+
return { items, ...nextPageCursor({ headers: responseHeaders, page, perPage, count: rows.length, total: isRecord(body) ? body.total_count : void 0 }) };
|
|
1756
|
+
},
|
|
1757
|
+
getRun,
|
|
1758
|
+
listJobs: async (key, query) => {
|
|
1759
|
+
const run = runKey(key);
|
|
1760
|
+
const { allAttempts, ...rest } = query;
|
|
1761
|
+
assertListQuery(JOBS_SUBJECT2, CAPABILITIES4.jobs, allAttempts === true ? query : rest, JOB_FILTERS4);
|
|
1762
|
+
const page = pageOf3(query.cursor, JOBS_SUBJECT2);
|
|
1763
|
+
const perPage = Math.min(query.limit, PAGE_SIZE_MAX);
|
|
1764
|
+
const { body, headers: responseHeaders } = await requestJson(`${actions}/runs/${run}/jobs?page=${String(page)}&per_page=${String(perPage)}`, call({ missing: missingRun(run) }));
|
|
1765
|
+
const rows = rowsOf2(body, "jobs");
|
|
1766
|
+
const items = rows.map(jobOf4).filter((job) => query.status === void 0 || query.status.length === 0 || query.status.includes(job.status.category));
|
|
1767
|
+
return { items, ...nextPageCursor({ headers: responseHeaders, page, perPage, count: rows.length, total: isRecord(body) ? body.total_count : void 0 }) };
|
|
1768
|
+
},
|
|
1769
|
+
getJob: async (key) => jobOf4(await rawJob(key)),
|
|
1770
|
+
log: async (key, query) => {
|
|
1771
|
+
const id = jobKey(key);
|
|
1772
|
+
const window = logWindow(query);
|
|
1773
|
+
const complete = isFinished(jobStatusOf(await rawJob(id)).category);
|
|
1774
|
+
if (!complete) return { text: "", truncated: false, complete: false, nextCursor: logCursor(0, 0) };
|
|
1775
|
+
const response = await requestText(`${actions}/jobs/${id}/logs`, {
|
|
1776
|
+
fetch,
|
|
1777
|
+
origin,
|
|
1778
|
+
headers,
|
|
1779
|
+
accept: GITVERSE_ACCEPT,
|
|
1780
|
+
skip: window.resume?.offset ?? 0,
|
|
1781
|
+
keep: { bytes: window.bytes, from: window.from },
|
|
1782
|
+
missing: missingJob(id)
|
|
1783
|
+
});
|
|
1784
|
+
return logOf({
|
|
1785
|
+
text: response.text,
|
|
1786
|
+
truncated: window.from === "tail" ? response.start > 0 : !response.whole,
|
|
1787
|
+
complete,
|
|
1788
|
+
page: 0,
|
|
1789
|
+
end: response.end,
|
|
1790
|
+
more: window.from === "head" && !response.whole,
|
|
1791
|
+
...response.whole ? { size: response.read } : {},
|
|
1792
|
+
raw: query.raw ?? false
|
|
1793
|
+
});
|
|
1794
|
+
},
|
|
1795
|
+
trigger: async (input) => {
|
|
1796
|
+
const workflows = input.workflows ?? [];
|
|
1797
|
+
const workflow = workflows[0];
|
|
1798
|
+
if (workflows.length !== 1 || workflow === void 0) throw new TrackerError("invalid_request", `${TRIGGER_SUBJECT2}: \u043D\u0443\u0436\u0435\u043D \u0440\u043E\u0432\u043D\u043E \u043E\u0434\u0438\u043D workflow \u2014 \u0438\u043C\u044F \u0444\u0430\u0439\u043B\u0430.`);
|
|
1799
|
+
const params = new URLSearchParams({ [input.refType === "tag" ? "tag" : "branch"]: input.ref });
|
|
1800
|
+
await requestJson(`${actions}/workflows/${encodeURIComponent(workflow)}/dispatches?${params.toString()}`, call({ method: "POST", body: { ...input.inputs }, conflictOn: [406, 409] }));
|
|
1801
|
+
return {};
|
|
1802
|
+
},
|
|
1803
|
+
rerun: async (key, input) => {
|
|
1804
|
+
const run = runKey(key);
|
|
1805
|
+
if (input.failedOnly === true) throw new TrackerError("unsupported", "\u041F\u0435\u0440\u0435\u0437\u0430\u043F\u0443\u0441\u043A CI GitVerse: \u0442\u043E\u043B\u044C\u043A\u043E \u0443\u043F\u0430\u0432\u0448\u0438\u0445 \u0437\u0430\u0434\u0430\u043D\u0438\u0439 \u043D\u0435\u0442 \u2014 \u043F\u0435\u0440\u0435\u0437\u0430\u043F\u0443\u0441\u043A\u0430\u0435\u0442\u0441\u044F \u043F\u0440\u043E\u0433\u043E\u043D \u0446\u0435\u043B\u0438\u043A\u043E\u043C.");
|
|
1806
|
+
if (input.debug === true) throw new TrackerError("unsupported", "\u041F\u0435\u0440\u0435\u0437\u0430\u043F\u0443\u0441\u043A CI GitVerse: \u043E\u0442\u043B\u0430\u0434\u043E\u0447\u043D\u043E\u0433\u043E \u043B\u043E\u0433\u0438\u0440\u043E\u0432\u0430\u043D\u0438\u044F \u043D\u0435\u0442.");
|
|
1807
|
+
await requestJson(`${actions}/runs/${run}/rerun`, call({ method: "POST", conflictOn: [406, 409], missing: missingRun(run) }));
|
|
1808
|
+
return getRun(run);
|
|
1809
|
+
},
|
|
1810
|
+
rerunJob: async (key, input) => {
|
|
1811
|
+
const id = jobKey(key);
|
|
1812
|
+
if (input.debug === true) throw new TrackerError("unsupported", "\u041F\u0435\u0440\u0435\u0437\u0430\u043F\u0443\u0441\u043A CI GitVerse: \u043E\u0442\u043B\u0430\u0434\u043E\u0447\u043D\u043E\u0433\u043E \u043B\u043E\u0433\u0438\u0440\u043E\u0432\u0430\u043D\u0438\u044F \u043D\u0435\u0442.");
|
|
1813
|
+
const run = idOf((await rawJob(id)).run_id);
|
|
1814
|
+
if (run === void 0) throw new TrackerError("failed", "GitVerse \u043D\u0435 \u0432\u0435\u0440\u043D\u0443\u043B \u043F\u0440\u043E\u0433\u043E\u043D \u0437\u0430\u0434\u0430\u043D\u0438\u044F.");
|
|
1815
|
+
await requestJson(`${actions}/jobs/${id}/rerun`, call({ method: "POST", conflictOn: [406, 409], missing: missingJob(id) }));
|
|
1816
|
+
return getRun(run);
|
|
1817
|
+
},
|
|
1818
|
+
cancel: async (key) => {
|
|
1819
|
+
const run = runKey(key);
|
|
1820
|
+
await requestJson(`${actions}/runs/${run}/cancel`, call({ method: "POST", conflictOn: [409], missing: missingRun(run) }));
|
|
1821
|
+
return getRun(run);
|
|
1822
|
+
},
|
|
1823
|
+
cancelJob: async () => {
|
|
1824
|
+
throw new TrackerError("unsupported", "\u041E\u0442\u043C\u0435\u043D\u0430 CI GitVerse: \u0437\u0430\u0434\u0430\u043D\u0438\u044F \u043F\u043E \u043E\u0442\u0434\u0435\u043B\u044C\u043D\u043E\u0441\u0442\u0438 \u043D\u0435 \u043E\u0442\u043C\u0435\u043D\u044F\u044E\u0442\u0441\u044F, \u043E\u0442\u043C\u0435\u043D\u044F\u0435\u0442\u0441\u044F \u043F\u0440\u043E\u0433\u043E\u043D.");
|
|
1825
|
+
}
|
|
1826
|
+
};
|
|
1827
|
+
}
|
|
1828
|
+
function pageOf3(cursor, subject) {
|
|
1829
|
+
if (cursor === void 0) return 1;
|
|
1830
|
+
if (!/^[1-9]\d{0,8}$/.test(cursor)) throw new TrackerError("invalid_request", `${subject}: \u043A\u0443\u0440\u0441\u043E\u0440 \u2014 \u043D\u043E\u043C\u0435\u0440 \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u044B \u0438\u0437 nextCursor.`);
|
|
1831
|
+
return Number(cursor);
|
|
1832
|
+
}
|
|
1833
|
+
function rowsOf2(body, field) {
|
|
1834
|
+
const rows = isRecord(body) ? body[field] : void 0;
|
|
1835
|
+
return Array.isArray(rows) ? rows : [];
|
|
1836
|
+
}
|
|
1837
|
+
function keyOf2(value) {
|
|
1838
|
+
if (typeof value === "number" && Number.isSafeInteger(value)) return String(value);
|
|
1839
|
+
return typeof value === "string" && value !== "" ? value : "?";
|
|
1840
|
+
}
|
|
1841
|
+
function positiveInt2(value) {
|
|
1842
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value > 0 ? value : void 0;
|
|
1843
|
+
}
|
|
1844
|
+
function idOf(value) {
|
|
1845
|
+
const id = positiveInt2(value);
|
|
1846
|
+
return id === void 0 ? void 0 : String(id);
|
|
1847
|
+
}
|
|
1848
|
+
function statusOf2(item) {
|
|
1849
|
+
const raw = text(item.status) ?? "unknown";
|
|
1850
|
+
return { category: lookup(GITVERSE_CI_STATUSES, raw.toLowerCase(), "running"), name: raw };
|
|
1851
|
+
}
|
|
1852
|
+
function jobStatusOf(item) {
|
|
1853
|
+
const status = statusOf2(item);
|
|
1854
|
+
return item.failed_step !== void 0 && item.failed_step !== null ? { category: "failed", name: status.name } : status;
|
|
1855
|
+
}
|
|
1856
|
+
function refOf(value) {
|
|
1857
|
+
const ref = text(value);
|
|
1858
|
+
return ref === void 0 ? void 0 : text(ref.replace(/^refs\/(?:heads|tags)\//, "")) ?? ref;
|
|
1859
|
+
}
|
|
1860
|
+
function workflowOf2(raw) {
|
|
1861
|
+
const item = isRecord(raw) ? raw : {};
|
|
1862
|
+
const key = text(item.workflow) ?? text(item.path) ?? text(item.name) ?? "?";
|
|
1863
|
+
const path = text(item.path);
|
|
1864
|
+
const state = text(item.state);
|
|
1865
|
+
return { key, name: text(item.name) ?? key, ...path === void 0 ? {} : { path }, enabled: state === void 0 || !/disabled/i.test(state) };
|
|
1866
|
+
}
|
|
1867
|
+
function runOf4(raw) {
|
|
1868
|
+
const item = isRecord(raw) ? raw : {};
|
|
1869
|
+
const status = statusOf2(item);
|
|
1870
|
+
const name = text(item.name);
|
|
1871
|
+
const ref = refOf(item.ref);
|
|
1872
|
+
const sha = text(item.commit_sha)?.toLowerCase();
|
|
1873
|
+
const actor = isRecord(item.actor) ? text(item.actor.login) : void 0;
|
|
1874
|
+
const number = positiveInt2(item.index);
|
|
1875
|
+
const url = text(item.html_url);
|
|
1876
|
+
const startedAt = toTimestamp(item.started);
|
|
1877
|
+
const finishedAt = isFinished(status.category) ? toTimestamp(item.stopped) : void 0;
|
|
1878
|
+
const event = text(item.event);
|
|
1879
|
+
const effective = item.need_approval === true && !isFinished(status.category) ? { category: "waiting", name: status.name } : status;
|
|
1880
|
+
return {
|
|
1881
|
+
key: keyOf2(item.id),
|
|
1882
|
+
...number === void 0 ? {} : { number },
|
|
1883
|
+
workflows: name === void 0 ? [] : [name],
|
|
1884
|
+
status: effective,
|
|
1885
|
+
...event === void 0 ? {} : { event: { category: lookup(GITVERSE_RUN_EVENTS, event, "other"), name: event } },
|
|
1886
|
+
...ref === void 0 ? {} : { ref },
|
|
1887
|
+
...sha === void 0 || !SHA2.test(sha) ? {} : { sha },
|
|
1888
|
+
...actor === void 0 ? {} : { actor },
|
|
1889
|
+
links: url === void 0 ? [] : [{ url, title: "GitVerse" }],
|
|
1890
|
+
...startedAt === void 0 ? {} : { startedAt },
|
|
1891
|
+
...finishedAt === void 0 ? {} : { finishedAt }
|
|
1892
|
+
};
|
|
1893
|
+
}
|
|
1894
|
+
function jobOf4(raw) {
|
|
1895
|
+
const item = isRecord(raw) ? raw : {};
|
|
1896
|
+
const key = keyOf2(item.id);
|
|
1897
|
+
const stage = text(item.workflow_name);
|
|
1898
|
+
const startedAt = toTimestamp(item.started_at);
|
|
1899
|
+
const finishedAt = toTimestamp(item.completed_at);
|
|
1900
|
+
const steps = Array.isArray(item.steps) ? item.steps.map(stepOf2) : void 0;
|
|
1901
|
+
return {
|
|
1902
|
+
key,
|
|
1903
|
+
runKey: idOf(item.run_id) ?? "?",
|
|
1904
|
+
name: text(item.name) ?? key,
|
|
1905
|
+
...stage === void 0 ? {} : { stage },
|
|
1906
|
+
status: jobStatusOf(item),
|
|
1907
|
+
...steps === void 0 ? {} : { steps },
|
|
1908
|
+
links: [],
|
|
1909
|
+
...startedAt === void 0 ? {} : { startedAt },
|
|
1910
|
+
...finishedAt === void 0 ? {} : { finishedAt }
|
|
1911
|
+
};
|
|
1912
|
+
}
|
|
1913
|
+
function stepOf2(raw) {
|
|
1914
|
+
const item = isRecord(raw) ? raw : {};
|
|
1915
|
+
const number = typeof item.number === "number" && Number.isSafeInteger(item.number) && item.number >= 0 ? item.number : 0;
|
|
1916
|
+
return { number, name: text(item.name) ?? String(number), status: statusOf2(item) };
|
|
1917
|
+
}
|
|
1918
|
+
|
|
1593
1919
|
// src/tracker/registry.lib.ts
|
|
1594
1920
|
var definitions = /* @__PURE__ */ new Map();
|
|
1595
1921
|
var userDefinitions = /* @__PURE__ */ new Map();
|
|
@@ -1646,9 +1972,9 @@ var pullRequestSchema = z2.object({
|
|
|
1646
1972
|
|
|
1647
1973
|
// src/tracker/github-pull.lib.ts
|
|
1648
1974
|
var DEFAULT_API3 = "https://api.github.com";
|
|
1649
|
-
var
|
|
1975
|
+
var TARGET5 = /^[\w.-]+\/[\w.-]+$/;
|
|
1650
1976
|
var NUMBER = /^[1-9]\d{0,19}$/;
|
|
1651
|
-
var
|
|
1977
|
+
var SHA3 = /^[0-9a-f]{7,64}$/;
|
|
1652
1978
|
var LIST_SUBJECT = "PR GitHub";
|
|
1653
1979
|
var COMMENTS_SUBJECT = "\u041A\u043E\u043C\u043C\u0435\u043D\u0442\u0430\u0440\u0438\u0438 PR GitHub";
|
|
1654
1980
|
var PULL_CAPABILITIES = {
|
|
@@ -1674,7 +2000,7 @@ function githubPulls() {
|
|
|
1674
2000
|
}
|
|
1675
2001
|
function createGithubPullAdapter({ connection, fetch }) {
|
|
1676
2002
|
const target = requireTarget(connection.target, "owner/repo \u0440\u0435\u043F\u043E\u0437\u0438\u0442\u043E\u0440\u0438\u044F GitHub");
|
|
1677
|
-
if (!
|
|
2003
|
+
if (!TARGET5.test(target)) throw new TrackerError("invalid_request", "target GitHub \u2014 owner/repo.");
|
|
1678
2004
|
const api = baseUrl(connection.url, DEFAULT_API3);
|
|
1679
2005
|
const origin = new URL(api).origin;
|
|
1680
2006
|
const root = `${api}/repos/${target}/pulls`;
|
|
@@ -1695,7 +2021,7 @@ function createGithubPullAdapter({ connection, fetch }) {
|
|
|
1695
2021
|
list: async (query) => {
|
|
1696
2022
|
assertListQuery(LIST_SUBJECT, PULL_CAPABILITIES.list, query, pullRequestFilterSchema.options);
|
|
1697
2023
|
const status = usedStatuses(query.status);
|
|
1698
|
-
const page =
|
|
2024
|
+
const page = pageOf4(query.cursor);
|
|
1699
2025
|
const params = new URLSearchParams({ state: stateFilter(status), per_page: String(query.limit), page: String(page) });
|
|
1700
2026
|
if (query.source !== void 0) params.set("head", `${owner}:${query.source}`);
|
|
1701
2027
|
if (query.target !== void 0) params.set("base", query.target);
|
|
@@ -1726,7 +2052,7 @@ function createGithubPullAdapter({ connection, fetch }) {
|
|
|
1726
2052
|
},
|
|
1727
2053
|
comments: async (key, query) => {
|
|
1728
2054
|
assertCommentQuery(COMMENTS_SUBJECT, PULL_CAPABILITIES.comments, query);
|
|
1729
|
-
const page =
|
|
2055
|
+
const page = pageOf4(query.cursor);
|
|
1730
2056
|
const params = new URLSearchParams({ per_page: String(query.limit), page: String(page) });
|
|
1731
2057
|
if (query.updatedAfter !== void 0) params.set("since", isoTime(query.updatedAfter));
|
|
1732
2058
|
const { body, headers: responseHeaders } = await requestJson(`${issues}/${number(key)}/comments?${params.toString()}`, { fetch, origin, headers, missing: missing(key) });
|
|
@@ -1735,7 +2061,7 @@ function createGithubPullAdapter({ connection, fetch }) {
|
|
|
1735
2061
|
comment: async (key, body) => commentOf((await requestJson(`${issues}/${number(key)}/comments`, { fetch, origin, headers, method: "POST", body: { body }, missing: missing(key) })).body)
|
|
1736
2062
|
};
|
|
1737
2063
|
}
|
|
1738
|
-
function
|
|
2064
|
+
function pageOf4(cursor) {
|
|
1739
2065
|
const page = cursor === void 0 ? 1 : Number(cursor);
|
|
1740
2066
|
return Number.isInteger(page) && page >= 1 ? page : 1;
|
|
1741
2067
|
}
|
|
@@ -1814,7 +2140,7 @@ function pullOf(raw) {
|
|
|
1814
2140
|
...author === void 0 ? {} : { author },
|
|
1815
2141
|
source: text(head.ref) ?? "?",
|
|
1816
2142
|
target: text(base.ref) ?? "?",
|
|
1817
|
-
...sha !== void 0 &&
|
|
2143
|
+
...sha !== void 0 && SHA3.test(sha) ? { headSha: sha } : {},
|
|
1818
2144
|
labels: Array.isArray(item.labels) ? stringList(item.labels.map((label) => isRecord(label) ? label.name : label)) : [],
|
|
1819
2145
|
reviewers: logins(item.requested_reviewers),
|
|
1820
2146
|
links: url === void 0 ? [] : [{ url, title: "GitHub" }],
|
|
@@ -1863,19 +2189,19 @@ var branchSchema = z3.object({
|
|
|
1863
2189
|
|
|
1864
2190
|
// src/tracker/github-repo.lib.ts
|
|
1865
2191
|
var DEFAULT_API4 = "https://api.github.com";
|
|
1866
|
-
var
|
|
1867
|
-
var
|
|
2192
|
+
var TARGET6 = /^[\w.-]+\/[\w.-]+$/;
|
|
2193
|
+
var SHA4 = /^[0-9a-f]{7,64}$/;
|
|
1868
2194
|
var BRANCHES_SUBJECT = "\u0412\u0435\u0442\u043A\u0438 GitHub";
|
|
1869
2195
|
var BRANCH_FILTERS = branchFilterSchema.options;
|
|
1870
|
-
var
|
|
2196
|
+
var CAPABILITIES5 = {
|
|
1871
2197
|
branches: { filters: BRANCH_FILTERS, clientSide: BRANCH_FILTERS, sorts: [] }
|
|
1872
2198
|
};
|
|
1873
2199
|
function githubRepo() {
|
|
1874
|
-
return { capabilities:
|
|
2200
|
+
return { capabilities: CAPABILITIES5, create: (context) => createGithubRepoAdapter(context) };
|
|
1875
2201
|
}
|
|
1876
2202
|
function createGithubRepoAdapter({ connection, fetch }) {
|
|
1877
2203
|
const target = requireTarget(connection.target, "owner/repo \u0440\u0435\u043F\u043E\u0437\u0438\u0442\u043E\u0440\u0438\u044F GitHub");
|
|
1878
|
-
if (!
|
|
2204
|
+
if (!TARGET6.test(target)) throw new TrackerError("invalid_request", "target GitHub \u2014 owner/repo.");
|
|
1879
2205
|
const api = baseUrl(connection.url, DEFAULT_API4);
|
|
1880
2206
|
const origin = new URL(api).origin;
|
|
1881
2207
|
const root = `${api}/repos/${target}`;
|
|
@@ -1888,8 +2214,8 @@ function createGithubRepoAdapter({ connection, fetch }) {
|
|
|
1888
2214
|
return {
|
|
1889
2215
|
get: async () => repoOf((await requestJson(root, { fetch, origin, headers, missing })).body, target),
|
|
1890
2216
|
branches: async (query) => {
|
|
1891
|
-
assertListQuery(BRANCHES_SUBJECT,
|
|
1892
|
-
const page =
|
|
2217
|
+
assertListQuery(BRANCHES_SUBJECT, CAPABILITIES5.branches, query, BRANCH_FILTERS);
|
|
2218
|
+
const page = pageOf5(query.cursor);
|
|
1893
2219
|
const params = new URLSearchParams({ per_page: String(query.limit), page: String(page) });
|
|
1894
2220
|
const { body, headers: responseHeaders } = await requestJson(`${root}/branches?${params.toString()}`, { fetch, origin, headers, missing });
|
|
1895
2221
|
const items = (Array.isArray(body) ? body : []).map(branchOf).filter((branch) => query.search === void 0 || containsText([branch.name], query.search));
|
|
@@ -1897,7 +2223,7 @@ function createGithubRepoAdapter({ connection, fetch }) {
|
|
|
1897
2223
|
}
|
|
1898
2224
|
};
|
|
1899
2225
|
}
|
|
1900
|
-
function
|
|
2226
|
+
function pageOf5(cursor) {
|
|
1901
2227
|
const page = cursor === void 0 ? 1 : Number(cursor);
|
|
1902
2228
|
return Number.isInteger(page) && page >= 1 ? page : 1;
|
|
1903
2229
|
}
|
|
@@ -1923,7 +2249,7 @@ function branchOf(raw) {
|
|
|
1923
2249
|
const sha = isRecord(item.commit) ? text(item.commit.sha) : void 0;
|
|
1924
2250
|
return {
|
|
1925
2251
|
name: text(item.name) ?? "?",
|
|
1926
|
-
...sha === void 0 || !
|
|
2252
|
+
...sha === void 0 || !SHA4.test(sha) ? {} : { sha },
|
|
1927
2253
|
...typeof item.protected === "boolean" ? { protected: item.protected } : {}
|
|
1928
2254
|
};
|
|
1929
2255
|
}
|
|
@@ -1934,7 +2260,7 @@ function visibilityOf(value) {
|
|
|
1934
2260
|
|
|
1935
2261
|
// src/tracker/github.lib.ts
|
|
1936
2262
|
var DEFAULT_API5 = "https://api.github.com";
|
|
1937
|
-
var
|
|
2263
|
+
var TARGET7 = /^[\w.-]+\/[\w.-]+$/;
|
|
1938
2264
|
var NUMBER2 = /^[1-9]\d{0,14}$/;
|
|
1939
2265
|
var LIST_SUBJECT2 = "\u0417\u0430\u0434\u0430\u0447\u0438 GitHub";
|
|
1940
2266
|
var COMMENTS_SUBJECT2 = "\u041A\u043E\u043C\u043C\u0435\u043D\u0442\u0430\u0440\u0438\u0438 GitHub";
|
|
@@ -1964,7 +2290,7 @@ function githubTracker() {
|
|
|
1964
2290
|
}
|
|
1965
2291
|
function createGithubAdapter({ connection, fetch }, capabilities) {
|
|
1966
2292
|
const target = requireTarget(connection.target, "owner/repo \u0440\u0435\u043F\u043E\u0437\u0438\u0442\u043E\u0440\u0438\u044F GitHub");
|
|
1967
|
-
if (!
|
|
2293
|
+
if (!TARGET7.test(target)) throw new TrackerError("invalid_request", "target GitHub \u2014 owner/repo.");
|
|
1968
2294
|
const api = baseUrl(connection.url, DEFAULT_API5);
|
|
1969
2295
|
const origin = new URL(api).origin;
|
|
1970
2296
|
const root = `${api}/repos/${target}/issues`;
|
|
@@ -1985,11 +2311,11 @@ function createGithubAdapter({ connection, fetch }, capabilities) {
|
|
|
1985
2311
|
list: async (query) => {
|
|
1986
2312
|
assertListQuery(LIST_SUBJECT2, capabilities.list, query, ISSUE_FILTERS);
|
|
1987
2313
|
assertCsvLabels(query.labels);
|
|
1988
|
-
const page =
|
|
2314
|
+
const page = pageOf6(query.cursor);
|
|
1989
2315
|
const search = needsSearch(query);
|
|
1990
2316
|
const params = search ? searchParams(target, query, page) : issuesParams(query, page);
|
|
1991
2317
|
const { body, headers: responseHeaders } = await requestJson(`${search ? `${api}/search/issues` : root}?${params.toString()}`, { fetch, origin, headers });
|
|
1992
|
-
return issuePageOf(
|
|
2318
|
+
return issuePageOf(rowsOf3(body, search), query, responseHeaders.get("link") ?? "", page);
|
|
1993
2319
|
},
|
|
1994
2320
|
get: async (key) => issueOf(await rawOf(key)),
|
|
1995
2321
|
create: async (input) => {
|
|
@@ -2009,7 +2335,7 @@ function createGithubAdapter({ connection, fetch }, capabilities) {
|
|
|
2009
2335
|
},
|
|
2010
2336
|
comments: async (key, query) => {
|
|
2011
2337
|
assertCommentQuery(COMMENTS_SUBJECT2, capabilities.comments, query);
|
|
2012
|
-
const page =
|
|
2338
|
+
const page = pageOf6(query.cursor);
|
|
2013
2339
|
const params = new URLSearchParams({ per_page: String(query.limit), page: String(page) });
|
|
2014
2340
|
if (query.updatedAfter !== void 0) params.set("since", isoTime(query.updatedAfter));
|
|
2015
2341
|
const { body, headers: responseHeaders } = await requestJson(`${root}/${number(key)}/comments?${params.toString()}`, { fetch, origin, headers, missingIsIssue: true });
|
|
@@ -2018,7 +2344,7 @@ function createGithubAdapter({ connection, fetch }, capabilities) {
|
|
|
2018
2344
|
comment: async (key, body) => commentOf2((await requestJson(`${root}/${number(key)}/comments`, { fetch, origin, headers, method: "POST", body: { body }, missingIsIssue: true })).body)
|
|
2019
2345
|
};
|
|
2020
2346
|
}
|
|
2021
|
-
function
|
|
2347
|
+
function pageOf6(cursor) {
|
|
2022
2348
|
const page = cursor === void 0 ? 1 : Number(cursor);
|
|
2023
2349
|
return Number.isInteger(page) && page >= 1 ? page : 1;
|
|
2024
2350
|
}
|
|
@@ -2073,7 +2399,7 @@ function timeRangeQualifier(field, after, before) {
|
|
|
2073
2399
|
if (before !== void 0) return `${field}:<=${isoTime(before)}`;
|
|
2074
2400
|
return void 0;
|
|
2075
2401
|
}
|
|
2076
|
-
function
|
|
2402
|
+
function rowsOf3(body, search) {
|
|
2077
2403
|
if (!search) return Array.isArray(body) ? body : [];
|
|
2078
2404
|
return isRecord(body) && Array.isArray(body.items) ? body.items : [];
|
|
2079
2405
|
}
|
|
@@ -2137,12 +2463,510 @@ function commentOf2(raw) {
|
|
|
2137
2463
|
return { id: typeof item.id === "number" ? String(item.id) : "?", ...author === void 0 ? {} : { author }, body: typeof item.body === "string" ? item.body : "", ...createdAt === void 0 ? {} : { createdAt } };
|
|
2138
2464
|
}
|
|
2139
2465
|
|
|
2466
|
+
// src/tracker/gitverse-pull.lib.ts
|
|
2467
|
+
var TARGET8 = /^[\w.-]+\/[\w.-]+$/;
|
|
2468
|
+
var NUMBER3 = /^[1-9]\d{0,14}$/;
|
|
2469
|
+
var OFFSET = /^\d{1,9}$/;
|
|
2470
|
+
var SHA5 = /^[0-9a-f]{7,64}$/;
|
|
2471
|
+
var LIST_SUBJECT3 = "PR GitVerse";
|
|
2472
|
+
var COMMENTS_SUBJECT3 = "\u041A\u043E\u043C\u043C\u0435\u043D\u0442\u0430\u0440\u0438\u0438 PR GitVerse";
|
|
2473
|
+
var PAGE_SIZE_MAX2 = 100;
|
|
2474
|
+
var PULL_FILTERS = pullRequestFilterSchema.options;
|
|
2475
|
+
var SORT_FIELDS_UPSTREAM = { created: "created", updated: "updated" };
|
|
2476
|
+
var PULL_CAPABILITIES2 = {
|
|
2477
|
+
list: {
|
|
2478
|
+
filters: PULL_FILTERS,
|
|
2479
|
+
clientSide: ["status", "author", "source", "target", "labels", "search", "createdAfter", "createdBefore", "updatedAfter", "updatedBefore"],
|
|
2480
|
+
sorts: ["created", "updated"]
|
|
2481
|
+
},
|
|
2482
|
+
comments: { filters: COMMENT_FILTERS, clientSide: COMMENT_FILTERS, order: ["asc", "desc"] },
|
|
2483
|
+
create: true,
|
|
2484
|
+
createDraft: true,
|
|
2485
|
+
update: ["title", "description", "target"],
|
|
2486
|
+
statuses: ["open", "closed"],
|
|
2487
|
+
comment: true,
|
|
2488
|
+
merge: [],
|
|
2489
|
+
deleteSourceOnMerge: false
|
|
2490
|
+
};
|
|
2491
|
+
function gitversePulls() {
|
|
2492
|
+
return { capabilities: PULL_CAPABILITIES2, create: (context) => createPullAdapter(context) };
|
|
2493
|
+
}
|
|
2494
|
+
function createPullAdapter({ connection, fetch }) {
|
|
2495
|
+
const target = requireTarget(connection.target, "owner/repo \u0440\u0435\u043F\u043E\u0437\u0438\u0442\u043E\u0440\u0438\u044F GitVerse");
|
|
2496
|
+
if (!TARGET8.test(target)) throw new TrackerError("invalid_request", "target GitVerse \u2014 owner/repo.");
|
|
2497
|
+
const api = baseUrl(connection.url, GITVERSE_API);
|
|
2498
|
+
const origin = new URL(api).origin;
|
|
2499
|
+
const repo = `${api}/repos/${target}`;
|
|
2500
|
+
const root = `${repo}/pulls`;
|
|
2501
|
+
const headers = connection.token === void 0 || connection.token === "" ? {} : { authorization: `Bearer ${connection.token}` };
|
|
2502
|
+
const web = connection.url === void 0 ? `${GITVERSE_WEB}/${target}` : void 0;
|
|
2503
|
+
const missing = (key) => ({ failure: "not_found", message: `\u0412 GitVerse \u043D\u0435\u0442 PR ${key}.` });
|
|
2504
|
+
const call = (key, extra = {}) => ({ fetch, origin, headers, accept: GITVERSE_ACCEPT, ...key === void 0 ? {} : { missing: missing(key) }, ...extra });
|
|
2505
|
+
const number = (key) => {
|
|
2506
|
+
if (!NUMBER3.test(key)) throw new TrackerError("not_found", `\u0412 GitVerse \u043D\u0435\u0442 PR ${key}.`);
|
|
2507
|
+
return key;
|
|
2508
|
+
};
|
|
2509
|
+
const toPull = (raw) => pullOf2(raw, web);
|
|
2510
|
+
const getPull = async (key) => toPull((await requestJson(`${root}/${number(key)}`, call(key))).body);
|
|
2511
|
+
return {
|
|
2512
|
+
list: async (query) => {
|
|
2513
|
+
assertListQuery(LIST_SUBJECT3, PULL_CAPABILITIES2.list, query, PULL_FILTERS);
|
|
2514
|
+
const page = pageOf7(query.cursor);
|
|
2515
|
+
const perPage = Math.min(query.limit, PAGE_SIZE_MAX2);
|
|
2516
|
+
const params = new URLSearchParams({ state: stateFilter3(query.status), page: String(page), per_page: String(perPage) });
|
|
2517
|
+
if (query.source !== void 0 && !query.source.includes("/")) params.set("head", query.source);
|
|
2518
|
+
if (query.target !== void 0 && !query.target.includes("/")) params.set("base", query.target);
|
|
2519
|
+
if (query.sort !== void 0) {
|
|
2520
|
+
params.set("sort", sortFieldOf(query.sort.field));
|
|
2521
|
+
params.set("direction", query.sort.direction ?? "desc");
|
|
2522
|
+
}
|
|
2523
|
+
const { body, headers: responseHeaders } = await requestJson(`${root}?${params.toString()}`, call(void 0));
|
|
2524
|
+
const rows = Array.isArray(body) ? body : [];
|
|
2525
|
+
return { items: rows.map(toPull).filter((pull) => matchesPage2(pull, query)), ...nextPageCursor({ headers: responseHeaders, page, perPage, count: rows.length }) };
|
|
2526
|
+
},
|
|
2527
|
+
get: (key) => getPull(key),
|
|
2528
|
+
create: async (input) => {
|
|
2529
|
+
const body = { title: input.title, head: input.source, base: input.target, ...input.description === void 0 ? {} : { body: input.description }, draft: input.draft === true };
|
|
2530
|
+
return toPull((await requestJson(root, call(void 0, { method: "POST", body }))).body);
|
|
2531
|
+
},
|
|
2532
|
+
update: async (key, patch) => {
|
|
2533
|
+
const id = number(key);
|
|
2534
|
+
if (patch.status === "draft") throw new TrackerError("unsupported", "PR GitVerse: \u0432\u0435\u0440\u043D\u0443\u0442\u044C PR \u0432 \u0447\u0435\u0440\u043D\u043E\u0432\u0438\u043A API \u043D\u0435 \u0434\u0430\u0451\u0442.");
|
|
2535
|
+
let state;
|
|
2536
|
+
if (patch.status === "closed") state = "closed";
|
|
2537
|
+
if (patch.status === "open") {
|
|
2538
|
+
const current = (await getPull(key)).status.category;
|
|
2539
|
+
if (current === "draft") throw new TrackerError("unsupported", "PR GitVerse: \u0441\u043D\u044F\u0442\u044C \u0447\u0435\u0440\u043D\u043E\u0432\u0438\u043A API \u043D\u0435 \u0434\u0430\u0451\u0442 \u2014 \u043E\u043F\u0443\u0431\u043B\u0438\u043A\u0443\u0439\u0442\u0435 PR \u0432 \u0432\u0435\u0431-\u0438\u043D\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0435.");
|
|
2540
|
+
if (current === "merged") throw new TrackerError("conflict", `PR ${key} \u0443\u0436\u0435 \u0432\u043B\u0438\u0442: \u043F\u0435\u0440\u0435\u043E\u0442\u043A\u0440\u044B\u0442\u044C \u0435\u0433\u043E \u043D\u0435\u043B\u044C\u0437\u044F.`);
|
|
2541
|
+
if (current === "closed") state = "open";
|
|
2542
|
+
}
|
|
2543
|
+
const body = {
|
|
2544
|
+
...patch.title === void 0 ? {} : { title: patch.title },
|
|
2545
|
+
...patch.description === void 0 ? {} : { body: patch.description },
|
|
2546
|
+
...patch.target === void 0 ? {} : { base: patch.target },
|
|
2547
|
+
...state === void 0 ? {} : { state }
|
|
2548
|
+
};
|
|
2549
|
+
if (Object.keys(body).length === 0) return getPull(key);
|
|
2550
|
+
const pull = toPull((await requestJson(`${root}/${id}`, call(key, { method: "PATCH", body }))).body);
|
|
2551
|
+
if (state !== void 0 && pull.status.category !== state) throw new TrackerError("conflict", `GitVerse \u043E\u0441\u0442\u0430\u0432\u0438\u043B PR ${key} \u0432 \u0441\u043E\u0441\u0442\u043E\u044F\u043D\u0438\u0438 ${pull.status.name}.`);
|
|
2552
|
+
return pull;
|
|
2553
|
+
},
|
|
2554
|
+
merge: async (key) => {
|
|
2555
|
+
const hint = web === void 0 || !NUMBER3.test(key) ? "\u0432 \u0432\u0435\u0431-\u0438\u043D\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0435 GitVerse" : `\u0432 \u0432\u0435\u0431-\u0438\u043D\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0435: ${web}/pulls/${key}`;
|
|
2556
|
+
throw new TrackerError("unsupported", `PR GitVerse: \u0441\u043B\u0438\u044F\u043D\u0438\u044F \u0432 API \u043D\u0435\u0442 \u2014 \u0432\u043B\u0438\u0442\u044C PR \u043C\u043E\u0436\u043D\u043E \u0442\u043E\u043B\u044C\u043A\u043E ${hint}.`);
|
|
2557
|
+
},
|
|
2558
|
+
comments: async (key, query) => {
|
|
2559
|
+
assertCommentQuery(COMMENTS_SUBJECT3, PULL_CAPABILITIES2.comments, query);
|
|
2560
|
+
const offset = offsetOf2(query.cursor);
|
|
2561
|
+
const { body } = await requestJson(`${repo}/issues/${number(key)}/comments`, call(key));
|
|
2562
|
+
const visible = (Array.isArray(body) ? body : []).map(commentOf3).filter((comment) => query.updatedAfter === void 0 || inTimeRange(comment.updatedAt, query.updatedAfter, void 0)).sort((left, right) => (left.comment.createdAt ?? 0) - (right.comment.createdAt ?? 0));
|
|
2563
|
+
if (query.order === "desc") visible.reverse();
|
|
2564
|
+
const end = offset + query.limit;
|
|
2565
|
+
return { items: visible.slice(offset, end).map((item) => item.comment), ...end < visible.length ? { nextCursor: String(end) } : {} };
|
|
2566
|
+
},
|
|
2567
|
+
comment: async (key, body) => commentOf3((await requestJson(`${repo}/issues/${number(key)}/comments`, call(key, { method: "POST", body: { body } }))).body).comment
|
|
2568
|
+
};
|
|
2569
|
+
}
|
|
2570
|
+
function pageOf7(cursor) {
|
|
2571
|
+
if (cursor === void 0) return 1;
|
|
2572
|
+
if (!/^[1-9]\d{0,8}$/.test(cursor)) throw new TrackerError("invalid_request", `${LIST_SUBJECT3}: \u043A\u0443\u0440\u0441\u043E\u0440 \u2014 \u043D\u043E\u043C\u0435\u0440 \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u044B \u0438\u0437 nextCursor.`);
|
|
2573
|
+
return Number(cursor);
|
|
2574
|
+
}
|
|
2575
|
+
function offsetOf2(cursor) {
|
|
2576
|
+
if (cursor === void 0) return 0;
|
|
2577
|
+
if (!OFFSET.test(cursor)) throw new TrackerError("invalid_request", `${COMMENTS_SUBJECT3}: \u043A\u0443\u0440\u0441\u043E\u0440 \u2014 nextCursor \u043F\u0440\u043E\u0448\u043B\u043E\u0439 \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u044B.`);
|
|
2578
|
+
return Number(cursor);
|
|
2579
|
+
}
|
|
2580
|
+
function stateFilter3(status) {
|
|
2581
|
+
if (status === void 0 || status.length === 0) return "all";
|
|
2582
|
+
if (status.every((item) => item === "open" || item === "draft")) return "open";
|
|
2583
|
+
if (status.every((item) => item === "merged" || item === "closed")) return "closed";
|
|
2584
|
+
return "all";
|
|
2585
|
+
}
|
|
2586
|
+
function sortFieldOf(field) {
|
|
2587
|
+
const upstream = SORT_FIELDS_UPSTREAM[field];
|
|
2588
|
+
if (upstream === void 0) throw new TrackerError("unsupported", `${LIST_SUBJECT3}: \u0441\u043E\u0440\u0442\u0438\u0440\u043E\u0432\u043A\u0430 \u043F\u043E ${field} \u043D\u0435 \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044F.`);
|
|
2589
|
+
return upstream;
|
|
2590
|
+
}
|
|
2591
|
+
function matchesPage2(pull, query) {
|
|
2592
|
+
if (query.status !== void 0 && query.status.length > 0 && !query.status.includes(pull.status.category)) return false;
|
|
2593
|
+
if (query.author !== void 0 && pull.author?.toLowerCase() !== query.author.toLowerCase()) return false;
|
|
2594
|
+
if (query.source !== void 0 && pull.source !== query.source) return false;
|
|
2595
|
+
if (query.target !== void 0 && pull.target !== query.target) return false;
|
|
2596
|
+
const labels = pull.labels.map((label) => label.toLowerCase());
|
|
2597
|
+
if (query.labels !== void 0 && !query.labels.every((label) => labels.includes(label.toLowerCase()))) return false;
|
|
2598
|
+
if (query.search !== void 0 && !containsText([pull.title, pull.description], query.search)) return false;
|
|
2599
|
+
return inTimeRange(pull.createdAt, query.createdAfter, query.createdBefore) && inTimeRange(pull.updatedAt, query.updatedAfter, query.updatedBefore);
|
|
2600
|
+
}
|
|
2601
|
+
function loginOf(value) {
|
|
2602
|
+
return isRecord(value) ? text(value.login) ?? text(value.username) : void 0;
|
|
2603
|
+
}
|
|
2604
|
+
function statusOf3(item) {
|
|
2605
|
+
const state = text(item.state) ?? "open";
|
|
2606
|
+
if (item.merged === true) return { category: "merged", name: "merged" };
|
|
2607
|
+
if (item.draft === true && state === "open") return { category: "draft", name: "draft" };
|
|
2608
|
+
return { category: lookup(GITVERSE_PULL_STATES, state, "open"), name: state };
|
|
2609
|
+
}
|
|
2610
|
+
function pullOf2(raw, web) {
|
|
2611
|
+
const item = isRecord(raw) ? raw : {};
|
|
2612
|
+
const head = isRecord(item.head) ? item.head : {};
|
|
2613
|
+
const base = isRecord(item.base) ? item.base : {};
|
|
2614
|
+
const key = typeof item.number === "number" && Number.isSafeInteger(item.number) ? String(item.number) : text(item.number) ?? "?";
|
|
2615
|
+
const headSha = text(head.sha);
|
|
2616
|
+
const description = text(item.body);
|
|
2617
|
+
const author = loginOf(item.user);
|
|
2618
|
+
const reviewers = Array.isArray(item.requested_reviewers) ? stringList(item.requested_reviewers.map(loginOf)) : void 0;
|
|
2619
|
+
const url = text(item.html_url) ?? (web === void 0 ? void 0 : `${web}/pulls/${key}`);
|
|
2620
|
+
const createdAt = toTimestamp(item.created_at);
|
|
2621
|
+
const updatedAt = toTimestamp(item.updated_at);
|
|
2622
|
+
const mergedAt = toTimestamp(item.merged_at);
|
|
2623
|
+
const closedAt = toTimestamp(item.closed_at);
|
|
2624
|
+
return {
|
|
2625
|
+
key,
|
|
2626
|
+
title: text(item.title) ?? key,
|
|
2627
|
+
...description === void 0 ? {} : { description },
|
|
2628
|
+
status: statusOf3(item),
|
|
2629
|
+
...author === void 0 ? {} : { author },
|
|
2630
|
+
source: text(head.ref) ?? "?",
|
|
2631
|
+
target: text(base.ref) ?? "?",
|
|
2632
|
+
...headSha !== void 0 && SHA5.test(headSha) ? { headSha } : {},
|
|
2633
|
+
labels: Array.isArray(item.labels) ? stringList(item.labels.map((label) => isRecord(label) ? label.name : label)) : [],
|
|
2634
|
+
...reviewers === void 0 ? {} : { reviewers },
|
|
2635
|
+
links: url === void 0 ? [] : [{ url, title: "GitVerse" }],
|
|
2636
|
+
...createdAt === void 0 ? {} : { createdAt },
|
|
2637
|
+
...updatedAt === void 0 ? {} : { updatedAt },
|
|
2638
|
+
...mergedAt === void 0 ? {} : { mergedAt },
|
|
2639
|
+
...closedAt === void 0 ? {} : { closedAt }
|
|
2640
|
+
};
|
|
2641
|
+
}
|
|
2642
|
+
function commentOf3(raw) {
|
|
2643
|
+
const item = isRecord(raw) ? raw : {};
|
|
2644
|
+
const id = typeof item.id === "number" && Number.isSafeInteger(item.id) ? String(item.id) : text(item.id) ?? "?";
|
|
2645
|
+
const author = loginOf(item.user);
|
|
2646
|
+
const createdAt = toTimestamp(item.created_at);
|
|
2647
|
+
return {
|
|
2648
|
+
comment: { id, ...author === void 0 ? {} : { author }, body: typeof item.body === "string" ? item.body : "", ...createdAt === void 0 ? {} : { createdAt } },
|
|
2649
|
+
updatedAt: toTimestamp(item.updated_at) ?? createdAt
|
|
2650
|
+
};
|
|
2651
|
+
}
|
|
2652
|
+
|
|
2653
|
+
// src/tracker/gitverse-repo.lib.ts
|
|
2654
|
+
var TARGET9 = /^[\w.-]+\/[\w.-]+$/;
|
|
2655
|
+
var SHA6 = /^[0-9a-f]{7,64}$/;
|
|
2656
|
+
var BRANCHES_SUBJECT2 = "\u0412\u0435\u0442\u043A\u0438 GitVerse";
|
|
2657
|
+
var BRANCH_FILTERS2 = branchFilterSchema.options;
|
|
2658
|
+
var PAGE_SIZE_MAX3 = 100;
|
|
2659
|
+
var CAPABILITIES6 = {
|
|
2660
|
+
branches: { filters: BRANCH_FILTERS2, clientSide: ["search"], sorts: [] }
|
|
2661
|
+
};
|
|
2662
|
+
function gitverseRepo() {
|
|
2663
|
+
return { capabilities: CAPABILITIES6, create: (context) => createGitverseRepoAdapter(context) };
|
|
2664
|
+
}
|
|
2665
|
+
function createGitverseRepoAdapter({ connection, fetch }) {
|
|
2666
|
+
const target = requireTarget(connection.target, "owner/repo \u0440\u0435\u043F\u043E\u0437\u0438\u0442\u043E\u0440\u0438\u044F GitVerse");
|
|
2667
|
+
if (!TARGET9.test(target)) throw new TrackerError("invalid_request", "target GitVerse \u2014 owner/repo.");
|
|
2668
|
+
const api = baseUrl(connection.url, GITVERSE_API);
|
|
2669
|
+
const origin = new URL(api).origin;
|
|
2670
|
+
const repo = `${api}/repos/${target}`;
|
|
2671
|
+
const headers = connection.token === void 0 || connection.token === "" ? {} : { authorization: `Bearer ${connection.token}` };
|
|
2672
|
+
const web = connection.url === void 0 ? `${GITVERSE_WEB}/${target}` : void 0;
|
|
2673
|
+
const missing = { failure: "not_found", message: `\u0412 GitVerse \u043D\u0435\u0442 \u0440\u0435\u043F\u043E\u0437\u0438\u0442\u043E\u0440\u0438\u044F ${target}.` };
|
|
2674
|
+
return {
|
|
2675
|
+
get: async () => repoOf2((await requestJson(repo, { fetch, origin, headers, accept: GITVERSE_ACCEPT, missing })).body, target, web),
|
|
2676
|
+
branches: async (query) => {
|
|
2677
|
+
assertListQuery(BRANCHES_SUBJECT2, CAPABILITIES6.branches, query, BRANCH_FILTERS2);
|
|
2678
|
+
if (query.cursor !== void 0 && !/^[1-9]\d{0,8}$/.test(query.cursor)) throw new TrackerError("invalid_request", `${BRANCHES_SUBJECT2}: \u043A\u0443\u0440\u0441\u043E\u0440 \u2014 \u043D\u043E\u043C\u0435\u0440 \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u044B \u0438\u0437 nextCursor.`);
|
|
2679
|
+
const page = query.cursor === void 0 ? 1 : Number(query.cursor);
|
|
2680
|
+
const perPage = Math.min(query.limit, PAGE_SIZE_MAX3);
|
|
2681
|
+
const params = new URLSearchParams({ page: String(page), per_page: String(perPage) });
|
|
2682
|
+
if (query.search !== void 0 && !query.search.includes("/")) params.set("q", query.search);
|
|
2683
|
+
const { body, headers: responseHeaders } = await requestJson(`${repo}/branches?${params.toString()}`, { fetch, origin, headers, accept: GITVERSE_ACCEPT, missing });
|
|
2684
|
+
const rows = Array.isArray(body) ? body : [];
|
|
2685
|
+
const search = query.search;
|
|
2686
|
+
const branches = rows.map(branchOf2).filter((branch) => search === void 0 || containsText([branch.name], search));
|
|
2687
|
+
return { items: branches, ...nextPageCursor({ headers: responseHeaders, page, perPage, count: rows.length }) };
|
|
2688
|
+
}
|
|
2689
|
+
};
|
|
2690
|
+
}
|
|
2691
|
+
function repoOf2(raw, target, web) {
|
|
2692
|
+
const item = isRecord(raw) ? raw : {};
|
|
2693
|
+
const defaultBranch = text(item.default_branch);
|
|
2694
|
+
const description = text(item.description);
|
|
2695
|
+
const visibility = visibilityOf2(item.visibility) ?? (typeof item.private === "boolean" ? item.private ? "private" : "public" : void 0);
|
|
2696
|
+
const url = text(item.html_url) ?? web;
|
|
2697
|
+
return {
|
|
2698
|
+
name: text(item.name) ?? target.slice(target.indexOf("/") + 1),
|
|
2699
|
+
...defaultBranch === void 0 ? {} : { defaultBranch },
|
|
2700
|
+
...description === void 0 ? {} : { description },
|
|
2701
|
+
...visibility === void 0 ? {} : { visibility },
|
|
2702
|
+
links: url === void 0 ? [] : [{ url, title: "GitVerse" }]
|
|
2703
|
+
};
|
|
2704
|
+
}
|
|
2705
|
+
function branchOf2(raw) {
|
|
2706
|
+
const item = isRecord(raw) ? raw : {};
|
|
2707
|
+
const sha = isRecord(item.commit) ? text(item.commit.sha) ?? text(item.commit.id) : void 0;
|
|
2708
|
+
return {
|
|
2709
|
+
name: text(item.name) ?? "?",
|
|
2710
|
+
...sha === void 0 || !SHA6.test(sha) ? {} : { sha },
|
|
2711
|
+
...typeof item.protected === "boolean" ? { protected: item.protected } : {}
|
|
2712
|
+
};
|
|
2713
|
+
}
|
|
2714
|
+
function visibilityOf2(value) {
|
|
2715
|
+
const parsed = repoVisibilitySchema.safeParse(value);
|
|
2716
|
+
return parsed.success ? parsed.data : void 0;
|
|
2717
|
+
}
|
|
2718
|
+
|
|
2719
|
+
// src/tracker/gitverse.lib.ts
|
|
2720
|
+
var TARGET10 = /^[\w.-]+\/[\w.-]+$/;
|
|
2721
|
+
var NUMBER4 = /^[1-9]\d{0,14}$/;
|
|
2722
|
+
var OFFSET2 = /^\d{1,9}$/;
|
|
2723
|
+
var LIST_SUBJECT4 = "\u0417\u0430\u0434\u0430\u0447\u0438 GitVerse";
|
|
2724
|
+
var COMMENTS_SUBJECT4 = "\u041A\u043E\u043C\u043C\u0435\u043D\u0442\u0430\u0440\u0438\u0438 GitVerse";
|
|
2725
|
+
var PAGE_SIZE_MAX4 = 100;
|
|
2726
|
+
var LABEL_PAGES_MAX = 10;
|
|
2727
|
+
var SORT_FIELDS_UPSTREAM2 = { created: "created", updated: "updated" };
|
|
2728
|
+
var CAPABILITIES7 = {
|
|
2729
|
+
list: { filters: ISSUE_FILTERS, clientSide: ["status", "labels", "assignee", "search", "createdAfter", "createdBefore"], sorts: ["created", "updated"] },
|
|
2730
|
+
comments: { filters: COMMENT_FILTERS, clientSide: COMMENT_FILTERS, order: ["asc", "desc"] }
|
|
2731
|
+
};
|
|
2732
|
+
function gitverseTracker() {
|
|
2733
|
+
return {
|
|
2734
|
+
descriptor: {
|
|
2735
|
+
tracker: "gitverse",
|
|
2736
|
+
title: "GitVerse",
|
|
2737
|
+
fields: [
|
|
2738
|
+
{ name: "target", required: true, secret: false },
|
|
2739
|
+
{ name: "token", required: true, secret: true },
|
|
2740
|
+
{ name: "url", required: false, secret: false }
|
|
2741
|
+
],
|
|
2742
|
+
features: { create: true, update: true, comment: true, priority: false, labels: true, assignee: true, statuses: ["open", "done"] }
|
|
2743
|
+
},
|
|
2744
|
+
issues: CAPABILITIES7,
|
|
2745
|
+
create: (context) => createGitverseAdapter(context),
|
|
2746
|
+
origin: (connection) => new URL(baseUrl(connection.url, GITVERSE_API)).origin,
|
|
2747
|
+
pulls: gitversePulls(),
|
|
2748
|
+
ci: gitverseCi(),
|
|
2749
|
+
repo: gitverseRepo()
|
|
2750
|
+
};
|
|
2751
|
+
}
|
|
2752
|
+
function createGitverseAdapter({ connection, fetch }) {
|
|
2753
|
+
const target = requireTarget(connection.target, "owner/repo \u0440\u0435\u043F\u043E\u0437\u0438\u0442\u043E\u0440\u0438\u044F GitVerse");
|
|
2754
|
+
if (!TARGET10.test(target)) throw new TrackerError("invalid_request", "target GitVerse \u2014 owner/repo.");
|
|
2755
|
+
const api = baseUrl(connection.url, GITVERSE_API);
|
|
2756
|
+
const origin = new URL(api).origin;
|
|
2757
|
+
const repo = `${api}/repos/${target}`;
|
|
2758
|
+
const root = `${repo}/issues`;
|
|
2759
|
+
const headers = connection.token === void 0 || connection.token === "" ? {} : { authorization: `Bearer ${connection.token}` };
|
|
2760
|
+
const web = connection.url === void 0 ? `${GITVERSE_WEB}/${target}` : void 0;
|
|
2761
|
+
const call = (extra = {}) => ({ fetch, origin, headers, accept: GITVERSE_ACCEPT, missingIsIssue: true, ...extra });
|
|
2762
|
+
const number = (key) => {
|
|
2763
|
+
if (!NUMBER4.test(key)) throw new TrackerError("unknown_issue", `\u0412 GitVerse \u043D\u0435\u0442 \u0437\u0430\u0434\u0430\u0447\u0438 ${key}.`);
|
|
2764
|
+
return key;
|
|
2765
|
+
};
|
|
2766
|
+
const toIssue2 = (raw) => issueOf2(raw, web);
|
|
2767
|
+
const rawOf = async (key) => {
|
|
2768
|
+
const { body } = await requestJson(`${root}/${number(key)}`, call());
|
|
2769
|
+
return isRecord(body) ? body : {};
|
|
2770
|
+
};
|
|
2771
|
+
const issueRawOf = async (key) => {
|
|
2772
|
+
const raw = await rawOf(key);
|
|
2773
|
+
if (isRecord(raw.pull_request)) throw new TrackerError("unknown_issue", `\u0412 GitVerse ${key} \u2014 pull request, \u0430 \u043D\u0435 \u0437\u0430\u0434\u0430\u0447\u0430.`);
|
|
2774
|
+
return raw;
|
|
2775
|
+
};
|
|
2776
|
+
const repoLabels = async () => {
|
|
2777
|
+
const names = [];
|
|
2778
|
+
for (let page = 1; page <= LABEL_PAGES_MAX; page += 1) {
|
|
2779
|
+
const { body } = await requestJson(`${repo}/labels?page=${String(page)}`, call({ missingIsIssue: false, missing: { failure: "not_found", message: `\u0412 GitVerse \u043D\u0435\u0442 \u0440\u0435\u043F\u043E\u0437\u0438\u0442\u043E\u0440\u0438\u044F ${target}.` } }));
|
|
2780
|
+
const fresh = (Array.isArray(body) ? body : []).map((label) => isRecord(label) ? text(label.name) : void 0).filter((name) => name !== void 0 && !names.includes(name));
|
|
2781
|
+
if (fresh.length === 0) break;
|
|
2782
|
+
names.push(...fresh);
|
|
2783
|
+
}
|
|
2784
|
+
return names;
|
|
2785
|
+
};
|
|
2786
|
+
const knownLabels = async (wanted) => {
|
|
2787
|
+
if (wanted.length === 0) return [];
|
|
2788
|
+
const known = await repoLabels();
|
|
2789
|
+
const resolved = [];
|
|
2790
|
+
const unknown = [];
|
|
2791
|
+
for (const name of new Set(wanted)) {
|
|
2792
|
+
const found = known.find((label) => label === name) ?? known.find((label) => label.toLowerCase() === name.toLowerCase());
|
|
2793
|
+
if (found === void 0) unknown.push(name);
|
|
2794
|
+
else if (!resolved.includes(found)) resolved.push(found);
|
|
2795
|
+
}
|
|
2796
|
+
if (unknown.length > 0) {
|
|
2797
|
+
throw new TrackerError("invalid_request", `\u0412 \u0440\u0435\u043F\u043E\u0437\u0438\u0442\u043E\u0440\u0438\u0438 GitVerse ${target} \u043D\u0435\u0442 \u043C\u0435\u0442\u043E\u043A: ${unknown.join(", ")}. GitVerse \u043C\u043E\u043B\u0447\u0430 \u043E\u0442\u0431\u0440\u043E\u0441\u0438\u043B \u0431\u044B \u0438\u0445, \u043F\u043E\u044D\u0442\u043E\u043C\u0443 \u0437\u0430\u043F\u0440\u043E\u0441 \u043D\u0435 \u043E\u0442\u043F\u0440\u0430\u0432\u043B\u0435\u043D.`);
|
|
2798
|
+
}
|
|
2799
|
+
return resolved;
|
|
2800
|
+
};
|
|
2801
|
+
const moveToColumn = async (key, raw, state) => {
|
|
2802
|
+
const stuck = () => new TrackerError(
|
|
2803
|
+
"conflict",
|
|
2804
|
+
`GitVerse \u043D\u0435 \u0441\u043C\u0435\u043D\u0438\u043B \u0441\u043E\u0441\u0442\u043E\u044F\u043D\u0438\u0435 \u0437\u0430\u0434\u0430\u0447\u0438 ${key} \u043D\u0430 ${state}: \u0441\u043E\u0441\u0442\u043E\u044F\u043D\u0438\u0435 \u0437\u0430\u0434\u0430\u0447\u0438 \u0441\u043B\u0435\u0434\u0443\u0435\u0442 \u0437\u0430 \u043A\u043E\u043B\u043E\u043D\u043A\u043E\u0439 \u0435\u0451 \u043F\u0440\u043E\u0435\u043A\u0442\u0430. \u041E\u0441\u0442\u0430\u043B\u044C\u043D\u044B\u0435 \u043F\u043E\u043B\u044F \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u044B; \u0441\u043C\u0435\u043D\u0438\u0442\u0435 \u0441\u0442\u0430\u0442\u0443\u0441 \u0432 \u0432\u0435\u0431-\u0438\u043D\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0435${web === void 0 ? "" : `: ${web}/issues/${key}`}.`
|
|
2805
|
+
);
|
|
2806
|
+
const project = projectIdOf(raw);
|
|
2807
|
+
if (project === void 0) throw stuck();
|
|
2808
|
+
const { body } = await requestJson(`${repo}/projects/${String(project)}`, call({ missingIsIssue: false, missing: { failure: "conflict", message: stuck().message } }));
|
|
2809
|
+
const columns = (isRecord(body) && Array.isArray(body.columns) ? body.columns : []).filter(isRecord);
|
|
2810
|
+
const done = (column2) => GITVERSE_DONE_COLUMN.test((text(column2.title) ?? text(column2.name) ?? "").trim());
|
|
2811
|
+
const column = state === "closed" ? columns.find(done) : columns.find((item) => item.default === true && !done(item)) ?? columns.find((item) => !done(item));
|
|
2812
|
+
const id = column === void 0 ? void 0 : column.id;
|
|
2813
|
+
if (typeof id !== "number" && typeof id !== "string") throw stuck();
|
|
2814
|
+
await requestJson(`${root}/${key}`, call({ method: "PATCH", body: { project_id: project, project_status_id: id } }));
|
|
2815
|
+
const reread = await rawOf(key);
|
|
2816
|
+
if (text(reread.state) !== state) throw stuck();
|
|
2817
|
+
return reread;
|
|
2818
|
+
};
|
|
2819
|
+
return {
|
|
2820
|
+
list: async (query) => {
|
|
2821
|
+
assertListQuery(LIST_SUBJECT4, CAPABILITIES7.list, query, ISSUE_FILTERS);
|
|
2822
|
+
const page = pageOf8(query.cursor, LIST_SUBJECT4);
|
|
2823
|
+
const perPage = Math.min(query.limit, PAGE_SIZE_MAX4);
|
|
2824
|
+
const params = new URLSearchParams({ state: stateFilter4(query.status), page: String(page), per_page: String(perPage) });
|
|
2825
|
+
const sent = (query.labels ?? []).filter((label) => !label.includes("/") && !label.includes(","));
|
|
2826
|
+
if (sent.length > 0) params.set("labels", sent.join(","));
|
|
2827
|
+
if (typeof query.assignee === "string") params.set("assigned_by", query.assignee);
|
|
2828
|
+
if (query.author !== void 0) params.set("created_by", query.author);
|
|
2829
|
+
if (query.search !== void 0 && !query.search.includes("/")) params.set("q", query.search);
|
|
2830
|
+
if (query.updatedAfter !== void 0) params.set("since", isoTime(query.updatedAfter));
|
|
2831
|
+
if (query.updatedBefore !== void 0) params.set("before", isoTime(query.updatedBefore));
|
|
2832
|
+
if (query.sort !== void 0) {
|
|
2833
|
+
params.set("sort", sortFieldOf2(query.sort.field));
|
|
2834
|
+
params.set("direction", query.sort.direction ?? "desc");
|
|
2835
|
+
}
|
|
2836
|
+
const { body, headers: responseHeaders } = await requestJson(`${root}?${params.toString()}`, call({ missingIsIssue: false }));
|
|
2837
|
+
const rows = Array.isArray(body) ? body : [];
|
|
2838
|
+
const issues = rows.filter((raw) => !(isRecord(raw) && isRecord(raw.pull_request))).map(toIssue2).filter((issue) => matchesPage3(issue, query));
|
|
2839
|
+
return { items: issues, ...nextPageCursor({ headers: responseHeaders, page, perPage, count: rows.length }) };
|
|
2840
|
+
},
|
|
2841
|
+
get: async (key) => toIssue2(await issueRawOf(key)),
|
|
2842
|
+
create: async (input) => {
|
|
2843
|
+
if (input.priority !== void 0) throw new TrackerError("unsupported", "\u0417\u0430\u0434\u0430\u0447\u0438 GitVerse: \u043F\u0440\u0438\u043E\u0440\u0438\u0442\u0435\u0442\u0430 \u0443 \u0437\u0430\u0434\u0430\u0447\u0438 \u043D\u0435\u0442.");
|
|
2844
|
+
const labels = await knownLabels(input.labels ?? []);
|
|
2845
|
+
const body = {
|
|
2846
|
+
title: input.title,
|
|
2847
|
+
...input.description === void 0 ? {} : { body: input.description },
|
|
2848
|
+
...labels.length === 0 ? {} : { labels },
|
|
2849
|
+
...input.assignee === void 0 ? {} : { assignees: [input.assignee] }
|
|
2850
|
+
};
|
|
2851
|
+
return toIssue2((await requestJson(root, call({ method: "POST", body, missingIsIssue: false }))).body);
|
|
2852
|
+
},
|
|
2853
|
+
update: async (key, patch) => {
|
|
2854
|
+
const id = number(key);
|
|
2855
|
+
if (patch.priority !== void 0) throw new TrackerError("unsupported", "\u0417\u0430\u0434\u0430\u0447\u0438 GitVerse: \u043F\u0440\u0438\u043E\u0440\u0438\u0442\u0435\u0442\u0430 \u0443 \u0437\u0430\u0434\u0430\u0447\u0438 \u043D\u0435\u0442.");
|
|
2856
|
+
const state = patch.status === void 0 ? void 0 : stateNameOf(patch.status);
|
|
2857
|
+
const before = await issueRawOf(id);
|
|
2858
|
+
const labels = patch.labels === void 0 ? void 0 : await knownLabels(patch.labels);
|
|
2859
|
+
const body = {
|
|
2860
|
+
...patch.title === void 0 ? {} : { title: patch.title },
|
|
2861
|
+
...patch.description === void 0 ? {} : { body: patch.description },
|
|
2862
|
+
...labels === void 0 ? {} : { labels },
|
|
2863
|
+
...patch.assignee === void 0 ? {} : { assignees: patch.assignee === null ? [] : [patch.assignee] },
|
|
2864
|
+
...state === void 0 ? {} : { state }
|
|
2865
|
+
};
|
|
2866
|
+
if (Object.keys(body).length === 0) return toIssue2(before);
|
|
2867
|
+
const { body: updated } = await requestJson(`${root}/${id}`, call({ method: "PATCH", body }));
|
|
2868
|
+
let raw = isRecord(updated) ? updated : await rawOf(id);
|
|
2869
|
+
if (state !== void 0 && text(raw.state) !== state) raw = await moveToColumn(id, raw, state);
|
|
2870
|
+
return toIssue2(raw);
|
|
2871
|
+
},
|
|
2872
|
+
comments: async (key, query) => {
|
|
2873
|
+
assertCommentQuery(COMMENTS_SUBJECT4, CAPABILITIES7.comments, query);
|
|
2874
|
+
const offset = offsetOf3(query.cursor);
|
|
2875
|
+
const id = number(key);
|
|
2876
|
+
await issueRawOf(id);
|
|
2877
|
+
const { body } = await requestJson(`${root}/${id}/comments`, call());
|
|
2878
|
+
const all = (Array.isArray(body) ? body : []).map(commentOf4);
|
|
2879
|
+
const visible = all.filter((comment) => query.updatedAfter === void 0 || inTimeRange(comment.updatedAt, query.updatedAfter, void 0)).sort((left, right) => (left.comment.createdAt ?? 0) - (right.comment.createdAt ?? 0));
|
|
2880
|
+
if (query.order === "desc") visible.reverse();
|
|
2881
|
+
const end = offset + query.limit;
|
|
2882
|
+
return { items: visible.slice(offset, end).map((item) => item.comment), ...end < visible.length ? { nextCursor: String(end) } : {} };
|
|
2883
|
+
},
|
|
2884
|
+
comment: async (key, body) => {
|
|
2885
|
+
const id = number(key);
|
|
2886
|
+
await issueRawOf(id);
|
|
2887
|
+
return commentOf4((await requestJson(`${root}/${id}/comments`, call({ method: "POST", body: { body } }))).body).comment;
|
|
2888
|
+
}
|
|
2889
|
+
};
|
|
2890
|
+
}
|
|
2891
|
+
function pageOf8(cursor, subject) {
|
|
2892
|
+
if (cursor === void 0) return 1;
|
|
2893
|
+
if (!/^[1-9]\d{0,8}$/.test(cursor)) throw new TrackerError("invalid_request", `${subject}: \u043A\u0443\u0440\u0441\u043E\u0440 \u2014 \u043D\u043E\u043C\u0435\u0440 \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u044B \u0438\u0437 nextCursor.`);
|
|
2894
|
+
return Number(cursor);
|
|
2895
|
+
}
|
|
2896
|
+
function offsetOf3(cursor) {
|
|
2897
|
+
if (cursor === void 0) return 0;
|
|
2898
|
+
if (!OFFSET2.test(cursor)) throw new TrackerError("invalid_request", `${COMMENTS_SUBJECT4}: \u043A\u0443\u0440\u0441\u043E\u0440 \u2014 nextCursor \u043F\u0440\u043E\u0448\u043B\u043E\u0439 \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u044B.`);
|
|
2899
|
+
return Number(cursor);
|
|
2900
|
+
}
|
|
2901
|
+
function stateFilter4(status) {
|
|
2902
|
+
if (status === void 0 || status.length === 0) return "all";
|
|
2903
|
+
if (status.every((item) => item === "open")) return "open";
|
|
2904
|
+
if (status.every((item) => item === "done")) return "closed";
|
|
2905
|
+
return "all";
|
|
2906
|
+
}
|
|
2907
|
+
function stateNameOf(status) {
|
|
2908
|
+
const name = GITVERSE_ISSUE_STATE_NAMES[status];
|
|
2909
|
+
if (name === void 0) throw new TrackerError("unsupported", `\u0417\u0430\u0434\u0430\u0447\u0438 GitVerse: \u0441\u0442\u0430\u0442\u0443\u0441\u0430 ${status} \u043D\u0435\u0442 \u2014 \u0442\u043E\u043B\u044C\u043A\u043E open \u0438 done.`);
|
|
2910
|
+
return name;
|
|
2911
|
+
}
|
|
2912
|
+
function sortFieldOf2(field) {
|
|
2913
|
+
const upstream = SORT_FIELDS_UPSTREAM2[field];
|
|
2914
|
+
if (upstream === void 0) throw new TrackerError("unsupported", `${LIST_SUBJECT4}: \u0441\u043E\u0440\u0442\u0438\u0440\u043E\u0432\u043A\u0430 \u043F\u043E ${field} \u043D\u0435 \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044F.`);
|
|
2915
|
+
return upstream;
|
|
2916
|
+
}
|
|
2917
|
+
function matchesPage3(issue, query) {
|
|
2918
|
+
if (query.status !== void 0 && query.status.length > 0 && !query.status.includes(issue.status.category)) return false;
|
|
2919
|
+
const labels = issue.labels.map((label) => label.toLowerCase());
|
|
2920
|
+
if (query.labels !== void 0 && !query.labels.every((label) => labels.includes(label.toLowerCase()))) return false;
|
|
2921
|
+
if (query.assignee === null && issue.assignee !== void 0) return false;
|
|
2922
|
+
if (query.search !== void 0 && query.search.includes("/") && !containsText([issue.title, issue.description], query.search)) return false;
|
|
2923
|
+
return inTimeRange(issue.createdAt, query.createdAfter, query.createdBefore);
|
|
2924
|
+
}
|
|
2925
|
+
function projectIdOf(raw) {
|
|
2926
|
+
const value = raw.project_id ?? (isRecord(raw.project) ? raw.project.id : void 0);
|
|
2927
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value > 0 || typeof value === "string" && /^\d{1,15}$/.test(value) ? value : void 0;
|
|
2928
|
+
}
|
|
2929
|
+
function loginOf2(value) {
|
|
2930
|
+
return isRecord(value) ? text(value.login) ?? text(value.username) : void 0;
|
|
2931
|
+
}
|
|
2932
|
+
function issueOf2(raw, web) {
|
|
2933
|
+
const item = isRecord(raw) ? raw : {};
|
|
2934
|
+
const key = typeof item.number === "number" && Number.isSafeInteger(item.number) ? String(item.number) : text(item.number) ?? "?";
|
|
2935
|
+
const state = text(item.state) ?? "open";
|
|
2936
|
+
const description = text(item.body);
|
|
2937
|
+
const assignee = (Array.isArray(item.assignees) ? item.assignees.map(loginOf2).find((login) => login !== void 0) : void 0) ?? loginOf2(item.assignee);
|
|
2938
|
+
const url = text(item.html_url) ?? (web === void 0 ? void 0 : `${web}/issues/${key}`);
|
|
2939
|
+
const createdAt = toTimestamp(item.created_at);
|
|
2940
|
+
const updatedAt = toTimestamp(item.updated_at);
|
|
2941
|
+
return {
|
|
2942
|
+
key,
|
|
2943
|
+
title: text(item.title) ?? key,
|
|
2944
|
+
...description === void 0 ? {} : { description },
|
|
2945
|
+
status: { category: lookup(GITVERSE_ISSUE_STATES, state, "open"), name: state },
|
|
2946
|
+
labels: Array.isArray(item.labels) ? stringList(item.labels.map((label) => isRecord(label) ? label.name : label)) : [],
|
|
2947
|
+
...assignee === void 0 ? {} : { assignee },
|
|
2948
|
+
links: url === void 0 ? [] : [{ url, title: "GitVerse" }],
|
|
2949
|
+
...createdAt === void 0 ? {} : { createdAt },
|
|
2950
|
+
...updatedAt === void 0 ? {} : { updatedAt }
|
|
2951
|
+
};
|
|
2952
|
+
}
|
|
2953
|
+
function commentOf4(raw) {
|
|
2954
|
+
const item = isRecord(raw) ? raw : {};
|
|
2955
|
+
const id = typeof item.id === "number" && Number.isSafeInteger(item.id) ? String(item.id) : text(item.id) ?? "?";
|
|
2956
|
+
const author = loginOf2(item.user) ?? loginOf2(item.author);
|
|
2957
|
+
const createdAt = toTimestamp(item.created_at);
|
|
2958
|
+
return {
|
|
2959
|
+
comment: { id, ...author === void 0 ? {} : { author }, body: typeof item.body === "string" ? item.body : "", ...createdAt === void 0 ? {} : { createdAt } },
|
|
2960
|
+
updatedAt: toTimestamp(item.updated_at) ?? createdAt
|
|
2961
|
+
};
|
|
2962
|
+
}
|
|
2963
|
+
|
|
2140
2964
|
// src/tracker/gitlab-pull.lib.ts
|
|
2141
2965
|
var DEFAULT_URL2 = "https://gitlab.com";
|
|
2142
|
-
var
|
|
2966
|
+
var TARGET11 = /^(\d{1,15}|[\w.-]+(\/[\w.-]+)+)$/;
|
|
2143
2967
|
var IID = /^[1-9]\d{0,19}$/;
|
|
2144
|
-
var
|
|
2145
|
-
var
|
|
2968
|
+
var SHA7 = /^[0-9a-f]{7,64}$/;
|
|
2969
|
+
var PULL_CAPABILITIES3 = {
|
|
2146
2970
|
list: { filters: pullRequestFilterSchema.options, clientSide: ["status"], sorts: ["created", "updated", "title"] },
|
|
2147
2971
|
comments: { filters: COMMENT_FILTERS, clientSide: COMMENT_FILTERS, order: ["asc", "desc"] },
|
|
2148
2972
|
create: true,
|
|
@@ -2156,13 +2980,13 @@ var PULL_CAPABILITIES2 = {
|
|
|
2156
2980
|
var ORDER_BY = { created: "created_at", updated: "updated_at", title: "title" };
|
|
2157
2981
|
function gitlabPulls() {
|
|
2158
2982
|
return {
|
|
2159
|
-
capabilities:
|
|
2983
|
+
capabilities: PULL_CAPABILITIES3,
|
|
2160
2984
|
create: (context) => createGitlabPullAdapter(context)
|
|
2161
2985
|
};
|
|
2162
2986
|
}
|
|
2163
2987
|
function createGitlabPullAdapter({ connection, fetch }) {
|
|
2164
2988
|
const target = requireTarget(connection.target, "\u043F\u0443\u0442\u044C \u043F\u0440\u043E\u0435\u043A\u0442\u0430 GitLab, group/project, \u0438\u043B\u0438 \u0435\u0433\u043E id");
|
|
2165
|
-
if (!
|
|
2989
|
+
if (!TARGET11.test(target)) throw new TrackerError("invalid_request", "target GitLab \u2014 group/project \u0438\u043B\u0438 \u0447\u0438\u0441\u043B\u043E\u0432\u043E\u0439 id.");
|
|
2166
2990
|
const site = baseUrl(connection.url, DEFAULT_URL2);
|
|
2167
2991
|
const origin = new URL(site).origin;
|
|
2168
2992
|
const root = `${site}/api/v4/projects/${encodeURIComponent(target)}/merge_requests`;
|
|
@@ -2171,14 +2995,14 @@ function createGitlabPullAdapter({ connection, fetch }) {
|
|
|
2171
2995
|
if (!IID.test(key)) throw new TrackerError("not_found", `\u0412 GitLab \u043D\u0435\u0442 MR ${key}.`);
|
|
2172
2996
|
return key;
|
|
2173
2997
|
};
|
|
2174
|
-
const currentOf = async (key) =>
|
|
2998
|
+
const currentOf = async (key) => pullOf3((await requestJson(`${root}/${iid(key)}`, { fetch, origin, headers, missing: { failure: "not_found", message: `\u0412 GitLab \u043D\u0435\u0442 MR ${key}.` } })).body);
|
|
2175
2999
|
return {
|
|
2176
3000
|
list: async (query) => {
|
|
2177
|
-
assertListQuery("PR GitLab",
|
|
3001
|
+
assertListQuery("PR GitLab", PULL_CAPABILITIES3.list, query, pullRequestFilterSchema.options);
|
|
2178
3002
|
const status = usedStatuses2(query.status);
|
|
2179
|
-
const page =
|
|
3003
|
+
const page = pageOf9(query.cursor);
|
|
2180
3004
|
const params = new URLSearchParams({
|
|
2181
|
-
state:
|
|
3005
|
+
state: stateFilter5(status),
|
|
2182
3006
|
per_page: String(query.limit),
|
|
2183
3007
|
page: String(page),
|
|
2184
3008
|
order_by: query.sort === void 0 ? "created_at" : ORDER_BY[query.sort.field] ?? "created_at",
|
|
@@ -2198,7 +3022,7 @@ function createGitlabPullAdapter({ connection, fetch }) {
|
|
|
2198
3022
|
if (query.updatedBefore !== void 0) params.set("updated_before", isoTime(query.updatedBefore));
|
|
2199
3023
|
const { body, headers: responseHeaders } = await requestJson(`${root}?${params.toString()}`, { fetch, origin, headers });
|
|
2200
3024
|
const next = responseHeaders.get("x-next-page");
|
|
2201
|
-
const items = (Array.isArray(body) ? body : []).map(
|
|
3025
|
+
const items = (Array.isArray(body) ? body : []).map(pullOf3);
|
|
2202
3026
|
return {
|
|
2203
3027
|
items: status === void 0 ? items : items.filter((pr) => status.includes(pr.status.category) === true),
|
|
2204
3028
|
...next === null || next === "" ? {} : { nextCursor: next }
|
|
@@ -2212,7 +3036,7 @@ function createGitlabPullAdapter({ connection, fetch }) {
|
|
|
2212
3036
|
title: (input.draft === true ? GITLAB_DRAFT_PREFIX : "") + input.title,
|
|
2213
3037
|
...input.description === void 0 ? {} : { description: input.description }
|
|
2214
3038
|
};
|
|
2215
|
-
return
|
|
3039
|
+
return pullOf3((await requestJson(root, { fetch, origin, headers, method: "POST", body, conflictOn: [409] })).body);
|
|
2216
3040
|
},
|
|
2217
3041
|
update: async (key, patch) => {
|
|
2218
3042
|
const current = patch.status === void 0 ? void 0 : await currentOf(key);
|
|
@@ -2220,11 +3044,11 @@ function createGitlabPullAdapter({ connection, fetch }) {
|
|
|
2220
3044
|
throw new TrackerError("unsupported", "PR GitLab: \u043F\u0435\u0440\u0435\u0432\u043E\u0434 \u0437\u0430\u043A\u0440\u044B\u0442\u043E\u0433\u043E MR \u0432 \u0447\u0435\u0440\u043D\u043E\u0432\u0438\u043A \u043D\u0435\u0434\u043E\u0441\u0442\u0443\u043F\u0435\u043D.");
|
|
2221
3045
|
}
|
|
2222
3046
|
const body = patchBody3(patch, current);
|
|
2223
|
-
if (Object.keys(body).length === 0) return current ??
|
|
2224
|
-
return
|
|
3047
|
+
if (Object.keys(body).length === 0) return current ?? pullOf3((await requestJson(`${root}/${iid(key)}`, { fetch, origin, headers, missing: { failure: "not_found", message: `\u0412 GitLab \u043D\u0435\u0442 MR ${key}.` } })).body);
|
|
3048
|
+
return pullOf3((await requestJson(`${root}/${iid(key)}`, { fetch, origin, headers, method: "PUT", body, missing: { failure: "not_found", message: `\u0412 GitLab \u043D\u0435\u0442 MR ${key}.` } })).body);
|
|
2225
3049
|
},
|
|
2226
3050
|
merge: async (key, input) => {
|
|
2227
|
-
if (input.method !== void 0 && !
|
|
3051
|
+
if (input.method !== void 0 && !PULL_CAPABILITIES3.merge.includes(input.method)) {
|
|
2228
3052
|
throw new TrackerError("unsupported", `PR GitLab: \u0441\u043B\u0438\u044F\u043D\u0438\u0435 \u0441\u043F\u043E\u0441\u043E\u0431\u043E\u043C ${input.method} \u043D\u0435 \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044F.`);
|
|
2229
3053
|
}
|
|
2230
3054
|
const body = {
|
|
@@ -2234,25 +3058,25 @@ function createGitlabPullAdapter({ connection, fetch }) {
|
|
|
2234
3058
|
...input.deleteSource === void 0 ? {} : { should_remove_source_branch: input.deleteSource },
|
|
2235
3059
|
...input.headSha === void 0 ? {} : { sha: input.headSha }
|
|
2236
3060
|
};
|
|
2237
|
-
return
|
|
3061
|
+
return pullOf3((await requestJson(`${root}/${iid(key)}/merge`, { fetch, origin, headers, method: "PUT", body, conflictOn: [405, 409, 422], missing: { failure: "not_found", message: `\u0412 GitLab \u043D\u0435\u0442 MR ${key}.` } })).body);
|
|
2238
3062
|
},
|
|
2239
3063
|
comments: async (key, query) => {
|
|
2240
|
-
assertCommentQuery("\u041A\u043E\u043C\u043C\u0435\u043D\u0442\u0430\u0440\u0438\u0438 GitLab",
|
|
2241
|
-
const page =
|
|
3064
|
+
assertCommentQuery("\u041A\u043E\u043C\u043C\u0435\u043D\u0442\u0430\u0440\u0438\u0438 GitLab", PULL_CAPABILITIES3.comments, query);
|
|
3065
|
+
const page = pageOf9(query.cursor);
|
|
2242
3066
|
const params = new URLSearchParams({ sort: query.order ?? "asc", order_by: "created_at", per_page: String(query.limit), page: String(page) });
|
|
2243
3067
|
const { body, headers: responseHeaders } = await requestJson(`${root}/${iid(key)}/notes?${params.toString()}`, { fetch, origin, headers, missing: { failure: "not_found", message: `\u0412 GitLab \u043D\u0435\u0442 MR ${key}.` } });
|
|
2244
3068
|
const next = responseHeaders.get("x-next-page");
|
|
2245
|
-
const items = (Array.isArray(body) ? body : []).filter((note) => isRecord(note) && note.system !== true && inTimeRange(toTimestamp(note.updated_at), query.updatedAfter, void 0)).map(
|
|
3069
|
+
const items = (Array.isArray(body) ? body : []).filter((note) => isRecord(note) && note.system !== true && inTimeRange(toTimestamp(note.updated_at), query.updatedAfter, void 0)).map(commentOf5);
|
|
2246
3070
|
return { items, ...next === null || next === "" ? {} : { nextCursor: next } };
|
|
2247
3071
|
},
|
|
2248
|
-
comment: async (key, body) =>
|
|
3072
|
+
comment: async (key, body) => commentOf5((await requestJson(`${root}/${iid(key)}/notes`, { fetch, origin, headers, method: "POST", body: { body }, missing: { failure: "not_found", message: `\u0412 GitLab \u043D\u0435\u0442 MR ${key}.` } })).body)
|
|
2249
3073
|
};
|
|
2250
3074
|
}
|
|
2251
|
-
function
|
|
3075
|
+
function pageOf9(cursor) {
|
|
2252
3076
|
const page = cursor === void 0 ? 1 : Number(cursor);
|
|
2253
3077
|
return Number.isInteger(page) && page >= 1 ? page : 1;
|
|
2254
3078
|
}
|
|
2255
|
-
function
|
|
3079
|
+
function stateFilter5(status) {
|
|
2256
3080
|
if (status === void 0) return "all";
|
|
2257
3081
|
if (status.every((item) => item === "draft" || item === "open")) return "opened";
|
|
2258
3082
|
if (status.every((item) => item === "merged")) return "merged";
|
|
@@ -2294,7 +3118,7 @@ function usernames(value) {
|
|
|
2294
3118
|
const names = value.map((item) => isRecord(item) ? text(item.username) : void 0);
|
|
2295
3119
|
return [...new Set(names.filter((name) => name !== void 0 && name !== ""))];
|
|
2296
3120
|
}
|
|
2297
|
-
function
|
|
3121
|
+
function pullOf3(raw) {
|
|
2298
3122
|
const item = isRecord(raw) ? raw : {};
|
|
2299
3123
|
const state = text(item.state) ?? "opened";
|
|
2300
3124
|
const draft = item.draft === true;
|
|
@@ -2316,7 +3140,7 @@ function pullOf2(raw) {
|
|
|
2316
3140
|
...author === void 0 ? {} : { author },
|
|
2317
3141
|
source: text(item.source_branch) ?? "?",
|
|
2318
3142
|
target: text(item.target_branch) ?? "?",
|
|
2319
|
-
...sha !== void 0 &&
|
|
3143
|
+
...sha !== void 0 && SHA7.test(sha) ? { headSha: sha } : {},
|
|
2320
3144
|
labels: labelNames(item.labels),
|
|
2321
3145
|
reviewers: usernames(item.reviewers),
|
|
2322
3146
|
links: url === void 0 ? [] : [{ url, title: "GitLab" }],
|
|
@@ -2326,7 +3150,7 @@ function pullOf2(raw) {
|
|
|
2326
3150
|
...closedAt === void 0 ? {} : { closedAt }
|
|
2327
3151
|
};
|
|
2328
3152
|
}
|
|
2329
|
-
function
|
|
3153
|
+
function commentOf5(raw) {
|
|
2330
3154
|
const item = isRecord(raw) ? raw : {};
|
|
2331
3155
|
const author = isRecord(item.author) ? text(item.author.username) : void 0;
|
|
2332
3156
|
const createdAt = toTimestamp(item.created_at);
|
|
@@ -2335,37 +3159,37 @@ function commentOf3(raw) {
|
|
|
2335
3159
|
|
|
2336
3160
|
// src/tracker/gitlab-repo.lib.ts
|
|
2337
3161
|
var DEFAULT_URL3 = "https://gitlab.com";
|
|
2338
|
-
var
|
|
2339
|
-
var
|
|
2340
|
-
var
|
|
2341
|
-
var
|
|
2342
|
-
var
|
|
2343
|
-
branches: { filters:
|
|
3162
|
+
var TARGET12 = /^(\d{1,15}|[\w.-]+(\/[\w.-]+)+)$/;
|
|
3163
|
+
var SHA8 = /^[0-9a-f]{7,64}$/;
|
|
3164
|
+
var BRANCHES_SUBJECT3 = "\u0412\u0435\u0442\u043A\u0438 GitLab";
|
|
3165
|
+
var BRANCH_FILTERS3 = branchFilterSchema.options;
|
|
3166
|
+
var CAPABILITIES8 = {
|
|
3167
|
+
branches: { filters: BRANCH_FILTERS3, clientSide: [], sorts: [] }
|
|
2344
3168
|
};
|
|
2345
3169
|
function gitlabRepo() {
|
|
2346
|
-
return { capabilities:
|
|
3170
|
+
return { capabilities: CAPABILITIES8, create: (context) => createGitlabRepoAdapter(context) };
|
|
2347
3171
|
}
|
|
2348
3172
|
function createGitlabRepoAdapter({ connection, fetch }) {
|
|
2349
3173
|
const target = requireTarget(connection.target, "\u043F\u0443\u0442\u044C \u043F\u0440\u043E\u0435\u043A\u0442\u0430 GitLab, group/project, \u0438\u043B\u0438 \u0435\u0433\u043E id");
|
|
2350
|
-
if (!
|
|
3174
|
+
if (!TARGET12.test(target)) throw new TrackerError("invalid_request", "target GitLab \u2014 group/project \u0438\u043B\u0438 \u0447\u0438\u0441\u043B\u043E\u0432\u043E\u0439 id.");
|
|
2351
3175
|
const site = baseUrl(connection.url, DEFAULT_URL3);
|
|
2352
3176
|
const origin = new URL(site).origin;
|
|
2353
3177
|
const project = `${site}/api/v4/projects/${encodeURIComponent(target)}`;
|
|
2354
3178
|
const headers = connection.token === void 0 || connection.token === "" ? {} : { "private-token": connection.token };
|
|
2355
3179
|
const missing = { failure: "not_found", message: `\u0412 GitLab \u043D\u0435\u0442 \u043F\u0440\u043E\u0435\u043A\u0442\u0430 ${target}.` };
|
|
2356
3180
|
return {
|
|
2357
|
-
get: async () =>
|
|
3181
|
+
get: async () => repoOf3((await requestJson(project, { fetch, origin, headers, missing })).body, target),
|
|
2358
3182
|
branches: async (query) => {
|
|
2359
|
-
assertListQuery(
|
|
2360
|
-
const params = new URLSearchParams({ per_page: String(query.limit), page: String(
|
|
3183
|
+
assertListQuery(BRANCHES_SUBJECT3, CAPABILITIES8.branches, query, BRANCH_FILTERS3);
|
|
3184
|
+
const params = new URLSearchParams({ per_page: String(query.limit), page: String(pageOf10(query.cursor)) });
|
|
2361
3185
|
if (query.search !== void 0) params.set("search", searchOf(query.search));
|
|
2362
3186
|
const { body, headers: responseHeaders } = await requestJson(`${project}/repository/branches?${params.toString()}`, { fetch, origin, headers, missing });
|
|
2363
3187
|
const next = responseHeaders.get("x-next-page");
|
|
2364
|
-
return { items: (Array.isArray(body) ? body : []).map(
|
|
3188
|
+
return { items: (Array.isArray(body) ? body : []).map(branchOf3), ...next === null || next === "" ? {} : { nextCursor: next } };
|
|
2365
3189
|
}
|
|
2366
3190
|
};
|
|
2367
3191
|
}
|
|
2368
|
-
function
|
|
3192
|
+
function pageOf10(cursor) {
|
|
2369
3193
|
const page = cursor === void 0 ? 1 : Number(cursor);
|
|
2370
3194
|
return Number.isInteger(page) && page >= 1 ? page : 1;
|
|
2371
3195
|
}
|
|
@@ -2373,11 +3197,11 @@ function searchOf(value) {
|
|
|
2373
3197
|
const stripped = value.replace(/^\^/, "").replace(/\$$/, "");
|
|
2374
3198
|
return stripped === "" ? value : stripped;
|
|
2375
3199
|
}
|
|
2376
|
-
function
|
|
3200
|
+
function repoOf3(raw, target) {
|
|
2377
3201
|
const item = isRecord(raw) ? raw : {};
|
|
2378
3202
|
const defaultBranch = text(item.default_branch);
|
|
2379
3203
|
const description = text(item.description);
|
|
2380
|
-
const visibility =
|
|
3204
|
+
const visibility = visibilityOf3(item.visibility);
|
|
2381
3205
|
const url = text(item.web_url);
|
|
2382
3206
|
return {
|
|
2383
3207
|
name: text(item.name) ?? text(item.path_with_namespace) ?? target,
|
|
@@ -2387,24 +3211,24 @@ function repoOf2(raw, target) {
|
|
|
2387
3211
|
links: url === void 0 ? [] : [{ url, title: "GitLab" }]
|
|
2388
3212
|
};
|
|
2389
3213
|
}
|
|
2390
|
-
function
|
|
3214
|
+
function branchOf3(raw) {
|
|
2391
3215
|
const item = isRecord(raw) ? raw : {};
|
|
2392
3216
|
const sha = isRecord(item.commit) ? text(item.commit.id) : void 0;
|
|
2393
3217
|
return {
|
|
2394
3218
|
name: text(item.name) ?? "?",
|
|
2395
|
-
...sha === void 0 || !
|
|
3219
|
+
...sha === void 0 || !SHA8.test(sha) ? {} : { sha },
|
|
2396
3220
|
...typeof item.protected === "boolean" ? { protected: item.protected } : {},
|
|
2397
3221
|
...typeof item.default === "boolean" ? { isDefault: item.default } : {}
|
|
2398
3222
|
};
|
|
2399
3223
|
}
|
|
2400
|
-
function
|
|
3224
|
+
function visibilityOf3(value) {
|
|
2401
3225
|
const parsed = repoVisibilitySchema.safeParse(value);
|
|
2402
3226
|
return parsed.success ? parsed.data : void 0;
|
|
2403
3227
|
}
|
|
2404
3228
|
|
|
2405
3229
|
// src/tracker/gitlab.lib.ts
|
|
2406
3230
|
var DEFAULT_URL4 = "https://gitlab.com";
|
|
2407
|
-
var
|
|
3231
|
+
var TARGET13 = /^(\d{1,15}|[\w.-]+(\/[\w.-]+)+)$/;
|
|
2408
3232
|
var IID2 = /^[1-9]\d{0,14}$/;
|
|
2409
3233
|
var ISSUE_CAPABILITIES = {
|
|
2410
3234
|
list: { filters: ISSUE_FILTERS, clientSide: ["status"], sorts: ["created", "updated", "priority", "title"] },
|
|
@@ -2438,7 +3262,7 @@ function gitlabTracker() {
|
|
|
2438
3262
|
}
|
|
2439
3263
|
function createGitlabAdapter({ connection, fetch }) {
|
|
2440
3264
|
const target = requireTarget(connection.target, "\u043F\u0443\u0442\u044C \u043F\u0440\u043E\u0435\u043A\u0442\u0430 GitLab, group/project, \u0438\u043B\u0438 \u0435\u0433\u043E id");
|
|
2441
|
-
if (!
|
|
3265
|
+
if (!TARGET13.test(target)) throw new TrackerError("invalid_request", "target GitLab \u2014 group/project \u0438\u043B\u0438 \u0447\u0438\u0441\u043B\u043E\u0432\u043E\u0439 id.");
|
|
2442
3266
|
const site = baseUrl(connection.url, DEFAULT_URL4);
|
|
2443
3267
|
const origin = new URL(site).origin;
|
|
2444
3268
|
const root = `${site}/api/v4/projects/${encodeURIComponent(target)}/issues`;
|
|
@@ -2447,13 +3271,13 @@ function createGitlabAdapter({ connection, fetch }) {
|
|
|
2447
3271
|
if (!IID2.test(key)) throw new TrackerError("unknown_issue", `\u0412 GitLab \u043D\u0435\u0442 \u0437\u0430\u0434\u0430\u0447\u0438 ${key}.`);
|
|
2448
3272
|
return key;
|
|
2449
3273
|
};
|
|
2450
|
-
const currentOf = async (key) =>
|
|
3274
|
+
const currentOf = async (key) => issueOf3((await requestJson(`${root}/${iid(key)}`, { fetch, origin, headers, missingIsIssue: true })).body);
|
|
2451
3275
|
return {
|
|
2452
3276
|
list: async (query) => {
|
|
2453
3277
|
assertListQuery("\u0417\u0430\u0434\u0430\u0447\u0438 GitLab", ISSUE_CAPABILITIES.list, query, ISSUE_FILTERS);
|
|
2454
|
-
const page =
|
|
3278
|
+
const page = pageOf11(query.cursor);
|
|
2455
3279
|
const params = new URLSearchParams({
|
|
2456
|
-
state:
|
|
3280
|
+
state: stateFilter6(query.status),
|
|
2457
3281
|
per_page: String(query.limit),
|
|
2458
3282
|
page: String(page),
|
|
2459
3283
|
order_by: query.sort === void 0 ? "created_at" : ORDER_BY2[query.sort.field] ?? "created_at",
|
|
@@ -2471,7 +3295,7 @@ function createGitlabAdapter({ connection, fetch }) {
|
|
|
2471
3295
|
if (query.updatedAfter !== void 0) params.set("updated_after", isoTime(query.updatedAfter));
|
|
2472
3296
|
if (query.updatedBefore !== void 0) params.set("updated_before", isoTime(query.updatedBefore));
|
|
2473
3297
|
const { body, headers: responseHeaders } = await requestJson(`${root}?${params.toString()}`, { fetch, origin, headers });
|
|
2474
|
-
const items = (Array.isArray(body) ? body : []).map(
|
|
3298
|
+
const items = (Array.isArray(body) ? body : []).map(issueOf3);
|
|
2475
3299
|
const next = responseHeaders.get("x-next-page");
|
|
2476
3300
|
return {
|
|
2477
3301
|
items: query.status === void 0 ? items : items.filter((issue) => query.status?.includes(issue.status.category) === true),
|
|
@@ -2482,29 +3306,29 @@ function createGitlabAdapter({ connection, fetch }) {
|
|
|
2482
3306
|
create: async (input) => {
|
|
2483
3307
|
const labels = composeLabels2(input.labels ?? [], input.priority, void 0);
|
|
2484
3308
|
const body = { title: input.title, ...input.description === void 0 ? {} : { description: input.description }, ...labels.length === 0 ? {} : { labels: labels.join(",") } };
|
|
2485
|
-
return
|
|
3309
|
+
return issueOf3((await requestJson(root, { fetch, origin, headers, method: "POST", body })).body);
|
|
2486
3310
|
},
|
|
2487
3311
|
update: async (key, patch) => {
|
|
2488
3312
|
const current = patch.labels === void 0 && patch.priority === void 0 && patch.status === void 0 ? void 0 : await currentOf(key);
|
|
2489
|
-
return
|
|
3313
|
+
return issueOf3((await requestJson(`${root}/${iid(key)}`, { fetch, origin, headers, method: "PUT", body: patchBody4(patch, current), missingIsIssue: true })).body);
|
|
2490
3314
|
},
|
|
2491
3315
|
comments: async (key, query) => {
|
|
2492
3316
|
assertCommentQuery("\u041A\u043E\u043C\u043C\u0435\u043D\u0442\u0430\u0440\u0438\u0438 GitLab", ISSUE_CAPABILITIES.comments, query);
|
|
2493
|
-
const page =
|
|
3317
|
+
const page = pageOf11(query.cursor);
|
|
2494
3318
|
const params = new URLSearchParams({ sort: query.order ?? "asc", order_by: "created_at", per_page: String(query.limit), page: String(page) });
|
|
2495
3319
|
const { body, headers: responseHeaders } = await requestJson(`${root}/${iid(key)}/notes?${params.toString()}`, { fetch, origin, headers, missingIsIssue: true });
|
|
2496
3320
|
const next = responseHeaders.get("x-next-page");
|
|
2497
|
-
const items = (Array.isArray(body) ? body : []).filter((note) => isRecord(note) && note.system !== true && inTimeRange(toTimestamp(note.updated_at), query.updatedAfter, void 0)).map(
|
|
3321
|
+
const items = (Array.isArray(body) ? body : []).filter((note) => isRecord(note) && note.system !== true && inTimeRange(toTimestamp(note.updated_at), query.updatedAfter, void 0)).map(commentOf6);
|
|
2498
3322
|
return { items, ...next === null || next === "" ? {} : { nextCursor: next } };
|
|
2499
3323
|
},
|
|
2500
|
-
comment: async (key, body) =>
|
|
3324
|
+
comment: async (key, body) => commentOf6((await requestJson(`${root}/${iid(key)}/notes`, { fetch, origin, headers, method: "POST", body: { body }, missingIsIssue: true })).body)
|
|
2501
3325
|
};
|
|
2502
3326
|
}
|
|
2503
|
-
function
|
|
3327
|
+
function pageOf11(cursor) {
|
|
2504
3328
|
const page = cursor === void 0 ? 1 : Number(cursor);
|
|
2505
3329
|
return Number.isInteger(page) && page >= 1 ? page : 1;
|
|
2506
3330
|
}
|
|
2507
|
-
function
|
|
3331
|
+
function stateFilter6(status) {
|
|
2508
3332
|
if (status === void 0) return "all";
|
|
2509
3333
|
if (status.every((item) => item === "open" || item === "in_progress")) return "opened";
|
|
2510
3334
|
if (status.every((item) => item === "done" || item === "declined")) return "closed";
|
|
@@ -2525,7 +3349,7 @@ function patchBody4(patch, current) {
|
|
|
2525
3349
|
...touchesLabels ? { labels: composeLabels2(patch.labels ?? current?.labels ?? [], patch.priority ?? current?.priority, status).join(",") } : {}
|
|
2526
3350
|
};
|
|
2527
3351
|
}
|
|
2528
|
-
function
|
|
3352
|
+
function issueOf3(raw) {
|
|
2529
3353
|
const item = isRecord(raw) ? raw : {};
|
|
2530
3354
|
const names = stringList(item.labels);
|
|
2531
3355
|
const closed = item.state === "closed";
|
|
@@ -2552,7 +3376,7 @@ function issueOf2(raw) {
|
|
|
2552
3376
|
...updatedAt === void 0 ? {} : { updatedAt }
|
|
2553
3377
|
};
|
|
2554
3378
|
}
|
|
2555
|
-
function
|
|
3379
|
+
function commentOf6(raw) {
|
|
2556
3380
|
const item = isRecord(raw) ? raw : {};
|
|
2557
3381
|
const author = isRecord(item.author) ? text(item.author.username) : void 0;
|
|
2558
3382
|
const createdAt = toTimestamp(item.created_at);
|
|
@@ -2603,7 +3427,7 @@ function createJiraAdapter({ connection, fetch }) {
|
|
|
2603
3427
|
if (!ISSUE_KEY.test(value)) throw new TrackerError("unknown_issue", `\u0412 Jira \u043D\u0435\u0442 \u0437\u0430\u0434\u0430\u0447\u0438 ${value}.`);
|
|
2604
3428
|
return value;
|
|
2605
3429
|
};
|
|
2606
|
-
const toIssue2 = (raw) =>
|
|
3430
|
+
const toIssue2 = (raw) => issueOf4(raw, site);
|
|
2607
3431
|
const load = async (value) => toIssue2((await requestJson(`${api}/issue/${key(value)}?fields=${FIELDS}`, { fetch, origin, headers, missingIsIssue: true })).body);
|
|
2608
3432
|
return {
|
|
2609
3433
|
list: async (query) => {
|
|
@@ -2662,9 +3486,9 @@ function createJiraAdapter({ connection, fetch }) {
|
|
|
2662
3486
|
const items = raw.filter((item) => inTimeRange(toTimestamp(isRecord(item) ? item.updated : void 0), query.updatedAfter, void 0));
|
|
2663
3487
|
const total = typeof record.total === "number" ? record.total : 0;
|
|
2664
3488
|
const at = typeof record.startAt === "number" ? record.startAt : 0;
|
|
2665
|
-
return { items: items.map(
|
|
3489
|
+
return { items: items.map(commentOf7), ...at + raw.length < total && raw.length > 0 ? { nextCursor: String(at + raw.length) } : {} };
|
|
2666
3490
|
},
|
|
2667
|
-
comment: async (value, body) =>
|
|
3491
|
+
comment: async (value, body) => commentOf7((await requestJson(`${api}/issue/${key(value)}/comment`, { fetch, origin, headers, method: "POST", body: { body }, missingIsIssue: true })).body)
|
|
2668
3492
|
};
|
|
2669
3493
|
}
|
|
2670
3494
|
function listJql(project, query) {
|
|
@@ -2712,7 +3536,7 @@ async function transition(api, key, category, request) {
|
|
|
2712
3536
|
if (id === void 0) throw new TrackerError("invalid_request", `\u0418\u0437 \u0442\u0435\u043A\u0443\u0449\u0435\u0433\u043E \u0441\u0442\u0430\u0442\u0443\u0441\u0430 Jira \u043D\u0435\u0442 \u043F\u0435\u0440\u0435\u0445\u043E\u0434\u0430 \u0432 \u043A\u0430\u0442\u0435\u0433\u043E\u0440\u0438\u044E ${category}.`);
|
|
2713
3537
|
await requestJson(`${api}/issue/${key}/transitions`, { fetch, origin, headers, method: "POST", body: { transition: { id } }, missingIsIssue: true });
|
|
2714
3538
|
}
|
|
2715
|
-
function
|
|
3539
|
+
function issueOf4(raw, site) {
|
|
2716
3540
|
const item = isRecord(raw) ? raw : {};
|
|
2717
3541
|
const fields = isRecord(item.fields) ? item.fields : {};
|
|
2718
3542
|
const status = isRecord(fields.status) ? fields.status : {};
|
|
@@ -2737,7 +3561,7 @@ function issueOf3(raw, site) {
|
|
|
2737
3561
|
...updatedAt === void 0 ? {} : { updatedAt }
|
|
2738
3562
|
};
|
|
2739
3563
|
}
|
|
2740
|
-
function
|
|
3564
|
+
function commentOf7(raw) {
|
|
2741
3565
|
const item = isRecord(raw) ? raw : {};
|
|
2742
3566
|
const author = isRecord(item.author) ? text(item.author.displayName) : void 0;
|
|
2743
3567
|
const createdAt = toTimestamp(item.created);
|
|
@@ -2826,15 +3650,15 @@ function toComment(row) {
|
|
|
2826
3650
|
|
|
2827
3651
|
// src/tracker/sourcecraft-pull.lib.ts
|
|
2828
3652
|
var DEFAULT_API6 = "https://api.sourcecraft.tech";
|
|
2829
|
-
var
|
|
3653
|
+
var TARGET14 = /^[\w.-]+\/[\w.-]+$/;
|
|
2830
3654
|
var SLUG = /^[\w-]{1,100}$/;
|
|
2831
|
-
var
|
|
3655
|
+
var SHA9 = /^[0-9a-f]{7,64}$/;
|
|
2832
3656
|
var PULL_SORT_FIELDS_UPSTREAM = {
|
|
2833
3657
|
created: "created_at",
|
|
2834
3658
|
updated: "updated_at",
|
|
2835
3659
|
title: "title"
|
|
2836
3660
|
};
|
|
2837
|
-
var
|
|
3661
|
+
var PULL_CAPABILITIES4 = {
|
|
2838
3662
|
list: {
|
|
2839
3663
|
filters: pullRequestFilterSchema.options,
|
|
2840
3664
|
clientSide: ["labels", "search", "createdAfter", "createdBefore", "updatedAfter", "updatedBefore"],
|
|
@@ -2850,11 +3674,11 @@ var PULL_CAPABILITIES3 = {
|
|
|
2850
3674
|
deleteSourceOnMerge: true
|
|
2851
3675
|
};
|
|
2852
3676
|
function sourcecraftPulls() {
|
|
2853
|
-
return { capabilities:
|
|
3677
|
+
return { capabilities: PULL_CAPABILITIES4, create: (context) => createPullAdapter2(context) };
|
|
2854
3678
|
}
|
|
2855
|
-
function
|
|
3679
|
+
function createPullAdapter2({ connection, fetch }) {
|
|
2856
3680
|
const target = requireTarget(connection.target, "org/repo \u0440\u0435\u043F\u043E\u0437\u0438\u0442\u043E\u0440\u0438\u044F SourceCraft");
|
|
2857
|
-
if (!
|
|
3681
|
+
if (!TARGET14.test(target)) throw new TrackerError("invalid_request", "target SourceCraft \u2014 org/repo.");
|
|
2858
3682
|
const api = baseUrl(connection.url, DEFAULT_API6);
|
|
2859
3683
|
const origin = new URL(api).origin;
|
|
2860
3684
|
const root = `${api}/repos/${target}/pulls`;
|
|
@@ -2864,10 +3688,10 @@ function createPullAdapter({ connection, fetch }) {
|
|
|
2864
3688
|
if (!SLUG.test(key)) throw new TrackerError("not_found", `\u0412 SourceCraft \u043D\u0435\u0442 PR ${key}.`);
|
|
2865
3689
|
return key;
|
|
2866
3690
|
};
|
|
2867
|
-
const getPull = async (key) =>
|
|
3691
|
+
const getPull = async (key) => pullOf4((await requestJson(`${root}/${slug(key)}`, { fetch, origin, headers, missing: missing(key) })).body);
|
|
2868
3692
|
return {
|
|
2869
3693
|
list: async (query) => {
|
|
2870
|
-
assertListQuery("PR SourceCraft",
|
|
3694
|
+
assertListQuery("PR SourceCraft", PULL_CAPABILITIES4.list, query, pullRequestFilterSchema.options);
|
|
2871
3695
|
const status = usedStatuses3(query.status);
|
|
2872
3696
|
const params = new URLSearchParams({ page_size: String(query.limit) });
|
|
2873
3697
|
if (query.cursor !== void 0) params.set("page_token", query.cursor);
|
|
@@ -2876,11 +3700,11 @@ function createPullAdapter({ connection, fetch }) {
|
|
|
2876
3700
|
if (query.sort !== void 0) params.set("sort_by", `${query.sort.direction === "asc" ? "" : "-"}${PULL_SORT_FIELDS_UPSTREAM[query.sort.field]}`);
|
|
2877
3701
|
const { body } = await requestJson(`${root}?${params.toString()}`, { fetch, origin, headers });
|
|
2878
3702
|
const record = isRecord(body) ? body : {};
|
|
2879
|
-
const pulls = (Array.isArray(record.pull_requests) ? record.pull_requests : []).map(
|
|
3703
|
+
const pulls = (Array.isArray(record.pull_requests) ? record.pull_requests : []).map(pullOf4).filter((pull) => matchesPage4(pull, query));
|
|
2880
3704
|
return { items: pulls, ...nextOf3(record.next_page_token) };
|
|
2881
3705
|
},
|
|
2882
3706
|
get: (key) => getPull(key),
|
|
2883
|
-
create: async (input) =>
|
|
3707
|
+
create: async (input) => pullOf4((await requestJson(root, { fetch, origin, headers, method: "POST", body: createBody2(input) })).body),
|
|
2884
3708
|
update: async (key, patch) => {
|
|
2885
3709
|
const id = slug(key);
|
|
2886
3710
|
let updated;
|
|
@@ -2897,12 +3721,12 @@ function createPullAdapter({ connection, fetch }) {
|
|
|
2897
3721
|
if (action !== void 0) await requestJson(`${root}/${id}/${action}`, { fetch, origin, headers, method: "POST", missing: missing(key) });
|
|
2898
3722
|
return getPull(key);
|
|
2899
3723
|
}
|
|
2900
|
-
return
|
|
3724
|
+
return pullOf4(updated ?? (await requestJson(`${root}/${id}`, { fetch, origin, headers, missing: missing(key) })).body);
|
|
2901
3725
|
},
|
|
2902
3726
|
merge: async (key, input) => {
|
|
2903
3727
|
const id = slug(key);
|
|
2904
3728
|
if (input.message !== void 0) throw new TrackerError("unsupported", "PR SourceCraft: \u0441\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u0435 \u043A\u043E\u043C\u043C\u0438\u0442\u0430 \u0441\u043B\u0438\u044F\u043D\u0438\u044F \u043D\u0435 \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044F.");
|
|
2905
|
-
if (input.method !== void 0 && !
|
|
3729
|
+
if (input.method !== void 0 && !PULL_CAPABILITIES4.merge.includes(input.method)) {
|
|
2906
3730
|
throw new TrackerError("unsupported", `PR SourceCraft: \u0441\u043B\u0438\u044F\u043D\u0438\u0435 \u0441\u043F\u043E\u0441\u043E\u0431\u043E\u043C ${input.method} \u043D\u0435 \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044F.`);
|
|
2907
3731
|
}
|
|
2908
3732
|
if (input.headSha !== void 0) {
|
|
@@ -2932,7 +3756,7 @@ function createPullAdapter({ connection, fetch }) {
|
|
|
2932
3756
|
},
|
|
2933
3757
|
comments: async (key, query) => {
|
|
2934
3758
|
const id = slug(key);
|
|
2935
|
-
assertCommentQuery("\u041A\u043E\u043C\u043C\u0435\u043D\u0442\u0430\u0440\u0438\u0438 PR SourceCraft",
|
|
3759
|
+
assertCommentQuery("\u041A\u043E\u043C\u043C\u0435\u043D\u0442\u0430\u0440\u0438\u0438 PR SourceCraft", PULL_CAPABILITIES4.comments, query);
|
|
2936
3760
|
const params = new URLSearchParams({ page_size: String(query.limit) });
|
|
2937
3761
|
if (query.cursor !== void 0) params.set("page_token", query.cursor);
|
|
2938
3762
|
if (query.order !== void 0) params.set("sort_by", query.order === "asc" ? "created_at" : "-created_at");
|
|
@@ -2941,9 +3765,9 @@ function createPullAdapter({ connection, fetch }) {
|
|
|
2941
3765
|
const rawComments = Array.isArray(record.pull_request_comments) ? record.pull_request_comments : [];
|
|
2942
3766
|
const visible = rawComments.filter((raw) => !(isRecord(raw) && raw.is_deleted === true));
|
|
2943
3767
|
const filtered = query.updatedAfter === void 0 ? visible : visible.filter((raw) => inTimeRange(toTimestamp(isRecord(raw) ? raw.updated_at : void 0), query.updatedAfter, void 0));
|
|
2944
|
-
return { items: filtered.map(
|
|
3768
|
+
return { items: filtered.map(commentOf8), ...nextOf3(record.next_page_token) };
|
|
2945
3769
|
},
|
|
2946
|
-
comment: async (key, body) =>
|
|
3770
|
+
comment: async (key, body) => commentOf8((await requestJson(`${root}/${slug(key)}/comments`, { fetch, origin, headers, method: "POST", body: { body }, missing: missing(key) })).body)
|
|
2947
3771
|
};
|
|
2948
3772
|
}
|
|
2949
3773
|
function createBody2(input) {
|
|
@@ -2970,7 +3794,7 @@ function usedStatuses3(status) {
|
|
|
2970
3794
|
}
|
|
2971
3795
|
return status;
|
|
2972
3796
|
}
|
|
2973
|
-
function
|
|
3797
|
+
function matchesPage4(pull, query) {
|
|
2974
3798
|
if (query.labels !== void 0 && !query.labels.every((label) => pull.labels.includes(label))) return false;
|
|
2975
3799
|
if (query.search !== void 0 && !containsText([pull.title, pull.description], query.search)) return false;
|
|
2976
3800
|
return inTimeRange(pull.createdAt, query.createdAfter, query.createdBefore) && inTimeRange(pull.updatedAt, query.updatedAfter, query.updatedBefore);
|
|
@@ -2990,7 +3814,7 @@ function nextOf3(token) {
|
|
|
2990
3814
|
const value = text(token);
|
|
2991
3815
|
return value === void 0 ? {} : { nextCursor: value };
|
|
2992
3816
|
}
|
|
2993
|
-
function
|
|
3817
|
+
function pullOf4(raw) {
|
|
2994
3818
|
const item = isRecord(raw) ? raw : {};
|
|
2995
3819
|
const source = isRecord(item.source) ? item.source : {};
|
|
2996
3820
|
const target = isRecord(item.target) ? item.target : {};
|
|
@@ -3011,7 +3835,7 @@ function pullOf3(raw) {
|
|
|
3011
3835
|
...author === void 0 ? {} : { author },
|
|
3012
3836
|
source: text(source.ref) ?? text(item.source_branch) ?? "?",
|
|
3013
3837
|
target: text(target.ref) ?? text(item.target_branch) ?? "?",
|
|
3014
|
-
...headSha !== void 0 &&
|
|
3838
|
+
...headSha !== void 0 && SHA9.test(headSha) ? { headSha } : {},
|
|
3015
3839
|
labels: Array.isArray(item.labels) ? stringList(item.labels.map((label) => isRecord(label) ? label.name : void 0)) : [],
|
|
3016
3840
|
links: [],
|
|
3017
3841
|
...createdAt === void 0 ? {} : { createdAt },
|
|
@@ -3020,7 +3844,7 @@ function pullOf3(raw) {
|
|
|
3020
3844
|
...closedAt === void 0 ? {} : { closedAt }
|
|
3021
3845
|
};
|
|
3022
3846
|
}
|
|
3023
|
-
function
|
|
3847
|
+
function commentOf8(raw) {
|
|
3024
3848
|
const item = isRecord(raw) ? raw : {};
|
|
3025
3849
|
const author = isRecord(item.author) ? text(item.author.slug) : void 0;
|
|
3026
3850
|
const createdAt = toTimestamp(item.created_at);
|
|
@@ -3029,45 +3853,45 @@ function commentOf6(raw) {
|
|
|
3029
3853
|
|
|
3030
3854
|
// src/tracker/sourcecraft-repo.lib.ts
|
|
3031
3855
|
var DEFAULT_API7 = "https://api.sourcecraft.tech";
|
|
3032
|
-
var
|
|
3033
|
-
var
|
|
3034
|
-
var
|
|
3035
|
-
var
|
|
3036
|
-
var
|
|
3037
|
-
var
|
|
3038
|
-
branches: { filters:
|
|
3856
|
+
var TARGET15 = /^[\w.-]+\/[\w.-]+$/;
|
|
3857
|
+
var SHA10 = /^[0-9a-f]{7,64}$/;
|
|
3858
|
+
var BRANCHES_SUBJECT4 = "\u0412\u0435\u0442\u043A\u0438 SourceCraft";
|
|
3859
|
+
var BRANCH_FILTERS4 = branchFilterSchema.options;
|
|
3860
|
+
var PAGE_SIZE_MAX5 = 100;
|
|
3861
|
+
var CAPABILITIES9 = {
|
|
3862
|
+
branches: { filters: BRANCH_FILTERS4, clientSide: [], sorts: [] }
|
|
3039
3863
|
};
|
|
3040
3864
|
function sourcecraftRepo() {
|
|
3041
|
-
return { capabilities:
|
|
3865
|
+
return { capabilities: CAPABILITIES9, create: (context) => createSourceCraftRepoAdapter(context) };
|
|
3042
3866
|
}
|
|
3043
3867
|
function createSourceCraftRepoAdapter({ connection, fetch }) {
|
|
3044
3868
|
const target = requireTarget(connection.target, "org/repo \u0440\u0435\u043F\u043E\u0437\u0438\u0442\u043E\u0440\u0438\u044F SourceCraft");
|
|
3045
|
-
if (!
|
|
3869
|
+
if (!TARGET15.test(target)) throw new TrackerError("invalid_request", "target SourceCraft \u2014 org/repo.");
|
|
3046
3870
|
const api = baseUrl(connection.url, DEFAULT_API7);
|
|
3047
3871
|
const origin = new URL(api).origin;
|
|
3048
3872
|
const repo = `${api}/repos/${target}`;
|
|
3049
3873
|
const headers = { authorization: `Bearer ${connection.token ?? ""}` };
|
|
3050
3874
|
const missing = { failure: "not_found", message: `\u0412 SourceCraft \u043D\u0435\u0442 \u0440\u0435\u043F\u043E\u0437\u0438\u0442\u043E\u0440\u0438\u044F ${target}.` };
|
|
3051
3875
|
return {
|
|
3052
|
-
get: async () =>
|
|
3876
|
+
get: async () => repoOf4((await requestJson(repo, { fetch, origin, headers, missing })).body, target),
|
|
3053
3877
|
branches: async (query) => {
|
|
3054
|
-
assertListQuery(
|
|
3055
|
-
const params = new URLSearchParams({ page_size: String(Math.min(query.limit,
|
|
3878
|
+
assertListQuery(BRANCHES_SUBJECT4, CAPABILITIES9.branches, query, BRANCH_FILTERS4);
|
|
3879
|
+
const params = new URLSearchParams({ page_size: String(Math.min(query.limit, PAGE_SIZE_MAX5)) });
|
|
3056
3880
|
if (query.cursor !== void 0) params.set("page_token", query.cursor);
|
|
3057
3881
|
if (query.search !== void 0) params.set("filter", query.search);
|
|
3058
3882
|
const { body } = await requestJson(`${repo}/branches?${params.toString()}`, { fetch, origin, headers, missing });
|
|
3059
3883
|
const record = isRecord(body) ? body : {};
|
|
3060
3884
|
const branches = Array.isArray(record.branches) ? record.branches : [];
|
|
3061
3885
|
const next = text(record.next_page_token);
|
|
3062
|
-
return { items: branches.map(
|
|
3886
|
+
return { items: branches.map(branchOf4), ...next === void 0 ? {} : { nextCursor: next } };
|
|
3063
3887
|
}
|
|
3064
3888
|
};
|
|
3065
3889
|
}
|
|
3066
|
-
function
|
|
3890
|
+
function repoOf4(raw, target) {
|
|
3067
3891
|
const item = isRecord(raw) ? raw : {};
|
|
3068
3892
|
const defaultBranch = text(item.default_branch);
|
|
3069
3893
|
const description = text(item.description);
|
|
3070
|
-
const visibility =
|
|
3894
|
+
const visibility = visibilityOf4(item.visibility);
|
|
3071
3895
|
const url = text(item.web_url);
|
|
3072
3896
|
return {
|
|
3073
3897
|
name: text(item.slug) ?? text(item.name) ?? target,
|
|
@@ -3077,15 +3901,15 @@ function repoOf3(raw, target) {
|
|
|
3077
3901
|
links: url === void 0 ? [] : [{ url, title: "SourceCraft" }]
|
|
3078
3902
|
};
|
|
3079
3903
|
}
|
|
3080
|
-
function
|
|
3904
|
+
function branchOf4(raw) {
|
|
3081
3905
|
const item = isRecord(raw) ? raw : {};
|
|
3082
3906
|
const sha = isRecord(item.commit) ? text(item.commit.hash) : void 0;
|
|
3083
3907
|
return {
|
|
3084
3908
|
name: text(item.name) ?? "?",
|
|
3085
|
-
...sha === void 0 || !
|
|
3909
|
+
...sha === void 0 || !SHA10.test(sha) ? {} : { sha }
|
|
3086
3910
|
};
|
|
3087
3911
|
}
|
|
3088
|
-
function
|
|
3912
|
+
function visibilityOf4(value) {
|
|
3089
3913
|
const parsed = repoVisibilitySchema.safeParse(value);
|
|
3090
3914
|
return parsed.success ? parsed.data : void 0;
|
|
3091
3915
|
}
|
|
@@ -3093,7 +3917,7 @@ function visibilityOf3(value) {
|
|
|
3093
3917
|
// src/tracker/sourcecraft.lib.ts
|
|
3094
3918
|
var DEFAULT_API8 = "https://api.sourcecraft.tech";
|
|
3095
3919
|
var DEFAULT_WEB = "https://sourcecraft.dev";
|
|
3096
|
-
var
|
|
3920
|
+
var TARGET16 = /^[\w.-]+\/[\w.-]+$/;
|
|
3097
3921
|
var SLUG2 = /^[\w-]{1,100}$/;
|
|
3098
3922
|
var ISSUE_SORT_FIELDS_UPSTREAM = {
|
|
3099
3923
|
created: "created_at",
|
|
@@ -3127,7 +3951,7 @@ function sourcecraftTracker() {
|
|
|
3127
3951
|
}
|
|
3128
3952
|
function createSourceCraftAdapter({ connection, fetch }) {
|
|
3129
3953
|
const target = requireTarget(connection.target, "org/repo \u0440\u0435\u043F\u043E\u0437\u0438\u0442\u043E\u0440\u0438\u044F SourceCraft");
|
|
3130
|
-
if (!
|
|
3954
|
+
if (!TARGET16.test(target)) throw new TrackerError("invalid_request", "target SourceCraft \u2014 org/repo.");
|
|
3131
3955
|
const api = baseUrl(connection.url, DEFAULT_API8);
|
|
3132
3956
|
const origin = new URL(api).origin;
|
|
3133
3957
|
const root = `${api}/repos/${target}/issues`;
|
|
@@ -3137,7 +3961,7 @@ function createSourceCraftAdapter({ connection, fetch }) {
|
|
|
3137
3961
|
if (!SLUG2.test(key)) throw new TrackerError("unknown_issue", `\u0412 SourceCraft \u043D\u0435\u0442 \u0437\u0430\u0434\u0430\u0447\u0438 ${key}.`);
|
|
3138
3962
|
return key;
|
|
3139
3963
|
};
|
|
3140
|
-
const toIssue2 = (raw) =>
|
|
3964
|
+
const toIssue2 = (raw) => issueOf5(raw, web);
|
|
3141
3965
|
return {
|
|
3142
3966
|
list: async (query) => {
|
|
3143
3967
|
assertListQuery("\u0417\u0430\u0434\u0430\u0447\u0438 SourceCraft", ISSUE_CAPABILITIES4.list, query, ISSUE_FILTERS);
|
|
@@ -3168,9 +3992,9 @@ function createSourceCraftAdapter({ connection, fetch }) {
|
|
|
3168
3992
|
const record = isRecord(body) ? body : {};
|
|
3169
3993
|
const rawComments = Array.isArray(record.issue_comments) ? record.issue_comments : [];
|
|
3170
3994
|
const filtered = query.updatedAfter === void 0 ? rawComments : rawComments.filter((raw) => inTimeRange(toTimestamp(isRecord(raw) ? raw.updated_at : void 0), query.updatedAfter, void 0));
|
|
3171
|
-
return { items: filtered.map(
|
|
3995
|
+
return { items: filtered.map(commentOf9), ...nextOf4(record.next_page_token) };
|
|
3172
3996
|
},
|
|
3173
|
-
comment: async (key, body) =>
|
|
3997
|
+
comment: async (key, body) => commentOf9((await requestJson(`${root}/${slug(key)}/comments`, { fetch, origin, headers, method: "POST", body: { body }, missingIsIssue: true })).body)
|
|
3174
3998
|
};
|
|
3175
3999
|
}
|
|
3176
4000
|
function patchBody5(patch) {
|
|
@@ -3206,7 +4030,7 @@ function issueFilterOf(query) {
|
|
|
3206
4030
|
if (query.updatedBefore !== void 0) clauses.push(`updated_at<=${quoted(isoTime(query.updatedBefore))}`);
|
|
3207
4031
|
return clauses.length === 0 ? void 0 : clauses.join(" and ");
|
|
3208
4032
|
}
|
|
3209
|
-
function
|
|
4033
|
+
function issueOf5(raw, web) {
|
|
3210
4034
|
const item = isRecord(raw) ? raw : {};
|
|
3211
4035
|
const status = isRecord(item.status) ? item.status : {};
|
|
3212
4036
|
const slug = text(item.slug) ?? "?";
|
|
@@ -3230,7 +4054,7 @@ function issueOf4(raw, web) {
|
|
|
3230
4054
|
...updatedAt === void 0 ? {} : { updatedAt }
|
|
3231
4055
|
};
|
|
3232
4056
|
}
|
|
3233
|
-
function
|
|
4057
|
+
function commentOf9(raw) {
|
|
3234
4058
|
const item = isRecord(raw) ? raw : {};
|
|
3235
4059
|
const author = isRecord(item.author) ? text(item.author.slug) : void 0;
|
|
3236
4060
|
const createdAt = toTimestamp(item.created_at);
|
|
@@ -3242,7 +4066,7 @@ var registered = false;
|
|
|
3242
4066
|
function registerBuiltinTrackers() {
|
|
3243
4067
|
if (registered) return;
|
|
3244
4068
|
registered = true;
|
|
3245
|
-
for (const definition of [localTracker(), sourcecraftTracker(), githubTracker(), gitlabTracker(), jiraTracker()]) registerTracker(definition);
|
|
4069
|
+
for (const definition of [localTracker(), sourcecraftTracker(), githubTracker(), gitlabTracker(), jiraTracker(), gitverseTracker()]) registerTracker(definition);
|
|
3246
4070
|
}
|
|
3247
4071
|
|
|
3248
4072
|
// src/tracker/secrets.lib.ts
|
|
@@ -3326,7 +4150,7 @@ var TRACKER_CONFIG_MAX_BYTES = 256 * 1024;
|
|
|
3326
4150
|
var TRACKER_CONFIG_ISSUES_MAX = 100;
|
|
3327
4151
|
var TRACKER_CONFIG_YAML_ALIAS_MAX = 100;
|
|
3328
4152
|
var TRACKER_CONFIG_DEPTH_MAX = 16;
|
|
3329
|
-
var BUILTIN_TRACKER_KINDS = ["local", "sourcecraft", "github", "gitlab", "jira"];
|
|
4153
|
+
var BUILTIN_TRACKER_KINDS = ["local", "sourcecraft", "github", "gitlab", "jira", "gitverse"];
|
|
3330
4154
|
|
|
3331
4155
|
// src/tracker/declarative/declarative.schema.ts
|
|
3332
4156
|
import { z as z4 } from "zod";
|
|
@@ -4565,7 +5389,7 @@ function parseConfigInput(input) {
|
|
|
4565
5389
|
|
|
4566
5390
|
// src/tracker/declarative/declarative-pull.lib.ts
|
|
4567
5391
|
var MERGE_CONFLICT = [405, 409, 422];
|
|
4568
|
-
function
|
|
5392
|
+
function createPullAdapter3(config, adapterContext, capabilities) {
|
|
4569
5393
|
const context = contextOf(config, adapterContext);
|
|
4570
5394
|
const subject = `PR \xAB${config.title}\xBB`;
|
|
4571
5395
|
const missing = (key) => ({ missing: { failure: "not_found", message: `\u0412 \u0442\u0440\u0435\u043A\u0435\u0440\u0435 \xAB${config.title}\xBB \u043D\u0435\u0442 PR ${key}.` } });
|
|
@@ -4893,7 +5717,7 @@ function definitionFromConfig(input) {
|
|
|
4893
5717
|
},
|
|
4894
5718
|
create: (context) => createIssuesAdapter(config, context, issues, features),
|
|
4895
5719
|
issues,
|
|
4896
|
-
...pulls === void 0 ? {} : { pulls: { capabilities: pulls, create: (context) =>
|
|
5720
|
+
...pulls === void 0 ? {} : { pulls: { capabilities: pulls, create: (context) => createPullAdapter3(config, context, pulls) } },
|
|
4897
5721
|
...ci === void 0 ? {} : { ci: { capabilities: ci, create: (context) => createCiAdapter(config, context, ci) } },
|
|
4898
5722
|
origin: (connection) => baseOf(config, connection).origin
|
|
4899
5723
|
};
|
|
@@ -5230,6 +6054,17 @@ export {
|
|
|
5230
6054
|
GITLAB_MERGE_REQUEST_STATES,
|
|
5231
6055
|
GITLAB_PIPELINE_SOURCES,
|
|
5232
6056
|
GITLAB_PRIORITY_LABELS,
|
|
6057
|
+
GITVERSE_ACCEPT,
|
|
6058
|
+
GITVERSE_API,
|
|
6059
|
+
GITVERSE_CI_STATUSES,
|
|
6060
|
+
GITVERSE_DONE_COLUMN,
|
|
6061
|
+
GITVERSE_ISSUE_STATES,
|
|
6062
|
+
GITVERSE_ISSUE_STATE_NAMES,
|
|
6063
|
+
GITVERSE_PULL_STATES,
|
|
6064
|
+
GITVERSE_REMOTE_HOSTS,
|
|
6065
|
+
GITVERSE_RUN_EVENTS,
|
|
6066
|
+
GITVERSE_TOKEN_ENV,
|
|
6067
|
+
GITVERSE_WEB,
|
|
5233
6068
|
ISSUE_FILTERS,
|
|
5234
6069
|
ISSUE_SORT_FIELDS,
|
|
5235
6070
|
JIRA_ISSUE_TYPE,
|
|
@@ -5288,6 +6123,10 @@ export {
|
|
|
5288
6123
|
gitlabPulls,
|
|
5289
6124
|
gitlabRepo,
|
|
5290
6125
|
gitlabTracker,
|
|
6126
|
+
gitverseCi,
|
|
6127
|
+
gitversePulls,
|
|
6128
|
+
gitverseRepo,
|
|
6129
|
+
gitverseTracker,
|
|
5291
6130
|
hasTrackerToken,
|
|
5292
6131
|
inTimeRange,
|
|
5293
6132
|
isFinished,
|
|
@@ -5296,6 +6135,7 @@ export {
|
|
|
5296
6135
|
issueCapabilitiesOf,
|
|
5297
6136
|
jiraTracker,
|
|
5298
6137
|
keysFor,
|
|
6138
|
+
linkNextPage,
|
|
5299
6139
|
listTrackers,
|
|
5300
6140
|
localTracker,
|
|
5301
6141
|
logCursor,
|
|
@@ -5304,6 +6144,7 @@ export {
|
|
|
5304
6144
|
lookup,
|
|
5305
6145
|
mergeMethodSchema,
|
|
5306
6146
|
nameOf,
|
|
6147
|
+
nextPageCursor,
|
|
5307
6148
|
priorityName,
|
|
5308
6149
|
pullRequestAdapterOf,
|
|
5309
6150
|
pullRequestFilterSchema,
|