Skip to content

Commit 598434d

Browse files
committed
added logic to fetch a page's relations
1 parent 36e4943 commit 598434d

File tree

2 files changed

+70
-1
lines changed

2 files changed

+70
-1
lines changed

examples/minimal/pages/[pageId].tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import notion from '../lib/notion'
66

77
export const getStaticProps = async (context: any) => {
88
const pageId = (context.params.pageId as string) || rootNotionPageId
9-
const recordMap = await notion.getPage(pageId)
9+
const recordMap = await notion.getPage(pageId, { fetchRelationPages: true })
1010

1111
return {
1212
props: {

packages/notion-client/src/notion-api.ts

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ export class NotionAPI {
5353
chunkNumber = 0,
5454
throwOnCollectionErrors = false,
5555
collectionReducerLimit = 999,
56+
fetchRelationPages = true, // New option
5657
kyOptions
5758
}: {
5859
concurrency?: number
@@ -63,6 +64,7 @@ export class NotionAPI {
6364
chunkNumber?: number
6465
throwOnCollectionErrors?: boolean
6566
collectionReducerLimit?: number
67+
fetchRelationPages?: boolean // New option
6668
kyOptions?: KyOptions
6769
} = {}
6870
): Promise<notion.ExtendedRecordMap> {
@@ -220,6 +222,73 @@ export class NotionAPI {
220222
await this.addSignedUrls({ recordMap, contentBlockIds, kyOptions })
221223
}
222224

225+
if (fetchRelationPages) {
226+
const maxIterations = 10 // Limit iterations to prevent infinite loops
227+
for (let i = 0; i < maxIterations; ++i) {
228+
const allRelationPageIdsInThisIteration = new Set<string>()
229+
230+
for (const blockId of Object.keys(recordMap.block)) {
231+
const blockValue = recordMap.block[blockId]?.value
232+
if (
233+
blockValue?.parent_table === 'collection' &&
234+
blockValue?.parent_id
235+
) {
236+
const collection = recordMap.collection[blockValue.parent_id]?.value
237+
if (collection?.schema) {
238+
for (const propertyId of Object.keys(
239+
blockValue.properties || {}
240+
)) {
241+
const schema = collection.schema[propertyId]
242+
if (schema?.type === 'relation') {
243+
const decorations = blockValue.properties![propertyId]
244+
if (decorations && Array.isArray(decorations)) {
245+
for (const decoration of decorations) {
246+
if (
247+
Array.isArray(decoration) &&
248+
decoration.length > 1 &&
249+
decoration[0] === '‣'
250+
) {
251+
const pagePointer = decoration[1]?.[0]
252+
if (
253+
Array.isArray(pagePointer) &&
254+
pagePointer.length > 1 &&
255+
pagePointer[0] === 'p'
256+
) {
257+
allRelationPageIdsInThisIteration.add(pagePointer[1])
258+
}
259+
}
260+
}
261+
}
262+
}
263+
}
264+
}
265+
}
266+
}
267+
268+
const pendingRelationPageIds = Array.from(
269+
allRelationPageIdsInThisIteration
270+
).filter((id) => !recordMap.block[id]?.value)
271+
272+
if (!pendingRelationPageIds.length) {
273+
break // No new related pages to fetch
274+
}
275+
276+
try {
277+
const newBlocks = await this.getBlocks(
278+
pendingRelationPageIds,
279+
kyOptions
280+
).then((res) => res.recordMap.block)
281+
recordMap.block = { ...recordMap.block, ...newBlocks }
282+
} catch (err: any) {
283+
console.warn(
284+
'NotionAPI getBlocks error during fetchRelationPages:',
285+
err.message
286+
)
287+
//TODO: Decide if we should break or continue if some blocks fail
288+
}
289+
}
290+
}
291+
223292
return recordMap
224293
}
225294

0 commit comments

Comments
 (0)