github-issue-tower-defence-management 1.35.2 → 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 +15 -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 +3 -7
- 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 +43 -33
- package/src/adapter/repositories/BaseGitHubRepository.ts +4 -8
- 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,218 +0,0 @@
|
|
|
1
|
-
import axios, { AxiosError, AxiosHeaders, AxiosInstance } from 'axios';
|
|
2
|
-
import axiosRetry from 'axios-retry';
|
|
3
|
-
import fs from 'fs';
|
|
4
|
-
import { SlackRepository } from '../../domain/usecases/adapter-interfaces/SlackRepository';
|
|
5
|
-
|
|
6
|
-
const getRetryAfterDelay = (error: AxiosError): number | null => {
|
|
7
|
-
const headers = error.response?.headers;
|
|
8
|
-
if (!headers) {
|
|
9
|
-
return null;
|
|
10
|
-
}
|
|
11
|
-
if (headers instanceof AxiosHeaders) {
|
|
12
|
-
const retryAfter = headers.get('retry-after');
|
|
13
|
-
if (typeof retryAfter === 'string') {
|
|
14
|
-
const parsed = parseInt(retryAfter, 10);
|
|
15
|
-
if (!isNaN(parsed)) {
|
|
16
|
-
return parsed * 1000;
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
return null;
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
export class AxiosSlackRepository implements SlackRepository {
|
|
24
|
-
private readonly client: AxiosInstance;
|
|
25
|
-
private readonly baseUrl = 'https://slack.com/api';
|
|
26
|
-
|
|
27
|
-
constructor(userToken: string) {
|
|
28
|
-
if (!userToken.startsWith('xoxp-')) {
|
|
29
|
-
throw new Error('Invalid user token. It should start with xoxp-');
|
|
30
|
-
}
|
|
31
|
-
this.client = axios.create({
|
|
32
|
-
baseURL: this.baseUrl,
|
|
33
|
-
headers: {
|
|
34
|
-
Authorization: `Bearer ${userToken}`,
|
|
35
|
-
},
|
|
36
|
-
});
|
|
37
|
-
axiosRetry(this.client, {
|
|
38
|
-
retries: 3,
|
|
39
|
-
retryDelay: (retryCount, error) => {
|
|
40
|
-
const retryAfterDelay = getRetryAfterDelay(error);
|
|
41
|
-
if (retryAfterDelay !== null) {
|
|
42
|
-
return retryAfterDelay;
|
|
43
|
-
}
|
|
44
|
-
return axiosRetry.exponentialDelay(retryCount);
|
|
45
|
-
},
|
|
46
|
-
retryCondition: (error) => {
|
|
47
|
-
return (
|
|
48
|
-
axiosRetry.isNetworkOrIdempotentRequestError(error) ||
|
|
49
|
-
error.response?.status === 429
|
|
50
|
-
);
|
|
51
|
-
},
|
|
52
|
-
});
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
async postMessageToChannel(
|
|
56
|
-
message: string,
|
|
57
|
-
channelName: string,
|
|
58
|
-
): Promise<{
|
|
59
|
-
threadTs: string;
|
|
60
|
-
}> {
|
|
61
|
-
const { data } = await this.client.get<{
|
|
62
|
-
ok: boolean;
|
|
63
|
-
channels: { id: string; name: string }[];
|
|
64
|
-
}>('/conversations.list');
|
|
65
|
-
|
|
66
|
-
const channel = data.channels.find((c) => c.name === channelName);
|
|
67
|
-
if (!channel) throw new Error(`Channel ${channelName} not found`);
|
|
68
|
-
|
|
69
|
-
const res = await this.client.post<{ ok: boolean; ts: string }>(
|
|
70
|
-
'/chat.postMessage',
|
|
71
|
-
{
|
|
72
|
-
channel: channel.id,
|
|
73
|
-
text: message,
|
|
74
|
-
},
|
|
75
|
-
);
|
|
76
|
-
if (!res.data.ok) {
|
|
77
|
-
throw new Error(`Failed to post message: ${JSON.stringify(res.data)}`);
|
|
78
|
-
}
|
|
79
|
-
return {
|
|
80
|
-
threadTs: res.data.ts,
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
async postMessageToChannelThread(
|
|
85
|
-
message: string,
|
|
86
|
-
channelName: string,
|
|
87
|
-
threadTs: string,
|
|
88
|
-
): Promise<void> {
|
|
89
|
-
const { data } = await this.client.get<{
|
|
90
|
-
ok: boolean;
|
|
91
|
-
channels: { id: string; name: string }[];
|
|
92
|
-
}>('/conversations.list');
|
|
93
|
-
|
|
94
|
-
const channel = data.channels.find((c) => c.name === channelName);
|
|
95
|
-
if (!channel) throw new Error(`Channel ${channelName} not found`);
|
|
96
|
-
|
|
97
|
-
const res = await this.client.post<{ ok: boolean }>('/chat.postMessage', {
|
|
98
|
-
channel: channel.id,
|
|
99
|
-
text: message,
|
|
100
|
-
thread_ts: threadTs,
|
|
101
|
-
});
|
|
102
|
-
if (!res.data.ok) {
|
|
103
|
-
throw new Error(`Failed to post message: ${JSON.stringify(res.data)}`);
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
async postMessageToDirectMessage(
|
|
108
|
-
message: string,
|
|
109
|
-
userName: string,
|
|
110
|
-
): Promise<void> {
|
|
111
|
-
const { data } = await this.client.get<{
|
|
112
|
-
ok: boolean;
|
|
113
|
-
members: { id: string; name: string }[];
|
|
114
|
-
}>('/users.list');
|
|
115
|
-
|
|
116
|
-
const user = data.members.find((u) => u.name === userName);
|
|
117
|
-
if (!user) throw new Error(`User ${userName} not found`);
|
|
118
|
-
|
|
119
|
-
const res = await this.client.post<{ ok: boolean }>('/chat.postMessage', {
|
|
120
|
-
channel: user.id,
|
|
121
|
-
text: message,
|
|
122
|
-
});
|
|
123
|
-
if (!res.data.ok) {
|
|
124
|
-
throw new Error(`Failed to post message: ${JSON.stringify(res.data)}`);
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
async postMessageToChannelWithImage(
|
|
128
|
-
message: string,
|
|
129
|
-
channelName: string,
|
|
130
|
-
imageFilePath: string,
|
|
131
|
-
): Promise<void> {
|
|
132
|
-
const { data } = await this.client.get<{
|
|
133
|
-
ok: boolean;
|
|
134
|
-
channels: { id: string; name: string }[];
|
|
135
|
-
}>('/conversations.list');
|
|
136
|
-
|
|
137
|
-
const channel = data.channels.find((c) => c.name === channelName);
|
|
138
|
-
if (!channel) throw new Error(`Channel ${channelName} not found`);
|
|
139
|
-
|
|
140
|
-
const fileStats = fs.statSync(imageFilePath);
|
|
141
|
-
const fileName = imageFilePath.split('/').pop();
|
|
142
|
-
|
|
143
|
-
const uploadUrlRes = await this.client.post<{
|
|
144
|
-
ok: boolean;
|
|
145
|
-
upload_url: string;
|
|
146
|
-
file_id: string;
|
|
147
|
-
}>(
|
|
148
|
-
'/files.getUploadURLExternal',
|
|
149
|
-
{
|
|
150
|
-
filename: fileName,
|
|
151
|
-
length: fileStats.size,
|
|
152
|
-
},
|
|
153
|
-
{
|
|
154
|
-
headers: {
|
|
155
|
-
'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8',
|
|
156
|
-
},
|
|
157
|
-
},
|
|
158
|
-
);
|
|
159
|
-
if (!uploadUrlRes.data.ok) {
|
|
160
|
-
throw new Error(
|
|
161
|
-
`Failed to get upload URL: ${JSON.stringify(uploadUrlRes.data)}`,
|
|
162
|
-
);
|
|
163
|
-
}
|
|
164
|
-
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
165
|
-
|
|
166
|
-
const fileContent = fs.readFileSync(imageFilePath);
|
|
167
|
-
await axios.post(uploadUrlRes.data.upload_url, fileContent, {
|
|
168
|
-
headers: {
|
|
169
|
-
'Content-Type': 'application/octet-stream',
|
|
170
|
-
},
|
|
171
|
-
});
|
|
172
|
-
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
173
|
-
|
|
174
|
-
const completeRes = await this.client.post<{ ok: boolean }>(
|
|
175
|
-
'/files.completeUploadExternal',
|
|
176
|
-
{
|
|
177
|
-
files: [
|
|
178
|
-
{
|
|
179
|
-
id: uploadUrlRes.data.file_id,
|
|
180
|
-
},
|
|
181
|
-
],
|
|
182
|
-
},
|
|
183
|
-
);
|
|
184
|
-
if (!completeRes.data.ok) {
|
|
185
|
-
throw new Error(
|
|
186
|
-
`Failed to complete upload: ${JSON.stringify(completeRes.data)}`,
|
|
187
|
-
);
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
const fileInfo = await this.client.get<{
|
|
191
|
-
ok: boolean;
|
|
192
|
-
file: { url_private: string };
|
|
193
|
-
}>(`/files.info?file=${uploadUrlRes.data.file_id}`);
|
|
194
|
-
|
|
195
|
-
if (!fileInfo.data.ok) {
|
|
196
|
-
throw new Error(
|
|
197
|
-
`Failed to get file info: ${JSON.stringify(fileInfo.data)}`,
|
|
198
|
-
);
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
const imageUrl = fileInfo.data.file.url_private;
|
|
202
|
-
await new Promise((resolve) => setTimeout(resolve, 2000));
|
|
203
|
-
const res = await this.client.post<{ ok: boolean }>('/chat.postMessage', {
|
|
204
|
-
channel: channel.id,
|
|
205
|
-
text: message,
|
|
206
|
-
blocks: [
|
|
207
|
-
{
|
|
208
|
-
type: 'image',
|
|
209
|
-
image_url: imageUrl,
|
|
210
|
-
alt_text: fileName,
|
|
211
|
-
},
|
|
212
|
-
],
|
|
213
|
-
});
|
|
214
|
-
if (!res.data.ok) {
|
|
215
|
-
throw new Error(`Failed to post message: ${JSON.stringify(res.data)}`);
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"AxiosSlackRepository.d.ts","sourceRoot":"","sources":["../../../src/adapter/repositories/AxiosSlackRepository.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,eAAe,EAAE,MAAM,0DAA0D,CAAC;AAmB3F,qBAAa,oBAAqB,YAAW,eAAe;IAC1D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;IACvC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA2B;gBAEvC,SAAS,EAAE,MAAM;IA4BvB,oBAAoB,CACxB,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC;QACT,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC;IAwBI,0BAA0B,CAC9B,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC;IAmBV,0BAA0B,CAC9B,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC;IAiBV,6BAA6B,CACjC,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,MAAM,EACnB,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,IAAI,CAAC;CAuFjB"}
|