@rawdash/connector-github 0.27.0 → 0.28.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/index.d.ts +49 -73
- package/dist/index.js +42 -76
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -45,8 +45,8 @@ A personal access token is optional for public repositories but required for pri
|
|
|
45
45
|
- The latest status is folded in from GET /repos/{owner}/{repo}/deployments/{id}/statuses.
|
|
46
46
|
- **`release`** _(entity)_ - Published, draft, and prerelease GitHub releases.
|
|
47
47
|
- Endpoint: `GET /repos/{owner}/{repo}/releases`
|
|
48
|
-
- **`contributor`** _(entity)_ - Per-author commit
|
|
49
|
-
- Endpoint: `GET /repos/{owner}/{repo}/
|
|
48
|
+
- **`contributor`** _(entity)_ - Per-author commit counts for the repository.
|
|
49
|
+
- Endpoint: `GET /repos/{owner}/{repo}/contributors`
|
|
50
50
|
|
|
51
51
|
## Example
|
|
52
52
|
|
package/dist/index.d.ts
CHANGED
|
@@ -72,8 +72,8 @@ declare const githubResources: {
|
|
|
72
72
|
check_suite_url: z.ZodOptional<z.ZodString>;
|
|
73
73
|
display_title: z.ZodOptional<z.ZodString>;
|
|
74
74
|
event: z.ZodOptional<z.ZodString>;
|
|
75
|
-
head_commit: z.ZodOptional<z.ZodUnknown
|
|
76
|
-
head_repository: z.ZodOptional<z.ZodUnknown
|
|
75
|
+
head_commit: z.ZodOptional<z.ZodNullable<z.ZodUnknown>>;
|
|
76
|
+
head_repository: z.ZodOptional<z.ZodNullable<z.ZodUnknown>>;
|
|
77
77
|
head_sha: z.ZodOptional<z.ZodString>;
|
|
78
78
|
html_url: z.ZodOptional<z.ZodString>;
|
|
79
79
|
jobs_url: z.ZodOptional<z.ZodString>;
|
|
@@ -81,9 +81,9 @@ declare const githubResources: {
|
|
|
81
81
|
node_id: z.ZodOptional<z.ZodString>;
|
|
82
82
|
path: z.ZodOptional<z.ZodString>;
|
|
83
83
|
previous_attempt_url: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
84
|
-
pull_requests: z.ZodOptional<z.ZodArray<z.ZodUnknown
|
|
85
|
-
referenced_workflows: z.ZodOptional<z.ZodArray<z.ZodUnknown
|
|
86
|
-
repository: z.ZodOptional<z.ZodUnknown
|
|
84
|
+
pull_requests: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodUnknown>>>;
|
|
85
|
+
referenced_workflows: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodUnknown>>>;
|
|
86
|
+
repository: z.ZodOptional<z.ZodNullable<z.ZodUnknown>>;
|
|
87
87
|
rerun_url: z.ZodOptional<z.ZodString>;
|
|
88
88
|
run_number: z.ZodOptional<z.ZodNumber>;
|
|
89
89
|
run_started_at: z.ZodOptional<z.ZodISODateTime>;
|
|
@@ -136,31 +136,31 @@ declare const githubResources: {
|
|
|
136
136
|
}, z.core.$strip>;
|
|
137
137
|
created_at: z.ZodISODateTime;
|
|
138
138
|
updated_at: z.ZodISODateTime;
|
|
139
|
-
_links: z.ZodOptional<z.ZodUnknown
|
|
139
|
+
_links: z.ZodOptional<z.ZodNullable<z.ZodUnknown>>;
|
|
140
140
|
active_lock_reason: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
141
141
|
assignee: z.ZodOptional<z.ZodUnknown>;
|
|
142
|
-
assignees: z.ZodOptional<z.ZodUnknown
|
|
142
|
+
assignees: z.ZodOptional<z.ZodNullable<z.ZodUnknown>>;
|
|
143
143
|
author_association: z.ZodOptional<z.ZodString>;
|
|
144
|
-
auto_merge: z.ZodOptional<z.ZodUnknown
|
|
145
|
-
base: z.ZodOptional<z.ZodUnknown
|
|
144
|
+
auto_merge: z.ZodOptional<z.ZodNullable<z.ZodUnknown>>;
|
|
145
|
+
base: z.ZodOptional<z.ZodNullable<z.ZodUnknown>>;
|
|
146
146
|
body: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
147
147
|
closed_at: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
148
148
|
comments_url: z.ZodOptional<z.ZodString>;
|
|
149
149
|
commits_url: z.ZodOptional<z.ZodString>;
|
|
150
150
|
diff_url: z.ZodOptional<z.ZodString>;
|
|
151
|
-
head: z.ZodOptional<z.ZodUnknown
|
|
151
|
+
head: z.ZodOptional<z.ZodNullable<z.ZodUnknown>>;
|
|
152
152
|
html_url: z.ZodOptional<z.ZodString>;
|
|
153
153
|
id: z.ZodOptional<z.ZodNumber>;
|
|
154
154
|
issue_url: z.ZodOptional<z.ZodString>;
|
|
155
|
-
labels: z.ZodOptional<z.ZodUnknown
|
|
155
|
+
labels: z.ZodOptional<z.ZodNullable<z.ZodUnknown>>;
|
|
156
156
|
locked: z.ZodOptional<z.ZodBoolean>;
|
|
157
157
|
merge_commit_sha: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
158
158
|
merged_at: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
159
159
|
milestone: z.ZodOptional<z.ZodUnknown>;
|
|
160
160
|
node_id: z.ZodOptional<z.ZodString>;
|
|
161
161
|
patch_url: z.ZodOptional<z.ZodString>;
|
|
162
|
-
requested_reviewers: z.ZodOptional<z.ZodUnknown
|
|
163
|
-
requested_teams: z.ZodOptional<z.ZodUnknown
|
|
162
|
+
requested_reviewers: z.ZodOptional<z.ZodNullable<z.ZodUnknown>>;
|
|
163
|
+
requested_teams: z.ZodOptional<z.ZodNullable<z.ZodUnknown>>;
|
|
164
164
|
review_comment_url: z.ZodOptional<z.ZodString>;
|
|
165
165
|
review_comments_url: z.ZodOptional<z.ZodString>;
|
|
166
166
|
statuses_url: z.ZodOptional<z.ZodString>;
|
|
@@ -314,20 +314,12 @@ declare const githubResources: {
|
|
|
314
314
|
readonly contributor: {
|
|
315
315
|
readonly shape: "entity";
|
|
316
316
|
readonly filterable: [];
|
|
317
|
-
readonly description: "Per-author commit
|
|
318
|
-
readonly endpoint: "GET /repos/{owner}/{repo}/
|
|
317
|
+
readonly description: "Per-author commit counts for the repository.";
|
|
318
|
+
readonly endpoint: "GET /repos/{owner}/{repo}/contributors";
|
|
319
319
|
readonly responses: {
|
|
320
320
|
readonly contributors: z.ZodArray<z.ZodObject<{
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
w: z.ZodNumber;
|
|
324
|
-
a: z.ZodNumber;
|
|
325
|
-
d: z.ZodNumber;
|
|
326
|
-
c: z.ZodNumber;
|
|
327
|
-
}, z.core.$strip>>;
|
|
328
|
-
author: z.ZodObject<{
|
|
329
|
-
login: z.ZodString;
|
|
330
|
-
}, z.core.$strip>;
|
|
321
|
+
login: z.ZodString;
|
|
322
|
+
contributions: z.ZodNumber;
|
|
331
323
|
}, z.core.$strip>>;
|
|
332
324
|
};
|
|
333
325
|
};
|
|
@@ -387,8 +379,8 @@ declare class GitHubConnector extends BaseConnector<GitHubSettings, GitHubCreden
|
|
|
387
379
|
check_suite_url: z.ZodOptional<z.ZodString>;
|
|
388
380
|
display_title: z.ZodOptional<z.ZodString>;
|
|
389
381
|
event: z.ZodOptional<z.ZodString>;
|
|
390
|
-
head_commit: z.ZodOptional<z.ZodUnknown
|
|
391
|
-
head_repository: z.ZodOptional<z.ZodUnknown
|
|
382
|
+
head_commit: z.ZodOptional<z.ZodNullable<z.ZodUnknown>>;
|
|
383
|
+
head_repository: z.ZodOptional<z.ZodNullable<z.ZodUnknown>>;
|
|
392
384
|
head_sha: z.ZodOptional<z.ZodString>;
|
|
393
385
|
html_url: z.ZodOptional<z.ZodString>;
|
|
394
386
|
jobs_url: z.ZodOptional<z.ZodString>;
|
|
@@ -396,9 +388,9 @@ declare class GitHubConnector extends BaseConnector<GitHubSettings, GitHubCreden
|
|
|
396
388
|
node_id: z.ZodOptional<z.ZodString>;
|
|
397
389
|
path: z.ZodOptional<z.ZodString>;
|
|
398
390
|
previous_attempt_url: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
399
|
-
pull_requests: z.ZodOptional<z.ZodArray<z.ZodUnknown
|
|
400
|
-
referenced_workflows: z.ZodOptional<z.ZodArray<z.ZodUnknown
|
|
401
|
-
repository: z.ZodOptional<z.ZodUnknown
|
|
391
|
+
pull_requests: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodUnknown>>>;
|
|
392
|
+
referenced_workflows: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodUnknown>>>;
|
|
393
|
+
repository: z.ZodOptional<z.ZodNullable<z.ZodUnknown>>;
|
|
402
394
|
rerun_url: z.ZodOptional<z.ZodString>;
|
|
403
395
|
run_number: z.ZodOptional<z.ZodNumber>;
|
|
404
396
|
run_started_at: z.ZodOptional<z.ZodISODateTime>;
|
|
@@ -451,31 +443,31 @@ declare class GitHubConnector extends BaseConnector<GitHubSettings, GitHubCreden
|
|
|
451
443
|
}, z.core.$strip>;
|
|
452
444
|
created_at: z.ZodISODateTime;
|
|
453
445
|
updated_at: z.ZodISODateTime;
|
|
454
|
-
_links: z.ZodOptional<z.ZodUnknown
|
|
446
|
+
_links: z.ZodOptional<z.ZodNullable<z.ZodUnknown>>;
|
|
455
447
|
active_lock_reason: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
456
448
|
assignee: z.ZodOptional<z.ZodUnknown>;
|
|
457
|
-
assignees: z.ZodOptional<z.ZodUnknown
|
|
449
|
+
assignees: z.ZodOptional<z.ZodNullable<z.ZodUnknown>>;
|
|
458
450
|
author_association: z.ZodOptional<z.ZodString>;
|
|
459
|
-
auto_merge: z.ZodOptional<z.ZodUnknown
|
|
460
|
-
base: z.ZodOptional<z.ZodUnknown
|
|
451
|
+
auto_merge: z.ZodOptional<z.ZodNullable<z.ZodUnknown>>;
|
|
452
|
+
base: z.ZodOptional<z.ZodNullable<z.ZodUnknown>>;
|
|
461
453
|
body: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
462
454
|
closed_at: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
463
455
|
comments_url: z.ZodOptional<z.ZodString>;
|
|
464
456
|
commits_url: z.ZodOptional<z.ZodString>;
|
|
465
457
|
diff_url: z.ZodOptional<z.ZodString>;
|
|
466
|
-
head: z.ZodOptional<z.ZodUnknown
|
|
458
|
+
head: z.ZodOptional<z.ZodNullable<z.ZodUnknown>>;
|
|
467
459
|
html_url: z.ZodOptional<z.ZodString>;
|
|
468
460
|
id: z.ZodOptional<z.ZodNumber>;
|
|
469
461
|
issue_url: z.ZodOptional<z.ZodString>;
|
|
470
|
-
labels: z.ZodOptional<z.ZodUnknown
|
|
462
|
+
labels: z.ZodOptional<z.ZodNullable<z.ZodUnknown>>;
|
|
471
463
|
locked: z.ZodOptional<z.ZodBoolean>;
|
|
472
464
|
merge_commit_sha: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
473
465
|
merged_at: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
474
466
|
milestone: z.ZodOptional<z.ZodUnknown>;
|
|
475
467
|
node_id: z.ZodOptional<z.ZodString>;
|
|
476
468
|
patch_url: z.ZodOptional<z.ZodString>;
|
|
477
|
-
requested_reviewers: z.ZodOptional<z.ZodUnknown
|
|
478
|
-
requested_teams: z.ZodOptional<z.ZodUnknown
|
|
469
|
+
requested_reviewers: z.ZodOptional<z.ZodNullable<z.ZodUnknown>>;
|
|
470
|
+
requested_teams: z.ZodOptional<z.ZodNullable<z.ZodUnknown>>;
|
|
479
471
|
review_comment_url: z.ZodOptional<z.ZodString>;
|
|
480
472
|
review_comments_url: z.ZodOptional<z.ZodString>;
|
|
481
473
|
statuses_url: z.ZodOptional<z.ZodString>;
|
|
@@ -629,20 +621,12 @@ declare class GitHubConnector extends BaseConnector<GitHubSettings, GitHubCreden
|
|
|
629
621
|
readonly contributor: {
|
|
630
622
|
readonly shape: "entity";
|
|
631
623
|
readonly filterable: [];
|
|
632
|
-
readonly description: "Per-author commit
|
|
633
|
-
readonly endpoint: "GET /repos/{owner}/{repo}/
|
|
624
|
+
readonly description: "Per-author commit counts for the repository.";
|
|
625
|
+
readonly endpoint: "GET /repos/{owner}/{repo}/contributors";
|
|
634
626
|
readonly responses: {
|
|
635
627
|
readonly contributors: z.ZodArray<z.ZodObject<{
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
w: z.ZodNumber;
|
|
639
|
-
a: z.ZodNumber;
|
|
640
|
-
d: z.ZodNumber;
|
|
641
|
-
c: z.ZodNumber;
|
|
642
|
-
}, z.core.$strip>>;
|
|
643
|
-
author: z.ZodObject<{
|
|
644
|
-
login: z.ZodString;
|
|
645
|
-
}, z.core.$strip>;
|
|
628
|
+
login: z.ZodString;
|
|
629
|
+
contributions: z.ZodNumber;
|
|
646
630
|
}, z.core.$strip>>;
|
|
647
631
|
};
|
|
648
632
|
};
|
|
@@ -675,8 +659,8 @@ declare class GitHubConnector extends BaseConnector<GitHubSettings, GitHubCreden
|
|
|
675
659
|
check_suite_url: z.ZodOptional<z.ZodString>;
|
|
676
660
|
display_title: z.ZodOptional<z.ZodString>;
|
|
677
661
|
event: z.ZodOptional<z.ZodString>;
|
|
678
|
-
head_commit: z.ZodOptional<z.ZodUnknown
|
|
679
|
-
head_repository: z.ZodOptional<z.ZodUnknown
|
|
662
|
+
head_commit: z.ZodOptional<z.ZodNullable<z.ZodUnknown>>;
|
|
663
|
+
head_repository: z.ZodOptional<z.ZodNullable<z.ZodUnknown>>;
|
|
680
664
|
head_sha: z.ZodOptional<z.ZodString>;
|
|
681
665
|
html_url: z.ZodOptional<z.ZodString>;
|
|
682
666
|
jobs_url: z.ZodOptional<z.ZodString>;
|
|
@@ -684,9 +668,9 @@ declare class GitHubConnector extends BaseConnector<GitHubSettings, GitHubCreden
|
|
|
684
668
|
node_id: z.ZodOptional<z.ZodString>;
|
|
685
669
|
path: z.ZodOptional<z.ZodString>;
|
|
686
670
|
previous_attempt_url: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
687
|
-
pull_requests: z.ZodOptional<z.ZodArray<z.ZodUnknown
|
|
688
|
-
referenced_workflows: z.ZodOptional<z.ZodArray<z.ZodUnknown
|
|
689
|
-
repository: z.ZodOptional<z.ZodUnknown
|
|
671
|
+
pull_requests: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodUnknown>>>;
|
|
672
|
+
referenced_workflows: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodUnknown>>>;
|
|
673
|
+
repository: z.ZodOptional<z.ZodNullable<z.ZodUnknown>>;
|
|
690
674
|
rerun_url: z.ZodOptional<z.ZodString>;
|
|
691
675
|
run_number: z.ZodOptional<z.ZodNumber>;
|
|
692
676
|
run_started_at: z.ZodOptional<z.ZodISODateTime>;
|
|
@@ -727,31 +711,31 @@ declare class GitHubConnector extends BaseConnector<GitHubSettings, GitHubCreden
|
|
|
727
711
|
}, z.core.$strip>;
|
|
728
712
|
created_at: z.ZodISODateTime;
|
|
729
713
|
updated_at: z.ZodISODateTime;
|
|
730
|
-
_links: z.ZodOptional<z.ZodUnknown
|
|
714
|
+
_links: z.ZodOptional<z.ZodNullable<z.ZodUnknown>>;
|
|
731
715
|
active_lock_reason: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
732
716
|
assignee: z.ZodOptional<z.ZodUnknown>;
|
|
733
|
-
assignees: z.ZodOptional<z.ZodUnknown
|
|
717
|
+
assignees: z.ZodOptional<z.ZodNullable<z.ZodUnknown>>;
|
|
734
718
|
author_association: z.ZodOptional<z.ZodString>;
|
|
735
|
-
auto_merge: z.ZodOptional<z.ZodUnknown
|
|
736
|
-
base: z.ZodOptional<z.ZodUnknown
|
|
719
|
+
auto_merge: z.ZodOptional<z.ZodNullable<z.ZodUnknown>>;
|
|
720
|
+
base: z.ZodOptional<z.ZodNullable<z.ZodUnknown>>;
|
|
737
721
|
body: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
738
722
|
closed_at: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
739
723
|
comments_url: z.ZodOptional<z.ZodString>;
|
|
740
724
|
commits_url: z.ZodOptional<z.ZodString>;
|
|
741
725
|
diff_url: z.ZodOptional<z.ZodString>;
|
|
742
|
-
head: z.ZodOptional<z.ZodUnknown
|
|
726
|
+
head: z.ZodOptional<z.ZodNullable<z.ZodUnknown>>;
|
|
743
727
|
html_url: z.ZodOptional<z.ZodString>;
|
|
744
728
|
id: z.ZodOptional<z.ZodNumber>;
|
|
745
729
|
issue_url: z.ZodOptional<z.ZodString>;
|
|
746
|
-
labels: z.ZodOptional<z.ZodUnknown
|
|
730
|
+
labels: z.ZodOptional<z.ZodNullable<z.ZodUnknown>>;
|
|
747
731
|
locked: z.ZodOptional<z.ZodBoolean>;
|
|
748
732
|
merge_commit_sha: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
749
733
|
merged_at: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
750
734
|
milestone: z.ZodOptional<z.ZodUnknown>;
|
|
751
735
|
node_id: z.ZodOptional<z.ZodString>;
|
|
752
736
|
patch_url: z.ZodOptional<z.ZodString>;
|
|
753
|
-
requested_reviewers: z.ZodOptional<z.ZodUnknown
|
|
754
|
-
requested_teams: z.ZodOptional<z.ZodUnknown
|
|
737
|
+
requested_reviewers: z.ZodOptional<z.ZodNullable<z.ZodUnknown>>;
|
|
738
|
+
requested_teams: z.ZodOptional<z.ZodNullable<z.ZodUnknown>>;
|
|
755
739
|
review_comment_url: z.ZodOptional<z.ZodString>;
|
|
756
740
|
review_comments_url: z.ZodOptional<z.ZodString>;
|
|
757
741
|
statuses_url: z.ZodOptional<z.ZodString>;
|
|
@@ -873,16 +857,8 @@ declare class GitHubConnector extends BaseConnector<GitHubSettings, GitHubCreden
|
|
|
873
857
|
}, z.core.$strip>>;
|
|
874
858
|
} & {
|
|
875
859
|
readonly contributors: z.ZodArray<z.ZodObject<{
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
w: z.ZodNumber;
|
|
879
|
-
a: z.ZodNumber;
|
|
880
|
-
d: z.ZodNumber;
|
|
881
|
-
c: z.ZodNumber;
|
|
882
|
-
}, z.core.$strip>>;
|
|
883
|
-
author: z.ZodObject<{
|
|
884
|
-
login: z.ZodString;
|
|
885
|
-
}, z.core.$strip>;
|
|
860
|
+
login: z.ZodString;
|
|
861
|
+
contributions: z.ZodNumber;
|
|
886
862
|
}, z.core.$strip>>;
|
|
887
863
|
} & Readonly<Record<string, z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>>>;
|
|
888
864
|
static create(input: unknown, ctx?: ConnectorContext): GitHubConnector;
|
package/dist/index.js
CHANGED
|
@@ -200,7 +200,6 @@ function selectPhases(allowlist) {
|
|
|
200
200
|
(phase) => PHASE_RESOURCES[phase].some((r) => allowlist.has(r))
|
|
201
201
|
);
|
|
202
202
|
}
|
|
203
|
-
var CONTRIBUTORS_SKIPPED = /* @__PURE__ */ Symbol("contributors-skipped");
|
|
204
203
|
var WORKFLOW_RUN_RERUN_LOOKBACK_MS = 32 * 864e5;
|
|
205
204
|
function dedupeByKey(items, keyFn, resource) {
|
|
206
205
|
if (items.length < 2) {
|
|
@@ -243,8 +242,8 @@ var workflowRunsResponseSchema = z.object({
|
|
|
243
242
|
check_suite_url: z.string().optional(),
|
|
244
243
|
display_title: z.string().optional(),
|
|
245
244
|
event: z.string().optional(),
|
|
246
|
-
head_commit: z.unknown().optional(),
|
|
247
|
-
head_repository: z.unknown().optional(),
|
|
245
|
+
head_commit: z.unknown().nullable().optional(),
|
|
246
|
+
head_repository: z.unknown().nullable().optional(),
|
|
248
247
|
head_sha: z.string().optional(),
|
|
249
248
|
html_url: z.string().optional(),
|
|
250
249
|
jobs_url: z.string().optional(),
|
|
@@ -252,9 +251,9 @@ var workflowRunsResponseSchema = z.object({
|
|
|
252
251
|
node_id: z.string().optional(),
|
|
253
252
|
path: z.string().optional(),
|
|
254
253
|
previous_attempt_url: z.string().nullable().optional(),
|
|
255
|
-
pull_requests: z.array(z.unknown()).optional(),
|
|
256
|
-
referenced_workflows: z.array(z.unknown()).optional(),
|
|
257
|
-
repository: z.unknown().optional(),
|
|
254
|
+
pull_requests: z.array(z.unknown()).nullable().optional(),
|
|
255
|
+
referenced_workflows: z.array(z.unknown()).nullable().optional(),
|
|
256
|
+
repository: z.unknown().nullable().optional(),
|
|
258
257
|
rerun_url: z.string().optional(),
|
|
259
258
|
run_number: z.number().int().optional(),
|
|
260
259
|
run_started_at: z.iso.datetime().optional(),
|
|
@@ -294,31 +293,31 @@ var pullRequestsSchema = z.array(
|
|
|
294
293
|
}),
|
|
295
294
|
created_at: z.iso.datetime(),
|
|
296
295
|
updated_at: z.iso.datetime(),
|
|
297
|
-
_links: z.unknown().optional(),
|
|
296
|
+
_links: z.unknown().nullable().optional(),
|
|
298
297
|
active_lock_reason: z.string().nullable().optional(),
|
|
299
298
|
assignee: z.unknown().optional(),
|
|
300
|
-
assignees: z.unknown().optional(),
|
|
299
|
+
assignees: z.unknown().nullable().optional(),
|
|
301
300
|
author_association: z.string().optional(),
|
|
302
|
-
auto_merge: z.unknown().optional(),
|
|
303
|
-
base: z.unknown().optional(),
|
|
301
|
+
auto_merge: z.unknown().nullable().optional(),
|
|
302
|
+
base: z.unknown().nullable().optional(),
|
|
304
303
|
body: z.string().nullable().optional(),
|
|
305
304
|
closed_at: z.string().nullable().optional(),
|
|
306
305
|
comments_url: z.string().optional(),
|
|
307
306
|
commits_url: z.string().optional(),
|
|
308
307
|
diff_url: z.string().optional(),
|
|
309
|
-
head: z.unknown().optional(),
|
|
308
|
+
head: z.unknown().nullable().optional(),
|
|
310
309
|
html_url: z.string().optional(),
|
|
311
310
|
id: z.number().int().optional(),
|
|
312
311
|
issue_url: z.string().optional(),
|
|
313
|
-
labels: z.unknown().optional(),
|
|
312
|
+
labels: z.unknown().nullable().optional(),
|
|
314
313
|
locked: z.boolean().optional(),
|
|
315
314
|
merge_commit_sha: z.string().nullable().optional(),
|
|
316
315
|
merged_at: z.string().nullable().optional(),
|
|
317
316
|
milestone: z.unknown().optional(),
|
|
318
317
|
node_id: z.string().optional(),
|
|
319
318
|
patch_url: z.string().optional(),
|
|
320
|
-
requested_reviewers: z.unknown().optional(),
|
|
321
|
-
requested_teams: z.unknown().optional(),
|
|
319
|
+
requested_reviewers: z.unknown().nullable().optional(),
|
|
320
|
+
requested_teams: z.unknown().nullable().optional(),
|
|
322
321
|
review_comment_url: z.string().optional(),
|
|
323
322
|
review_comments_url: z.string().optional(),
|
|
324
323
|
statuses_url: z.string().optional(),
|
|
@@ -442,16 +441,8 @@ var releasesSchema = z.array(
|
|
|
442
441
|
);
|
|
443
442
|
var contributorsSchema = z.array(
|
|
444
443
|
z.object({
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
z.object({
|
|
448
|
-
w: z.number().int(),
|
|
449
|
-
a: z.number().int(),
|
|
450
|
-
d: z.number().int(),
|
|
451
|
-
c: z.number().int()
|
|
452
|
-
})
|
|
453
|
-
),
|
|
454
|
-
author: z.object({ login: z.string().min(1) })
|
|
444
|
+
login: z.string().min(1),
|
|
445
|
+
contributions: z.number().int()
|
|
455
446
|
})
|
|
456
447
|
);
|
|
457
448
|
var repoStatsSchema = z.object({
|
|
@@ -541,8 +532,8 @@ var githubResources = defineResources({
|
|
|
541
532
|
contributor: {
|
|
542
533
|
shape: "entity",
|
|
543
534
|
filterable: [],
|
|
544
|
-
description: "Per-author commit
|
|
545
|
-
endpoint: "GET /repos/{owner}/{repo}/
|
|
535
|
+
description: "Per-author commit counts for the repository.",
|
|
536
|
+
endpoint: "GET /repos/{owner}/{repo}/contributors",
|
|
546
537
|
responses: { contributors: contributorsSchema }
|
|
547
538
|
}
|
|
548
539
|
});
|
|
@@ -595,8 +586,9 @@ var GitHubConnector = class _GitHubConnector extends BaseConnector {
|
|
|
595
586
|
return `/repos/${owner}/${repo}/deployments`;
|
|
596
587
|
case "releases":
|
|
597
588
|
return `/repos/${owner}/${repo}/releases`;
|
|
598
|
-
case "repo_stats":
|
|
599
589
|
case "contributors":
|
|
590
|
+
return `/repos/${owner}/${repo}/contributors`;
|
|
591
|
+
case "repo_stats":
|
|
600
592
|
return null;
|
|
601
593
|
}
|
|
602
594
|
}
|
|
@@ -816,32 +808,16 @@ var GitHubConnector = class _GitHubConnector extends BaseConnector {
|
|
|
816
808
|
const filtered = cutoff !== null ? releases.filter((r) => new Date(r.created_at).getTime() >= cutoff) : releases;
|
|
817
809
|
return { items: filtered, next: nextLink };
|
|
818
810
|
}
|
|
819
|
-
async fetchContributors(signal) {
|
|
811
|
+
async fetchContributors(page, signal) {
|
|
820
812
|
const { owner, repo } = this.settings;
|
|
821
|
-
const
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
sig
|
|
827
|
-
);
|
|
828
|
-
if (res.status === 202) {
|
|
829
|
-
return { status: "retry" };
|
|
830
|
-
}
|
|
831
|
-
return {
|
|
832
|
-
status: "done",
|
|
833
|
-
value: res.body ?? []
|
|
834
|
-
};
|
|
835
|
-
},
|
|
836
|
-
{ maxAttempts: 15, initialDelayMs: 1e3, maxDelayMs: 1e4, signal }
|
|
813
|
+
const url = page ?? `https://api.github.com/repos/${owner}/${repo}/contributors?per_page=100`;
|
|
814
|
+
const res = await this.fetch(
|
|
815
|
+
url,
|
|
816
|
+
"contributors",
|
|
817
|
+
signal
|
|
837
818
|
);
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
"[github-actions] Stats endpoint never became ready \u2014 skipping contributor sync and keeping previous data."
|
|
841
|
-
);
|
|
842
|
-
return { items: [CONTRIBUTORS_SKIPPED], next: null };
|
|
843
|
-
}
|
|
844
|
-
return { items: contributors, next: null };
|
|
819
|
+
const nextLink = parseLinkHeader(res.headers.get("link"))["next"] ?? null;
|
|
820
|
+
return { items: res.body, next: nextLink };
|
|
845
821
|
}
|
|
846
822
|
async writeRepoStats(storage, items) {
|
|
847
823
|
const repoBody = items[0];
|
|
@@ -1089,34 +1065,24 @@ var GitHubConnector = class _GitHubConnector extends BaseConnector {
|
|
|
1089
1065
|
});
|
|
1090
1066
|
}
|
|
1091
1067
|
}
|
|
1092
|
-
async writeContributors(storage, items) {
|
|
1093
|
-
if (
|
|
1094
|
-
|
|
1068
|
+
async writeContributors(storage, items, page) {
|
|
1069
|
+
if (page === null) {
|
|
1070
|
+
await storage.entities([], { types: ["contributor"] });
|
|
1095
1071
|
}
|
|
1096
1072
|
const contributors = dedupeByKey(
|
|
1097
1073
|
items,
|
|
1098
|
-
(c) => c.
|
|
1074
|
+
(c) => c.login,
|
|
1099
1075
|
"contributors"
|
|
1100
1076
|
);
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
commits: c.total,
|
|
1111
|
-
additions,
|
|
1112
|
-
deletions,
|
|
1113
|
-
latest_commit_at: latestWeek ? latestWeek.w * 1e3 : null
|
|
1114
|
-
},
|
|
1115
|
-
updated_at: latestWeek ? latestWeek.w * 1e3 : 0
|
|
1116
|
-
};
|
|
1117
|
-
}),
|
|
1118
|
-
{ types: ["contributor"] }
|
|
1119
|
-
);
|
|
1077
|
+
const observedAt = Date.now();
|
|
1078
|
+
for (const c of contributors) {
|
|
1079
|
+
await storage.entity({
|
|
1080
|
+
type: "contributor",
|
|
1081
|
+
id: c.login,
|
|
1082
|
+
attributes: { commits: c.contributions },
|
|
1083
|
+
updated_at: observedAt
|
|
1084
|
+
});
|
|
1085
|
+
}
|
|
1120
1086
|
}
|
|
1121
1087
|
async sync(options, storage, signal) {
|
|
1122
1088
|
const cursor = this.resolveCursor(options.cursor);
|
|
@@ -1168,7 +1134,7 @@ var GitHubConnector = class _GitHubConnector extends BaseConnector {
|
|
|
1168
1134
|
case "releases":
|
|
1169
1135
|
return this.fetchReleases(page, sig, cutoffFor(phase, spec));
|
|
1170
1136
|
case "contributors":
|
|
1171
|
-
return this.fetchContributors(sig);
|
|
1137
|
+
return this.fetchContributors(page, sig);
|
|
1172
1138
|
}
|
|
1173
1139
|
},
|
|
1174
1140
|
writeBatch: async (phase, items, page, specIndex) => {
|
|
@@ -1198,7 +1164,7 @@ var GitHubConnector = class _GitHubConnector extends BaseConnector {
|
|
|
1198
1164
|
case "releases":
|
|
1199
1165
|
return this.writeReleases(storage, items, page, specIndex);
|
|
1200
1166
|
case "contributors":
|
|
1201
|
-
return this.writeContributors(storage, items);
|
|
1167
|
+
return this.writeContributors(storage, items, page);
|
|
1202
1168
|
}
|
|
1203
1169
|
}
|
|
1204
1170
|
});
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../connector-shared/src/errors.ts","../../../connector-shared/src/retry.ts","../../../connector-shared/src/version.ts","../../../connector-shared/src/request.ts","../../../connector-shared/src/rate-limit.ts","../../../connector-shared/src/map-concurrent.ts","../../../connector-shared/src/sanitize.ts","../../../connector-shared/src/epoch.ts","../../../connector-shared/src/pagination.ts","../../../connector-shared/src/logger.ts","../src/github.ts","../src/index.ts"],"sourcesContent":["import type { HttpResponse } from './types';\n\nexport type HttpErrorKind =\n | 'transient'\n | 'rate_limit'\n | 'auth'\n | 'upstream_bug'\n | 'client_bug';\n\nexport abstract class HttpClientError extends Error {\n abstract readonly kind: HttpErrorKind;\n readonly response?: HttpResponse;\n\n constructor(message: string, response?: HttpResponse) {\n super(message);\n this.name = new.target.name;\n this.response = response;\n }\n}\n\nexport class TransientError extends HttpClientError {\n readonly kind = 'transient' as const;\n}\n\nexport class RateLimitError extends HttpClientError {\n readonly kind = 'rate_limit' as const;\n readonly retryAfter?: Date;\n\n constructor(message: string, response?: HttpResponse, retryAfter?: Date) {\n super(message, response);\n this.retryAfter = retryAfter;\n }\n}\n\nexport class AuthError extends HttpClientError {\n readonly kind = 'auth' as const;\n}\n\nexport class UpstreamBugError extends HttpClientError {\n readonly kind = 'upstream_bug' as const;\n}\n\nexport class ClientBugError extends HttpClientError {\n readonly kind = 'client_bug' as const;\n}\n\nexport function classifyStatus(status: number): HttpErrorKind {\n if (status === 429) {\n return 'rate_limit';\n }\n if (status === 401 || status === 403) {\n return 'auth';\n }\n if (status === 408) {\n return 'transient';\n }\n if (status >= 500) {\n return 'upstream_bug';\n }\n if (status >= 400) {\n return 'client_bug';\n }\n return 'client_bug';\n}\n\nexport function errorForStatus(\n message: string,\n response: HttpResponse,\n retryAfter?: Date,\n): HttpClientError {\n const kind = classifyStatus(response.status);\n switch (kind) {\n case 'rate_limit':\n return new RateLimitError(message, response, retryAfter);\n case 'auth':\n return new AuthError(message, response);\n case 'transient':\n return new TransientError(message, response);\n case 'upstream_bug':\n return new UpstreamBugError(message, response);\n case 'client_bug':\n return new ClientBugError(message, response);\n }\n}\n","import { HttpClientError, RateLimitError, TransientError } from './errors';\n\nexport interface RetryPolicy {\n maxAttempts?: number;\n initialDelayMs?: number;\n maxDelayMs?: number;\n retryOn?: (status: number | null, err?: Error) => boolean;\n}\n\nexport const defaultRetryOn = (status: number | null, err?: Error): boolean => {\n if (err instanceof RateLimitError) {\n return true;\n }\n if (err instanceof TransientError) {\n return true;\n }\n if (status === null) {\n return err instanceof Error && !(err instanceof HttpClientError);\n }\n if (status === 408 || status === 429) {\n return true;\n }\n if (status >= 500) {\n return true;\n }\n return false;\n};\n\nexport function backoffDelayMs(\n attempt: number,\n policy: Required<Pick<RetryPolicy, 'initialDelayMs' | 'maxDelayMs'>>,\n): number {\n const base = policy.initialDelayMs * 2 ** attempt;\n const jitter = base * 0.25 * Math.random();\n return Math.min(base + jitter, policy.maxDelayMs);\n}\n\nexport function parseRetryAfter(\n headerValue: string | null,\n now: Date = new Date(),\n): Date | undefined {\n if (!headerValue) {\n return undefined;\n }\n const trimmed = headerValue.trim();\n if (/^\\d+$/.test(trimmed)) {\n return new Date(now.getTime() + Number(trimmed) * 1000);\n }\n const parsed = Date.parse(trimmed);\n if (Number.isNaN(parsed)) {\n return undefined;\n }\n return new Date(parsed);\n}\n\nexport function sleep(ms: number, signal?: AbortSignal): Promise<void> {\n if (signal?.aborted) {\n return Promise.reject(signal.reason ?? new Error('Aborted'));\n }\n return new Promise<void>((resolve, reject) => {\n const onAbort = () => {\n clearTimeout(timer);\n reject(signal!.reason ?? new Error('Aborted'));\n };\n const timer = setTimeout(() => {\n signal?.removeEventListener('abort', onAbort);\n resolve();\n }, ms);\n signal?.addEventListener('abort', onAbort, { once: true });\n });\n}\n","export const HTTP_CLIENT_VERSION = '0.0.0';\n\nexport const DEFAULT_USER_AGENT = `rawdash-connector/${HTTP_CLIENT_VERSION} (+https://rawdash.dev)`;\n\nexport function connectorUserAgent(connectorId: string): string {\n return `rawdash-connector-${connectorId}/${HTTP_CLIENT_VERSION} (+https://rawdash.dev)`;\n}\n","import {\n AuthError,\n ClientBugError,\n HttpClientError,\n RateLimitError,\n TransientError,\n UpstreamBugError,\n errorForStatus,\n} from './errors';\nimport { defaultRetryOn, parseRetryAfter, sleep } from './retry';\nimport type { FetchLike, HttpMethod, HttpRequest, HttpResponse } from './types';\nimport { DEFAULT_USER_AGENT } from './version';\n\nconst DEFAULT_TIMEOUT_MS = 10_000;\nconst DEFAULT_MAX_ATTEMPTS = 3;\nconst DEFAULT_INITIAL_DELAY_MS = 1000;\nconst DEFAULT_MAX_DELAY_MS = 60_000;\nconst OBSERVER_TIMEOUT_MS = 250;\n\nexport interface RequestObservation {\n url: string;\n method: HttpMethod;\n status: number;\n resource: string;\n requestId: string;\n body: unknown;\n}\n\nexport type RequestObserver = (\n event: RequestObservation,\n) => void | Promise<void>;\n\nexport interface RequestOptions {\n fetch?: FetchLike;\n observer?: RequestObserver;\n resource: string;\n requestId?: string;\n}\n\nasync function notifyObserver(\n observer: RequestObserver,\n event: RequestObservation,\n): Promise<void> {\n let result: void | Promise<void>;\n try {\n result = observer(event);\n } catch (err) {\n console.warn('[connector-shared] request observer threw:', err);\n return;\n }\n if (!(result instanceof Promise)) {\n return;\n }\n const guarded = result.catch((err) => {\n console.warn('[connector-shared] request observer rejected:', err);\n });\n let timer: ReturnType<typeof setTimeout> | undefined;\n const timeout = new Promise<void>((resolve) => {\n timer = setTimeout(resolve, OBSERVER_TIMEOUT_MS);\n });\n try {\n await Promise.race([guarded, timeout]);\n } finally {\n if (timer) {\n clearTimeout(timer);\n }\n }\n}\n\nfunction newRequestId(): string {\n const c = (globalThis as { crypto?: { randomUUID?: () => string } }).crypto;\n if (c?.randomUUID) {\n return c.randomUUID();\n }\n return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;\n}\n\nfunction mergeHeaders(\n defaults: Record<string, string>,\n overrides: Record<string, string> | undefined,\n): Record<string, string> {\n const merged: Record<string, string> = {};\n for (const [k, v] of Object.entries(defaults)) {\n merged[k.toLowerCase()] = v;\n }\n if (overrides) {\n for (const [k, v] of Object.entries(overrides)) {\n merged[k.toLowerCase()] = v;\n }\n }\n return merged;\n}\n\nfunction linkTimeoutSignal(\n parent: AbortSignal | undefined,\n timeoutMs: number,\n): { signal: AbortSignal; cancel: () => void } {\n const controller = new AbortController();\n const onParentAbort = () => {\n controller.abort(parent?.reason);\n };\n if (parent) {\n if (parent.aborted) {\n controller.abort(parent.reason);\n } else {\n parent.addEventListener('abort', onParentAbort, { once: true });\n }\n }\n const timer = setTimeout(() => {\n controller.abort(new Error(`Request timed out after ${timeoutMs}ms`));\n }, timeoutMs);\n return {\n signal: controller.signal,\n cancel: () => {\n clearTimeout(timer);\n if (parent) {\n parent.removeEventListener('abort', onParentAbort);\n }\n },\n };\n}\n\nasync function readBody(res: Response, parseJson: boolean): Promise<unknown> {\n if (res.status === 204 || res.status === 205) {\n return null;\n }\n const contentType = res.headers.get('content-type') ?? '';\n if (parseJson && contentType.includes('application/json')) {\n const text = await res.text();\n if (text.length === 0) {\n return null;\n }\n return JSON.parse(text);\n }\n return res.text();\n}\n\nexport async function request<T = unknown>(\n req: HttpRequest,\n options: RequestOptions,\n): Promise<HttpResponse<T>> {\n const fetchImpl: FetchLike = options.fetch ?? (globalThis.fetch as FetchLike);\n const retry = req.retry ?? {};\n const maxAttempts = retry.maxAttempts ?? DEFAULT_MAX_ATTEMPTS;\n const initialDelayMs = retry.initialDelayMs ?? DEFAULT_INITIAL_DELAY_MS;\n const maxDelayMs = retry.maxDelayMs ?? DEFAULT_MAX_DELAY_MS;\n const retryOn = retry.retryOn ?? defaultRetryOn;\n const timeoutMs = req.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const parseJson = req.parseJson ?? true;\n\n const headers = mergeHeaders(\n {\n 'User-Agent': DEFAULT_USER_AGENT,\n Accept: 'application/json',\n },\n req.headers,\n );\n\n let lastErr: Error | undefined;\n\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n req.signal?.throwIfAborted();\n\n const { signal, cancel } = linkTimeoutSignal(req.signal, timeoutMs);\n let res: Response;\n try {\n res = await fetchImpl(req.url, {\n method: req.method ?? 'GET',\n headers,\n body: req.body as RequestInit['body'],\n signal,\n });\n } catch (err) {\n cancel();\n if (req.signal?.aborted) {\n throw req.signal.reason ?? err;\n }\n const error = err instanceof Error ? err : new Error(String(err));\n lastErr = error;\n if (attempt < maxAttempts - 1 && retryOn(null, error)) {\n const delay = computeDelay(attempt, initialDelayMs, maxDelayMs);\n await sleep(delay, req.signal);\n continue;\n }\n throw new TransientError(error.message);\n }\n cancel();\n\n const body = await readBody(res, parseJson);\n const httpResponse: HttpResponse<T> = {\n status: res.status,\n headers: res.headers,\n body: body as T,\n };\n if (req.rateLimit) {\n const state = req.rateLimit.parse(res.headers);\n if (state) {\n httpResponse.rateLimitState = state;\n }\n }\n\n if (options.observer) {\n await notifyObserver(options.observer, {\n url: req.url,\n method: req.method ?? 'GET',\n status: res.status,\n resource: options.resource,\n requestId: options.requestId ?? newRequestId(),\n body,\n });\n }\n\n if (res.ok) {\n return httpResponse;\n }\n\n const retryAfter = parseRetryAfter(res.headers.get('retry-after'));\n const message = `HTTP ${res.status} ${res.statusText} for ${req.method ?? 'GET'} ${req.url}`;\n const err = errorForStatus(message, httpResponse, retryAfter);\n\n if (\n attempt < maxAttempts - 1 &&\n retryOn(res.status, err) &&\n !(err instanceof AuthError) &&\n !(err instanceof ClientBugError)\n ) {\n lastErr = err;\n let delay = computeDelay(attempt, initialDelayMs, maxDelayMs);\n if (err instanceof RateLimitError && retryAfter) {\n const wait = retryAfter.getTime() - Date.now();\n if (wait > 0) {\n delay = Math.min(wait, maxDelayMs);\n }\n }\n await sleep(delay, req.signal);\n continue;\n }\n\n throw err;\n }\n\n throw lastErr ?? new UpstreamBugError('Exhausted retry attempts');\n}\n\nfunction computeDelay(\n attempt: number,\n initialDelayMs: number,\n maxDelayMs: number,\n): number {\n const base = initialDelayMs * 2 ** attempt;\n const jitter = base * 0.25 * Math.random();\n return Math.min(base + jitter, maxDelayMs);\n}\n\nexport { HttpClientError };\n","export interface RateLimitState {\n remaining: number;\n resetAt: Date;\n}\n\nexport interface RateLimitPolicy {\n parse(headers: Headers): RateLimitState | null;\n}\n\nexport interface StandardRateLimitPolicyConfig {\n remainingHeader: string;\n resetHeader: string;\n resetUnit: 's' | 'ms';\n resetFallbackMs?: number;\n}\n\nexport function standardRateLimitPolicy(\n config: StandardRateLimitPolicyConfig,\n): RateLimitPolicy {\n const { remainingHeader, resetHeader, resetUnit, resetFallbackMs } = config;\n const multiplier = resetUnit === 's' ? 1000 : 1;\n return {\n parse(h) {\n const remainingRaw = h.get(remainingHeader);\n if (remainingRaw === null || remainingRaw.trim() === '') {\n return null;\n }\n const remaining = Number(remainingRaw);\n if (!Number.isFinite(remaining)) {\n return null;\n }\n const resetRaw = h.get(resetHeader);\n if (resetRaw === null) {\n if (resetFallbackMs === undefined) {\n return null;\n }\n return {\n remaining,\n resetAt: new Date(Date.now() + resetFallbackMs),\n };\n }\n if (resetRaw.trim() === '') {\n return null;\n }\n const reset = Number(resetRaw);\n if (!Number.isFinite(reset) || reset < 0) {\n return null;\n }\n const resetMs = reset * multiplier;\n if (!Number.isFinite(resetMs)) {\n return null;\n }\n return { remaining, resetAt: new Date(resetMs) };\n },\n };\n}\n","export async function mapWithConcurrency<T, R>(\n items: readonly T[],\n concurrency: number,\n fn: (item: T, index: number) => Promise<R>,\n): Promise<R[]> {\n const results = new Array<R>(items.length);\n if (items.length === 0) {\n return results;\n }\n const normalized = Number.isFinite(concurrency) ? Math.floor(concurrency) : 1;\n const limit = Math.max(1, Math.min(normalized, items.length));\n let next = 0;\n let failed = false;\n\n async function worker(): Promise<void> {\n while (!failed) {\n const i = next++;\n if (i >= items.length) {\n return;\n }\n try {\n results[i] = await fn(items[i]!, i);\n } catch (err) {\n failed = true;\n throw err;\n }\n }\n }\n\n const workers: Promise<void>[] = [];\n for (let w = 0; w < limit; w++) {\n workers.push(worker());\n }\n await Promise.all(workers);\n return results;\n}\n","export interface SanitizeAllowedUrlOptions {\n url: string | null;\n host: string;\n pathname: string;\n protocol?: 'https:' | 'http:';\n}\n\nexport function sanitizeAllowedUrl(\n options: SanitizeAllowedUrlOptions,\n): string | null {\n const { url, host, pathname, protocol = 'https:' } = options;\n if (url === null) {\n return null;\n }\n try {\n const u = new URL(url);\n if (u.protocol !== protocol || u.host !== host || u.pathname !== pathname) {\n return null;\n }\n return u.toString();\n } catch {\n return null;\n }\n}\n","export type EpochUnit = 'ms' | 's' | 'iso';\n\nexport function parseEpoch(\n value: number | string | null | undefined,\n unit: EpochUnit,\n): number | null {\n if (value === null || value === undefined) {\n return null;\n }\n if (unit === 'iso') {\n if (typeof value !== 'string') {\n return null;\n }\n const ms = new Date(value).getTime();\n return Number.isFinite(ms) ? ms : null;\n }\n if (typeof value === 'string' && value.trim() === '') {\n return null;\n }\n const n = typeof value === 'number' ? value : Number(value);\n if (!Number.isFinite(n)) {\n return null;\n }\n const result = unit === 's' ? n * 1000 : n;\n return Number.isFinite(result) ? result : null;\n}\n","import { request } from './request';\nimport type { HttpRequest } from './types';\n\nexport function parseLinkHeader(header: string | null): Record<string, string> {\n if (!header) {\n return {};\n }\n const result: Record<string, string> = {};\n for (const part of header.split(',')) {\n const match = part.match(/<([^>]+)>\\s*;\\s*rel=\"([^\"]+)\"/);\n if (match) {\n result[match[2]!] = match[1]!;\n }\n }\n return result;\n}\n\nexport async function* paginateLink<T>(\n initial: HttpRequest,\n parse: (body: unknown) => T[],\n options: { resource: string },\n): AsyncIterable<T> {\n let next: string | null = initial.url;\n while (next) {\n const res: Awaited<ReturnType<typeof request>> = await request(\n {\n ...initial,\n url: next,\n },\n { resource: options.resource },\n );\n for (const item of parse(res.body)) {\n yield item;\n }\n const links = parseLinkHeader(res.headers.get('link'));\n next = links['next'] ?? null;\n }\n}\n\nexport async function* paginateCursor<T>(\n initial: HttpRequest,\n parse: (body: unknown) => { items: T[]; nextCursor: string | null },\n buildNext: (req: HttpRequest, cursor: string) => HttpRequest,\n options: { resource: string },\n): AsyncIterable<T> {\n let req: HttpRequest = initial;\n while (true) {\n const res = await request(req, { resource: options.resource });\n const { items, nextCursor } = parse(res.body);\n for (const item of items) {\n yield item;\n }\n if (!nextCursor) {\n return;\n }\n req = buildNext(req, nextCursor);\n }\n}\n\nexport async function* paginatePage<T>(\n initial: HttpRequest,\n parse: (body: unknown) => { items: T[]; hasMore: boolean },\n buildPage: (req: HttpRequest, page: number) => HttpRequest,\n options: { resource: string },\n): AsyncIterable<T> {\n let page = 1;\n while (true) {\n const req = page === 1 ? initial : buildPage(initial, page);\n const res = await request(req, { resource: options.resource });\n const { items, hasMore } = parse(res.body);\n for (const item of items) {\n yield item;\n }\n if (!hasMore || items.length === 0) {\n return;\n }\n page++;\n }\n}\n","export type LogFields = Record<string, unknown>;\n\nexport interface ConnectorLogger {\n info(event: string, fields?: LogFields): void;\n warn(event: string, fields?: LogFields): void;\n}\n\nexport interface ConnectorLoggerOptions {\n scope: string;\n}\n\nconst MAX_VALUE_LEN = 120;\n\nfunction truncate(s: string, max = MAX_VALUE_LEN): string {\n if (s.length <= max) {\n return s;\n }\n return `${s.slice(0, max - 1)}…`;\n}\n\nfunction formatValue(value: unknown): string {\n if (value === null) {\n return 'null';\n }\n if (value === undefined) {\n return '';\n }\n if (typeof value === 'number' || typeof value === 'boolean') {\n return String(value);\n }\n if (typeof value === 'string') {\n const t = truncate(value);\n if (/[\\s\"=]/.test(t)) {\n return JSON.stringify(t);\n }\n return t;\n }\n if (typeof value === 'bigint') {\n return value.toString();\n }\n let json: string | undefined;\n try {\n json = JSON.stringify(value);\n } catch {\n json = undefined;\n }\n return truncate(json ?? String(value));\n}\n\nexport function formatLogFields(fields?: LogFields): string {\n if (!fields) {\n return '';\n }\n const parts: string[] = [];\n for (const [k, v] of Object.entries(fields)) {\n if (v === undefined) {\n continue;\n }\n parts.push(`${k}=${formatValue(v)}`);\n }\n return parts.length > 0 ? ` ${parts.join(' ')}` : '';\n}\n\nexport function formatLogLine(\n scope: string,\n event: string,\n fields?: LogFields,\n): string {\n return `[${scope}] ${event}${formatLogFields(fields)}`;\n}\n\nexport function createDefaultConnectorLogger(\n opts: ConnectorLoggerOptions,\n): ConnectorLogger {\n return {\n info(event, fields) {\n console.info(formatLogLine(opts.scope, event, fields));\n },\n warn(event, fields) {\n console.warn(formatLogLine(opts.scope, event, fields));\n },\n };\n}\n\nconst NOOP_LOGGER: ConnectorLogger = {\n info() {},\n warn() {},\n};\n\nexport function noopConnectorLogger(): ConnectorLogger {\n return NOOP_LOGGER;\n}\n","import {\n type HttpResponse,\n connectorUserAgent,\n parseLinkHeader,\n sanitizeAllowedUrl,\n standardRateLimitPolicy,\n} from '@rawdash/connector-shared';\nimport {\n BaseConnector,\n type ChunkedSyncCursor,\n type ConnectorContext,\n type ConnectorDoc,\n type CredentialsSchema,\n type FetchPageResult,\n type FetchSpec,\n type FilterClause,\n type StorageHandle,\n type SyncOptions,\n type SyncResult,\n defineConfigFields,\n defineConnectorDoc,\n defineResources,\n makeChunkedCursorGuard,\n paginateChunked,\n resolveBackfillCutoff,\n resolveSpecCutoff,\n schemasFromResources,\n} from '@rawdash/core';\nimport { z } from 'zod';\n\nexport const configFields = defineConfigFields(\n z.object({\n owner: z.string().min(1).meta({\n label: 'Repository owner',\n description: 'GitHub username or organization name.',\n placeholder: 'rawdash',\n }),\n repo: z.string().min(1).meta({\n label: 'Repository',\n description: 'Repository name.',\n placeholder: 'rawdash',\n }),\n token: z.object({ $secret: z.string() }).optional().meta({\n label: 'Personal access token',\n description: 'GitHub PAT with `repo` scope.',\n secret: true,\n }),\n }),\n);\n\nexport const doc: ConnectorDoc = defineConnectorDoc({\n displayName: 'GitHub',\n category: 'engineering',\n brandColor: '#181717',\n tagline:\n 'Sync pull requests, issues, deployments, releases, CI runs, and contributor activity from a GitHub repository.',\n vendor: {\n name: 'GitHub',\n domain: 'github.com',\n apiDocs: 'https://docs.github.com/rest',\n website: 'https://github.com',\n },\n auth: {\n summary:\n 'A personal access token is optional for public repositories but required for private repos and to avoid the low unauthenticated rate limit.',\n setup: [\n 'Open GitHub → Settings → Developer settings → Personal access tokens.',\n 'Generate a token with the `repo` scope (read access is sufficient).',\n 'Store it as a secret and reference it from the connector config as `token: secret(\"GITHUB_TOKEN\")`.',\n ],\n },\n rateLimit:\n 'Unauthenticated requests share GitHub’s low 60 requests/hour limit; an authenticated token raises it to 5,000 requests/hour.',\n limitations: [\n 'The GitHub REST API can return the same item more than once within a sync (cursor pagination overlapping a mutating collection, retried requests, or an item surfaced via multiple endpoints). Each resource dedupes by stable id before writing, keeping the last copy seen.',\n 'Public repositories without a token are subject to GitHub’s low unauthenticated rate limit.',\n ],\n});\n\nexport interface GitHubSettings {\n owner: string;\n repo: string;\n}\n\ninterface GitHubRunsResponse {\n workflow_runs: Array<{\n id: number;\n name: string;\n conclusion: string | null;\n status: string;\n head_branch: string | null;\n actor: { login: string } | null;\n created_at: string;\n updated_at: string;\n run_attempt: number;\n }>;\n}\n\ninterface GitHubPR {\n number: number;\n title: string;\n state: string;\n draft: boolean;\n user: { login: string };\n created_at: string;\n updated_at: string;\n}\n\ninterface GitHubReview {\n user: { login: string } | null;\n state: string;\n submitted_at: string;\n}\n\ninterface GitHubIssue {\n number: number;\n title: string;\n state: string;\n labels: Array<{ name: string }>;\n assignees: Array<{ login: string }>;\n user: { login: string };\n created_at: string;\n updated_at: string;\n closed_at: string | null;\n pull_request?: unknown;\n}\n\ninterface GitHubDeployment {\n id: number;\n environment: string;\n ref: string;\n sha: string;\n creator: { login: string } | null;\n created_at: string;\n}\n\ninterface GitHubDeploymentStatus {\n state: string;\n updated_at: string;\n}\n\ninterface GitHubRelease {\n id: number;\n tag_name: string;\n name: string | null;\n draft: boolean;\n prerelease: boolean;\n created_at: string;\n published_at: string | null;\n author: { login: string };\n}\n\ninterface GitHubContributorStats {\n total: number;\n weeks: Array<{ w: number; a: number; d: number; c: number }>;\n author: { login: string };\n}\n\ninterface GitHubRepo {\n stargazers_count: number;\n forks_count: number;\n subscribers_count: number;\n}\n\nconst githubCredentials = {\n token: {\n description: 'GitHub personal access token',\n auth: 'optional' as const,\n },\n} satisfies CredentialsSchema;\n\ntype GitHubCredentials = typeof githubCredentials;\n\ntype GitHubSyncPhase =\n | 'repo_stats'\n | 'workflow_runs'\n | 'pull_requests'\n | 'issues'\n | 'deployments'\n | 'releases'\n | 'contributors';\n\nconst githubRateLimit = standardRateLimitPolicy({\n remainingHeader: 'x-ratelimit-remaining',\n resetHeader: 'x-ratelimit-reset',\n resetUnit: 's',\n});\n\nconst PHASE_ORDER: readonly GitHubSyncPhase[] = [\n 'repo_stats',\n 'workflow_runs',\n 'pull_requests',\n 'issues',\n 'deployments',\n 'releases',\n 'contributors',\n];\n\nconst PHASE_RESOURCES: Record<GitHubSyncPhase, readonly string[]> = {\n repo_stats: ['repo'],\n workflow_runs: ['workflow_run'],\n pull_requests: ['pull_request'],\n issues: ['issue'],\n deployments: ['deployment'],\n releases: ['release'],\n contributors: ['contributor'],\n};\n\nconst SINGLE_SPEC_PHASES: ReadonlySet<GitHubSyncPhase> = new Set([\n 'repo_stats',\n 'contributors',\n]);\n\nfunction pushableState(filter: FilterClause[] | undefined): string | null {\n if (!filter) {\n return null;\n }\n for (const clause of filter) {\n if ('field' in clause && clause.field === 'state' && clause.op === 'eq') {\n const { value } = clause;\n if (value === 'open' || value === 'closed') {\n return value;\n }\n }\n }\n return null;\n}\n\nfunction pushableEq(\n filter: FilterClause[] | undefined,\n field: string,\n): string | null {\n if (!filter) {\n return null;\n }\n for (const clause of filter) {\n if ('field' in clause && clause.field === field && clause.op === 'eq') {\n const { value } = clause;\n if (typeof value === 'string') {\n return value;\n }\n }\n }\n return null;\n}\n\nfunction pushableWorkflowRunStatus(\n filter: FilterClause[] | undefined,\n): string | null {\n return pushableEq(filter, 'status') ?? pushableEq(filter, 'conclusion');\n}\n\nfunction selectPhases(\n allowlist: ReadonlySet<string> | undefined,\n): readonly GitHubSyncPhase[] {\n if (allowlist === undefined) {\n return PHASE_ORDER;\n }\n return PHASE_ORDER.filter((phase) =>\n PHASE_RESOURCES[phase].some((r) => allowlist.has(r)),\n );\n}\n\ntype GitHubSyncCursor = ChunkedSyncCursor<GitHubSyncPhase, string>;\n\ninterface PRPageItems {\n prs: GitHubPR[];\n reviewsByPR: Map<number, GitHubReview[]>;\n}\n\ninterface DeploymentPageItems {\n deployments: GitHubDeployment[];\n latestStatusById: Map<number, GitHubDeploymentStatus | null>;\n}\n\nconst CONTRIBUTORS_SKIPPED = Symbol('contributors-skipped');\n\nconst WORKFLOW_RUN_RERUN_LOOKBACK_MS = 32 * 86_400_000;\n\nfunction dedupeByKey<T>(\n items: T[],\n keyFn: (item: T) => string,\n resource: string,\n): T[] {\n if (items.length < 2) {\n return items;\n }\n const seen = new Map<string, T>();\n let duplicates = 0;\n for (const item of items) {\n const key = keyFn(item);\n if (seen.has(key)) {\n duplicates++;\n }\n seen.set(key, item);\n }\n if (duplicates > 0) {\n console.warn(\n `[github-actions] ${resource}: dropped ${duplicates} duplicate id(s) — keeping latest copy of each`,\n );\n }\n return Array.from(seen.values());\n}\n\nconst isGitHubSyncCursor = makeChunkedCursorGuard(PHASE_ORDER);\n\nconst workflowRunsResponseSchema = z.object({\n total_count: z.number().int().optional(),\n workflow_runs: z.array(\n z.object({\n id: z.number().int(),\n name: z.string(),\n conclusion: z.string().nullable(),\n status: z.string(),\n head_branch: z.string().nullable(),\n actor: z.object({ login: z.string().min(1) }).nullable(),\n created_at: z.iso.datetime(),\n updated_at: z.iso.datetime(),\n run_attempt: z.number().int(),\n artifacts_url: z.string().optional(),\n cancel_url: z.string().optional(),\n check_suite_id: z.number().int().optional(),\n check_suite_node_id: z.string().optional(),\n check_suite_url: z.string().optional(),\n display_title: z.string().optional(),\n event: z.string().optional(),\n head_commit: z.unknown().optional(),\n head_repository: z.unknown().optional(),\n head_sha: z.string().optional(),\n html_url: z.string().optional(),\n jobs_url: z.string().optional(),\n logs_url: z.string().optional(),\n node_id: z.string().optional(),\n path: z.string().optional(),\n previous_attempt_url: z.string().nullable().optional(),\n pull_requests: z.array(z.unknown()).optional(),\n referenced_workflows: z.array(z.unknown()).optional(),\n repository: z.unknown().optional(),\n rerun_url: z.string().optional(),\n run_number: z.number().int().optional(),\n run_started_at: z.iso.datetime().optional(),\n triggering_actor: z.object({ login: z.string().min(1) }).optional(),\n url: z.string().optional(),\n workflow_id: z.number().int().optional(),\n workflow_url: z.string().optional(),\n }),\n ),\n});\n\nconst pullRequestsSchema = z.array(\n z.object({\n number: z.number().int(),\n title: z.string(),\n state: z.string(),\n draft: z.boolean(),\n user: z.object({\n login: z.string().min(1),\n avatar_url: z.string().optional(),\n events_url: z.string().optional(),\n followers_url: z.string().optional(),\n following_url: z.string().optional(),\n gists_url: z.string().optional(),\n gravatar_id: z.string().nullable().optional(),\n html_url: z.string().optional(),\n id: z.number().int().optional(),\n node_id: z.string().optional(),\n organizations_url: z.string().optional(),\n received_events_url: z.string().optional(),\n repos_url: z.string().optional(),\n site_admin: z.boolean().optional(),\n starred_url: z.string().optional(),\n subscriptions_url: z.string().optional(),\n type: z.string().optional(),\n url: z.string().optional(),\n user_view_type: z.string().optional(),\n }),\n created_at: z.iso.datetime(),\n updated_at: z.iso.datetime(),\n _links: z.unknown().optional(),\n active_lock_reason: z.string().nullable().optional(),\n assignee: z.unknown().optional(),\n assignees: z.unknown().optional(),\n author_association: z.string().optional(),\n auto_merge: z.unknown().optional(),\n base: z.unknown().optional(),\n body: z.string().nullable().optional(),\n closed_at: z.string().nullable().optional(),\n comments_url: z.string().optional(),\n commits_url: z.string().optional(),\n diff_url: z.string().optional(),\n head: z.unknown().optional(),\n html_url: z.string().optional(),\n id: z.number().int().optional(),\n issue_url: z.string().optional(),\n labels: z.unknown().optional(),\n locked: z.boolean().optional(),\n merge_commit_sha: z.string().nullable().optional(),\n merged_at: z.string().nullable().optional(),\n milestone: z.unknown().optional(),\n node_id: z.string().optional(),\n patch_url: z.string().optional(),\n requested_reviewers: z.unknown().optional(),\n requested_teams: z.unknown().optional(),\n review_comment_url: z.string().optional(),\n review_comments_url: z.string().optional(),\n statuses_url: z.string().optional(),\n url: z.string().optional(),\n }),\n);\n\nconst reviewsSchema = z.array(\n z.object({\n user: z.object({ login: z.string().min(1) }).nullable(),\n state: z.string(),\n submitted_at: z.iso.datetime(),\n }),\n);\n\nconst issuesSchema = z.array(\n z.object({\n number: z.number().int(),\n title: z.string(),\n state: z.string(),\n labels: z.array(\n z.object({\n name: z.string(),\n id: z.number().int().optional(),\n node_id: z.string().optional(),\n url: z.string().optional(),\n color: z.string().optional(),\n default: z.boolean().optional(),\n description: z.string().nullable().optional(),\n }),\n ),\n assignees: z.array(z.object({ login: z.string().min(1) })),\n user: z.object({ login: z.string().min(1) }).catchall(z.unknown()),\n created_at: z.iso.datetime(),\n updated_at: z.iso.datetime(),\n closed_at: z.iso.datetime().nullable().optional(),\n pull_request: z.unknown().optional(),\n active_lock_reason: z.unknown().optional(),\n assignee: z.unknown().optional(),\n author_association: z.string().optional(),\n body: z.string().nullable().optional(),\n closed_by: z.unknown().optional(),\n comments: z.number().int().optional(),\n comments_url: z.string().optional(),\n draft: z.boolean().optional(),\n events_url: z.string().optional(),\n html_url: z.string().optional(),\n id: z.number().int().optional(),\n issue_field_values: z.unknown().optional(),\n labels_url: z.string().optional(),\n locked: z.boolean().optional(),\n milestone: z.unknown().optional(),\n node_id: z.string().optional(),\n performed_via_github_app: z.unknown().optional(),\n reactions: z.unknown().optional(),\n repository_url: z.string().optional(),\n state_reason: z.unknown().optional(),\n timeline_url: z.string().optional(),\n type: z.unknown().optional(),\n url: z.string().optional(),\n }),\n);\n\nconst deploymentsSchema = z.array(\n z.object({\n id: z.number().int(),\n environment: z.string(),\n ref: z.string(),\n sha: z.string(),\n creator: z.object({ login: z.string().min(1) }).nullable(),\n created_at: z.iso.datetime(),\n }),\n);\n\nconst deploymentStatusesSchema = z.array(\n z.object({\n state: z.string(),\n updated_at: z.iso.datetime(),\n }),\n);\n\nconst releasesSchema = z.array(\n z.object({\n id: z.number().int(),\n tag_name: z.string(),\n name: z.string().nullable(),\n draft: z.boolean(),\n prerelease: z.boolean(),\n created_at: z.iso.datetime(),\n published_at: z.iso.datetime().nullable(),\n author: z.object({\n login: z.string().min(1),\n id: z.number().int().optional(),\n node_id: z.string().optional(),\n avatar_url: z.string().optional(),\n gravatar_id: z.string().nullable().optional(),\n url: z.string().optional(),\n html_url: z.string().optional(),\n followers_url: z.string().optional(),\n following_url: z.string().optional(),\n gists_url: z.string().optional(),\n starred_url: z.string().optional(),\n subscriptions_url: z.string().optional(),\n organizations_url: z.string().optional(),\n repos_url: z.string().optional(),\n events_url: z.string().optional(),\n received_events_url: z.string().optional(),\n type: z.string().optional(),\n site_admin: z.boolean().optional(),\n user_view_type: z.string().optional(),\n }),\n node_id: z.string().optional(),\n url: z.string().optional(),\n html_url: z.string().optional(),\n assets_url: z.string().optional(),\n upload_url: z.string().optional(),\n tarball_url: z.string().nullable().optional(),\n zipball_url: z.string().nullable().optional(),\n target_commitish: z.string().optional(),\n body: z.string().nullable().optional(),\n immutable: z.boolean().optional(),\n mentions_count: z.number().int().optional(),\n updated_at: z.iso.datetime().optional(),\n assets: z.array(z.unknown()).optional(),\n }),\n);\n\nconst contributorsSchema = z.array(\n z.object({\n total: z.number().int(),\n weeks: z.array(\n z.object({\n w: z.number().int(),\n a: z.number().int(),\n d: z.number().int(),\n c: z.number().int(),\n }),\n ),\n author: z.object({ login: z.string().min(1) }),\n }),\n);\n\nconst repoStatsSchema = z.object({\n stargazers_count: z.number().int(),\n forks_count: z.number().int(),\n subscribers_count: z.number().int(),\n});\n\nexport const githubResources = defineResources({\n repo: {\n shape: 'entity',\n filterable: [],\n description:\n 'Top-level repository stats (stars, forks, and watchers) as a single entity.',\n endpoint: 'GET /repos/{owner}/{repo}',\n responses: { repo: repoStatsSchema },\n },\n workflow_run: {\n shape: 'event',\n filterable: [\n {\n field: 'status',\n ops: ['eq'],\n values: [\n 'queued',\n 'in_progress',\n 'completed',\n 'requested',\n 'waiting',\n 'pending',\n ],\n },\n {\n field: 'conclusion',\n ops: ['eq'],\n values: [\n 'success',\n 'failure',\n 'cancelled',\n 'neutral',\n 'skipped',\n 'stale',\n 'timed_out',\n 'action_required',\n ],\n },\n { field: 'branch', ops: ['eq'] },\n ],\n description: 'GitHub Actions CI pipeline executions.',\n endpoint: 'GET /repos/{owner}/{repo}/actions/runs',\n responses: { workflow_runs: workflowRunsResponseSchema },\n },\n pull_request: {\n shape: 'entity',\n description:\n 'Open and closed pull requests, including draft state, author, and review state.',\n endpoint: 'GET /repos/{owner}/{repo}/pulls',\n notes:\n 'Review state is folded in from GET /repos/{owner}/{repo}/pulls/{number}/reviews per PR.',\n filterable: [{ field: 'state', ops: ['eq'], values: ['open', 'closed'] }],\n responses: {\n pull_requests: pullRequestsSchema,\n pull_request_reviews: reviewsSchema,\n },\n },\n issue: {\n shape: 'entity',\n description:\n 'Open and closed issues with labels, assignees, and author (pull requests excluded).',\n endpoint: 'GET /repos/{owner}/{repo}/issues',\n filterable: [{ field: 'state', ops: ['eq'], values: ['open', 'closed'] }],\n responses: { issues: issuesSchema },\n },\n deployment: {\n shape: 'entity',\n filterable: [{ field: 'environment', ops: ['eq'] }],\n description:\n 'Deployments with their latest status, keyed by environment and ref.',\n endpoint: 'GET /repos/{owner}/{repo}/deployments',\n notes:\n 'The latest status is folded in from GET /repos/{owner}/{repo}/deployments/{id}/statuses.',\n responses: {\n deployments: deploymentsSchema,\n deployment_statuses: deploymentStatusesSchema,\n },\n },\n release: {\n shape: 'entity',\n filterable: [],\n description: 'Published, draft, and prerelease GitHub releases.',\n endpoint: 'GET /repos/{owner}/{repo}/releases',\n responses: { releases: releasesSchema },\n },\n contributor: {\n shape: 'entity',\n filterable: [],\n description:\n 'Per-author commit activity (commits, additions, deletions) for the repository.',\n endpoint: 'GET /repos/{owner}/{repo}/stats/contributors',\n responses: { contributors: contributorsSchema },\n },\n});\n\nexport const id = 'github-actions';\n\nexport class GitHubConnector extends BaseConnector<\n GitHubSettings,\n GitHubCredentials\n> {\n static readonly id = id;\n\n static readonly resources = githubResources;\n\n static readonly schemas = schemasFromResources(githubResources);\n\n static create(input: unknown, ctx?: ConnectorContext): GitHubConnector {\n const parsed = configFields.parse(input);\n return new GitHubConnector(\n { owner: parsed.owner, repo: parsed.repo },\n { token: parsed.token },\n ctx,\n );\n }\n\n readonly id = id;\n\n override readonly credentials = githubCredentials;\n\n private seenWorkflowRunIds = new Set<string>();\n\n private preservedDeploymentStatus = new Map<string, string>();\n\n private buildHeaders(): Record<string, string> {\n const headers: Record<string, string> = {\n Accept: 'application/vnd.github+json',\n 'X-GitHub-Api-Version': '2022-11-28',\n 'User-Agent': connectorUserAgent('github'),\n };\n if (this.creds.token) {\n headers['Authorization'] = `Bearer ${this.creds.token}`;\n }\n return headers;\n }\n\n private fetch<T>(\n url: string,\n resource: string,\n signal: AbortSignal | undefined,\n ): Promise<HttpResponse<T>> {\n return this.get<T>(url, {\n resource,\n headers: this.buildHeaders(),\n signal,\n rateLimit: githubRateLimit,\n });\n }\n\n private allowedPageBasePath(phase: GitHubSyncPhase): string | null {\n const { owner, repo } = this.settings;\n switch (phase) {\n case 'workflow_runs':\n return `/repos/${owner}/${repo}/actions/runs`;\n case 'pull_requests':\n return `/repos/${owner}/${repo}/pulls`;\n case 'issues':\n return `/repos/${owner}/${repo}/issues`;\n case 'deployments':\n return `/repos/${owner}/${repo}/deployments`;\n case 'releases':\n return `/repos/${owner}/${repo}/releases`;\n case 'repo_stats':\n case 'contributors':\n return null;\n }\n }\n\n private sanitizePageUrl(\n phase: GitHubSyncPhase,\n pageUrl: string | null,\n ): string | null {\n const allowedPath = this.allowedPageBasePath(phase);\n if (allowedPath === null) {\n return null;\n }\n const canonical = sanitizeAllowedUrl({\n url: pageUrl,\n host: 'api.github.com',\n pathname: allowedPath,\n });\n if (canonical !== null || pageUrl === null) {\n return canonical;\n }\n try {\n const u = new URL(pageUrl);\n const resourceSuffix = allowedPath.replace(/^\\/repos\\/[^/]+\\/[^/]+/, '');\n const escapedSuffix = resourceSuffix.replace(\n /[.*+?^${}()|[\\]\\\\]/g,\n '\\\\$&',\n );\n const numericPath = new RegExp(`^/repositories/\\\\d+${escapedSuffix}$`);\n if (\n u.protocol === 'https:' &&\n u.host === 'api.github.com' &&\n numericPath.test(u.pathname)\n ) {\n return u.toString();\n }\n } catch {\n return null;\n }\n return null;\n }\n\n private isResourceAllowed(options: SyncOptions, resource: string): boolean {\n if (!options.resources) {\n return true;\n }\n return options.resources.has(resource);\n }\n\n private resolveCursor(cursor: unknown): GitHubSyncCursor | undefined {\n if (!isGitHubSyncCursor(cursor)) {\n return undefined;\n }\n return {\n phase: cursor.phase,\n page: this.sanitizePageUrl(cursor.phase, cursor.page),\n spec: cursor.spec,\n };\n }\n\n private specsForResource(\n options: SyncOptions,\n resource: string,\n ): FetchSpec[] {\n const specs = options.fetchSpecs?.[resource];\n return specs && specs.length > 0 ? specs : [{}];\n }\n\n private specCutoff(\n options: SyncOptions,\n resource: string,\n spec: FetchSpec,\n now: number,\n ): number | null {\n if (options.fetchSpecs?.[resource]) {\n const specCutoffMs = resolveSpecCutoff(spec.requiredWindowMs, now);\n if (specCutoffMs === null) {\n return null;\n }\n const sinceCutoffMs = options.since\n ? new Date(options.since).getTime()\n : null;\n return sinceCutoffMs !== null\n ? Math.min(specCutoffMs, sinceCutoffMs)\n : specCutoffMs;\n }\n return resolveBackfillCutoff(options, resource, now);\n }\n\n private async fetchRepoStats(\n signal: AbortSignal | undefined,\n ): Promise<FetchPageResult<string>> {\n const { owner, repo } = this.settings;\n const res = await this.fetch<GitHubRepo>(\n `https://api.github.com/repos/${owner}/${repo}`,\n 'repo',\n signal,\n );\n return { items: [res.body], next: null };\n }\n\n private async fetchWorkflowRunsLatest(\n signal: AbortSignal | undefined,\n ): Promise<FetchPageResult<string>> {\n const { owner, repo } = this.settings;\n const res = await this.fetch<GitHubRunsResponse>(\n `https://api.github.com/repos/${owner}/${repo}/actions/runs?per_page=1`,\n 'workflow_runs',\n signal,\n );\n const run = res.body.workflow_runs[0];\n return { items: run ? [run] : [], next: null };\n }\n\n private async fetchWorkflowRunsFull(\n page: string | null,\n signal: AbortSignal | undefined,\n spec: FetchSpec,\n cutoff: number | null,\n ): Promise<FetchPageResult<string>> {\n const { owner, repo } = this.settings;\n let url: string;\n if (page) {\n url = page;\n } else {\n const u = new URL(\n `https://api.github.com/repos/${owner}/${repo}/actions/runs`,\n );\n u.searchParams.set('per_page', '100');\n const status = pushableWorkflowRunStatus(spec.filter);\n if (status !== null) {\n u.searchParams.set('status', status);\n }\n const branch = pushableEq(spec.filter, 'branch');\n if (branch !== null) {\n u.searchParams.set('branch', branch);\n }\n url = u.toString();\n }\n const res = await this.fetch<GitHubRunsResponse>(\n url,\n 'workflow_runs',\n signal,\n );\n const nextLink = parseLinkHeader(res.headers.get('link'))['next'] ?? null;\n const runs = res.body.workflow_runs;\n\n const filtered = runs.filter((run) => {\n if (cutoff === null) {\n return true;\n }\n const createdMs = new Date(run.created_at).getTime();\n const updatedMs = new Date(run.updated_at).getTime();\n return !(createdMs < cutoff && updatedMs < cutoff);\n });\n\n const lastRun = runs.at(-1);\n const cutoffReached =\n cutoff !== null &&\n lastRun !== undefined &&\n new Date(lastRun.created_at).getTime() <\n cutoff - WORKFLOW_RUN_RERUN_LOOKBACK_MS;\n\n return {\n items: filtered,\n next: cutoffReached ? null : nextLink,\n };\n }\n\n private async fetchPullRequests(\n options: SyncOptions,\n page: string | null,\n signal: AbortSignal | undefined,\n spec: FetchSpec,\n cutoff: number | null,\n ): Promise<FetchPageResult<string>> {\n const { owner, repo } = this.settings;\n const state = pushableState(spec.filter) ?? 'all';\n const url =\n page ??\n `https://api.github.com/repos/${owner}/${repo}/pulls?state=${state}&sort=updated&direction=desc&per_page=100`;\n const res = await this.fetch<GitHubPR[]>(url, 'pull_requests', signal);\n const nextLink = parseLinkHeader(res.headers.get('link'))['next'] ?? null;\n const prs = res.body;\n const filteredPrs =\n cutoff !== null\n ? prs.filter((pr) => new Date(pr.updated_at).getTime() >= cutoff)\n : prs;\n const lastPr = prs.at(-1);\n const cutoffReached =\n cutoff !== null &&\n lastPr !== undefined &&\n new Date(lastPr.updated_at).getTime() < cutoff;\n\n const reviewsByPR = new Map<number, GitHubReview[]>();\n if (this.isResourceAllowed(options, 'pull_request_reviews')) {\n for (const pr of filteredPrs) {\n signal?.throwIfAborted();\n const reviews = await this.fetch<GitHubReview[]>(\n `https://api.github.com/repos/${owner}/${repo}/pulls/${pr.number}/reviews`,\n 'pull_request_reviews',\n signal,\n );\n reviewsByPR.set(pr.number, reviews.body);\n }\n }\n\n const items: PRPageItems[] = [{ prs: filteredPrs, reviewsByPR }];\n return { items, next: cutoffReached ? null : nextLink };\n }\n\n private async fetchIssues(\n page: string | null,\n signal: AbortSignal | undefined,\n spec: FetchSpec,\n cutoff: number | null,\n ): Promise<FetchPageResult<string>> {\n const { owner, repo } = this.settings;\n let url: string;\n if (page) {\n url = page;\n } else {\n const u = new URL(`https://api.github.com/repos/${owner}/${repo}/issues`);\n u.searchParams.set('state', pushableState(spec.filter) ?? 'all');\n u.searchParams.set('sort', 'updated');\n u.searchParams.set('direction', 'asc');\n u.searchParams.set('per_page', '100');\n if (cutoff !== null) {\n u.searchParams.set('since', new Date(cutoff).toISOString());\n }\n url = u.toString();\n }\n const res = await this.fetch<GitHubIssue[]>(url, 'issues', signal);\n const nextLink = parseLinkHeader(res.headers.get('link'))['next'] ?? null;\n return { items: res.body, next: nextLink };\n }\n\n private async fetchDeployments(\n options: SyncOptions,\n page: string | null,\n signal: AbortSignal | undefined,\n spec: FetchSpec,\n cutoff: number | null,\n ): Promise<FetchPageResult<string>> {\n const { owner, repo } = this.settings;\n let url: string;\n if (page) {\n url = page;\n } else {\n const u = new URL(\n `https://api.github.com/repos/${owner}/${repo}/deployments`,\n );\n u.searchParams.set('per_page', '100');\n const environment = pushableEq(spec.filter, 'environment');\n if (environment !== null) {\n u.searchParams.set('environment', environment);\n }\n url = u.toString();\n }\n const res = await this.fetch<GitHubDeployment[]>(\n url,\n 'deployments',\n signal,\n );\n const nextLink = parseLinkHeader(res.headers.get('link'))['next'] ?? null;\n const deployments = res.body;\n const filteredDeployments =\n cutoff !== null\n ? deployments.filter((d) => new Date(d.created_at).getTime() >= cutoff)\n : deployments;\n\n const latestStatusById = new Map<number, GitHubDeploymentStatus | null>();\n if (this.isResourceAllowed(options, 'deployment_statuses')) {\n for (const deployment of filteredDeployments) {\n signal?.throwIfAborted();\n const statusRes = await this.fetch<GitHubDeploymentStatus[]>(\n `https://api.github.com/repos/${owner}/${repo}/deployments/${deployment.id}/statuses?per_page=1`,\n 'deployment_statuses',\n signal,\n );\n latestStatusById.set(deployment.id, statusRes.body[0] ?? null);\n }\n }\n\n const items: DeploymentPageItems[] = [\n { deployments: filteredDeployments, latestStatusById },\n ];\n return { items, next: nextLink };\n }\n\n private async fetchReleases(\n page: string | null,\n signal: AbortSignal | undefined,\n cutoff: number | null,\n ): Promise<FetchPageResult<string>> {\n const { owner, repo } = this.settings;\n const url =\n page ??\n `https://api.github.com/repos/${owner}/${repo}/releases?per_page=100`;\n const res = await this.fetch<GitHubRelease[]>(url, 'releases', signal);\n const nextLink = parseLinkHeader(res.headers.get('link'))['next'] ?? null;\n const releases = res.body;\n const filtered =\n cutoff !== null\n ? releases.filter((r) => new Date(r.created_at).getTime() >= cutoff)\n : releases;\n return { items: filtered, next: nextLink };\n }\n\n private async fetchContributors(\n signal: AbortSignal | undefined,\n ): Promise<FetchPageResult<string>> {\n const { owner, repo } = this.settings;\n const contributors = await this.withRetry<GitHubContributorStats[]>(\n async (sig) => {\n const res = await this.fetch<GitHubContributorStats[] | null>(\n `https://api.github.com/repos/${owner}/${repo}/stats/contributors`,\n 'contributors',\n sig,\n );\n if (res.status === 202) {\n return { status: 'retry' };\n }\n return {\n status: 'done',\n value: (res.body ?? []) as GitHubContributorStats[],\n };\n },\n { maxAttempts: 15, initialDelayMs: 1000, maxDelayMs: 10000, signal },\n );\n\n if (!contributors) {\n console.warn(\n '[github-actions] Stats endpoint never became ready — skipping contributor sync and keeping previous data.',\n );\n return { items: [CONTRIBUTORS_SKIPPED], next: null };\n }\n return { items: contributors, next: null };\n }\n\n private async writeRepoStats(\n storage: StorageHandle,\n items: unknown[],\n ): Promise<void> {\n const repoBody = items[0] as GitHubRepo | undefined;\n if (!repoBody) {\n return;\n }\n const { owner, repo } = this.settings;\n await storage.entities(\n [\n {\n type: 'repo',\n id: `${owner}/${repo}`,\n attributes: {\n stars: repoBody.stargazers_count,\n forks: repoBody.forks_count,\n watchers: repoBody.subscribers_count,\n },\n updated_at: Date.now(),\n },\n ],\n { types: ['repo'] },\n );\n }\n\n private async writeWorkflowRunsLatest(\n storage: StorageHandle,\n items: unknown[],\n ): Promise<void> {\n const run = items[0] as\n | GitHubRunsResponse['workflow_runs'][number]\n | undefined;\n if (!run) {\n return;\n }\n await storage.event({\n name: 'workflow_run',\n start_ts: new Date(run.created_at).getTime(),\n end_ts: new Date(run.updated_at).getTime(),\n attributes: {\n id: run.id,\n workflow_name: run.name,\n conclusion: run.conclusion ?? 'unknown',\n status: run.status,\n branch: run.head_branch ?? '',\n actor: run.actor?.login ?? '',\n run_attempt: run.run_attempt,\n },\n });\n }\n\n private async writeWorkflowRunsFull(\n storage: StorageHandle,\n items: unknown[],\n page: string | null,\n spec: number,\n ): Promise<void> {\n if (page === null && spec === 0) {\n await storage.events([], { names: ['workflow_run'] });\n this.seenWorkflowRunIds.clear();\n }\n const withinPage = dedupeByKey(\n items as GitHubRunsResponse['workflow_runs'],\n (run) => String(run.id),\n 'workflow_runs',\n );\n let crossPageDuplicates = 0;\n const runs: GitHubRunsResponse['workflow_runs'] = [];\n for (const run of withinPage) {\n const key = String(run.id);\n if (this.seenWorkflowRunIds.has(key)) {\n crossPageDuplicates++;\n continue;\n }\n this.seenWorkflowRunIds.add(key);\n runs.push(run);\n }\n if (crossPageDuplicates > 0) {\n console.warn(\n `[github-actions] workflow_runs: dropped ${crossPageDuplicates} duplicate id(s) seen on an earlier page`,\n );\n }\n for (const run of runs) {\n await storage.event({\n name: 'workflow_run',\n start_ts: new Date(run.created_at).getTime(),\n end_ts: new Date(run.updated_at).getTime(),\n attributes: {\n id: run.id,\n workflow_name: run.name,\n conclusion: run.conclusion ?? 'unknown',\n status: run.status,\n branch: run.head_branch ?? '',\n actor: run.actor?.login ?? '',\n run_attempt: run.run_attempt,\n },\n });\n }\n }\n\n private async writePullRequests(\n storage: StorageHandle,\n items: unknown[],\n page: string | null,\n spec: number,\n options: SyncOptions,\n ): Promise<void> {\n const reviewsAllowed = this.isResourceAllowed(\n options,\n 'pull_request_reviews',\n );\n if (page === null && spec === 0) {\n await storage.entities([], { types: ['pull_request'] });\n if (reviewsAllowed) {\n await storage.edges([], { kinds: ['reviewed_by'] });\n }\n }\n const pageItems = items as PRPageItems[];\n for (const { prs: rawPrs, reviewsByPR } of pageItems) {\n const prs = dedupeByKey(\n rawPrs,\n (pr) => String(pr.number),\n 'pull_requests',\n );\n for (const pr of prs) {\n await storage.entity({\n type: 'pull_request',\n id: String(pr.number),\n attributes: {\n title: pr.title,\n state: pr.state,\n draft: pr.draft,\n author: pr.user.login,\n created_at: new Date(pr.created_at).getTime(),\n },\n updated_at: new Date(pr.updated_at).getTime(),\n });\n }\n if (!reviewsAllowed) {\n continue;\n }\n for (const pr of prs) {\n const reviews = reviewsByPR.get(pr.number) ?? [];\n for (const review of reviews) {\n if (!review.user) {\n continue;\n }\n await storage.edge({\n from_type: 'pull_request',\n from_id: String(pr.number),\n kind: 'reviewed_by',\n to_type: 'user',\n to_id: review.user.login,\n attributes: { state: review.state },\n updated_at: new Date(review.submitted_at).getTime(),\n });\n }\n }\n }\n }\n\n private async writeIssues(\n storage: StorageHandle,\n items: unknown[],\n page: string | null,\n spec: number,\n ): Promise<void> {\n if (page === null && spec === 0) {\n await storage.entities([], { types: ['issue'] });\n }\n const issues = dedupeByKey(\n (items as GitHubIssue[]).filter((i) => i.pull_request === undefined),\n (issue) => String(issue.number),\n 'issues',\n );\n for (const issue of issues) {\n await storage.entity({\n type: 'issue',\n id: String(issue.number),\n attributes: {\n number: issue.number,\n title: issue.title,\n state: issue.state,\n labels: issue.labels.map((l) => l.name),\n assignees: issue.assignees.map((a) => a.login),\n author: issue.user.login,\n created_at: new Date(issue.created_at).getTime(),\n updated_at: new Date(issue.updated_at).getTime(),\n closed_at: issue.closed_at\n ? new Date(issue.closed_at).getTime()\n : null,\n },\n updated_at: new Date(issue.updated_at).getTime(),\n });\n }\n }\n\n private async writeDeployments(\n storage: StorageHandle,\n items: unknown[],\n page: string | null,\n spec: number,\n options: SyncOptions,\n ): Promise<void> {\n const statusesAllowed = this.isResourceAllowed(\n options,\n 'deployment_statuses',\n );\n if (page === null && spec === 0) {\n if (!statusesAllowed) {\n const existing = await storage.queryEntities({ type: 'deployment' });\n for (const entity of existing) {\n const prev = entity.attributes['latest_status'];\n if (typeof prev === 'string') {\n this.preservedDeploymentStatus.set(entity.id, prev);\n }\n }\n }\n await storage.entities([], { types: ['deployment'] });\n }\n const pageItems = items as DeploymentPageItems[];\n for (const { deployments: rawDeployments, latestStatusById } of pageItems) {\n const deployments = dedupeByKey(\n rawDeployments,\n (d) => String(d.id),\n 'deployments',\n );\n for (const deployment of deployments) {\n const createdMs = new Date(deployment.created_at).getTime();\n let latestStatus: string;\n let statusUpdatedMs: number | null = null;\n if (statusesAllowed) {\n const status = latestStatusById.get(deployment.id) ?? null;\n latestStatus = status?.state ?? 'unknown';\n statusUpdatedMs = status?.updated_at\n ? new Date(status.updated_at).getTime()\n : null;\n } else {\n latestStatus =\n this.preservedDeploymentStatus.get(String(deployment.id)) ??\n 'unknown';\n }\n await storage.entity({\n type: 'deployment',\n id: String(deployment.id),\n attributes: {\n environment: deployment.environment,\n ref: deployment.ref,\n sha: deployment.sha,\n creator: deployment.creator?.login ?? '',\n created_at: createdMs,\n latest_status: latestStatus,\n },\n updated_at: Math.max(createdMs, statusUpdatedMs ?? 0),\n });\n }\n }\n }\n\n private async writeReleases(\n storage: StorageHandle,\n items: unknown[],\n page: string | null,\n spec: number,\n ): Promise<void> {\n if (page === null && spec === 0) {\n await storage.entities([], { types: ['release'] });\n }\n const releases = dedupeByKey(\n items as GitHubRelease[],\n (r) => String(r.id),\n 'releases',\n );\n for (const release of releases) {\n await storage.entity({\n type: 'release',\n id: String(release.id),\n attributes: {\n tag_name: release.tag_name,\n name: release.name ?? '',\n draft: release.draft,\n prerelease: release.prerelease,\n created_at: new Date(release.created_at).getTime(),\n published_at: release.published_at\n ? new Date(release.published_at).getTime()\n : null,\n author: release.author.login,\n },\n updated_at: new Date(\n release.published_at ?? release.created_at,\n ).getTime(),\n });\n }\n }\n\n private async writeContributors(\n storage: StorageHandle,\n items: unknown[],\n ): Promise<void> {\n if (items[0] === CONTRIBUTORS_SKIPPED) {\n return;\n }\n const contributors = dedupeByKey(\n items as GitHubContributorStats[],\n (c) => c.author.login,\n 'contributors',\n );\n await storage.entities(\n contributors.map((c) => {\n const additions = c.weeks.reduce((sum, w) => sum + w.a, 0);\n const deletions = c.weeks.reduce((sum, w) => sum + w.d, 0);\n const latestWeek = [...c.weeks].reverse().find((w) => w.c > 0);\n return {\n type: 'contributor',\n id: c.author.login,\n attributes: {\n commits: c.total,\n additions,\n deletions,\n latest_commit_at: latestWeek ? latestWeek.w * 1000 : null,\n },\n updated_at: latestWeek ? latestWeek.w * 1000 : 0,\n };\n }),\n { types: ['contributor'] },\n );\n }\n\n async sync(\n options: SyncOptions,\n storage: StorageHandle,\n signal?: AbortSignal,\n ): Promise<SyncResult> {\n const cursor = this.resolveCursor(options.cursor);\n const phases = selectPhases(options.resources);\n const specCount = (phase: GitHubSyncPhase): number => {\n if (options.mode === 'latest' || SINGLE_SPEC_PHASES.has(phase)) {\n return 1;\n }\n return this.specsForResource(options, PHASE_RESOURCES[phase][0]!).length;\n };\n const specFor = (phase: GitHubSyncPhase, specIndex: number): FetchSpec =>\n this.specsForResource(options, PHASE_RESOURCES[phase][0]!)[specIndex] ??\n {};\n const cutoffFor = (\n phase: GitHubSyncPhase,\n spec: FetchSpec,\n ): number | null =>\n this.specCutoff(options, PHASE_RESOURCES[phase][0]!, spec, Date.now());\n return paginateChunked<GitHubSyncPhase, string>({\n phases,\n cursor,\n signal,\n specCount,\n logger: this.logger,\n fetchPage: async (phase, page, sig, specIndex) => {\n const spec = specFor(phase, specIndex);\n switch (phase) {\n case 'repo_stats':\n return this.fetchRepoStats(sig);\n case 'workflow_runs':\n return options.mode === 'latest'\n ? this.fetchWorkflowRunsLatest(sig)\n : this.fetchWorkflowRunsFull(\n page,\n sig,\n spec,\n cutoffFor(phase, spec),\n );\n case 'pull_requests':\n return this.fetchPullRequests(\n options,\n page,\n sig,\n spec,\n cutoffFor(phase, spec),\n );\n case 'issues':\n return this.fetchIssues(page, sig, spec, cutoffFor(phase, spec));\n case 'deployments':\n return this.fetchDeployments(\n options,\n page,\n sig,\n spec,\n cutoffFor(phase, spec),\n );\n case 'releases':\n return this.fetchReleases(page, sig, cutoffFor(phase, spec));\n case 'contributors':\n return this.fetchContributors(sig);\n }\n },\n writeBatch: async (phase, items, page, specIndex) => {\n switch (phase) {\n case 'repo_stats':\n return this.writeRepoStats(storage, items);\n case 'workflow_runs':\n return options.mode === 'latest'\n ? this.writeWorkflowRunsLatest(storage, items)\n : this.writeWorkflowRunsFull(storage, items, page, specIndex);\n case 'pull_requests':\n return this.writePullRequests(\n storage,\n items,\n page,\n specIndex,\n options,\n );\n case 'issues':\n return this.writeIssues(storage, items, page, specIndex);\n case 'deployments':\n return this.writeDeployments(\n storage,\n items,\n page,\n specIndex,\n options,\n );\n case 'releases':\n return this.writeReleases(storage, items, page, specIndex);\n case 'contributors':\n return this.writeContributors(storage, items);\n }\n },\n });\n }\n}\n","import { GitHubConnector } from './github';\n\nexport {\n configFields,\n doc,\n GitHubConnector,\n githubResources as resources,\n id,\n} from './github';\nexport type { GitHubSettings } from './github';\nexport default GitHubConnector;\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../connector-shared/src/errors.ts","../../../connector-shared/src/retry.ts","../../../connector-shared/src/version.ts","../../../connector-shared/src/request.ts","../../../connector-shared/src/rate-limit.ts","../../../connector-shared/src/map-concurrent.ts","../../../connector-shared/src/sanitize.ts","../../../connector-shared/src/epoch.ts","../../../connector-shared/src/pagination.ts","../../../connector-shared/src/logger.ts","../src/github.ts","../src/index.ts"],"sourcesContent":["import type { HttpResponse } from './types';\n\nexport type HttpErrorKind =\n | 'transient'\n | 'rate_limit'\n | 'auth'\n | 'upstream_bug'\n | 'client_bug';\n\nexport abstract class HttpClientError extends Error {\n abstract readonly kind: HttpErrorKind;\n readonly response?: HttpResponse;\n\n constructor(message: string, response?: HttpResponse) {\n super(message);\n this.name = new.target.name;\n this.response = response;\n }\n}\n\nexport class TransientError extends HttpClientError {\n readonly kind = 'transient' as const;\n}\n\nexport class RateLimitError extends HttpClientError {\n readonly kind = 'rate_limit' as const;\n readonly retryAfter?: Date;\n\n constructor(message: string, response?: HttpResponse, retryAfter?: Date) {\n super(message, response);\n this.retryAfter = retryAfter;\n }\n}\n\nexport class AuthError extends HttpClientError {\n readonly kind = 'auth' as const;\n}\n\nexport class UpstreamBugError extends HttpClientError {\n readonly kind = 'upstream_bug' as const;\n}\n\nexport class ClientBugError extends HttpClientError {\n readonly kind = 'client_bug' as const;\n}\n\nexport function classifyStatus(status: number): HttpErrorKind {\n if (status === 429) {\n return 'rate_limit';\n }\n if (status === 401 || status === 403) {\n return 'auth';\n }\n if (status === 408) {\n return 'transient';\n }\n if (status >= 500) {\n return 'upstream_bug';\n }\n if (status >= 400) {\n return 'client_bug';\n }\n return 'client_bug';\n}\n\nexport function errorForStatus(\n message: string,\n response: HttpResponse,\n retryAfter?: Date,\n): HttpClientError {\n const kind = classifyStatus(response.status);\n switch (kind) {\n case 'rate_limit':\n return new RateLimitError(message, response, retryAfter);\n case 'auth':\n return new AuthError(message, response);\n case 'transient':\n return new TransientError(message, response);\n case 'upstream_bug':\n return new UpstreamBugError(message, response);\n case 'client_bug':\n return new ClientBugError(message, response);\n }\n}\n","import { HttpClientError, RateLimitError, TransientError } from './errors';\n\nexport interface RetryPolicy {\n maxAttempts?: number;\n initialDelayMs?: number;\n maxDelayMs?: number;\n retryOn?: (status: number | null, err?: Error) => boolean;\n}\n\nexport const defaultRetryOn = (status: number | null, err?: Error): boolean => {\n if (err instanceof RateLimitError) {\n return true;\n }\n if (err instanceof TransientError) {\n return true;\n }\n if (status === null) {\n return err instanceof Error && !(err instanceof HttpClientError);\n }\n if (status === 408 || status === 429) {\n return true;\n }\n if (status >= 500) {\n return true;\n }\n return false;\n};\n\nexport function backoffDelayMs(\n attempt: number,\n policy: Required<Pick<RetryPolicy, 'initialDelayMs' | 'maxDelayMs'>>,\n): number {\n const base = policy.initialDelayMs * 2 ** attempt;\n const jitter = base * 0.25 * Math.random();\n return Math.min(base + jitter, policy.maxDelayMs);\n}\n\nexport function parseRetryAfter(\n headerValue: string | null,\n now: Date = new Date(),\n): Date | undefined {\n if (!headerValue) {\n return undefined;\n }\n const trimmed = headerValue.trim();\n if (/^\\d+$/.test(trimmed)) {\n return new Date(now.getTime() + Number(trimmed) * 1000);\n }\n const parsed = Date.parse(trimmed);\n if (Number.isNaN(parsed)) {\n return undefined;\n }\n return new Date(parsed);\n}\n\nexport function sleep(ms: number, signal?: AbortSignal): Promise<void> {\n if (signal?.aborted) {\n return Promise.reject(signal.reason ?? new Error('Aborted'));\n }\n return new Promise<void>((resolve, reject) => {\n const onAbort = () => {\n clearTimeout(timer);\n reject(signal!.reason ?? new Error('Aborted'));\n };\n const timer = setTimeout(() => {\n signal?.removeEventListener('abort', onAbort);\n resolve();\n }, ms);\n signal?.addEventListener('abort', onAbort, { once: true });\n });\n}\n","export const HTTP_CLIENT_VERSION = '0.0.0';\n\nexport const DEFAULT_USER_AGENT = `rawdash-connector/${HTTP_CLIENT_VERSION} (+https://rawdash.dev)`;\n\nexport function connectorUserAgent(connectorId: string): string {\n return `rawdash-connector-${connectorId}/${HTTP_CLIENT_VERSION} (+https://rawdash.dev)`;\n}\n","import {\n AuthError,\n ClientBugError,\n HttpClientError,\n RateLimitError,\n TransientError,\n UpstreamBugError,\n errorForStatus,\n} from './errors';\nimport { defaultRetryOn, parseRetryAfter, sleep } from './retry';\nimport type { FetchLike, HttpMethod, HttpRequest, HttpResponse } from './types';\nimport { DEFAULT_USER_AGENT } from './version';\n\nconst DEFAULT_TIMEOUT_MS = 10_000;\nconst DEFAULT_MAX_ATTEMPTS = 3;\nconst DEFAULT_INITIAL_DELAY_MS = 1000;\nconst DEFAULT_MAX_DELAY_MS = 60_000;\nconst OBSERVER_TIMEOUT_MS = 250;\n\nexport interface RequestObservation {\n url: string;\n method: HttpMethod;\n status: number;\n resource: string;\n requestId: string;\n body: unknown;\n}\n\nexport type RequestObserver = (\n event: RequestObservation,\n) => void | Promise<void>;\n\nexport interface RequestOptions {\n fetch?: FetchLike;\n observer?: RequestObserver;\n resource: string;\n requestId?: string;\n}\n\nasync function notifyObserver(\n observer: RequestObserver,\n event: RequestObservation,\n): Promise<void> {\n let result: void | Promise<void>;\n try {\n result = observer(event);\n } catch (err) {\n console.warn('[connector-shared] request observer threw:', err);\n return;\n }\n if (!(result instanceof Promise)) {\n return;\n }\n const guarded = result.catch((err) => {\n console.warn('[connector-shared] request observer rejected:', err);\n });\n let timer: ReturnType<typeof setTimeout> | undefined;\n const timeout = new Promise<void>((resolve) => {\n timer = setTimeout(resolve, OBSERVER_TIMEOUT_MS);\n });\n try {\n await Promise.race([guarded, timeout]);\n } finally {\n if (timer) {\n clearTimeout(timer);\n }\n }\n}\n\nfunction newRequestId(): string {\n const c = (globalThis as { crypto?: { randomUUID?: () => string } }).crypto;\n if (c?.randomUUID) {\n return c.randomUUID();\n }\n return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;\n}\n\nfunction mergeHeaders(\n defaults: Record<string, string>,\n overrides: Record<string, string> | undefined,\n): Record<string, string> {\n const merged: Record<string, string> = {};\n for (const [k, v] of Object.entries(defaults)) {\n merged[k.toLowerCase()] = v;\n }\n if (overrides) {\n for (const [k, v] of Object.entries(overrides)) {\n merged[k.toLowerCase()] = v;\n }\n }\n return merged;\n}\n\nfunction linkTimeoutSignal(\n parent: AbortSignal | undefined,\n timeoutMs: number,\n): { signal: AbortSignal; cancel: () => void } {\n const controller = new AbortController();\n const onParentAbort = () => {\n controller.abort(parent?.reason);\n };\n if (parent) {\n if (parent.aborted) {\n controller.abort(parent.reason);\n } else {\n parent.addEventListener('abort', onParentAbort, { once: true });\n }\n }\n const timer = setTimeout(() => {\n controller.abort(new Error(`Request timed out after ${timeoutMs}ms`));\n }, timeoutMs);\n return {\n signal: controller.signal,\n cancel: () => {\n clearTimeout(timer);\n if (parent) {\n parent.removeEventListener('abort', onParentAbort);\n }\n },\n };\n}\n\nasync function readBody(\n res: Response,\n parseJson: boolean,\n binary: boolean,\n): Promise<unknown> {\n if (res.status === 204 || res.status === 205) {\n return null;\n }\n if (binary) {\n return new Uint8Array(await res.arrayBuffer());\n }\n const contentType = res.headers.get('content-type') ?? '';\n if (parseJson && contentType.includes('application/json')) {\n const text = await res.text();\n if (text.length === 0) {\n return null;\n }\n return JSON.parse(text);\n }\n return res.text();\n}\n\nexport async function request<T = unknown>(\n req: HttpRequest,\n options: RequestOptions,\n): Promise<HttpResponse<T>> {\n const fetchImpl: FetchLike = options.fetch ?? (globalThis.fetch as FetchLike);\n const retry = req.retry ?? {};\n const maxAttempts = retry.maxAttempts ?? DEFAULT_MAX_ATTEMPTS;\n const initialDelayMs = retry.initialDelayMs ?? DEFAULT_INITIAL_DELAY_MS;\n const maxDelayMs = retry.maxDelayMs ?? DEFAULT_MAX_DELAY_MS;\n const retryOn = retry.retryOn ?? defaultRetryOn;\n const timeoutMs = req.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const parseJson = req.parseJson ?? true;\n const binary = req.binary ?? false;\n\n const headers = mergeHeaders(\n {\n 'User-Agent': DEFAULT_USER_AGENT,\n Accept: 'application/json',\n },\n req.headers,\n );\n\n let lastErr: Error | undefined;\n\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n req.signal?.throwIfAborted();\n\n const { signal, cancel } = linkTimeoutSignal(req.signal, timeoutMs);\n let res: Response;\n try {\n res = await fetchImpl(req.url, {\n method: req.method ?? 'GET',\n headers,\n body: req.body as RequestInit['body'],\n signal,\n });\n } catch (err) {\n cancel();\n if (req.signal?.aborted) {\n throw req.signal.reason ?? err;\n }\n const error = err instanceof Error ? err : new Error(String(err));\n lastErr = error;\n if (attempt < maxAttempts - 1 && retryOn(null, error)) {\n const delay = computeDelay(attempt, initialDelayMs, maxDelayMs);\n await sleep(delay, req.signal);\n continue;\n }\n throw new TransientError(error.message);\n }\n cancel();\n\n const body = await readBody(res, parseJson, binary);\n const httpResponse: HttpResponse<T> = {\n status: res.status,\n headers: res.headers,\n body: body as T,\n };\n if (req.rateLimit) {\n const state = req.rateLimit.parse(res.headers);\n if (state) {\n httpResponse.rateLimitState = state;\n }\n }\n\n if (options.observer) {\n await notifyObserver(options.observer, {\n url: req.url,\n method: req.method ?? 'GET',\n status: res.status,\n resource: options.resource,\n requestId: options.requestId ?? newRequestId(),\n body,\n });\n }\n\n if (res.ok) {\n return httpResponse;\n }\n\n const retryAfter = parseRetryAfter(res.headers.get('retry-after'));\n const message = `HTTP ${res.status} ${res.statusText} for ${req.method ?? 'GET'} ${req.url}`;\n const err = errorForStatus(message, httpResponse, retryAfter);\n\n if (\n attempt < maxAttempts - 1 &&\n retryOn(res.status, err) &&\n !(err instanceof AuthError) &&\n !(err instanceof ClientBugError)\n ) {\n lastErr = err;\n let delay = computeDelay(attempt, initialDelayMs, maxDelayMs);\n if (err instanceof RateLimitError && retryAfter) {\n const wait = retryAfter.getTime() - Date.now();\n if (wait > 0) {\n delay = Math.min(wait, maxDelayMs);\n }\n }\n await sleep(delay, req.signal);\n continue;\n }\n\n throw err;\n }\n\n throw lastErr ?? new UpstreamBugError('Exhausted retry attempts');\n}\n\nfunction computeDelay(\n attempt: number,\n initialDelayMs: number,\n maxDelayMs: number,\n): number {\n const base = initialDelayMs * 2 ** attempt;\n const jitter = base * 0.25 * Math.random();\n return Math.min(base + jitter, maxDelayMs);\n}\n\nexport { HttpClientError };\n","export interface RateLimitState {\n remaining: number;\n resetAt: Date;\n}\n\nexport interface RateLimitPolicy {\n parse(headers: Headers): RateLimitState | null;\n}\n\nexport interface StandardRateLimitPolicyConfig {\n remainingHeader: string;\n resetHeader: string;\n resetUnit: 's' | 'ms';\n resetFallbackMs?: number;\n}\n\nexport function standardRateLimitPolicy(\n config: StandardRateLimitPolicyConfig,\n): RateLimitPolicy {\n const { remainingHeader, resetHeader, resetUnit, resetFallbackMs } = config;\n const multiplier = resetUnit === 's' ? 1000 : 1;\n return {\n parse(h) {\n const remainingRaw = h.get(remainingHeader);\n if (remainingRaw === null || remainingRaw.trim() === '') {\n return null;\n }\n const remaining = Number(remainingRaw);\n if (!Number.isFinite(remaining)) {\n return null;\n }\n const resetRaw = h.get(resetHeader);\n if (resetRaw === null) {\n if (resetFallbackMs === undefined) {\n return null;\n }\n return {\n remaining,\n resetAt: new Date(Date.now() + resetFallbackMs),\n };\n }\n if (resetRaw.trim() === '') {\n return null;\n }\n const reset = Number(resetRaw);\n if (!Number.isFinite(reset) || reset < 0) {\n return null;\n }\n const resetMs = reset * multiplier;\n if (!Number.isFinite(resetMs)) {\n return null;\n }\n return { remaining, resetAt: new Date(resetMs) };\n },\n };\n}\n","export async function mapWithConcurrency<T, R>(\n items: readonly T[],\n concurrency: number,\n fn: (item: T, index: number) => Promise<R>,\n): Promise<R[]> {\n const results = new Array<R>(items.length);\n if (items.length === 0) {\n return results;\n }\n const normalized = Number.isFinite(concurrency) ? Math.floor(concurrency) : 1;\n const limit = Math.max(1, Math.min(normalized, items.length));\n let next = 0;\n let failed = false;\n\n async function worker(): Promise<void> {\n while (!failed) {\n const i = next++;\n if (i >= items.length) {\n return;\n }\n try {\n results[i] = await fn(items[i]!, i);\n } catch (err) {\n failed = true;\n throw err;\n }\n }\n }\n\n const workers: Promise<void>[] = [];\n for (let w = 0; w < limit; w++) {\n workers.push(worker());\n }\n await Promise.all(workers);\n return results;\n}\n","export interface SanitizeAllowedUrlOptions {\n url: string | null;\n host: string;\n pathname: string;\n protocol?: 'https:' | 'http:';\n}\n\nexport function sanitizeAllowedUrl(\n options: SanitizeAllowedUrlOptions,\n): string | null {\n const { url, host, pathname, protocol = 'https:' } = options;\n if (url === null) {\n return null;\n }\n try {\n const u = new URL(url);\n if (u.protocol !== protocol || u.host !== host || u.pathname !== pathname) {\n return null;\n }\n return u.toString();\n } catch {\n return null;\n }\n}\n","export type EpochUnit = 'ms' | 's' | 'iso';\n\nexport function parseEpoch(\n value: number | string | null | undefined,\n unit: EpochUnit,\n): number | null {\n if (value === null || value === undefined) {\n return null;\n }\n if (unit === 'iso') {\n if (typeof value !== 'string') {\n return null;\n }\n const ms = new Date(value).getTime();\n return Number.isFinite(ms) ? ms : null;\n }\n if (typeof value === 'string' && value.trim() === '') {\n return null;\n }\n const n = typeof value === 'number' ? value : Number(value);\n if (!Number.isFinite(n)) {\n return null;\n }\n const result = unit === 's' ? n * 1000 : n;\n return Number.isFinite(result) ? result : null;\n}\n","import { request } from './request';\nimport type { HttpRequest } from './types';\n\nexport function parseLinkHeader(header: string | null): Record<string, string> {\n if (!header) {\n return {};\n }\n const result: Record<string, string> = {};\n for (const part of header.split(',')) {\n const match = part.match(/<([^>]+)>\\s*;\\s*rel=\"([^\"]+)\"/);\n if (match) {\n result[match[2]!] = match[1]!;\n }\n }\n return result;\n}\n\nexport async function* paginateLink<T>(\n initial: HttpRequest,\n parse: (body: unknown) => T[],\n options: { resource: string },\n): AsyncIterable<T> {\n let next: string | null = initial.url;\n while (next) {\n const res: Awaited<ReturnType<typeof request>> = await request(\n {\n ...initial,\n url: next,\n },\n { resource: options.resource },\n );\n for (const item of parse(res.body)) {\n yield item;\n }\n const links = parseLinkHeader(res.headers.get('link'));\n next = links['next'] ?? null;\n }\n}\n\nexport async function* paginateCursor<T>(\n initial: HttpRequest,\n parse: (body: unknown) => { items: T[]; nextCursor: string | null },\n buildNext: (req: HttpRequest, cursor: string) => HttpRequest,\n options: { resource: string },\n): AsyncIterable<T> {\n let req: HttpRequest = initial;\n while (true) {\n const res = await request(req, { resource: options.resource });\n const { items, nextCursor } = parse(res.body);\n for (const item of items) {\n yield item;\n }\n if (!nextCursor) {\n return;\n }\n req = buildNext(req, nextCursor);\n }\n}\n\nexport async function* paginatePage<T>(\n initial: HttpRequest,\n parse: (body: unknown) => { items: T[]; hasMore: boolean },\n buildPage: (req: HttpRequest, page: number) => HttpRequest,\n options: { resource: string },\n): AsyncIterable<T> {\n let page = 1;\n while (true) {\n const req = page === 1 ? initial : buildPage(initial, page);\n const res = await request(req, { resource: options.resource });\n const { items, hasMore } = parse(res.body);\n for (const item of items) {\n yield item;\n }\n if (!hasMore || items.length === 0) {\n return;\n }\n page++;\n }\n}\n","export type LogFields = Record<string, unknown>;\n\nexport interface ConnectorLogger {\n info(event: string, fields?: LogFields): void;\n warn(event: string, fields?: LogFields): void;\n}\n\nexport interface ConnectorLoggerOptions {\n scope: string;\n}\n\nconst MAX_VALUE_LEN = 120;\n\nfunction truncate(s: string, max = MAX_VALUE_LEN): string {\n if (s.length <= max) {\n return s;\n }\n return `${s.slice(0, max - 1)}…`;\n}\n\nfunction formatValue(value: unknown): string {\n if (value === null) {\n return 'null';\n }\n if (value === undefined) {\n return '';\n }\n if (typeof value === 'number' || typeof value === 'boolean') {\n return String(value);\n }\n if (typeof value === 'string') {\n const t = truncate(value);\n if (/[\\s\"=]/.test(t)) {\n return JSON.stringify(t);\n }\n return t;\n }\n if (typeof value === 'bigint') {\n return value.toString();\n }\n let json: string | undefined;\n try {\n json = JSON.stringify(value);\n } catch {\n json = undefined;\n }\n return truncate(json ?? String(value));\n}\n\nexport function formatLogFields(fields?: LogFields): string {\n if (!fields) {\n return '';\n }\n const parts: string[] = [];\n for (const [k, v] of Object.entries(fields)) {\n if (v === undefined) {\n continue;\n }\n parts.push(`${k}=${formatValue(v)}`);\n }\n return parts.length > 0 ? ` ${parts.join(' ')}` : '';\n}\n\nexport function formatLogLine(\n scope: string,\n event: string,\n fields?: LogFields,\n): string {\n return `[${scope}] ${event}${formatLogFields(fields)}`;\n}\n\nexport function createDefaultConnectorLogger(\n opts: ConnectorLoggerOptions,\n): ConnectorLogger {\n return {\n info(event, fields) {\n console.info(formatLogLine(opts.scope, event, fields));\n },\n warn(event, fields) {\n console.warn(formatLogLine(opts.scope, event, fields));\n },\n };\n}\n\nconst NOOP_LOGGER: ConnectorLogger = {\n info() {},\n warn() {},\n};\n\nexport function noopConnectorLogger(): ConnectorLogger {\n return NOOP_LOGGER;\n}\n","import {\n type HttpResponse,\n connectorUserAgent,\n parseLinkHeader,\n sanitizeAllowedUrl,\n standardRateLimitPolicy,\n} from '@rawdash/connector-shared';\nimport {\n BaseConnector,\n type ChunkedSyncCursor,\n type ConnectorContext,\n type ConnectorDoc,\n type CredentialsSchema,\n type FetchPageResult,\n type FetchSpec,\n type FilterClause,\n type StorageHandle,\n type SyncOptions,\n type SyncResult,\n defineConfigFields,\n defineConnectorDoc,\n defineResources,\n makeChunkedCursorGuard,\n paginateChunked,\n resolveBackfillCutoff,\n resolveSpecCutoff,\n schemasFromResources,\n} from '@rawdash/core';\nimport { z } from 'zod';\n\nexport const configFields = defineConfigFields(\n z.object({\n owner: z.string().min(1).meta({\n label: 'Repository owner',\n description: 'GitHub username or organization name.',\n placeholder: 'rawdash',\n }),\n repo: z.string().min(1).meta({\n label: 'Repository',\n description: 'Repository name.',\n placeholder: 'rawdash',\n }),\n token: z.object({ $secret: z.string() }).optional().meta({\n label: 'Personal access token',\n description: 'GitHub PAT with `repo` scope.',\n secret: true,\n }),\n }),\n);\n\nexport const doc: ConnectorDoc = defineConnectorDoc({\n displayName: 'GitHub',\n category: 'engineering',\n brandColor: '#181717',\n tagline:\n 'Sync pull requests, issues, deployments, releases, CI runs, and contributor activity from a GitHub repository.',\n vendor: {\n name: 'GitHub',\n domain: 'github.com',\n apiDocs: 'https://docs.github.com/rest',\n website: 'https://github.com',\n },\n auth: {\n summary:\n 'A personal access token is optional for public repositories but required for private repos and to avoid the low unauthenticated rate limit.',\n setup: [\n 'Open GitHub → Settings → Developer settings → Personal access tokens.',\n 'Generate a token with the `repo` scope (read access is sufficient).',\n 'Store it as a secret and reference it from the connector config as `token: secret(\"GITHUB_TOKEN\")`.',\n ],\n },\n rateLimit:\n 'Unauthenticated requests share GitHub’s low 60 requests/hour limit; an authenticated token raises it to 5,000 requests/hour.',\n limitations: [\n 'The GitHub REST API can return the same item more than once within a sync (cursor pagination overlapping a mutating collection, retried requests, or an item surfaced via multiple endpoints). Each resource dedupes by stable id before writing, keeping the last copy seen.',\n 'Public repositories without a token are subject to GitHub’s low unauthenticated rate limit.',\n ],\n});\n\nexport interface GitHubSettings {\n owner: string;\n repo: string;\n}\n\ninterface GitHubRunsResponse {\n workflow_runs: Array<{\n id: number;\n name: string;\n conclusion: string | null;\n status: string;\n head_branch: string | null;\n actor: { login: string } | null;\n created_at: string;\n updated_at: string;\n run_attempt: number;\n }>;\n}\n\ninterface GitHubPR {\n number: number;\n title: string;\n state: string;\n draft: boolean;\n user: { login: string };\n created_at: string;\n updated_at: string;\n}\n\ninterface GitHubReview {\n user: { login: string } | null;\n state: string;\n submitted_at: string;\n}\n\ninterface GitHubIssue {\n number: number;\n title: string;\n state: string;\n labels: Array<{ name: string }>;\n assignees: Array<{ login: string }>;\n user: { login: string };\n created_at: string;\n updated_at: string;\n closed_at: string | null;\n pull_request?: unknown;\n}\n\ninterface GitHubDeployment {\n id: number;\n environment: string;\n ref: string;\n sha: string;\n creator: { login: string } | null;\n created_at: string;\n}\n\ninterface GitHubDeploymentStatus {\n state: string;\n updated_at: string;\n}\n\ninterface GitHubRelease {\n id: number;\n tag_name: string;\n name: string | null;\n draft: boolean;\n prerelease: boolean;\n created_at: string;\n published_at: string | null;\n author: { login: string };\n}\n\ninterface GitHubContributor {\n login: string;\n contributions: number;\n}\n\ninterface GitHubRepo {\n stargazers_count: number;\n forks_count: number;\n subscribers_count: number;\n}\n\nconst githubCredentials = {\n token: {\n description: 'GitHub personal access token',\n auth: 'optional' as const,\n },\n} satisfies CredentialsSchema;\n\ntype GitHubCredentials = typeof githubCredentials;\n\ntype GitHubSyncPhase =\n | 'repo_stats'\n | 'workflow_runs'\n | 'pull_requests'\n | 'issues'\n | 'deployments'\n | 'releases'\n | 'contributors';\n\nconst githubRateLimit = standardRateLimitPolicy({\n remainingHeader: 'x-ratelimit-remaining',\n resetHeader: 'x-ratelimit-reset',\n resetUnit: 's',\n});\n\nconst PHASE_ORDER: readonly GitHubSyncPhase[] = [\n 'repo_stats',\n 'workflow_runs',\n 'pull_requests',\n 'issues',\n 'deployments',\n 'releases',\n 'contributors',\n];\n\nconst PHASE_RESOURCES: Record<GitHubSyncPhase, readonly string[]> = {\n repo_stats: ['repo'],\n workflow_runs: ['workflow_run'],\n pull_requests: ['pull_request'],\n issues: ['issue'],\n deployments: ['deployment'],\n releases: ['release'],\n contributors: ['contributor'],\n};\n\nconst SINGLE_SPEC_PHASES: ReadonlySet<GitHubSyncPhase> = new Set([\n 'repo_stats',\n 'contributors',\n]);\n\nfunction pushableState(filter: FilterClause[] | undefined): string | null {\n if (!filter) {\n return null;\n }\n for (const clause of filter) {\n if ('field' in clause && clause.field === 'state' && clause.op === 'eq') {\n const { value } = clause;\n if (value === 'open' || value === 'closed') {\n return value;\n }\n }\n }\n return null;\n}\n\nfunction pushableEq(\n filter: FilterClause[] | undefined,\n field: string,\n): string | null {\n if (!filter) {\n return null;\n }\n for (const clause of filter) {\n if ('field' in clause && clause.field === field && clause.op === 'eq') {\n const { value } = clause;\n if (typeof value === 'string') {\n return value;\n }\n }\n }\n return null;\n}\n\nfunction pushableWorkflowRunStatus(\n filter: FilterClause[] | undefined,\n): string | null {\n return pushableEq(filter, 'status') ?? pushableEq(filter, 'conclusion');\n}\n\nfunction selectPhases(\n allowlist: ReadonlySet<string> | undefined,\n): readonly GitHubSyncPhase[] {\n if (allowlist === undefined) {\n return PHASE_ORDER;\n }\n return PHASE_ORDER.filter((phase) =>\n PHASE_RESOURCES[phase].some((r) => allowlist.has(r)),\n );\n}\n\ntype GitHubSyncCursor = ChunkedSyncCursor<GitHubSyncPhase, string>;\n\ninterface PRPageItems {\n prs: GitHubPR[];\n reviewsByPR: Map<number, GitHubReview[]>;\n}\n\ninterface DeploymentPageItems {\n deployments: GitHubDeployment[];\n latestStatusById: Map<number, GitHubDeploymentStatus | null>;\n}\n\nconst WORKFLOW_RUN_RERUN_LOOKBACK_MS = 32 * 86_400_000;\n\nfunction dedupeByKey<T>(\n items: T[],\n keyFn: (item: T) => string,\n resource: string,\n): T[] {\n if (items.length < 2) {\n return items;\n }\n const seen = new Map<string, T>();\n let duplicates = 0;\n for (const item of items) {\n const key = keyFn(item);\n if (seen.has(key)) {\n duplicates++;\n }\n seen.set(key, item);\n }\n if (duplicates > 0) {\n console.warn(\n `[github-actions] ${resource}: dropped ${duplicates} duplicate id(s) — keeping latest copy of each`,\n );\n }\n return Array.from(seen.values());\n}\n\nconst isGitHubSyncCursor = makeChunkedCursorGuard(PHASE_ORDER);\n\nconst workflowRunsResponseSchema = z.object({\n total_count: z.number().int().optional(),\n workflow_runs: z.array(\n z.object({\n id: z.number().int(),\n name: z.string(),\n conclusion: z.string().nullable(),\n status: z.string(),\n head_branch: z.string().nullable(),\n actor: z.object({ login: z.string().min(1) }).nullable(),\n created_at: z.iso.datetime(),\n updated_at: z.iso.datetime(),\n run_attempt: z.number().int(),\n artifacts_url: z.string().optional(),\n cancel_url: z.string().optional(),\n check_suite_id: z.number().int().optional(),\n check_suite_node_id: z.string().optional(),\n check_suite_url: z.string().optional(),\n display_title: z.string().optional(),\n event: z.string().optional(),\n head_commit: z.unknown().nullable().optional(),\n head_repository: z.unknown().nullable().optional(),\n head_sha: z.string().optional(),\n html_url: z.string().optional(),\n jobs_url: z.string().optional(),\n logs_url: z.string().optional(),\n node_id: z.string().optional(),\n path: z.string().optional(),\n previous_attempt_url: z.string().nullable().optional(),\n pull_requests: z.array(z.unknown()).nullable().optional(),\n referenced_workflows: z.array(z.unknown()).nullable().optional(),\n repository: z.unknown().nullable().optional(),\n rerun_url: z.string().optional(),\n run_number: z.number().int().optional(),\n run_started_at: z.iso.datetime().optional(),\n triggering_actor: z.object({ login: z.string().min(1) }).optional(),\n url: z.string().optional(),\n workflow_id: z.number().int().optional(),\n workflow_url: z.string().optional(),\n }),\n ),\n});\n\nconst pullRequestsSchema = z.array(\n z.object({\n number: z.number().int(),\n title: z.string(),\n state: z.string(),\n draft: z.boolean(),\n user: z.object({\n login: z.string().min(1),\n avatar_url: z.string().optional(),\n events_url: z.string().optional(),\n followers_url: z.string().optional(),\n following_url: z.string().optional(),\n gists_url: z.string().optional(),\n gravatar_id: z.string().nullable().optional(),\n html_url: z.string().optional(),\n id: z.number().int().optional(),\n node_id: z.string().optional(),\n organizations_url: z.string().optional(),\n received_events_url: z.string().optional(),\n repos_url: z.string().optional(),\n site_admin: z.boolean().optional(),\n starred_url: z.string().optional(),\n subscriptions_url: z.string().optional(),\n type: z.string().optional(),\n url: z.string().optional(),\n user_view_type: z.string().optional(),\n }),\n created_at: z.iso.datetime(),\n updated_at: z.iso.datetime(),\n _links: z.unknown().nullable().optional(),\n active_lock_reason: z.string().nullable().optional(),\n assignee: z.unknown().optional(),\n assignees: z.unknown().nullable().optional(),\n author_association: z.string().optional(),\n auto_merge: z.unknown().nullable().optional(),\n base: z.unknown().nullable().optional(),\n body: z.string().nullable().optional(),\n closed_at: z.string().nullable().optional(),\n comments_url: z.string().optional(),\n commits_url: z.string().optional(),\n diff_url: z.string().optional(),\n head: z.unknown().nullable().optional(),\n html_url: z.string().optional(),\n id: z.number().int().optional(),\n issue_url: z.string().optional(),\n labels: z.unknown().nullable().optional(),\n locked: z.boolean().optional(),\n merge_commit_sha: z.string().nullable().optional(),\n merged_at: z.string().nullable().optional(),\n milestone: z.unknown().optional(),\n node_id: z.string().optional(),\n patch_url: z.string().optional(),\n requested_reviewers: z.unknown().nullable().optional(),\n requested_teams: z.unknown().nullable().optional(),\n review_comment_url: z.string().optional(),\n review_comments_url: z.string().optional(),\n statuses_url: z.string().optional(),\n url: z.string().optional(),\n }),\n);\n\nconst reviewsSchema = z.array(\n z.object({\n user: z.object({ login: z.string().min(1) }).nullable(),\n state: z.string(),\n submitted_at: z.iso.datetime(),\n }),\n);\n\nconst issuesSchema = z.array(\n z.object({\n number: z.number().int(),\n title: z.string(),\n state: z.string(),\n labels: z.array(\n z.object({\n name: z.string(),\n id: z.number().int().optional(),\n node_id: z.string().optional(),\n url: z.string().optional(),\n color: z.string().optional(),\n default: z.boolean().optional(),\n description: z.string().nullable().optional(),\n }),\n ),\n assignees: z.array(z.object({ login: z.string().min(1) })),\n user: z.object({ login: z.string().min(1) }).catchall(z.unknown()),\n created_at: z.iso.datetime(),\n updated_at: z.iso.datetime(),\n closed_at: z.iso.datetime().nullable().optional(),\n pull_request: z.unknown().optional(),\n active_lock_reason: z.unknown().optional(),\n assignee: z.unknown().optional(),\n author_association: z.string().optional(),\n body: z.string().nullable().optional(),\n closed_by: z.unknown().optional(),\n comments: z.number().int().optional(),\n comments_url: z.string().optional(),\n draft: z.boolean().optional(),\n events_url: z.string().optional(),\n html_url: z.string().optional(),\n id: z.number().int().optional(),\n issue_field_values: z.unknown().optional(),\n labels_url: z.string().optional(),\n locked: z.boolean().optional(),\n milestone: z.unknown().optional(),\n node_id: z.string().optional(),\n performed_via_github_app: z.unknown().optional(),\n reactions: z.unknown().optional(),\n repository_url: z.string().optional(),\n state_reason: z.unknown().optional(),\n timeline_url: z.string().optional(),\n type: z.unknown().optional(),\n url: z.string().optional(),\n }),\n);\n\nconst deploymentsSchema = z.array(\n z.object({\n id: z.number().int(),\n environment: z.string(),\n ref: z.string(),\n sha: z.string(),\n creator: z.object({ login: z.string().min(1) }).nullable(),\n created_at: z.iso.datetime(),\n }),\n);\n\nconst deploymentStatusesSchema = z.array(\n z.object({\n state: z.string(),\n updated_at: z.iso.datetime(),\n }),\n);\n\nconst releasesSchema = z.array(\n z.object({\n id: z.number().int(),\n tag_name: z.string(),\n name: z.string().nullable(),\n draft: z.boolean(),\n prerelease: z.boolean(),\n created_at: z.iso.datetime(),\n published_at: z.iso.datetime().nullable(),\n author: z.object({\n login: z.string().min(1),\n id: z.number().int().optional(),\n node_id: z.string().optional(),\n avatar_url: z.string().optional(),\n gravatar_id: z.string().nullable().optional(),\n url: z.string().optional(),\n html_url: z.string().optional(),\n followers_url: z.string().optional(),\n following_url: z.string().optional(),\n gists_url: z.string().optional(),\n starred_url: z.string().optional(),\n subscriptions_url: z.string().optional(),\n organizations_url: z.string().optional(),\n repos_url: z.string().optional(),\n events_url: z.string().optional(),\n received_events_url: z.string().optional(),\n type: z.string().optional(),\n site_admin: z.boolean().optional(),\n user_view_type: z.string().optional(),\n }),\n node_id: z.string().optional(),\n url: z.string().optional(),\n html_url: z.string().optional(),\n assets_url: z.string().optional(),\n upload_url: z.string().optional(),\n tarball_url: z.string().nullable().optional(),\n zipball_url: z.string().nullable().optional(),\n target_commitish: z.string().optional(),\n body: z.string().nullable().optional(),\n immutable: z.boolean().optional(),\n mentions_count: z.number().int().optional(),\n updated_at: z.iso.datetime().optional(),\n assets: z.array(z.unknown()).optional(),\n }),\n);\n\nconst contributorsSchema = z.array(\n z.object({\n login: z.string().min(1),\n contributions: z.number().int(),\n }),\n);\n\nconst repoStatsSchema = z.object({\n stargazers_count: z.number().int(),\n forks_count: z.number().int(),\n subscribers_count: z.number().int(),\n});\n\nexport const githubResources = defineResources({\n repo: {\n shape: 'entity',\n filterable: [],\n description:\n 'Top-level repository stats (stars, forks, and watchers) as a single entity.',\n endpoint: 'GET /repos/{owner}/{repo}',\n responses: { repo: repoStatsSchema },\n },\n workflow_run: {\n shape: 'event',\n filterable: [\n {\n field: 'status',\n ops: ['eq'],\n values: [\n 'queued',\n 'in_progress',\n 'completed',\n 'requested',\n 'waiting',\n 'pending',\n ],\n },\n {\n field: 'conclusion',\n ops: ['eq'],\n values: [\n 'success',\n 'failure',\n 'cancelled',\n 'neutral',\n 'skipped',\n 'stale',\n 'timed_out',\n 'action_required',\n ],\n },\n { field: 'branch', ops: ['eq'] },\n ],\n description: 'GitHub Actions CI pipeline executions.',\n endpoint: 'GET /repos/{owner}/{repo}/actions/runs',\n responses: { workflow_runs: workflowRunsResponseSchema },\n },\n pull_request: {\n shape: 'entity',\n description:\n 'Open and closed pull requests, including draft state, author, and review state.',\n endpoint: 'GET /repos/{owner}/{repo}/pulls',\n notes:\n 'Review state is folded in from GET /repos/{owner}/{repo}/pulls/{number}/reviews per PR.',\n filterable: [{ field: 'state', ops: ['eq'], values: ['open', 'closed'] }],\n responses: {\n pull_requests: pullRequestsSchema,\n pull_request_reviews: reviewsSchema,\n },\n },\n issue: {\n shape: 'entity',\n description:\n 'Open and closed issues with labels, assignees, and author (pull requests excluded).',\n endpoint: 'GET /repos/{owner}/{repo}/issues',\n filterable: [{ field: 'state', ops: ['eq'], values: ['open', 'closed'] }],\n responses: { issues: issuesSchema },\n },\n deployment: {\n shape: 'entity',\n filterable: [{ field: 'environment', ops: ['eq'] }],\n description:\n 'Deployments with their latest status, keyed by environment and ref.',\n endpoint: 'GET /repos/{owner}/{repo}/deployments',\n notes:\n 'The latest status is folded in from GET /repos/{owner}/{repo}/deployments/{id}/statuses.',\n responses: {\n deployments: deploymentsSchema,\n deployment_statuses: deploymentStatusesSchema,\n },\n },\n release: {\n shape: 'entity',\n filterable: [],\n description: 'Published, draft, and prerelease GitHub releases.',\n endpoint: 'GET /repos/{owner}/{repo}/releases',\n responses: { releases: releasesSchema },\n },\n contributor: {\n shape: 'entity',\n filterable: [],\n description: 'Per-author commit counts for the repository.',\n endpoint: 'GET /repos/{owner}/{repo}/contributors',\n responses: { contributors: contributorsSchema },\n },\n});\n\nexport const id = 'github-actions';\n\nexport class GitHubConnector extends BaseConnector<\n GitHubSettings,\n GitHubCredentials\n> {\n static readonly id = id;\n\n static readonly resources = githubResources;\n\n static readonly schemas = schemasFromResources(githubResources);\n\n static create(input: unknown, ctx?: ConnectorContext): GitHubConnector {\n const parsed = configFields.parse(input);\n return new GitHubConnector(\n { owner: parsed.owner, repo: parsed.repo },\n { token: parsed.token },\n ctx,\n );\n }\n\n readonly id = id;\n\n override readonly credentials = githubCredentials;\n\n private seenWorkflowRunIds = new Set<string>();\n\n private preservedDeploymentStatus = new Map<string, string>();\n\n private buildHeaders(): Record<string, string> {\n const headers: Record<string, string> = {\n Accept: 'application/vnd.github+json',\n 'X-GitHub-Api-Version': '2022-11-28',\n 'User-Agent': connectorUserAgent('github'),\n };\n if (this.creds.token) {\n headers['Authorization'] = `Bearer ${this.creds.token}`;\n }\n return headers;\n }\n\n private fetch<T>(\n url: string,\n resource: string,\n signal: AbortSignal | undefined,\n ): Promise<HttpResponse<T>> {\n return this.get<T>(url, {\n resource,\n headers: this.buildHeaders(),\n signal,\n rateLimit: githubRateLimit,\n });\n }\n\n private allowedPageBasePath(phase: GitHubSyncPhase): string | null {\n const { owner, repo } = this.settings;\n switch (phase) {\n case 'workflow_runs':\n return `/repos/${owner}/${repo}/actions/runs`;\n case 'pull_requests':\n return `/repos/${owner}/${repo}/pulls`;\n case 'issues':\n return `/repos/${owner}/${repo}/issues`;\n case 'deployments':\n return `/repos/${owner}/${repo}/deployments`;\n case 'releases':\n return `/repos/${owner}/${repo}/releases`;\n case 'contributors':\n return `/repos/${owner}/${repo}/contributors`;\n case 'repo_stats':\n return null;\n }\n }\n\n private sanitizePageUrl(\n phase: GitHubSyncPhase,\n pageUrl: string | null,\n ): string | null {\n const allowedPath = this.allowedPageBasePath(phase);\n if (allowedPath === null) {\n return null;\n }\n const canonical = sanitizeAllowedUrl({\n url: pageUrl,\n host: 'api.github.com',\n pathname: allowedPath,\n });\n if (canonical !== null || pageUrl === null) {\n return canonical;\n }\n try {\n const u = new URL(pageUrl);\n const resourceSuffix = allowedPath.replace(/^\\/repos\\/[^/]+\\/[^/]+/, '');\n const escapedSuffix = resourceSuffix.replace(\n /[.*+?^${}()|[\\]\\\\]/g,\n '\\\\$&',\n );\n const numericPath = new RegExp(`^/repositories/\\\\d+${escapedSuffix}$`);\n if (\n u.protocol === 'https:' &&\n u.host === 'api.github.com' &&\n numericPath.test(u.pathname)\n ) {\n return u.toString();\n }\n } catch {\n return null;\n }\n return null;\n }\n\n private isResourceAllowed(options: SyncOptions, resource: string): boolean {\n if (!options.resources) {\n return true;\n }\n return options.resources.has(resource);\n }\n\n private resolveCursor(cursor: unknown): GitHubSyncCursor | undefined {\n if (!isGitHubSyncCursor(cursor)) {\n return undefined;\n }\n return {\n phase: cursor.phase,\n page: this.sanitizePageUrl(cursor.phase, cursor.page),\n spec: cursor.spec,\n };\n }\n\n private specsForResource(\n options: SyncOptions,\n resource: string,\n ): FetchSpec[] {\n const specs = options.fetchSpecs?.[resource];\n return specs && specs.length > 0 ? specs : [{}];\n }\n\n private specCutoff(\n options: SyncOptions,\n resource: string,\n spec: FetchSpec,\n now: number,\n ): number | null {\n if (options.fetchSpecs?.[resource]) {\n const specCutoffMs = resolveSpecCutoff(spec.requiredWindowMs, now);\n if (specCutoffMs === null) {\n return null;\n }\n const sinceCutoffMs = options.since\n ? new Date(options.since).getTime()\n : null;\n return sinceCutoffMs !== null\n ? Math.min(specCutoffMs, sinceCutoffMs)\n : specCutoffMs;\n }\n return resolveBackfillCutoff(options, resource, now);\n }\n\n private async fetchRepoStats(\n signal: AbortSignal | undefined,\n ): Promise<FetchPageResult<string>> {\n const { owner, repo } = this.settings;\n const res = await this.fetch<GitHubRepo>(\n `https://api.github.com/repos/${owner}/${repo}`,\n 'repo',\n signal,\n );\n return { items: [res.body], next: null };\n }\n\n private async fetchWorkflowRunsLatest(\n signal: AbortSignal | undefined,\n ): Promise<FetchPageResult<string>> {\n const { owner, repo } = this.settings;\n const res = await this.fetch<GitHubRunsResponse>(\n `https://api.github.com/repos/${owner}/${repo}/actions/runs?per_page=1`,\n 'workflow_runs',\n signal,\n );\n const run = res.body.workflow_runs[0];\n return { items: run ? [run] : [], next: null };\n }\n\n private async fetchWorkflowRunsFull(\n page: string | null,\n signal: AbortSignal | undefined,\n spec: FetchSpec,\n cutoff: number | null,\n ): Promise<FetchPageResult<string>> {\n const { owner, repo } = this.settings;\n let url: string;\n if (page) {\n url = page;\n } else {\n const u = new URL(\n `https://api.github.com/repos/${owner}/${repo}/actions/runs`,\n );\n u.searchParams.set('per_page', '100');\n const status = pushableWorkflowRunStatus(spec.filter);\n if (status !== null) {\n u.searchParams.set('status', status);\n }\n const branch = pushableEq(spec.filter, 'branch');\n if (branch !== null) {\n u.searchParams.set('branch', branch);\n }\n url = u.toString();\n }\n const res = await this.fetch<GitHubRunsResponse>(\n url,\n 'workflow_runs',\n signal,\n );\n const nextLink = parseLinkHeader(res.headers.get('link'))['next'] ?? null;\n const runs = res.body.workflow_runs;\n\n const filtered = runs.filter((run) => {\n if (cutoff === null) {\n return true;\n }\n const createdMs = new Date(run.created_at).getTime();\n const updatedMs = new Date(run.updated_at).getTime();\n return !(createdMs < cutoff && updatedMs < cutoff);\n });\n\n const lastRun = runs.at(-1);\n const cutoffReached =\n cutoff !== null &&\n lastRun !== undefined &&\n new Date(lastRun.created_at).getTime() <\n cutoff - WORKFLOW_RUN_RERUN_LOOKBACK_MS;\n\n return {\n items: filtered,\n next: cutoffReached ? null : nextLink,\n };\n }\n\n private async fetchPullRequests(\n options: SyncOptions,\n page: string | null,\n signal: AbortSignal | undefined,\n spec: FetchSpec,\n cutoff: number | null,\n ): Promise<FetchPageResult<string>> {\n const { owner, repo } = this.settings;\n const state = pushableState(spec.filter) ?? 'all';\n const url =\n page ??\n `https://api.github.com/repos/${owner}/${repo}/pulls?state=${state}&sort=updated&direction=desc&per_page=100`;\n const res = await this.fetch<GitHubPR[]>(url, 'pull_requests', signal);\n const nextLink = parseLinkHeader(res.headers.get('link'))['next'] ?? null;\n const prs = res.body;\n const filteredPrs =\n cutoff !== null\n ? prs.filter((pr) => new Date(pr.updated_at).getTime() >= cutoff)\n : prs;\n const lastPr = prs.at(-1);\n const cutoffReached =\n cutoff !== null &&\n lastPr !== undefined &&\n new Date(lastPr.updated_at).getTime() < cutoff;\n\n const reviewsByPR = new Map<number, GitHubReview[]>();\n if (this.isResourceAllowed(options, 'pull_request_reviews')) {\n for (const pr of filteredPrs) {\n signal?.throwIfAborted();\n const reviews = await this.fetch<GitHubReview[]>(\n `https://api.github.com/repos/${owner}/${repo}/pulls/${pr.number}/reviews`,\n 'pull_request_reviews',\n signal,\n );\n reviewsByPR.set(pr.number, reviews.body);\n }\n }\n\n const items: PRPageItems[] = [{ prs: filteredPrs, reviewsByPR }];\n return { items, next: cutoffReached ? null : nextLink };\n }\n\n private async fetchIssues(\n page: string | null,\n signal: AbortSignal | undefined,\n spec: FetchSpec,\n cutoff: number | null,\n ): Promise<FetchPageResult<string>> {\n const { owner, repo } = this.settings;\n let url: string;\n if (page) {\n url = page;\n } else {\n const u = new URL(`https://api.github.com/repos/${owner}/${repo}/issues`);\n u.searchParams.set('state', pushableState(spec.filter) ?? 'all');\n u.searchParams.set('sort', 'updated');\n u.searchParams.set('direction', 'asc');\n u.searchParams.set('per_page', '100');\n if (cutoff !== null) {\n u.searchParams.set('since', new Date(cutoff).toISOString());\n }\n url = u.toString();\n }\n const res = await this.fetch<GitHubIssue[]>(url, 'issues', signal);\n const nextLink = parseLinkHeader(res.headers.get('link'))['next'] ?? null;\n return { items: res.body, next: nextLink };\n }\n\n private async fetchDeployments(\n options: SyncOptions,\n page: string | null,\n signal: AbortSignal | undefined,\n spec: FetchSpec,\n cutoff: number | null,\n ): Promise<FetchPageResult<string>> {\n const { owner, repo } = this.settings;\n let url: string;\n if (page) {\n url = page;\n } else {\n const u = new URL(\n `https://api.github.com/repos/${owner}/${repo}/deployments`,\n );\n u.searchParams.set('per_page', '100');\n const environment = pushableEq(spec.filter, 'environment');\n if (environment !== null) {\n u.searchParams.set('environment', environment);\n }\n url = u.toString();\n }\n const res = await this.fetch<GitHubDeployment[]>(\n url,\n 'deployments',\n signal,\n );\n const nextLink = parseLinkHeader(res.headers.get('link'))['next'] ?? null;\n const deployments = res.body;\n const filteredDeployments =\n cutoff !== null\n ? deployments.filter((d) => new Date(d.created_at).getTime() >= cutoff)\n : deployments;\n\n const latestStatusById = new Map<number, GitHubDeploymentStatus | null>();\n if (this.isResourceAllowed(options, 'deployment_statuses')) {\n for (const deployment of filteredDeployments) {\n signal?.throwIfAborted();\n const statusRes = await this.fetch<GitHubDeploymentStatus[]>(\n `https://api.github.com/repos/${owner}/${repo}/deployments/${deployment.id}/statuses?per_page=1`,\n 'deployment_statuses',\n signal,\n );\n latestStatusById.set(deployment.id, statusRes.body[0] ?? null);\n }\n }\n\n const items: DeploymentPageItems[] = [\n { deployments: filteredDeployments, latestStatusById },\n ];\n return { items, next: nextLink };\n }\n\n private async fetchReleases(\n page: string | null,\n signal: AbortSignal | undefined,\n cutoff: number | null,\n ): Promise<FetchPageResult<string>> {\n const { owner, repo } = this.settings;\n const url =\n page ??\n `https://api.github.com/repos/${owner}/${repo}/releases?per_page=100`;\n const res = await this.fetch<GitHubRelease[]>(url, 'releases', signal);\n const nextLink = parseLinkHeader(res.headers.get('link'))['next'] ?? null;\n const releases = res.body;\n const filtered =\n cutoff !== null\n ? releases.filter((r) => new Date(r.created_at).getTime() >= cutoff)\n : releases;\n return { items: filtered, next: nextLink };\n }\n\n private async fetchContributors(\n page: string | null,\n signal: AbortSignal | undefined,\n ): Promise<FetchPageResult<string>> {\n const { owner, repo } = this.settings;\n const url =\n page ??\n `https://api.github.com/repos/${owner}/${repo}/contributors?per_page=100`;\n const res = await this.fetch<GitHubContributor[]>(\n url,\n 'contributors',\n signal,\n );\n const nextLink = parseLinkHeader(res.headers.get('link'))['next'] ?? null;\n return { items: res.body, next: nextLink };\n }\n\n private async writeRepoStats(\n storage: StorageHandle,\n items: unknown[],\n ): Promise<void> {\n const repoBody = items[0] as GitHubRepo | undefined;\n if (!repoBody) {\n return;\n }\n const { owner, repo } = this.settings;\n await storage.entities(\n [\n {\n type: 'repo',\n id: `${owner}/${repo}`,\n attributes: {\n stars: repoBody.stargazers_count,\n forks: repoBody.forks_count,\n watchers: repoBody.subscribers_count,\n },\n updated_at: Date.now(),\n },\n ],\n { types: ['repo'] },\n );\n }\n\n private async writeWorkflowRunsLatest(\n storage: StorageHandle,\n items: unknown[],\n ): Promise<void> {\n const run = items[0] as\n | GitHubRunsResponse['workflow_runs'][number]\n | undefined;\n if (!run) {\n return;\n }\n await storage.event({\n name: 'workflow_run',\n start_ts: new Date(run.created_at).getTime(),\n end_ts: new Date(run.updated_at).getTime(),\n attributes: {\n id: run.id,\n workflow_name: run.name,\n conclusion: run.conclusion ?? 'unknown',\n status: run.status,\n branch: run.head_branch ?? '',\n actor: run.actor?.login ?? '',\n run_attempt: run.run_attempt,\n },\n });\n }\n\n private async writeWorkflowRunsFull(\n storage: StorageHandle,\n items: unknown[],\n page: string | null,\n spec: number,\n ): Promise<void> {\n if (page === null && spec === 0) {\n await storage.events([], { names: ['workflow_run'] });\n this.seenWorkflowRunIds.clear();\n }\n const withinPage = dedupeByKey(\n items as GitHubRunsResponse['workflow_runs'],\n (run) => String(run.id),\n 'workflow_runs',\n );\n let crossPageDuplicates = 0;\n const runs: GitHubRunsResponse['workflow_runs'] = [];\n for (const run of withinPage) {\n const key = String(run.id);\n if (this.seenWorkflowRunIds.has(key)) {\n crossPageDuplicates++;\n continue;\n }\n this.seenWorkflowRunIds.add(key);\n runs.push(run);\n }\n if (crossPageDuplicates > 0) {\n console.warn(\n `[github-actions] workflow_runs: dropped ${crossPageDuplicates} duplicate id(s) seen on an earlier page`,\n );\n }\n for (const run of runs) {\n await storage.event({\n name: 'workflow_run',\n start_ts: new Date(run.created_at).getTime(),\n end_ts: new Date(run.updated_at).getTime(),\n attributes: {\n id: run.id,\n workflow_name: run.name,\n conclusion: run.conclusion ?? 'unknown',\n status: run.status,\n branch: run.head_branch ?? '',\n actor: run.actor?.login ?? '',\n run_attempt: run.run_attempt,\n },\n });\n }\n }\n\n private async writePullRequests(\n storage: StorageHandle,\n items: unknown[],\n page: string | null,\n spec: number,\n options: SyncOptions,\n ): Promise<void> {\n const reviewsAllowed = this.isResourceAllowed(\n options,\n 'pull_request_reviews',\n );\n if (page === null && spec === 0) {\n await storage.entities([], { types: ['pull_request'] });\n if (reviewsAllowed) {\n await storage.edges([], { kinds: ['reviewed_by'] });\n }\n }\n const pageItems = items as PRPageItems[];\n for (const { prs: rawPrs, reviewsByPR } of pageItems) {\n const prs = dedupeByKey(\n rawPrs,\n (pr) => String(pr.number),\n 'pull_requests',\n );\n for (const pr of prs) {\n await storage.entity({\n type: 'pull_request',\n id: String(pr.number),\n attributes: {\n title: pr.title,\n state: pr.state,\n draft: pr.draft,\n author: pr.user.login,\n created_at: new Date(pr.created_at).getTime(),\n },\n updated_at: new Date(pr.updated_at).getTime(),\n });\n }\n if (!reviewsAllowed) {\n continue;\n }\n for (const pr of prs) {\n const reviews = reviewsByPR.get(pr.number) ?? [];\n for (const review of reviews) {\n if (!review.user) {\n continue;\n }\n await storage.edge({\n from_type: 'pull_request',\n from_id: String(pr.number),\n kind: 'reviewed_by',\n to_type: 'user',\n to_id: review.user.login,\n attributes: { state: review.state },\n updated_at: new Date(review.submitted_at).getTime(),\n });\n }\n }\n }\n }\n\n private async writeIssues(\n storage: StorageHandle,\n items: unknown[],\n page: string | null,\n spec: number,\n ): Promise<void> {\n if (page === null && spec === 0) {\n await storage.entities([], { types: ['issue'] });\n }\n const issues = dedupeByKey(\n (items as GitHubIssue[]).filter((i) => i.pull_request === undefined),\n (issue) => String(issue.number),\n 'issues',\n );\n for (const issue of issues) {\n await storage.entity({\n type: 'issue',\n id: String(issue.number),\n attributes: {\n number: issue.number,\n title: issue.title,\n state: issue.state,\n labels: issue.labels.map((l) => l.name),\n assignees: issue.assignees.map((a) => a.login),\n author: issue.user.login,\n created_at: new Date(issue.created_at).getTime(),\n updated_at: new Date(issue.updated_at).getTime(),\n closed_at: issue.closed_at\n ? new Date(issue.closed_at).getTime()\n : null,\n },\n updated_at: new Date(issue.updated_at).getTime(),\n });\n }\n }\n\n private async writeDeployments(\n storage: StorageHandle,\n items: unknown[],\n page: string | null,\n spec: number,\n options: SyncOptions,\n ): Promise<void> {\n const statusesAllowed = this.isResourceAllowed(\n options,\n 'deployment_statuses',\n );\n if (page === null && spec === 0) {\n if (!statusesAllowed) {\n const existing = await storage.queryEntities({ type: 'deployment' });\n for (const entity of existing) {\n const prev = entity.attributes['latest_status'];\n if (typeof prev === 'string') {\n this.preservedDeploymentStatus.set(entity.id, prev);\n }\n }\n }\n await storage.entities([], { types: ['deployment'] });\n }\n const pageItems = items as DeploymentPageItems[];\n for (const { deployments: rawDeployments, latestStatusById } of pageItems) {\n const deployments = dedupeByKey(\n rawDeployments,\n (d) => String(d.id),\n 'deployments',\n );\n for (const deployment of deployments) {\n const createdMs = new Date(deployment.created_at).getTime();\n let latestStatus: string;\n let statusUpdatedMs: number | null = null;\n if (statusesAllowed) {\n const status = latestStatusById.get(deployment.id) ?? null;\n latestStatus = status?.state ?? 'unknown';\n statusUpdatedMs = status?.updated_at\n ? new Date(status.updated_at).getTime()\n : null;\n } else {\n latestStatus =\n this.preservedDeploymentStatus.get(String(deployment.id)) ??\n 'unknown';\n }\n await storage.entity({\n type: 'deployment',\n id: String(deployment.id),\n attributes: {\n environment: deployment.environment,\n ref: deployment.ref,\n sha: deployment.sha,\n creator: deployment.creator?.login ?? '',\n created_at: createdMs,\n latest_status: latestStatus,\n },\n updated_at: Math.max(createdMs, statusUpdatedMs ?? 0),\n });\n }\n }\n }\n\n private async writeReleases(\n storage: StorageHandle,\n items: unknown[],\n page: string | null,\n spec: number,\n ): Promise<void> {\n if (page === null && spec === 0) {\n await storage.entities([], { types: ['release'] });\n }\n const releases = dedupeByKey(\n items as GitHubRelease[],\n (r) => String(r.id),\n 'releases',\n );\n for (const release of releases) {\n await storage.entity({\n type: 'release',\n id: String(release.id),\n attributes: {\n tag_name: release.tag_name,\n name: release.name ?? '',\n draft: release.draft,\n prerelease: release.prerelease,\n created_at: new Date(release.created_at).getTime(),\n published_at: release.published_at\n ? new Date(release.published_at).getTime()\n : null,\n author: release.author.login,\n },\n updated_at: new Date(\n release.published_at ?? release.created_at,\n ).getTime(),\n });\n }\n }\n\n private async writeContributors(\n storage: StorageHandle,\n items: unknown[],\n page: string | null,\n ): Promise<void> {\n if (page === null) {\n await storage.entities([], { types: ['contributor'] });\n }\n const contributors = dedupeByKey(\n items as GitHubContributor[],\n (c) => c.login,\n 'contributors',\n );\n const observedAt = Date.now();\n for (const c of contributors) {\n await storage.entity({\n type: 'contributor',\n id: c.login,\n attributes: { commits: c.contributions },\n updated_at: observedAt,\n });\n }\n }\n\n async sync(\n options: SyncOptions,\n storage: StorageHandle,\n signal?: AbortSignal,\n ): Promise<SyncResult> {\n const cursor = this.resolveCursor(options.cursor);\n const phases = selectPhases(options.resources);\n const specCount = (phase: GitHubSyncPhase): number => {\n if (options.mode === 'latest' || SINGLE_SPEC_PHASES.has(phase)) {\n return 1;\n }\n return this.specsForResource(options, PHASE_RESOURCES[phase][0]!).length;\n };\n const specFor = (phase: GitHubSyncPhase, specIndex: number): FetchSpec =>\n this.specsForResource(options, PHASE_RESOURCES[phase][0]!)[specIndex] ??\n {};\n const cutoffFor = (\n phase: GitHubSyncPhase,\n spec: FetchSpec,\n ): number | null =>\n this.specCutoff(options, PHASE_RESOURCES[phase][0]!, spec, Date.now());\n return paginateChunked<GitHubSyncPhase, string>({\n phases,\n cursor,\n signal,\n specCount,\n logger: this.logger,\n fetchPage: async (phase, page, sig, specIndex) => {\n const spec = specFor(phase, specIndex);\n switch (phase) {\n case 'repo_stats':\n return this.fetchRepoStats(sig);\n case 'workflow_runs':\n return options.mode === 'latest'\n ? this.fetchWorkflowRunsLatest(sig)\n : this.fetchWorkflowRunsFull(\n page,\n sig,\n spec,\n cutoffFor(phase, spec),\n );\n case 'pull_requests':\n return this.fetchPullRequests(\n options,\n page,\n sig,\n spec,\n cutoffFor(phase, spec),\n );\n case 'issues':\n return this.fetchIssues(page, sig, spec, cutoffFor(phase, spec));\n case 'deployments':\n return this.fetchDeployments(\n options,\n page,\n sig,\n spec,\n cutoffFor(phase, spec),\n );\n case 'releases':\n return this.fetchReleases(page, sig, cutoffFor(phase, spec));\n case 'contributors':\n return this.fetchContributors(page, sig);\n }\n },\n writeBatch: async (phase, items, page, specIndex) => {\n switch (phase) {\n case 'repo_stats':\n return this.writeRepoStats(storage, items);\n case 'workflow_runs':\n return options.mode === 'latest'\n ? this.writeWorkflowRunsLatest(storage, items)\n : this.writeWorkflowRunsFull(storage, items, page, specIndex);\n case 'pull_requests':\n return this.writePullRequests(\n storage,\n items,\n page,\n specIndex,\n options,\n );\n case 'issues':\n return this.writeIssues(storage, items, page, specIndex);\n case 'deployments':\n return this.writeDeployments(\n storage,\n items,\n page,\n specIndex,\n options,\n );\n case 'releases':\n return this.writeReleases(storage, items, page, specIndex);\n case 'contributors':\n return this.writeContributors(storage, items, page);\n }\n },\n });\n }\n}\n","import { GitHubConnector } from './github';\n\nexport {\n configFields,\n doc,\n GitHubConnector,\n githubResources as resources,\n id,\n} from './github';\nexport type { GitHubSettings } from './github';\nexport default GitHubConnector;\n"],"mappings":";AEAO,IAAM,sBAAsB;AAE5B,IAAM,qBAAqB,qBAAqB,mBAAmB;AAEnE,SAAS,mBAAmB,aAA6B;AAC9D,SAAO,qBAAqB,WAAW,IAAI,mBAAmB;AAChE;AEUO,SAAS,wBACd,QACiB;AACjB,QAAM,EAAE,iBAAiB,aAAa,WAAW,gBAAgB,IAAI;AACrE,QAAM,aAAa,cAAc,MAAM,MAAO;AAC9C,SAAO;IACL,MAAM,GAAG;AACP,YAAM,eAAe,EAAE,IAAI,eAAe;AAC1C,UAAI,iBAAiB,QAAQ,aAAa,KAAK,MAAM,IAAI;AACvD,eAAO;MACT;AACA,YAAM,YAAY,OAAO,YAAY;AACrC,UAAI,CAAC,OAAO,SAAS,SAAS,GAAG;AAC/B,eAAO;MACT;AACA,YAAM,WAAW,EAAE,IAAI,WAAW;AAClC,UAAI,aAAa,MAAM;AACrB,YAAI,oBAAoB,QAAW;AACjC,iBAAO;QACT;AACA,eAAO;UACL;UACA,SAAS,IAAI,KAAK,KAAK,IAAI,IAAI,eAAe;QAChD;MACF;AACA,UAAI,SAAS,KAAK,MAAM,IAAI;AAC1B,eAAO;MACT;AACA,YAAM,QAAQ,OAAO,QAAQ;AAC7B,UAAI,CAAC,OAAO,SAAS,KAAK,KAAK,QAAQ,GAAG;AACxC,eAAO;MACT;AACA,YAAM,UAAU,QAAQ;AACxB,UAAI,CAAC,OAAO,SAAS,OAAO,GAAG;AAC7B,eAAO;MACT;AACA,aAAO,EAAE,WAAW,SAAS,IAAI,KAAK,OAAO,EAAE;IACjD;EACF;AACF;AEhDO,SAAS,mBACd,SACe;AACf,QAAM,EAAE,KAAK,MAAM,UAAU,WAAW,SAAS,IAAI;AACrD,MAAI,QAAQ,MAAM;AAChB,WAAO;EACT;AACA,MAAI;AACF,UAAM,IAAI,IAAI,IAAI,GAAG;AACrB,QAAI,EAAE,aAAa,YAAY,EAAE,SAAS,QAAQ,EAAE,aAAa,UAAU;AACzE,aAAO;IACT;AACA,WAAO,EAAE,SAAS;EACpB,QAAQ;AACN,WAAO;EACT;AACF;AEpBO,SAAS,gBAAgB,QAA+C;AAC7E,MAAI,CAAC,QAAQ;AACX,WAAO,CAAC;EACV;AACA,QAAM,SAAiC,CAAC;AACxC,aAAW,QAAQ,OAAO,MAAM,GAAG,GAAG;AACpC,UAAM,QAAQ,KAAK,MAAM,+BAA+B;AACxD,QAAI,OAAO;AACT,aAAO,MAAM,CAAC,CAAE,IAAI,MAAM,CAAC;IAC7B;EACF;AACA,SAAO;AACT;;;AERA;AAAA,EACE;AAAA,EAWA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,SAAS;AAEX,IAAM,eAAe;AAAA,EAC1B,EAAE,OAAO;AAAA,IACP,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,KAAK;AAAA,MAC5B,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAa;AAAA,IACf,CAAC;AAAA,IACD,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,KAAK;AAAA,MAC3B,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAa;AAAA,IACf,CAAC;AAAA,IACD,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE,SAAS,EAAE,KAAK;AAAA,MACvD,OAAO;AAAA,MACP,aAAa;AAAA,MACb,QAAQ;AAAA,IACV,CAAC;AAAA,EACH,CAAC;AACH;AAEO,IAAM,MAAoB,mBAAmB;AAAA,EAClD,aAAa;AAAA,EACb,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,SACE;AAAA,EACF,QAAQ;AAAA,IACN,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,SAAS;AAAA,EACX;AAAA,EACA,MAAM;AAAA,IACJ,SACE;AAAA,IACF,OAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EACA,WACE;AAAA,EACF,aAAa;AAAA,IACX;AAAA,IACA;AAAA,EACF;AACF,CAAC;AAsFD,IAAM,oBAAoB;AAAA,EACxB,OAAO;AAAA,IACL,aAAa;AAAA,IACb,MAAM;AAAA,EACR;AACF;AAaA,IAAM,kBAAkB,wBAAwB;AAAA,EAC9C,iBAAiB;AAAA,EACjB,aAAa;AAAA,EACb,WAAW;AACb,CAAC;AAED,IAAM,cAA0C;AAAA,EAC9C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,IAAM,kBAA8D;AAAA,EAClE,YAAY,CAAC,MAAM;AAAA,EACnB,eAAe,CAAC,cAAc;AAAA,EAC9B,eAAe,CAAC,cAAc;AAAA,EAC9B,QAAQ,CAAC,OAAO;AAAA,EAChB,aAAa,CAAC,YAAY;AAAA,EAC1B,UAAU,CAAC,SAAS;AAAA,EACpB,cAAc,CAAC,aAAa;AAC9B;AAEA,IAAM,qBAAmD,oBAAI,IAAI;AAAA,EAC/D;AAAA,EACA;AACF,CAAC;AAED,SAAS,cAAc,QAAmD;AACxE,MAAI,CAAC,QAAQ;AACX,WAAO;AAAA,EACT;AACA,aAAW,UAAU,QAAQ;AAC3B,QAAI,WAAW,UAAU,OAAO,UAAU,WAAW,OAAO,OAAO,MAAM;AACvE,YAAM,EAAE,MAAM,IAAI;AAClB,UAAI,UAAU,UAAU,UAAU,UAAU;AAC1C,eAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,WACP,QACA,OACe;AACf,MAAI,CAAC,QAAQ;AACX,WAAO;AAAA,EACT;AACA,aAAW,UAAU,QAAQ;AAC3B,QAAI,WAAW,UAAU,OAAO,UAAU,SAAS,OAAO,OAAO,MAAM;AACrE,YAAM,EAAE,MAAM,IAAI;AAClB,UAAI,OAAO,UAAU,UAAU;AAC7B,eAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,0BACP,QACe;AACf,SAAO,WAAW,QAAQ,QAAQ,KAAK,WAAW,QAAQ,YAAY;AACxE;AAEA,SAAS,aACP,WAC4B;AAC5B,MAAI,cAAc,QAAW;AAC3B,WAAO;AAAA,EACT;AACA,SAAO,YAAY;AAAA,IAAO,CAAC,UACzB,gBAAgB,KAAK,EAAE,KAAK,CAAC,MAAM,UAAU,IAAI,CAAC,CAAC;AAAA,EACrD;AACF;AAcA,IAAM,iCAAiC,KAAK;AAE5C,SAAS,YACP,OACA,OACA,UACK;AACL,MAAI,MAAM,SAAS,GAAG;AACpB,WAAO;AAAA,EACT;AACA,QAAM,OAAO,oBAAI,IAAe;AAChC,MAAI,aAAa;AACjB,aAAW,QAAQ,OAAO;AACxB,UAAM,MAAM,MAAM,IAAI;AACtB,QAAI,KAAK,IAAI,GAAG,GAAG;AACjB;AAAA,IACF;AACA,SAAK,IAAI,KAAK,IAAI;AAAA,EACpB;AACA,MAAI,aAAa,GAAG;AAClB,YAAQ;AAAA,MACN,oBAAoB,QAAQ,aAAa,UAAU;AAAA,IACrD;AAAA,EACF;AACA,SAAO,MAAM,KAAK,KAAK,OAAO,CAAC;AACjC;AAEA,IAAM,qBAAqB,uBAAuB,WAAW;AAE7D,IAAM,6BAA6B,EAAE,OAAO;AAAA,EAC1C,aAAa,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS;AAAA,EACvC,eAAe,EAAE;AAAA,IACf,EAAE,OAAO;AAAA,MACP,IAAI,EAAE,OAAO,EAAE,IAAI;AAAA,MACnB,MAAM,EAAE,OAAO;AAAA,MACf,YAAY,EAAE,OAAO,EAAE,SAAS;AAAA,MAChC,QAAQ,EAAE,OAAO;AAAA,MACjB,aAAa,EAAE,OAAO,EAAE,SAAS;AAAA,MACjC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,SAAS;AAAA,MACvD,YAAY,EAAE,IAAI,SAAS;AAAA,MAC3B,YAAY,EAAE,IAAI,SAAS;AAAA,MAC3B,aAAa,EAAE,OAAO,EAAE,IAAI;AAAA,MAC5B,eAAe,EAAE,OAAO,EAAE,SAAS;AAAA,MACnC,YAAY,EAAE,OAAO,EAAE,SAAS;AAAA,MAChC,gBAAgB,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS;AAAA,MAC1C,qBAAqB,EAAE,OAAO,EAAE,SAAS;AAAA,MACzC,iBAAiB,EAAE,OAAO,EAAE,SAAS;AAAA,MACrC,eAAe,EAAE,OAAO,EAAE,SAAS;AAAA,MACnC,OAAO,EAAE,OAAO,EAAE,SAAS;AAAA,MAC3B,aAAa,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS;AAAA,MAC7C,iBAAiB,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS;AAAA,MACjD,UAAU,EAAE,OAAO,EAAE,SAAS;AAAA,MAC9B,UAAU,EAAE,OAAO,EAAE,SAAS;AAAA,MAC9B,UAAU,EAAE,OAAO,EAAE,SAAS;AAAA,MAC9B,UAAU,EAAE,OAAO,EAAE,SAAS;AAAA,MAC9B,SAAS,EAAE,OAAO,EAAE,SAAS;AAAA,MAC7B,MAAM,EAAE,OAAO,EAAE,SAAS;AAAA,MAC1B,sBAAsB,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,MACrD,eAAe,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,SAAS,EAAE,SAAS;AAAA,MACxD,sBAAsB,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,SAAS,EAAE,SAAS;AAAA,MAC/D,YAAY,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS;AAAA,MAC5C,WAAW,EAAE,OAAO,EAAE,SAAS;AAAA,MAC/B,YAAY,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS;AAAA,MACtC,gBAAgB,EAAE,IAAI,SAAS,EAAE,SAAS;AAAA,MAC1C,kBAAkB,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,SAAS;AAAA,MAClE,KAAK,EAAE,OAAO,EAAE,SAAS;AAAA,MACzB,aAAa,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS;AAAA,MACvC,cAAc,EAAE,OAAO,EAAE,SAAS;AAAA,IACpC,CAAC;AAAA,EACH;AACF,CAAC;AAED,IAAM,qBAAqB,EAAE;AAAA,EAC3B,EAAE,OAAO;AAAA,IACP,QAAQ,EAAE,OAAO,EAAE,IAAI;AAAA,IACvB,OAAO,EAAE,OAAO;AAAA,IAChB,OAAO,EAAE,OAAO;AAAA,IAChB,OAAO,EAAE,QAAQ;AAAA,IACjB,MAAM,EAAE,OAAO;AAAA,MACb,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA,MACvB,YAAY,EAAE,OAAO,EAAE,SAAS;AAAA,MAChC,YAAY,EAAE,OAAO,EAAE,SAAS;AAAA,MAChC,eAAe,EAAE,OAAO,EAAE,SAAS;AAAA,MACnC,eAAe,EAAE,OAAO,EAAE,SAAS;AAAA,MACnC,WAAW,EAAE,OAAO,EAAE,SAAS;AAAA,MAC/B,aAAa,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,MAC5C,UAAU,EAAE,OAAO,EAAE,SAAS;AAAA,MAC9B,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS;AAAA,MAC9B,SAAS,EAAE,OAAO,EAAE,SAAS;AAAA,MAC7B,mBAAmB,EAAE,OAAO,EAAE,SAAS;AAAA,MACvC,qBAAqB,EAAE,OAAO,EAAE,SAAS;AAAA,MACzC,WAAW,EAAE,OAAO,EAAE,SAAS;AAAA,MAC/B,YAAY,EAAE,QAAQ,EAAE,SAAS;AAAA,MACjC,aAAa,EAAE,OAAO,EAAE,SAAS;AAAA,MACjC,mBAAmB,EAAE,OAAO,EAAE,SAAS;AAAA,MACvC,MAAM,EAAE,OAAO,EAAE,SAAS;AAAA,MAC1B,KAAK,EAAE,OAAO,EAAE,SAAS;AAAA,MACzB,gBAAgB,EAAE,OAAO,EAAE,SAAS;AAAA,IACtC,CAAC;AAAA,IACD,YAAY,EAAE,IAAI,SAAS;AAAA,IAC3B,YAAY,EAAE,IAAI,SAAS;AAAA,IAC3B,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS;AAAA,IACxC,oBAAoB,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,IACnD,UAAU,EAAE,QAAQ,EAAE,SAAS;AAAA,IAC/B,WAAW,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS;AAAA,IAC3C,oBAAoB,EAAE,OAAO,EAAE,SAAS;AAAA,IACxC,YAAY,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS;AAAA,IAC5C,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS;AAAA,IACtC,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,IACrC,WAAW,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,IAC1C,cAAc,EAAE,OAAO,EAAE,SAAS;AAAA,IAClC,aAAa,EAAE,OAAO,EAAE,SAAS;AAAA,IACjC,UAAU,EAAE,OAAO,EAAE,SAAS;AAAA,IAC9B,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS;AAAA,IACtC,UAAU,EAAE,OAAO,EAAE,SAAS;AAAA,IAC9B,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS;AAAA,IAC9B,WAAW,EAAE,OAAO,EAAE,SAAS;AAAA,IAC/B,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS;AAAA,IACxC,QAAQ,EAAE,QAAQ,EAAE,SAAS;AAAA,IAC7B,kBAAkB,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,IACjD,WAAW,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,IAC1C,WAAW,EAAE,QAAQ,EAAE,SAAS;AAAA,IAChC,SAAS,EAAE,OAAO,EAAE,SAAS;AAAA,IAC7B,WAAW,EAAE,OAAO,EAAE,SAAS;AAAA,IAC/B,qBAAqB,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS;AAAA,IACrD,iBAAiB,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS;AAAA,IACjD,oBAAoB,EAAE,OAAO,EAAE,SAAS;AAAA,IACxC,qBAAqB,EAAE,OAAO,EAAE,SAAS;AAAA,IACzC,cAAc,EAAE,OAAO,EAAE,SAAS;AAAA,IAClC,KAAK,EAAE,OAAO,EAAE,SAAS;AAAA,EAC3B,CAAC;AACH;AAEA,IAAM,gBAAgB,EAAE;AAAA,EACtB,EAAE,OAAO;AAAA,IACP,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,SAAS;AAAA,IACtD,OAAO,EAAE,OAAO;AAAA,IAChB,cAAc,EAAE,IAAI,SAAS;AAAA,EAC/B,CAAC;AACH;AAEA,IAAM,eAAe,EAAE;AAAA,EACrB,EAAE,OAAO;AAAA,IACP,QAAQ,EAAE,OAAO,EAAE,IAAI;AAAA,IACvB,OAAO,EAAE,OAAO;AAAA,IAChB,OAAO,EAAE,OAAO;AAAA,IAChB,QAAQ,EAAE;AAAA,MACR,EAAE,OAAO;AAAA,QACP,MAAM,EAAE,OAAO;AAAA,QACf,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS;AAAA,QAC9B,SAAS,EAAE,OAAO,EAAE,SAAS;AAAA,QAC7B,KAAK,EAAE,OAAO,EAAE,SAAS;AAAA,QACzB,OAAO,EAAE,OAAO,EAAE,SAAS;AAAA,QAC3B,SAAS,EAAE,QAAQ,EAAE,SAAS;AAAA,QAC9B,aAAa,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,MAC9C,CAAC;AAAA,IACH;AAAA,IACA,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;AAAA,IACzD,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,SAAS,EAAE,QAAQ,CAAC;AAAA,IACjE,YAAY,EAAE,IAAI,SAAS;AAAA,IAC3B,YAAY,EAAE,IAAI,SAAS;AAAA,IAC3B,WAAW,EAAE,IAAI,SAAS,EAAE,SAAS,EAAE,SAAS;AAAA,IAChD,cAAc,EAAE,QAAQ,EAAE,SAAS;AAAA,IACnC,oBAAoB,EAAE,QAAQ,EAAE,SAAS;AAAA,IACzC,UAAU,EAAE,QAAQ,EAAE,SAAS;AAAA,IAC/B,oBAAoB,EAAE,OAAO,EAAE,SAAS;AAAA,IACxC,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,IACrC,WAAW,EAAE,QAAQ,EAAE,SAAS;AAAA,IAChC,UAAU,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS;AAAA,IACpC,cAAc,EAAE,OAAO,EAAE,SAAS;AAAA,IAClC,OAAO,EAAE,QAAQ,EAAE,SAAS;AAAA,IAC5B,YAAY,EAAE,OAAO,EAAE,SAAS;AAAA,IAChC,UAAU,EAAE,OAAO,EAAE,SAAS;AAAA,IAC9B,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS;AAAA,IAC9B,oBAAoB,EAAE,QAAQ,EAAE,SAAS;AAAA,IACzC,YAAY,EAAE,OAAO,EAAE,SAAS;AAAA,IAChC,QAAQ,EAAE,QAAQ,EAAE,SAAS;AAAA,IAC7B,WAAW,EAAE,QAAQ,EAAE,SAAS;AAAA,IAChC,SAAS,EAAE,OAAO,EAAE,SAAS;AAAA,IAC7B,0BAA0B,EAAE,QAAQ,EAAE,SAAS;AAAA,IAC/C,WAAW,EAAE,QAAQ,EAAE,SAAS;AAAA,IAChC,gBAAgB,EAAE,OAAO,EAAE,SAAS;AAAA,IACpC,cAAc,EAAE,QAAQ,EAAE,SAAS;AAAA,IACnC,cAAc,EAAE,OAAO,EAAE,SAAS;AAAA,IAClC,MAAM,EAAE,QAAQ,EAAE,SAAS;AAAA,IAC3B,KAAK,EAAE,OAAO,EAAE,SAAS;AAAA,EAC3B,CAAC;AACH;AAEA,IAAM,oBAAoB,EAAE;AAAA,EAC1B,EAAE,OAAO;AAAA,IACP,IAAI,EAAE,OAAO,EAAE,IAAI;AAAA,IACnB,aAAa,EAAE,OAAO;AAAA,IACtB,KAAK,EAAE,OAAO;AAAA,IACd,KAAK,EAAE,OAAO;AAAA,IACd,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,SAAS;AAAA,IACzD,YAAY,EAAE,IAAI,SAAS;AAAA,EAC7B,CAAC;AACH;AAEA,IAAM,2BAA2B,EAAE;AAAA,EACjC,EAAE,OAAO;AAAA,IACP,OAAO,EAAE,OAAO;AAAA,IAChB,YAAY,EAAE,IAAI,SAAS;AAAA,EAC7B,CAAC;AACH;AAEA,IAAM,iBAAiB,EAAE;AAAA,EACvB,EAAE,OAAO;AAAA,IACP,IAAI,EAAE,OAAO,EAAE,IAAI;AAAA,IACnB,UAAU,EAAE,OAAO;AAAA,IACnB,MAAM,EAAE,OAAO,EAAE,SAAS;AAAA,IAC1B,OAAO,EAAE,QAAQ;AAAA,IACjB,YAAY,EAAE,QAAQ;AAAA,IACtB,YAAY,EAAE,IAAI,SAAS;AAAA,IAC3B,cAAc,EAAE,IAAI,SAAS,EAAE,SAAS;AAAA,IACxC,QAAQ,EAAE,OAAO;AAAA,MACf,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA,MACvB,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS;AAAA,MAC9B,SAAS,EAAE,OAAO,EAAE,SAAS;AAAA,MAC7B,YAAY,EAAE,OAAO,EAAE,SAAS;AAAA,MAChC,aAAa,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,MAC5C,KAAK,EAAE,OAAO,EAAE,SAAS;AAAA,MACzB,UAAU,EAAE,OAAO,EAAE,SAAS;AAAA,MAC9B,eAAe,EAAE,OAAO,EAAE,SAAS;AAAA,MACnC,eAAe,EAAE,OAAO,EAAE,SAAS;AAAA,MACnC,WAAW,EAAE,OAAO,EAAE,SAAS;AAAA,MAC/B,aAAa,EAAE,OAAO,EAAE,SAAS;AAAA,MACjC,mBAAmB,EAAE,OAAO,EAAE,SAAS;AAAA,MACvC,mBAAmB,EAAE,OAAO,EAAE,SAAS;AAAA,MACvC,WAAW,EAAE,OAAO,EAAE,SAAS;AAAA,MAC/B,YAAY,EAAE,OAAO,EAAE,SAAS;AAAA,MAChC,qBAAqB,EAAE,OAAO,EAAE,SAAS;AAAA,MACzC,MAAM,EAAE,OAAO,EAAE,SAAS;AAAA,MAC1B,YAAY,EAAE,QAAQ,EAAE,SAAS;AAAA,MACjC,gBAAgB,EAAE,OAAO,EAAE,SAAS;AAAA,IACtC,CAAC;AAAA,IACD,SAAS,EAAE,OAAO,EAAE,SAAS;AAAA,IAC7B,KAAK,EAAE,OAAO,EAAE,SAAS;AAAA,IACzB,UAAU,EAAE,OAAO,EAAE,SAAS;AAAA,IAC9B,YAAY,EAAE,OAAO,EAAE,SAAS;AAAA,IAChC,YAAY,EAAE,OAAO,EAAE,SAAS;AAAA,IAChC,aAAa,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,IAC5C,aAAa,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,IAC5C,kBAAkB,EAAE,OAAO,EAAE,SAAS;AAAA,IACtC,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,IACrC,WAAW,EAAE,QAAQ,EAAE,SAAS;AAAA,IAChC,gBAAgB,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS;AAAA,IAC1C,YAAY,EAAE,IAAI,SAAS,EAAE,SAAS;AAAA,IACtC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,SAAS;AAAA,EACxC,CAAC;AACH;AAEA,IAAM,qBAAqB,EAAE;AAAA,EAC3B,EAAE,OAAO;AAAA,IACP,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA,IACvB,eAAe,EAAE,OAAO,EAAE,IAAI;AAAA,EAChC,CAAC;AACH;AAEA,IAAM,kBAAkB,EAAE,OAAO;AAAA,EAC/B,kBAAkB,EAAE,OAAO,EAAE,IAAI;AAAA,EACjC,aAAa,EAAE,OAAO,EAAE,IAAI;AAAA,EAC5B,mBAAmB,EAAE,OAAO,EAAE,IAAI;AACpC,CAAC;AAEM,IAAM,kBAAkB,gBAAgB;AAAA,EAC7C,MAAM;AAAA,IACJ,OAAO;AAAA,IACP,YAAY,CAAC;AAAA,IACb,aACE;AAAA,IACF,UAAU;AAAA,IACV,WAAW,EAAE,MAAM,gBAAgB;AAAA,EACrC;AAAA,EACA,cAAc;AAAA,IACZ,OAAO;AAAA,IACP,YAAY;AAAA,MACV;AAAA,QACE,OAAO;AAAA,QACP,KAAK,CAAC,IAAI;AAAA,QACV,QAAQ;AAAA,UACN;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,MACA;AAAA,QACE,OAAO;AAAA,QACP,KAAK,CAAC,IAAI;AAAA,QACV,QAAQ;AAAA,UACN;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,MACA,EAAE,OAAO,UAAU,KAAK,CAAC,IAAI,EAAE;AAAA,IACjC;AAAA,IACA,aAAa;AAAA,IACb,UAAU;AAAA,IACV,WAAW,EAAE,eAAe,2BAA2B;AAAA,EACzD;AAAA,EACA,cAAc;AAAA,IACZ,OAAO;AAAA,IACP,aACE;AAAA,IACF,UAAU;AAAA,IACV,OACE;AAAA,IACF,YAAY,CAAC,EAAE,OAAO,SAAS,KAAK,CAAC,IAAI,GAAG,QAAQ,CAAC,QAAQ,QAAQ,EAAE,CAAC;AAAA,IACxE,WAAW;AAAA,MACT,eAAe;AAAA,MACf,sBAAsB;AAAA,IACxB;AAAA,EACF;AAAA,EACA,OAAO;AAAA,IACL,OAAO;AAAA,IACP,aACE;AAAA,IACF,UAAU;AAAA,IACV,YAAY,CAAC,EAAE,OAAO,SAAS,KAAK,CAAC,IAAI,GAAG,QAAQ,CAAC,QAAQ,QAAQ,EAAE,CAAC;AAAA,IACxE,WAAW,EAAE,QAAQ,aAAa;AAAA,EACpC;AAAA,EACA,YAAY;AAAA,IACV,OAAO;AAAA,IACP,YAAY,CAAC,EAAE,OAAO,eAAe,KAAK,CAAC,IAAI,EAAE,CAAC;AAAA,IAClD,aACE;AAAA,IACF,UAAU;AAAA,IACV,OACE;AAAA,IACF,WAAW;AAAA,MACT,aAAa;AAAA,MACb,qBAAqB;AAAA,IACvB;AAAA,EACF;AAAA,EACA,SAAS;AAAA,IACP,OAAO;AAAA,IACP,YAAY,CAAC;AAAA,IACb,aAAa;AAAA,IACb,UAAU;AAAA,IACV,WAAW,EAAE,UAAU,eAAe;AAAA,EACxC;AAAA,EACA,aAAa;AAAA,IACX,OAAO;AAAA,IACP,YAAY,CAAC;AAAA,IACb,aAAa;AAAA,IACb,UAAU;AAAA,IACV,WAAW,EAAE,cAAc,mBAAmB;AAAA,EAChD;AACF,CAAC;AAEM,IAAM,KAAK;AAEX,IAAM,kBAAN,MAAM,yBAAwB,cAGnC;AAAA,EACA,OAAgB,KAAK;AAAA,EAErB,OAAgB,YAAY;AAAA,EAE5B,OAAgB,UAAU,qBAAqB,eAAe;AAAA,EAE9D,OAAO,OAAO,OAAgB,KAAyC;AACrE,UAAM,SAAS,aAAa,MAAM,KAAK;AACvC,WAAO,IAAI;AAAA,MACT,EAAE,OAAO,OAAO,OAAO,MAAM,OAAO,KAAK;AAAA,MACzC,EAAE,OAAO,OAAO,MAAM;AAAA,MACtB;AAAA,IACF;AAAA,EACF;AAAA,EAES,KAAK;AAAA,EAEI,cAAc;AAAA,EAExB,qBAAqB,oBAAI,IAAY;AAAA,EAErC,4BAA4B,oBAAI,IAAoB;AAAA,EAEpD,eAAuC;AAC7C,UAAM,UAAkC;AAAA,MACtC,QAAQ;AAAA,MACR,wBAAwB;AAAA,MACxB,cAAc,mBAAmB,QAAQ;AAAA,IAC3C;AACA,QAAI,KAAK,MAAM,OAAO;AACpB,cAAQ,eAAe,IAAI,UAAU,KAAK,MAAM,KAAK;AAAA,IACvD;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,MACN,KACA,UACA,QAC0B;AAC1B,WAAO,KAAK,IAAO,KAAK;AAAA,MACtB;AAAA,MACA,SAAS,KAAK,aAAa;AAAA,MAC3B;AAAA,MACA,WAAW;AAAA,IACb,CAAC;AAAA,EACH;AAAA,EAEQ,oBAAoB,OAAuC;AACjE,UAAM,EAAE,OAAO,KAAK,IAAI,KAAK;AAC7B,YAAQ,OAAO;AAAA,MACb,KAAK;AACH,eAAO,UAAU,KAAK,IAAI,IAAI;AAAA,MAChC,KAAK;AACH,eAAO,UAAU,KAAK,IAAI,IAAI;AAAA,MAChC,KAAK;AACH,eAAO,UAAU,KAAK,IAAI,IAAI;AAAA,MAChC,KAAK;AACH,eAAO,UAAU,KAAK,IAAI,IAAI;AAAA,MAChC,KAAK;AACH,eAAO,UAAU,KAAK,IAAI,IAAI;AAAA,MAChC,KAAK;AACH,eAAO,UAAU,KAAK,IAAI,IAAI;AAAA,MAChC,KAAK;AACH,eAAO;AAAA,IACX;AAAA,EACF;AAAA,EAEQ,gBACN,OACA,SACe;AACf,UAAM,cAAc,KAAK,oBAAoB,KAAK;AAClD,QAAI,gBAAgB,MAAM;AACxB,aAAO;AAAA,IACT;AACA,UAAM,YAAY,mBAAmB;AAAA,MACnC,KAAK;AAAA,MACL,MAAM;AAAA,MACN,UAAU;AAAA,IACZ,CAAC;AACD,QAAI,cAAc,QAAQ,YAAY,MAAM;AAC1C,aAAO;AAAA,IACT;AACA,QAAI;AACF,YAAM,IAAI,IAAI,IAAI,OAAO;AACzB,YAAM,iBAAiB,YAAY,QAAQ,0BAA0B,EAAE;AACvE,YAAM,gBAAgB,eAAe;AAAA,QACnC;AAAA,QACA;AAAA,MACF;AACA,YAAM,cAAc,IAAI,OAAO,sBAAsB,aAAa,GAAG;AACrE,UACE,EAAE,aAAa,YACf,EAAE,SAAS,oBACX,YAAY,KAAK,EAAE,QAAQ,GAC3B;AACA,eAAO,EAAE,SAAS;AAAA,MACpB;AAAA,IACF,QAAQ;AACN,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,kBAAkB,SAAsB,UAA2B;AACzE,QAAI,CAAC,QAAQ,WAAW;AACtB,aAAO;AAAA,IACT;AACA,WAAO,QAAQ,UAAU,IAAI,QAAQ;AAAA,EACvC;AAAA,EAEQ,cAAc,QAA+C;AACnE,QAAI,CAAC,mBAAmB,MAAM,GAAG;AAC/B,aAAO;AAAA,IACT;AACA,WAAO;AAAA,MACL,OAAO,OAAO;AAAA,MACd,MAAM,KAAK,gBAAgB,OAAO,OAAO,OAAO,IAAI;AAAA,MACpD,MAAM,OAAO;AAAA,IACf;AAAA,EACF;AAAA,EAEQ,iBACN,SACA,UACa;AACb,UAAM,QAAQ,QAAQ,aAAa,QAAQ;AAC3C,WAAO,SAAS,MAAM,SAAS,IAAI,QAAQ,CAAC,CAAC,CAAC;AAAA,EAChD;AAAA,EAEQ,WACN,SACA,UACA,MACA,KACe;AACf,QAAI,QAAQ,aAAa,QAAQ,GAAG;AAClC,YAAM,eAAe,kBAAkB,KAAK,kBAAkB,GAAG;AACjE,UAAI,iBAAiB,MAAM;AACzB,eAAO;AAAA,MACT;AACA,YAAM,gBAAgB,QAAQ,QAC1B,IAAI,KAAK,QAAQ,KAAK,EAAE,QAAQ,IAChC;AACJ,aAAO,kBAAkB,OACrB,KAAK,IAAI,cAAc,aAAa,IACpC;AAAA,IACN;AACA,WAAO,sBAAsB,SAAS,UAAU,GAAG;AAAA,EACrD;AAAA,EAEA,MAAc,eACZ,QACkC;AAClC,UAAM,EAAE,OAAO,KAAK,IAAI,KAAK;AAC7B,UAAM,MAAM,MAAM,KAAK;AAAA,MACrB,gCAAgC,KAAK,IAAI,IAAI;AAAA,MAC7C;AAAA,MACA;AAAA,IACF;AACA,WAAO,EAAE,OAAO,CAAC,IAAI,IAAI,GAAG,MAAM,KAAK;AAAA,EACzC;AAAA,EAEA,MAAc,wBACZ,QACkC;AAClC,UAAM,EAAE,OAAO,KAAK,IAAI,KAAK;AAC7B,UAAM,MAAM,MAAM,KAAK;AAAA,MACrB,gCAAgC,KAAK,IAAI,IAAI;AAAA,MAC7C;AAAA,MACA;AAAA,IACF;AACA,UAAM,MAAM,IAAI,KAAK,cAAc,CAAC;AACpC,WAAO,EAAE,OAAO,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,MAAM,KAAK;AAAA,EAC/C;AAAA,EAEA,MAAc,sBACZ,MACA,QACA,MACA,QACkC;AAClC,UAAM,EAAE,OAAO,KAAK,IAAI,KAAK;AAC7B,QAAI;AACJ,QAAI,MAAM;AACR,YAAM;AAAA,IACR,OAAO;AACL,YAAM,IAAI,IAAI;AAAA,QACZ,gCAAgC,KAAK,IAAI,IAAI;AAAA,MAC/C;AACA,QAAE,aAAa,IAAI,YAAY,KAAK;AACpC,YAAM,SAAS,0BAA0B,KAAK,MAAM;AACpD,UAAI,WAAW,MAAM;AACnB,UAAE,aAAa,IAAI,UAAU,MAAM;AAAA,MACrC;AACA,YAAM,SAAS,WAAW,KAAK,QAAQ,QAAQ;AAC/C,UAAI,WAAW,MAAM;AACnB,UAAE,aAAa,IAAI,UAAU,MAAM;AAAA,MACrC;AACA,YAAM,EAAE,SAAS;AAAA,IACnB;AACA,UAAM,MAAM,MAAM,KAAK;AAAA,MACrB;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,UAAM,WAAW,gBAAgB,IAAI,QAAQ,IAAI,MAAM,CAAC,EAAE,MAAM,KAAK;AACrE,UAAM,OAAO,IAAI,KAAK;AAEtB,UAAM,WAAW,KAAK,OAAO,CAAC,QAAQ;AACpC,UAAI,WAAW,MAAM;AACnB,eAAO;AAAA,MACT;AACA,YAAM,YAAY,IAAI,KAAK,IAAI,UAAU,EAAE,QAAQ;AACnD,YAAM,YAAY,IAAI,KAAK,IAAI,UAAU,EAAE,QAAQ;AACnD,aAAO,EAAE,YAAY,UAAU,YAAY;AAAA,IAC7C,CAAC;AAED,UAAM,UAAU,KAAK,GAAG,EAAE;AAC1B,UAAM,gBACJ,WAAW,QACX,YAAY,UACZ,IAAI,KAAK,QAAQ,UAAU,EAAE,QAAQ,IACnC,SAAS;AAEb,WAAO;AAAA,MACL,OAAO;AAAA,MACP,MAAM,gBAAgB,OAAO;AAAA,IAC/B;AAAA,EACF;AAAA,EAEA,MAAc,kBACZ,SACA,MACA,QACA,MACA,QACkC;AAClC,UAAM,EAAE,OAAO,KAAK,IAAI,KAAK;AAC7B,UAAM,QAAQ,cAAc,KAAK,MAAM,KAAK;AAC5C,UAAM,MACJ,QACA,gCAAgC,KAAK,IAAI,IAAI,gBAAgB,KAAK;AACpE,UAAM,MAAM,MAAM,KAAK,MAAkB,KAAK,iBAAiB,MAAM;AACrE,UAAM,WAAW,gBAAgB,IAAI,QAAQ,IAAI,MAAM,CAAC,EAAE,MAAM,KAAK;AACrE,UAAM,MAAM,IAAI;AAChB,UAAM,cACJ,WAAW,OACP,IAAI,OAAO,CAAC,OAAO,IAAI,KAAK,GAAG,UAAU,EAAE,QAAQ,KAAK,MAAM,IAC9D;AACN,UAAM,SAAS,IAAI,GAAG,EAAE;AACxB,UAAM,gBACJ,WAAW,QACX,WAAW,UACX,IAAI,KAAK,OAAO,UAAU,EAAE,QAAQ,IAAI;AAE1C,UAAM,cAAc,oBAAI,IAA4B;AACpD,QAAI,KAAK,kBAAkB,SAAS,sBAAsB,GAAG;AAC3D,iBAAW,MAAM,aAAa;AAC5B,gBAAQ,eAAe;AACvB,cAAM,UAAU,MAAM,KAAK;AAAA,UACzB,gCAAgC,KAAK,IAAI,IAAI,UAAU,GAAG,MAAM;AAAA,UAChE;AAAA,UACA;AAAA,QACF;AACA,oBAAY,IAAI,GAAG,QAAQ,QAAQ,IAAI;AAAA,MACzC;AAAA,IACF;AAEA,UAAM,QAAuB,CAAC,EAAE,KAAK,aAAa,YAAY,CAAC;AAC/D,WAAO,EAAE,OAAO,MAAM,gBAAgB,OAAO,SAAS;AAAA,EACxD;AAAA,EAEA,MAAc,YACZ,MACA,QACA,MACA,QACkC;AAClC,UAAM,EAAE,OAAO,KAAK,IAAI,KAAK;AAC7B,QAAI;AACJ,QAAI,MAAM;AACR,YAAM;AAAA,IACR,OAAO;AACL,YAAM,IAAI,IAAI,IAAI,gCAAgC,KAAK,IAAI,IAAI,SAAS;AACxE,QAAE,aAAa,IAAI,SAAS,cAAc,KAAK,MAAM,KAAK,KAAK;AAC/D,QAAE,aAAa,IAAI,QAAQ,SAAS;AACpC,QAAE,aAAa,IAAI,aAAa,KAAK;AACrC,QAAE,aAAa,IAAI,YAAY,KAAK;AACpC,UAAI,WAAW,MAAM;AACnB,UAAE,aAAa,IAAI,SAAS,IAAI,KAAK,MAAM,EAAE,YAAY,CAAC;AAAA,MAC5D;AACA,YAAM,EAAE,SAAS;AAAA,IACnB;AACA,UAAM,MAAM,MAAM,KAAK,MAAqB,KAAK,UAAU,MAAM;AACjE,UAAM,WAAW,gBAAgB,IAAI,QAAQ,IAAI,MAAM,CAAC,EAAE,MAAM,KAAK;AACrE,WAAO,EAAE,OAAO,IAAI,MAAM,MAAM,SAAS;AAAA,EAC3C;AAAA,EAEA,MAAc,iBACZ,SACA,MACA,QACA,MACA,QACkC;AAClC,UAAM,EAAE,OAAO,KAAK,IAAI,KAAK;AAC7B,QAAI;AACJ,QAAI,MAAM;AACR,YAAM;AAAA,IACR,OAAO;AACL,YAAM,IAAI,IAAI;AAAA,QACZ,gCAAgC,KAAK,IAAI,IAAI;AAAA,MAC/C;AACA,QAAE,aAAa,IAAI,YAAY,KAAK;AACpC,YAAM,cAAc,WAAW,KAAK,QAAQ,aAAa;AACzD,UAAI,gBAAgB,MAAM;AACxB,UAAE,aAAa,IAAI,eAAe,WAAW;AAAA,MAC/C;AACA,YAAM,EAAE,SAAS;AAAA,IACnB;AACA,UAAM,MAAM,MAAM,KAAK;AAAA,MACrB;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,UAAM,WAAW,gBAAgB,IAAI,QAAQ,IAAI,MAAM,CAAC,EAAE,MAAM,KAAK;AACrE,UAAM,cAAc,IAAI;AACxB,UAAM,sBACJ,WAAW,OACP,YAAY,OAAO,CAAC,MAAM,IAAI,KAAK,EAAE,UAAU,EAAE,QAAQ,KAAK,MAAM,IACpE;AAEN,UAAM,mBAAmB,oBAAI,IAA2C;AACxE,QAAI,KAAK,kBAAkB,SAAS,qBAAqB,GAAG;AAC1D,iBAAW,cAAc,qBAAqB;AAC5C,gBAAQ,eAAe;AACvB,cAAM,YAAY,MAAM,KAAK;AAAA,UAC3B,gCAAgC,KAAK,IAAI,IAAI,gBAAgB,WAAW,EAAE;AAAA,UAC1E;AAAA,UACA;AAAA,QACF;AACA,yBAAiB,IAAI,WAAW,IAAI,UAAU,KAAK,CAAC,KAAK,IAAI;AAAA,MAC/D;AAAA,IACF;AAEA,UAAM,QAA+B;AAAA,MACnC,EAAE,aAAa,qBAAqB,iBAAiB;AAAA,IACvD;AACA,WAAO,EAAE,OAAO,MAAM,SAAS;AAAA,EACjC;AAAA,EAEA,MAAc,cACZ,MACA,QACA,QACkC;AAClC,UAAM,EAAE,OAAO,KAAK,IAAI,KAAK;AAC7B,UAAM,MACJ,QACA,gCAAgC,KAAK,IAAI,IAAI;AAC/C,UAAM,MAAM,MAAM,KAAK,MAAuB,KAAK,YAAY,MAAM;AACrE,UAAM,WAAW,gBAAgB,IAAI,QAAQ,IAAI,MAAM,CAAC,EAAE,MAAM,KAAK;AACrE,UAAM,WAAW,IAAI;AACrB,UAAM,WACJ,WAAW,OACP,SAAS,OAAO,CAAC,MAAM,IAAI,KAAK,EAAE,UAAU,EAAE,QAAQ,KAAK,MAAM,IACjE;AACN,WAAO,EAAE,OAAO,UAAU,MAAM,SAAS;AAAA,EAC3C;AAAA,EAEA,MAAc,kBACZ,MACA,QACkC;AAClC,UAAM,EAAE,OAAO,KAAK,IAAI,KAAK;AAC7B,UAAM,MACJ,QACA,gCAAgC,KAAK,IAAI,IAAI;AAC/C,UAAM,MAAM,MAAM,KAAK;AAAA,MACrB;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,UAAM,WAAW,gBAAgB,IAAI,QAAQ,IAAI,MAAM,CAAC,EAAE,MAAM,KAAK;AACrE,WAAO,EAAE,OAAO,IAAI,MAAM,MAAM,SAAS;AAAA,EAC3C;AAAA,EAEA,MAAc,eACZ,SACA,OACe;AACf,UAAM,WAAW,MAAM,CAAC;AACxB,QAAI,CAAC,UAAU;AACb;AAAA,IACF;AACA,UAAM,EAAE,OAAO,KAAK,IAAI,KAAK;AAC7B,UAAM,QAAQ;AAAA,MACZ;AAAA,QACE;AAAA,UACE,MAAM;AAAA,UACN,IAAI,GAAG,KAAK,IAAI,IAAI;AAAA,UACpB,YAAY;AAAA,YACV,OAAO,SAAS;AAAA,YAChB,OAAO,SAAS;AAAA,YAChB,UAAU,SAAS;AAAA,UACrB;AAAA,UACA,YAAY,KAAK,IAAI;AAAA,QACvB;AAAA,MACF;AAAA,MACA,EAAE,OAAO,CAAC,MAAM,EAAE;AAAA,IACpB;AAAA,EACF;AAAA,EAEA,MAAc,wBACZ,SACA,OACe;AACf,UAAM,MAAM,MAAM,CAAC;AAGnB,QAAI,CAAC,KAAK;AACR;AAAA,IACF;AACA,UAAM,QAAQ,MAAM;AAAA,MAClB,MAAM;AAAA,MACN,UAAU,IAAI,KAAK,IAAI,UAAU,EAAE,QAAQ;AAAA,MAC3C,QAAQ,IAAI,KAAK,IAAI,UAAU,EAAE,QAAQ;AAAA,MACzC,YAAY;AAAA,QACV,IAAI,IAAI;AAAA,QACR,eAAe,IAAI;AAAA,QACnB,YAAY,IAAI,cAAc;AAAA,QAC9B,QAAQ,IAAI;AAAA,QACZ,QAAQ,IAAI,eAAe;AAAA,QAC3B,OAAO,IAAI,OAAO,SAAS;AAAA,QAC3B,aAAa,IAAI;AAAA,MACnB;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,MAAc,sBACZ,SACA,OACA,MACA,MACe;AACf,QAAI,SAAS,QAAQ,SAAS,GAAG;AAC/B,YAAM,QAAQ,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,cAAc,EAAE,CAAC;AACpD,WAAK,mBAAmB,MAAM;AAAA,IAChC;AACA,UAAM,aAAa;AAAA,MACjB;AAAA,MACA,CAAC,QAAQ,OAAO,IAAI,EAAE;AAAA,MACtB;AAAA,IACF;AACA,QAAI,sBAAsB;AAC1B,UAAM,OAA4C,CAAC;AACnD,eAAW,OAAO,YAAY;AAC5B,YAAM,MAAM,OAAO,IAAI,EAAE;AACzB,UAAI,KAAK,mBAAmB,IAAI,GAAG,GAAG;AACpC;AACA;AAAA,MACF;AACA,WAAK,mBAAmB,IAAI,GAAG;AAC/B,WAAK,KAAK,GAAG;AAAA,IACf;AACA,QAAI,sBAAsB,GAAG;AAC3B,cAAQ;AAAA,QACN,2CAA2C,mBAAmB;AAAA,MAChE;AAAA,IACF;AACA,eAAW,OAAO,MAAM;AACtB,YAAM,QAAQ,MAAM;AAAA,QAClB,MAAM;AAAA,QACN,UAAU,IAAI,KAAK,IAAI,UAAU,EAAE,QAAQ;AAAA,QAC3C,QAAQ,IAAI,KAAK,IAAI,UAAU,EAAE,QAAQ;AAAA,QACzC,YAAY;AAAA,UACV,IAAI,IAAI;AAAA,UACR,eAAe,IAAI;AAAA,UACnB,YAAY,IAAI,cAAc;AAAA,UAC9B,QAAQ,IAAI;AAAA,UACZ,QAAQ,IAAI,eAAe;AAAA,UAC3B,OAAO,IAAI,OAAO,SAAS;AAAA,UAC3B,aAAa,IAAI;AAAA,QACnB;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEA,MAAc,kBACZ,SACA,OACA,MACA,MACA,SACe;AACf,UAAM,iBAAiB,KAAK;AAAA,MAC1B;AAAA,MACA;AAAA,IACF;AACA,QAAI,SAAS,QAAQ,SAAS,GAAG;AAC/B,YAAM,QAAQ,SAAS,CAAC,GAAG,EAAE,OAAO,CAAC,cAAc,EAAE,CAAC;AACtD,UAAI,gBAAgB;AAClB,cAAM,QAAQ,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,aAAa,EAAE,CAAC;AAAA,MACpD;AAAA,IACF;AACA,UAAM,YAAY;AAClB,eAAW,EAAE,KAAK,QAAQ,YAAY,KAAK,WAAW;AACpD,YAAM,MAAM;AAAA,QACV;AAAA,QACA,CAAC,OAAO,OAAO,GAAG,MAAM;AAAA,QACxB;AAAA,MACF;AACA,iBAAW,MAAM,KAAK;AACpB,cAAM,QAAQ,OAAO;AAAA,UACnB,MAAM;AAAA,UACN,IAAI,OAAO,GAAG,MAAM;AAAA,UACpB,YAAY;AAAA,YACV,OAAO,GAAG;AAAA,YACV,OAAO,GAAG;AAAA,YACV,OAAO,GAAG;AAAA,YACV,QAAQ,GAAG,KAAK;AAAA,YAChB,YAAY,IAAI,KAAK,GAAG,UAAU,EAAE,QAAQ;AAAA,UAC9C;AAAA,UACA,YAAY,IAAI,KAAK,GAAG,UAAU,EAAE,QAAQ;AAAA,QAC9C,CAAC;AAAA,MACH;AACA,UAAI,CAAC,gBAAgB;AACnB;AAAA,MACF;AACA,iBAAW,MAAM,KAAK;AACpB,cAAM,UAAU,YAAY,IAAI,GAAG,MAAM,KAAK,CAAC;AAC/C,mBAAW,UAAU,SAAS;AAC5B,cAAI,CAAC,OAAO,MAAM;AAChB;AAAA,UACF;AACA,gBAAM,QAAQ,KAAK;AAAA,YACjB,WAAW;AAAA,YACX,SAAS,OAAO,GAAG,MAAM;AAAA,YACzB,MAAM;AAAA,YACN,SAAS;AAAA,YACT,OAAO,OAAO,KAAK;AAAA,YACnB,YAAY,EAAE,OAAO,OAAO,MAAM;AAAA,YAClC,YAAY,IAAI,KAAK,OAAO,YAAY,EAAE,QAAQ;AAAA,UACpD,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAc,YACZ,SACA,OACA,MACA,MACe;AACf,QAAI,SAAS,QAAQ,SAAS,GAAG;AAC/B,YAAM,QAAQ,SAAS,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC;AAAA,IACjD;AACA,UAAM,SAAS;AAAA,MACZ,MAAwB,OAAO,CAAC,MAAM,EAAE,iBAAiB,MAAS;AAAA,MACnE,CAAC,UAAU,OAAO,MAAM,MAAM;AAAA,MAC9B;AAAA,IACF;AACA,eAAW,SAAS,QAAQ;AAC1B,YAAM,QAAQ,OAAO;AAAA,QACnB,MAAM;AAAA,QACN,IAAI,OAAO,MAAM,MAAM;AAAA,QACvB,YAAY;AAAA,UACV,QAAQ,MAAM;AAAA,UACd,OAAO,MAAM;AAAA,UACb,OAAO,MAAM;AAAA,UACb,QAAQ,MAAM,OAAO,IAAI,CAAC,MAAM,EAAE,IAAI;AAAA,UACtC,WAAW,MAAM,UAAU,IAAI,CAAC,MAAM,EAAE,KAAK;AAAA,UAC7C,QAAQ,MAAM,KAAK;AAAA,UACnB,YAAY,IAAI,KAAK,MAAM,UAAU,EAAE,QAAQ;AAAA,UAC/C,YAAY,IAAI,KAAK,MAAM,UAAU,EAAE,QAAQ;AAAA,UAC/C,WAAW,MAAM,YACb,IAAI,KAAK,MAAM,SAAS,EAAE,QAAQ,IAClC;AAAA,QACN;AAAA,QACA,YAAY,IAAI,KAAK,MAAM,UAAU,EAAE,QAAQ;AAAA,MACjD,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEA,MAAc,iBACZ,SACA,OACA,MACA,MACA,SACe;AACf,UAAM,kBAAkB,KAAK;AAAA,MAC3B;AAAA,MACA;AAAA,IACF;AACA,QAAI,SAAS,QAAQ,SAAS,GAAG;AAC/B,UAAI,CAAC,iBAAiB;AACpB,cAAM,WAAW,MAAM,QAAQ,cAAc,EAAE,MAAM,aAAa,CAAC;AACnE,mBAAW,UAAU,UAAU;AAC7B,gBAAM,OAAO,OAAO,WAAW,eAAe;AAC9C,cAAI,OAAO,SAAS,UAAU;AAC5B,iBAAK,0BAA0B,IAAI,OAAO,IAAI,IAAI;AAAA,UACpD;AAAA,QACF;AAAA,MACF;AACA,YAAM,QAAQ,SAAS,CAAC,GAAG,EAAE,OAAO,CAAC,YAAY,EAAE,CAAC;AAAA,IACtD;AACA,UAAM,YAAY;AAClB,eAAW,EAAE,aAAa,gBAAgB,iBAAiB,KAAK,WAAW;AACzE,YAAM,cAAc;AAAA,QAClB;AAAA,QACA,CAAC,MAAM,OAAO,EAAE,EAAE;AAAA,QAClB;AAAA,MACF;AACA,iBAAW,cAAc,aAAa;AACpC,cAAM,YAAY,IAAI,KAAK,WAAW,UAAU,EAAE,QAAQ;AAC1D,YAAI;AACJ,YAAI,kBAAiC;AACrC,YAAI,iBAAiB;AACnB,gBAAM,SAAS,iBAAiB,IAAI,WAAW,EAAE,KAAK;AACtD,yBAAe,QAAQ,SAAS;AAChC,4BAAkB,QAAQ,aACtB,IAAI,KAAK,OAAO,UAAU,EAAE,QAAQ,IACpC;AAAA,QACN,OAAO;AACL,yBACE,KAAK,0BAA0B,IAAI,OAAO,WAAW,EAAE,CAAC,KACxD;AAAA,QACJ;AACA,cAAM,QAAQ,OAAO;AAAA,UACnB,MAAM;AAAA,UACN,IAAI,OAAO,WAAW,EAAE;AAAA,UACxB,YAAY;AAAA,YACV,aAAa,WAAW;AAAA,YACxB,KAAK,WAAW;AAAA,YAChB,KAAK,WAAW;AAAA,YAChB,SAAS,WAAW,SAAS,SAAS;AAAA,YACtC,YAAY;AAAA,YACZ,eAAe;AAAA,UACjB;AAAA,UACA,YAAY,KAAK,IAAI,WAAW,mBAAmB,CAAC;AAAA,QACtD,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAc,cACZ,SACA,OACA,MACA,MACe;AACf,QAAI,SAAS,QAAQ,SAAS,GAAG;AAC/B,YAAM,QAAQ,SAAS,CAAC,GAAG,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC;AAAA,IACnD;AACA,UAAM,WAAW;AAAA,MACf;AAAA,MACA,CAAC,MAAM,OAAO,EAAE,EAAE;AAAA,MAClB;AAAA,IACF;AACA,eAAW,WAAW,UAAU;AAC9B,YAAM,QAAQ,OAAO;AAAA,QACnB,MAAM;AAAA,QACN,IAAI,OAAO,QAAQ,EAAE;AAAA,QACrB,YAAY;AAAA,UACV,UAAU,QAAQ;AAAA,UAClB,MAAM,QAAQ,QAAQ;AAAA,UACtB,OAAO,QAAQ;AAAA,UACf,YAAY,QAAQ;AAAA,UACpB,YAAY,IAAI,KAAK,QAAQ,UAAU,EAAE,QAAQ;AAAA,UACjD,cAAc,QAAQ,eAClB,IAAI,KAAK,QAAQ,YAAY,EAAE,QAAQ,IACvC;AAAA,UACJ,QAAQ,QAAQ,OAAO;AAAA,QACzB;AAAA,QACA,YAAY,IAAI;AAAA,UACd,QAAQ,gBAAgB,QAAQ;AAAA,QAClC,EAAE,QAAQ;AAAA,MACZ,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEA,MAAc,kBACZ,SACA,OACA,MACe;AACf,QAAI,SAAS,MAAM;AACjB,YAAM,QAAQ,SAAS,CAAC,GAAG,EAAE,OAAO,CAAC,aAAa,EAAE,CAAC;AAAA,IACvD;AACA,UAAM,eAAe;AAAA,MACnB;AAAA,MACA,CAAC,MAAM,EAAE;AAAA,MACT;AAAA,IACF;AACA,UAAM,aAAa,KAAK,IAAI;AAC5B,eAAW,KAAK,cAAc;AAC5B,YAAM,QAAQ,OAAO;AAAA,QACnB,MAAM;AAAA,QACN,IAAI,EAAE;AAAA,QACN,YAAY,EAAE,SAAS,EAAE,cAAc;AAAA,QACvC,YAAY;AAAA,MACd,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEA,MAAM,KACJ,SACA,SACA,QACqB;AACrB,UAAM,SAAS,KAAK,cAAc,QAAQ,MAAM;AAChD,UAAM,SAAS,aAAa,QAAQ,SAAS;AAC7C,UAAM,YAAY,CAAC,UAAmC;AACpD,UAAI,QAAQ,SAAS,YAAY,mBAAmB,IAAI,KAAK,GAAG;AAC9D,eAAO;AAAA,MACT;AACA,aAAO,KAAK,iBAAiB,SAAS,gBAAgB,KAAK,EAAE,CAAC,CAAE,EAAE;AAAA,IACpE;AACA,UAAM,UAAU,CAAC,OAAwB,cACvC,KAAK,iBAAiB,SAAS,gBAAgB,KAAK,EAAE,CAAC,CAAE,EAAE,SAAS,KACpE,CAAC;AACH,UAAM,YAAY,CAChB,OACA,SAEA,KAAK,WAAW,SAAS,gBAAgB,KAAK,EAAE,CAAC,GAAI,MAAM,KAAK,IAAI,CAAC;AACvE,WAAO,gBAAyC;AAAA,MAC9C;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,QAAQ,KAAK;AAAA,MACb,WAAW,OAAO,OAAO,MAAM,KAAK,cAAc;AAChD,cAAM,OAAO,QAAQ,OAAO,SAAS;AACrC,gBAAQ,OAAO;AAAA,UACb,KAAK;AACH,mBAAO,KAAK,eAAe,GAAG;AAAA,UAChC,KAAK;AACH,mBAAO,QAAQ,SAAS,WACpB,KAAK,wBAAwB,GAAG,IAChC,KAAK;AAAA,cACH;AAAA,cACA;AAAA,cACA;AAAA,cACA,UAAU,OAAO,IAAI;AAAA,YACvB;AAAA,UACN,KAAK;AACH,mBAAO,KAAK;AAAA,cACV;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA,UAAU,OAAO,IAAI;AAAA,YACvB;AAAA,UACF,KAAK;AACH,mBAAO,KAAK,YAAY,MAAM,KAAK,MAAM,UAAU,OAAO,IAAI,CAAC;AAAA,UACjE,KAAK;AACH,mBAAO,KAAK;AAAA,cACV;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA,UAAU,OAAO,IAAI;AAAA,YACvB;AAAA,UACF,KAAK;AACH,mBAAO,KAAK,cAAc,MAAM,KAAK,UAAU,OAAO,IAAI,CAAC;AAAA,UAC7D,KAAK;AACH,mBAAO,KAAK,kBAAkB,MAAM,GAAG;AAAA,QAC3C;AAAA,MACF;AAAA,MACA,YAAY,OAAO,OAAO,OAAO,MAAM,cAAc;AACnD,gBAAQ,OAAO;AAAA,UACb,KAAK;AACH,mBAAO,KAAK,eAAe,SAAS,KAAK;AAAA,UAC3C,KAAK;AACH,mBAAO,QAAQ,SAAS,WACpB,KAAK,wBAAwB,SAAS,KAAK,IAC3C,KAAK,sBAAsB,SAAS,OAAO,MAAM,SAAS;AAAA,UAChE,KAAK;AACH,mBAAO,KAAK;AAAA,cACV;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,YACF;AAAA,UACF,KAAK;AACH,mBAAO,KAAK,YAAY,SAAS,OAAO,MAAM,SAAS;AAAA,UACzD,KAAK;AACH,mBAAO,KAAK;AAAA,cACV;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,YACF;AAAA,UACF,KAAK;AACH,mBAAO,KAAK,cAAc,SAAS,OAAO,MAAM,SAAS;AAAA,UAC3D,KAAK;AACH,mBAAO,KAAK,kBAAkB,SAAS,OAAO,IAAI;AAAA,QACtD;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AACF;;;AC95CA,IAAO,gBAAQ;","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rawdash/connector-github",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.28.2",
|
|
4
4
|
"description": "Rawdash connector for GitHub",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -24,15 +24,15 @@
|
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"zod": "^4.4.3",
|
|
27
|
-
"@rawdash/core": "0.
|
|
27
|
+
"@rawdash/core": "0.28.2"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
30
|
"fast-check": "^4.8.0",
|
|
31
31
|
"tsup": "^8.0.0",
|
|
32
32
|
"typescript": "^5.7.2",
|
|
33
33
|
"vitest": "^4.1.4",
|
|
34
|
-
"@rawdash/connector-
|
|
35
|
-
"@rawdash/connector-
|
|
34
|
+
"@rawdash/connector-shared": "0.3.1",
|
|
35
|
+
"@rawdash/connector-test-utils": "0.0.10"
|
|
36
36
|
},
|
|
37
37
|
"scripts": {
|
|
38
38
|
"build": "tsup",
|