github-issue-tower-defence-management 1.35.1 → 1.36.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +23 -0
- package/bin/adapter/entry-points/handlers/GetStoryObjectMapUseCaseHandler.js +1 -27
- package/bin/adapter/entry-points/handlers/GetStoryObjectMapUseCaseHandler.js.map +1 -1
- package/bin/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.js +1 -27
- package/bin/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.js.map +1 -1
- package/bin/adapter/repositories/BaseGitHubRepository.js +7 -9
- package/bin/adapter/repositories/BaseGitHubRepository.js.map +1 -1
- package/bin/adapter/repositories/CheerioProjectRepository.js +11 -11
- package/bin/adapter/repositories/CheerioProjectRepository.js.map +1 -1
- package/bin/adapter/repositories/FetchWebhookRepository.js +5 -1
- package/bin/adapter/repositories/FetchWebhookRepository.js.map +1 -1
- package/bin/adapter/repositories/GraphqlProjectRepository.js +14 -16
- package/bin/adapter/repositories/GraphqlProjectRepository.js.map +1 -1
- package/bin/adapter/repositories/KySlackRepository.js +212 -0
- package/bin/adapter/repositories/KySlackRepository.js.map +1 -0
- package/bin/adapter/repositories/issue/ApiV3IssueRepository.js +11 -13
- package/bin/adapter/repositories/issue/ApiV3IssueRepository.js.map +1 -1
- package/bin/adapter/repositories/issue/CheerioIssueRepository.js +2 -3
- package/bin/adapter/repositories/issue/CheerioIssueRepository.js.map +1 -1
- package/bin/adapter/repositories/issue/GraphqlProjectItemRepository.js +47 -63
- package/bin/adapter/repositories/issue/GraphqlProjectItemRepository.js.map +1 -1
- package/bin/adapter/repositories/issue/InternalGraphqlIssueRepository.js +12 -8
- package/bin/adapter/repositories/issue/InternalGraphqlIssueRepository.js.map +1 -1
- package/bin/adapter/repositories/issue/RestIssueRepository.js +36 -69
- package/bin/adapter/repositories/issue/RestIssueRepository.js.map +1 -1
- package/jest.config.js +2 -1
- package/package.json +2 -3
- package/src/adapter/entry-points/handlers/GetStoryObjectMapUseCaseHandler.test.ts +0 -78
- package/src/adapter/entry-points/handlers/GetStoryObjectMapUseCaseHandler.ts +1 -33
- package/src/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.test.ts +0 -78
- package/src/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.ts +1 -33
- package/src/adapter/repositories/BaseGitHubRepository.test.ts +141 -0
- package/src/adapter/repositories/BaseGitHubRepository.ts +10 -10
- package/src/adapter/repositories/CheerioProjectRepository.ts +19 -23
- package/src/adapter/repositories/FetchWebhookRepository.ts +2 -1
- package/src/adapter/repositories/GraphqlProjectRepository.ts +63 -69
- package/src/adapter/repositories/{AxiosSlackRepository.test.ts → KySlackRepository.test.ts} +4 -4
- package/src/adapter/repositories/KySlackRepository.ts +297 -0
- package/src/adapter/repositories/issue/ApiV3IssueRepository.ts +31 -33
- package/src/adapter/repositories/issue/CheerioIssueRepository.test.ts +3 -3
- package/src/adapter/repositories/issue/CheerioIssueRepository.ts +2 -3
- package/src/adapter/repositories/issue/GraphqlProjectItemRepository.test.ts +30 -22
- package/src/adapter/repositories/issue/GraphqlProjectItemRepository.ts +178 -191
- package/src/adapter/repositories/issue/InternalGraphqlIssueRepository.ts +12 -8
- package/src/adapter/repositories/issue/RestIssueRepository.ts +51 -91
- package/types/adapter/entry-points/function/getStoryObjectMap.d.ts +1 -1
- package/types/adapter/entry-points/handlers/GetStoryObjectMapUseCaseHandler.d.ts +1 -1
- package/types/adapter/entry-points/handlers/GetStoryObjectMapUseCaseHandler.d.ts.map +1 -1
- package/types/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.d.ts +1 -1
- package/types/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.d.ts.map +1 -1
- package/types/adapter/repositories/BaseGitHubRepository.d.ts +1 -1
- package/types/adapter/repositories/BaseGitHubRepository.d.ts.map +1 -1
- package/types/adapter/repositories/CheerioProjectRepository.d.ts.map +1 -1
- package/types/adapter/repositories/FetchWebhookRepository.d.ts.map +1 -1
- package/types/adapter/repositories/GraphqlProjectRepository.d.ts.map +1 -1
- package/types/adapter/repositories/{AxiosSlackRepository.d.ts → KySlackRepository.d.ts} +3 -2
- package/types/adapter/repositories/KySlackRepository.d.ts.map +1 -0
- package/types/adapter/repositories/issue/ApiV3IssueRepository.d.ts.map +1 -1
- package/types/adapter/repositories/issue/CheerioIssueRepository.d.ts.map +1 -1
- package/types/adapter/repositories/issue/GraphqlProjectItemRepository.d.ts.map +1 -1
- package/types/adapter/repositories/issue/InternalGraphqlIssueRepository.d.ts.map +1 -1
- package/types/adapter/repositories/issue/RestIssueRepository.d.ts.map +1 -1
- package/types/index.d.ts +1 -1
- package/bin/adapter/repositories/AxiosSlackRepository.js +0 -188
- package/bin/adapter/repositories/AxiosSlackRepository.js.map +0 -1
- package/src/adapter/repositories/AxiosSlackRepository.ts +0 -218
- package/types/adapter/repositories/AxiosSlackRepository.d.ts.map +0 -1
|
@@ -1,24 +1,32 @@
|
|
|
1
|
-
|
|
1
|
+
const mockPost = jest.fn();
|
|
2
|
+
|
|
3
|
+
jest.mock('ky', () => ({
|
|
4
|
+
default: {
|
|
5
|
+
post: mockPost,
|
|
6
|
+
get: jest.fn(),
|
|
7
|
+
put: jest.fn(),
|
|
8
|
+
patch: jest.fn(),
|
|
9
|
+
delete: jest.fn(),
|
|
10
|
+
extend: jest.fn(),
|
|
11
|
+
create: jest.fn(),
|
|
12
|
+
stop: jest.fn(),
|
|
13
|
+
},
|
|
14
|
+
__esModule: true,
|
|
15
|
+
}));
|
|
16
|
+
|
|
2
17
|
import {
|
|
3
18
|
GraphqlProjectItemRepository,
|
|
4
19
|
PAGINATION_DELAY_MS,
|
|
5
20
|
} from './GraphqlProjectItemRepository';
|
|
6
21
|
import { LocalStorageRepository } from '../LocalStorageRepository';
|
|
7
22
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const toAxiosResponse = <T>(data: T): AxiosResponse<T> => ({
|
|
12
|
-
data,
|
|
13
|
-
status: 200,
|
|
14
|
-
statusText: 'OK',
|
|
15
|
-
headers: {},
|
|
16
|
-
config: { headers: new AxiosHeaders() },
|
|
23
|
+
const mockJsonResponse = <T>(data: T) => ({
|
|
24
|
+
json: jest.fn().mockResolvedValue(data),
|
|
17
25
|
});
|
|
18
26
|
|
|
19
27
|
describe('GraphqlProjectItemRepository', () => {
|
|
20
28
|
const makePageResponse = (hasNextPage: boolean, endCursor: string) =>
|
|
21
|
-
|
|
29
|
+
mockJsonResponse({
|
|
22
30
|
data: {
|
|
23
31
|
node: {
|
|
24
32
|
items: {
|
|
@@ -64,7 +72,7 @@ describe('GraphqlProjectItemRepository', () => {
|
|
|
64
72
|
|
|
65
73
|
afterEach(() => {
|
|
66
74
|
jest.useRealTimers();
|
|
67
|
-
|
|
75
|
+
mockPost.mockClear();
|
|
68
76
|
});
|
|
69
77
|
|
|
70
78
|
it('should sleep between paginated requests to avoid 403', async () => {
|
|
@@ -76,15 +84,15 @@ describe('GraphqlProjectItemRepository', () => {
|
|
|
76
84
|
);
|
|
77
85
|
|
|
78
86
|
const setTimeoutSpy = jest.spyOn(global, 'setTimeout');
|
|
79
|
-
|
|
80
|
-
.
|
|
81
|
-
.
|
|
87
|
+
mockPost
|
|
88
|
+
.mockReturnValueOnce(makePageResponse(true, 'cursor-1'))
|
|
89
|
+
.mockReturnValueOnce(makePageResponse(false, 'cursor-2'));
|
|
82
90
|
|
|
83
91
|
const resultPromise = repository.fetchProjectItems('test-project-id');
|
|
84
92
|
await jest.advanceTimersByTimeAsync(PAGINATION_DELAY_MS);
|
|
85
93
|
const result = await resultPromise;
|
|
86
94
|
|
|
87
|
-
expect(
|
|
95
|
+
expect(mockPost).toHaveBeenCalledTimes(2);
|
|
88
96
|
expect(result).toHaveLength(2);
|
|
89
97
|
expect(setTimeoutSpy).toHaveBeenCalledWith(
|
|
90
98
|
expect.any(Function),
|
|
@@ -102,11 +110,11 @@ describe('GraphqlProjectItemRepository', () => {
|
|
|
102
110
|
);
|
|
103
111
|
|
|
104
112
|
const setTimeoutSpy = jest.spyOn(global, 'setTimeout');
|
|
105
|
-
|
|
113
|
+
mockPost.mockReturnValueOnce(makePageResponse(false, 'cursor-1'));
|
|
106
114
|
|
|
107
115
|
const result = await repository.fetchProjectItems('test-project-id');
|
|
108
116
|
|
|
109
|
-
expect(
|
|
117
|
+
expect(mockPost).toHaveBeenCalledTimes(1);
|
|
110
118
|
expect(result).toHaveLength(1);
|
|
111
119
|
expect(setTimeoutSpy).not.toHaveBeenCalledWith(
|
|
112
120
|
expect.any(Function),
|
|
@@ -118,7 +126,7 @@ describe('GraphqlProjectItemRepository', () => {
|
|
|
118
126
|
|
|
119
127
|
describe('getProjectItemFields', () => {
|
|
120
128
|
afterEach(() => {
|
|
121
|
-
|
|
129
|
+
mockPost.mockClear();
|
|
122
130
|
});
|
|
123
131
|
|
|
124
132
|
it('should return project item fields', async () => {
|
|
@@ -129,8 +137,8 @@ describe('GraphqlProjectItemRepository', () => {
|
|
|
129
137
|
'dummy-token',
|
|
130
138
|
);
|
|
131
139
|
|
|
132
|
-
|
|
133
|
-
|
|
140
|
+
mockPost.mockReturnValueOnce(
|
|
141
|
+
mockJsonResponse({
|
|
134
142
|
data: {
|
|
135
143
|
repository: {
|
|
136
144
|
issue: {
|
|
@@ -163,7 +171,7 @@ describe('GraphqlProjectItemRepository', () => {
|
|
|
163
171
|
|
|
164
172
|
const result = await repository.getProjectItemFields('owner', 'repo', 1);
|
|
165
173
|
|
|
166
|
-
expect(
|
|
174
|
+
expect(mockPost).toHaveBeenCalledTimes(1);
|
|
167
175
|
expect(result).toEqual([
|
|
168
176
|
{
|
|
169
177
|
fieldName: 'NextActionDate',
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import ky from 'ky';
|
|
2
2
|
import { BaseGitHubRepository } from '../BaseGitHubRepository';
|
|
3
3
|
import { Project } from '../../../domain/entities/Project';
|
|
4
4
|
import { Issue } from '../../../domain/entities/Issue';
|
|
@@ -50,33 +50,32 @@ export class GraphqlProjectItemRepository extends BaseGitHubRepository {
|
|
|
50
50
|
};
|
|
51
51
|
|
|
52
52
|
try {
|
|
53
|
-
const response = await
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
53
|
+
const response = await ky
|
|
54
|
+
.post('https://api.github.com/graphql', {
|
|
55
|
+
json: graphqlQuery,
|
|
56
|
+
headers: {
|
|
57
|
+
Authorization: `Bearer ${this.ghToken}`,
|
|
58
|
+
},
|
|
59
|
+
})
|
|
60
|
+
.json<{
|
|
61
|
+
data: {
|
|
62
|
+
repository: {
|
|
63
|
+
issue: {
|
|
64
|
+
projectItems: {
|
|
65
|
+
nodes: {
|
|
66
|
+
id: string;
|
|
67
|
+
project: { id: string };
|
|
68
|
+
}[];
|
|
69
|
+
};
|
|
62
70
|
};
|
|
63
71
|
};
|
|
64
72
|
};
|
|
65
|
-
};
|
|
66
|
-
}>({
|
|
67
|
-
url: 'https://api.github.com/graphql',
|
|
68
|
-
method: 'post',
|
|
69
|
-
headers: {
|
|
70
|
-
Authorization: `Bearer ${this.ghToken}`,
|
|
71
|
-
'Content-Type': 'application/json',
|
|
72
|
-
},
|
|
73
|
-
data: JSON.stringify(graphqlQuery),
|
|
74
|
-
});
|
|
73
|
+
}>();
|
|
75
74
|
|
|
76
75
|
const projectItems: {
|
|
77
76
|
id: string;
|
|
78
77
|
project: { id: string };
|
|
79
|
-
}[] = response.data.
|
|
78
|
+
}[] = response.data.repository.issue.projectItems.nodes;
|
|
80
79
|
const projectItemId = projectItems.find(
|
|
81
80
|
(item) => item.project.id === projectId,
|
|
82
81
|
)?.id;
|
|
@@ -240,56 +239,55 @@ query GetProjectItems($projectId: ID!, $after: String) {
|
|
|
240
239
|
after: after,
|
|
241
240
|
},
|
|
242
241
|
};
|
|
243
|
-
const response = await
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
date: string;
|
|
260
|
-
field: {
|
|
261
|
-
name: string;
|
|
262
|
-
};
|
|
263
|
-
}[];
|
|
264
|
-
};
|
|
265
|
-
content: {
|
|
266
|
-
repository: { nameWithOwner: string };
|
|
267
|
-
number: number;
|
|
268
|
-
title: string;
|
|
269
|
-
state: string;
|
|
270
|
-
url: string;
|
|
271
|
-
body: string;
|
|
272
|
-
createdAt: string;
|
|
273
|
-
labels: { nodes: { name: string }[] };
|
|
274
|
-
assignees: { nodes: { login: string }[] };
|
|
242
|
+
const response = await ky
|
|
243
|
+
.post('https://api.github.com/graphql', {
|
|
244
|
+
json: graphqlQuery,
|
|
245
|
+
headers: {
|
|
246
|
+
Authorization: `Bearer ${this.ghToken}`,
|
|
247
|
+
},
|
|
248
|
+
})
|
|
249
|
+
.json<{
|
|
250
|
+
data: {
|
|
251
|
+
node: {
|
|
252
|
+
items: {
|
|
253
|
+
totalCount: number;
|
|
254
|
+
pageInfo: {
|
|
255
|
+
endCursor: string;
|
|
256
|
+
startCursor: string;
|
|
257
|
+
hasNextPage: boolean;
|
|
275
258
|
};
|
|
276
|
-
|
|
259
|
+
nodes: {
|
|
260
|
+
id: string;
|
|
261
|
+
fieldValues: {
|
|
262
|
+
nodes: {
|
|
263
|
+
text: string;
|
|
264
|
+
number: number;
|
|
265
|
+
date: string;
|
|
266
|
+
field: {
|
|
267
|
+
name: string;
|
|
268
|
+
};
|
|
269
|
+
}[];
|
|
270
|
+
};
|
|
271
|
+
content: {
|
|
272
|
+
repository: { nameWithOwner: string };
|
|
273
|
+
number: number;
|
|
274
|
+
title: string;
|
|
275
|
+
state: string;
|
|
276
|
+
url: string;
|
|
277
|
+
body: string;
|
|
278
|
+
createdAt: string;
|
|
279
|
+
labels: { nodes: { name: string }[] };
|
|
280
|
+
assignees: { nodes: { login: string }[] };
|
|
281
|
+
};
|
|
282
|
+
}[];
|
|
283
|
+
};
|
|
277
284
|
};
|
|
278
285
|
};
|
|
279
|
-
};
|
|
280
|
-
|
|
281
|
-
url: 'https://api.github.com/graphql',
|
|
282
|
-
method: 'post',
|
|
283
|
-
headers: {
|
|
284
|
-
Authorization: `Bearer ${this.ghToken}`,
|
|
285
|
-
'Content-Type': 'application/json',
|
|
286
|
-
},
|
|
287
|
-
data: JSON.stringify(graphqlQuery),
|
|
288
|
-
});
|
|
289
|
-
if (!response.data.data) {
|
|
286
|
+
}>();
|
|
287
|
+
if (!response.data) {
|
|
290
288
|
throw new Error('No data returned from GitHub API');
|
|
291
289
|
}
|
|
292
|
-
return response.data
|
|
290
|
+
return response.data;
|
|
293
291
|
};
|
|
294
292
|
const issues: ProjectItem[] = [];
|
|
295
293
|
let after: string | null = null;
|
|
@@ -458,40 +456,39 @@ query GetProjectFields($owner: String!, $repository: String!, $issueNumber: Int!
|
|
|
458
456
|
issueNumber: issueNumber,
|
|
459
457
|
},
|
|
460
458
|
};
|
|
461
|
-
const response = await
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
459
|
+
const response = await ky
|
|
460
|
+
.post('https://api.github.com/graphql', {
|
|
461
|
+
json: graphqlQuery,
|
|
462
|
+
headers: {
|
|
463
|
+
Authorization: `Bearer ${this.ghToken}`,
|
|
464
|
+
},
|
|
465
|
+
})
|
|
466
|
+
.json<{
|
|
467
|
+
data: {
|
|
468
|
+
repository: {
|
|
469
|
+
issue: {
|
|
470
|
+
projectItems: {
|
|
471
|
+
nodes: {
|
|
472
|
+
id: string;
|
|
473
|
+
fieldValues: {
|
|
474
|
+
nodes: {
|
|
475
|
+
__typename: string;
|
|
476
|
+
field: { name: string };
|
|
477
|
+
date: string;
|
|
478
|
+
name: string;
|
|
479
|
+
text: string;
|
|
480
|
+
repository: { name: string };
|
|
481
|
+
user: { login: string };
|
|
482
|
+
}[];
|
|
483
|
+
};
|
|
484
|
+
}[];
|
|
485
|
+
};
|
|
480
486
|
};
|
|
481
487
|
};
|
|
482
488
|
};
|
|
483
|
-
};
|
|
484
|
-
}>({
|
|
485
|
-
url: 'https://api.github.com/graphql',
|
|
486
|
-
method: 'post',
|
|
487
|
-
headers: {
|
|
488
|
-
Authorization: `Bearer ${this.ghToken}`,
|
|
489
|
-
'Content-Type': 'application/json',
|
|
490
|
-
},
|
|
491
|
-
data: JSON.stringify(graphqlQuery),
|
|
492
|
-
});
|
|
489
|
+
}>();
|
|
493
490
|
|
|
494
|
-
const data = response.data
|
|
491
|
+
const data = response.data;
|
|
495
492
|
const issueFields: {
|
|
496
493
|
fieldName: string;
|
|
497
494
|
fieldValue: string;
|
|
@@ -615,48 +612,47 @@ query GetProjectFields($owner: String!, $repository: String!, $issueNumber: Int!
|
|
|
615
612
|
number: issueNumber,
|
|
616
613
|
},
|
|
617
614
|
};
|
|
618
|
-
const response = await
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
615
|
+
const response = await ky
|
|
616
|
+
.post('https://api.github.com/graphql', {
|
|
617
|
+
json: graphqlQuery,
|
|
618
|
+
headers: {
|
|
619
|
+
Authorization: `Bearer ${this.ghToken}`,
|
|
620
|
+
},
|
|
621
|
+
})
|
|
622
|
+
.json<{
|
|
623
|
+
data: {
|
|
624
|
+
repository: {
|
|
625
|
+
issue: {
|
|
626
|
+
number: number;
|
|
627
|
+
title: string;
|
|
628
|
+
state: string;
|
|
629
|
+
url: string;
|
|
630
|
+
body: string;
|
|
631
|
+
createdAt: string;
|
|
632
|
+
labels: { nodes: { name: string }[] };
|
|
633
|
+
assignees: { nodes: { login: string }[] };
|
|
634
|
+
repository: { nameWithOwner: string };
|
|
635
|
+
projectItems: {
|
|
636
|
+
nodes: {
|
|
637
|
+
id: string;
|
|
638
|
+
fieldValues: {
|
|
639
|
+
nodes: {
|
|
640
|
+
text: string;
|
|
641
|
+
number: number;
|
|
642
|
+
date: string;
|
|
641
643
|
name: string;
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
644
|
+
field: {
|
|
645
|
+
name: string;
|
|
646
|
+
};
|
|
647
|
+
}[];
|
|
648
|
+
};
|
|
649
|
+
}[];
|
|
650
|
+
};
|
|
646
651
|
};
|
|
647
652
|
};
|
|
648
653
|
};
|
|
649
|
-
};
|
|
650
|
-
|
|
651
|
-
url: 'https://api.github.com/graphql',
|
|
652
|
-
method: 'post',
|
|
653
|
-
headers: {
|
|
654
|
-
Authorization: `Bearer ${this.ghToken}`,
|
|
655
|
-
'Content-Type': 'application/json',
|
|
656
|
-
},
|
|
657
|
-
data: JSON.stringify(graphqlQuery),
|
|
658
|
-
});
|
|
659
|
-
const data = response.data.data;
|
|
654
|
+
}>();
|
|
655
|
+
const data = response.data;
|
|
660
656
|
if (!data.repository.issue) {
|
|
661
657
|
return null;
|
|
662
658
|
}
|
|
@@ -738,26 +734,23 @@ query GetProjectFields($owner: String!, $repository: String!, $issueNumber: Int!
|
|
|
738
734
|
}`,
|
|
739
735
|
};
|
|
740
736
|
|
|
741
|
-
const res = await
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
737
|
+
const res = await ky
|
|
738
|
+
.post('https://api.github.com/graphql', {
|
|
739
|
+
json: graphqlQuery,
|
|
740
|
+
headers: {
|
|
741
|
+
Authorization: `Bearer ${this.ghToken}`,
|
|
742
|
+
},
|
|
743
|
+
})
|
|
744
|
+
.json<{
|
|
745
|
+
data: {
|
|
746
|
+
updateProjectV2ItemFieldValue: {
|
|
747
|
+
clientMutationId: string;
|
|
748
|
+
};
|
|
745
749
|
};
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
method: 'post',
|
|
751
|
-
headers: {
|
|
752
|
-
Authorization: `Bearer ${this.ghToken}`,
|
|
753
|
-
'Content-Type': 'application/json',
|
|
754
|
-
},
|
|
755
|
-
data: JSON.stringify(graphqlQuery),
|
|
756
|
-
});
|
|
757
|
-
if (res.status !== 200) {
|
|
758
|
-
throw new Error('Failed to update project field');
|
|
759
|
-
} else if (res.data.errors) {
|
|
760
|
-
throw new Error(res.data.errors.map((e) => e.message).join('\n'));
|
|
750
|
+
errors: { message: string }[];
|
|
751
|
+
}>();
|
|
752
|
+
if (res.errors) {
|
|
753
|
+
throw new Error(res.errors.map((e) => e.message).join('\n'));
|
|
761
754
|
}
|
|
762
755
|
};
|
|
763
756
|
|
|
@@ -778,26 +771,23 @@ query GetProjectFields($owner: String!, $repository: String!, $issueNumber: Int!
|
|
|
778
771
|
}`,
|
|
779
772
|
};
|
|
780
773
|
|
|
781
|
-
const res = await
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
774
|
+
const res = await ky
|
|
775
|
+
.post('https://api.github.com/graphql', {
|
|
776
|
+
json: graphqlQuery,
|
|
777
|
+
headers: {
|
|
778
|
+
Authorization: `Bearer ${this.ghToken}`,
|
|
779
|
+
},
|
|
780
|
+
})
|
|
781
|
+
.json<{
|
|
782
|
+
data: {
|
|
783
|
+
clearProjectV2ItemFieldValue: {
|
|
784
|
+
clientMutationId: string;
|
|
785
|
+
};
|
|
785
786
|
};
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
method: 'post',
|
|
791
|
-
headers: {
|
|
792
|
-
Authorization: `Bearer ${this.ghToken}`,
|
|
793
|
-
'Content-Type': 'application/json',
|
|
794
|
-
},
|
|
795
|
-
data: JSON.stringify(graphqlQuery),
|
|
796
|
-
});
|
|
797
|
-
if (res.status !== 200) {
|
|
798
|
-
throw new Error('Failed to clear project field');
|
|
799
|
-
} else if (res.data.errors) {
|
|
800
|
-
throw new Error(res.data.errors.map((e) => e.message).join('\n'));
|
|
787
|
+
errors: { message: string }[];
|
|
788
|
+
}>();
|
|
789
|
+
if (res.errors) {
|
|
790
|
+
throw new Error(res.errors.map((e) => e.message).join('\n'));
|
|
801
791
|
}
|
|
802
792
|
};
|
|
803
793
|
updateProjectTextField = async (
|
|
@@ -825,27 +815,24 @@ query GetProjectFields($owner: String!, $repository: String!, $issueNumber: Int!
|
|
|
825
815
|
},
|
|
826
816
|
};
|
|
827
817
|
|
|
828
|
-
const res = await
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
818
|
+
const res = await ky
|
|
819
|
+
.post('https://api.github.com/graphql', {
|
|
820
|
+
json: graphqlQuery,
|
|
821
|
+
headers: {
|
|
822
|
+
Authorization: `Bearer ${this.ghToken}`,
|
|
823
|
+
},
|
|
824
|
+
})
|
|
825
|
+
.json<{
|
|
826
|
+
data: {
|
|
827
|
+
deleteProjectV2Item: {
|
|
828
|
+
clientMutationId: string;
|
|
829
|
+
};
|
|
832
830
|
};
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
}>({
|
|
836
|
-
url: 'https://api.github.com/graphql',
|
|
837
|
-
method: 'post',
|
|
838
|
-
headers: {
|
|
839
|
-
Authorization: `Bearer ${this.ghToken}`,
|
|
840
|
-
'Content-Type': 'application/json',
|
|
841
|
-
},
|
|
842
|
-
data: JSON.stringify(graphqlQuery),
|
|
843
|
-
});
|
|
831
|
+
errors?: { message: string }[];
|
|
832
|
+
}>();
|
|
844
833
|
|
|
845
|
-
if (res.
|
|
846
|
-
throw new Error(
|
|
847
|
-
} else if (res.data.errors) {
|
|
848
|
-
throw new Error(res.data.errors.map((e) => e.message).join('\n'));
|
|
834
|
+
if (res.errors) {
|
|
835
|
+
throw new Error(res.errors.map((e) => e.message).join('\n'));
|
|
849
836
|
}
|
|
850
837
|
};
|
|
851
838
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import ky from 'ky';
|
|
2
2
|
import { BaseGitHubRepository } from '../BaseGitHubRepository';
|
|
3
3
|
import typia from 'typia';
|
|
4
4
|
import { Issue, IssueStatusTimeline } from './CheerioIssueRepository';
|
|
@@ -419,23 +419,27 @@ export class InternalGraphqlIssueRepository extends BaseGitHubRepository {
|
|
|
419
419
|
for (let i = 0; i < maxRetries; i++) {
|
|
420
420
|
try {
|
|
421
421
|
console.log(url);
|
|
422
|
-
const
|
|
422
|
+
const kyResponse = await ky.get(url, {
|
|
423
423
|
headers: headers,
|
|
424
|
-
|
|
424
|
+
throwHttpErrors: false,
|
|
425
425
|
});
|
|
426
|
-
if (!
|
|
426
|
+
if (!kyResponse.ok) {
|
|
427
|
+
throw new Error(`HTTP error ${kyResponse.status}`);
|
|
428
|
+
}
|
|
429
|
+
const rawResponse = await kyResponse.json<GraphqlResponse>();
|
|
430
|
+
if (!rawResponse?.data?.node?.frontTimelineItems) {
|
|
427
431
|
throw new Error(
|
|
428
432
|
`No frontTimelineItems found. URL: ${issueUrl}, Response: ${JSON.stringify(
|
|
429
|
-
|
|
433
|
+
rawResponse,
|
|
430
434
|
)}`,
|
|
431
435
|
);
|
|
432
436
|
}
|
|
433
437
|
await new Promise((resolve) => setTimeout(resolve, 2000));
|
|
434
|
-
return
|
|
438
|
+
return rawResponse.data.node.frontTimelineItems;
|
|
435
439
|
} catch (e) {
|
|
436
440
|
const statusCode =
|
|
437
|
-
|
|
438
|
-
? e.
|
|
441
|
+
e instanceof Error && e.message.startsWith('HTTP error ')
|
|
442
|
+
? parseInt(e.message.replace('HTTP error ', ''), 10)
|
|
439
443
|
: null;
|
|
440
444
|
const isRetryableError =
|
|
441
445
|
statusCode !== null && [500, 502, 503, 504].includes(statusCode);
|