@hansolbangul/notion-api
Version:
A lightweight library for fetching and statically generating data and TypeScript types from Notion pages.
140 lines (136 loc) • 5.51 kB
JavaScript
;
var notionClient = require('notion-client');
var notionUtils = require('notion-utils');
class NotionApiService {
api;
config;
constructor(config) {
this.api = new notionClient.NotionAPI();
new notionClient.NotionAPI();
this.config = config;
}
async fetchPage(pageId) {
return await this.api.getPage(pageId);
}
/**
* Get all page IDs from a Notion response
* @param response - ExtendedRecordMap from Notion API
* @param viewId - Optional viewId for filtering
*/
getAllPageIds(response, viewId) {
const collectionQuery = response.collection_query;
const views = Object.values(collectionQuery)[0];
let pageIds = [];
if (viewId) {
const vId = notionUtils.idToUuid(viewId);
pageIds = views[vId]?.blockIds || [];
}
else {
const pageSet = new Set();
Object.values(views).forEach((view) => {
view?.collection_group_results?.blockIds?.forEach((id) => pageSet.add(id));
});
pageIds = Array.from(pageSet);
}
return pageIds;
}
async extractPageProperties(pageId, block, schema) {
const rawProperties = Object.entries(block?.[pageId]?.value?.properties || {});
const properties = { id: pageId };
for (const [key, value] of rawProperties) {
const fieldSchema = schema[key];
if (!fieldSchema)
continue;
switch (fieldSchema.type) {
case 'title':
case 'text':
case 'email':
case 'url':
properties[fieldSchema.name] = notionUtils.getTextContent(value);
break;
case 'date':
properties[fieldSchema.name] = notionUtils.getDateValue(value);
break;
case 'file': {
const files = value.map((file) => ({
name: file[0],
url: file[1]?.[0]?.[1],
}));
properties[fieldSchema.name] = files;
break;
}
case 'person': {
const rawUsers = value.flat();
const users = await Promise.all(rawUsers.map(async (user) => {
const userId = user?.[0][1];
if (!userId) {
return null;
}
try {
const userDetails = await this.api.getUsers([userId]);
const userRecord = userDetails?.recordMapWithRoles?.notion_user?.[userId]?.value;
return {
id: userId,
name: userRecord?.name ||
`${userRecord?.family_name ?? ''} ${userRecord?.given_name ?? ''}`.trim() ||
'Unknown',
profile_photo: userRecord?.profile_photo || null,
};
}
catch (error) {
console.error(`Failed to fetch user details for userId: ${userId}`, error);
return null;
}
}));
properties[fieldSchema.name] = users.filter((user) => user !== null);
break;
}
case 'select':
case 'multi_select': {
const selections = notionUtils.getTextContent(value);
properties[fieldSchema.name] = selections
? selections.split(',')
: [];
break;
}
default:
properties[fieldSchema.name] = notionUtils.getTextContent(value);
}
}
return properties;
}
async getPosts(viewId) {
let id = this.config.pageId;
id = notionUtils.idToUuid(id);
const recordMap = await this.fetchPage(id);
const collection = Object.values(recordMap.collection)[0]?.value;
const block = recordMap.block;
const schema = collection?.schema;
if (!schema) {
throw new Error('Schema not found in the given Notion page.');
}
const rawMetadata = block[id]?.value;
if (rawMetadata?.type !== 'collection_view_page' &&
rawMetadata?.type !== 'collection_view') {
return [];
}
const pageIds = this.getAllPageIds(recordMap, viewId);
const posts = await Promise.all(pageIds.map(async (pageId) => {
const [properties, postBlock] = await Promise.all([
this.extractPageProperties(pageId, block, schema),
this.fetchPage(pageId),
]);
const blockValue = block[pageId]?.value;
if (blockValue) {
properties['createdTime'] = new Date(blockValue?.created_time).toISOString();
properties['fullWidth'] =
blockValue?.format?.page_full_width || false;
}
properties.block = postBlock;
return properties;
}));
return posts;
}
}
exports.NotionApiService = NotionApiService;
//# sourceMappingURL=index.js.map