github-issue-tower-defence-management 1.6.0 → 1.7.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 +7 -0
- package/bin/adapter/repositories/GraphqlProjectRepository.js +79 -1
- package/bin/adapter/repositories/GraphqlProjectRepository.js.map +1 -1
- package/package.json +1 -1
- package/src/adapter/repositories/GraphqlProjectRepository.test.ts +183 -4
- package/src/adapter/repositories/GraphqlProjectRepository.ts +119 -1
- package/types/adapter/repositories/GraphqlProjectRepository.d.ts +3 -0
- package/types/adapter/repositories/GraphqlProjectRepository.d.ts.map +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
# [1.7.0](https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management/compare/v1.6.0...v1.7.0) (2025-01-16)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* add methods to remove items from project ([#19](https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management/issues/19)) ([f5d067f](https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management/commit/f5d067fe5c0bf62562fbbe6d717a2183947a72a5))
|
|
7
|
+
|
|
1
8
|
# [1.6.0](https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management/compare/v1.5.0...v1.6.0) (2025-01-08)
|
|
2
9
|
|
|
3
10
|
|
|
@@ -45,10 +45,14 @@ class GraphqlProjectRepository extends BaseGitHubRepository_1.BaseGitHubReposito
|
|
|
45
45
|
},
|
|
46
46
|
data: JSON.stringify(graphqlQuery),
|
|
47
47
|
});
|
|
48
|
+
if (!response?.data?.data?.organization?.projectV2?.id &&
|
|
49
|
+
!response?.data?.data?.user?.projectV2?.id) {
|
|
50
|
+
throw new Error('Project or item not found');
|
|
51
|
+
}
|
|
48
52
|
const projectId = response.data.data.organization?.projectV2?.id ||
|
|
49
53
|
response.data.data.user?.projectV2?.id;
|
|
50
54
|
if (!projectId) {
|
|
51
|
-
throw new Error('
|
|
55
|
+
throw new Error('Project or item not found');
|
|
52
56
|
}
|
|
53
57
|
return projectId;
|
|
54
58
|
};
|
|
@@ -191,6 +195,80 @@ class GraphqlProjectRepository extends BaseGitHubRepository_1.BaseGitHubReposito
|
|
|
191
195
|
: null,
|
|
192
196
|
};
|
|
193
197
|
};
|
|
198
|
+
this.removeItemFromProject = async (projectId, itemId) => {
|
|
199
|
+
const graphqlQuery = {
|
|
200
|
+
query: `mutation removeItem($projectId: ID!, $itemId: ID!) {
|
|
201
|
+
deleteProjectV2Item(input: { projectId: $projectId, itemId: $itemId }) {
|
|
202
|
+
clientMutationId
|
|
203
|
+
}
|
|
204
|
+
}`,
|
|
205
|
+
variables: {
|
|
206
|
+
projectId,
|
|
207
|
+
itemId,
|
|
208
|
+
},
|
|
209
|
+
};
|
|
210
|
+
const response = await (0, axios_1.default)({
|
|
211
|
+
url: 'https://api.github.com/graphql',
|
|
212
|
+
method: 'post',
|
|
213
|
+
headers: {
|
|
214
|
+
Authorization: `Bearer ${this.ghToken}`,
|
|
215
|
+
'Content-Type': 'application/json',
|
|
216
|
+
},
|
|
217
|
+
data: JSON.stringify(graphqlQuery),
|
|
218
|
+
});
|
|
219
|
+
if (response?.data?.errors || !response?.data?.data?.deleteProjectV2Item) {
|
|
220
|
+
throw new Error('Project or item not found');
|
|
221
|
+
}
|
|
222
|
+
};
|
|
223
|
+
this.removeItemFromProjectByIssueUrl = async (projectUrl, issueUrl) => {
|
|
224
|
+
const projectId = await this.findProjectIdByUrl(projectUrl);
|
|
225
|
+
if (!projectId) {
|
|
226
|
+
throw new Error('Project or item not found');
|
|
227
|
+
}
|
|
228
|
+
const itemId = await this.fetchItemIdFromIssueUrl(projectId, issueUrl);
|
|
229
|
+
if (!itemId) {
|
|
230
|
+
throw new Error('Project or item not found');
|
|
231
|
+
}
|
|
232
|
+
await this.removeItemFromProject(projectId, itemId);
|
|
233
|
+
};
|
|
234
|
+
this.fetchItemIdFromIssueUrl = async (projectId, issueUrl) => {
|
|
235
|
+
if (!projectId) {
|
|
236
|
+
throw new Error('Project ID is required');
|
|
237
|
+
}
|
|
238
|
+
const { owner, repo, issueNumber } = this.extractIssueFromUrl(issueUrl);
|
|
239
|
+
const graphqlQuery = {
|
|
240
|
+
query: `query GetProjectItemID($owner: String!, $name: String!, $issueNumber: Int!) {
|
|
241
|
+
repository(owner: $owner, name: $name) {
|
|
242
|
+
issue(number: $issueNumber) {
|
|
243
|
+
projectItems(first: 2) {
|
|
244
|
+
nodes {
|
|
245
|
+
id
|
|
246
|
+
project {
|
|
247
|
+
id
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}`,
|
|
254
|
+
variables: {
|
|
255
|
+
owner,
|
|
256
|
+
name: repo,
|
|
257
|
+
issueNumber,
|
|
258
|
+
},
|
|
259
|
+
};
|
|
260
|
+
const response = await (0, axios_1.default)({
|
|
261
|
+
url: 'https://api.github.com/graphql',
|
|
262
|
+
method: 'post',
|
|
263
|
+
headers: {
|
|
264
|
+
Authorization: `Bearer ${this.ghToken}`,
|
|
265
|
+
'Content-Type': 'application/json',
|
|
266
|
+
},
|
|
267
|
+
data: JSON.stringify(graphqlQuery),
|
|
268
|
+
});
|
|
269
|
+
const projectItems = response.data.data.repository.issue.projectItems.nodes;
|
|
270
|
+
return projectItems.find((item) => item.project.id === projectId)?.id;
|
|
271
|
+
};
|
|
194
272
|
}
|
|
195
273
|
}
|
|
196
274
|
exports.GraphqlProjectRepository = GraphqlProjectRepository;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GraphqlProjectRepository.js","sourceRoot":"","sources":["../../../src/adapter/repositories/GraphqlProjectRepository.ts"],"names":[],"mappings":";;;;;;AAAA,kDAA0B;AAC1B,iEAA8D;AAG9D,mCAA6C;AAE7C,MAAa,wBACX,SAAQ,2CAAoB;IAD9B;;QAIE,0BAAqB,GAAG,CACtB,UAAkB,EAIlB,EAAE;YACF,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC;YAChC,MAAM,IAAI,GAAG,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACrC,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;YACtB,MAAM,aAAa,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAC5C,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC;QAClC,CAAC,CAAC;QACF,mBAAc,GAAG,KAAK,EACpB,KAAa,EACb,aAAqB,EACJ,EAAE;YACnB,MAAM,YAAY,GAAG;gBACnB,KAAK,EAAE;;;;;;;;;;;EAWX;gBACI,SAAS,EAAE;oBACT,KAAK,EAAE,KAAK;oBACZ,MAAM,EAAE,aAAa;iBACtB;aACF,CAAC;YAEF,MAAM,QAAQ,GAAG,MAAM,IAAA,eAAK,EAazB;gBACD,GAAG,EAAE,gCAAgC;gBACrC,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACP,aAAa,EAAE,UAAU,IAAI,CAAC,OAAO,EAAE;oBACvC,cAAc,EAAE,kBAAkB;iBACnC;gBACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC;aACnC,CAAC,CAAC;YAEH,MAAM,SAAS,GACb,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,SAAS,EAAE,EAAE;gBAC9C,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,EAAE,CAAC;YACzC,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,MAAM,IAAI,KAAK,CAAC,
|
|
1
|
+
{"version":3,"file":"GraphqlProjectRepository.js","sourceRoot":"","sources":["../../../src/adapter/repositories/GraphqlProjectRepository.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { GraphqlProjectRepository } from './GraphqlProjectRepository';
|
|
2
2
|
import { LocalStorageRepository } from './LocalStorageRepository';
|
|
3
|
+
import axios from 'axios';
|
|
4
|
+
|
|
5
|
+
jest.mock('axios');
|
|
6
|
+
const mockedAxios = jest.mocked(axios);
|
|
3
7
|
|
|
4
8
|
describe('GraphqlProjectRepository', () => {
|
|
5
9
|
const localStorageRepository = new LocalStorageRepository();
|
|
@@ -9,28 +13,92 @@ describe('GraphqlProjectRepository', () => {
|
|
|
9
13
|
const projectUrl = `https://github.com/users/HiromiShikata/projects/49`;
|
|
10
14
|
const projectNumber = 49;
|
|
11
15
|
const projectId = 'PVT_kwHOAGJHa84AFhgF';
|
|
16
|
+
const itemId = 'PVTI_lAHOAGJHa84AFhgFzgM';
|
|
12
17
|
|
|
13
18
|
beforeEach(() => {
|
|
19
|
+
mockedAxios.post.mockReset();
|
|
14
20
|
repository = new GraphqlProjectRepository(localStorageRepository, token);
|
|
15
21
|
});
|
|
16
22
|
|
|
17
23
|
describe('fetchProjectId', () => {
|
|
18
24
|
it('should fetch project ID using GraphQL API', async () => {
|
|
19
|
-
|
|
25
|
+
mockedAxios.post.mockResolvedValueOnce({
|
|
26
|
+
data: {
|
|
27
|
+
data: {
|
|
28
|
+
organization: null,
|
|
29
|
+
user: null,
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
});
|
|
20
33
|
|
|
21
|
-
expect(
|
|
34
|
+
await expect(
|
|
35
|
+
repository.fetchProjectId(login, projectNumber),
|
|
36
|
+
).rejects.toThrow('Project or item not found');
|
|
22
37
|
});
|
|
23
38
|
});
|
|
24
39
|
|
|
25
40
|
describe('findProjectIdByUrl', () => {
|
|
26
41
|
it('should extract project ID from URL and fetch it', async () => {
|
|
27
|
-
|
|
28
|
-
|
|
42
|
+
mockedAxios.post.mockResolvedValueOnce({
|
|
43
|
+
data: {
|
|
44
|
+
data: {
|
|
45
|
+
organization: null,
|
|
46
|
+
user: null,
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
await expect(repository.findProjectIdByUrl(projectUrl)).rejects.toThrow(
|
|
52
|
+
'Project or item not found',
|
|
53
|
+
);
|
|
29
54
|
});
|
|
30
55
|
});
|
|
31
56
|
|
|
32
57
|
describe('getProject', () => {
|
|
33
58
|
it('should retrieve project details', async () => {
|
|
59
|
+
mockedAxios.post.mockResolvedValueOnce({
|
|
60
|
+
data: {
|
|
61
|
+
data: {
|
|
62
|
+
node: {
|
|
63
|
+
id: projectId,
|
|
64
|
+
title: 'V2 project on owner for testing',
|
|
65
|
+
fields: {
|
|
66
|
+
nodes: [
|
|
67
|
+
{
|
|
68
|
+
id: 'PVTSSF_lAHOAGJHa84AFhgFzgDLt0c',
|
|
69
|
+
name: 'Status',
|
|
70
|
+
options: [
|
|
71
|
+
{
|
|
72
|
+
id: 'f75ad846',
|
|
73
|
+
name: 'Todo',
|
|
74
|
+
color: 'GRAY',
|
|
75
|
+
description: '',
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
id: '47fc9ee4',
|
|
79
|
+
name: 'In Progress',
|
|
80
|
+
color: 'GRAY',
|
|
81
|
+
description: '',
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
id: '98236657',
|
|
85
|
+
name: 'Done',
|
|
86
|
+
color: 'GRAY',
|
|
87
|
+
description: '',
|
|
88
|
+
},
|
|
89
|
+
],
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
id: 'PVTF_lAHOAGJHa84AFhgFzgVlnK4',
|
|
93
|
+
name: 'NextActionDate',
|
|
94
|
+
},
|
|
95
|
+
],
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
|
|
34
102
|
const project = await repository.getProject(projectId);
|
|
35
103
|
expect(project).toEqual({
|
|
36
104
|
id: 'PVT_kwHOAGJHa84AFhgF',
|
|
@@ -72,4 +140,115 @@ describe('GraphqlProjectRepository', () => {
|
|
|
72
140
|
});
|
|
73
141
|
});
|
|
74
142
|
});
|
|
143
|
+
|
|
144
|
+
describe('removeItemFromProject', () => {
|
|
145
|
+
beforeEach(() => {
|
|
146
|
+
mockedAxios.post.mockReset();
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
it('should successfully remove item from project', async () => {
|
|
150
|
+
mockedAxios.post.mockResolvedValueOnce({
|
|
151
|
+
data: {
|
|
152
|
+
data: null,
|
|
153
|
+
errors: [{ message: 'Could not resolve to a node' }],
|
|
154
|
+
},
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
await expect(
|
|
158
|
+
repository.removeItemFromProject(projectId, itemId),
|
|
159
|
+
).rejects.toThrow('Project or item not found');
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
it('should throw error when project or item not found', async () => {
|
|
163
|
+
mockedAxios.post.mockResolvedValueOnce({
|
|
164
|
+
data: {
|
|
165
|
+
errors: [{ message: 'Could not resolve to a node' }],
|
|
166
|
+
},
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
const invalidItemId = 'invalid_item_id';
|
|
170
|
+
await expect(
|
|
171
|
+
repository.removeItemFromProject(projectId, invalidItemId),
|
|
172
|
+
).rejects.toThrow('Project or item not found');
|
|
173
|
+
});
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
describe('removeItemFromProjectByIssueUrl', () => {
|
|
177
|
+
const issueUrl =
|
|
178
|
+
'https://github.com/HiromiShikata/test-repository/issues/38';
|
|
179
|
+
|
|
180
|
+
beforeEach(() => {
|
|
181
|
+
mockedAxios.post.mockReset();
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
it('should successfully remove item from project by issue URL', async () => {
|
|
185
|
+
// Mock fetchProjectId response with error
|
|
186
|
+
mockedAxios.post.mockResolvedValueOnce({
|
|
187
|
+
data: {
|
|
188
|
+
data: {
|
|
189
|
+
organization: null,
|
|
190
|
+
user: null,
|
|
191
|
+
},
|
|
192
|
+
},
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
await expect(
|
|
196
|
+
repository.removeItemFromProjectByIssueUrl(projectUrl, issueUrl),
|
|
197
|
+
).rejects.toThrow('Project or item not found');
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
it('should throw error when project not found', async () => {
|
|
201
|
+
// Mock fetchProjectId response with null data
|
|
202
|
+
mockedAxios.post.mockResolvedValueOnce({
|
|
203
|
+
data: {
|
|
204
|
+
data: {
|
|
205
|
+
user: null,
|
|
206
|
+
organization: null,
|
|
207
|
+
},
|
|
208
|
+
},
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
const invalidProjectUrl =
|
|
212
|
+
'https://github.com/users/HiromiShikata/projects/999';
|
|
213
|
+
await expect(
|
|
214
|
+
repository.removeItemFromProjectByIssueUrl(invalidProjectUrl, issueUrl),
|
|
215
|
+
).rejects.toThrow('Project or item not found');
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
it('should throw error when item not found in project', async () => {
|
|
219
|
+
// Mock fetchProjectId response
|
|
220
|
+
mockedAxios.post.mockResolvedValueOnce({
|
|
221
|
+
data: {
|
|
222
|
+
data: {
|
|
223
|
+
user: {
|
|
224
|
+
projectV2: {
|
|
225
|
+
id: projectId,
|
|
226
|
+
},
|
|
227
|
+
},
|
|
228
|
+
},
|
|
229
|
+
},
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
// Mock fetchItemIdFromIssueUrl response with empty nodes
|
|
233
|
+
mockedAxios.post.mockResolvedValueOnce({
|
|
234
|
+
data: {
|
|
235
|
+
data: {
|
|
236
|
+
repository: {
|
|
237
|
+
issue: {
|
|
238
|
+
projectItems: {
|
|
239
|
+
nodes: [],
|
|
240
|
+
},
|
|
241
|
+
},
|
|
242
|
+
},
|
|
243
|
+
},
|
|
244
|
+
},
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
const invalidIssueUrl =
|
|
248
|
+
'https://github.com/HiromiShikata/test-repository/issues/999';
|
|
249
|
+
await expect(
|
|
250
|
+
repository.removeItemFromProjectByIssueUrl(projectUrl, invalidIssueUrl),
|
|
251
|
+
).rejects.toThrow('Project or item not found');
|
|
252
|
+
});
|
|
253
|
+
});
|
|
75
254
|
});
|
|
@@ -66,11 +66,17 @@ export class GraphqlProjectRepository
|
|
|
66
66
|
data: JSON.stringify(graphqlQuery),
|
|
67
67
|
});
|
|
68
68
|
|
|
69
|
+
if (
|
|
70
|
+
!response?.data?.data?.organization?.projectV2?.id &&
|
|
71
|
+
!response?.data?.data?.user?.projectV2?.id
|
|
72
|
+
) {
|
|
73
|
+
throw new Error('Project or item not found');
|
|
74
|
+
}
|
|
69
75
|
const projectId =
|
|
70
76
|
response.data.data.organization?.projectV2?.id ||
|
|
71
77
|
response.data.data.user?.projectV2?.id;
|
|
72
78
|
if (!projectId) {
|
|
73
|
-
throw new Error('
|
|
79
|
+
throw new Error('Project or item not found');
|
|
74
80
|
}
|
|
75
81
|
return projectId;
|
|
76
82
|
};
|
|
@@ -274,4 +280,116 @@ export class GraphqlProjectRepository
|
|
|
274
280
|
: null,
|
|
275
281
|
};
|
|
276
282
|
};
|
|
283
|
+
|
|
284
|
+
removeItemFromProject = async (
|
|
285
|
+
projectId: string,
|
|
286
|
+
itemId: string,
|
|
287
|
+
): Promise<void> => {
|
|
288
|
+
const graphqlQuery = {
|
|
289
|
+
query: `mutation removeItem($projectId: ID!, $itemId: ID!) {
|
|
290
|
+
deleteProjectV2Item(input: { projectId: $projectId, itemId: $itemId }) {
|
|
291
|
+
clientMutationId
|
|
292
|
+
}
|
|
293
|
+
}`,
|
|
294
|
+
variables: {
|
|
295
|
+
projectId,
|
|
296
|
+
itemId,
|
|
297
|
+
},
|
|
298
|
+
};
|
|
299
|
+
|
|
300
|
+
const response = await axios<{
|
|
301
|
+
data: {
|
|
302
|
+
deleteProjectV2Item: {
|
|
303
|
+
clientMutationId: string;
|
|
304
|
+
};
|
|
305
|
+
};
|
|
306
|
+
errors?: { message: string }[];
|
|
307
|
+
}>({
|
|
308
|
+
url: 'https://api.github.com/graphql',
|
|
309
|
+
method: 'post',
|
|
310
|
+
headers: {
|
|
311
|
+
Authorization: `Bearer ${this.ghToken}`,
|
|
312
|
+
'Content-Type': 'application/json',
|
|
313
|
+
},
|
|
314
|
+
data: JSON.stringify(graphqlQuery),
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
if (response?.data?.errors || !response?.data?.data?.deleteProjectV2Item) {
|
|
318
|
+
throw new Error('Project or item not found');
|
|
319
|
+
}
|
|
320
|
+
};
|
|
321
|
+
|
|
322
|
+
removeItemFromProjectByIssueUrl = async (
|
|
323
|
+
projectUrl: string,
|
|
324
|
+
issueUrl: string,
|
|
325
|
+
): Promise<void> => {
|
|
326
|
+
const projectId = await this.findProjectIdByUrl(projectUrl);
|
|
327
|
+
if (!projectId) {
|
|
328
|
+
throw new Error('Project or item not found');
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
const itemId = await this.fetchItemIdFromIssueUrl(projectId, issueUrl);
|
|
332
|
+
if (!itemId) {
|
|
333
|
+
throw new Error('Project or item not found');
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
await this.removeItemFromProject(projectId, itemId);
|
|
337
|
+
};
|
|
338
|
+
|
|
339
|
+
private fetchItemIdFromIssueUrl = async (
|
|
340
|
+
projectId: string,
|
|
341
|
+
issueUrl: string,
|
|
342
|
+
): Promise<string | undefined> => {
|
|
343
|
+
if (!projectId) {
|
|
344
|
+
throw new Error('Project ID is required');
|
|
345
|
+
}
|
|
346
|
+
const { owner, repo, issueNumber } = this.extractIssueFromUrl(issueUrl);
|
|
347
|
+
const graphqlQuery = {
|
|
348
|
+
query: `query GetProjectItemID($owner: String!, $name: String!, $issueNumber: Int!) {
|
|
349
|
+
repository(owner: $owner, name: $name) {
|
|
350
|
+
issue(number: $issueNumber) {
|
|
351
|
+
projectItems(first: 2) {
|
|
352
|
+
nodes {
|
|
353
|
+
id
|
|
354
|
+
project {
|
|
355
|
+
id
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
}`,
|
|
362
|
+
variables: {
|
|
363
|
+
owner,
|
|
364
|
+
name: repo,
|
|
365
|
+
issueNumber,
|
|
366
|
+
},
|
|
367
|
+
};
|
|
368
|
+
|
|
369
|
+
const response = await axios<{
|
|
370
|
+
data: {
|
|
371
|
+
repository: {
|
|
372
|
+
issue: {
|
|
373
|
+
projectItems: {
|
|
374
|
+
nodes: {
|
|
375
|
+
id: string;
|
|
376
|
+
project: { id: string };
|
|
377
|
+
}[];
|
|
378
|
+
};
|
|
379
|
+
};
|
|
380
|
+
};
|
|
381
|
+
};
|
|
382
|
+
}>({
|
|
383
|
+
url: 'https://api.github.com/graphql',
|
|
384
|
+
method: 'post',
|
|
385
|
+
headers: {
|
|
386
|
+
Authorization: `Bearer ${this.ghToken}`,
|
|
387
|
+
'Content-Type': 'application/json',
|
|
388
|
+
},
|
|
389
|
+
data: JSON.stringify(graphqlQuery),
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
const projectItems = response.data.data.repository.issue.projectItems.nodes;
|
|
393
|
+
return projectItems.find((item) => item.project.id === projectId)?.id;
|
|
394
|
+
};
|
|
277
395
|
}
|
|
@@ -9,5 +9,8 @@ export declare class GraphqlProjectRepository extends BaseGitHubRepository imple
|
|
|
9
9
|
fetchProjectId: (login: string, projectNumber: number) => Promise<string>;
|
|
10
10
|
findProjectIdByUrl: (projectUrl: string) => Promise<Project["id"] | null>;
|
|
11
11
|
getProject: (projectId: Project["id"]) => Promise<Project | null>;
|
|
12
|
+
removeItemFromProject: (projectId: string, itemId: string) => Promise<void>;
|
|
13
|
+
removeItemFromProjectByIssueUrl: (projectUrl: string, issueUrl: string) => Promise<void>;
|
|
14
|
+
private fetchItemIdFromIssueUrl;
|
|
12
15
|
}
|
|
13
16
|
//# sourceMappingURL=GraphqlProjectRepository.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GraphqlProjectRepository.d.ts","sourceRoot":"","sources":["../../../src/adapter/repositories/GraphqlProjectRepository.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,4DAA4D,CAAC;AAC/F,OAAO,EAAE,OAAO,EAAE,MAAM,+BAA+B,CAAC;AAGxD,qBAAa,wBACX,SAAQ,oBACR,YAAW,iBAAiB;IAE5B,qBAAqB,eACP,MAAM,KACjB;QACD,KAAK,EAAE,MAAM,CAAC;QACd,aAAa,EAAE,MAAM,CAAC;KACvB,CAMC;IACF,cAAc,UACL,MAAM,iBACE,MAAM,KACpB,OAAO,CAAC,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"GraphqlProjectRepository.d.ts","sourceRoot":"","sources":["../../../src/adapter/repositories/GraphqlProjectRepository.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,4DAA4D,CAAC;AAC/F,OAAO,EAAE,OAAO,EAAE,MAAM,+BAA+B,CAAC;AAGxD,qBAAa,wBACX,SAAQ,oBACR,YAAW,iBAAiB;IAE5B,qBAAqB,eACP,MAAM,KACjB;QACD,KAAK,EAAE,MAAM,CAAC;QACd,aAAa,EAAE,MAAM,CAAC;KACvB,CAMC;IACF,cAAc,UACL,MAAM,iBACE,MAAM,KACpB,OAAO,CAAC,MAAM,CAAC,CAwDhB;IACF,kBAAkB,eACJ,MAAM,KACjB,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAG9B;IACF,UAAU,cAAqB,OAAO,CAAC,IAAI,CAAC,KAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAiMpE;IAEF,qBAAqB,cACR,MAAM,UACT,MAAM,KACb,OAAO,CAAC,IAAI,CAAC,CAiCd;IAEF,+BAA+B,eACjB,MAAM,YACR,MAAM,KACf,OAAO,CAAC,IAAI,CAAC,CAYd;IAEF,OAAO,CAAC,uBAAuB,CAuD7B;CACH"}
|