@smwb/onreel-git-mcp 0.10.1 → 0.12.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.
Files changed (41) hide show
  1. package/README.md +147 -15
  2. package/dist/{chunk-3YP22YLA.js → chunk-33ISKIW7.js} +2 -2
  3. package/dist/{chunk-AGGJK2XZ.js → chunk-AJOAZMU4.js} +26 -1
  4. package/dist/{chunk-AGGJK2XZ.js.map → chunk-AJOAZMU4.js.map} +1 -1
  5. package/dist/{chunk-4ZGRXIVA.js → chunk-D5QUOIRC.js} +5 -1
  6. package/dist/{chunk-4ZGRXIVA.js.map → chunk-D5QUOIRC.js.map} +1 -1
  7. package/dist/{chunk-ZTME4HFD.js → chunk-OWLVTLYZ.js} +3 -3
  8. package/dist/contract/contract.schema.d.ts +12 -0
  9. package/dist/contract/contract.types.d.ts +2 -1
  10. package/dist/files/index.js +1 -1
  11. package/dist/git/index.d.ts +1 -1
  12. package/dist/git/index.js +7 -5
  13. package/dist/index.js +6 -3
  14. package/dist/index.js.map +1 -1
  15. package/dist/kernel/log.types.d.ts +4 -1
  16. package/dist/kernel/redact.lib.d.ts +12 -2
  17. package/dist/mcp/index.js +3 -3
  18. package/dist/tracker/declarative/declarative-call.lib.d.ts +28 -0
  19. package/dist/tracker/declarative/declarative-capabilities.lib.d.ts +20 -0
  20. package/dist/tracker/declarative/declarative-ci.lib.d.ts +4 -0
  21. package/dist/tracker/declarative/declarative-hint.const.d.ts +4 -0
  22. package/dist/tracker/declarative/declarative-issues.lib.d.ts +5 -0
  23. package/dist/tracker/declarative/declarative-model.const.d.ts +40 -0
  24. package/dist/tracker/declarative/declarative-model.types.d.ts +87 -0
  25. package/dist/tracker/declarative/declarative-parse.lib.d.ts +7 -0
  26. package/dist/tracker/declarative/declarative-pull.lib.d.ts +4 -0
  27. package/dist/tracker/declarative/declarative-request.lib.d.ts +49 -0
  28. package/dist/tracker/declarative/declarative-result.lib.d.ts +11 -0
  29. package/dist/tracker/declarative/declarative-rules.lib.d.ts +4 -0
  30. package/dist/tracker/declarative/declarative.const.d.ts +10 -0
  31. package/dist/tracker/declarative/declarative.lib.d.ts +19 -0
  32. package/dist/tracker/declarative/declarative.schema.d.ts +1324 -0
  33. package/dist/tracker/declarative/declarative.types.d.ts +22 -0
  34. package/dist/tracker/index.d.ts +6 -0
  35. package/dist/tracker/index.js +1941 -22
  36. package/dist/tracker/index.js.map +1 -1
  37. package/dist/tracker/registry.lib.d.ts +8 -1
  38. package/dist/worktree/index.js +4 -4
  39. package/package.json +2 -1
  40. /package/dist/{chunk-3YP22YLA.js.map → chunk-33ISKIW7.js.map} +0 -0
  41. /package/dist/{chunk-ZTME4HFD.js.map → chunk-OWLVTLYZ.js.map} +0 -0
@@ -1,12 +1,20 @@
1
1
  import {
2
2
  REDACTED,
3
3
  defaultSecretSink,
4
- redactSecretText
5
- } from "../chunk-AGGJK2XZ.js";
4
+ isSecretKey,
5
+ redactSecretText,
6
+ setSecretSink
7
+ } from "../chunk-AJOAZMU4.js";
6
8
  import {
9
+ issueCommentSchema,
7
10
  issueLinkSchema,
8
- timestampSchema
9
- } from "../chunk-4ZGRXIVA.js";
11
+ issuePrioritySchema,
12
+ issueSchema,
13
+ issueStatusCategorySchema,
14
+ timestampSchema,
15
+ trackerFieldNameSchema,
16
+ trackerKindSchema
17
+ } from "../chunk-D5QUOIRC.js";
10
18
 
11
19
  // src/tracker/tracker.const.ts
12
20
  var TRACKER_TIMEOUT_MS = 15e3;
@@ -960,8 +968,8 @@ function pageOf(cursor) {
960
968
  const page = cursor === void 0 ? 1 : Number(cursor);
961
969
  return Number.isInteger(page) && page >= 1 ? page : 1;
962
970
  }
