Skip to content

Commit 577bd0f

Browse files
Notion - new sources (#18202)
* new sources * pnpm-lock.yaml * update * Update webhook setup instructions for clarity and detail --------- Co-authored-by: Leo Vu <[email protected]>
1 parent 0ae47eb commit 577bd0f

File tree

7 files changed

+246
-3
lines changed

7 files changed

+246
-3
lines changed

components/notion/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@pipedream/notion",
3-
"version": "0.9.1",
3+
"version": "0.10.0",
44
"description": "Pipedream Notion Components",
55
"main": "notion.app.mjs",
66
"keywords": [
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import notion from "../../notion.app.mjs";
2+
import {
3+
createHmac, timingSafeEqual,
4+
} from "crypto";
5+
import { ConfigurationError } from "@pipedream/platform";
6+
7+
export default {
8+
props: {
9+
notion,
10+
db: "$.service.db",
11+
http: "$.interface.http",
12+
info: {
13+
type: "alert",
14+
alertType: "info",
15+
content: `1. Create this Pipedream source and copy the Source Endpoint URL.
16+
2. In Notion, create a webhook subscription and paste the Source Endpoint URL as the webhook URL. See Notion's guide: https://developers.notion.com/reference/webhooks#step-1-creating-a-webhook-subscription
17+
3. After adding the subscription in Notion, you'll be prompted to verify the webhook using a secret. Open the Source Logs tab in this Pipedream source to find the verification secret (token) and enter it in Notion to complete verification.`,
18+
},
19+
},
20+
methods: {
21+
_getToken() {
22+
return this.db.get("token");
23+
},
24+
_setToken(token) {
25+
this.db.set("token", token);
26+
},
27+
verifyWebhook(token, body, headers) {
28+
const calculatedSignature = `sha256=${createHmac("sha256", token).update(JSON.stringify(body))
29+
.digest("hex")}`;
30+
return timingSafeEqual(
31+
Buffer.from(calculatedSignature),
32+
Buffer.from(headers["x-notion-signature"]),
33+
);
34+
},
35+
processEvent() {
36+
throw new ConfigurationError("processEvent must be implemented in the source");
37+
},
38+
},
39+
async run(event) {
40+
const {
41+
body, headers,
42+
} = event;
43+
if (!body) {
44+
return;
45+
}
46+
const token = this._getToken();
47+
if (body.verification_token && !token) {
48+
this._setToken(body.verification_token);
49+
console.log(`Verification token: ${body.verification_token}. Enter this in your Notion webhook settings.`);
50+
return;
51+
}
52+
if (!this.verifyWebhook(token, body, headers)) {
53+
throw new Error("Invalid webhook signature");
54+
}
55+
56+
await this.processEvent(body);
57+
},
58+
};
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import common from "../common/base-webhook.mjs";
2+
import sampleEmit from "./test-event.mjs";
3+
4+
export default {
5+
...common,
6+
key: "notion-new-webhook-event-instant",
7+
name: "New Webhook Event (Instant)",
8+
description: "Emit new event each time a webhook event is received. Webhook must be setup in Notion. [See the documentation](https://developers.notion.com/reference/webhooks#step-1-creating-a-webhook-subscription)",
9+
version: "0.0.1",
10+
type: "source",
11+
dedupe: "unique",
12+
methods: {
13+
...common.methods,
14+
_generateMeta(event) {
15+
return {
16+
id: event.id,
17+
summary: `Webhook event: ${event.type}`,
18+
ts: Date.now(),
19+
};
20+
},
21+
processEvent(event) {
22+
const meta = this._generateMeta(event);
23+
this.$emit(event, meta);
24+
},
25+
},
26+
sampleEmit,
27+
};
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
export default {
2+
"id": "555831bd-c1d6-400b-873e-42b10fb7f7e8",
3+
"timestamp": "2025-08-27T20:51:19.356Z",
4+
"workspace_id": "e0f732bd-e43f-4db3-b923-8a12ffdbfcce",
5+
"workspace_name": "Notion",
6+
"subscription_id": "25cd872b-594c-8181-982c-009998a96535",
7+
"integration_id": "1ded872b-594c-804e-88d9-0037511f15c1",
8+
"authors": [
9+
{
10+
"id": "22da95d5-0f61-4b51-963d-63c4cf51ae19",
11+
"type": "person"
12+
}
13+
],
14+
"attempt_number": 1,
15+
"api_version": "2022-06-28",
16+
"entity": {
17+
"id": "10773a03-a25e-8061-8256-f26813633a59",
18+
"type": "page"
19+
},
20+
"type": "page.properties_updated",
21+
"data": {
22+
"parent": {
23+
"id": "9813bf8c-a429-4d63-b73b-f476783ff448",
24+
"type": "database",
25+
"data_source_id": "dabbe504-b5ff-48f1-a1fa-d5fea5ef9ac4"
26+
},
27+
"updated_properties": [
28+
"title"
29+
]
30+
}
31+
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import common from "../common/base-webhook.mjs";
2+
import sampleEmit from "./test-event.mjs";
3+
4+
export default {
5+
...common,
6+
key: "notion-page-properties-updated-instant",
7+
name: "Page Properties Updated (Instant)",
8+
description: "Emit new event each time a page property is updated in a database. For use with Page Properties Updated event type. Webhook must be set up in Notion. [See the documentation](https://developers.notion.com/reference/webhooks#step-1-creating-a-webhook-subscription)",
9+
version: "0.0.1",
10+
type: "source",
11+
dedupe: "unique",
12+
props: {
13+
...common.props,
14+
databaseId: {
15+
propDefinition: [
16+
common.props.notion,
17+
"databaseId",
18+
],
19+
},
20+
properties: {
21+
type: "string[]",
22+
label: "Properties",
23+
description: "Only emit events when one or more of the selected properties have changed",
24+
optional: true,
25+
async options() {
26+
try {
27+
const { properties } = await this.notion.retrieveDatabase(this.databaseId);
28+
const propEntries = Object.entries(properties);
29+
return propEntries.map((prop) => ({
30+
label: prop[1].name,
31+
value: prop[1].id,
32+
}));
33+
} catch (error) {
34+
console.log(error);
35+
return [];
36+
}
37+
},
38+
},
39+
},
40+
methods: {
41+
...common.methods,
42+
_generateMeta(page) {
43+
const { id } = page;
44+
const title = this.notion.extractPageTitle(page);
45+
const ts = Date.now();
46+
return {
47+
id: `${id}-${ts}`,
48+
summary: `Page updated: ${title}`,
49+
ts,
50+
};
51+
},
52+
async processEvent(event) {
53+
if (event?.type !== "page.properties_updated") {
54+
console.log(`Skipping event type: ${event?.type}`);
55+
return;
56+
}
57+
58+
if (event.data.parent.id !== this.databaseId) {
59+
console.log(`Skipping event for database: ${event.data.parent.id}`);
60+
return;
61+
}
62+
63+
const updatedProperties = event.data.updated_properties;
64+
if (!updatedProperties?.length) {
65+
return;
66+
}
67+
68+
let propertyHasChanged = false;
69+
for (const propertyName of updatedProperties) {
70+
if (!this.properties || this.properties.includes(propertyName)) {
71+
propertyHasChanged = true;
72+
}
73+
}
74+
75+
if (!propertyHasChanged) {
76+
return;
77+
}
78+
79+
const page = await this.notion.retrievePage(event.entity.id);
80+
81+
const meta = this._generateMeta(page);
82+
this.$emit({
83+
...event,
84+
page,
85+
}, meta);
86+
},
87+
},
88+
sampleEmit,
89+
};
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
export default {
2+
"id": "1782edd6-a853-4d4a-b02c-9c8c16f28e53",
3+
"timestamp": "2024-12-05T23:57:05.379Z",
4+
"workspace_id": "13950b26-c203-4f3b-b97d-93ec06319565",
5+
"workspace_name": "Quantify Labs",
6+
"subscription_id": "29d75c0d-5546-4414-8459-7b7a92f1fc4b",
7+
"integration_id": "0ef2e755-4912-8096-91c1-00376a88a5ca",
8+
"type": "page.properties_updated",
9+
"authors": [
10+
{
11+
"id": "c7c11cca-1d73-471d-9b6e-bdef51470190",
12+
"type": "person"
13+
}
14+
],
15+
"accessible_by": [
16+
{
17+
"id": "556a1abf-4f08-40c6-878a-75890d2a88ba",
18+
"type": "person"
19+
},
20+
{
21+
"id": "1edc05f6-2702-81b5-8408-00279347f034",
22+
"type": "bot"
23+
}
24+
],
25+
"attempt_number": 1,
26+
"entity": {
27+
"id": "153104cd-477e-809d-8dc4-ff2d96ae3090",
28+
"type": "page"
29+
},
30+
"data": {
31+
"parent": {
32+
"id": "13950b26-c203-4f3b-b97d-93ec06319565",
33+
"type": "space"
34+
},
35+
"updated_properties": ["XGe%40", "bDf%5B", "DbAu"]
36+
}
37+
}

pnpm-lock.yaml

Lines changed: 3 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)