@pipedream/linear_app 0.5.6 → 0.5.7
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/package.json +1 -1
- package/sources/comment-created-instant/comment-created-instant.mjs +7 -2
- package/sources/common/webhook.mjs +90 -69
- package/sources/issue-created-instant/issue-created-instant.mjs +7 -2
- package/sources/issue-updated-instant/issue-updated-instant.mjs +10 -5
- package/sources/new-issue-status-updated/new-issue-status-updated.mjs +50 -7
package/package.json
CHANGED
|
@@ -5,9 +5,9 @@ export default {
|
|
|
5
5
|
...common,
|
|
6
6
|
key: "linear_app-comment-created-instant",
|
|
7
7
|
name: "New Created Comment (Instant)",
|
|
8
|
-
description: "Emit new event when a new comment is created. See the
|
|
8
|
+
description: "Emit new event when a new comment is created. [See the documentation](https://developers.linear.app/docs/graphql/webhooks)",
|
|
9
9
|
type: "source",
|
|
10
|
-
version: "0.1.
|
|
10
|
+
version: "0.1.7",
|
|
11
11
|
dedupe: "unique",
|
|
12
12
|
methods: {
|
|
13
13
|
...common.methods,
|
|
@@ -50,6 +50,11 @@ export default {
|
|
|
50
50
|
},
|
|
51
51
|
};
|
|
52
52
|
},
|
|
53
|
+
getResource(comment) {
|
|
54
|
+
return this.linearApp.getComment({
|
|
55
|
+
commentId: comment.id,
|
|
56
|
+
});
|
|
57
|
+
},
|
|
53
58
|
getMetadata(resource) {
|
|
54
59
|
const {
|
|
55
60
|
delivery,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import linearApp from "../../linear_app.app.mjs";
|
|
2
2
|
import constants from "../../common/constants.mjs";
|
|
3
3
|
import utils from "../../common/utils.mjs";
|
|
4
|
-
import {
|
|
4
|
+
import { DEFAULT_POLLING_SOURCE_TIMER_INTERVAL } from "@pipedream/platform";
|
|
5
5
|
|
|
6
6
|
export default {
|
|
7
7
|
props: {
|
|
@@ -21,18 +21,28 @@ export default {
|
|
|
21
21
|
"projectId",
|
|
22
22
|
],
|
|
23
23
|
},
|
|
24
|
-
http: "$.interface.http",
|
|
25
24
|
db: "$.service.db",
|
|
26
25
|
},
|
|
27
26
|
async additionalProps() {
|
|
28
27
|
const props = {};
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
28
|
+
let msg;
|
|
29
|
+
if (await this.isAdmin()) {
|
|
30
|
+
msg = "Admin role detected. Trigger will be set up as a webhook.";
|
|
31
|
+
props.http = "$.interface.http";
|
|
32
|
+
} else {
|
|
33
|
+
msg = "No admin role detected. Trigger will set up to use polling.";
|
|
34
|
+
props.timer = {
|
|
35
|
+
type: "$.interface.timer",
|
|
36
|
+
default: {
|
|
37
|
+
intervalSeconds: DEFAULT_POLLING_SOURCE_TIMER_INTERVAL,
|
|
38
|
+
},
|
|
34
39
|
};
|
|
35
40
|
}
|
|
41
|
+
props.alert = {
|
|
42
|
+
type: "alert",
|
|
43
|
+
alertType: "info",
|
|
44
|
+
content: `${msg} See the Linear [documentation](https://linear.app/docs/api-and-webhooks#webhooks) for details.`,
|
|
45
|
+
};
|
|
36
46
|
return props;
|
|
37
47
|
},
|
|
38
48
|
methods: {
|
|
@@ -54,6 +64,9 @@ export default {
|
|
|
54
64
|
useGraphQl() {
|
|
55
65
|
return true;
|
|
56
66
|
},
|
|
67
|
+
getResource() {
|
|
68
|
+
throw new Error("getResource is not implemented");
|
|
69
|
+
},
|
|
57
70
|
getResourceTypes() {
|
|
58
71
|
throw new Error("getResourceTypes is not implemented");
|
|
59
72
|
},
|
|
@@ -85,15 +98,7 @@ export default {
|
|
|
85
98
|
});
|
|
86
99
|
return data?.user?.admin;
|
|
87
100
|
},
|
|
88
|
-
|
|
89
|
-
hooks: {
|
|
90
|
-
async deploy() {
|
|
91
|
-
if (!(await this.isAdmin())) {
|
|
92
|
-
throw new ConfigurationError("You must have an admin role to create or manage webhooks. See the Linear [documentation](https://linear.app/docs/api-and-webhooks#webhooks) for details.");
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// Retrieve historical events
|
|
96
|
-
console.log("Retrieving historical events...");
|
|
101
|
+
async emitPolledResources() {
|
|
97
102
|
const stream = this.linearApp.paginateResources({
|
|
98
103
|
resourcesFn: this.getResourcesFn(),
|
|
99
104
|
resourcesFnArgs: this.getResourcesFnArgs(),
|
|
@@ -107,73 +112,89 @@ export default {
|
|
|
107
112
|
this.$emit(resource, this.getMetadata(resource));
|
|
108
113
|
});
|
|
109
114
|
},
|
|
115
|
+
},
|
|
116
|
+
hooks: {
|
|
117
|
+
async deploy() {
|
|
118
|
+
// Retrieve historical events
|
|
119
|
+
console.log("Retrieving historical events...");
|
|
120
|
+
await this.emitPolledResources();
|
|
121
|
+
},
|
|
110
122
|
async activate() {
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
this.
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
const
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
123
|
+
if (await this.isAdmin()) {
|
|
124
|
+
const args = {
|
|
125
|
+
resourceTypes: this.getResourceTypes(),
|
|
126
|
+
url: this.http.endpoint,
|
|
127
|
+
label: this.getWebhookLabel(),
|
|
128
|
+
};
|
|
129
|
+
if (!this.teamIds && !this.teamId) {
|
|
130
|
+
args.allPublicTeams = true;
|
|
131
|
+
const { _webhook: webhook } = await this.linearApp.createWebhook(args);
|
|
132
|
+
this.setWebhookId("1", webhook.id);
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
const teamIds = this.teamIds || [
|
|
136
|
+
this.teamId,
|
|
137
|
+
];
|
|
138
|
+
for (const teamId of teamIds) {
|
|
139
|
+
const { _webhook: webhook } =
|
|
140
|
+
await this.linearApp.createWebhook({
|
|
141
|
+
teamId,
|
|
142
|
+
...args,
|
|
143
|
+
});
|
|
144
|
+
this.setWebhookId(teamId, webhook.id);
|
|
145
|
+
}
|
|
132
146
|
}
|
|
133
147
|
},
|
|
134
148
|
async deactivate() {
|
|
135
|
-
if (
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
149
|
+
if (await this.isAdmin()) {
|
|
150
|
+
if (!this.teamIds && !this.teamId) {
|
|
151
|
+
const webhookId = this.getWebhookId("1");
|
|
152
|
+
if (webhookId) {
|
|
153
|
+
await this.linearApp.deleteWebhook(webhookId);
|
|
154
|
+
}
|
|
155
|
+
return;
|
|
139
156
|
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
await this.linearApp.deleteWebhook(webhookId);
|
|
157
|
+
const teamIds = this.teamIds || [
|
|
158
|
+
this.teamId,
|
|
159
|
+
];
|
|
160
|
+
for (const teamId of teamIds) {
|
|
161
|
+
const webhookId = this.getWebhookId(teamId);
|
|
162
|
+
if (webhookId) {
|
|
163
|
+
await this.linearApp.deleteWebhook(webhookId);
|
|
164
|
+
}
|
|
149
165
|
}
|
|
150
166
|
}
|
|
151
167
|
},
|
|
152
168
|
},
|
|
153
169
|
async run(event) {
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
170
|
+
if (!(await this.isAdmin())) {
|
|
171
|
+
await this.emitPolledResources();
|
|
172
|
+
} else {
|
|
173
|
+
const {
|
|
174
|
+
client_ip: clientIp,
|
|
175
|
+
body,
|
|
176
|
+
headers,
|
|
177
|
+
} = event;
|
|
159
178
|
|
|
160
|
-
|
|
179
|
+
const { [constants.LINEAR_DELIVERY_HEADER]: delivery } = headers;
|
|
161
180
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
181
|
+
const resource = {
|
|
182
|
+
...body,
|
|
183
|
+
delivery,
|
|
184
|
+
};
|
|
166
185
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
186
|
+
if (!this.isWebhookValid(clientIp)) {
|
|
187
|
+
console.log("Webhook is not valid");
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
171
190
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
191
|
+
if (!(await this.isFromProject(body)) || !this.isRelevant(body)) {
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
175
194
|
|
|
176
|
-
|
|
177
|
-
|
|
195
|
+
const meta = this.getMetadata(resource);
|
|
196
|
+
const item = await this.getResource(body.data);
|
|
197
|
+
this.$emit(item, meta);
|
|
198
|
+
}
|
|
178
199
|
},
|
|
179
200
|
};
|
|
@@ -5,9 +5,9 @@ export default {
|
|
|
5
5
|
...common,
|
|
6
6
|
key: "linear_app-issue-created-instant",
|
|
7
7
|
name: "New Created Issue (Instant)",
|
|
8
|
-
description: "Emit new event when a new issue is created. See the
|
|
8
|
+
description: "Emit new event when a new issue is created. [See the documentation](https://developers.linear.app/docs/graphql/webhooks)",
|
|
9
9
|
type: "source",
|
|
10
|
-
version: "0.3.
|
|
10
|
+
version: "0.3.7",
|
|
11
11
|
dedupe: "unique",
|
|
12
12
|
methods: {
|
|
13
13
|
...common.methods,
|
|
@@ -42,6 +42,11 @@ export default {
|
|
|
42
42
|
isRelevant(body) {
|
|
43
43
|
return body?.action === "create";
|
|
44
44
|
},
|
|
45
|
+
getResource(issue) {
|
|
46
|
+
return this.linearApp.getIssue({
|
|
47
|
+
issueId: issue.id,
|
|
48
|
+
});
|
|
49
|
+
},
|
|
45
50
|
getMetadata(resource) {
|
|
46
51
|
const {
|
|
47
52
|
delivery,
|
|
@@ -5,9 +5,9 @@ export default {
|
|
|
5
5
|
...common,
|
|
6
6
|
key: "linear_app-issue-updated-instant",
|
|
7
7
|
name: "New Updated Issue (Instant)",
|
|
8
|
-
description: "Emit new event when an issue is updated. See the
|
|
8
|
+
description: "Emit new event when an issue is updated. [See the documentation](https://developers.linear.app/docs/graphql/webhooks)",
|
|
9
9
|
type: "source",
|
|
10
|
-
version: "0.3.
|
|
10
|
+
version: "0.3.7",
|
|
11
11
|
dedupe: "unique",
|
|
12
12
|
methods: {
|
|
13
13
|
...common.methods,
|
|
@@ -39,17 +39,22 @@ export default {
|
|
|
39
39
|
},
|
|
40
40
|
};
|
|
41
41
|
},
|
|
42
|
+
getResource(issue) {
|
|
43
|
+
return this.linearApp.getIssue({
|
|
44
|
+
issueId: issue.id,
|
|
45
|
+
});
|
|
46
|
+
},
|
|
42
47
|
getMetadata(resource) {
|
|
43
48
|
const {
|
|
44
|
-
delivery,
|
|
45
49
|
title,
|
|
46
50
|
data,
|
|
47
51
|
updatedAt,
|
|
48
52
|
} = resource;
|
|
53
|
+
const ts = Date.parse(data?.updatedAt || updatedAt);
|
|
49
54
|
return {
|
|
50
|
-
id:
|
|
55
|
+
id: `${resource.id}-${ts}`,
|
|
51
56
|
summary: `Issue Updated: ${data?.title || title}`,
|
|
52
|
-
ts
|
|
57
|
+
ts,
|
|
53
58
|
};
|
|
54
59
|
},
|
|
55
60
|
},
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import common from "../common/webhook.mjs";
|
|
2
2
|
import constants from "../../common/constants.mjs";
|
|
3
|
+
import utils from "../../common/utils.mjs";
|
|
3
4
|
|
|
4
5
|
export default {
|
|
5
6
|
...common,
|
|
6
7
|
key: "linear_app-new-issue-status-updated",
|
|
7
8
|
name: "New Issue Status Updated (Instant)",
|
|
8
|
-
description: "Emit new event when the status of an issue is updated. See the
|
|
9
|
+
description: "Emit new event when the status of an issue is updated. [See the documentation](https://developers.linear.app/docs/graphql/webhooks)",
|
|
9
10
|
type: "source",
|
|
10
|
-
version: "0.1.
|
|
11
|
+
version: "0.1.7",
|
|
11
12
|
dedupe: "unique",
|
|
12
13
|
props: {
|
|
13
14
|
linearApp: common.props.linearApp,
|
|
14
|
-
|
|
15
|
-
db: common.props.db,
|
|
15
|
+
db: "$.service.db",
|
|
16
16
|
teamId: {
|
|
17
17
|
label: "Team ID",
|
|
18
18
|
type: "string",
|
|
@@ -20,7 +20,7 @@ export default {
|
|
|
20
20
|
common.props.linearApp,
|
|
21
21
|
"teamId",
|
|
22
22
|
],
|
|
23
|
-
|
|
23
|
+
reloadProps: true,
|
|
24
24
|
},
|
|
25
25
|
projectId: {
|
|
26
26
|
propDefinition: [
|
|
@@ -41,6 +41,12 @@ export default {
|
|
|
41
41
|
},
|
|
42
42
|
methods: {
|
|
43
43
|
...common.methods,
|
|
44
|
+
_getPreviousStatuses() {
|
|
45
|
+
return this.db.get("previousStatuses") || {};
|
|
46
|
+
},
|
|
47
|
+
_setPreviousStatuses(previousStatuses) {
|
|
48
|
+
this.db.set("previousStatuses", previousStatuses);
|
|
49
|
+
},
|
|
44
50
|
getResourceTypes() {
|
|
45
51
|
return [
|
|
46
52
|
constants.RESOURCE_TYPE.ISSUE,
|
|
@@ -79,6 +85,11 @@ export default {
|
|
|
79
85
|
isRelevant(body) {
|
|
80
86
|
return body?.updatedFrom?.stateId && (!this.stateId || body.data.stateId === this.stateId);
|
|
81
87
|
},
|
|
88
|
+
getResource(issue) {
|
|
89
|
+
return this.linearApp.getIssue({
|
|
90
|
+
issueId: issue.id,
|
|
91
|
+
});
|
|
92
|
+
},
|
|
82
93
|
getMetadata(resource) {
|
|
83
94
|
const {
|
|
84
95
|
delivery,
|
|
@@ -86,11 +97,43 @@ export default {
|
|
|
86
97
|
data,
|
|
87
98
|
updatedAt,
|
|
88
99
|
} = resource;
|
|
100
|
+
const ts = Date.parse(updatedAt);
|
|
89
101
|
return {
|
|
90
|
-
id: delivery || resource.id
|
|
102
|
+
id: delivery || `${resource.id}-${ts}`,
|
|
91
103
|
summary: `Issue status updated: ${data?.title || title}`,
|
|
92
|
-
ts
|
|
104
|
+
ts,
|
|
93
105
|
};
|
|
94
106
|
},
|
|
107
|
+
async emitPolledResources() {
|
|
108
|
+
const previousStatuses = this._getPreviousStatuses();
|
|
109
|
+
const newStatuses = {};
|
|
110
|
+
|
|
111
|
+
const stream = this.linearApp.paginateResources({
|
|
112
|
+
resourcesFn: this.getResourcesFn(),
|
|
113
|
+
resourcesFnArgs: this.getResourcesFnArgs(),
|
|
114
|
+
useGraphQl: this.useGraphQl(),
|
|
115
|
+
max: 1000,
|
|
116
|
+
});
|
|
117
|
+
const resources = await utils.streamIterator(stream);
|
|
118
|
+
|
|
119
|
+
const updatedResources = [];
|
|
120
|
+
for (const issue of resources) {
|
|
121
|
+
newStatuses[issue.id] = issue.state.id;
|
|
122
|
+
if (issue.createdAt === issue.updatedAt) {
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
if (previousStatuses[issue.id] !== issue.state.id) {
|
|
126
|
+
updatedResources.push(issue);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
this._setPreviousStatuses(newStatuses);
|
|
131
|
+
|
|
132
|
+
updatedResources
|
|
133
|
+
.reverse()
|
|
134
|
+
.forEach((resource) => {
|
|
135
|
+
this.$emit(resource, this.getMetadata(resource));
|
|
136
|
+
});
|
|
137
|
+
},
|
|
95
138
|
},
|
|
96
139
|
};
|