963
- function nextCursorOf(page, link) {
964
- return /rel="next"/.test(link) ? { nextCursor: String(page + 1) } : {};
971
+ function nextCursorOf(page, link2) {
972
+ return /rel="next"/.test(link2) ? { nextCursor: String(page + 1) } : {};
965
973
  }
966
974
  function rowsOf(body, field) {
967
975
  const rows = isRecord(body) ? body[field] : void 0;
@@ -1584,16 +1592,27 @@ function concat(head, tail) {
1584
1592
 
1585
1593
  // src/tracker/registry.lib.ts
1586
1594
  var definitions = /* @__PURE__ */ new Map();
1595
+ var userDefinitions = /* @__PURE__ */ new Map();
1587
1596
  function registerTracker(definition) {
1588
1597
  const kind = definition.descriptor.tracker;
1589
1598
  if (definitions.has(kind)) throw new Error(`\u0422\u0440\u0435\u043A\u0435\u0440 ${kind} \u0443\u0436\u0435 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043E\u0432\u0430\u043D.`);
1590
1599
  definitions.set(kind, definition);
1591
1600
  }
1601
+ function setUserTrackers(next) {
1602
+ const replacement = /* @__PURE__ */ new Map();
1603
+ for (const definition of next) {
1604
+ const kind = definition.descriptor.tracker;
1605
+ if (replacement.has(kind)) throw new Error(`\u0421\u0432\u043E\u0439 \u0442\u0440\u0435\u043A\u0435\u0440 ${kind} \u043F\u043E\u0432\u0442\u043E\u0440\u044F\u0435\u0442\u0441\u044F \u0432 \u043D\u0430\u0431\u043E\u0440\u0435.`);
1606
+ replacement.set(kind, definition);
1607
+ }
1608
+ userDefinitions = replacement;
1609
+ return [...replacement.keys()].filter((kind) => definitions.has(kind));
1610
+ }
1592
1611
  function findTracker(kind) {
1593
- return definitions.get(kind);
1612
+ return definitions.get(kind) ?? userDefinitions.get(kind);
1594
1613
  }
1595
1614
  function listTrackers() {
1596
- return [...definitions.values()];
1615
+ return [...definitions.values(), ...[...userDefinitions.values()].filter((definition) => !definitions.has(definition.descriptor.tracker))];
1597
1616
  }
1598
1617
 
1599
1618
  // src/tracker/pull.schema.ts
@@ -1720,8 +1739,8 @@ function pageOf3(cursor) {
1720
1739
  const page = cursor === void 0 ? 1 : Number(cursor);
1721
1740
  return Number.isInteger(page) && page >= 1 ? page : 1;
1722
1741
  }
1723
- function nextOf(link, page) {
1724
- return link !== null && /rel="next"/.test(link) ? { nextCursor: String(page + 1) } : {};
1742
+ function nextOf(link2, page) {
1743
+ return link2 !== null && /rel="next"/.test(link2) ? { nextCursor: String(page + 1) } : {};
1725
1744
  }
1726
1745
  function stateFilter(status) {
1727
1746
  if (status === void 0) return "all";
@@ -1882,8 +1901,8 @@ function pageOf4(cursor) {
1882
1901
  const page = cursor === void 0 ? 1 : Number(cursor);
1883
1902
  return Number.isInteger(page) && page >= 1 ? page : 1;
1884
1903
  }
1885
- function nextOf2(link, page) {
1886
- return link !== null && /rel="next"/.test(link) ? { nextCursor: String(page + 1) } : {};
1904
+ function nextOf2(link2, page) {
1905
+ return link2 !== null && /rel="next"/.test(link2) ? { nextCursor: String(page + 1) } : {};
1887
1906
  }
1888
1907
  function repoOf(raw, target) {
1889
1908
  const item = isRecord(raw) ? raw : {};
@@ -2064,11 +2083,11 @@ function searchStateFilter(status) {
2064
2083
  if (status.every((item) => item === "done" || item === "declined")) return "is:closed";
2065
2084
  return void 0;
2066
2085
  }
2067
- function issuePageOf(rows, query, link, page) {
2086
+ function issuePageOf(rows, query, link2, page) {
2068
2087
  const items = rows.filter((row) => isRecord(row) && row.pull_request === void 0).map(issueOf);
2069
2088
  return {
2070
2089
  items: query.status === void 0 ? items : items.filter((issue) => query.status?.includes(issue.status.category) === true),
2071
- .../rel="next"/.test(link) ? { nextCursor: String(page + 1) } : {}
2090
+ .../rel="next"/.test(link2) ? { nextCursor: String(page + 1) } : {}
2072
2091
  };
2073
2092
  }
2074
2093
  function composeLabels(plain, priority, status) {
@@ -2684,8 +2703,8 @@ function fieldsOf(patch) {
2684
2703
  async function transition(api, key, category, request) {
2685
2704
  const { fetch, origin, headers } = request;
2686
2705
  const { body } = await requestJson(`${api}/issue/${key}/transitions`, { fetch, origin, headers, missingIsIssue: true });
2687
- const list = isRecord(body) && Array.isArray(body.transitions) ? body.transitions : [];
2688
- const match = list.find((item) => {
2706
+ const list2 = isRecord(body) && Array.isArray(body.transitions) ? body.transitions : [];
2707
+ const match = list2.find((item) => {
2689
2708
  if (!isRecord(item) || !isRecord(item.to) || !isRecord(item.to.statusCategory)) return false;
2690
2709
  return lookup(JIRA_STATUS_CATEGORIES, item.to.statusCategory.key, void 0) === category;
2691
2710
  });
@@ -2904,10 +2923,10 @@ function createPullAdapter({ connection, fetch }) {
2904
2923
  },
2905
2924
  missing: missing(key)
2906
2925
  });
2907
- const operation = isRecord(body) ? body : {};
2908
- if (operation.status === "failed" || operation.status === "cancel") {
2909
- const errorMessage = isRecord(operation.error) ? text(operation.error.message) : void 0;
2910
- throw new TrackerError("conflict", `\u0421\u043B\u0438\u044F\u043D\u0438\u0435 PR ${key} \u043D\u0435 \u0437\u0430\u043F\u0443\u0449\u0435\u043D\u043E: ${redactSecretText(errorMessage ?? String(operation.status))}.`);
2926
+ const operation2 = isRecord(body) ? body : {};
2927
+ if (operation2.status === "failed" || operation2.status === "cancel") {
2928
+ const errorMessage = isRecord(operation2.error) ? text(operation2.error.message) : void 0;
2929
+ throw new TrackerError("conflict", `\u0421\u043B\u0438\u044F\u043D\u0438\u0435 PR ${key} \u043D\u0435 \u0437\u0430\u043F\u0443\u0449\u0435\u043D\u043E: ${redactSecretText(errorMessage ?? String(operation2.status))}.`);
2911
2930
  }
2912
2931
  return getPull(key);
2913
2932
  },
@@ -2983,12 +3002,12 @@ function pullOf3(raw) {
2983
3002
  const mergedAt = toTimestamp(item.merged_at);
2984
3003
  const closedAt = toTimestamp(item.closed_at);
2985
3004
  const key = text(item.slug) ?? "?";
2986
- const statusName = text(item.status) ?? "open";
3005
+ const statusName2 = text(item.status) ?? "open";
2987
3006
  return {
2988
3007
  key,
2989
3008
  title: text(item.title) ?? key,
2990
3009
  ...description === void 0 ? {} : { description },
2991
- status: { category: lookup(SOURCECRAFT_PULL_STATUSES, statusName, "open"), name: statusName },
3010
+ status: { category: lookup(SOURCECRAFT_PULL_STATUSES, statusName2, "open"), name: statusName2 },
2992
3011
  ...author === void 0 ? {} : { author },
2993
3012
  source: text(source.ref) ?? text(item.source_branch) ?? "?",
2994
3013
  target: text(target.ref) ?? text(item.target_branch) ?? "?",
@@ -3286,8 +3305,1896 @@ function repoAdapterOf(definition, context) {
3286
3305
  if (definition.repo === void 0) throw new TrackerError("unsupported", `\u0422\u0440\u0435\u043A\u0435\u0440 ${definition.descriptor.title} \u043D\u0435 \u0432\u0435\u0434\u0451\u0442 \u0440\u0435\u043F\u043E\u0437\u0438\u0442\u043E\u0440\u0438\u0439.`);
3287
3306
  return definition.repo.create(context);
3288
3307
  }
3308
+
3309
+ // src/tracker/declarative/declarative.const.ts
3310
+ var TRACKER_CONFIG_MAX_BYTES = 256 * 1024;
3311
+ var TRACKER_CONFIG_ISSUES_MAX = 100;
3312
+ var TRACKER_CONFIG_YAML_ALIAS_MAX = 100;
3313
+ var TRACKER_CONFIG_DEPTH_MAX = 16;
3314
+ var BUILTIN_TRACKER_KINDS = ["local", "sourcecraft", "github", "gitlab", "jira"];
3315
+
3316
+ // src/tracker/declarative/declarative.schema.ts
3317
+ import { z as z4 } from "zod";
3318
+ var templateSchema = z4.string().max(2e3);
3319
+ var trackerConfigJsonPathSchema = z4.string().max(300).regex(/^\$(?:\.[A-Za-z_][\w-]*|\[(?:\d{1,4}|\*)\])*$/, "\u043F\u0443\u0442\u044C JSON \u0432\u0438\u0434\u0430 $.a.b, $.items[0] \u0438\u043B\u0438 $.items[*].name");
3320
+ var paramNameSchema = z4.string().regex(/^[A-Za-z0-9_][\w.\-[\]]{0,99}$/, "\u0438\u043C\u044F \u043F\u0430\u0440\u0430\u043C\u0435\u0442\u0440\u0430: \u043B\u0430\u0442\u0438\u043D\u0438\u0446\u0430, \u0446\u0438\u0444\u0440\u044B, \xAB_\xBB, \xAB.\xBB, \xAB-\xBB, \xAB[\xBB, \xAB]\xBB");
3321
+ var headerNameSchema = z4.string().regex(/^[A-Za-z][A-Za-z0-9-]{0,99}$/, "\u0438\u043C\u044F \u0437\u0430\u0433\u043E\u043B\u043E\u0432\u043A\u0430 HTTP: \u043B\u0430\u0442\u0438\u043D\u0438\u0446\u0430, \u0446\u0438\u0444\u0440\u044B \u0438 \xAB-\xBB");
3322
+ var valueItemSchema = z4.union([
3323
+ trackerConfigJsonPathSchema,
3324
+ z4.strictObject({
3325
+ path: trackerConfigJsonPathSchema,
3326
+ /** Значение ответа → значение единой модели. */
3327
+ map: z4.record(z4.string().max(200), z4.union([z4.string().max(200), z4.boolean()])).optional(),
3328
+ /** Значение, когда по пути ничего нет или значения нет в map. */
3329
+ default: z4.union([z4.string().max(200), z4.number(), z4.boolean()]).optional(),
3330
+ /** Поле единой модели — флаг: есть ли значение по пути. */
3331
+ exists: z4.literal(true).optional()
3332
+ })
3333
+ ]);
3334
+ var trackerConfigValueSchema = z4.union([valueItemSchema, z4.array(valueItemSchema).min(1).max(5)]);
3335
+ var bodyValueSchema = z4.lazy(
3336
+ () => z4.union([templateSchema, z4.number(), z4.boolean(), z4.null(), z4.array(bodyValueSchema).max(100), z4.record(paramNameSchema, bodyValueSchema)])
3337
+ );
3338
+ var trackerConfigPaginationSchema = z4.discriminatedUnion("style", [
3339
+ z4.strictObject({
3340
+ style: z4.literal("page"),
3341
+ /** Параметр номера страницы (с 1) и размера. */
3342
+ page: paramNameSchema,
3343
+ size: paramNameSchema,
3344
+ /** Есть ли следующая: заголовок Link с rel="next", полная страница, свой заголовок или путь JSON с номером. */
3345
+ next: z4.union([z4.enum(["link", "count"]), z4.strictObject({ header: headerNameSchema }), z4.strictObject({ path: trackerConfigJsonPathSchema })])
3346
+ }),
3347
+ z4.strictObject({
3348
+ style: z4.literal("cursor"),
3349
+ /** Параметр курсора и размера страницы. */
3350
+ param: paramNameSchema,
3351
+ size: paramNameSchema.optional(),
3352
+ /** Курсор следующей страницы: путь JSON в ответе или заголовок. */
3353
+ next: z4.union([trackerConfigJsonPathSchema, z4.strictObject({ header: headerNameSchema })])
3354
+ }),
3355
+ z4.strictObject({ style: z4.literal("none") })
3356
+ ]);
3357
+ var trackerConfigOperationSchema = z4.strictObject({
3358
+ method: z4.enum(["GET", "POST", "PUT", "PATCH"]).default("GET"),
3359
+ /** Путь от http.base: начинается с «/», адрес остаётся на origin базы. */
3360
+ path: templateSchema,
3361
+ query: z4.record(paramNameSchema, z4.union([templateSchema, z4.number(), z4.boolean()])).optional(),
3362
+ body: z4.record(paramNameSchema, bodyValueSchema).optional(),
3363
+ /** Таблицы значений входов: вход → (значение единой модели → значение API). */
3364
+ inputs: z4.record(z4.string().max(50), z4.record(z4.string().max(50), z4.string().max(200))).optional(),
3365
+ /** Где в ответе элемент или список элементов; нет — сам ответ. */
3366
+ items: trackerConfigJsonPathSchema.optional(),
3367
+ /** Поле единой модели → откуда взять значение в элементе ответа. */
3368
+ result: z4.record(z4.string().max(100), trackerConfigValueSchema).optional(),
3369
+ /** Своя постраничность списка вместо http.pagination. */
3370
+ pagination: trackerConfigPaginationSchema.optional()
3371
+ });
3372
+ var trackerConfigAuthSchema = z4.discriminatedUnion("kind", [
3373
+ /** `Authorization: Bearer <токен>`. */
3374
+ z4.strictObject({ kind: z4.literal("bearer") }),
3375
+ /** Свой заголовок: `<header>: <prefix><токен>`. */
3376
+ z4.strictObject({
3377
+ kind: z4.literal("header"),
3378
+ header: headerNameSchema,
3379
+ prefix: z4.string().max(50).regex(/^[^\r\n\0]*$/, "\u043F\u0440\u0435\u0444\u0438\u043A\u0441 \u0431\u0435\u0437 \u043F\u0435\u0440\u0435\u0432\u043E\u0434\u0430 \u0441\u0442\u0440\u043E\u043A\u0438").optional()
3380
+ }),
3381
+ /** `Authorization: Basic` из полей user и token. */
3382
+ z4.strictObject({ kind: z4.literal("basic") }),
3383
+ z4.strictObject({ kind: z4.literal("none") })
3384
+ ]);
3385
+ var trackerConfigFieldSchema = z4.strictObject({ name: trackerFieldNameSchema, required: z4.boolean(), secret: z4.boolean() });
3386
+ var operation = trackerConfigOperationSchema;
3387
+ var trackerConfigIssuesSchema = z4.strictObject({
3388
+ list: operation,
3389
+ get: operation,
3390
+ create: operation.optional(),
3391
+ update: operation.optional(),
3392
+ comments: operation.optional(),
3393
+ comment: operation.optional()
3394
+ });
3395
+ var trackerConfigPullsSchema = z4.strictObject({
3396
+ list: operation,
3397
+ get: operation,
3398
+ create: operation.optional(),
3399
+ update: operation.optional(),
3400
+ merge: operation.optional(),
3401
+ comments: operation.optional(),
3402
+ comment: operation.optional()
3403
+ });
3404
+ var trackerConfigCiSchema = z4.strictObject({
3405
+ workflows: operation.optional(),
3406
+ runs: operation,
3407
+ run: operation,
3408
+ jobs: operation.optional(),
3409
+ job: operation.optional(),
3410
+ log: operation.optional(),
3411
+ trigger: operation.optional(),
3412
+ rerun: operation.optional(),
3413
+ rerunFailed: operation.optional(),
3414
+ rerunJob: operation.optional(),
3415
+ cancel: operation.optional(),
3416
+ cancelJob: operation.optional()
3417
+ });
3418
+ var trackerConfigSchema = z4.strictObject({
3419
+ format: z4.literal(1),
3420
+ kind: trackerKindSchema,
3421
+ title: z4.string().min(1).max(100),
3422
+ fields: z4.array(trackerConfigFieldSchema).max(4),
3423
+ http: z4.strictObject({
3424
+ /** Адрес API: `https://…` или `{{url}}/…`; origin базы — единственный, куда уходит токен. */
3425
+ base: templateSchema,
3426
+ auth: trackerConfigAuthSchema,
3427
+ /** Постоянные заголовки (Accept, версия API); секретных среди них нет. */
3428
+ headers: z4.record(headerNameSchema, templateSchema).optional(),
3429
+ pagination: trackerConfigPaginationSchema.default({ style: "none" })
3430
+ }),
3431
+ issues: trackerConfigIssuesSchema.optional(),
3432
+ pulls: trackerConfigPullsSchema.optional(),
3433
+ ci: trackerConfigCiSchema.optional()
3434
+ });
3435
+
3436
+ // src/tracker/declarative/declarative.lib.ts
3437
+ import { z as z5 } from "zod";
3438
+
3439
+ // src/tracker/declarative/declarative-model.const.ts
3440
+ var PLACEHOLDER = /\{\{\s*([A-Za-z][A-Za-z0-9]*)\s*(?:\|\s*([A-Za-z]+)\s*)?\}\}/g;
3441
+ var CONNECTION_PLACEHOLDERS = ["url", "target", "user"];
3442
+ var RESERVED_HEADERS = ["host", "content-length", "content-type", "transfer-encoding", "connection", "accept-encoding", "te", "upgrade", "trailer"];
3443
+ var FORBIDDEN_KEYS = ["__proto__", "constructor", "prototype"];
3444
+ var SECRET_IN_CONFIG = "\u043F\u043E\u0445\u043E\u0436\u0435 \u043D\u0430 \u0441\u0435\u043A\u0440\u0435\u0442: \u0442\u043E\u043A\u0435\u043D \u043D\u0435 \u043F\u0438\u0448\u0443\u0442 \u0432 \u043A\u043E\u043D\u0444\u0438\u0433 \u2014 \u0435\u0433\u043E \u0432\u0432\u043E\u0434\u044F\u0442 \u0432 \u043F\u043E\u0434\u043A\u043B\u044E\u0447\u0435\u043D\u0438\u0438 \u043F\u0440\u043E\u0435\u043A\u0442\u0430, \u0430 \u043F\u043E\u0434\u0441\u0442\u0430\u0432\u043B\u044F\u0435\u0442 \u0442\u043E\u043B\u044C\u043A\u043E http.auth";
3445
+ var INPUT_ANY = "*";
3446
+ var INPUT_NULL = "null";
3447
+ var time = ["createdAfter", "createdBefore", "updatedAfter", "updatedBefore"];
3448
+ var sorting = ["sort", "direction"];
3449
+ var OPERATIONS = {
3450
+ issues: {
3451
+ list: { inputs: ["status", "labels", "assignee", "author", "search", ...time, ...sorting], required: [], model: "issue", list: true, result: "required" },
3452
+ get: { inputs: ["key"], required: ["key"], model: "issue", result: "required" },
3453
+ create: { inputs: ["title", "description", "priority", "labels", "assignee"], required: ["title"], model: "issue", result: "required" },
3454
+ update: { inputs: ["key", "title", "description", "status", "priority", "labels", "assignee"], required: ["key"], model: "issue", result: "optional" },
3455
+ comments: { inputs: ["key", "updatedAfter", "order"], required: ["key"], model: "comment", list: true, result: "required" },
3456
+ comment: { inputs: ["key", "body"], required: ["key", "body"], model: "comment", result: "required" }
3457
+ },
3458
+ pulls: {
3459
+ list: { inputs: ["status", "author", "sourceBranch", "targetBranch", "labels", "search", ...time, ...sorting], required: [], model: "pull", list: true, result: "required" },
3460
+ get: { inputs: ["key"], required: ["key"], model: "pull", result: "required" },
3461
+ create: { inputs: ["title", "sourceBranch", "targetBranch", "description", "draft"], required: ["title", "sourceBranch", "targetBranch"], model: "pull", result: "required" },
3462
+ update: { inputs: ["key", "title", "description", "targetBranch", "status"], required: ["key"], model: "pull", result: "optional" },
3463
+ merge: { inputs: ["key", "method", "headSha", "message", "deleteSource"], required: ["key"], result: "forbidden" },
3464
+ comments: { inputs: ["key", "updatedAfter", "order"], required: ["key"], model: "comment", list: true, result: "required" },
3465
+ comment: { inputs: ["key", "body"], required: ["key", "body"], model: "comment", result: "required" }
3466
+ },
3467
+ ci: {
3468
+ workflows: { inputs: [], required: [], model: "workflow", list: true, result: "required" },
3469
+ runs: { inputs: ["status", "ref", "sha", "event", "workflow", "actor", "pullRequest", ...time, ...sorting], required: [], model: "run", list: true, result: "required" },
3470
+ run: { inputs: ["key"], required: ["key"], model: "run", result: "required" },
3471
+ jobs: { inputs: ["run", "status", "allAttempts"], required: ["run"], model: "job", list: true, result: "required" },
3472
+ job: { inputs: ["key"], required: ["key"], model: "job", result: "required" },
3473
+ log: { inputs: ["key"], required: ["key"], result: "forbidden", text: true },
3474
+ trigger: { inputs: ["ref", "refType", "workflow", "workflows", "inputs"], required: ["ref"], model: "run", result: "optional" },
3475
+ rerun: { inputs: ["key", "debug"], required: ["key"], result: "forbidden" },
3476
+ rerunFailed: { inputs: ["key", "debug"], required: ["key"], result: "forbidden" },
3477
+ rerunJob: { inputs: ["key", "debug"], required: ["key"], result: "forbidden" },
3478
+ cancel: { inputs: ["key"], required: ["key"], result: "forbidden" },
3479
+ cancelJob: { inputs: ["key"], required: ["key"], result: "forbidden" }
3480
+ }
3481
+ };
3482
+ var REQUIRED_OPERATIONS = {
3483
+ issues: ["list", "get"],
3484
+ pulls: ["list", "get"],
3485
+ ci: ["runs", "run"]
3486
+ };
3487
+ var CI_OPERATION_NEEDS = {
3488
+ log: ["job"],
3489
+ rerunJob: ["job"],
3490
+ cancelJob: ["job"]
3491
+ };
3492
+ var BOOLEAN = ["true", "false"];
3493
+ var DIRECTION = ["asc", "desc"];
3494
+ var INPUT_DOMAINS = {
3495
+ issues: {
3496
+ status: issueStatusCategorySchema.options,
3497
+ priority: issuePrioritySchema.options,
3498
+ sort: ISSUE_SORT_FIELDS,
3499
+ direction: DIRECTION,
3500
+ order: DIRECTION,
3501
+ assignee: [INPUT_NULL]
3502
+ },
3503
+ pulls: {
3504
+ status: pullRequestStatusCategorySchema.options,
3505
+ sort: pullRequestSortFieldSchema.options,
3506
+ direction: DIRECTION,
3507
+ order: DIRECTION,
3508
+ method: mergeMethodSchema.options,
3509
+ draft: BOOLEAN,
3510
+ deleteSource: BOOLEAN
3511
+ },
3512
+ ci: {
3513
+ status: ciStatusCategorySchema.options,
3514
+ event: ciEventCategorySchema.options,
3515
+ sort: ciRunSortFieldSchema.options,
3516
+ direction: DIRECTION,
3517
+ refType: ["branch", "tag"],
3518
+ allAttempts: BOOLEAN,
3519
+ debug: BOOLEAN
3520
+ }
3521
+ };
3522
+ var WILDCARD_INPUTS = ["status", "event"];
3523
+ var OBJECT_INPUTS = ["inputs"];
3524
+ var statusName = { type: "text", max: 200 };
3525
+ var ciStatusName = { type: "text", max: 100 };
3526
+ var person = { type: "text", max: 200 };
3527
+ var moment = { type: "time" };
3528
+ var link = { type: "link", max: 2048 };
3529
+ var RESULT_FIELDS = {
3530
+ issue: {
3531
+ key: { type: "id", max: 200, required: true },
3532
+ title: { type: "text", max: 500, required: true },
3533
+ description: { type: "text", max: 1e5 },
3534
+ "status.category": { type: "enum", values: issueStatusCategorySchema.options, required: true },
3535
+ "status.name": statusName,
3536
+ priority: { type: "enum", values: issuePrioritySchema.options },
3537
+ labels: { type: "list", max: 200, count: 100 },
3538
+ assignee: person,
3539
+ url: link,
3540
+ createdAt: moment,
3541
+ updatedAt: moment
3542
+ },
3543
+ comment: {
3544
+ id: { type: "id", max: 200, required: true },
3545
+ author: person,
3546
+ body: { type: "text", max: 1e5, required: true, empty: true },
3547
+ createdAt: moment
3548
+ },
3549
+ pull: {
3550
+ key: { type: "id", max: 200, required: true },
3551
+ title: { type: "text", max: 1024, required: true },
3552
+ description: { type: "text", max: 1048576 },
3553
+ "status.category": { type: "enum", values: pullRequestStatusCategorySchema.options, required: true },
3554
+ "status.name": statusName,
3555
+ merged: { type: "flag" },
3556
+ draft: { type: "flag" },
3557
+ author: person,
3558
+ source: { type: "text", max: 500, required: true },
3559
+ target: { type: "text", max: 500, required: true },
3560
+ headSha: { type: "sha" },
3561
+ labels: { type: "list", max: 200, count: 100 },
3562
+ reviewers: { type: "list", max: 200, count: 100 },
3563
+ url: link,
3564
+ createdAt: moment,
3565
+ updatedAt: moment,
3566
+ mergedAt: moment,
3567
+ closedAt: moment
3568
+ },
3569
+ run: {
3570
+ key: { type: "id", max: 200, required: true },
3571
+ number: { type: "int" },
3572
+ workflows: { type: "list", max: 500, count: 100 },
3573
+ "status.category": { type: "enum", values: ciStatusCategorySchema.options, required: true },
3574
+ "status.name": ciStatusName,
3575
+ "event.category": { type: "enum", values: ciEventCategorySchema.options },
3576
+ "event.name": { type: "text", max: 100 },
3577
+ ref: { type: "text", max: 500 },
3578
+ sha: { type: "sha" },
3579
+ actor: person,
3580
+ pullRequest: { type: "id", max: 200 },
3581
+ attempt: { type: "int", positive: true },
3582
+ errors: { type: "list", max: 4e3, count: 20 },
3583
+ url: link,
3584
+ createdAt: moment,
3585
+ startedAt: moment,
3586
+ finishedAt: moment,
3587
+ updatedAt: moment
3588
+ },
3589
+ job: {
3590
+ key: { type: "id", max: 1e3, required: true },
3591
+ runKey: { type: "id", max: 200 },
3592
+ name: { type: "text", max: 500, required: true },
3593
+ stage: { type: "text", max: 1e3 },
3594
+ "status.category": { type: "enum", values: ciStatusCategorySchema.options, required: true },
3595
+ "status.name": ciStatusName,
3596
+ attempt: { type: "int", positive: true },
3597
+ url: link,
3598
+ createdAt: moment,
3599
+ startedAt: moment,
3600
+ finishedAt: moment
3601
+ },
3602
+ workflow: {
3603
+ key: { type: "id", max: 200, required: true },
3604
+ name: { type: "text", max: 500, required: true },
3605
+ path: { type: "text", max: 1e3 },
3606
+ enabled: { type: "flag" }
3607
+ }
3608
+ };
3609
+ var OPERATION_REQUIRED_FIELDS = {
3610
+ "ci.job": ["runKey"]
3611
+ };
3612
+
3613
+ // src/tracker/declarative/declarative-result.lib.ts
3614
+ var MODEL_SCHEMAS = {
3615
+ issue: issueSchema,
3616
+ comment: issueCommentSchema,
3617
+ pull: pullRequestSchema,
3618
+ run: ciRunSchema,
3619
+ job: ciJobSchema,
3620
+ workflow: ciWorkflowSchema
3621
+ };
3622
+ function stepsOf(path) {
3623
+ const steps = [];
3624
+ const pattern = /\.([A-Za-z_][\w-]*)|\[(\d{1,4})\]|\[\*\]/gy;
3625
+ pattern.lastIndex = 1;
3626
+ for (let match = pattern.exec(path); match !== null; match = pattern.exec(path)) {
3627
+ if (match[1] !== void 0) steps.push({ key: match[1] });
3628
+ else if (match[2] !== void 0) steps.push({ index: Number(match[2]) });
3629
+ else steps.push({ all: true });
3630
+ }
3631
+ return steps;
3632
+ }
3633
+ function readPath(path, value) {
3634
+ const steps = stepsOf(path);
3635
+ let current = [value];
3636
+ for (const step of steps) {
3637
+ const next = [];
3638
+ for (const item of current) {
3639
+ if ("all" in step) {
3640
+ if (Array.isArray(item)) next.push(...item);
3641
+ } else if ("index" in step) {
3642
+ if (Array.isArray(item) && step.index < item.length) next.push(item[step.index]);
3643
+ } else if (isRecord(item) && Object.hasOwn(item, step.key)) {
3644
+ next.push(item[step.key]);
3645
+ }
3646
+ }
3647
+ current = next;
3648
+ }
3649
+ if (steps.some((step) => "all" in step)) return current.filter((item) => item !== void 0 && item !== null);
3650
+ return current[0];
3651
+ }
3652
+ function present(value, field) {
3653
+ return value !== void 0 && value !== null && (value !== "" || field.empty === true);
3654
+ }
3655
+ function valueOfItem(item, raw) {
3656
+ if (typeof item === "string") return raw;
3657
+ if (item.exists === true) return !(Array.isArray(raw) && raw.length === 0);
3658
+ const map = item.map;
3659
+ if (map === void 0) return raw;
3660
+ const lookup2 = (value) => {
3661
+ const key = String(value);
3662
+ return Object.hasOwn(map, key) ? map[key] : item.default ?? value;
3663
+ };
3664
+ return Array.isArray(raw) ? raw.map(lookup2) : lookup2(raw);
3665
+ }
3666
+ function evaluate(spec, element, field) {
3667
+ const items = Array.isArray(spec) ? spec : [spec];
3668
+ for (const item of items) {
3669
+ const raw = readPath(typeof item === "string" ? item : item.path, element);
3670
+ if (present(raw, field)) return { raw, value: valueOfItem(item, raw) };
3671
+ }
3672
+ const last = items.at(-1);
3673
+ if (last === void 0 || typeof last === "string") return void 0;
3674
+ if (last.exists === true) return { raw: void 0, value: false };
3675
+ return last.default === void 0 ? void 0 : { raw: void 0, value: last.default };
3676
+ }
3677
+ function clip(value, max) {
3678
+ return max === void 0 ? value : clipText(value, max);
3679
+ }
3680
+ function timeOf(value) {
3681
+ if (typeof value === "string") {
3682
+ const ms = Date.parse(value);
3683
+ return Number.isFinite(ms) && ms >= 0 ? ms : void 0;
3684
+ }
3685
+ if (typeof value === "number" && Number.isSafeInteger(value) && value >= 0) return value < 1e11 ? value * 1e3 : value;
3686
+ return void 0;
3687
+ }
3688
+ function linkOf(value) {
3689
+ if (typeof value !== "string" || value.length > 2048) return void 0;
3690
+ try {
3691
+ const url = new URL(value);
3692
+ return url.protocol === "http:" || url.protocol === "https:" ? value : void 0;
3693
+ } catch {
3694
+ return void 0;
3695
+ }
3696
+ }
3697
+ function coerce(field, value) {
3698
+ switch (field.type) {
3699
+ case "id":
3700
+ if (typeof value === "string" && value !== "") return clip(value, field.max);
3701
+ if (typeof value === "number" && Number.isFinite(value)) return String(value);
3702
+ return void 0;
3703
+ case "text":
3704
+ if (typeof value === "string") return value === "" && field.empty !== true ? void 0 : clip(value, field.max);
3705
+ if (typeof value === "number" || typeof value === "boolean") return String(value);
3706
+ return void 0;
3707
+ case "int": {
3708
+ const number = typeof value === "string" && /^\d{1,15}$/.test(value) ? Number(value) : value;
3709
+ if (typeof number !== "number" || !Number.isSafeInteger(number) || number < (field.positive === true ? 1 : 0)) return void 0;
3710
+ return number;
3711
+ }
3712
+ case "flag":
3713
+ if (typeof value === "boolean") return value;
3714
+ return value === "true" ? true : value === "false" ? false : void 0;
3715
+ case "time":
3716
+ return timeOf(value);
3717
+ case "list": {
3718
+ const items = Array.isArray(value) ? value : [value];
3719
+ const texts = items.map((item) => typeof item === "string" ? item : typeof item === "number" ? String(item) : "").filter((item) => item !== "");
3720
+ return [...new Set(texts.map((item) => clip(item, field.max)))].slice(0, field.count);
3721
+ }
3722
+ case "link":
3723
+ return linkOf(value);
3724
+ case "enum":
3725
+ return typeof value === "string" || typeof value === "number" || typeof value === "boolean" ? String(value) : void 0;
3726
+ case "sha":
3727
+ return typeof value === "string" && /^[0-9a-fA-F]{7,64}$/.test(value) ? value.toLowerCase() : void 0;
3728
+ }
3729
+ }
3730
+ function setNested(target, path, value) {
3731
+ const [head, ...rest] = path.split(".");
3732
+ if (head === void 0) return;
3733
+ if (rest.length === 0) {
3734
+ target[head] = value;
3735
+ return;
3736
+ }
3737
+ const inner = isRecord(target[head]) ? target[head] : {};
3738
+ target[head] = inner;
3739
+ setNested(inner, rest.join("."), value);
3740
+ }
3741
+ function nativeName(out, key, raw, max) {
3742
+ const native = out[key];
3743
+ if (!isRecord(native) || typeof native.category !== "string" || native.name !== void 0) return;
3744
+ const source = typeof raw === "string" && raw !== "" ? raw : typeof raw === "number" || typeof raw === "boolean" ? String(raw) : native.category;
3745
+ native.name = clipText(source, max);
3746
+ }
3747
+ function answerFailed(title, call, detail) {
3748
+ return new TrackerError("failed", redactSecretText(`\u0422\u0440\u0435\u043A\u0435\u0440 \xAB${title}\xBB: \u043E\u0442\u0432\u0435\u0442 \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u0438 ${call.section}.${call.name} \u043D\u0435 \u0441\u043E\u0432\u043F\u0430\u043B \u0441 \u0435\u0434\u0438\u043D\u043E\u0439 \u043C\u043E\u0434\u0435\u043B\u044C\u044E: ${detail}.`));
3749
+ }
3750
+ function buildItem(title, call, element, defaults = {}) {
3751
+ const model = call.spec.model;
3752
+ if (model === void 0) throw answerFailed(title, call, "\u0443 \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u0438 \u043D\u0435\u0442 \u043C\u043E\u0434\u0435\u043B\u0438 \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442\u0430");
3753
+ const fields = RESULT_FIELDS[model];
3754
+ const out = {};
3755
+ const raws = {};
3756
+ for (const [name, spec] of Object.entries(call.operation.result ?? {})) {
3757
+ const field = Object.hasOwn(fields, name) ? fields[name] : void 0;
3758
+ if (field === void 0) continue;
3759
+ const found = evaluate(spec, element, field);
3760
+ if (found === void 0) continue;
3761
+ raws[name] = found.raw;
3762
+ const value = coerce(field, found.value);
3763
+ if (value === void 0) continue;
3764
+ if (field.type === "enum" && typeof value === "string" && field.values !== void 0 && !field.values.includes(value)) {
3765
+ if (field.required === true) throw answerFailed(title, call, `${name}: \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435 \xAB${clipText(value, 100)}\xBB \u043D\u0435 \u0438\u0437 \u043F\u0435\u0440\u0435\u0447\u043D\u044F ${field.values.join(", ")} \u2014 \u0434\u043E\u0431\u0430\u0432\u044C\u0442\u0435 \u0435\u0433\u043E \u0432 map \u0438\u043B\u0438 \u0437\u0430\u0434\u0430\u0439\u0442\u0435 default`);
3766
+ continue;
3767
+ }
3768
+ if (field.type === "link") out.links = [{ url: value }];
3769
+ else setNested(out, name, value);
3770
+ }
3771
+ for (const [name, value] of Object.entries(defaults)) if (out[name] === void 0) setNested(out, name, value);
3772
+ if (model === "issue" || model === "pull" || model === "run" || model === "job") out.links ??= [];
3773
+ if (model === "issue" || model === "pull") out.labels ??= [];
3774
+ if (model === "run") out.workflows ??= [];
3775
+ if (model === "workflow") out.enabled ??= true;
3776
+ if (model === "run" && isRecord(out.event) && out.event.category === void 0) out.event.category = "other";
3777
+ nativeName(out, "status", raws["status.category"], model === "run" || model === "job" ? 100 : 200);
3778
+ nativeName(out, "event", raws["event.category"], 100);
3779
+ if (model === "pull") {
3780
+ const status = isRecord(out.status) ? out.status : void 0;
3781
+ if (status !== void 0 && (out.merged === true || out.mergedAt !== void 0)) status.category = "merged";
3782
+ else if (status !== void 0 && out.draft === true && status.category === "open") status.category = "draft";
3783
+ delete out.merged;
3784
+ delete out.draft;
3785
+ }
3786
+ const parsed = MODEL_SCHEMAS[model].safeParse(out);
3787
+ if (!parsed.success) {
3788
+ const first = parsed.error.issues[0];
3789
+ const where = first === void 0 || first.path.length === 0 ? "\u044D\u043B\u0435\u043C\u0435\u043D\u0442" : first.path.map(String).join(".");
3790
+ throw answerFailed(title, call, `${where}: ${first?.message ?? "\u043D\u0435 \u043F\u0440\u043E\u0448\u0451\u043B \u0441\u0445\u0435\u043C\u0443"}`);
3791
+ }
3792
+ return parsed.data;
3793
+ }
3794
+
3795
+ // src/tracker/declarative/declarative-request.lib.ts
3796
+ function placeholdersOf(template) {
3797
+ return [...template.matchAll(new RegExp(PLACEHOLDER.source, "g"))].map((match) => ({ name: match[1] ?? "", modifier: match[2] }));
3798
+ }
3799
+ function wholePlaceholder(template) {
3800
+ return /^\{\{\s*([A-Za-z][A-Za-z0-9]*)\s*\}\}$/.exec(template)?.[1];
3801
+ }
3802
+ function bodyTemplates(value) {
3803
+ if (typeof value === "string") return [value];
3804
+ if (Array.isArray(value)) return value.flatMap(bodyTemplates);
3805
+ if (isRecord(value)) return Object.values(value).flatMap(bodyTemplates);
3806
+ return [];
3807
+ }
3808
+ function usedNames(operation2) {
3809
+ if (operation2 === void 0) return /* @__PURE__ */ new Set();
3810
+ const templates = [operation2.path, ...Object.values(operation2.query ?? {}).map(String), ...bodyTemplates(operation2.body)];
3811
+ return new Set(templates.flatMap((template) => placeholdersOf(template).map((placeholder) => placeholder.name)));
3812
+ }
3813
+ function invalid(title, message) {
3814
+ return new TrackerError("invalid_request", `\u0422\u0440\u0435\u043A\u0435\u0440 \xAB${title}\xBB: ${message}`);
3815
+ }
3816
+ function httpUrl(title, value, what) {
3817
+ let parsed;
3818
+ try {
3819
+ parsed = new URL(value);
3820
+ } catch {
3821
+ throw invalid(title, `${what} \u2014 \u043D\u0435 URL.`);
3822
+ }
3823
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") throw invalid(title, `${what} \u0434\u043E\u043B\u0436\u0435\u043D \u0431\u044B\u0442\u044C http \u0438\u043B\u0438 https.`);
3824
+ if (parsed.username !== "" || parsed.password !== "" || parsed.search !== "" || parsed.hash !== "") {
3825
+ throw invalid(title, `\u0432 ${what === "url \u043F\u043E\u0434\u043A\u043B\u044E\u0447\u0435\u043D\u0438\u044F" ? "url \u043F\u043E\u0434\u043A\u043B\u044E\u0447\u0435\u043D\u0438\u044F" : "\u0430\u0434\u0440\u0435\u0441\u0435 API"} \u043D\u0435 \u0434\u043E\u043B\u0436\u043D\u043E \u0431\u044B\u0442\u044C \u0438\u043C\u0435\u043D\u0438, \u043F\u0430\u0440\u043E\u043B\u044F, \u043F\u0430\u0440\u0430\u043C\u0435\u0442\u0440\u043E\u0432 \u0438 \u044F\u043A\u043E\u0440\u044F.`);
3826
+ }
3827
+ return parsed;
3828
+ }
3829
+ function baseOf(config, connection) {
3830
+ const template = config.http.base;
3831
+ const head = /^\{\{\s*url\s*\}\}/.exec(template);
3832
+ let raw = template;
3833
+ if (head !== null) {
3834
+ const url = connection.url?.trim().replace(/\/+$/, "");
3835
+ if (url === void 0 || url === "") throw invalid(config.title, "\u043D\u0435 \u0437\u0430\u0434\u0430\u043D url \u043F\u043E\u0434\u043A\u043B\u044E\u0447\u0435\u043D\u0438\u044F.");
3836
+ if (/[?#]/.test(url)) throw invalid(config.title, "\u0432 url \u043F\u043E\u0434\u043A\u043B\u044E\u0447\u0435\u043D\u0438\u044F \u043D\u0435 \u0434\u043E\u043B\u0436\u043D\u043E \u0431\u044B\u0442\u044C \u0438\u043C\u0435\u043D\u0438, \u043F\u0430\u0440\u043E\u043B\u044F, \u043F\u0430\u0440\u0430\u043C\u0435\u0442\u0440\u043E\u0432 \u0438 \u044F\u043A\u043E\u0440\u044F.");
3837
+ httpUrl(config.title, url, "url \u043F\u043E\u0434\u043A\u043B\u044E\u0447\u0435\u043D\u0438\u044F");
3838
+ raw = url + template.slice(head[0].length);
3839
+ }
3840
+ raw = raw.replace(/\/+$/, "");
3841
+ const parsed = httpUrl(config.title, raw, "\u0430\u0434\u0440\u0435\u0441 API");
3842
+ return { base: raw, origin: parsed.origin, path: parsed.pathname.replace(/\/+$/, "") };
3843
+ }
3844
+ function valueOf(context, inputs, name) {
3845
+ if (CONNECTION_PLACEHOLDERS.includes(name)) {
3846
+ const value = context.connection[name];
3847
+ return value === void 0 || value === "" ? void 0 : name === "url" ? value.trim().replace(/\/+$/, "") : value;
3848
+ }
3849
+ return Object.hasOwn(inputs, name) ? inputs[name] : void 0;
3850
+ }
3851
+ function mapInputs(title, call, inputs) {
3852
+ const out = { ...inputs };
3853
+ for (const [name, table] of Object.entries(call.operation.inputs ?? {})) {
3854
+ const value = inputs[name];
3855
+ if (value === void 0) continue;
3856
+ const refuse = (key2) => new TrackerError("unsupported", `\u0422\u0440\u0435\u043A\u0435\u0440 \xAB${title}\xBB: \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435 \xAB${key2}\xBB \u0432\u0445\u043E\u0434\u0430 ${name} \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u0438 ${call.section}.${call.name} \u043D\u0435 \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044F.`);
3857
+ if (value === null) {
3858
+ if (!Object.hasOwn(table, INPUT_NULL)) throw refuse(INPUT_NULL);
3859
+ out[name] = table[INPUT_NULL];
3860
+ continue;
3861
+ }
3862
+ if (Array.isArray(value)) {
3863
+ const items = value;
3864
+ const any = Object.hasOwn(table, INPUT_ANY) ? table[INPUT_ANY] : void 0;
3865
+ const missing = items.find((item) => !Object.hasOwn(table, item));
3866
+ if (missing !== void 0) {
3867
+ if (any === void 0) throw refuse(missing);
3868
+ out[name] = any;
3869
+ continue;
3870
+ }
3871
+ const mapped = [...new Set(items.map((item) => table[item] ?? item))];
3872
+ out[name] = mapped.length === 1 ? mapped[0] : any ?? mapped;
3873
+ continue;
3874
+ }
3875
+ if (typeof value === "object") continue;
3876
+ const key = String(value);
3877
+ if (!Object.hasOwn(table, key)) throw refuse(key);
3878
+ out[name] = table[key];
3879
+ }
3880
+ return out;
3881
+ }
3882
+ function textOf(title, name, value) {
3883
+ if (value === null) throw new TrackerError("unsupported", `\u0422\u0440\u0435\u043A\u0435\u0440 \xAB${title}\xBB: \u043F\u0443\u0441\u0442\u043E\u0435 \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435 (null) \u0432\u0445\u043E\u0434\u0430 ${name} \u043D\u0435 \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044F.`);
3884
+ if (typeof value === "string") return value;
3885
+ if (typeof value === "number" || typeof value === "boolean") return String(value);
3886
+ if (Array.isArray(value)) {
3887
+ const items = value;
3888
+ if (items.some((item) => item.includes(","))) throw invalid(title, `\u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435 \u0432\u0445\u043E\u0434\u0430 ${name} \u043D\u0435 \u0434\u043E\u043B\u0436\u043D\u043E \u0441\u043E\u0434\u0435\u0440\u0436\u0430\u0442\u044C \u0437\u0430\u043F\u044F\u0442\u0443\u044E: \u0441\u043F\u0438\u0441\u043E\u043A \u0443\u0445\u043E\u0434\u0438\u0442 \u0447\u0435\u0440\u0435\u0437 \u0437\u0430\u043F\u044F\u0442\u0443\u044E.`);
3889
+ return items.join(",");
3890
+ }
3891
+ throw invalid(title, `\u0432\u0445\u043E\u0434 ${name} \u2014 \u0441\u043B\u043E\u0432\u0430\u0440\u044C: \u043E\u043D \u043F\u043E\u0434\u0441\u0442\u0430\u0432\u043B\u044F\u0435\u0442\u0441\u044F \u0442\u043E\u043B\u044C\u043A\u043E \u0446\u0435\u043B\u044B\u043C \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435\u043C \u0442\u0435\u043B\u0430.`);
3892
+ }
3893
+ function segment(title, name, value, input) {
3894
+ const refuse = (why) => invalid(title, `\u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435 \u0432\u0445\u043E\u0434\u0430 ${name} \u043D\u0435\u043B\u044C\u0437\u044F \u043F\u043E\u0434\u0441\u0442\u0430\u0432\u0438\u0442\u044C \u0432 \u043F\u0443\u0442\u044C \u0437\u0430\u043F\u0440\u043E\u0441\u0430: ${why}.`);
3895
+ if (value === "" || value === "." || value === "..") throw refuse(value === "" ? "\u043F\u0443\u0441\u0442\u043E\u0439 \u0441\u0435\u0433\u043C\u0435\u043D\u0442" : `\xAB${value}\xBB \u2014 \u043F\u0435\u0440\u0435\u0445\u043E\u0434 \u043F\u043E \u043F\u0443\u0442\u0438`);
3896
+ if (/[\\\u0000-\u001f\u007f]/.test(value)) throw refuse("\xAB\\\xBB \u0438 \u0443\u043F\u0440\u0430\u0432\u043B\u044F\u044E\u0449\u0438\u0435 \u0441\u0438\u043C\u0432\u043E\u043B\u044B \u043D\u0435\u0434\u043E\u043F\u0443\u0441\u0442\u0438\u043C\u044B");
3897
+ if (input && (value.includes("/") || /%(?:2f|5c)/i.test(value))) throw refuse("\u0440\u0430\u0437\u0434\u0435\u043B\u0438\u0442\u0435\u043B\u044C \u043F\u0443\u0442\u0438 \xAB/\xBB \u043D\u0435\u0434\u043E\u043F\u0443\u0441\u0442\u0438\u043C");
3898
+ try {
3899
+ return encodeURIComponent(value);
3900
+ } catch {
3901
+ throw refuse("\u0441\u0442\u0440\u043E\u043A\u0430 \u043D\u0435 \u043A\u043E\u0434\u0438\u0440\u0443\u0435\u0442\u0441\u044F \u0432 UTF-8");
3902
+ }
3903
+ }
3904
+ function render(context, inputs, template, where) {
3905
+ let missing = false;
3906
+ const out = template.replace(new RegExp(PLACEHOLDER.source, "g"), (_match, name, modifier) => {
3907
+ const value = valueOf(context, inputs, name);
3908
+ if (value === void 0) {
3909
+ missing = true;
3910
+ return "";
3911
+ }
3912
+ const text2 = textOf(context.config.title, name, value);
3913
+ if (where !== "path") return text2;
3914
+ const input = !CONNECTION_PLACEHOLDERS.includes(name);
3915
+ if (modifier === "path") return text2.split("/").map((part) => segment(context.config.title, name, part, input)).join("/");
3916
+ return segment(context.config.title, name, text2, input);
3917
+ });
3918
+ return missing ? void 0 : out;
3919
+ }
3920
+ function headerValue(title, name, value) {
3921
+ if (/[\r\n\0]/.test(value)) throw invalid(title, `\u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435 \u0437\u0430\u0433\u043E\u043B\u043E\u0432\u043A\u0430 ${name} \u0441\u043E\u0434\u0435\u0440\u0436\u0438\u0442 \u043F\u0435\u0440\u0435\u0432\u043E\u0434 \u0441\u0442\u0440\u043E\u043A\u0438.`);
3922
+ return value;
3923
+ }
3924
+ function headersOf(config, connection) {
3925
+ const headers = {};
3926
+ for (const [name, template] of Object.entries(config.http.headers ?? {})) {
3927
+ const value = render({ config, connection }, {}, template, "text");
3928
+ if (value !== void 0) headers[name.toLowerCase()] = headerValue(config.title, name, value);
3929
+ }
3930
+ const token = connection.token;
3931
+ const auth = config.http.auth;
3932
+ if (token === void 0 || token === "" || auth.kind === "none") return headers;
3933
+ headerValue(config.title, "\u0430\u0432\u0442\u043E\u0440\u0438\u0437\u0430\u0446\u0438\u0438", token);
3934
+ if (auth.kind === "bearer") headers.authorization = `Bearer ${token}`;
3935
+ else if (auth.kind === "header") headers[auth.header.toLowerCase()] = `${auth.prefix ?? ""}${token}`;
3936
+ else headers.authorization = `Basic ${Buffer.from(`${connection.user ?? ""}:${token}`).toString("base64")}`;
3937
+ return headers;
3938
+ }
3939
+ function urlOf(context, call, inputs) {
3940
+ const path = render(context, inputs, call.operation.path, "path");
3941
+ if (path === void 0) {
3942
+ const names = placeholdersOf(call.operation.path).map((placeholder) => placeholder.name).filter((name) => valueOf(context, inputs, name) === void 0);
3943
+ throw invalid(context.config.title, `\u043E\u043F\u0435\u0440\u0430\u0446\u0438\u0438 ${call.section}.${call.name} \u043D\u0435 \u0445\u0432\u0430\u0442\u0430\u0435\u0442 \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0439: ${[...new Set(names)].join(", ")}.`);
3944
+ }
3945
+ const url = new URL(context.base.base + path);
3946
+ const base = context.base.path;
3947
+ if (url.origin !== context.base.origin || base !== "" && url.pathname !== base && !url.pathname.startsWith(`${base}/`)) {
3948
+ throw invalid(context.config.title, `\u0430\u0434\u0440\u0435\u0441 \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u0438 ${call.section}.${call.name} \u0443\u0445\u043E\u0434\u0438\u0442 \u0437\u0430 \u0430\u0434\u0440\u0435\u0441 API ${context.base.base}: \u0437\u0430\u043F\u0440\u043E\u0441 \u043D\u0435 \u043E\u0442\u043F\u0440\u0430\u0432\u043B\u0435\u043D.`);
3949
+ }
3950
+ return url;
3951
+ }
3952
+ function bodyOf(context, inputs, value) {
3953
+ if (typeof value === "string") {
3954
+ const whole = wholePlaceholder(value);
3955
+ if (whole !== void 0) return valueOf(context, inputs, whole);
3956
+ return render(context, inputs, value, "text");
3957
+ }
3958
+ if (Array.isArray(value)) return value.map((item) => bodyOf(context, inputs, item)).filter((item) => item !== void 0);
3959
+ if (isRecord(value)) {
3960
+ const out = {};
3961
+ for (const [key, item] of Object.entries(value)) {
3962
+ const rendered = bodyOf(context, inputs, item);
3963
+ if (rendered !== void 0) out[key] = rendered;
3964
+ }
3965
+ return out;
3966
+ }
3967
+ return value;
3968
+ }
3969
+ function prepare(context, call, inputs, params) {
3970
+ const url = urlOf(context, call, inputs);
3971
+ const search = new URLSearchParams();
3972
+ for (const [name, template] of Object.entries(call.operation.query ?? {})) {
3973
+ const value = render(context, inputs, String(template), "text");
3974
+ if (value !== void 0 && value !== "") search.set(name, value);
3975
+ }
3976
+ for (const [name, value] of params) search.set(name, value);
3977
+ if (search.size > 0) url.search = search.toString();
3978
+ const body = call.operation.body === void 0 || call.operation.method === "GET" ? void 0 : bodyOf(context, inputs, call.operation.body);
3979
+ return { url: url.href, body };
3980
+ }
3981
+ async function callJson(context, call, inputs, options = {}) {
3982
+ const { params = [], ...rest } = options;
3983
+ const request = prepare(context, call, mapInputs(context.config.title, call, inputs), params);
3984
+ return requestJson(request.url, {
3985
+ fetch: context.fetch,
3986
+ origin: context.base.origin,
3987
+ method: call.operation.method,
3988
+ headers: context.headers,
3989
+ ...request.body === void 0 ? {} : { body: request.body },
3990
+ ...rest
3991
+ });
3992
+ }
3993
+ async function callText(context, call, inputs, options) {
3994
+ const request = prepare(context, call, mapInputs(context.config.title, call, inputs), []);
3995
+ const { accept: _accept, ...headers } = context.headers;
3996
+ return requestText(request.url, { fetch: context.fetch, origin: context.base.origin, headers, ...options });
3997
+ }
3998
+ var PAGE_NUMBER = /^[1-9]\d{0,8}$/;
3999
+ var CURSOR_MAX = 2e3;
4000
+ function paginationOf(context, call) {
4001
+ return call.operation.pagination ?? context.config.http.pagination;
4002
+ }
4003
+ function pageParams(title, pagination, page) {
4004
+ if (pagination.style === "page") {
4005
+ if (page.cursor !== void 0 && !PAGE_NUMBER.test(page.cursor)) throw invalid(title, "\u043A\u0443\u0440\u0441\u043E\u0440 \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u044B \u2014 \u043D\u043E\u043C\u0435\u0440 \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u044B, \u0446\u0435\u043B\u043E\u0435 \u0447\u0438\u0441\u043B\u043E \u043E\u0442 1.");
4006
+ const number = page.cursor === void 0 ? 1 : Number(page.cursor);
4007
+ return { params: [[pagination.page, String(number)], [pagination.size, String(page.limit)]], number };
4008
+ }
4009
+ if (pagination.style === "cursor") {
4010
+ if (page.cursor !== void 0 && (page.cursor === "" || page.cursor.length > CURSOR_MAX)) throw invalid(title, `\u043A\u0443\u0440\u0441\u043E\u0440 \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u044B \u2014 \u043D\u0435\u043F\u0443\u0441\u0442\u0430\u044F \u0441\u0442\u0440\u043E\u043A\u0430 \u043D\u0435 \u0434\u043B\u0438\u043D\u043D\u0435\u0435 ${String(CURSOR_MAX)} \u0441\u0438\u043C\u0432\u043E\u043B\u043E\u0432.`);
4011
+ const params = pagination.size === void 0 ? [] : [[pagination.size, String(page.limit)]];
4012
+ if (page.cursor !== void 0) params.push([pagination.param, page.cursor]);
4013
+ return { params, number: 1 };
4014
+ }
4015
+ if (page.cursor !== void 0) throw invalid(title, "\u0443 \u0441\u043F\u0438\u0441\u043A\u0430 \u043E\u0434\u043D\u0430 \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u0430: \u043A\u0443\u0440\u0441\u043E\u0440\u0430 \u043D\u0435\u0442.");
4016
+ return { params: [], number: 1 };
4017
+ }
4018
+ function hasNextLink(headers) {
4019
+ const link2 = headers.get("link");
4020
+ if (link2 === null) return false;
4021
+ for (const match of link2.replace(/<[^>]*>/g, "").matchAll(/;\s*rel\s*=\s*(?:"([^"]*)"|([^\s;,"]+))/gi)) {
4022
+ if ((match[1] ?? match[2] ?? "").toLowerCase().split(/\s+/).includes("next")) return true;
4023
+ }
4024
+ return false;
4025
+ }
4026
+ function nextCursorOf2(pagination, page, number, count, response) {
4027
+ if (pagination.style === "page") {
4028
+ const next = pagination.next;
4029
+ if (next === "link") return hasNextLink(response.headers) ? String(number + 1) : void 0;
4030
+ if (next === "count") return count >= page.limit ? String(number + 1) : void 0;
4031
+ const value = "header" in next ? response.headers.get(next.header)?.trim() : readPath(next.path, response.body);
4032
+ const text2 = typeof value === "number" ? String(value) : value;
4033
+ return typeof text2 === "string" && PAGE_NUMBER.test(text2) && Number(text2) > number ? text2 : void 0;
4034
+ }
4035
+ if (pagination.style === "cursor") {
4036
+ const value = typeof pagination.next === "string" ? readPath(pagination.next, response.body) : response.headers.get(pagination.next.header)?.trim();
4037
+ const text2 = typeof value === "number" && Number.isFinite(value) ? String(value) : value;
4038
+ return typeof text2 === "string" && text2 !== "" && text2.length <= CURSOR_MAX && text2 !== page.cursor ? text2 : void 0;
4039
+ }
4040
+ return void 0;
4041
+ }
4042
+
4043
+ // src/tracker/declarative/declarative-capabilities.lib.ts
4044
+ var issueRules = {
4045
+ status: { input: "status", needs: [], check: (item, query) => query.status?.includes(item.status.category) === true },
4046
+ labels: { input: "labels", needs: ["labels"], check: (item, query) => (query.labels ?? []).every((label) => item.labels.includes(label)) },
4047
+ assignee: { input: "assignee", needs: ["assignee"], check: (item, query) => query.assignee === null ? item.assignee === void 0 : item.assignee === query.assignee },
4048
+ author: { input: "author", needs: [] },
4049
+ search: { input: "search", needs: [], check: (item, query) => containsText([item.title, item.description], query.search ?? "") },
4050
+ createdAfter: { input: "createdAfter", needs: ["createdAt"], check: (item, query) => inTimeRange(item.createdAt, query.createdAfter, void 0) },
4051
+ createdBefore: { input: "createdBefore", needs: ["createdAt"], check: (item, query) => inTimeRange(item.createdAt, void 0, query.createdBefore) },
4052
+ updatedAfter: { input: "updatedAfter", needs: ["updatedAt"], check: (item, query) => inTimeRange(item.updatedAt, query.updatedAfter, void 0) },
4053
+ updatedBefore: { input: "updatedBefore", needs: ["updatedAt"], check: (item, query) => inTimeRange(item.updatedAt, void 0, query.updatedBefore) }
4054
+ };
4055
+ var pullRules = {
4056
+ status: { input: "status", needs: [], check: (item, query) => query.status?.includes(item.status.category) === true },
4057
+ author: { input: "author", needs: ["author"], check: (item, query) => item.author === query.author },
4058
+ source: { input: "sourceBranch", needs: [], check: (item, query) => item.source === query.source },
4059
+ target: { input: "targetBranch", needs: [], check: (item, query) => item.target === query.target },
4060
+ labels: { input: "labels", needs: ["labels"], check: (item, query) => (query.labels ?? []).every((label) => item.labels.includes(label)) },
4061
+ search: { input: "search", needs: [], check: (item, query) => containsText([item.title, item.description], query.search ?? "") },
4062
+ createdAfter: { input: "createdAfter", needs: ["createdAt"], check: (item, query) => inTimeRange(item.createdAt, query.createdAfter, void 0) },
4063
+ createdBefore: { input: "createdBefore", needs: ["createdAt"], check: (item, query) => inTimeRange(item.createdAt, void 0, query.createdBefore) },
4064
+ updatedAfter: { input: "updatedAfter", needs: ["updatedAt"], check: (item, query) => inTimeRange(item.updatedAt, query.updatedAfter, void 0) },
4065
+ updatedBefore: { input: "updatedBefore", needs: ["updatedAt"], check: (item, query) => inTimeRange(item.updatedAt, void 0, query.updatedBefore) }
4066
+ };
4067
+ var runRules = {
4068
+ status: { input: "status", needs: [], check: (item, query) => query.status?.includes(item.status.category) === true },
4069
+ ref: { input: "ref", needs: ["ref"], check: (item, query) => item.ref === query.ref },
4070
+ sha: { input: "sha", needs: ["sha"], check: (item, query) => item.sha !== void 0 && item.sha.startsWith((query.sha ?? "").toLowerCase()) },
4071
+ event: { input: "event", needs: ["event.category"], check: (item, query) => item.event !== void 0 && query.event?.includes(item.event.category) === true },
4072
+ workflow: { input: "workflow", needs: ["workflows"], check: (item, query) => item.workflows.includes(query.workflow ?? "") },
4073
+ actor: { input: "actor", needs: ["actor"], check: (item, query) => item.actor === query.actor },
4074
+ pullRequest: { input: "pullRequest", needs: ["pullRequest"], check: (item, query) => item.pullRequest === query.pullRequest },
4075
+ createdAfter: { input: "createdAfter", needs: ["createdAt"], check: (item, query) => inTimeRange(item.createdAt, query.createdAfter, void 0) },
4076
+ createdBefore: { input: "createdBefore", needs: ["createdAt"], check: (item, query) => inTimeRange(item.createdAt, void 0, query.createdBefore) },
4077
+ updatedAfter: { input: "updatedAfter", needs: ["updatedAt"], check: (item, query) => inTimeRange(item.updatedAt, query.updatedAfter, void 0) },
4078
+ updatedBefore: { input: "updatedBefore", needs: ["updatedAt"], check: (item, query) => inTimeRange(item.updatedAt, void 0, query.updatedBefore) }
4079
+ };
4080
+ var jobRules = {
4081
+ status: { input: "status", needs: [], check: (item, query) => query.status?.includes(item.status.category) === true },
4082
+ allAttempts: { input: "allAttempts", needs: [] }
4083
+ };
4084
+ function uses(operation2, input) {
4085
+ return usedNames(operation2).has(input);
4086
+ }
4087
+ function tableOf(operation2, input) {
4088
+ return operation2?.inputs?.[input];
4089
+ }
4090
+ function keysWithin(operation2, input, domain) {
4091
+ const table = tableOf(operation2, input);
4092
+ return table === void 0 ? [...domain] : domain.filter((value) => Object.hasOwn(table, value));
4093
+ }
4094
+ function listOf(operation2, rules, sorts) {
4095
+ if (operation2 === void 0) return { filters: [], clientSide: [], sorts: [] };
4096
+ const used = usedNames(operation2);
4097
+ const result = operation2.result ?? {};
4098
+ const filters = [];
4099
+ const clientSide = [];
4100
+ for (const [name, rule] of Object.entries(rules)) {
4101
+ const server = used.has(rule.input);
4102
+ const checkable = rule.check !== void 0 && rule.needs.every((field) => result[field] !== void 0);
4103
+ if (!server && !checkable) continue;
4104
+ filters.push(name);
4105
+ if (checkable && (!server || tableOf(operation2, rule.input) !== void 0)) clientSide.push(name);
4106
+ }
4107
+ return { filters, clientSide, sorts: used.has("sort") ? keysWithin(operation2, "sort", sorts) : [] };
4108
+ }
4109
+ function pageCheck(rules, capabilities, query) {
4110
+ const names = usedFilters(query, Object.keys(rules)).filter((name) => capabilities.clientSide.includes(name));
4111
+ return (item) => names.every((name) => rules[name].check?.(item, query) !== false);
4112
+ }
4113
+ function commentsOf(operation2) {
4114
+ if (operation2 === void 0) return { filters: [], clientSide: [], order: ["asc"] };
4115
+ const order = uses(operation2, "order") ? keysWithin(operation2, "order", ["asc", "desc"]) : ["asc"];
4116
+ return { filters: uses(operation2, "updatedAfter") ? ["updatedAfter"] : [], clientSide: [], order };
4117
+ }
4118
+ function issueCapabilitiesFrom(config) {
4119
+ return { list: listOf(config.issues?.list, issueRules, ISSUE_SORT_FIELDS), comments: commentsOf(config.issues?.comments) };
4120
+ }
4121
+ function featuresFrom(config) {
4122
+ const issues = config.issues;
4123
+ const touches = (input) => uses(issues?.create, input) || uses(issues?.update, input);
4124
+ return {
4125
+ create: issues?.create !== void 0,
4126
+ update: issues?.update !== void 0,
4127
+ comment: issues?.comment !== void 0,
4128
+ priority: touches("priority"),
4129
+ labels: touches("labels"),
4130
+ assignee: touches("assignee"),
4131
+ statuses: uses(issues?.update, "status") ? keysWithin(issues?.update, "status", ["open", "in_progress", "done", "declined"]) : []
4132
+ };
4133
+ }
4134
+ function pullCapabilitiesFrom(config) {
4135
+ const pulls = config.pulls;
4136
+ if (pulls === void 0) return void 0;
4137
+ const merge = pulls.merge === void 0 ? [] : uses(pulls.merge, "method") ? keysWithin(pulls.merge, "method", mergeMethodSchema.options) : ["merge"];
4138
+ return {
4139
+ list: listOf(pulls.list, pullRules, pullRequestSortFieldSchema.options),
4140
+ comments: commentsOf(pulls.comments),
4141
+ create: pulls.create !== void 0,
4142
+ createDraft: uses(pulls.create, "draft"),
4143
+ update: ["title", "description", "target"].filter((field) => uses(pulls.update, field === "target" ? "targetBranch" : field)),
4144
+ statuses: uses(pulls.update, "status") ? keysWithin(pulls.update, "status", ["draft", "open", "closed"]) : [],
4145
+ comment: pulls.comment !== void 0,
4146
+ merge,
4147
+ deleteSourceOnMerge: uses(pulls.merge, "deleteSource")
4148
+ };
4149
+ }
4150
+ function ciCapabilitiesFrom(config) {
4151
+ const ci = config.ci;
4152
+ if (ci === void 0) return void 0;
4153
+ const reruns = [ci.rerun, ci.rerunFailed, ci.rerunJob];
4154
+ const tags = uses(ci.trigger, "refType") && keysWithin(ci.trigger, "refType", ["branch", "tag"]).includes("tag");
4155
+ return {
4156
+ workflows: ci.workflows !== void 0,
4157
+ runs: listOf(ci.runs, runRules, ciRunSortFieldSchema.options),
4158
+ jobs: listOf(ci.jobs, jobRules, []),
4159
+ log: { live: ci.log !== void 0, cursor: ci.log !== void 0 },
4160
+ trigger: {
4161
+ supported: ci.trigger !== void 0,
4162
+ workflows: uses(ci.trigger, "workflows") ? "many" : uses(ci.trigger, "workflow") ? "one" : "none",
4163
+ inputs: uses(ci.trigger, "inputs"),
4164
+ tags
4165
+ },
4166
+ rerun: { all: ci.rerun !== void 0, failedOnly: ci.rerunFailed !== void 0, job: ci.rerunJob !== void 0, debug: reruns.some((operation2) => uses(operation2, "debug")) },
4167
+ cancel: { run: ci.cancel !== void 0, job: ci.cancelJob !== void 0 }
4168
+ };
4169
+ }
4170
+ function issueFilter(capabilities, query) {
4171
+ return pageCheck(issueRules, capabilities.list, query);
4172
+ }
4173
+ function pullFilter(capabilities, query) {
4174
+ return pageCheck(pullRules, capabilities.list, query);
4175
+ }
4176
+ function runFilter(capabilities, query) {
4177
+ return pageCheck(runRules, capabilities.runs, query);
4178
+ }
4179
+ function jobFilter(capabilities, query) {
4180
+ return pageCheck(jobRules, capabilities.jobs, query);
4181
+ }
4182
+
4183
+ // src/tracker/declarative/declarative-call.lib.ts
4184
+ function contextOf(config, { connection, fetch }) {
4185
+ for (const field of config.fields) {
4186
+ if (field.required && field.name !== "token" && (connection[field.name] === void 0 || connection[field.name] === "")) {
4187
+ throw new TrackerError("invalid_request", `\u0422\u0440\u0435\u043A\u0435\u0440 \xAB${config.title}\xBB: \u043D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E \u043F\u043E\u043B\u0435 ${field.name} \u043F\u043E\u0434\u043A\u043B\u044E\u0447\u0435\u043D\u0438\u044F.`);
4188
+ }
4189
+ }
4190
+ const values = { url: connection.url, target: connection.target, user: connection.user };
4191
+ return { config, connection: values, base: baseOf(config, values), fetch, headers: headersOf(config, { ...values, token: connection.token }) };
4192
+ }
4193
+ function callOf(config, section, name) {
4194
+ const operations = config[section];
4195
+ const operation2 = operations?.[name];
4196
+ const spec = OPERATIONS[section][name];
4197
+ return operation2 === void 0 || spec === void 0 ? void 0 : { section, name, operation: operation2, spec };
4198
+ }
4199
+ function requireCall(config, section, name, what) {
4200
+ const call = callOf(config, section, name);
4201
+ if (call === void 0) throw new TrackerError("unsupported", `\u0422\u0440\u0435\u043A\u0435\u0440 \xAB${config.title}\xBB \u043D\u0435 \u0443\u043C\u0435\u0435\u0442 ${what}: \u0432 \u043A\u043E\u043D\u0444\u0438\u0433\u0435 \u043D\u0435\u0442 \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u0438 ${section}.${name}.`);
4202
+ return call;
4203
+ }
4204
+ function assertUsed(subject, call, inputs) {
4205
+ const used = usedNames(call.operation);
4206
+ for (const [name, value] of Object.entries(inputs)) {
4207
+ if (value === void 0 || value === false || Array.isArray(value) && value.length === 0 || used.has(name)) continue;
4208
+ throw new TrackerError("unsupported", `${subject}: \u043F\u043E\u043B\u0435 ${name} \u043D\u0435 \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044F \u2014 \u0435\u0433\u043E \u043D\u0435\u0442 \u0432 \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u0438 ${call.section}.${call.name} \u043A\u043E\u043D\u0444\u0438\u0433\u0430.`);
4209
+ }
4210
+ }
4211
+ function isoOf(value) {
4212
+ return value === void 0 ? void 0 : isoTime(value);
4213
+ }
4214
+ function sortInputs(sort) {
4215
+ return sort === void 0 ? {} : { sort: sort.field, direction: sort.direction ?? "desc" };
4216
+ }
4217
+ async function single(context, call, inputs, options = {}, defaults = {}) {
4218
+ const { body } = await callJson(context, call, inputs, options);
4219
+ const element = call.operation.items === void 0 ? body : readPath(call.operation.items, body);
4220
+ if (element === void 0 || element === null) throw answerFailed(context.config.title, call, "\u0432 \u043E\u0442\u0432\u0435\u0442\u0435 \u043D\u0435\u0442 \u044D\u043B\u0435\u043C\u0435\u043D\u0442\u0430");
4221
+ return buildItem(context.config.title, call, element, defaults);
4222
+ }
4223
+ async function list(context, call, inputs, page, options = {}, defaults = {}) {
4224
+ const pagination = paginationOf(context, call);
4225
+ const { params, number } = pageParams(context.config.title, pagination, page);
4226
+ const response = await callJson(context, call, inputs, { ...options, params });
4227
+ const elements = call.operation.items === void 0 ? response.body : readPath(call.operation.items, response.body);
4228
+ if (!Array.isArray(elements)) throw answerFailed(context.config.title, call, `\u043E\u0436\u0438\u0434\u0430\u043B\u0441\u044F \u0441\u043F\u0438\u0441\u043E\u043A \u044D\u043B\u0435\u043C\u0435\u043D\u0442\u043E\u0432${call.operation.items === void 0 ? "" : ` \u043F\u043E \u043F\u0443\u0442\u0438 ${call.operation.items}`}`);
4229
+ const items = elements.slice(0, page.limit).map((element) => buildItem(context.config.title, call, element, defaults));
4230
+ const next = nextCursorOf2(pagination, page, number, elements.length, response);
4231
+ return { items, ...next === void 0 ? {} : { nextCursor: next } };
4232
+ }
4233
+
4234
+ // src/tracker/declarative/declarative-ci.lib.ts
4235
+ var ACTION_CONFLICT = [409, 422];
4236
+ function createCiAdapter(config, adapterContext, capabilities) {
4237
+ const context = contextOf(config, adapterContext);
4238
+ const subject = `CI \xAB${config.title}\xBB`;
4239
+ const missingRun = (key) => ({ missing: { failure: "not_found", message: `\u0412 \u0442\u0440\u0435\u043A\u0435\u0440\u0435 \xAB${config.title}\xBB \u043D\u0435\u0442 \u043F\u0440\u043E\u0433\u043E\u043D\u0430 ${key}.` } });
4240
+ const missingJob = (key) => ({ missing: { failure: "not_found", message: `\u0412 \u0442\u0440\u0435\u043A\u0435\u0440\u0435 \xAB${config.title}\xBB \u043D\u0435\u0442 \u0437\u0430\u0434\u0430\u043D\u0438\u044F ${key}.` } });
4241
+ const getRun = (key) => single(context, requireCall(config, "ci", "run", "\u043F\u043E\u043A\u0430\u0437\u044B\u0432\u0430\u0442\u044C \u043F\u0440\u043E\u0433\u043E\u043D\u044B"), { key }, missingRun(key));
4242
+ const getJob = (key) => single(context, requireCall(config, "ci", "job", "\u043F\u043E\u043A\u0430\u0437\u044B\u0432\u0430\u0442\u044C \u0437\u0430\u0434\u0430\u043D\u0438\u044F"), { key }, missingJob(key));
4243
+ const debugOf = (name, debug) => {
4244
+ if (debug === true) assertUsed(subject, requireCall(config, "ci", name, "\u043F\u0435\u0440\u0435\u0437\u0430\u043F\u0443\u0441\u043A\u0430\u0442\u044C"), { debug });
4245
+ };
4246
+ return {
4247
+ listWorkflows: async (query) => {
4248
+ const call = requireCall(config, "ci", "workflows", "\u043F\u043E\u043A\u0430\u0437\u044B\u0432\u0430\u0442\u044C workflow");
4249
+ assertListQuery(subject, { filters: [], clientSide: [], sorts: [] }, query, []);
4250
+ return list(context, call, {}, query);
4251
+ },
4252
+ listRuns: async (query) => {
4253
+ const call = requireCall(config, "ci", "runs", "\u043F\u043E\u043A\u0430\u0437\u044B\u0432\u0430\u0442\u044C \u043F\u0440\u043E\u0433\u043E\u043D\u044B");
4254
+ assertListQuery(`\u041F\u0440\u043E\u0433\u043E\u043D\u044B ${subject}`, capabilities.runs, query, ciRunFilterSchema.options);
4255
+ const page = await list(
4256
+ context,
4257
+ call,
4258
+ {
4259
+ status: query.status,
4260
+ ref: query.ref,
4261
+ sha: query.sha,
4262
+ event: query.event,
4263
+ workflow: query.workflow,
4264
+ actor: query.actor,
4265
+ pullRequest: query.pullRequest,
4266
+ createdAfter: isoOf(query.createdAfter),
4267
+ createdBefore: isoOf(query.createdBefore),
4268
+ updatedAfter: isoOf(query.updatedAfter),
4269
+ updatedBefore: isoOf(query.updatedBefore),
4270
+ ...sortInputs(query.sort)
4271
+ },
4272
+ query
4273
+ );
4274
+ return { ...page, items: page.items.filter(runFilter(capabilities, query)) };
4275
+ },
4276
+ getRun,
4277
+ listJobs: async (runKey, query) => {
4278
+ const call = requireCall(config, "ci", "jobs", "\u043F\u043E\u043A\u0430\u0437\u044B\u0432\u0430\u0442\u044C \u0437\u0430\u0434\u0430\u043D\u0438\u044F");
4279
+ const { allAttempts, ...rest } = query;
4280
+ if (allAttempts === true && !capabilities.jobs.filters.includes("allAttempts")) throw new TrackerError("unsupported", `\u0417\u0430\u0434\u0430\u043D\u0438\u044F ${subject}: \u0444\u0438\u043B\u044C\u0442\u0440 allAttempts \u043D\u0435 \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044F.`);
4281
+ assertListQuery(`\u0417\u0430\u0434\u0430\u043D\u0438\u044F ${subject}`, capabilities.jobs, rest, ciJobFilterSchema.options);
4282
+ const page = await list(context, call, { run: runKey, status: query.status, allAttempts }, query, missingRun(runKey), { runKey });
4283
+ return { ...page, items: page.items.filter(jobFilter(capabilities, query)) };
4284
+ },
4285
+ getJob,
4286
+ log: async (key, query) => {
4287
+ const call = requireCall(config, "ci", "log", "\u043F\u043E\u043A\u0430\u0437\u044B\u0432\u0430\u0442\u044C \u043B\u043E\u0433");
4288
+ const window = logWindow(query);
4289
+ const complete = isFinished((await getJob(key)).status.category);
4290
+ const response = await callText(context, call, { key }, { skip: window.resume?.offset ?? 0, keep: { bytes: window.bytes, from: window.from }, ...missingJob(key) });
4291
+ return logOf({
4292
+ text: response.text,
4293
+ truncated: window.from === "tail" ? response.start > 0 : !response.whole,
4294
+ complete,
4295
+ page: 0,
4296
+ end: response.end,
4297
+ more: !response.whole,
4298
+ ...response.whole ? { size: response.read } : {},
4299
+ startCut: window.from === "tail" && response.start > 0,
4300
+ raw: query.raw ?? false
4301
+ });
4302
+ },
4303
+ trigger: async (input) => {
4304
+ const call = requireCall(config, "ci", "trigger", "\u0437\u0430\u043F\u0443\u0441\u043A\u0430\u0442\u044C CI");
4305
+ if (input.ref === "") throw new TrackerError("invalid_request", `\u0417\u0430\u043F\u0443\u0441\u043A ${subject}: ref \u2014 \u043D\u0435\u043F\u0443\u0441\u0442\u043E\u0435 \u0438\u043C\u044F \u0432\u0435\u0442\u043A\u0438 \u0438\u043B\u0438 \u0442\u0435\u0433\u0430.`);
4306
+ const workflows = input.workflows ?? [];
4307
+ const mode = capabilities.trigger.workflows;
4308
+ if (mode === "none" && workflows.length > 0) throw new TrackerError("unsupported", `\u0417\u0430\u043F\u0443\u0441\u043A ${subject}: workflow \u043D\u0435 \u0437\u0430\u0434\u0430\u0451\u0442\u0441\u044F.`);
4309
+ if (mode === "one" && workflows.length !== 1) throw new TrackerError("invalid_request", `\u0417\u0430\u043F\u0443\u0441\u043A ${subject}: \u043D\u0443\u0436\u0435\u043D \u0440\u043E\u0432\u043D\u043E \u043E\u0434\u0438\u043D workflow.`);
4310
+ if (mode === "many" && workflows.length === 0) throw new TrackerError("invalid_request", `\u0417\u0430\u043F\u0443\u0441\u043A ${subject}: \u043D\u0443\u0436\u0435\u043D \u0445\u043E\u0442\u044F \u0431\u044B \u043E\u0434\u0438\u043D workflow.`);
4311
+ if (input.refType === "tag" && !capabilities.trigger.tags) throw new TrackerError("unsupported", `\u0417\u0430\u043F\u0443\u0441\u043A ${subject}: \u0437\u0430\u043F\u0443\u0441\u043A \u043D\u0430 \u0442\u0435\u0433\u0435 \u043D\u0435 \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044F.`);
4312
+ const parameters = input.inputs !== void 0 && Object.keys(input.inputs).length > 0 ? input.inputs : void 0;
4313
+ if (parameters !== void 0 && !capabilities.trigger.inputs) throw new TrackerError("unsupported", `\u0417\u0430\u043F\u0443\u0441\u043A ${subject}: \u043F\u0430\u0440\u0430\u043C\u0435\u0442\u0440\u044B \u0437\u0430\u043F\u0443\u0441\u043A\u0430 \u043D\u0435 \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044E\u0442\u0441\u044F.`);
4314
+ const inputs = {
4315
+ ref: input.ref,
4316
+ refType: capabilities.trigger.tags ? input.refType ?? "branch" : void 0,
4317
+ workflow: mode === "one" ? workflows[0] : void 0,
4318
+ workflows: mode === "many" ? workflows : void 0,
4319
+ inputs: parameters
4320
+ };
4321
+ if (call.operation.result === void 0) {
4322
+ await callJson(context, call, inputs);
4323
+ return {};
4324
+ }
4325
+ return { run: await single(context, call, inputs) };
4326
+ },
4327
+ rerun: async (key, input) => {
4328
+ const name = input.failedOnly === true ? "rerunFailed" : "rerun";
4329
+ const call = requireCall(config, "ci", name, input.failedOnly === true ? "\u043F\u0435\u0440\u0435\u0437\u0430\u043F\u0443\u0441\u043A\u0430\u0442\u044C \u0443\u043F\u0430\u0432\u0448\u0438\u0435 \u0437\u0430\u0434\u0430\u043D\u0438\u044F" : "\u043F\u0435\u0440\u0435\u0437\u0430\u043F\u0443\u0441\u043A\u0430\u0442\u044C \u043F\u0440\u043E\u0433\u043E\u043D \u0446\u0435\u043B\u0438\u043A\u043E\u043C");
4330
+ debugOf(name, input.debug);
4331
+ await callJson(context, call, { key, debug: input.debug }, { ...missingRun(key), conflictOn: ACTION_CONFLICT });
4332
+ return getRun(key);
4333
+ },
4334
+ rerunJob: async (key, input) => {
4335
+ const call = requireCall(config, "ci", "rerunJob", "\u043F\u0435\u0440\u0435\u0437\u0430\u043F\u0443\u0441\u043A\u0430\u0442\u044C \u0437\u0430\u0434\u0430\u043D\u0438\u0435");
4336
+ debugOf("rerunJob", input.debug);
4337
+ await callJson(context, call, { key, debug: input.debug }, { ...missingJob(key), conflictOn: ACTION_CONFLICT });
4338
+ return getRun((await getJob(key)).runKey);
4339
+ },
4340
+ cancel: async (key) => {
4341
+ await callJson(context, requireCall(config, "ci", "cancel", "\u043E\u0442\u043C\u0435\u043D\u044F\u0442\u044C \u043F\u0440\u043E\u0433\u043E\u043D"), { key }, { ...missingRun(key), conflictOn: ACTION_CONFLICT });
4342
+ return getRun(key);
4343
+ },
4344
+ cancelJob: async (key) => {
4345
+ await callJson(context, requireCall(config, "ci", "cancelJob", "\u043E\u0442\u043C\u0435\u043D\u044F\u0442\u044C \u0437\u0430\u0434\u0430\u043D\u0438\u0435"), { key }, { ...missingJob(key), conflictOn: ACTION_CONFLICT });
4346
+ return getJob(key);
4347
+ }
4348
+ };
4349
+ }
4350
+
4351
+ // src/tracker/declarative/declarative-issues.lib.ts
4352
+ var MISSING = { missingIsIssue: true };
4353
+ function createIssuesAdapter(config, adapterContext, capabilities, features) {
4354
+ const context = contextOf(config, adapterContext);
4355
+ const subject = `\u0417\u0430\u0434\u0430\u0447\u0438 \xAB${config.title}\xBB`;
4356
+ const comments = `\u041A\u043E\u043C\u043C\u0435\u043D\u0442\u0430\u0440\u0438\u0438 \xAB${config.title}\xBB`;
4357
+ const get = (key) => single(context, requireCall(config, "issues", "get", "\u043F\u043E\u043A\u0430\u0437\u044B\u0432\u0430\u0442\u044C \u0437\u0430\u0434\u0430\u0447\u0438"), { key }, MISSING);
4358
+ return {
4359
+ list: async (query) => {
4360
+ const call = requireCall(config, "issues", "list", "\u043F\u043E\u043A\u0430\u0437\u044B\u0432\u0430\u0442\u044C \u0437\u0430\u0434\u0430\u0447\u0438");
4361
+ assertListQuery(subject, capabilities.list, query, ISSUE_FILTERS);
4362
+ const page = await list(
4363
+ context,
4364
+ call,
4365
+ {
4366
+ status: query.status,
4367
+ labels: query.labels,
4368
+ assignee: query.assignee,
4369
+ author: query.author,
4370
+ search: query.search,
4371
+ createdAfter: isoOf(query.createdAfter),
4372
+ createdBefore: isoOf(query.createdBefore),
4373
+ updatedAfter: isoOf(query.updatedAfter),
4374
+ updatedBefore: isoOf(query.updatedBefore),
4375
+ ...sortInputs(query.sort)
4376
+ },
4377
+ query
4378
+ );
4379
+ return { ...page, items: page.items.filter(issueFilter(capabilities, query)) };
4380
+ },
4381
+ get,
4382
+ create: async (input) => {
4383
+ const call = requireCall(config, "issues", "create", "\u0441\u043E\u0437\u0434\u0430\u0432\u0430\u0442\u044C \u0437\u0430\u0434\u0430\u0447\u0438");
4384
+ const inputs = { title: input.title, description: input.description, priority: input.priority, labels: input.labels, assignee: input.assignee };
4385
+ assertUsed(subject, call, inputs);
4386
+ return single(context, call, inputs);
4387
+ },
4388
+ update: async (key, patch) => {
4389
+ const call = requireCall(config, "issues", "update", "\u043C\u0435\u043D\u044F\u0442\u044C \u0437\u0430\u0434\u0430\u0447\u0438");
4390
+ if (patch.status !== void 0 && !features.statuses.includes(patch.status)) throw new TrackerError("unsupported", `${subject}: \u043F\u0435\u0440\u0435\u0432\u043E\u0434 \u0432 ${patch.status} \u043D\u0435 \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044F.`);
4391
+ const inputs = { key, title: patch.title, description: patch.description, status: patch.status, priority: patch.priority, labels: patch.labels, assignee: patch.assignee };
4392
+ assertUsed(subject, call, inputs);
4393
+ if (call.operation.result === void 0) {
4394
+ await callJson(context, call, inputs, MISSING);
4395
+ return get(key);
4396
+ }
4397
+ return single(context, call, inputs, MISSING);
4398
+ },
4399
+ comments: async (key, query) => {
4400
+ const call = requireCall(config, "issues", "comments", "\u043F\u043E\u043A\u0430\u0437\u044B\u0432\u0430\u0442\u044C \u043A\u043E\u043C\u043C\u0435\u043D\u0442\u0430\u0440\u0438\u0438");
4401
+ assertCommentQuery(comments, capabilities.comments, query);
4402
+ return list(context, call, { key, updatedAfter: isoOf(query.updatedAfter), order: query.order ?? capabilities.comments.order[0] }, query, MISSING);
4403
+ },
4404
+ comment: async (key, body) => single(context, requireCall(config, "issues", "comment", "\u043A\u043E\u043C\u043C\u0435\u043D\u0442\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u0437\u0430\u0434\u0430\u0447\u0438"), { key, body }, MISSING)
4405
+ };
4406
+ }
4407
+
4408
+ // src/tracker/declarative/declarative-parse.lib.ts
4409
+ import { isAlias, isMap, isPair, isScalar, isSeq, LineCounter, parseDocument, Parser } from "yaml";
4410
+ function issueAt(path, message) {
4411
+ return { path: path.map(String).join("."), message };
4412
+ }
4413
+ function looksSecret(text2) {
4414
+ return redactSecretText(text2) !== text2;
4415
+ }
4416
+ function literalOf(value) {
4417
+ return value.replace(new RegExp(PLACEHOLDER.source, "g"), "").trim();
4418
+ }
4419
+ function secretPair(key, value) {
4420
+ return typeof value === "string" && isSecretKey(key) && literalOf(value) !== "";
4421
+ }
4422
+ function scanNode(node, path, issues) {
4423
+ if (isAlias(node)) return;
4424
+ if (isScalar(node)) {
4425
+ if (typeof node.value === "string" && looksSecret(node.value)) issues.push(issueAt(path, SECRET_IN_CONFIG));
4426
+ return;
4427
+ }
4428
+ if (isSeq(node)) {
4429
+ node.items.forEach((item, index) => scanNode(item, [...path, index], issues));
4430
+ return;
4431
+ }
4432
+ if (!isMap(node)) return;
4433
+ for (const pair of node.items) {
4434
+ if (!isPair(pair)) continue;
4435
+ const key = isScalar(pair.key) ? String(pair.key.value) : "";
4436
+ const at = [...path, key];
4437
+ if (looksSecret(key) || isScalar(pair.value) && secretPair(key, pair.value.value)) {
4438
+ issues.push(issueAt(at, SECRET_IN_CONFIG));
4439
+ continue;
4440
+ }
4441
+ scanNode(pair.value, at, issues);
4442
+ }
4443
+ }
4444
+ function scanComments(text2, lines, issues) {
4445
+ const visit = (value, depth) => {
4446
+ if (depth > 200 || typeof value !== "object" || value === null) return;
4447
+ if (Array.isArray(value)) {
4448
+ for (const item of value) visit(item, depth + 1);
4449
+ return;
4450
+ }
4451
+ const token = value;
4452
+ if (token.type === "comment" && typeof token.source === "string" && typeof token.offset === "number") {
4453
+ if (looksSecret(token.source)) issues.push({ path: "", message: `\u0441\u0442\u0440\u043E\u043A\u0430 ${String(lines.linePos(token.offset).line)}, \u043A\u043E\u043C\u043C\u0435\u043D\u0442\u0430\u0440\u0438\u0439: ${SECRET_IN_CONFIG}` });
4454
+ return;
4455
+ }
4456
+ for (const item of Object.values(value)) visit(item, depth + 1);
4457
+ };
4458
+ for (const token of new Parser().parse(text2)) visit(token, 0);
4459
+ }
4460
+ function scanValue(value, path, issues, depth) {
4461
+ if (depth > TRACKER_CONFIG_DEPTH_MAX) return;
4462
+ if (typeof value === "string") {
4463
+ if (looksSecret(value)) issues.push(issueAt(path, SECRET_IN_CONFIG));
4464
+ return;
4465
+ }
4466
+ if (Array.isArray(value)) {
4467
+ value.forEach((item, index) => scanValue(item, [...path, index], issues, depth + 1));
4468
+ return;
4469
+ }
4470
+ if (typeof value !== "object" || value === null) return;
4471
+ for (const [key, item] of Object.entries(value)) {
4472
+ const at = [...path, key];
4473
+ if (looksSecret(key) || secretPair(key, item)) {
4474
+ issues.push(issueAt(at, SECRET_IN_CONFIG));
4475
+ continue;
4476
+ }
4477
+ scanValue(item, at, issues, depth + 1);
4478
+ }
4479
+ }
4480
+ function scanShape(value, path, issues, depth, seen = /* @__PURE__ */ new WeakMap()) {
4481
+ if (typeof value !== "object" || value === null || issues.length >= TRACKER_CONFIG_ISSUES_MAX) return;
4482
+ if (depth > TRACKER_CONFIG_DEPTH_MAX) {
4483
+ issues.push(issueAt(path, `\u0432\u043B\u043E\u0436\u0435\u043D\u043D\u043E\u0441\u0442\u044C \u0431\u043E\u043B\u044C\u0448\u0435 ${String(TRACKER_CONFIG_DEPTH_MAX)} \u0443\u0440\u043E\u0432\u043D\u0435\u0439`));
4484
+ return;
4485
+ }
4486
+ const before = seen.get(value);
4487
+ if (before !== void 0 && before <= depth) return;
4488
+ seen.set(value, depth);
4489
+ if (Array.isArray(value)) {
4490
+ value.forEach((item, index) => scanShape(item, [...path, index], issues, depth + 1, seen));
4491
+ return;
4492
+ }
4493
+ for (const [key, item] of Object.entries(value)) {
4494
+ if (issues.length >= TRACKER_CONFIG_ISSUES_MAX) return;
4495
+ if (FORBIDDEN_KEYS.includes(key)) {
4496
+ issues.push(issueAt([...path, key], `\u0438\u043C\u044F \xAB${key}\xBB \u0432 \u043A\u043E\u043D\u0444\u0438\u0433\u0435 \u043D\u0435\u0434\u043E\u043F\u0443\u0441\u0442\u0438\u043C\u043E`));
4497
+ continue;
4498
+ }
4499
+ scanShape(item, [...path, key], issues, depth + 1, seen);
4500
+ }
4501
+ }
4502
+ function tooLarge(bytes) {
4503
+ return { path: "", message: `\u043A\u043E\u043D\u0444\u0438\u0433 ${String(bytes)} \u0431\u0430\u0439\u0442 \u0431\u043E\u043B\u044C\u0448\u0435 \u043F\u0440\u0435\u0434\u0435\u043B\u0430 ${String(TRACKER_CONFIG_MAX_BYTES)} \u0431\u0430\u0439\u0442` };
4504
+ }
4505
+ function parseText(text2) {
4506
+ const bytes = Buffer.byteLength(text2, "utf8");
4507
+ if (bytes > TRACKER_CONFIG_MAX_BYTES) return { issues: [tooLarge(bytes)], secret: false };
4508
+ const lines = new LineCounter();
4509
+ const document = parseDocument(text2, { lineCounter: lines, uniqueKeys: true, prettyErrors: false, strict: true });
4510
+ const secrets = [];
4511
+ scanComments(text2, lines, secrets);
4512
+ scanNode(document.contents, [], secrets);
4513
+ if (document.errors.length > 0) {
4514
+ const errors = document.errors.map((error) => ({ path: "", message: `\u0441\u0442\u0440\u043E\u043A\u0430 ${String(lines.linePos(error.pos[0]).line)}: ${error.message.split("\n")[0] ?? ""}` }));
4515
+ return { issues: [...secrets, ...errors], secret: secrets.length > 0 };
4516
+ }
4517
+ let data;
4518
+ try {
4519
+ data = document.toJS({ maxAliasCount: TRACKER_CONFIG_YAML_ALIAS_MAX });
4520
+ } catch (error) {
4521
+ return { issues: [...secrets, { path: "", message: `YAML \u043D\u0435 \u0440\u0430\u0437\u043E\u0431\u0440\u0430\u043B\u0441\u044F: ${error instanceof Error ? error.message : String(error)}` }], secret: secrets.length > 0 };
4522
+ }
4523
+ const shape = [];
4524
+ scanShape(data, [], shape, 0);
4525
+ return { ...shape.length === 0 ? { data } : {}, issues: [...secrets, ...shape], secret: secrets.length > 0 };
4526
+ }
4527
+ function parseObject(value) {
4528
+ let json;
4529
+ try {
4530
+ json = JSON.stringify(value);
4531
+ } catch (error) {
4532
+ return { issues: [{ path: "", message: `\u043A\u043E\u043D\u0444\u0438\u0433 \u2014 \u043D\u0435 JSON: ${error instanceof Error ? error.message : String(error)}` }], secret: false };
4533
+ }
4534
+ if (json === void 0) return { issues: [{ path: "", message: "\u043A\u043E\u043D\u0444\u0438\u0433 \u2014 \u043D\u0435 JSON: \u043E\u0431\u044A\u0435\u043A\u0442 \u043D\u0435 \u0441\u0435\u0440\u0438\u0430\u043B\u0438\u0437\u0443\u0435\u0442\u0441\u044F" }], secret: false };
4535
+ const bytes = Buffer.byteLength(json, "utf8");
4536
+ if (bytes > TRACKER_CONFIG_MAX_BYTES) return { issues: [tooLarge(bytes)], secret: false };
4537
+ const data = JSON.parse(json);
4538
+ const shape = [];
4539
+ scanShape(data, [], shape, 0);
4540
+ if (shape.length > 0) return { issues: shape, secret: false };
4541
+ const secrets = [];
4542
+ scanValue(data, [], secrets, 0);
4543
+ return { data, issues: secrets, secret: secrets.length > 0 };
4544
+ }
4545
+ function parseConfigInput(input) {
4546
+ if (typeof input === "string") return parseText(input);
4547
+ if (typeof input === "object" && input !== null && !Array.isArray(input)) return parseObject(input);
4548
+ return { issues: [{ path: "", message: "\u043A\u043E\u043D\u0444\u0438\u0433 \u2014 \u0442\u0435\u043A\u0441\u0442 YAML \u0438\u043B\u0438 \u043E\u0431\u044A\u0435\u043A\u0442" }], secret: false };
4549
+ }
4550
+
4551
+ // src/tracker/declarative/declarative-pull.lib.ts
4552
+ var MERGE_CONFLICT = [405, 409, 422];
4553
+ function createPullAdapter2(config, adapterContext, capabilities) {
4554
+ const context = contextOf(config, adapterContext);
4555
+ const subject = `PR \xAB${config.title}\xBB`;
4556
+ 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}.` } });
4557
+ const get = (key) => single(context, requireCall(config, "pulls", "get", "\u043F\u043E\u043A\u0430\u0437\u044B\u0432\u0430\u0442\u044C PR"), { key }, missing(key));
4558
+ return {
4559
+ list: async (query) => {
4560
+ const call = requireCall(config, "pulls", "list", "\u043F\u043E\u043A\u0430\u0437\u044B\u0432\u0430\u0442\u044C PR");
4561
+ assertListQuery(subject, capabilities.list, query, pullRequestFilterSchema.options);
4562
+ const page = await list(
4563
+ context,
4564
+ call,
4565
+ {
4566
+ status: query.status,
4567
+ author: query.author,
4568
+ sourceBranch: query.source,
4569
+ targetBranch: query.target,
4570
+ labels: query.labels,
4571
+ search: query.search,
4572
+ createdAfter: isoOf(query.createdAfter),
4573
+ createdBefore: isoOf(query.createdBefore),
4574
+ updatedAfter: isoOf(query.updatedAfter),
4575
+ updatedBefore: isoOf(query.updatedBefore),
4576
+ ...sortInputs(query.sort)
4577
+ },
4578
+ query
4579
+ );
4580
+ return { ...page, items: page.items.filter(pullFilter(capabilities, query)) };
4581
+ },
4582
+ get,
4583
+ create: async (input) => {
4584
+ const call = requireCall(config, "pulls", "create", "\u0441\u043E\u0437\u0434\u0430\u0432\u0430\u0442\u044C PR");
4585
+ const inputs = { title: input.title, sourceBranch: input.source, targetBranch: input.target, description: input.description, draft: input.draft };
4586
+ assertUsed(subject, call, inputs);
4587
+ return single(context, call, inputs);
4588
+ },
4589
+ update: async (key, patch) => {
4590
+ const call = requireCall(config, "pulls", "update", "\u043C\u0435\u043D\u044F\u0442\u044C PR");
4591
+ if (patch.status !== void 0 && !capabilities.statuses.includes(patch.status)) throw new TrackerError("unsupported", `${subject}: \u043F\u0435\u0440\u0435\u0432\u043E\u0434 \u0432 ${patch.status} \u043D\u0435 \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044F.`);
4592
+ const inputs = { key, title: patch.title, description: patch.description, targetBranch: patch.target, status: patch.status };
4593
+ assertUsed(subject, call, inputs);
4594
+ if (call.operation.result === void 0) {
4595
+ await callJson(context, call, inputs, missing(key));
4596
+ return get(key);
4597
+ }
4598
+ return single(context, call, inputs, missing(key));
4599
+ },
4600
+ merge: async (key, input) => {
4601
+ const call = requireCall(config, "pulls", "merge", "\u0441\u043B\u0438\u0432\u0430\u0442\u044C PR");
4602
+ const used = usedNames(call.operation);
4603
+ const method = input.method ?? capabilities.merge[0];
4604
+ if (method === void 0 || !capabilities.merge.includes(method)) throw new TrackerError("unsupported", `${subject}: \u0441\u043B\u0438\u044F\u043D\u0438\u0435 \u0441\u043F\u043E\u0441\u043E\u0431\u043E\u043C ${String(method)} \u043D\u0435 \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044F.`);
4605
+ if (input.deleteSource === true && !capabilities.deleteSourceOnMerge) throw new TrackerError("unsupported", `${subject}: \u0443\u0434\u0430\u043B\u0435\u043D\u0438\u0435 \u0432\u0435\u0442\u043A\u0438-\u0438\u0441\u0442\u043E\u0447\u043D\u0438\u043A\u0430 \u043F\u0440\u0438 \u0441\u043B\u0438\u044F\u043D\u0438\u0438 \u043D\u0435 \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044F.`);
4606
+ if (input.message !== void 0 && !used.has("message")) throw new TrackerError("unsupported", `${subject}: \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.`);
4607
+ if (input.headSha !== void 0 && !used.has("headSha")) {
4608
+ const current = await get(key);
4609
+ if (current.headSha === void 0) throw new TrackerError("unsupported", `${subject}: \u0441\u0432\u0435\u0440\u043A\u0430 \u0433\u043E\u043B\u043E\u0432\u044B \u0438\u0441\u0442\u043E\u0447\u043D\u0438\u043A\u0430 \u043D\u0435\u0434\u043E\u0441\u0442\u0443\u043F\u043D\u0430 \u2014 \u0432 \u043E\u0442\u0432\u0435\u0442\u0435 PR \u043D\u0435\u0442 headSha.`);
4610
+ if (current.headSha !== input.headSha.toLowerCase()) throw new TrackerError("conflict", `${subject}: \u0433\u043E\u043B\u043E\u0432\u0430 \u0438\u0441\u0442\u043E\u0447\u043D\u0438\u043A\u0430 ${current.headSha} \u043D\u0435 \u0441\u043E\u0432\u043F\u0430\u043B\u0430 \u0441 ${input.headSha}.`);
4611
+ }
4612
+ const inputs = { key, method, headSha: used.has("headSha") ? input.headSha : void 0, message: input.message, deleteSource: input.deleteSource };
4613
+ await callJson(context, call, inputs, { ...missing(key), conflictOn: MERGE_CONFLICT });
4614
+ return get(key);
4615
+ },
4616
+ comments: async (key, query) => {
4617
+ const call = requireCall(config, "pulls", "comments", "\u043F\u043E\u043A\u0430\u0437\u044B\u0432\u0430\u0442\u044C \u043A\u043E\u043C\u043C\u0435\u043D\u0442\u0430\u0440\u0438\u0438 PR");
4618
+ assertCommentQuery(`\u041A\u043E\u043C\u043C\u0435\u043D\u0442\u0430\u0440\u0438\u0438 PR \xAB${config.title}\xBB`, capabilities.comments, query);
4619
+ return list(context, call, { key, updatedAfter: isoOf(query.updatedAfter), order: query.order ?? capabilities.comments.order[0] }, query, missing(key));
4620
+ },
4621
+ comment: async (key, body) => single(context, requireCall(config, "pulls", "comment", "\u043A\u043E\u043C\u043C\u0435\u043D\u0442\u0438\u0440\u043E\u0432\u0430\u0442\u044C PR"), { key, body }, missing(key))
4622
+ };
4623
+ }
4624
+
4625
+ // src/tracker/declarative/declarative-rules.lib.ts
4626
+ var PATH_LITERAL = /^\/[A-Za-z0-9\-._~!$&'()*+,;=:@/]*$/;
4627
+ var SECTIONS = ["issues", "pulls", "ci"];
4628
+ function declared(config) {
4629
+ return new Set(config.fields.map((field) => field.name));
4630
+ }
4631
+ function checkTemplate(config, template, path, inputs, where, issues) {
4632
+ const fields = declared(config);
4633
+ for (const { name, modifier } of placeholdersOf(template)) {
4634
+ if (name === "token") {
4635
+ issues.push(issueAt(path, "\u043F\u043B\u0435\u0439\u0441\u0445\u043E\u043B\u0434\u0435\u0440\u0430 {{token}} \u043D\u0435\u0442: \u0442\u043E\u043A\u0435\u043D \u043F\u043E\u0434\u0441\u0442\u0430\u0432\u043B\u044F\u0435\u0442 \u0442\u043E\u043B\u044C\u043A\u043E http.auth \u0438 \u0442\u043E\u043B\u044C\u043A\u043E \u0434\u043B\u044F origin http.base"));
4636
+ continue;
4637
+ }
4638
+ if (CONNECTION_PLACEHOLDERS.includes(name)) {
4639
+ if (!fields.has(name)) issues.push(issueAt(path, `\u043F\u043E\u043B\u0435 \u043F\u043E\u0434\u043A\u043B\u044E\u0447\u0435\u043D\u0438\u044F \xAB${name}\xBB \u043D\u0435 \u043E\u0431\u044A\u044F\u0432\u043B\u0435\u043D\u043E \u0432 fields`));
4640
+ } else if (!inputs.includes(name)) {
4641
+ const known = [...CONNECTION_PLACEHOLDERS.filter((field) => fields.has(field)), ...inputs].join(", ") || "\u043D\u0435\u0442";
4642
+ issues.push(issueAt(path, `\u043D\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043D\u044B\u0439 \u043F\u043B\u0435\u0439\u0441\u0445\u043E\u043B\u0434\u0435\u0440 {{${name}}}; \u0437\u0434\u0435\u0441\u044C \u0434\u043E\u0441\u0442\u0443\u043F\u043D\u044B: ${known}`));
4643
+ continue;
4644
+ }
4645
+ if (modifier !== void 0 && !(modifier === "path" && where === "path")) {
4646
+ issues.push(issueAt(path, `\u043C\u043E\u0434\u0438\u0444\u0438\u043A\u0430\u0442\u043E\u0440 |${modifier} \u043D\u0435\u0434\u043E\u043F\u0443\u0441\u0442\u0438\u043C: \u0435\u0441\u0442\u044C \u0442\u043E\u043B\u044C\u043A\u043E |path, \u0438 \u0442\u043E\u043B\u044C\u043A\u043E \u0432 \u043F\u0443\u0442\u0438 \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u0438`));
4647
+ }
4648
+ if (OBJECT_INPUTS.includes(name) && !(where === "body" && wholePlaceholder(template) === name)) {
4649
+ issues.push(issueAt(path, `\u0432\u0445\u043E\u0434 ${name} \u2014 \u0441\u043B\u043E\u0432\u0430\u0440\u044C: \u043E\u043D \u043F\u043E\u0434\u0441\u0442\u0430\u0432\u043B\u044F\u0435\u0442\u0441\u044F \u0442\u043E\u043B\u044C\u043A\u043E \u0446\u0435\u043B\u044B\u043C \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435\u043C \u0442\u0435\u043B\u0430 ("{{${name}}}")`));
4650
+ }
4651
+ }
4652
+ const rest = template.replace(new RegExp(PLACEHOLDER.source, "g"), "");
4653
+ if (rest.includes("{{") || rest.includes("}}")) issues.push(issueAt(path, "\u043D\u0435\u0437\u0430\u043A\u0440\u044B\u0442\u044B\u0439 \u0438\u043B\u0438 \u043D\u0435\u0432\u0435\u0440\u043D\u044B\u0439 \u043F\u043B\u0435\u0439\u0441\u0445\u043E\u043B\u0434\u0435\u0440: \u043E\u0436\u0438\u0434\u0430\u0435\u0442\u0441\u044F {{\u0438\u043C\u044F}} \u0438\u043B\u0438 {{\u0438\u043C\u044F|path}}"));
4654
+ }
4655
+ function checkPath(config, template, path, inputs, issues) {
4656
+ checkTemplate(config, template, path, inputs, "path", issues);
4657
+ const literal = template.replace(new RegExp(PLACEHOLDER.source, "g"), "x");
4658
+ if (!template.startsWith("/") || template.startsWith("//")) {
4659
+ issues.push(issueAt(path, "\u043F\u0443\u0442\u044C \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u0438 \u043D\u0430\u0447\u0438\u043D\u0430\u0435\u0442\u0441\u044F \u0441 \u043E\u0434\u043D\u043E\u0433\u043E \xAB/\xBB: \u0430\u0434\u0440\u0435\u0441 \u0441\u043E\u0431\u0438\u0440\u0430\u0435\u0442\u0441\u044F \u043E\u0442 http.base"));
4660
+ return;
4661
+ }
4662
+ if (!PATH_LITERAL.test(literal)) {
4663
+ issues.push(issueAt(path, "\u0432 \u043F\u0443\u0442\u0438 \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u0438 \u0442\u043E\u043B\u044C\u043A\u043E \u043B\u0430\u0442\u0438\u043D\u0438\u0446\u0430, \u0446\u0438\u0444\u0440\u044B, \xAB/\xBB \u0438 \u0441\u0438\u043C\u0432\u043E\u043B\u044B -._~!$&'()*+,;=:@ \u2014 \u0431\u0435\u0437 \xAB?\xBB, \xAB#\xBB, \xAB%\xBB, \xAB\\\xBB \u0438 \u043F\u0440\u043E\u0431\u0435\u043B\u043E\u0432; \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u044F \u043A\u043E\u0434\u0438\u0440\u0443\u0435\u0442 \u0438\u043D\u0442\u0435\u0440\u043F\u0440\u0435\u0442\u0430\u0442\u043E\u0440"));
4664
+ return;
4665
+ }
4666
+ const segments = template.split("/").slice(1);
4667
+ if (segments.some((part) => part === "." || part === "..")) issues.push(issueAt(path, "\u0441\u0435\u0433\u043C\u0435\u043D\u0442\u044B \xAB.\xBB \u0438 \xAB..\xBB \u0443\u0432\u043E\u0434\u044F\u0442 \u0430\u0434\u0440\u0435\u0441 \u0441 \u0431\u0430\u0437\u044B: \u043E\u043D\u0438 \u0432 \u043F\u0443\u0442\u0438 \u0437\u0430\u043F\u0440\u0435\u0449\u0435\u043D\u044B"));
4668
+ }
4669
+ function checkBase(config, issues) {
4670
+ const path = ["http", "base"];
4671
+ const base = config.http.base;
4672
+ const head = /^\{\{\s*url\s*\}\}/.exec(base);
4673
+ const rest = head === null ? base : base.slice(head[0].length);
4674
+ if (head !== null) {
4675
+ if (!declared(config).has("url")) issues.push(issueAt(path, "\u043F\u043E\u043B\u0435 \u043F\u043E\u0434\u043A\u043B\u044E\u0447\u0435\u043D\u0438\u044F \xABurl\xBB \u043D\u0435 \u043E\u0431\u044A\u044F\u0432\u043B\u0435\u043D\u043E \u0432 fields"));
4676
+ if (rest !== "" && !rest.startsWith("/")) issues.push(issueAt(path, "\u043F\u043E\u0441\u043B\u0435 {{url}} \u2014 \u0442\u043E\u043B\u044C\u043A\u043E \u043F\u0443\u0442\u044C \u043E\u0442 \xAB/\xBB: url \u043F\u043E\u0434\u043A\u043B\u044E\u0447\u0435\u043D\u0438\u044F \u0437\u0430\u0434\u0430\u0451\u0442 origin \u0446\u0435\u043B\u0438\u043A\u043E\u043C"));
4677
+ } else if (!/^https?:\/\/[^/?#@{}\s]+(?:\/[^?#{}\s]*)?$/.test(base)) {
4678
+ issues.push(issueAt(path, "http.base \u2014 \u0430\u0434\u0440\u0435\u0441 http(s) \u0431\u0435\u0437 \u043F\u0430\u0440\u0430\u043C\u0435\u0442\u0440\u043E\u0432, \u044F\u043A\u043E\u0440\u044F \u0438 \u0438\u043C\u0435\u043D\u0438 \u0441 \u043F\u0430\u0440\u043E\u043B\u0435\u043C, \u0438\u043B\u0438 {{url}} \u0438 \u043F\u0443\u0442\u044C \u043F\u043E\u0441\u043B\u0435 \u043D\u0435\u0433\u043E"));
4679
+ return;
4680
+ }
4681
+ if (rest.includes("{{") || rest.includes("}}")) issues.push(issueAt(path, "\u0432 http.base \u043F\u043B\u0435\u0439\u0441\u0445\u043E\u043B\u0434\u0435\u0440 \u0442\u043E\u043B\u044C\u043A\u043E \u043E\u0434\u0438\u043D \u2014 {{url}} \u0432 \u043D\u0430\u0447\u0430\u043B\u0435"));
4682
+ if (/[?#\\\s%]/.test(rest)) issues.push(issueAt(path, "\u043F\u0443\u0442\u044C http.base \u0431\u0435\u0437 \xAB?\xBB, \xAB#\xBB, \xAB%\xBB, \xAB\\\xBB \u0438 \u043F\u0440\u043E\u0431\u0435\u043B\u043E\u0432"));
4683
+ if (rest.split("/").some((part) => part === "." || part === "..")) issues.push(issueAt(path, "\u0441\u0435\u0433\u043C\u0435\u043D\u0442\u044B \xAB.\xBB \u0438 \xAB..\xBB \u0432 http.base \u0437\u0430\u043F\u0440\u0435\u0449\u0435\u043D\u044B"));
4684
+ }
4685
+ function checkHeaders(config, issues) {
4686
+ for (const [name, value] of Object.entries(config.http.headers ?? {})) {
4687
+ const path = ["http", "headers", name];
4688
+ if (isSecretKey(name)) issues.push(issueAt(path, "\u0437\u0430\u0433\u043E\u043B\u043E\u0432\u043E\u043A \u043F\u043E\u0445\u043E\u0436 \u043D\u0430 \u0441\u0435\u043A\u0440\u0435\u0442\u043D\u044B\u0439: \u0430\u0432\u0442\u043E\u0440\u0438\u0437\u0430\u0446\u0438\u044F \u2014 \u0442\u043E\u043B\u044C\u043A\u043E \u0447\u0435\u0440\u0435\u0437 http.auth"));
4689
+ if (RESERVED_HEADERS.includes(name.toLowerCase())) issues.push(issueAt(path, `\u0437\u0430\u0433\u043E\u043B\u043E\u0432\u043E\u043A ${name} \u0437\u0430\u0434\u0430\u0451\u0442 \u0441\u0430\u043C \u043A\u043B\u0438\u0435\u043D\u0442 HTTP`));
4690
+ if (config.http.auth.kind === "header" && config.http.auth.header.toLowerCase() === name.toLowerCase()) issues.push(issueAt(path, `\u0437\u0430\u0433\u043E\u043B\u043E\u0432\u043E\u043A ${name} \u0437\u0430\u043D\u044F\u0442 \u0430\u0432\u0442\u043E\u0440\u0438\u0437\u0430\u0446\u0438\u0435\u0439 http.auth`));
4691
+ if (/[\r\n\0]/.test(value)) issues.push(issueAt(path, "\u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435 \u0437\u0430\u0433\u043E\u043B\u043E\u0432\u043A\u0430 \u0431\u0435\u0437 \u043F\u0435\u0440\u0435\u0432\u043E\u0434\u0430 \u0441\u0442\u0440\u043E\u043A\u0438"));
4692
+ checkTemplate(config, value, path, [], "header", issues);
4693
+ }
4694
+ const auth = config.http.auth;
4695
+ if (auth.kind === "header" && RESERVED_HEADERS.includes(auth.header.toLowerCase())) {
4696
+ issues.push(issueAt(["http", "auth", "header"], `\u0437\u0430\u0433\u043E\u043B\u043E\u0432\u043E\u043A ${auth.header} \u0437\u0430\u0434\u0430\u0451\u0442 \u0441\u0430\u043C \u043A\u043B\u0438\u0435\u043D\u0442 HTTP`));
4697
+ }
4698
+ }
4699
+ function checkFields(config, issues) {
4700
+ const names = config.fields.map((field) => field.name);
4701
+ config.fields.forEach((field, index) => {
4702
+ if (names.indexOf(field.name) !== index) issues.push(issueAt(["fields", index, "name"], `\u043F\u043E\u043B\u0435 \xAB${field.name}\xBB \u043E\u0431\u044A\u044F\u0432\u043B\u0435\u043D\u043E \u0434\u0432\u0430\u0436\u0434\u044B`));
4703
+ if (field.secret !== (field.name === "token")) issues.push(issueAt(["fields", index, "secret"], "\u0441\u0435\u043A\u0440\u0435\u0442\u043D\u044B\u043C \u0431\u044B\u0432\u0430\u0435\u0442 \u0442\u043E\u043B\u044C\u043A\u043E \u043F\u043E\u043B\u0435 token, \u0438 \u043E\u043D\u043E \u0432\u0441\u0435\u0433\u0434\u0430 \u0441\u0435\u043A\u0440\u0435\u0442\u043D\u043E\u0435"));
4704
+ });
4705
+ const auth = config.http.auth;
4706
+ if (auth.kind === "none" && names.includes("token")) issues.push(issueAt(["http", "auth"], "\u043F\u043E\u043B\u0435 token \u0431\u0435\u0437 \u0430\u0432\u0442\u043E\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u043D\u0435 \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0435\u0442\u0441\u044F: \u0443\u043A\u0430\u0436\u0438\u0442\u0435 http.auth"));
4707
+ if (auth.kind !== "none" && !names.includes("token")) issues.push(issueAt(["fields"], `\u0430\u0432\u0442\u043E\u0440\u0438\u0437\u0430\u0446\u0438\u0438 ${auth.kind} \u043D\u0443\u0436\u043D\u043E \u043F\u043E\u043B\u0435 token`));
4708
+ if (auth.kind === "basic" && !names.includes("user")) issues.push(issueAt(["fields"], "\u0430\u0432\u0442\u043E\u0440\u0438\u0437\u0430\u0446\u0438\u0438 basic \u043D\u0443\u0436\u043D\u043E \u043F\u043E\u043B\u0435 user"));
4709
+ }
4710
+ function checkPagination(pagination, path, issues) {
4711
+ if (pagination.style === "none") return;
4712
+ const params = pagination.style === "page" ? [pagination.page, pagination.size] : [pagination.param, ...pagination.size === void 0 ? [] : [pagination.size]];
4713
+ for (const name of params) {
4714
+ if (isSecretKey(name)) issues.push(issueAt(path, `\u043F\u0430\u0440\u0430\u043C\u0435\u0442\u0440 ${name} \u043F\u043E\u0445\u043E\u0436 \u043D\u0430 \u0441\u0435\u043A\u0440\u0435\u0442\u043D\u044B\u0439: \u0442\u043E\u043A\u0435\u043D \u0432 query \u043D\u0435 \u043F\u0435\u0440\u0435\u0434\u0430\u044E\u0442`));
4715
+ }
4716
+ }
4717
+ function checkValue(field, spec, path, issues) {
4718
+ const items = Array.isArray(spec) ? spec : [spec];
4719
+ items.forEach((item, index) => {
4720
+ const at = Array.isArray(spec) ? [...path, index] : path;
4721
+ const itemPath = typeof item === "string" ? item : item.path;
4722
+ if (itemPath.includes("[*]") && field.type !== "list") issues.push(issueAt(at, "[*] \u0434\u0430\u0451\u0442 \u0441\u043F\u0438\u0441\u043E\u043A: \u043E\u043D \u0434\u043E\u043F\u0443\u0441\u0442\u0438\u043C \u0442\u043E\u043B\u044C\u043A\u043E \u0443 \u043F\u043E\u043B\u044F-\u0441\u043F\u0438\u0441\u043A\u0430"));
4723
+ if (typeof item === "string") return;
4724
+ if (item.exists === true && field.type !== "flag") issues.push(issueAt([...at, "exists"], "exists \u0434\u0430\u0451\u0442 \u0444\u043B\u0430\u0433: \u043E\u043D \u0434\u043E\u043F\u0443\u0441\u0442\u0438\u043C \u0442\u043E\u043B\u044C\u043A\u043E \u0443 \u043F\u043E\u043B\u044F-\u0444\u043B\u0430\u0433\u0430"));
4725
+ const values = field.type === "flag" ? ["true", "false"] : field.values;
4726
+ if (values === void 0) return;
4727
+ for (const [from, to] of Object.entries(item.map ?? {})) {
4728
+ if (!values.includes(String(to))) issues.push(issueAt([...at, "map", from], `\u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435 \xAB${String(to)}\xBB \u043D\u0435 \u0438\u0437 \u043F\u0435\u0440\u0435\u0447\u043D\u044F ${values.join(", ")}`));
4729
+ }
4730
+ if (item.default !== void 0 && !values.includes(String(item.default))) issues.push(issueAt([...at, "default"], `\u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435 \xAB${String(item.default)}\xBB \u043D\u0435 \u0438\u0437 \u043F\u0435\u0440\u0435\u0447\u043D\u044F ${values.join(", ")}`));
4731
+ });
4732
+ }
4733
+ function checkResult(section, name, operation2, spec, path, issues) {
4734
+ const result = operation2.result;
4735
+ if (spec.text === true) {
4736
+ if (operation2.items !== void 0) issues.push(issueAt([...path, "items"], "\u043E\u0442\u0432\u0435\u0442 \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u0438 \u2014 \u0442\u0435\u043A\u0441\u0442: items \u0443 \u043D\u0435\u0451 \u043D\u0435\u0442"));
4737
+ if (result !== void 0) issues.push(issueAt([...path, "result"], "\u043E\u0442\u0432\u0435\u0442 \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u0438 \u2014 \u0442\u0435\u043A\u0441\u0442: result \u0443 \u043D\u0435\u0451 \u043D\u0435\u0442"));
4738
+ return;
4739
+ }
4740
+ if (spec.result === "forbidden") {
4741
+ if (result !== void 0 || operation2.items !== void 0) issues.push(issueAt(path, "\u0443 \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u0438 \u043D\u0435\u0442 result \u0438 items: \u043F\u043E\u0441\u043B\u0435 \u043D\u0435\u0451 \u044D\u043B\u0435\u043C\u0435\u043D\u0442 \u043F\u0435\u0440\u0435\u0447\u0438\u0442\u044B\u0432\u0430\u0435\u0442\u0441\u044F"));
4742
+ return;
4743
+ }
4744
+ if (operation2.items?.includes("[*]") === true && spec.list !== true) issues.push(issueAt([...path, "items"], "\u043E\u043F\u0435\u0440\u0430\u0446\u0438\u044F \u0432\u043E\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043E\u0434\u0438\u043D \u044D\u043B\u0435\u043C\u0435\u043D\u0442: [*] \u0432 items \u2014 \u0442\u043E\u043B\u044C\u043A\u043E \u0443 \u0441\u043F\u0438\u0441\u043A\u043E\u0432"));
4745
+ if (result === void 0) {
4746
+ if (spec.result === "required") issues.push(issueAt([...path, "result"], "\u043D\u0443\u0436\u0435\u043D result: \u0438\u0437 \u0447\u0435\u0433\u043E \u0441\u043E\u0431\u0440\u0430\u0442\u044C \u044D\u043B\u0435\u043C\u0435\u043D\u0442 \u0435\u0434\u0438\u043D\u043E\u0439 \u043C\u043E\u0434\u0435\u043B\u0438"));
4747
+ return;
4748
+ }
4749
+ const model = spec.model;
4750
+ if (model === void 0) return;
4751
+ const fields = RESULT_FIELDS[model];
4752
+ for (const [field, value] of Object.entries(result)) {
4753
+ const target = Object.hasOwn(fields, field) ? fields[field] : void 0;
4754
+ if (target === void 0) {
4755
+ issues.push(issueAt([...path, "result", field], `\u0443 \u043C\u043E\u0434\u0435\u043B\u0438 ${model} \u043D\u0435\u0442 \u043F\u043E\u043B\u044F \xAB${field}\xBB; \u043F\u043E\u043B\u044F: ${Object.keys(fields).join(", ")}`));
4756
+ continue;
4757
+ }
4758
+ checkValue(target, value, [...path, "result", field], issues);
4759
+ }
4760
+ const required = [...Object.entries(fields).filter(([, field]) => field.required === true).map(([field]) => field), ...OPERATION_REQUIRED_FIELDS[`${section}.${name}`] ?? []];
4761
+ for (const field of required) {
4762
+ if (result[field] === void 0) issues.push(issueAt([...path, "result"], `\u043D\u0435\u0442 \u043E\u0431\u044F\u0437\u0430\u0442\u0435\u043B\u044C\u043D\u043E\u0433\u043E \u043F\u043E\u043B\u044F \xAB${field}\xBB \u043C\u043E\u0434\u0435\u043B\u0438 ${model}`));
4763
+ }
4764
+ }
4765
+ function checkTables(section, name, operation2, spec, used, path, issues) {
4766
+ for (const [input, table] of Object.entries(operation2.inputs ?? {})) {
4767
+ const at = [...path, "inputs", input];
4768
+ if (!spec.inputs.includes(input)) {
4769
+ issues.push(issueAt(at, `\u0443 \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u0438 \u043D\u0435\u0442 \u0432\u0445\u043E\u0434\u0430 \xAB${input}\xBB; \u0432\u0445\u043E\u0434\u044B: ${spec.inputs.join(", ") || "\u043D\u0435\u0442"}`));
4770
+ continue;
4771
+ }
4772
+ const domain = INPUT_DOMAINS[section][input];
4773
+ if (domain === void 0) {
4774
+ issues.push(issueAt(at, `\u0443 \u0432\u0445\u043E\u0434\u0430 ${input} \u043D\u0435\u0442 \u0442\u0430\u0431\u043B\u0438\u0446\u044B \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0439: \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435 \u043F\u043E\u0434\u0441\u0442\u0430\u0432\u043B\u044F\u0435\u0442\u0441\u044F \u043A\u0430\u043A \u0435\u0441\u0442\u044C`));
4775
+ continue;
4776
+ }
4777
+ if (!used.has(input)) issues.push(issueAt(at, `\u0442\u0430\u0431\u043B\u0438\u0446\u0430 \u043D\u0435 \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0435\u0442\u0441\u044F: \u0432 \u0448\u0430\u0431\u043B\u043E\u043D\u0430\u0445 \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u0438 \u043D\u0435\u0442 {{${input}}}`));
4778
+ const wildcard = spec.list === true && WILDCARD_INPUTS.includes(input);
4779
+ const allowed = section === "pulls" && name === "update" && input === "status" ? domain.filter((value) => value !== "merged") : domain;
4780
+ for (const key of Object.keys(table)) {
4781
+ if (key === INPUT_ANY && wildcard) continue;
4782
+ if (!allowed.includes(key)) issues.push(issueAt([...at, key], `\u0443 \u0432\u0445\u043E\u0434\u0430 ${input} \u043D\u0435\u0442 \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u044F \xAB${key}\xBB; \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u044F: ${[...allowed, ...wildcard ? [INPUT_ANY] : []].join(", ")}`));
4783
+ }
4784
+ }
4785
+ }
4786
+ function checkOperation(config, section, name, operation2, issues) {
4787
+ const spec = OPERATIONS[section][name];
4788
+ if (spec === void 0) return;
4789
+ const path = [section, name];
4790
+ checkPath(config, operation2.path, [...path, "path"], spec.inputs, issues);
4791
+ for (const [param, value] of Object.entries(operation2.query ?? {})) {
4792
+ if (isSecretKey(param)) issues.push(issueAt([...path, "query", param], "\u043F\u0430\u0440\u0430\u043C\u0435\u0442\u0440 \u043F\u043E\u0445\u043E\u0436 \u043D\u0430 \u0441\u0435\u043A\u0440\u0435\u0442\u043D\u044B\u0439: \u0442\u043E\u043A\u0435\u043D \u0432 query \u043D\u0435 \u043F\u0435\u0440\u0435\u0434\u0430\u044E\u0442, \u0430\u0432\u0442\u043E\u0440\u0438\u0437\u0430\u0446\u0438\u044F \u2014 \u0442\u043E\u043B\u044C\u043A\u043E \u0447\u0435\u0440\u0435\u0437 http.auth"));
4793
+ checkTemplate(config, String(value), [...path, "query", param], spec.inputs, "query", issues);
4794
+ }
4795
+ if (operation2.body !== void 0) {
4796
+ if (operation2.method === "GET") issues.push(issueAt([...path, "body"], "\u0443 GET \u043D\u0435\u0442 \u0442\u0435\u043B\u0430: \u0443\u0431\u0435\u0440\u0438\u0442\u0435 body \u0438\u043B\u0438 \u0441\u043C\u0435\u043D\u0438\u0442\u0435 method"));
4797
+ for (const template of bodyTemplates(operation2.body)) checkTemplate(config, template, [...path, "body"], spec.inputs, "body", issues);
4798
+ }
4799
+ const used = usedNames(operation2);
4800
+ for (const input of spec.required) {
4801
+ if (!used.has(input)) issues.push(issueAt(path, `\u043E\u043F\u0435\u0440\u0430\u0446\u0438\u0438 \u043D\u0443\u0436\u0435\u043D \u0432\u0445\u043E\u0434 {{${input}}} \u0432 \u043F\u0443\u0442\u0438, query \u0438\u043B\u0438 \u0442\u0435\u043B\u0435`));
4802
+ }
4803
+ if (used.has("sort") !== used.has("direction")) issues.push(issueAt(path, "\u0441\u043E\u0440\u0442\u0438\u0440\u043E\u0432\u043A\u0435 \u043D\u0443\u0436\u043D\u044B \u043E\u0431\u0430 \u0432\u0445\u043E\u0434\u0430: {{sort}} \u0438 {{direction}}"));
4804
+ if (used.has("sort") && operation2.inputs?.sort === void 0) issues.push(issueAt([...path, "inputs"], "\u0432\u0445\u043E\u0434\u0443 sort \u043D\u0443\u0436\u043D\u0430 \u0442\u0430\u0431\u043B\u0438\u0446\u0430 inputs.sort: \u043F\u043E\u043B\u0435 \u0435\u0434\u0438\u043D\u043E\u0439 \u043C\u043E\u0434\u0435\u043B\u0438 \u2192 \u043F\u043E\u043B\u0435 API"));
4805
+ if (used.has("workflow") && used.has("workflows")) issues.push(issueAt(path, "\u0437\u0430\u043F\u0443\u0441\u043A \u0431\u0435\u0440\u0451\u0442 \u043E\u0434\u0438\u043D workflow ({{workflow}}) \u0438\u043B\u0438 \u0441\u043F\u0438\u0441\u043E\u043A ({{workflows}}), \u043D\u0435 \u043E\u0431\u0430"));
4806
+ checkTables(section, name, operation2, spec, used, path, issues);
4807
+ if (operation2.pagination !== void 0) {
4808
+ if (spec.list !== true) issues.push(issueAt([...path, "pagination"], "\u043F\u043E\u0441\u0442\u0440\u0430\u043D\u0438\u0447\u043D\u043E\u0441\u0442\u044C \u2014 \u0442\u043E\u043B\u044C\u043A\u043E \u0443 \u0441\u043F\u0438\u0441\u043A\u043E\u0432"));
4809
+ checkPagination(operation2.pagination, [...path, "pagination"], issues);
4810
+ }
4811
+ checkResult(section, name, operation2, spec, path, issues);
4812
+ }
4813
+ function checkSection(config, section, issues) {
4814
+ const operations = config[section];
4815
+ if (operations === void 0) return;
4816
+ for (const [name, operation2] of Object.entries(operations)) {
4817
+ if (operation2 === void 0) continue;
4818
+ checkOperation(config, section, name, operation2, issues);
4819
+ if (section !== "ci") continue;
4820
+ for (const need of CI_OPERATION_NEEDS[name] ?? []) {
4821
+ if (operations[need] === void 0) issues.push(issueAt([section, name], `\u043E\u043F\u0435\u0440\u0430\u0446\u0438\u0438 ${name} \u043D\u0443\u0436\u043D\u0430 \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u044F ${need}`));
4822
+ }
4823
+ }
4824
+ }
4825
+ function configIssues(config) {
4826
+ const issues = [];
4827
+ if (SECTIONS.every((section) => config[section] === void 0)) issues.push(issueAt([], "\u043D\u0443\u0436\u0435\u043D \u0445\u043E\u0442\u044F \u0431\u044B \u043E\u0434\u0438\u043D \u0440\u0430\u0437\u0434\u0435\u043B: issues, pulls \u0438\u043B\u0438 ci"));
4828
+ if (BUILTIN_TRACKER_KINDS.includes(config.kind)) issues.push(issueAt(["kind"], `\u0432\u0438\u0434 \xAB${config.kind}\xBB \u0437\u0430\u043D\u044F\u0442 \u0432\u0441\u0442\u0440\u043E\u0435\u043D\u043D\u044B\u043C \u0442\u0440\u0435\u043A\u0435\u0440\u043E\u043C: \u0432\u044B\u0431\u0435\u0440\u0438\u0442\u0435 \u0434\u0440\u0443\u0433\u043E\u0439`));
4829
+ checkFields(config, issues);
4830
+ checkBase(config, issues);
4831
+ checkHeaders(config, issues);
4832
+ checkPagination(config.http.pagination, ["http", "pagination"], issues);
4833
+ for (const section of SECTIONS) checkSection(config, section, issues);
4834
+ return issues;
4835
+ }
4836
+
4837
+ // src/tracker/declarative/declarative.lib.ts
4838
+ var SCHEMA_ERRORS = z5.locales.ru().localeError;
4839
+ var TrackerConfigError = class extends Error {
4840
+ issues;
4841
+ secret;
4842
+ constructor(issues, secret) {
4843
+ const first = issues[0];
4844
+ super(`\u041A\u043E\u043D\u0444\u0438\u0433 \u0442\u0440\u0435\u043A\u0435\u0440\u0430 \u043D\u0435 \u043F\u0440\u043E\u0448\u0451\u043B \u043F\u0440\u043E\u0432\u0435\u0440\u043A\u0443 (${String(issues.length)}): ${first === void 0 ? "" : `${first.path === "" ? "\u043A\u043E\u043D\u0444\u0438\u0433" : first.path} \u2014 ${first.message}`}`);
4845
+ this.name = "TrackerConfigError";
4846
+ this.issues = issues;
4847
+ this.secret = secret;
4848
+ }
4849
+ };
4850
+ function validateTrackerConfig(input) {
4851
+ const parsed = parseConfigInput(input);
4852
+ const done = (issues2) => ({
4853
+ ok: false,
4854
+ issues: issues2.slice(0, TRACKER_CONFIG_ISSUES_MAX).map((issue) => ({ path: redactSecretText(issue.path), message: redactSecretText(issue.message) })),
4855
+ secret: parsed.secret
4856
+ });
4857
+ if (parsed.data === void 0) return done(parsed.issues);
4858
+ const schema = trackerConfigSchema.safeParse(parsed.data, { error: SCHEMA_ERRORS });
4859
+ if (!schema.success) return done([...parsed.issues, ...schema.error.issues.map((item) => issueAt(item.path, item.message))]);
4860
+ const issues = [...parsed.issues, ...configIssues(schema.data)];
4861
+ return issues.length === 0 ? { ok: true, config: schema.data } : done(issues);
4862
+ }
4863
+ function definitionFromConfig(input) {
4864
+ const check = validateTrackerConfig(input);
4865
+ if (!check.ok) throw new TrackerConfigError(check.issues, check.secret);
4866
+ const config = check.config;
4867
+ const issues = issueCapabilitiesFrom(config);
4868
+ const features = featuresFrom(config);
4869
+ const pulls = pullCapabilitiesFrom(config);
4870
+ const ci = ciCapabilitiesFrom(config);
4871
+ return {
4872
+ descriptor: {
4873
+ tracker: config.kind,
4874
+ title: config.title,
4875
+ source: "user",
4876
+ fields: config.fields.map((field) => ({ name: field.name, required: field.required, secret: field.secret })),
4877
+ features
4878
+ },
4879
+ create: (context) => createIssuesAdapter(config, context, issues, features),
4880
+ issues,
4881
+ ...pulls === void 0 ? {} : { pulls: { capabilities: pulls, create: (context) => createPullAdapter2(config, context, pulls) } },
4882
+ ...ci === void 0 ? {} : { ci: { capabilities: ci, create: (context) => createCiAdapter(config, context, ci) } },
4883
+ origin: (connection) => baseOf(config, connection).origin
4884
+ };
4885
+ }
4886
+
4887
+ // src/tracker/declarative/declarative-hint.const.ts
4888
+ var TRACKER_CONFIG_EXAMPLE = `format: 1
4889
+ kind: gitea
4890
+ title: Gitea
4891
+ fields:
4892
+ - { name: url, required: true, secret: false }
4893
+ - { name: target, required: true, secret: false }
4894
+ - { name: token, required: true, secret: true }
4895
+ http:
4896
+ base: "{{url}}/api/v1"
4897
+ auth: { kind: bearer }
4898
+ headers:
4899
+ Accept: application/json
4900
+ pagination: { style: page, page: page, size: limit, next: link }
4901
+ issues:
4902
+ list:
4903
+ path: "/repos/{{target|path}}/issues"
4904
+ query:
4905
+ type: issues
4906
+ state: "{{status}}"
4907
+ labels: "{{labels}}"
4908
+ q: "{{search}}"
4909
+ created_by: "{{author}}"
4910
+ since: "{{updatedAfter}}"
4911
+ before: "{{updatedBefore}}"
4912
+ inputs:
4913
+ status: { open: open, in_progress: open, done: closed, declined: closed, "*": all }
4914
+ result: &issue
4915
+ key: $.number
4916
+ title: $.title
4917
+ description: $.body
4918
+ status.category: { path: $.state, map: { open: open, closed: done } }
4919
+ labels: $.labels[*].name
4920
+ assignee: $.assignee.login
4921
+ url: $.html_url
4922
+ createdAt: $.created_at
4923
+ updatedAt: $.updated_at
4924
+ get:
4925
+ path: "/repos/{{target|path}}/issues/{{key}}"
4926
+ result: *issue
4927
+ create:
4928
+ method: POST
4929
+ path: "/repos/{{target|path}}/issues"
4930
+ body:
4931
+ title: "{{title}}"
4932
+ body: "{{description}}"
4933
+ assignee: "{{assignee}}"
4934
+ result: *issue
4935
+ update:
4936
+ method: PATCH
4937
+ path: "/repos/{{target|path}}/issues/{{key}}"
4938
+ body:
4939
+ title: "{{title}}"
4940
+ body: "{{description}}"
4941
+ state: "{{status}}"
4942
+ assignee: "{{assignee}}"
4943
+ inputs:
4944
+ status: { open: open, done: closed }
4945
+ result: *issue
4946
+ comments:
4947
+ path: "/repos/{{target|path}}/issues/{{key}}/comments"
4948
+ query:
4949
+ since: "{{updatedAfter}}"
4950
+ result: &comment
4951
+ id: $.id
4952
+ author: $.user.login
4953
+ body: $.body
4954
+ createdAt: $.created_at
4955
+ comment:
4956
+ method: POST
4957
+ path: "/repos/{{target|path}}/issues/{{key}}/comments"
4958
+ body:
4959
+ body: "{{body}}"
4960
+ result: *comment
4961
+ pulls:
4962
+ list:
4963
+ path: "/repos/{{target|path}}/pulls"
4964
+ query:
4965
+ state: "{{status}}"
4966
+ inputs:
4967
+ status: { draft: open, open: open, merged: closed, closed: closed, "*": all }
4968
+ result: &pull
4969
+ key: $.number
4970
+ title: $.title
4971
+ description: $.body
4972
+ status.category: { path: $.state, map: { open: open, closed: closed } }
4973
+ merged: $.merged
4974
+ draft: $.draft
4975
+ author: $.user.login
4976
+ source: $.head.ref
4977
+ target: $.base.ref
4978
+ headSha: $.head.sha
4979
+ labels: $.labels[*].name
4980
+ url: $.html_url
4981
+ createdAt: $.created_at
4982
+ updatedAt: $.updated_at
4983
+ mergedAt: $.merged_at
4984
+ closedAt: $.closed_at
4985
+ get:
4986
+ path: "/repos/{{target|path}}/pulls/{{key}}"
4987
+ result: *pull
4988
+ create:
4989
+ method: POST
4990
+ path: "/repos/{{target|path}}/pulls"
4991
+ body:
4992
+ title: "{{title}}"
4993
+ body: "{{description}}"
4994
+ head: "{{sourceBranch}}"
4995
+ base: "{{targetBranch}}"
4996
+ result: *pull
4997
+ update:
4998
+ method: PATCH
4999
+ path: "/repos/{{target|path}}/pulls/{{key}}"
5000
+ body:
5001
+ title: "{{title}}"
5002
+ body: "{{description}}"
5003
+ base: "{{targetBranch}}"
5004
+ state: "{{status}}"
5005
+ inputs:
5006
+ status: { open: open, closed: closed }
5007
+ result: *pull
5008
+ merge:
5009
+ method: POST
5010
+ path: "/repos/{{target|path}}/pulls/{{key}}/merge"
5011
+ body:
5012
+ Do: "{{method}}"
5013
+ merge_message_field: "{{message}}"
5014
+ delete_branch_after_merge: "{{deleteSource}}"
5015
+ head_commit_id: "{{headSha}}"
5016
+ comments:
5017
+ path: "/repos/{{target|path}}/issues/{{key}}/comments"
5018
+ result: *comment
5019
+ comment:
5020
+ method: POST
5021
+ path: "/repos/{{target|path}}/issues/{{key}}/comments"
5022
+ body:
5023
+ body: "{{body}}"
5024
+ result: *comment
5025
+ ci:
5026
+ workflows:
5027
+ path: "/repos/{{target|path}}/actions/workflows"
5028
+ items: $.workflows
5029
+ result:
5030
+ key: $.id
5031
+ name: $.name
5032
+ path: $.path
5033
+ enabled: { path: $.state, map: { active: true }, default: false }
5034
+ runs:
5035
+ path: "/repos/{{target|path}}/actions/runs"
5036
+ query:
5037
+ branch: "{{ref}}"
5038
+ event: "{{event}}"
5039
+ status: "{{status}}"
5040
+ actor: "{{actor}}"
5041
+ head_sha: "{{sha}}"
5042
+ inputs:
5043
+ event: { push: push, pull_request: pull_request, manual: workflow_dispatch, schedule: schedule }
5044
+ status: { queued: queued, waiting: waiting, running: in_progress, success: success, failed: failure, canceled: cancelled, skipped: skipped }
5045
+ items: $.workflow_runs
5046
+ result: &run
5047
+ key: $.id
5048
+ number: $.run_number
5049
+ workflows: $.path
5050
+ status.category: &state
5051
+ - { path: $.conclusion, map: { success: success, failure: failed, cancelled: canceled, skipped: skipped }, default: failed }
5052
+ - { path: $.status, map: { queued: queued, waiting: waiting, in_progress: running }, default: running }
5053
+ status.name: $.status
5054
+ event.category: { path: $.event, map: { push: push, pull_request: pull_request, workflow_dispatch: manual, schedule: schedule }, default: other }
5055
+ ref: $.head_branch
5056
+ sha: $.head_sha
5057
+ actor: $.actor.login
5058
+ attempt: $.run_attempt
5059
+ url: $.html_url
5060
+ createdAt: $.created_at
5061
+ startedAt: $.run_started_at
5062
+ finishedAt: $.completed_at
5063
+ updatedAt: $.updated_at
5064
+ run:
5065
+ path: "/repos/{{target|path}}/actions/runs/{{key}}"
5066
+ result: *run
5067
+ jobs:
5068
+ path: "/repos/{{target|path}}/actions/runs/{{run}}/jobs"
5069
+ items: $.jobs
5070
+ result: &job
5071
+ key: $.id
5072
+ runKey: $.run_id
5073
+ name: $.name
5074
+ status.category: *state
5075
+ status.name: $.status
5076
+ url: $.html_url
5077
+ startedAt: $.started_at
5078
+ finishedAt: $.completed_at
5079
+ job:
5080
+ path: "/repos/{{target|path}}/actions/jobs/{{key}}"
5081
+ result: *job
5082
+ log:
5083
+ path: "/repos/{{target|path}}/actions/jobs/{{key}}/logs"
5084
+ trigger:
5085
+ method: POST
5086
+ path: "/repos/{{target|path}}/actions/workflows/{{workflow}}/dispatches"
5087
+ body:
5088
+ ref: "{{ref}}"
5089
+ inputs: "{{inputs}}"
5090
+ rerun:
5091
+ method: POST
5092
+ path: "/repos/{{target|path}}/actions/runs/{{key}}/rerun"
5093
+ cancel:
5094
+ method: POST
5095
+ path: "/repos/{{target|path}}/actions/runs/{{key}}/cancel"
5096
+ `;
5097
+ var SECTION_TITLES = { issues: "\u0437\u0430\u0434\u0430\u0447\u0438", pulls: "pull request-\u044B", ci: "CI" };
5098
+ var MODEL_TITLES = {
5099
+ issue: "\u0437\u0430\u0434\u0430\u0447\u0430 (list, get, create, update)",
5100
+ comment: "\u043A\u043E\u043C\u043C\u0435\u043D\u0442\u0430\u0440\u0438\u0439 (comments, comment)",
5101
+ pull: "PR (pulls.list, pulls.get, pulls.create, pulls.update)",
5102
+ run: "\u043F\u0440\u043E\u0433\u043E\u043D CI (runs, run, trigger)",
5103
+ job: "\u0437\u0430\u0434\u0430\u043D\u0438\u0435 CI (jobs, job)",
5104
+ workflow: "workflow (workflows)"
5105
+ };
5106
+ function operationLines(section) {
5107
+ return Object.entries(OPERATIONS[section]).map(([name, spec]) => {
5108
+ const required = REQUIRED_OPERATIONS[section].includes(name) ? ", \u043E\u0431\u044F\u0437\u0430\u0442\u0435\u043B\u044C\u043D\u0430" : "";
5109
+ const answer = spec.text === true ? ", \u043E\u0442\u0432\u0435\u0442 \u2014 \u0442\u0435\u043A\u0441\u0442" : spec.result === "forbidden" ? ", \u0431\u0435\u0437 result: \u044D\u043B\u0435\u043C\u0435\u043D\u0442 \u043F\u0435\u0440\u0435\u0447\u0438\u0442\u044B\u0432\u0430\u0435\u0442\u0441\u044F" : spec.result === "optional" ? ", result \u043F\u043E \u0436\u0435\u043B\u0430\u043D\u0438\u044E" : "";
5110
+ return ` - \`${section}.${name}\`${required}${answer}: ${spec.inputs.length === 0 ? "\u0432\u0445\u043E\u0434\u043E\u0432 \u043D\u0435\u0442" : spec.inputs.map((input) => spec.required.includes(input) ? `**${input}**` : input).join(", ")}`;
5111
+ }).join("\n");
5112
+ }
5113
+ function fieldLines() {
5114
+ return Object.keys(RESULT_FIELDS).map((model) => {
5115
+ const fields = Object.entries(RESULT_FIELDS[model]).map(([name, field]) => field.required === true ? `**${name}**` : name);
5116
+ return ` - ${MODEL_TITLES[model]}: ${fields.join(", ")}`;
5117
+ }).join("\n");
5118
+ }
5119
+ var TRACKER_CONFIG_HINT = `# \u0421\u0432\u043E\u0439 \u0442\u0440\u0435\u043A\u0435\u0440: \u0434\u0435\u043A\u043B\u0430\u0440\u0430\u0442\u0438\u0432\u043D\u044B\u0439 \u043A\u043E\u043D\u0444\u0438\u0433 \`format: 1\`
5120
+
5121
+ \u041A\u043E\u043D\u0444\u0438\u0433 \u2014 \u0434\u0430\u043D\u043D\u044B\u0435, \u0430 \u043D\u0435 \u043A\u043E\u0434: \u0435\u0433\u043E \u0438\u0441\u043F\u043E\u043B\u043D\u044F\u0435\u0442 \u0432\u0441\u0442\u0440\u043E\u0435\u043D\u043D\u044B\u0439 \u0438\u043D\u0442\u0435\u0440\u043F\u0440\u0435\u0442\u0430\u0442\u043E\u0440 \u0431\u0438\u0431\u043B\u0438\u043E\u0442\u0435\u043A\u0438. \u0423\u0441\u043B\u043E\u0432\u0438\u0439, \u0441\u043A\u0440\u0438\u043F\u0442\u043E\u0432 \u0438 \u0432\u044B\u0447\u0438\u0441\u043B\u0435\u043D\u0438\u0439 \u043D\u0435\u0442 \u2014
5122
+ \u0442\u043E\u043B\u044C\u043A\u043E \u0448\u0430\u0431\u043B\u043E\u043D\u044B \u0437\u0430\u043F\u0440\u043E\u0441\u043E\u0432, \u043F\u0443\u0442\u0438 JSON \u0438 \u0442\u0430\u0431\u043B\u0438\u0446\u044B \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0439. \u041A\u043E\u043D\u0444\u0438\u0433 \u043E\u043F\u0438\u0441\u044B\u0432\u0430\u0435\u0442 \u0440\u0430\u0437\u0434\u0435\u043B\u044B ${Object.keys(SECTION_TITLES).map((section) => `\`${section}\` (${SECTION_TITLES[section]})`).join(", ")} \u2014 \u0445\u043E\u0442\u044F \u0431\u044B \u043E\u0434\u0438\u043D.
5123
+
5124
+ ## \u041A\u0430\u043A \u0440\u0430\u0431\u043E\u0442\u0430\u0442\u044C
5125
+ 1. \u041F\u0440\u043E\u0447\u0438\u0442\u0430\u0439 \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0430\u0446\u0438\u044E REST API \u0441\u0435\u0440\u0432\u0438\u0441\u0430: \u0430\u0434\u0440\u0435\u0441 API, \u0430\u0432\u0442\u043E\u0440\u0438\u0437\u0430\u0446\u0438\u044E, \u043F\u043E\u0441\u0442\u0440\u0430\u043D\u0438\u0447\u043D\u043E\u0441\u0442\u044C, \u043D\u0443\u0436\u043D\u044B\u0435 \u0437\u0430\u043F\u0440\u043E\u0441\u044B \u0438 \u043E\u0442\u0432\u0435\u0442\u044B.
5126
+ 2. \u041D\u0430\u043F\u0438\u0448\u0438 YAML \u043F\u043E \u044D\u0442\u043E\u0439 \u043F\u043E\u0434\u0441\u043A\u0430\u0437\u043A\u0435 \u0438 \u043F\u0440\u0438\u043C\u0435\u0440\u0443 \u043D\u0438\u0436\u0435.
5127
+ 3. \u041F\u0440\u043E\u0432\u0435\u0440\u044F\u0439 \u0435\u0433\u043E (\`validateTrackerConfig\`), \u043F\u043E\u043A\u0430 \u043F\u0440\u043E\u0432\u0435\u0440\u043A\u0430 \u043D\u0435 \u043F\u0440\u043E\u0439\u0434\u0451\u0442: \u043A\u0430\u0436\u0434\u0430\u044F \u043E\u0448\u0438\u0431\u043A\u0430 \u2014 \u043F\u0443\u0442\u044C \u043F\u043E\u043B\u044F
5128
+ (\`issues.list.query.state\`) \u0438 \u0441\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u0435.
5129
+ 4. \u041E\u0442\u0434\u0430\u0439 \u0442\u0435\u043A\u0441\u0442 \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044E. \u0422\u043E\u043A\u0435\u043D \u0432 \u043A\u043E\u043D\u0444\u0438\u0433 \u043D\u0435 \u043F\u0438\u0448\u0443\u0442: \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044C \u0432\u0432\u043E\u0434\u0438\u0442 \u0435\u0433\u043E \u0432 \u043F\u043E\u0434\u043A\u043B\u044E\u0447\u0435\u043D\u0438\u0438 \u043F\u0440\u043E\u0435\u043A\u0442\u0430.
5130
+
5131
+ ## \u0421\u0442\u0440\u0443\u043A\u0442\u0443\u0440\u0430
5132
+ - \`format: 1\`; \`kind\` \u2014 \u0441\u043B\u0430\u0433 \u0432\u0438\u0434\u0430 (\`gitea\`, \u043B\u0430\u0442\u0438\u043D\u0438\u0446\u0430, \u0446\u0438\u0444\u0440\u044B \u0438 \xAB-\xBB), \u0432\u0438\u0434\u044B \u0432\u0441\u0442\u0440\u043E\u0435\u043D\u043D\u044B\u0445 \u0442\u0440\u0435\u043A\u0435\u0440\u043E\u0432 \u0437\u0430\u043D\u044F\u0442\u044B;
5133
+ \`title\` \u2014 \u0438\u043C\u044F \u0432 \u0438\u043D\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0435.
5134
+ - \`fields\` \u2014 \u043F\u043E\u043B\u044F \u0444\u043E\u0440\u043C\u044B \u043F\u043E\u0434\u043A\u043B\u044E\u0447\u0435\u043D\u0438\u044F: \`url\`, \`target\`, \`user\`, \`token\` (\`name\`, \`required\`, \`secret\`);
5135
+ \u0441\u0435\u043A\u0440\u0435\u0442\u043D\u043E\u0435 \u2014 \u0442\u043E\u043B\u044C\u043A\u043E \`token\`, \u0438 \u043E\u043D\u043E \u0432\u0441\u0435\u0433\u0434\u0430 \u0441\u0435\u043A\u0440\u0435\u0442\u043D\u043E\u0435.
5136
+ - \`http.base\` \u2014 \u0430\u0434\u0440\u0435\u0441 API: \`https://api.example.com/v1\` \u0438\u043B\u0438 \`{{url}}/api/v1\` (url \u043F\u043E\u0434\u043A\u043B\u044E\u0447\u0435\u043D\u0438\u044F \u0437\u0430\u0434\u0430\u0451\u0442 origin, \u043F\u043E\u0441\u043B\u0435
5137
+ \u043D\u0435\u0433\u043E \u2014 \u0442\u043E\u043B\u044C\u043A\u043E \u043F\u0443\u0442\u044C \u043E\u0442 \xAB/\xBB). \u0422\u043E\u043A\u0435\u043D \u0443\u0445\u043E\u0434\u0438\u0442 \u0442\u043E\u043B\u044C\u043A\u043E \u043D\u0430 origin \u0431\u0430\u0437\u044B, \u0432\u0441\u0435 \u0437\u0430\u043F\u0440\u043E\u0441\u044B \u043E\u0441\u0442\u0430\u044E\u0442\u0441\u044F \u043F\u043E\u0434 \u0435\u0451 \u043F\u0443\u0442\u0451\u043C.
5138
+ - \`http.auth\` \u2014 \`{ kind: bearer }\` (Authorization: Bearer), \`{ kind: header, header, prefix }\` (\u0441\u0432\u043E\u0439 \u0437\u0430\u0433\u043E\u043B\u043E\u0432\u043E\u043A),
5139
+ \`{ kind: basic }\` (\u043F\u043E\u043B\u044F user \u0438 token) \u0438\u043B\u0438 \`{ kind: none }\`.
5140
+ - \`http.headers\` \u2014 \u043F\u043E\u0441\u0442\u043E\u044F\u043D\u043D\u044B\u0435 \u0437\u0430\u0433\u043E\u043B\u043E\u0432\u043A\u0438 (Accept, \u0432\u0435\u0440\u0441\u0438\u044F API); \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u044F \u2014 \u043B\u0438\u0442\u0435\u0440\u0430\u043B\u044B \u0438\u043B\u0438 \u043F\u043E\u043B\u044F \u043F\u043E\u0434\u043A\u043B\u044E\u0447\u0435\u043D\u0438\u044F.
5141
+ - \`http.pagination\` \u2014 \`{ style: page, page, size, next }\` (\u043D\u043E\u043C\u0435\u0440 \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u044B \u0441 1; \u0441\u043B\u0435\u0434\u0443\u044E\u0449\u0430\u044F \u2014 \`link\` \u043F\u043E \u0437\u0430\u0433\u043E\u043B\u043E\u0432\u043A\u0443
5142
+ Link, \`count\` \u043F\u043E \u043F\u043E\u043B\u043D\u043E\u0439 \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u0435, \`{ header }\` \u0438\u043B\u0438 \`{ path }\` \u0441 \u043D\u043E\u043C\u0435\u0440\u043E\u043C), \`{ style: cursor, param, size, next }\`
5143
+ (\u043A\u0443\u0440\u0441\u043E\u0440 \u2014 \u043F\u0443\u0442\u044C JSON \u0438\u043B\u0438 \`{ header }\`) \u0438\u043B\u0438 \`{ style: none }\`; \u0443 \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u0438-\u0441\u043F\u0438\u0441\u043A\u0430 \u0431\u044B\u0432\u0430\u0435\u0442 \u0441\u0432\u043E\u044F \`pagination\`.
5144
+
5145
+ ## \u041E\u043F\u0435\u0440\u0430\u0446\u0438\u0438 \u0438 \u0438\u0445 \u0432\u0445\u043E\u0434\u044B (\u043E\u0431\u044F\u0437\u0430\u0442\u0435\u043B\u044C\u043D\u044B\u0435 \u2014 \u0436\u0438\u0440\u043D\u044B\u043C)
5146
+ ${Object.keys(SECTION_TITLES).map(operationLines).join("\n")}
5147
+
5148
+ \u041E\u043F\u0435\u0440\u0430\u0446\u0438\u044F: \`method\` (GET \u043F\u043E \u0443\u043C\u043E\u043B\u0447\u0430\u043D\u0438\u044E; POST, PUT, PATCH), \`path\` \u043E\u0442 \`http.base\` (\u0441 \xAB/\xBB), \`query\`, \`body\`, \`inputs\`,
5149
+ \`items\`, \`result\`. \u0411\u0435\u0437 \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u0438 \u043D\u0435\u0442 \u0438 \u0432\u043E\u0437\u043C\u043E\u0436\u043D\u043E\u0441\u0442\u0438: create, update, comment, \u0441\u043B\u0438\u044F\u043D\u0438\u0435, \u0437\u0430\u043F\u0443\u0441\u043A CI \u043E\u0442\u043A\u0430\u0437\u044B\u0432\u0430\u044E\u0442
5150
+ unsupported. \u041B\u043E\u0433 \u0437\u0430\u0434\u0430\u043D\u0438\u044F \u0447\u0438\u0442\u0430\u0435\u0442 \u0441\u043E\u0441\u0442\u043E\u044F\u043D\u0438\u0435 \u0437\u0430\u0434\u0430\u043D\u0438\u044F \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u0435\u0439 \`job\`; \u043F\u0435\u0440\u0435\u0437\u0430\u043F\u0443\u0441\u043A \u0437\u0430\u0434\u0430\u043D\u0438\u044F \u0438 \u043E\u0442\u043C\u0435\u043D\u0430 \u0437\u0430\u0434\u0430\u043D\u0438\u044F \u2014 \u0442\u043E\u0436\u0435.
5151
+
5152
+ ## \u0428\u0430\u0431\u043B\u043E\u043D\u044B
5153
+ - \u041F\u043B\u0435\u0439\u0441\u0445\u043E\u043B\u0434\u0435\u0440\u044B \u2014 \`{{\u0438\u043C\u044F}}\`: \u043F\u043E\u043B\u044F \u043F\u043E\u0434\u043A\u043B\u044E\u0447\u0435\u043D\u0438\u044F \`{{url}}\`, \`{{target}}\`, \`{{user}}\` (\u043E\u0431\u044A\u044F\u0432\u043B\u0435\u043D\u043D\u044B\u0435 \u0432 fields) \u0438 \u0432\u0445\u043E\u0434\u044B
5154
+ \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u0438. \u0412\u0435\u0442\u043A\u0438 PR \u0432\u043E \u0432\u0445\u043E\u0434\u0430\u0445 \u2014 \`sourceBranch\` \u0438 \`targetBranch\` (\`target\` \u2014 \u043F\u043E\u043B\u0435 \u043F\u043E\u0434\u043A\u043B\u044E\u0447\u0435\u043D\u0438\u044F).
5155
+ - \u0412 \u043F\u0443\u0442\u0438 \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435 \u043A\u043E\u0434\u0438\u0440\u0443\u0435\u0442\u0441\u044F \u043A\u0430\u043A \u043E\u0434\u0438\u043D \u0441\u0435\u0433\u043C\u0435\u043D\u0442; \`{{\u0438\u043C\u044F|path}}\` \u2014 \u043F\u0443\u0442\u044C \u0438\u0437 \u0441\u0435\u0433\u043C\u0435\u043D\u0442\u043E\u0432 \u0447\u0435\u0440\u0435\u0437 \xAB/\xBB (\`owner/repo\`),
5156
+ \u043F\u0443\u0441\u0442\u044B\u0435 \u0441\u0435\u0433\u043C\u0435\u043D\u0442\u044B, \xAB.\xBB, \xAB..\xBB, \xAB\\\xBB \u0438 \u0443\u043F\u0440\u0430\u0432\u043B\u044F\u044E\u0449\u0438\u0435 \u0441\u0438\u043C\u0432\u043E\u043B\u044B \u2014 \u043E\u0442\u043A\u0430\u0437. \u0412\u0445\u043E\u0434\u0443 \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u0438 \xAB/\xBB \u0432\u043D\u0435 \`|path\` \u0438 \`%2F\`/\`%5C\` \u2014
5157
+ \u043E\u0442\u043A\u0430\u0437; \u043F\u043E\u043B\u0435 \u043F\u043E\u0434\u043A\u043B\u044E\u0447\u0435\u043D\u0438\u044F \u0432 \u043F\u0440\u043E\u0441\u0442\u043E\u043C \u043F\u043B\u0435\u0439\u0441\u0445\u043E\u043B\u0434\u0435\u0440\u0435 \u0443\u0445\u043E\u0434\u0438\u0442 \u0441 \xAB/\xBB \u043A\u0430\u043A \`%2F\` (\`o/r\` \u2192 \`o%2Fr\`, \u043A\u0430\u043A \u0443 GitLab). \u0412 query
5158
+ \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435 \u043A\u043E\u0434\u0438\u0440\u0443\u0435\u0442 \u043A\u043B\u0438\u0435\u043D\u0442, \u0432 \u0437\u0430\u0433\u043E\u043B\u043E\u0432\u043A\u0435 \u043F\u0435\u0440\u0435\u0432\u043E\u0434 \u0441\u0442\u0440\u043E\u043A\u0438 \u2014 \u043E\u0442\u043A\u0430\u0437.
5159
+ - \u041D\u0435\u0442 \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u044F \u2014 \u043F\u0430\u0440\u0430\u043C\u0435\u0442\u0440 query \u0438\u043B\u0438 \u043F\u043E\u043B\u0435 body \u043F\u0440\u043E\u043F\u0443\u0441\u043A\u0430\u044E\u0442\u0441\u044F, \u0430 \u0432 \u043F\u0443\u0442\u0438 \u2014 \u043E\u0442\u043A\u0430\u0437 \u0437\u0430\u043F\u0440\u043E\u0441\u0430. \u041F\u043E\u043B\u0435 body, \u0440\u0430\u0432\u043D\u043E\u0435 \u0440\u043E\u0432\u043D\u043E
5160
+ \u043E\u0434\u043D\u043E\u043C\u0443 \u043F\u043B\u0435\u0439\u0441\u0445\u043E\u043B\u0434\u0435\u0440\u0443, \u0441\u043E\u0445\u0440\u0430\u043D\u044F\u0435\u0442 \u0442\u0438\u043F: \u0444\u043B\u0430\u0433, \u0441\u043F\u0438\u0441\u043E\u043A, null, \u0441\u043B\u043E\u0432\u0430\u0440\u044C (\`{{inputs}}\` \u0437\u0430\u043F\u0443\u0441\u043A\u0430 CI). \u0421\u043F\u0438\u0441\u043A\u0438 \u0432 \u0442\u0435\u043A\u0441\u0442\u0435 \u2014 \u0447\u0435\u0440\u0435\u0437
5161
+ \u0437\u0430\u043F\u044F\u0442\u0443\u044E. \u0412\u0440\u0435\u043C\u044F \u2014 ISO 8601 UTC.
5162
+ - \`inputs\` \u2014 \u0442\u0430\u0431\u043B\u0438\u0446\u044B \xAB\u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435 \u0435\u0434\u0438\u043D\u043E\u0439 \u043C\u043E\u0434\u0435\u043B\u0438 \u2192 \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435 API\xBB \u0443 \u0432\u0445\u043E\u0434\u043E\u0432 \u0441 \u043F\u0435\u0440\u0435\u0447\u043D\u0435\u043C (\u0441\u0442\u0430\u0442\u0443\u0441\u044B, \u043F\u0440\u0438\u043E\u0440\u0438\u0442\u0435\u0442, \u0441\u043F\u043E\u0441\u043E\u0431
5163
+ \u0441\u043B\u0438\u044F\u043D\u0438\u044F, \u0441\u043E\u0431\u044B\u0442\u0438\u0435 CI, sort, direction, order, \u0444\u043B\u0430\u0433\u0438 \`"true"\`/\`"false"\`). \u0417\u043D\u0430\u0447\u0435\u043D\u0438\u044F \u043D\u0435\u0442 \u0432 \u0442\u0430\u0431\u043B\u0438\u0446\u0435 \u2014 \u043E\u0442\u043A\u0430\u0437
5164
+ unsupported; \u0443 \u0444\u0438\u043B\u044C\u0442\u0440\u0430 \u0441\u043F\u0438\u0441\u043A\u0430 \u043A\u043B\u044E\u0447 \`"*"\` \u2014 \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435 \u0434\u043B\u044F \xAB\u043D\u0435\u0441\u043A\u043E\u043B\u044C\u043A\u0438\u0445 \u0441\u0440\u0430\u0437\u0443\xBB, \u043B\u0438\u0448\u043D\u0435\u0435 \u043E\u0442\u0441\u0435\u0435\u0442 \u043F\u0440\u043E\u0432\u0435\u0440\u043A\u0430 \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u044B;
5165
+ \u043A\u043B\u044E\u0447 \`"null"\` \u0443 assignee \u2014 \xAB\u0431\u0435\u0437 \u0438\u0441\u043F\u043E\u043B\u043D\u0438\u0442\u0435\u043B\u044F\xBB. \u0421\u043E\u0440\u0442\u0438\u0440\u043E\u0432\u043A\u0435 \u043D\u0443\u0436\u043D\u044B \`{{sort}}\` \u0441 \u0442\u0430\u0431\u043B\u0438\u0446\u0435\u0439 \u0438 \`{{direction}}\`.
5166
+
5167
+ ## \u0420\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442
5168
+ - \`items\` \u2014 \u043F\u0443\u0442\u044C JSON \u043A \u044D\u043B\u0435\u043C\u0435\u043D\u0442\u0443 \u0438\u043B\u0438 \u0441\u043F\u0438\u0441\u043A\u0443 (\`$.workflow_runs\`); \u0431\u0435\u0437 \u043D\u0435\u0433\u043E \u043E\u0442\u0432\u0435\u0442 \u2014 \u0441\u0430\u043C \u044D\u043B\u0435\u043C\u0435\u043D\u0442 \u0438\u043B\u0438 \u0441\u043F\u0438\u0441\u043E\u043A.
5169
+ - \`result\` \u2014 \u043F\u043E\u043B\u0435 \u0435\u0434\u0438\u043D\u043E\u0439 \u043C\u043E\u0434\u0435\u043B\u0438 \u2192 \u043F\u0443\u0442\u044C JSON (\`$.a.b\`, \`$.items[0]\`, \`$.labels[*].name\` \u2014 \u0442\u043E\u043B\u044C\u043A\u043E \u0443 \u0441\u043F\u0438\u0441\u043A\u043E\u0432) \u0438\u043B\u0438
5170
+ \`{ path, map, default, exists }\`, \u0438\u043B\u0438 \u0446\u0435\u043F\u043E\u0447\u043A\u0430 \u0442\u0430\u043A\u0438\u0445 \u0437\u0432\u0435\u043D\u044C\u0435\u0432: \u0440\u0435\u0448\u0430\u0435\u0442 \u043F\u0435\u0440\u0432\u043E\u0435, \u0443 \u043A\u043E\u0442\u043E\u0440\u043E\u0433\u043E \u043F\u043E \u043F\u0443\u0442\u0438 \u0435\u0441\u0442\u044C \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435
5171
+ (\u0435\u0433\u043E \`map\`, \u0430 \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u044F \u043D\u0435\u0442 \u0432 map \u2014 \u0435\u0433\u043E \`default\`); \u043D\u0438 \u043E\u0434\u043D\u043E \u043D\u0435 \u043D\u0430\u0448\u043B\u043E \u2014 \`default\` \u043F\u043E\u0441\u043B\u0435\u0434\u043D\u0435\u0433\u043E. \`exists: true\` \u2014 \u0444\u043B\u0430\u0433
5172
+ \xAB\u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435 \u0435\u0441\u0442\u044C\xBB. \`url\` \u2014 \u043F\u0435\u0440\u0432\u0430\u044F \u0441\u0441\u044B\u043B\u043A\u0430 \u044D\u043B\u0435\u043C\u0435\u043D\u0442\u0430. \u0421\u0432\u043E\u0451 \u0438\u043C\u044F \u0441\u0442\u0430\u0442\u0443\u0441\u0430 (\`status.name\`) \u043F\u043E \u0443\u043C\u043E\u043B\u0447\u0430\u043D\u0438\u044E \u2014 \u0438\u0441\u0445\u043E\u0434\u043D\u043E\u0435
5173
+ \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435. \u0423 PR \u0444\u043B\u0430\u0433 \`merged\` \u0438\u043B\u0438 \u0432\u0440\u0435\u043C\u044F \`mergedAt\` \u0434\u0435\u043B\u0430\u044E\u0442 \u043A\u0430\u0442\u0435\u0433\u043E\u0440\u0438\u044E merged, \u0444\u043B\u0430\u0433 \`draft\` \u2014 draft.
5174
+ - \u041F\u043E\u043B\u044F \u043C\u043E\u0434\u0435\u043B\u0435\u0439 (\u043E\u0431\u044F\u0437\u0430\u0442\u0435\u043B\u044C\u043D\u044B\u0435 \u2014 \u0436\u0438\u0440\u043D\u044B\u043C; \u0443 \`ci.job\` \u043E\u0431\u044F\u0437\u0430\u0442\u0435\u043B\u0435\u043D \u0438 runKey):
5175
+ ${fieldLines()}
5176
+ - \u041A\u0430\u0436\u0434\u044B\u0439 \u044D\u043B\u0435\u043C\u0435\u043D\u0442 \u043E\u0442\u0432\u0435\u0442\u0430 \u043F\u0440\u043E\u0432\u0435\u0440\u044F\u0435\u0442\u0441\u044F \u0441\u0445\u0435\u043C\u043E\u0439 \u0435\u0434\u0438\u043D\u043E\u0439 \u043C\u043E\u0434\u0435\u043B\u0438: \u043D\u0435 \u043B\u0435\u0433\u043B\u043E \u2014 \u043E\u0442\u043A\u0430\u0437 failed \u0441 \u043F\u043E\u043B\u0435\u043C, \u0430 \u043D\u0435 \u043C\u0443\u0441\u043E\u0440.
5177
+
5178
+ ## \u0412\u043E\u0437\u043C\u043E\u0436\u043D\u043E\u0441\u0442\u0438
5179
+ \u0412\u043E\u0437\u043C\u043E\u0436\u043D\u043E\u0441\u0442\u0438 \u0432\u044B\u0432\u043E\u0434\u044F\u0442\u0441\u044F \u0438\u0437 \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u0439: \u0444\u0438\u043B\u044C\u0442\u0440 \u0441\u043F\u0438\u0441\u043A\u0430 \u0435\u0441\u0442\u044C, \u0435\u0441\u043B\u0438 \u0435\u0433\u043E \u0432\u0445\u043E\u0434 \u0441\u0442\u043E\u0438\u0442 \u0432 \u0448\u0430\u0431\u043B\u043E\u043D\u0430\u0445 (\u0444\u0438\u043B\u044C\u0442\u0440\u0443\u0435\u0442 API) \u0438\u043B\u0438 result
5180
+ \u0437\u0430\u043F\u043E\u043B\u043D\u044F\u0435\u0442 \u043F\u043E\u043B\u044F \u0434\u043B\u044F \u043F\u0440\u043E\u0432\u0435\u0440\u043A\u0438 \u043F\u043E \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u0435; \u0432\u0445\u043E\u0434 \u0447\u0435\u0440\u0435\u0437 \u0442\u0430\u0431\u043B\u0438\u0446\u0443 \u043F\u0440\u043E\u0432\u0435\u0440\u044F\u0435\u0442\u0441\u044F \u0438 \u043F\u043E \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u0435. \u0421\u0442\u0430\u0442\u0443\u0441\u044B \u043F\u0440\u0430\u0432\u043A\u0438 \u2014 \u043A\u043B\u044E\u0447\u0438
5181
+ \u0442\u0430\u0431\u043B\u0438\u0446\u044B \`status\` \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u0438 update; \u0441\u043F\u043E\u0441\u043E\u0431\u044B \u0441\u043B\u0438\u044F\u043D\u0438\u044F \u2014 \u043A\u043B\u044E\u0447\u0438 \u0442\u0430\u0431\u043B\u0438\u0446\u044B \`method\`, \u0431\u0435\u0437 \`{{method}}\` \u2014 \u0442\u043E\u043B\u044C\u043A\u043E merge.
5182
+
5183
+ ## \u0411\u0435\u0437\u043E\u043F\u0430\u0441\u043D\u043E\u0441\u0442\u044C
5184
+ - \u041F\u043B\u0435\u0439\u0441\u0445\u043E\u043B\u0434\u0435\u0440\u0430 \`{{token}}\` \u043D\u0435\u0442: \u0442\u043E\u043A\u0435\u043D \u043F\u043E\u0434\u0441\u0442\u0430\u0432\u043B\u044F\u0435\u0442 \u0442\u043E\u043B\u044C\u043A\u043E \`http.auth\`, \u0438 \u0442\u043E\u043B\u044C\u043A\u043E \u0434\u043B\u044F origin \`http.base\`.
5185
+ - \u0410\u0434\u0440\u0435\u0441 \u043D\u0435 \u043F\u043E\u043A\u0438\u0434\u0430\u0435\u0442 origin \u0438 \u043F\u0443\u0442\u044C \u0431\u0430\u0437\u044B: \u043F\u0443\u0442\u044C \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u0438 \u2014 \u0441 \u043E\u0434\u043D\u043E\u0433\u043E \xAB/\xBB, \u0431\u0435\u0437 \xAB?\xBB, \xAB#\xBB, \xAB%\xBB, \xAB\\\xBB \u0438 \u0441\u0435\u0433\u043C\u0435\u043D\u0442\u043E\u0432 \xAB.\xBB/\xAB..\xBB.
5186
+ - \u0421\u0435\u043A\u0440\u0435\u0442\u043D\u044B\u0435 \u0437\u0430\u0433\u043E\u043B\u043E\u0432\u043A\u0438 (Authorization, Cookie, X-Api-Key, *-Token\u2026) \u0432 \`http.headers\` \u0438 \u0441\u0435\u043A\u0440\u0435\u0442\u043D\u044B\u0435 \u043F\u0430\u0440\u0430\u043C\u0435\u0442\u0440\u044B query
5187
+ \u0437\u0430\u043F\u0440\u0435\u0449\u0435\u043D\u044B; \u0430\u0432\u0442\u043E\u0440\u0438\u0437\u0430\u0446\u0438\u044F \u2014 \u0442\u043E\u043B\u044C\u043A\u043E \`http.auth\`.
5188
+ - \u0422\u0435\u043A\u0441\u0442, \u043F\u043E\u0445\u043E\u0436\u0438\u0439 \u043D\u0430 \u0441\u0435\u043A\u0440\u0435\u0442 (\u0442\u043E\u043A\u0435\u043D\u044B, \u043F\u0430\u0440\u043E\u043B\u0438, \u043A\u043B\u044E\u0447\u0438, \u0430\u0434\u0440\u0435\u0441 \u0441 \u043F\u0430\u0440\u043E\u043B\u0435\u043C), \u0434\u0430\u0436\u0435 \u0432 \u043A\u043E\u043C\u043C\u0435\u043D\u0442\u0430\u0440\u0438\u0438 YAML \u2014 \u043E\u0448\u0438\u0431\u043A\u0430.
5189
+ - \u041A\u043E\u043D\u0444\u0438\u0433 \u043D\u0435 \u0431\u043E\u043B\u044C\u0448\u0435 ${String(TRACKER_CONFIG_MAX_BYTES / 1024)} \u041A\u0438\u0411; \u044F\u043A\u043E\u0440\u044F YAML (\`&\u0438\u043C\u044F\`, \`*\u0438\u043C\u044F\`) \u2014 \u0442\u043E\u043B\u044C\u043A\u043E \u043A\u0430\u043A \u043F\u043E\u0432\u0442\u043E\u0440 \u0431\u043B\u043E\u043A\u0430.
5190
+
5191
+ ## \u041F\u0440\u0438\u043C\u0435\u0440 (Gitea)
5192
+ \`\`\`yaml
5193
+ ${TRACKER_CONFIG_EXAMPLE}\`\`\`
5194
+ `;
3289
5195
  export {
3290
5196
  ALL_STATUSES,
5197
+ BUILTIN_TRACKER_KINDS,
3291
5198
  CI_FINISHED_STATUSES,
3292
5199
  CI_LOG_DEFAULT_BYTES,
3293
5200
  CI_LOG_MAX_BYTES,
@@ -3322,12 +5229,19 @@ export {
3322
5229
  SOURCECRAFT_STATUSES,
3323
5230
  SOURCECRAFT_STATUS_FILTER,
3324
5231
  SOURCECRAFT_STATUS_SLUGS,
5232
+ TRACKER_CONFIG_DEPTH_MAX,
5233
+ TRACKER_CONFIG_EXAMPLE,
5234
+ TRACKER_CONFIG_HINT,
5235
+ TRACKER_CONFIG_ISSUES_MAX,
5236
+ TRACKER_CONFIG_MAX_BYTES,
5237
+ TRACKER_CONFIG_YAML_ALIAS_MAX,
3325
5238
  TRACKER_ERROR_BODY_MAX,
3326
5239
  TRACKER_LOCAL_AUTHOR,
3327
5240
  TRACKER_PAGE_LIMIT_DEFAULT,
3328
5241
  TRACKER_REDIRECT_MAX,
3329
5242
  TRACKER_SECRETS_FILE,
3330
5243
  TRACKER_TIMEOUT_MS,
5244
+ TrackerConfigError,
3331
5245
  TrackerError,
3332
5246
  assertCommentQuery,
3333
5247
  assertListQuery,
@@ -3348,6 +5262,7 @@ export {
3348
5262
  cleanLogText,
3349
5263
  clipText,
3350
5264
  containsText,
5265
+ definitionFromConfig,
3351
5266
  deleteTrackerToken,
3352
5267
  findTracker,
3353
5268
  githubCi,
@@ -3390,6 +5305,8 @@ export {
3390
5305
  requestJson,
3391
5306
  requestText,
3392
5307
  requireTarget,
5308
+ setSecretSink,
5309
+ setUserTrackers,
3393
5310
  sourcecraftCi,
3394
5311
  sourcecraftPulls,
3395
5312
  sourcecraftRepo,
@@ -3397,7 +5314,9 @@ export {
3397
5314
  stringList,
3398
5315
  text,
3399
5316
  toTimestamp,
5317
+ trackerConfigSchema,
3400
5318
  usedFilters,
5319
+ validateTrackerConfig,
3401
5320
  writeTrackerToken
3402
5321
  };
3403
5322
  //# sourceMappingURL=index.js.map