From 3ffa1af11e0eda10a6355f5423ab5432345c67d4 Mon Sep 17 00:00:00 2001 From: Isaac Roberts <119639439+madebyisaacr@users.noreply.github.com> Date: Thu, 9 Apr 2026 13:08:06 -0400 Subject: [PATCH 1/2] Sync up to 100 relation values --- plugins/notion/src/api.ts | 24 ++++++++++++++++++++++++ plugins/notion/src/data.ts | 19 ++++++++++++++----- 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/plugins/notion/src/api.ts b/plugins/notion/src/api.ts index f542ab766..adfb37046 100644 --- a/plugins/notion/src/api.ts +++ b/plugins/notion/src/api.ts @@ -2,6 +2,7 @@ import { Client, collectPaginatedAPI, isFullBlock, isFullDatabase, isFullPage } import type { BlockObjectResponse, GetDatabaseResponse, + GetPagePropertyResponse, PageObjectResponse, RichTextItemResponse, } from "@notionhq/client/build/src/api-endpoints" @@ -405,6 +406,29 @@ export async function getPageBlocksAsRichText(pageId: string) { return blocksToHtml(blocks) } +const RELATION_PROPERTY_PAGE_SIZE = 100 + +/** + * Loads up to {@link RELATION_PROPERTY_PAGE_SIZE} related page ids when the relation is truncated on + * retrieve-page / query (has_more). Does not paginate past the first page. + */ +export async function fetchRelationIdsForPageProperty(pageId: string, propertyId: string): Promise { + const notion = getNotionClient() + const response = await notion.pages.properties.retrieve({ + page_id: pageId, + property_id: propertyId, + page_size: RELATION_PROPERTY_PAGE_SIZE, + }) + + if (response.object === "list") { + return response.results.flatMap(item => (item.type === "relation" ? [item.relation.id] : [])) + } + if (response.type === "relation") { + return [response.relation.id] + } + return [] +} + export async function getDatabaseItems( database: GetDatabaseResponse, onProgress?: (progress: { current: number; total: number; hasFinishedLoading: boolean }) => void diff --git a/plugins/notion/src/data.ts b/plugins/notion/src/data.ts index 039470991..1f3ff7304 100644 --- a/plugins/notion/src/data.ts +++ b/plugins/notion/src/data.ts @@ -13,6 +13,7 @@ import { alwaysSyncedPropertyTypes, assertFieldTypeMatchesPropertyType, type FieldInfo, + fetchRelationIdsForPageProperty, getDatabase, getDatabaseFieldsInfo, getDatabaseItems, @@ -241,7 +242,7 @@ export async function syncCollection( continue } - const fieldEntry = getFieldDataEntryForProperty(property, field) + const fieldEntry = await getFieldDataEntryForProperty(property, field, item.id) if (fieldEntry) { fieldData[field.id] = fieldEntry } else { @@ -624,10 +625,11 @@ export function fieldsInfoToCollectionFields( return fields } -export function getFieldDataEntryForProperty( +async function getFieldDataEntryForProperty( property: PageObjectResponse["properties"][string], - field: ManagedCollectionFieldInput -): FieldDataEntryInput | null { + field: ManagedCollectionFieldInput, + itemId: string +): Promise { switch (property.type) { case "checkbox": { return { type: "boolean", value: property.checkbox } @@ -691,7 +693,14 @@ export function getFieldDataEntryForProperty( } case "relation": { if (field.type === "multiCollectionReference") { - return { type: "multiCollectionReference", value: property.relation.map(({ id }) => id) } + let relationItemIds: string[] = [] + if ("has_more" in property && property.has_more) { + relationItemIds = await fetchRelationIdsForPageProperty(itemId, property.id) + } else { + relationItemIds = property.relation.map(({ id }) => id) + } + + return { type: "multiCollectionReference", value: relationItemIds } } else if (field.type === "collectionReference") { return { type: "collectionReference", value: property.relation[0]?.id ?? null } } From ae6d9830e5eedb3b61a51bcaf0da5adb60210a00 Mon Sep 17 00:00:00 2001 From: Isaac Roberts <119639439+madebyisaacr@users.noreply.github.com> Date: Thu, 9 Apr 2026 13:36:08 -0400 Subject: [PATCH 2/2] Improve code, remove unused type --- plugins/notion/src/api.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/plugins/notion/src/api.ts b/plugins/notion/src/api.ts index adfb37046..24aa81984 100644 --- a/plugins/notion/src/api.ts +++ b/plugins/notion/src/api.ts @@ -2,7 +2,6 @@ import { Client, collectPaginatedAPI, isFullBlock, isFullDatabase, isFullPage } import type { BlockObjectResponse, GetDatabaseResponse, - GetPagePropertyResponse, PageObjectResponse, RichTextItemResponse, } from "@notionhq/client/build/src/api-endpoints" @@ -421,7 +420,7 @@ export async function fetchRelationIdsForPageProperty(pageId: string, propertyId }) if (response.object === "list") { - return response.results.flatMap(item => (item.type === "relation" ? [item.relation.id] : [])) + return response.results.map(item => (item.type === "relation" ? item.relation.id : "")).filter(id => id !== "") } if (response.type === "relation") { return [response.relation.id]