Skip to content

Commit 1a3cf02

Browse files
committed
new component
1 parent 43ca975 commit 1a3cf02

File tree

5 files changed

+201
-84
lines changed

5 files changed

+201
-84
lines changed
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
const ENTITIES = [
2+
{
3+
value: "api:addon-attachment",
4+
label: "addon-attachment - An add-on has been attached or removed from the app",
5+
},
6+
{
7+
value: "api:addon",
8+
label: "addon - An add-on for the app has been newly provisioned or deleted, or its details have been modified",
9+
},
10+
{
11+
value: "api:app",
12+
label: "app - The app itself has been provisioned or deleted, or its details have been modified",
13+
},
14+
{
15+
value: "api:build",
16+
label: "build - A new build for the app has been initiated or the build’s status has changed since the last notification",
17+
},
18+
{
19+
value: "api:collaborator",
20+
label: "collaborator - A collaborator has been added or removed from the app, or an existing collaborator’s details have been modified",
21+
},
22+
{
23+
value: "api:domain",
24+
label: "domain - Custom domain details have been added or removed from the app",
25+
},
26+
{
27+
value: "api:dyno",
28+
label: "dyno - A new dyno has begun running for the app",
29+
},
30+
{
31+
value: "api:formation",
32+
label: "formation - The dyno formation for a particular process type has been modified",
33+
},
34+
{
35+
value: "api:release",
36+
label: "release - A new release for the app has been initiated or the release’s status has changed since the last notification",
37+
},
38+
{
39+
value: "api:sni-endpoint",
40+
label: "sni-endpoint - An SNI endpoint has been specified or removed for the app, or the existing SNI endpoint’s details have been modified",
41+
},
42+
];
43+
44+
export default {
45+
ENTITIES,
46+
};

components/heroku/heroku.app.mjs

Lines changed: 26 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { axios } from "@pipedream/platform";
2+
import constants from "./common/constants.mjs";
23

