Skip to content

Commit

Permalink
Update examples with new SDK version. (#398)
Browse files Browse the repository at this point in the history
  • Loading branch information
rhart92 authored Apr 12, 2023
1 parent 9d139dc commit ab29303
Show file tree
Hide file tree
Showing 10 changed files with 163 additions and 64 deletions.
37 changes: 24 additions & 13 deletions examples/database-email-update/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@

## About the Integration

This Notion integration sends an email whenever the Status of a page in a database is updated. This sample was built using [this database template](https://www.notion.com/5b593126d3eb401db62c83cbe362d2d5?v=a44397b3675545f389a6f28282c402ae) and emails are sent using [SendGrid's API](https://sendgrid.com).
This Notion integration sends an email whenever the Status of a page in a database is updated.

## Running Locally
This sample was built using [this database template](https://public-api-examples.notion.site/0def5dfb6d9b4cdaa907a0466834b9f4?v=aea75fc133e54b3382d12292291d9248) and emails are sent using [SendGrid's API](https://sendgrid.com).

### 1. Setup your local project

Expand All @@ -21,7 +21,26 @@ cd notion-sdk-js/examples/database-update-send-email
npm install
```

### 2. Set your environment variables in a `.env` file
### 2. Setup a free account at [SendGrid](https://sendgrid.com)

Sign up for a free account and follow the instructions to use the Email API.

Choose the option for integrating with the Web API and follow instructions to
get your API token.

## Running Locally

### 3. Setup your Notion workspace

You can create your Notion API key [here](https://www.notion.com/my-integrations).

To create a Notion database that will work with this example, duplicate [this database template](https://public-api-examples.notion.site/0def5dfb6d9b4cdaa907a0466834b9f4?v=aea75fc133e54b3382d12292291d9248).

Your Notion integration will need access to the Notion database you have created. To provide access, follow the instructions found in Notion's [Integration guide](https://developers.notion.com/docs/create-a-notion-integration#step-2-share-a-database-with-your-integration).

### 4. Set your environment variables to a `.env` file

Rename `example.env` to `.env` in this directory and add the following fields:

```zsh
NOTION_KEY=<your-notion-api-key>
Expand All @@ -31,16 +50,8 @@ EMAIL_TO_FIELD=<email-recipients>
EMAIL_FROM_FIELD=<email-from-field>
```

You can create your Notion API key [here](https://www.notion.com/my-integrations).

You can create your SendGrid API key [here](https://signup.sendgrid.com).

To create a Notion database that will work with this example, duplicate [this template](https://www.notion.com/5b593126d3eb401db62c83cbe362d2d5?v=a44397b3675545f389a6f28282c402ae).

Your Notion integration will need access to the Notion database you have created. To provide access, follow the instructions found in Notion's [Integration guide](https://developers.notion.com/docs/create-a-notion-integration#step-2-share-a-database-with-your-integration).

### 3. Run code
### 5. Run code

```zsh
node index.js
npm run ts-run
```
5 changes: 5 additions & 0 deletions examples/database-email-update/example.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
NOTION_KEY=<your-notion-api-key>
SENDGRID_KEY=<your-sendgrid-api-key>
NOTION_DATABASE_ID=<your-notion-database-id>
EMAIL_TO_FIELD=<email-recipients>
EMAIL_FROM_FIELD=<email-from-field>
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@
================================================================================ */

const { Client } = require("@notionhq/client")
const dotenv = require("dotenv")
const sendgridMail = require("@sendgrid/mail")
import { Client } from "@notionhq/client"
import { config } from "dotenv"
import SendGrid from "@sendgrid/mail"
import { PropertyItemObjectResponse } from "../../build/src/api-endpoints"

dotenv.config()
sendgridMail.setApiKey(process.env.SENDGRID_KEY)
config()
SendGrid.setApiKey(process.env.SENDGRID_KEY)
const notion = new Client({ auth: process.env.NOTION_KEY })

const databaseId = process.env.NOTION_DATABASE_ID
Expand Down Expand Up @@ -59,14 +60,15 @@ async function findAndSendEmailsForUpdatedTasks() {

/**
* Gets tasks from the database.
*
* @returns {Promise<Array<{ pageId: string, status: string, title: string }>>}
*/
async function getTasksFromNotionDatabase() {
async function getTasksFromNotionDatabase(): Promise<
Array<{ pageId: string; status: string; title: string }>
> {
const pages = []
let cursor = undefined

while (true) {
const shouldContinue = true
while (shouldContinue) {
const { results, next_cursor } = await notion.databases.query({
database_id: databaseId,
start_cursor: cursor,
Expand All @@ -88,33 +90,71 @@ async function getTasksFromNotionDatabase() {
pageId,
propertyId: statusPropertyId,
})
const status = statusPropertyItem.select
? statusPropertyItem.select.name
: "No Status"

const status = getStatusPropertyValue(statusPropertyItem)

const titlePropertyId = page.properties["Name"].id
const titlePropertyItems = await getPropertyValue({
pageId,
propertyId: titlePropertyId,
})
const title = titlePropertyItems
.map(propertyItem => propertyItem.title.plain_text)
.join("")
const title = getTitlePropertyValue(titlePropertyItems)

tasks.push({ pageId, status, title })
}

return tasks
}

/**
* Extract status as string from property value
*/
function getStatusPropertyValue(
property: PropertyItemObjectResponse | Array<PropertyItemObjectResponse>
): string {
if (Array.isArray(property)) {
if (property?.[0]?.type === "select") {
return property[0].select.name
} else {
return "No Status"
}
} else {
if (property.type === "select") {
return property.select.name
} else {
return "No Status"
}
}
}

/**
* Extract title as string from property value
*/
function getTitlePropertyValue(
property: PropertyItemObjectResponse | Array<PropertyItemObjectResponse>
): string {
if (Array.isArray(property)) {
if (property?.[0].type === "title") {
return property[0].title.plain_text
} else {
return "No Title"
}
} else {
if (property.type === "title") {
return property.title.plain_text
} else {
return "No Title"
}
}
}

/**
* Compares task to most recent version of task stored in taskPageIdToStatusMap.
* Returns any tasks that have a different status than their last version.
*
* @param {Array<{ pageId: string, status: string, title: string }>} currentTasks
* @returns {Array<{ pageId: string, status: string, title: string }>}
*/
function findUpdatedTasks(currentTasks) {
function findUpdatedTasks(
currentTasks: Array<{ pageId: string; status: string; title: string }>
): Array<{ pageId: string; status: string; title: string }> {
return currentTasks.filter(currentTask => {
const previousStatus = getPreviousTaskStatus(currentTask)
return currentTask.status !== previousStatus
Expand All @@ -123,33 +163,37 @@ function findUpdatedTasks(currentTasks) {

/**
* Sends task update notification using Sendgrid.
*
* @param {{ status: string, title: string }} task
*/
async function sendUpdateEmailWithSendgrid({ title, status }) {
async function sendUpdateEmailWithSendgrid({
title,
status,
}: {
status: string
title: string
}) {
const message = `Status of Notion task ("${title}") has been updated to "${status}".`
console.log(message)

try {
// Send an email about this change.
await sendgridMail.send({
await SendGrid.send({
to: process.env.EMAIL_TO_FIELD,
from: process.env.EMAIL_FROM_FIELD,
subject: "Notion Task Status Updated",
text: message,
})
console.log("Email Sent")
console.log(
`Email Sent to ${process.env.EMAIL_TO_FIELD}, from: ${process.env.EMAIL_FROM_FIELD}`
)
} catch (error) {
console.error(error)
}
}

/**
* Finds or creates task in local data store and returns its status.
* @param {{ pageId: string; status: string }} task
* @returns {string}
*/
function getPreviousTaskStatus({ pageId, status }) {
function getPreviousTaskStatus({ pageId, status }): string {
// If this task hasn't been seen before, add to local pageId to status map.
if (!taskPageIdToStatusMap[pageId]) {
taskPageIdToStatusMap[pageId] = status
Expand All @@ -161,12 +205,15 @@ function getPreviousTaskStatus({ pageId, status }) {
* If property is paginated, returns an array of property items.
*
* Otherwise, it will return a single property item.
*
* @param {{ pageId: string, propertyId: string }}
* @returns {Promise<PropertyItemObject | Array<PropertyItemObject>>}
*/
async function getPropertyValue({ pageId, propertyId }) {
const propertyItem = await notion.pages.properties.retrieve({
async function getPropertyValue({
pageId,
propertyId,
}: {
pageId: string
propertyId: string
}): Promise<PropertyItemObjectResponse | Array<PropertyItemObjectResponse>> {
let propertyItem = await notion.pages.properties.retrieve({
page_id: pageId,
property_id: propertyId,
})
Expand All @@ -179,14 +226,18 @@ async function getPropertyValue({ pageId, propertyId }) {
const results = propertyItem.results

while (nextCursor !== null) {
const propertyItem = await notion.pages.properties.retrieve({
propertyItem = await notion.pages.properties.retrieve({
page_id: pageId,
property_id: propertyId,
start_cursor: nextCursor,
})

nextCursor = propertyItem.next_cursor
results.push(...propertyItem.results)
if (propertyItem.object === "list") {
nextCursor = propertyItem.next_cursor
results.push(...propertyItem.results)
} else {
nextCursor = null
}
}

return results
Expand Down
7 changes: 4 additions & 3 deletions examples/database-email-update/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": ""
"ts-run": "node --loader ts-node/esm index.ts"
},
"dependencies": {
"@notionhq/client": "^2.1.1",
"@notionhq/client": "file:../../",
"@sendgrid/mail": "^7.7.0",
"dotenv": "^16.0.1"
"dotenv": "^16.0.1",
"ts-node": "^10.8.2"
},
"author": "Aman Gupta",
"license": "MIT"
Expand Down
25 changes: 25 additions & 0 deletions examples/database-email-update/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"compilerOptions": {
"incremental": true,
"sourceMap": false,

"target": "ESNext",
"module": "commonjs",

"moduleResolution": "Node",

"allowSyntheticDefaultImports": true,

"useDefineForClassFields": false,

"strict": false,
"suppressImplicitAnyIndexErrors": true,

"isolatedModules": true,
"esModuleInterop": true,
"noUncheckedIndexedAccess": true,
"allowJs": true,
"checkJs": false
},
"include": ["src/**/*"]
}
23 changes: 14 additions & 9 deletions examples/generate-random-data/README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
# API Example
# Sample Integration: Generate Random Data with Notion API

## About the Integration

This integration finds the first database which your bot has access to, and creates correctly typed random rows of data.
It is designed to show and exercise the full types of the Notion API and the typescript bindings.

## Running Locally

Expand All @@ -20,17 +19,23 @@ cd notion-sdk-js/examples/generate-random-data
npm install
```

### 2. Set your environment variables in a `.env` file

```zsh
NOTION_KEY=<your-notion-api-key>
```
### 2. Setup your Notion workspace

You can create your Notion API key [here](https://www.notion.com/my-integrations).

To create a Notion database that will work with this example, duplicate [this empty database template](https://www.notion.com/367cd67cfe8f49bfaf0ac21305ebb9bf?v=bc79ca62b36e4c54b655ceed4ef06ebd).
To create a Notion database that will work with this example, duplicate [this database template](https://public-api-examples.notion.site/f3e098475baa45878759ed8d04ea79af).

Your Notion integration will need access to the Notion database you have created. To provide access, follow the instructions found in Notion's [Integration guide](https://developers.notion.com/docs/create-a-notion-integration#step-2-share-a-database-with-your-integration).

### 3. Set your environment variables to a `.env` file

Rename `example.env` to `.env` in this directory and add your API key.

```zsh
NOTION_KEY=<api-key-you-created-in-the-previous-step>
```

### 3. Run code
### 4. Run code

```zsh
npm run ts-run
Expand Down
1 change: 1 addition & 0 deletions examples/generate-random-data/example.env
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
NOTION_KEY=notion-api-key
4 changes: 2 additions & 2 deletions examples/generate-random-data/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "generate-random-data",
"version": "1.0.0",
"description": "**TODO**",
"version": "1.0.1",
"description": "Generate random data in a Notion Database.",
"main": "index.js",
"scripts": {
"ts-run": "node --loader ts-node/esm index.ts"
Expand Down
2 changes: 1 addition & 1 deletion examples/notion-github-sync/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"author": "Aman Gupta",
"license": "MIT",
"dependencies": {
"@notionhq/client": "^2.1.1",
"@notionhq/client": "file:../../",
"dotenv": "^16.0.1",
"lodash": "^4.17.21",
"octokit": "^2.0.3"
Expand Down
2 changes: 1 addition & 1 deletion examples/notion-task-github-pr-sync/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"author": "Sid Verma",
"license": "MIT",
"dependencies": {
"@notionhq/client": "^2.1.1",
"@notionhq/client": "file:../../",
"dotenv": "^16.0.1",
"lodash": "^4.17.21",
"octokit": "^2.0.3"
Expand Down

0 comments on commit ab29303

Please sign in to comment.