Hey there, fellow JavaScript enthusiasts! Ready to dive into the world of Notion API? Let's get our hands dirty with some data syncing for user-facing integrations. Buckle up!
First things first, let's get you set up. Head over to the Notion developers page and snag your API key. Once you've got that, install the Notion client:
npm install @notionhq/client
Now, let's initialize our client:
const { Client } = require('@notionhq/client'); const notion = new Client({ auth: process.env.NOTION_API_KEY });
Reading data is a breeze. Here's how you can query a database:
async function queryDatabase(databaseId) { try { const response = await notion.databases.query({ database_id: databaseId, }); return response.results; } catch (error) { console.error('Error querying database:', error); } }
Creating a new page in a database is just as easy:
async function createPage(databaseId, properties) { try { const response = await notion.pages.create({ parent: { database_id: databaseId }, properties: properties, }); return response; } catch (error) { console.error('Error creating page:', error); } }
Now, let's put it all together with a basic sync function:
async function syncData(localData, databaseId) { const notionData = await queryDatabase(databaseId); for (const item of localData) { const existingItem = notionData.find(n => n.properties.ID.rich_text[0].text.content === item.id); if (existingItem) { // Update existing item await notion.pages.update({ page_id: existingItem.id, properties: { // Map your properties here }, }); } else { // Create new item await createPage(databaseId, { // Map your properties here }); } } }
Always wrap your API calls in try-catch blocks. Here's a handy wrapper:
async function notionApiCall(apiFunction, ...args) { try { return await apiFunction(...args); } catch (error) { if (error.status === 429) { console.log('Rate limited. Retrying in 5 seconds...'); await new Promise(resolve => setTimeout(resolve, 5000)); return notionApiCall(apiFunction, ...args); } throw error; } }
Batching updates can significantly improve performance:
async function batchUpdate(pages) { const batchSize = 10; for (let i = 0; i < pages.length; i += batchSize) { const batch = pages.slice(i, i + batchSize); await Promise.all(batch.map(page => notion.pages.update(page))); } }
Notion webhooks are your friend for real-time updates. Here's a simple Express handler:
app.post('/notion-webhook', (req, res) => { const { type, page } = req.body; if (type === 'page_updated') { // Handle page update console.log('Page updated:', page.id); } res.sendStatus(200); });
Don't forget to test! Here's a simple test case using Jest:
test('createPage creates a new page', async () => { const mockPage = { id: 'test-id', properties: {} }; notion.pages.create = jest.fn().mockResolvedValue(mockPage); const result = await createPage('database-id', {}); expect(result).toEqual(mockPage); expect(notion.pages.create).toHaveBeenCalledWith({ parent: { database_id: 'database-id' }, properties: {}, }); });
And there you have it! You're now equipped to read and write data like a Notion API pro. Remember to keep an eye on those rate limits, batch your requests when possible, and always handle your errors gracefully.
Happy coding, and may your data always be in sync! 🚀