34
export default {
45
type: "app",
@@ -9,83 +10,62 @@ export default {
910
label: "App ID",
1011
description: "The ID of the app",
1112
async options() {
12-
const { data } = await this.listApps();
13-
return data.map((app) => ({
13+
const apps = await this.listApps();
14+
return apps?.map((app) => ({
1415
label: app.name,
1516
value: app.id,
16-
}));
17+
})) || [];
1718
},
1819
},
19-
entity: {
20+
entities: {
2021
type: "string[]",
21-
label: "Entity",
22-
description: "The entity to subscribe to",
23-
options: [
24-
"api:addon-attachment",
25-
"api:addon",
26-
"api:app",
27-
"api:build",
28-
"api:collaborator",
29-
"api:domain",
30-
"api:dyno",
31-
"api:formation",
32-
"api:release",
33-
"api:sni-endpoint",
34-
],
35-
},
36-
eventTypes: {
37-
type: "string[]",
38-
label: "Event Types",
39-
description: "The types of events to subscribe to",
40-
options: [
41-
"create",
42-
"destroy",
43-
"update",
44-
],
22+
label: "Entities",
23+
description: "The entity or entities to subscribe to",
24+
options: constants.ENTITIES,
4525
},
4626
},
4727
methods: {
4828
_baseUrl() {
4929
return "https://api.heroku.com";
5030
},
51-
async _makeRequest(opts = {}) {
31+
_makeRequest(opts = {}) {
5232
const {
5333
$ = this,
54-
method = "GET",
5534
path,
56-
headers,
5735
...otherOpts
5836
} = opts;
5937
return axios($, {
6038
...otherOpts,
61-
method,
62-
url: this._baseUrl() + path,
39+
url: `${this._baseUrl()}${path}`,
6340
headers: {
64-
...headers,
65-
"Authorization": `Bearer ${this.$auth.oauth_access_token}`,
41+
Authorization: `Bearer ${this.$auth.oauth_access_token}`,
42+
Accept: "application/vnd.heroku+json; version=3",
6643
},
6744
});
6845
},
69-
async listApps() {
46+
listApps(opts = {}) {
7047
return this._makeRequest({
7148
path: "/apps",
49+
...opts,
7250
});
7351
},
74-
async createWebhookSubscription(appId, entity) {
52+
createWebhookSubscription({
53+
appId, ...opts
54+
}) {
7555
return this._makeRequest({
7656
method: "POST",
7757
path: `/apps/${appId}/webhooks`,
78-
data: {
79-
include: entity,
80-
level: "notify",
81-
secret: "my_secret",
82-
url: "https://example.com/hooks",
83-
authorization: this.$auth.oauth_access_token,
84-
},
58+
...opts,
8559
});
8660
},
87-
authKeys() {
88-
console.log(Object.keys(this.$auth));
61+
deleteWebhookSubscription({
62+
appId, hookId, ...opts
63+
}) {
64+
return this._makeRequest({
65+
method: "DELETE",
66+
path: `/apps/${appId}/webhooks/${hookId}`,
67+
...opts,
68+
});
8969
},
9070
},
9171
};

components/heroku/package.json

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"name": "@pipedream/heroku",
3+
"version": "0.0.1",
4+
"description": "Pipedream Heroku Components",
5+
"main": "heroku.app.mjs",
6+
"keywords": [
7+
"pipedream",
8+
"heroku"
9+
],
10+
"homepage": "https://pipedream.com/apps/heroku",
11+
"author": "Pipedream <[email protected]> (https://pipedream.com/)",
12+
"publishConfig": {
13+
"access": "public"
14+
},
15+
"dependencies": {
16+
"@pipedream/platform": "^3.0.3"
17+
}
18+
}
Lines changed: 42 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,70 +1,74 @@
11
import heroku from "../../heroku.app.mjs";
2+
import sampleEmit from "./test-event.mjs";
23

34
export default {
45
key: "heroku-new-webhook-event-instant",
5-
name: "New Webhook Event Instant",
6-
description: "Emit new event on each webhook event. [See the documentation](https://devcenter.heroku.com/categories/platform-api)",
7-
version: "0.0.{{ts}}",
6+
name: "New Webhook Event (Instant)",
7+
description: "Emit new event on each webhook event. [See the documentation](https://devcenter.heroku.com/articles/app-webhooks-schema#webhook-create)",
8+
version: "0.0.1",
89
type: "source",
910
dedupe: "unique",
1011
props: {
1112
heroku,
12-
http: {
13-
type: "$.interface.http",
14-
customResponse: false,
15-
},
13+
http: "$.interface.http",
1614
db: "$.service.db",
1715
appId: {
1816
propDefinition: [
1917
heroku,
2018
"appId",
2119
],
2220
},
23-
entity: {
24-
propDefinition: [
25-
heroku,
26-
"entity",
27-
],
28-
},
29-
eventTypes: {
21+
entities: {
3022
propDefinition: [
3123
heroku,
32-
"eventTypes",
24+
"entities",
3325
],
3426
},
3527
},
3628
hooks: {
3729
async activate() {
38-
const webhookId = await this.heroku.createWebhookSubscription(
39-
this.appId,
40-
this.entity,
41-
this.eventTypes,
42-
);
43-
this.db.set("webhookId", webhookId);
30+
const { id } = await this.heroku.createWebhookSubscription({
31+
appId: this.appId,
32+
data: {
33+
include: this.entities,
34+
level: "notify",
35+
url: this.http.endpoint,
36+
},
37+
});
38+
this._setHookId(id);
4439
},
4540
async deactivate() {
46-
const webhookId = this.db.get("webhookId");
47-
if (webhookId) {
48-
await this.heroku.deleteWebhookSubscription(webhookId);
41+
const hookId = this._getHookId();
42+
if (hookId) {
43+
await this.heroku.deleteWebhookSubscription({
44+
appId: this.appId,
45+
hookId,
46+
});
4947
}
5048
},
5149
},
50+
methods: {
51+
_getHookId() {
52+
return this.db.get("hookId");
53+
},
54+
_setHookId(hookId) {
55+
this.db.set("hookId", hookId);
56+
},
57+
generateMeta(event) {
58+
return {
59+
id: event.id,
60+
summary: `New ${event.webhook_metadata.event.include} - ${event.action} Event`,
61+
ts: Date.now(),
62+
};
63+
},
64+
},
5265
async run(event) {
53-
const {
54-
body, headers,
55-
} = event;
56-
57-
// Validate the incoming webhook payload
58-
if (headers["heroku-webhook-hmac-sha256"] !== this.heroku.$auth.webhook_secret) {
59-
console.log("Invalid signature");
66+
const { body } = event;
67+
if (!body) {
6068
return;
6169
}
62-
63-
// Emit the event
64-
this.$emit(body, {
65-
id: body.id,
66-
summary: `New event: ${body.event_type}`,
67-
ts: Date.parse(body.created_at),
68-
});
70+
const meta = this.generateMeta(body);
71+
this.$emit(body, meta);
6972
},
73+
sampleEmit,
7074
};
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
export default {
2+
"id": "a5b27512-1f14-4f45-bc26-fe6bf03686fe",
3+
"data": {
4+
"id": "9a4eaeed-24cc-4b23-a8ca-7867b251eaf3",
5+
"acm": false,
6+
"name": "",
7+
"team": null,
8+
"owner": {
9+
"id": "7b25912d-b147-48d6-b03d-f0fc72be381b",
10+
"email": ""
11+
},
12+
"space": null,
13+
"stack": {
14+
"id": "74cfe988-7527-4ca9-9667-77bb9f3029cf",
15+
"name": "heroku-24"
16+
},
17+
"region": {
18+
"id": "59accabd-516d-4f0e-83e6-6e3757701145",
19+
"name": "us"
20+
},
21+
"git_url": "",
22+
"web_url": "",
23+
"repo_size": null,
24+
"slug_size": null,
25+
"created_at": "2024-11-07T16:38:38Z",
26+
"updated_at": "2024-11-07T17:14:52Z",
27+
"archived_at": null,
28+
"build_stack": {
29+
"id": "74cfe988-7527-4ca9-9667-77bb9f3029cf",
30+
"name": "heroku-24"
31+
},
32+
"maintenance": false,
33+
"released_at": "2024-11-07T16:38:39Z",
34+
"organization": null,
35+
"internal_routing": null,
36+
"buildpack_provided_description": null
37+
},
38+
"actor": {
39+
"id": "7b25912d-b147-48d6-b03d-f0fc72be381b",
40+
"email": ""
41+
},
42+
"action": "update",
43+
"version": "application/vnd.heroku+json; version=3",
44+
"resource": "app",
45+
"sequence": null,
46+
"created_at": "2024-11-07T17:14:52.475272Z",
47+
"updated_at": "2024-11-07T17:14:52.475276Z",
48+
"published_at": "2024-11-07T17:14:52Z",
49+
"previous_data": {
50+
"name": "",
51+
"git_url": "",
52+
"updated_at": "2024-11-07T17:13:42Z"
53+
},
54+
"webhook_metadata": {
55+
"attempt": {
56+
"id": "16e90948-01d8-4ba0-97de-5868a4aed0bf"
57+
},
58+
"delivery": {
59+
"id": "bbf72057-15f2-40b0-87c7-99ccf95e1666"
60+
},
61+
"event": {
62+
"id": "a5b27512-1f14-4f45-bc26-fe6bf03686fe",
63+
"include": "api:app"
64+
},
65+
"webhook": {
66+
"id": "c385bb39-42ab-49c6-9255-108ff4cabdbd"
67+
}
68+
}
69+
}

0 commit comments

Comments
 (0)