wuffle 0.41.5 → 0.43.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/bin/run.js +1 -1
- package/lib/apps/auth-routes/AuthRoutes.js +5 -3
- package/lib/apps/automatic-dev-flow.js +2 -0
- package/lib/apps/background-sync/BackgroundSync.js +11 -9
- package/lib/apps/board-api-routes.js +3 -3
- package/lib/apps/board-routes.js +1 -1
- package/lib/apps/dump-store/local/DumpStoreLocal.js +5 -3
- package/lib/apps/dump-store/s3/DumpStoreS3.js +5 -3
- package/lib/apps/events-sync.js +28 -18
- package/lib/apps/github-app/GithubApp.js +19 -3
- package/lib/apps/github-checks/GithubChecks.js +6 -4
- package/lib/apps/github-client/GithubClient.js +33 -3
- package/lib/apps/github-comments/GithubComments.js +205 -0
- package/lib/apps/github-comments/index.js +6 -0
- package/lib/apps/github-issues/GithubIssues.js +77 -22
- package/lib/apps/github-reviews/GithubReviews.js +7 -3
- package/lib/apps/github-statuses/GithubStatuses.js +2 -0
- package/lib/apps/log-events.js +11 -7
- package/lib/apps/reindex-store.js +14 -2
- package/lib/apps/route-compression.js +1 -1
- package/lib/apps/route-https.js +1 -1
- package/lib/apps/search/Search.js +32 -5
- package/lib/apps/security-context/SecurityContext.js +5 -0
- package/lib/apps/user-access/UserAccess.js +6 -4
- package/lib/apps/webhook-events/WebhookEvents.js +33 -9
- package/lib/columns.js +16 -3
- package/lib/filters.js +20 -16
- package/lib/index.js +1 -0
- package/lib/links.js +15 -5
- package/lib/probot/apps/setup.js +1 -1
- package/lib/probot/manifest-creation.js +1 -1
- package/lib/store.js +11 -0
- package/lib/types.d.ts +23 -6
- package/lib/util/index.js +1 -1
- package/lib/util/links.js +48 -26
- package/package.json +24 -19
- package/public/bundle.css +1 -1
- package/public/bundle.js +1 -1
- package/public/bundle.js.map +1 -1
- package/public/service-worker.js.map +1 -1
- package/CHANGELOG.md +0 -465
package/bin/run.js
CHANGED
|
@@ -23,9 +23,11 @@ const {
|
|
|
23
23
|
* Under the hood, it uses GitHub's APIs to perform user authentication
|
|
24
24
|
* via OAuth.
|
|
25
25
|
*
|
|
26
|
-
* @
|
|
27
|
-
*
|
|
28
|
-
* @param {import(
|
|
26
|
+
* @constructor
|
|
27
|
+
*
|
|
28
|
+
* @param {import('../../types').Logger} logger
|
|
29
|
+
* @param {import('../../types').Router} router
|
|
30
|
+
* @param {import('../security-context/SecurityContext')} securityContext
|
|
29
31
|
*/
|
|
30
32
|
function AuthRoutes(logger, router, securityContext) {
|
|
31
33
|
|
|
@@ -9,6 +9,8 @@ const IN_REVIEW = 'IN_REVIEW';
|
|
|
9
9
|
* across the board, as long as the user adheres to a specified
|
|
10
10
|
* dev flow.
|
|
11
11
|
*
|
|
12
|
+
* @constructor
|
|
13
|
+
*
|
|
12
14
|
* @param {import('./webhook-events/WebhookEvents')} webhookEvents
|
|
13
15
|
* @param {import('./github-issues/GithubIssues')} githubIssues
|
|
14
16
|
* @param {import('../columns')} columns
|
|
@@ -15,12 +15,14 @@ function isInternalError(error) {
|
|
|
15
15
|
/**
|
|
16
16
|
* This component performs a periodic background sync of a project.
|
|
17
17
|
*
|
|
18
|
-
* @
|
|
18
|
+
* @constructor
|
|
19
|
+
*
|
|
20
|
+
* @param {import('../../types').Logger} logger
|
|
19
21
|
* @param {Object} config
|
|
20
|
-
* @param {import(
|
|
21
|
-
* @param {import(
|
|
22
|
-
* @param {import(
|
|
23
|
-
* @param {import(
|
|
22
|
+
* @param {import('../../store')} store
|
|
23
|
+
* @param {import('../github-client/GithubClient')} githubClient
|
|
24
|
+
* @param {import('../github-app/GithubApp')} githubApp
|
|
25
|
+
* @param {import('../../events')} events
|
|
24
26
|
*/
|
|
25
27
|
function BackgroundSync(logger, config, store, githubClient, githubApp, events) {
|
|
26
28
|
|
|
@@ -140,8 +142,8 @@ We automatically synchronize all repositories you granted us access to via the G
|
|
|
140
142
|
}, 'processing');
|
|
141
143
|
|
|
142
144
|
const params = {
|
|
143
|
-
sort: 'updated',
|
|
144
|
-
direction: 'desc',
|
|
145
|
+
sort: /** @type { 'updated' } */ ('updated'),
|
|
146
|
+
direction: /** @type { 'desc' } */ ('desc'),
|
|
145
147
|
per_page: 100,
|
|
146
148
|
owner,
|
|
147
149
|
repo
|
|
@@ -161,7 +163,7 @@ We automatically synchronize all repositories you granted us access to via the G
|
|
|
161
163
|
...params,
|
|
162
164
|
state: 'open'
|
|
163
165
|
},
|
|
164
|
-
response => response.data.filter(issue => !issue
|
|
166
|
+
response => response.data.filter(issue => !('pull_request' in issue))
|
|
165
167
|
),
|
|
166
168
|
|
|
167
169
|
// closed issues, updated last 30 days
|
|
@@ -172,7 +174,7 @@ We automatically synchronize all repositories you granted us access to via the G
|
|
|
172
174
|
state: 'closed',
|
|
173
175
|
since: new Date(syncClosedSince).toISOString()
|
|
174
176
|
},
|
|
175
|
-
response => response.data.filter(issue => !issue
|
|
177
|
+
response => response.data.filter(issue => !('pull_request' in issue))
|
|
176
178
|
),
|
|
177
179
|
|
|
178
180
|
// open pulls
|
|
@@ -13,9 +13,9 @@ const {
|
|
|
13
13
|
* This component provides the board API routes.
|
|
14
14
|
*
|
|
15
15
|
* @param {Object} config
|
|
16
|
-
* @param {import(
|
|
17
|
-
* @param {import(
|
|
18
|
-
* @param {import(
|
|
16
|
+
* @param {import('../store')} store
|
|
17
|
+
* @param {import('../types').Router} router
|
|
18
|
+
* @param {import('../types').Logger} logger
|
|
19
19
|
* @param {import('./github-client/GithubClient')} githubClient
|
|
20
20
|
* @param {import('./auth-routes/AuthRoutes')} authRoutes
|
|
21
21
|
* @param {import('./user-access/UserAccess')} userAccess
|
package/lib/apps/board-routes.js
CHANGED
|
@@ -8,9 +8,11 @@ const mkdirp = require('mkdirp');
|
|
|
8
8
|
* This component restores a store dump on startup and periodically
|
|
9
9
|
* persists the store to disc.
|
|
10
10
|
*
|
|
11
|
-
* @
|
|
12
|
-
*
|
|
13
|
-
* @param {import(
|
|
11
|
+
* @constructor
|
|
12
|
+
*
|
|
13
|
+
* @param {import('../../../types').Logger} logger
|
|
14
|
+
* @param {import('../../../store')} store
|
|
15
|
+
* @param {import('../../../events')} events
|
|
14
16
|
*/
|
|
15
17
|
function DumpStoreLocal(logger, store, events) {
|
|
16
18
|
|
|
@@ -5,9 +5,11 @@ const S3 = require('./S3');
|
|
|
5
5
|
* This component restores a store dump on startup and periodically
|
|
6
6
|
* persists the store to disc.
|
|
7
7
|
*
|
|
8
|
-
* @
|
|
9
|
-
*
|
|
10
|
-
* @param
|
|
8
|
+
* @constructor
|
|
9
|
+
*
|
|
10
|
+
* @param {import('../../../types').Logger} logger
|
|
11
|
+
* @param {import('../../../store')} store
|
|
12
|
+
* @param {import('../../../events')} events
|
|
11
13
|
*/
|
|
12
14
|
function DumpStoreS3(logger, store, events) {
|
|
13
15
|
|
package/lib/apps/events-sync.js
CHANGED
|
@@ -11,11 +11,13 @@ const {
|
|
|
11
11
|
/**
|
|
12
12
|
* This component updates the stored issues based on GitHub events.
|
|
13
13
|
*
|
|
14
|
-
* @
|
|
15
|
-
*
|
|
16
|
-
* @param {import(
|
|
14
|
+
* @constructor
|
|
15
|
+
*
|
|
16
|
+
* @param {import('./webhook-events/WebhookEvents')} webhookEvents
|
|
17
|
+
* @param {import('../store')} store
|
|
18
|
+
* @param {import('../types').Logger} logger
|
|
17
19
|
*/
|
|
18
|
-
|
|
20
|
+
function EventsSync(webhookEvents, store, logger) {
|
|
19
21
|
|
|
20
22
|
const log = logger.child({
|
|
21
23
|
name: 'wuffle:user-access'
|
|
@@ -71,6 +73,25 @@ module.exports = function EventsSync(webhookEvents, store, logger) {
|
|
|
71
73
|
return store.removeIssueById(id);
|
|
72
74
|
});
|
|
73
75
|
|
|
76
|
+
// issue_comment ///////////////////////
|
|
77
|
+
|
|
78
|
+
// https://docs.github.com/en/free-pro-team@latest/developers/webhooks-and-events/webhook-events-and-payloads#issue_comment
|
|
79
|
+
|
|
80
|
+
webhookEvents.on([
|
|
81
|
+
'issue_comment.created',
|
|
82
|
+
'issue_comment.edited'
|
|
83
|
+
], async ({ payload }) => {
|
|
84
|
+
|
|
85
|
+
const {
|
|
86
|
+
issue,
|
|
87
|
+
repository
|
|
88
|
+
} = payload;
|
|
89
|
+
|
|
90
|
+
// necro bump issue on comment
|
|
91
|
+
return store.updateIssue(filterIssueOrPull(issue, repository));
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
|
|
74
95
|
// pull requests //////////////////
|
|
75
96
|
|
|
76
97
|
webhookEvents.on([
|
|
@@ -203,19 +224,6 @@ module.exports = function EventsSync(webhookEvents, store, logger) {
|
|
|
203
224
|
});
|
|
204
225
|
|
|
205
226
|
|
|
206
|
-
// issue_comment ///////////////////////
|
|
207
|
-
|
|
208
|
-
// https://docs.github.com/en/free-pro-team@latest/developers/webhooks-and-events/webhook-events-and-payloads#issue_comment
|
|
209
|
-
|
|
210
|
-
webhookEvents.on([
|
|
211
|
-
'issue_comment.created',
|
|
212
|
-
'issue_comment.edited'
|
|
213
|
-
], async ({ payload }) => {
|
|
214
|
-
|
|
215
|
-
// necro bump issue
|
|
216
|
-
});
|
|
217
|
-
|
|
218
|
-
|
|
219
227
|
// issues ///////////////////////////////
|
|
220
228
|
|
|
221
229
|
// https://docs.github.com/en/free-pro-team@latest/developers/webhooks-and-events/webhook-events-and-payloads#issues
|
|
@@ -265,4 +273,6 @@ module.exports = function EventsSync(webhookEvents, store, logger) {
|
|
|
265
273
|
return store.removeIssueById(storedIssue.id);
|
|
266
274
|
});
|
|
267
275
|
|
|
268
|
-
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
module.exports = EventsSync;
|
|
@@ -34,10 +34,12 @@ const RequiredEvents = [
|
|
|
34
34
|
* This component validates and exposes
|
|
35
35
|
* installations of the GitHub app.
|
|
36
36
|
*
|
|
37
|
+
* @constructor
|
|
38
|
+
*
|
|
37
39
|
* @param {Object} config
|
|
38
|
-
* @param {import(
|
|
39
|
-
* @param {import(
|
|
40
|
-
* @param {import(
|
|
40
|
+
* @param {import('../../types').ProbotApp} app
|
|
41
|
+
* @param {import('../../types').Logger} logger
|
|
42
|
+
* @param {import('../../types').Injector} injector
|
|
41
43
|
*/
|
|
42
44
|
function GithubApp(config, app, logger, injector) {
|
|
43
45
|
|
|
@@ -68,6 +70,9 @@ function GithubApp(config, app, logger, injector) {
|
|
|
68
70
|
|
|
69
71
|
// functionality /////////////////
|
|
70
72
|
|
|
73
|
+
/**
|
|
74
|
+
* @return {Promise<import('../../types').Octokit>}
|
|
75
|
+
*/
|
|
71
76
|
function getAppScopedClient() {
|
|
72
77
|
return app.auth();
|
|
73
78
|
}
|
|
@@ -159,6 +164,11 @@ function GithubApp(config, app, logger, injector) {
|
|
|
159
164
|
return getInstallationById(installation_id).then(installation => !!installation);
|
|
160
165
|
}
|
|
161
166
|
|
|
167
|
+
/**
|
|
168
|
+
* @param {string} login
|
|
169
|
+
*
|
|
170
|
+
* @return {boolean}
|
|
171
|
+
*/
|
|
162
172
|
function isLoginEnabled(login) {
|
|
163
173
|
if (allowedOrgs) {
|
|
164
174
|
return allowedOrgs.some(org => org === login);
|
|
@@ -167,6 +177,12 @@ function GithubApp(config, app, logger, injector) {
|
|
|
167
177
|
return true;
|
|
168
178
|
}
|
|
169
179
|
|
|
180
|
+
/**
|
|
181
|
+
* @param {string} requested
|
|
182
|
+
* @param {string} actual
|
|
183
|
+
*
|
|
184
|
+
* @return {boolean}
|
|
185
|
+
*/
|
|
170
186
|
function isRequiredLevel(requested, actual) {
|
|
171
187
|
return PermissionLevels[requested] <= PermissionLevels[actual || 'none'];
|
|
172
188
|
}
|
|
@@ -6,10 +6,12 @@ const {
|
|
|
6
6
|
/**
|
|
7
7
|
* This component updates the stored issues based on GitHub events.
|
|
8
8
|
*
|
|
9
|
-
* @
|
|
10
|
-
*
|
|
11
|
-
* @param {import(
|
|
12
|
-
* @param {import(
|
|
9
|
+
* @constructor
|
|
10
|
+
*
|
|
11
|
+
* @param {import('../webhook-events/WebhookEvents')} webhookEvents
|
|
12
|
+
* @param {import('../../events')} events
|
|
13
|
+
* @param {import('../github-client/GithubClient')} githubClient
|
|
14
|
+
* @param {import('../../store')} store
|
|
13
15
|
*/
|
|
14
16
|
module.exports = function GithubChecks(webhookEvents, events, githubClient, store) {
|
|
15
17
|
|
|
@@ -10,7 +10,20 @@ const {
|
|
|
10
10
|
// 15 minutes
|
|
11
11
|
const TTL = 1000 * 60 * 15;
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
/**
|
|
14
|
+
* @typedef { import('../../types').Octokit } Octokit
|
|
15
|
+
* @typedef { { [x: string]: Promise<Octokit> } } LoginCache
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @constructor
|
|
20
|
+
*
|
|
21
|
+
* @param {import('../../types').ProbotApp} app
|
|
22
|
+
* @param {import('../webhook-events/WebhookEvents')} webhookEvents
|
|
23
|
+
* @param {import('../../types').Logger} logger
|
|
24
|
+
* @param {import('../github-app/GithubApp')} githubApp
|
|
25
|
+
* @param {import('../../events')} events
|
|
26
|
+
*/
|
|
14
27
|
function GitHubClient(app, webhookEvents, logger, githubApp, events) {
|
|
15
28
|
|
|
16
29
|
const log = logger.child({
|
|
@@ -21,7 +34,7 @@ function GitHubClient(app, webhookEvents, logger, githubApp, events) {
|
|
|
21
34
|
|
|
22
35
|
// cached data ///////////////////
|
|
23
36
|
|
|
24
|
-
let authByLogin = {};
|
|
37
|
+
let authByLogin = /** @type { LoginCache } */ ({});
|
|
25
38
|
|
|
26
39
|
|
|
27
40
|
// reactivity ////////////////////
|
|
@@ -33,10 +46,20 @@ function GitHubClient(app, webhookEvents, logger, githubApp, events) {
|
|
|
33
46
|
|
|
34
47
|
// functionality /////////////////
|
|
35
48
|
|
|
49
|
+
/**
|
|
50
|
+
* @param {number} id
|
|
51
|
+
*
|
|
52
|
+
* @return {Promise<Octokit>}
|
|
53
|
+
*/
|
|
36
54
|
function getInstallationScoped(id) {
|
|
37
55
|
return app.auth(id);
|
|
38
56
|
}
|
|
39
57
|
|
|
58
|
+
/**
|
|
59
|
+
* @param {string} login
|
|
60
|
+
*
|
|
61
|
+
* @return {Promise<Octokit>}
|
|
62
|
+
*/
|
|
40
63
|
function getOrgScoped(login) {
|
|
41
64
|
|
|
42
65
|
let auth = authByLogin[login];
|
|
@@ -50,7 +73,7 @@ function GitHubClient(app, webhookEvents, logger, githubApp, events) {
|
|
|
50
73
|
auth = authByLogin[login] =
|
|
51
74
|
githubApp.getInstallationByLogin(login)
|
|
52
75
|
.then(
|
|
53
|
-
installation =>
|
|
76
|
+
installation => getInstallationScoped(installation.id),
|
|
54
77
|
err => {
|
|
55
78
|
log.error({
|
|
56
79
|
err,
|
|
@@ -64,6 +87,13 @@ function GitHubClient(app, webhookEvents, logger, githubApp, events) {
|
|
|
64
87
|
return auth;
|
|
65
88
|
}
|
|
66
89
|
|
|
90
|
+
/**
|
|
91
|
+
* Return user scoped octokit instance.
|
|
92
|
+
*
|
|
93
|
+
* @param {string|{ access_token: string }} user
|
|
94
|
+
*
|
|
95
|
+
* @return {Promise<Octokit>}
|
|
96
|
+
*/
|
|
67
97
|
function getUserScoped(user) {
|
|
68
98
|
|
|
69
99
|
const access_token = typeof user === 'string' ? user : user.access_token;
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
const {
|
|
2
|
+
repoAndOwner
|
|
3
|
+
} = require('../../util');
|
|
4
|
+
|
|
5
|
+
const {
|
|
6
|
+
filterUser,
|
|
7
|
+
filterIssue
|
|
8
|
+
} = require('../../filters');
|
|
9
|
+
|
|
10
|
+
const gql = require('fake-tag');
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* This component updates the stored issues based on GitHub events.
|
|
15
|
+
*
|
|
16
|
+
* @constructor
|
|
17
|
+
*
|
|
18
|
+
* @param {import('../webhook-events/WebhookEvents')} webhookEvents
|
|
19
|
+
* @param {import('../../events')} events
|
|
20
|
+
* @param {import('../github-client/GithubClient')} githubClient
|
|
21
|
+
* @param {import('../../store')} store
|
|
22
|
+
*/
|
|
23
|
+
function GithubComments(webhookEvents, events, githubClient, store) {
|
|
24
|
+
|
|
25
|
+
// issues /////////////////////
|
|
26
|
+
|
|
27
|
+
events.on('backgroundSync.sync', async (event) => {
|
|
28
|
+
|
|
29
|
+
const {
|
|
30
|
+
issue
|
|
31
|
+
} = event;
|
|
32
|
+
|
|
33
|
+
const {
|
|
34
|
+
id,
|
|
35
|
+
number
|
|
36
|
+
} = issue;
|
|
37
|
+
|
|
38
|
+
const {
|
|
39
|
+
repo,
|
|
40
|
+
owner
|
|
41
|
+
} = repoAndOwner(issue);
|
|
42
|
+
|
|
43
|
+
const github = await githubClient.getOrgScoped(owner);
|
|
44
|
+
|
|
45
|
+
const result = await github.graphql(gql`
|
|
46
|
+
|
|
47
|
+
fragment CommentInfo on IssueComment {
|
|
48
|
+
id: databaseId
|
|
49
|
+
node_id: id
|
|
50
|
+
body: bodyText
|
|
51
|
+
created_at: publishedAt
|
|
52
|
+
authorAssociation,
|
|
53
|
+
html_url: url,
|
|
54
|
+
user: author {
|
|
55
|
+
login
|
|
56
|
+
avatar_url: avatarUrl,
|
|
57
|
+
html_url: url
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
query FetchComments(
|
|
62
|
+
$repo: String!,
|
|
63
|
+
$owner: String!,
|
|
64
|
+
$issue_number: Int!,
|
|
65
|
+
$after: String
|
|
66
|
+
) {
|
|
67
|
+
repository(name: $repo, owner: $owner) {
|
|
68
|
+
issueOrPullRequest(number: $issue_number) {
|
|
69
|
+
...on Issue {
|
|
70
|
+
comments(first: 100, after: $after) {
|
|
71
|
+
edges {
|
|
72
|
+
node {
|
|
73
|
+
...CommentInfo
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
pageInfo {
|
|
77
|
+
endCursor
|
|
78
|
+
hasNextPage
|
|
79
|
+
}
|
|
80
|
+
totalCount
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
...on PullRequest {
|
|
84
|
+
comments(first: 100, after: $after) {
|
|
85
|
+
edges {
|
|
86
|
+
node {
|
|
87
|
+
...CommentInfo
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
pageInfo {
|
|
91
|
+
endCursor
|
|
92
|
+
hasNextPage
|
|
93
|
+
}
|
|
94
|
+
totalCount
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
`, {
|
|
101
|
+
owner,
|
|
102
|
+
repo,
|
|
103
|
+
issue_number: number
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
const comments = (
|
|
107
|
+
result.repository.issueOrPullRequest.comments.edges.map(e => e.node)
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
await store.queueUpdate({
|
|
111
|
+
id,
|
|
112
|
+
comments: comments.map(filterComment)
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
webhookEvents.on([
|
|
117
|
+
'issue_comment'
|
|
118
|
+
], async ({ payload }) => {
|
|
119
|
+
const {
|
|
120
|
+
action,
|
|
121
|
+
comment: _comment,
|
|
122
|
+
issue: _issue,
|
|
123
|
+
repository
|
|
124
|
+
} = payload;
|
|
125
|
+
|
|
126
|
+
const commentedIssue = filterIssue(_issue, repository);
|
|
127
|
+
const comment = filterComment(_comment);
|
|
128
|
+
|
|
129
|
+
const {
|
|
130
|
+
id
|
|
131
|
+
} = commentedIssue;
|
|
132
|
+
|
|
133
|
+
const issue = await store.getIssueById(id);
|
|
134
|
+
|
|
135
|
+
let comments = Array.isArray(issue.comments)
|
|
136
|
+
? issue.comments
|
|
137
|
+
: [];
|
|
138
|
+
|
|
139
|
+
if (action === 'created') {
|
|
140
|
+
comments = [
|
|
141
|
+
...comments,
|
|
142
|
+
comment
|
|
143
|
+
];
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (action === 'deleted') {
|
|
147
|
+
const index = comments.findIndex(c => c.id === comment.id);
|
|
148
|
+
|
|
149
|
+
if (index !== -1) {
|
|
150
|
+
comments = [
|
|
151
|
+
...comments.slice(0, index),
|
|
152
|
+
...comments.slice(index + 1)
|
|
153
|
+
];
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (action === 'edited') {
|
|
158
|
+
|
|
159
|
+
const index = comments.findIndex(c => c.id === comment.id);
|
|
160
|
+
|
|
161
|
+
if (index !== -1) {
|
|
162
|
+
comments = [
|
|
163
|
+
...comments.slice(0, index),
|
|
164
|
+
comment,
|
|
165
|
+
...comments.slice(index + 1)
|
|
166
|
+
];
|
|
167
|
+
} else {
|
|
168
|
+
comments = [
|
|
169
|
+
...comments,
|
|
170
|
+
comment
|
|
171
|
+
];
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
await store.updateIssue({
|
|
176
|
+
...commentedIssue,
|
|
177
|
+
comments
|
|
178
|
+
});
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
module.exports = GithubComments;
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
function filterComment(comment) {
|
|
187
|
+
|
|
188
|
+
const {
|
|
189
|
+
id,
|
|
190
|
+
node_id,
|
|
191
|
+
body,
|
|
192
|
+
created_at,
|
|
193
|
+
html_url,
|
|
194
|
+
user
|
|
195
|
+
} = comment;
|
|
196
|
+
|
|
197
|
+
return {
|
|
198
|
+
id,
|
|
199
|
+
node_id,
|
|
200
|
+
body,
|
|
201
|
+
created_at,
|
|
202
|
+
html_url,
|
|
203
|
+
user: filterUser(user)
|
|
204
|
+
};
|
|
205
|
+
}
|