import { getAllPagesInSpace, getPageProperty, uuidToId } from 'notion-utils' import pMemoize from 'p-memoize' import type * as types from './types' import * as config from './config' import { includeNotionIdInUrls } from './config' import { getCanonicalPageId } from './get-canonical-page-id' import { notion } from './notion-api' const uuid = !!includeNotionIdInUrls export async function getSiteMap(): Promise { const partialSiteMap = await getAllPages( config.rootNotionPageId, config.rootNotionSpaceId ?? undefined ) return { site: config.site, ...partialSiteMap } as types.SiteMap } const getAllPages = pMemoize(getAllPagesImpl, { cacheKey: (...args) => JSON.stringify(args) }) const getPage = async (pageId: string, opts?: any) => { console.log('\nnotion getPage', uuidToId(pageId)) return notion.getPage(pageId, { kyOptions: { timeout: 30_000 }, ...opts }) } async function getAllPagesImpl( rootNotionPageId: string, rootNotionSpaceId?: string, { maxDepth = 1 }: { maxDepth?: number } = {} ): Promise> { const pageMap = await getAllPagesInSpace( rootNotionPageId, rootNotionSpaceId, getPage, { maxDepth } ) const canonicalPageMap = Object.keys(pageMap).reduce( (map: Record, pageId: string) => { const recordMap = pageMap[pageId] if (!recordMap) { throw new Error(`Error loading page "${pageId}"`) } const block = recordMap.block[pageId]?.value if ( !(getPageProperty('Public', block!, recordMap) ?? true) ) { return map } const canonicalPageId = getCanonicalPageId(pageId, recordMap, { uuid })! if (map[canonicalPageId]) { // you can have multiple pages in different collections that have the same id // TODO: we may want to error if neither entry is a collection page console.warn('error duplicate canonical page id', { canonicalPageId, pageId, existingPageId: map[canonicalPageId] }) return map } else { return { ...map, [canonicalPageId]: pageId } } }, {} ) return { pageMap, canonicalPageMap } }