Skip to content

Latest commit

 

History

History
254 lines (201 loc) · 7.26 KB

README.md

File metadata and controls

254 lines (201 loc) · 7.26 KB

Notion ORM

⚠️ This package is Still in development 🏗️

A library to simplify adding and querying Notion databases/tables. Giving typeahead/intellisense support on columns and expected column values on user specified databases. Built on top of Notion API

Databases with the following column types are supported:

  • Multi-select
  • Select
  • Status
  • Date
  • Text
  • Url
  • Checkbox
  • Email
  • Phone Number

Installation

The only requirement is a Notion Developer API key (here) and database IDs you want. Be sure to connect your integration (🚧 Permissions section) with your tables

npm install @haustle/notion-orm --save-dev

At the root of your project create a notion.config.js file

You’ll need to pass your developer key and database IDs. How to get database IDs here

// notion.config.js

const auth = process.env.NOTION_KEY;
const NotionConfig = {
	auth,
	databaseIds: [
		"a52239e4839d4a3a8f4875376cfbfb02",
		"5f4bf76a1e3f48d684d2506ea2690d64",
	],
};

module.exports = NotionConfig;

Execute the following command from the root project directory.

npx notion generate

Package Size Unpackaged size is 70.6KB and the installation size is 5.12MB (5.03MB from @notionhq/client dependency)

Implementation

Databases can be imported via barrel file or from the individual database file. All database names will be camelCase 🐫.

// Barrel Import (access to all databases)
import * as notion from "@haustle/notion-orm";
notion.databaseName.add();
notion.databaseName2.query();
// Individual Database Import
import {
	databaseName,
	DatabaseSchemaType,
	QuerySchemaType,
} from "@haustle/notion-orm/build/db/databaseName";

databaseName.add();
  • DatabaseSchemaType: Object type accepted in the database’s add() function
  • QuerySchemaType: Object type accepted in the database’s query() function

The following examples for querying & adding are for server-side calls. If you’re looking to use this framework to execute client-side calls (ex. button click add/query X) visit the Client (React) section after reading

Adding

Only required column required is the title.

notion.books.add({
	bookName: "Raphael, Painter in Rome: a Novel", // title
	author: "Stephanie Storey", // text
	status: "In progress", // status
	numberOfPages: 307, // number
	genre: ["Historical Fiction"], // multi-select
	rating: "⭐️⭐️⭐️⭐️", // select
	startDate: {
		// date
		start: "2023-01-01",
	},
	phone: "0000000000", // phone
	email: "[email protected]", // email
});

All column types in Notion databases are mapped to a typescript type.

Column Type Object
Title string
Text string
Select string
Multi-select Array (string)
Status string
Number number
Date Object
Phone number string
Email string

Querying

For each column type you’ll be presented with the available querying filter. Find all filter conditions here

While the querying functionality works, it’s not complete and there is room for user error. For instance, the filter object should contain one child. Either the column name (signifies single filter), or and or or (signify compound filters). However there is no typecheck in place to stop adding multiple children

Unlike add() , there is no transformation after the inputted object. So the querying object you’re creating is exactly what you’d normally use to query the Notion API. Learn more about them here

Example of a single filter

notion.books.query({
  filter: {
    genre: {
      contains: "Sci-Fi",
    },
  },
	sort: [
		{
			property: "name",
			direction: "ascending"
		},
		{
			property: "Author name",
			direction: "ascending"
		}
	]
});

Example of compound filters, which is signified with and and or. You can nest these are far as you want (i.e and filters within or filter). Learn more here

await notion.books.query({
	filter: {
		or: [
			{
				genre: {
					contains: "Sci-Fi",
				},
			},
			{
				genre: {
					contains: "Biography",
				},
			},
		],
	},
});

Down below is what’s returned on a successful response. results being a simplified extracted version of the rawResponse (response from Notion API)

{
	rawResponse: { /* Whatever Notion API returns */},
	results: [
		{
			bookName: "How to Change Your Mind",
			genre: ["Non-fiction"],
			numberPages: 460,
			rating: "⭐️⭐️⭐️⭐️"
		},
	]
}

Client-side (React)

Notion API currently blocks calls from browser (per CORS)

You can get around this by creating API endpoints on stack of your choice. I’ve provided examples only for Next.js, but the high level implementation should work with any backend.

If you’re planning to only make server-side calls to your Notion database (from GetStaticProps or GetServerSideProps). These calls work totally fine, as these functions are executed server-side before page load. So you can ignore the proceeding steps

export const getStaticProps: GetStaticProps = async () => {
	const response = await NotionClient.books.query({
		filter: {
			genre: {
				is_not_empty: true,
			},
		},
	});
	return {
		props: {
			apiResponse: response
		}
	}

To execute calls client-side (ex. on button click) an API endpoint is needed to get around CORS. In this example we’re passing the databases DatabaseSchemaType as the body of the API call.

import { DatabaseSchemaType } from "@haustle/notion-orm/build/db/books";

async function addPageToNotionDatabase() {
	const example: DatabaseSchemaType = {
		bookName: "How to Change Your Mind",
		genre: ["Non-fiction"],
	};

	// make sure this route reflects your API path
	await fetch("/api/notion/books", {
		method: "POST",
		body: JSON.stringify(example),
	});
}
<button onClick={ async() => await addPageToNotionDatabase()}>

Example API endpoint below, where we’re taking the body of type DatabaseSchemaType and passing it into the respected databases add() function to add a new page to the database. Learn more about Next.js API’s and routing here.

// pages/api/notion/yourDatabaseName.ts

import type { NextApiRequest, NextApiResponse } from "next";
import {
	DatabaseSchemaType,
	yourDatabaseName,
} from "@haustle/notion-orm/build/db/yourDatabaseName";

export default async function handler(
	req: NextApiRequest,
	res: NextApiResponse
) {
	const { method, body } = req;

	if (method === "POST") {
		const bodyJSON = JSON.parse(body) as DatabaseSchemaType;
		await yourDatabaseName.add(bodyJSON);
	}
}