Skip to content

Commit abdaf2c

Browse files
committed
fix(selectors): drain fetchPage in direct fetchList callers
Making `fetchList` optional left three direct callers (outside the useSelectorOptions hook) calling it unguarded, which broke the build's type check. Route them through a shared `loadAllSelectorOptions` helper that uses `fetchList` when present and otherwise drains `fetchPage`. This also prevents a regression: `confluence.spaces` / `knowledge.documents` now paginate via `fetchPage` only, and these callers (search/replace, value resolution) would otherwise have silently returned no options.
1 parent dc41d23 commit abdaf2c

3 files changed

Lines changed: 47 additions & 6 deletions

File tree

apps/sim/hooks/queries/workflow-search-replace.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ import {
3333
fetchOAuthCredentialDetail,
3434
fetchOAuthCredentials,
3535
} from '@/hooks/queries/oauth/oauth-credentials'
36-
import { getSelectorDefinition } from '@/hooks/selectors/registry'
36+
import { getSelectorDefinition, loadAllSelectorOptions } from '@/hooks/selectors/registry'
3737
import type { SelectorKey, SelectorOption } from '@/hooks/selectors/types'
3838

3939
export interface WorkflowSearchResolvedResource {
@@ -374,7 +374,11 @@ export function useWorkflowSearchSelectorDetails(matches: WorkflowSearchMatch[])
374374
return definition.fetchById({ ...queryArgs, signal })
375375
}
376376

377-
const options = await definition.fetchList({ key: selectorKey, context, signal })
377+
const options = await loadAllSelectorOptions(definition, {
378+
key: selectorKey,
379+
context,
380+
signal,
381+
})
378382
return options.find((option) => option.id === match.rawValue) ?? null
379383
},
380384
enabled: Boolean(selectorKey && match.rawValue && baseEnabled),
@@ -620,7 +624,7 @@ export function useWorkflowSearchSelectorReplacementOptions(matches: WorkflowSea
620624
return {
621625
queryKey: workflowSearchReplaceKeys.selectorReplacementOptions(selectorKey, contextKey),
622626
queryFn: ({ signal }: { signal: AbortSignal }) =>
623-
definition.fetchList({ ...queryArgs, signal }),
627+
loadAllSelectorOptions(definition, { ...queryArgs, signal }),
624628
enabled: Boolean(selectorKey && baseEnabled),
625629
staleTime: definition.staleTime ?? 60 * 1000,
626630
select: (options: SelectorOption[]): WorkflowSearchReplacementOption[] =>

apps/sim/hooks/selectors/registry.ts

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,12 @@ import { trelloSelectors } from '@/hooks/selectors/providers/trello/selectors'
2121
import { wealthboxSelectors } from '@/hooks/selectors/providers/wealthbox/selectors'
2222
import { webflowSelectors } from '@/hooks/selectors/providers/webflow/selectors'
2323
import { zoomSelectors } from '@/hooks/selectors/providers/zoom/selectors'
24-
import type { SelectorDefinition, SelectorKey, SelectorOption } from '@/hooks/selectors/types'
24+
import type {
25+
SelectorDefinition,
26+
SelectorKey,
27+
SelectorOption,
28+
SelectorQueryArgs,
29+
} from '@/hooks/selectors/types'
2530

2631
export const selectorRegistry = {
2732
...airtableSelectors,
@@ -57,6 +62,38 @@ export function getSelectorDefinition(key: SelectorKey): SelectorDefinition {
5762
return definition
5863
}
5964

65+
const MAX_LOAD_ALL_PAGES = 50
66+
67+
/**
68+
* Loads the complete option list for a selector outside the React Query hook —
69+
* for callers (search/replace, value resolution) that need every option in one
70+
* call. Uses `fetchList` when defined, otherwise drains `fetchPage` (bounded by
71+
* {@link MAX_LOAD_ALL_PAGES}). Returns an empty array for a selector that
72+
* provides neither.
73+
*/
74+
export async function loadAllSelectorOptions(
75+
definition: SelectorDefinition,
76+
args: SelectorQueryArgs
77+
): Promise<SelectorOption[]> {
78+
if (definition.fetchList) {
79+
return definition.fetchList(args)
80+
}
81+
82+
if (definition.fetchPage) {
83+
const items: SelectorOption[] = []
84+
let cursor: string | undefined
85+
for (let page = 0; page < MAX_LOAD_ALL_PAGES; page++) {
86+
const { items: pageItems, nextCursor } = await definition.fetchPage({ ...args, cursor })
87+
items.push(...pageItems)
88+
cursor = nextCursor
89+
if (!cursor) break
90+
}
91+
return items
92+
}
93+
94+
return []
95+
}
96+
6097
export function mergeOption(options: SelectorOption[], option?: SelectorOption | null) {
6198
if (!option) return options
6299
if (options.some((item) => item.id === option.id)) {

apps/sim/lib/workflows/comparison/resolve-values.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { SELECTOR_TYPES_HYDRATION_REQUIRED, type SubBlockConfig } from '@/blocks
66
import { CREDENTIAL_SET, isUuid } from '@/executor/constants'
77
import { fetchCredentialSetById } from '@/hooks/queries/credential-sets'
88
import { fetchOAuthCredentialDetail } from '@/hooks/queries/oauth/oauth-credentials'
9-
import { getSelectorDefinition } from '@/hooks/selectors/registry'
9+
import { getSelectorDefinition, loadAllSelectorOptions } from '@/hooks/selectors/registry'
1010
import { resolveSelectorForSubBlock } from '@/hooks/selectors/resolution'
1111
import type { SelectorContext, SelectorKey } from '@/hooks/selectors/types'
1212
import type { WorkflowState } from '@/stores/workflows/workflow/types'
@@ -107,7 +107,7 @@ async function resolveSelectorValue(
107107
}
108108
}
109109

110-
const options = await definition.fetchList({
110+
const options = await loadAllSelectorOptions(definition, {
111111
key: selectorKey,
112112
context: selectorContext,
113113
})

0 commit comments

Comments
 (0)