@open-mercato/core 0.6.4-develop.4113.1.5e87922616 → 0.6.4-develop.4133.1.48fc6c8f7b

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/dist/modules/auth/lib/sessionIntegrity.js +16 -13
  3. package/dist/modules/auth/lib/sessionIntegrity.js.map +2 -2
  4. package/dist/modules/customers/api/utils.js +14 -9
  5. package/dist/modules/customers/api/utils.js.map +2 -2
  6. package/dist/modules/dashboards/api/widgets/data/batch/route.js +137 -0
  7. package/dist/modules/dashboards/api/widgets/data/batch/route.js.map +7 -0
  8. package/dist/modules/dashboards/api/widgets/data/route.js +1 -75
  9. package/dist/modules/dashboards/api/widgets/data/route.js.map +2 -2
  10. package/dist/modules/dashboards/api/widgets/data/schema.js +85 -0
  11. package/dist/modules/dashboards/api/widgets/data/schema.js.map +7 -0
  12. package/dist/modules/dashboards/lib/widgetDataBatch.js +49 -0
  13. package/dist/modules/dashboards/lib/widgetDataBatch.js.map +7 -0
  14. package/dist/modules/dashboards/widgets/dashboard/aov-kpi/widget.client.js +6 -14
  15. package/dist/modules/dashboards/widgets/dashboard/aov-kpi/widget.client.js.map +2 -2
  16. package/dist/modules/dashboards/widgets/dashboard/new-customers-kpi/widget.client.js +6 -14
  17. package/dist/modules/dashboards/widgets/dashboard/new-customers-kpi/widget.client.js.map +2 -2
  18. package/dist/modules/dashboards/widgets/dashboard/orders-by-status/widget.client.js +6 -14
  19. package/dist/modules/dashboards/widgets/dashboard/orders-by-status/widget.client.js.map +2 -2
  20. package/dist/modules/dashboards/widgets/dashboard/orders-kpi/widget.client.js +6 -14
  21. package/dist/modules/dashboards/widgets/dashboard/orders-kpi/widget.client.js.map +2 -2
  22. package/dist/modules/dashboards/widgets/dashboard/pipeline-summary/widget.client.js +6 -14
  23. package/dist/modules/dashboards/widgets/dashboard/pipeline-summary/widget.client.js.map +2 -2
  24. package/dist/modules/dashboards/widgets/dashboard/revenue-kpi/widget.client.js +6 -14
  25. package/dist/modules/dashboards/widgets/dashboard/revenue-kpi/widget.client.js.map +2 -2
  26. package/dist/modules/dashboards/widgets/dashboard/revenue-trend/widget.client.js +6 -14
  27. package/dist/modules/dashboards/widgets/dashboard/revenue-trend/widget.client.js.map +2 -2
  28. package/dist/modules/dashboards/widgets/dashboard/sales-by-region/widget.client.js +6 -14
  29. package/dist/modules/dashboards/widgets/dashboard/sales-by-region/widget.client.js.map +2 -2
  30. package/dist/modules/dashboards/widgets/dashboard/top-customers/widget.client.js +6 -14
  31. package/dist/modules/dashboards/widgets/dashboard/top-customers/widget.client.js.map +2 -2
  32. package/dist/modules/dashboards/widgets/dashboard/top-products/widget.client.js +6 -14
  33. package/dist/modules/dashboards/widgets/dashboard/top-products/widget.client.js.map +2 -2
  34. package/dist/modules/directory/utils/organizationScope.js +33 -20
  35. package/dist/modules/directory/utils/organizationScope.js.map +2 -2
  36. package/package.json +7 -7
  37. package/src/modules/auth/lib/sessionIntegrity.ts +37 -16
  38. package/src/modules/customers/api/utils.ts +17 -11
  39. package/src/modules/dashboards/api/widgets/data/batch/route.ts +168 -0
  40. package/src/modules/dashboards/api/widgets/data/route.ts +1 -90
  41. package/src/modules/dashboards/api/widgets/data/schema.ts +90 -0
  42. package/src/modules/dashboards/lib/widgetDataBatch.ts +89 -0
  43. package/src/modules/dashboards/widgets/dashboard/aov-kpi/widget.client.tsx +6 -16
  44. package/src/modules/dashboards/widgets/dashboard/new-customers-kpi/widget.client.tsx +6 -16
  45. package/src/modules/dashboards/widgets/dashboard/orders-by-status/widget.client.tsx +6 -16
  46. package/src/modules/dashboards/widgets/dashboard/orders-kpi/widget.client.tsx +6 -16
  47. package/src/modules/dashboards/widgets/dashboard/pipeline-summary/widget.client.tsx +6 -16
  48. package/src/modules/dashboards/widgets/dashboard/revenue-kpi/widget.client.tsx +6 -16
  49. package/src/modules/dashboards/widgets/dashboard/revenue-trend/widget.client.tsx +6 -16
  50. package/src/modules/dashboards/widgets/dashboard/sales-by-region/widget.client.tsx +6 -16
  51. package/src/modules/dashboards/widgets/dashboard/top-customers/widget.client.tsx +6 -16
  52. package/src/modules/dashboards/widgets/dashboard/top-products/widget.client.tsx +6 -16
  53. package/src/modules/directory/utils/organizationScope.ts +51 -20
@@ -2,7 +2,7 @@
2
2
 
3
3
  import * as React from 'react'
4
4
  import type { DashboardWidgetComponentProps } from '@open-mercato/shared/modules/dashboard/widgets'
5
- import { apiCall } from '@open-mercato/ui/backend/utils/apiCall'
5
+ import { useWidgetData, type WidgetDataFetcher } from '@open-mercato/ui/backend/dashboard/widgetData'
6
6
  import { useT, useLocale } from '@open-mercato/shared/lib/i18n/context'
7
7
  import { LineChart, type LineChartDataItem } from '@open-mercato/ui/backend/charts'
8
8
  import {
@@ -22,7 +22,7 @@ import { DEFAULT_SETTINGS, hydrateSettings, type RevenueTrendSettings } from './
22
22
  import type { WidgetDataResponse } from '../../../services/widgetDataService'
23
23
  import { formatCurrencyCompact } from '../../../lib/formatters'
24
24
 
25
- async function fetchRevenueTrendData(settings: RevenueTrendSettings): Promise<WidgetDataResponse> {
25
+ async function fetchRevenueTrendData(settings: RevenueTrendSettings, fetchWidgetData: WidgetDataFetcher): Promise<WidgetDataResponse> {
26
26
  const body = {
27
27
  entityType: 'sales:orders',
28
28
  metric: {
@@ -39,18 +39,7 @@ async function fetchRevenueTrendData(settings: RevenueTrendSettings): Promise<Wi
39
39
  },
40
40
  }
41
41
 
42
- const call = await apiCall<WidgetDataResponse>('/api/dashboards/widgets/data', {
43
- method: 'POST',
44
- headers: { 'Content-Type': 'application/json' },
45
- body: JSON.stringify(body),
46
- })
47
-
48
- if (!call.ok) {
49
- const errorMsg = (call.result as Record<string, unknown>)?.error
50
- throw new Error(typeof errorMsg === 'string' ? errorMsg : 'Failed to fetch revenue trend data')
51
- }
52
-
53
- return call.result as WidgetDataResponse
42
+ return fetchWidgetData<WidgetDataResponse>(body)
54
43
  }
55
44
 
56
45
  function formatDate(dateStr: string | null, granularity: DateGranularity, locale?: string): string {
@@ -125,12 +114,13 @@ const RevenueTrendWidget: React.FC<DashboardWidgetComponentProps<RevenueTrendSet
125
114
  const [loading, setLoading] = React.useState(true)
126
115
  const [error, setError] = React.useState<string | null>(null)
127
116
 
117
+ const fetchWidgetData = useWidgetData()
128
118
  const refresh = React.useCallback(async () => {
129
119
  onRefreshStateChange?.(true)
130
120
  setLoading(true)
131
121
  setError(null)
132
122
  try {
133
- const result = await fetchRevenueTrendData(hydrated)
123
+ const result = await fetchRevenueTrendData(hydrated, fetchWidgetData)
134
124
  const sortedData = [...result.data].sort((a, b) => {
135
125
  const aTime = new Date(a.groupKey as string || 0).getTime()
136
126
  const bTime = new Date(b.groupKey as string || 0).getTime()
@@ -148,7 +138,7 @@ const RevenueTrendWidget: React.FC<DashboardWidgetComponentProps<RevenueTrendSet
148
138
  setLoading(false)
149
139
  onRefreshStateChange?.(false)
150
140
  }
151
- }, [hydrated, locale, onRefreshStateChange, t])
141
+ }, [hydrated, fetchWidgetData, locale, onRefreshStateChange, t])
152
142
 
153
143
  React.useEffect(() => {
154
144
  refresh().catch(() => {})
@@ -2,7 +2,7 @@
2
2
 
3
3
  import * as React from 'react'
4
4
  import type { DashboardWidgetComponentProps } from '@open-mercato/shared/modules/dashboard/widgets'
5
- import { apiCall } from '@open-mercato/ui/backend/utils/apiCall'
5
+ import { useWidgetData, type WidgetDataFetcher } from '@open-mercato/ui/backend/dashboard/widgetData'
6
6
  import { useT } from '@open-mercato/shared/lib/i18n/context'
7
7
  import { BarChart, type BarChartDataItem } from '@open-mercato/ui/backend/charts'
8
8
  import { DateRangeSelect, type DateRangePreset } from '@open-mercato/ui/backend/date-range'
@@ -11,7 +11,7 @@ import { DEFAULT_SETTINGS, hydrateSettings, type SalesByRegionSettings } from '.
11
11
  import type { WidgetDataResponse } from '../../../services/widgetDataService'
12
12
  import { formatCurrencyCompact } from '../../../lib/formatters'
13
13
 
14
- async function fetchSalesByRegionData(settings: SalesByRegionSettings): Promise<WidgetDataResponse> {
14
+ async function fetchSalesByRegionData(settings: SalesByRegionSettings, fetchWidgetData: WidgetDataFetcher): Promise<WidgetDataResponse> {
15
15
  const body = {
16
16
  entityType: 'sales:orders',
17
17
  metric: {
@@ -28,18 +28,7 @@ async function fetchSalesByRegionData(settings: SalesByRegionSettings): Promise<
28
28
  },
29
29
  }
30
30
 
31
- const call = await apiCall<WidgetDataResponse>('/api/dashboards/widgets/data', {
32
- method: 'POST',
33
- headers: { 'Content-Type': 'application/json' },
34
- body: JSON.stringify(body),
35
- })
36
-
37
- if (!call.ok) {
38
- const errorMsg = (call.result as Record<string, unknown>)?.error
39
- throw new Error(typeof errorMsg === 'string' ? errorMsg : 'Failed to fetch sales by region data')
40
- }
41
-
42
- return call.result as WidgetDataResponse
31
+ return fetchWidgetData<WidgetDataResponse>(body)
43
32
  }
44
33
 
45
34
  const SalesByRegionWidget: React.FC<DashboardWidgetComponentProps<SalesByRegionSettings>> = ({
@@ -55,12 +44,13 @@ const SalesByRegionWidget: React.FC<DashboardWidgetComponentProps<SalesByRegionS
55
44
  const [loading, setLoading] = React.useState(true)
56
45
  const [error, setError] = React.useState<string | null>(null)
57
46
 
47
+ const fetchWidgetData = useWidgetData()
58
48
  const refresh = React.useCallback(async () => {
59
49
  onRefreshStateChange?.(true)
60
50
  setLoading(true)
61
51
  setError(null)
62
52
  try {
63
- const result = await fetchSalesByRegionData(hydrated)
53
+ const result = await fetchSalesByRegionData(hydrated, fetchWidgetData)
64
54
  const chartData = result.data.map((item) => ({
65
55
  region: String(item.groupKey || t('dashboards.analytics.labels.unknown', 'Unknown')),
66
56
  Revenue: item.value ?? 0,
@@ -73,7 +63,7 @@ const SalesByRegionWidget: React.FC<DashboardWidgetComponentProps<SalesByRegionS
73
63
  setLoading(false)
74
64
  onRefreshStateChange?.(false)
75
65
  }
76
- }, [hydrated, onRefreshStateChange, t])
66
+ }, [hydrated, fetchWidgetData, onRefreshStateChange, t])
77
67
 
78
68
  React.useEffect(() => {
79
69
  refresh().catch(() => {})
@@ -2,7 +2,7 @@
2
2
 
3
3
  import * as React from 'react'
4
4
  import type { DashboardWidgetComponentProps } from '@open-mercato/shared/modules/dashboard/widgets'
5
- import { apiCall } from '@open-mercato/ui/backend/utils/apiCall'
5
+ import { useWidgetData, type WidgetDataFetcher } from '@open-mercato/ui/backend/dashboard/widgetData'
6
6
  import { useT } from '@open-mercato/shared/lib/i18n/context'
7
7
  import { TopNTable, type TopNTableColumn } from '@open-mercato/ui/backend/charts'
8
8
  import { DateRangeSelect, type DateRangePreset } from '@open-mercato/ui/backend/date-range'
@@ -17,7 +17,7 @@ type CustomerRow = {
17
17
  revenue: number
18
18
  }
19
19
 
20
- async function fetchTopCustomersData(settings: TopCustomersSettings): Promise<WidgetDataResponse> {
20
+ async function fetchTopCustomersData(settings: TopCustomersSettings, fetchWidgetData: WidgetDataFetcher): Promise<WidgetDataResponse> {
21
21
  const body = {
22
22
  entityType: 'sales:orders',
23
23
  metric: {
@@ -35,18 +35,7 @@ async function fetchTopCustomersData(settings: TopCustomersSettings): Promise<Wi
35
35
  },
36
36
  }
37
37
 
38
- const call = await apiCall<WidgetDataResponse>('/api/dashboards/widgets/data', {
39
- method: 'POST',
40
- headers: { 'Content-Type': 'application/json' },
41
- body: JSON.stringify(body),
42
- })
43
-
44
- if (!call.ok) {
45
- const errorMsg = (call.result as Record<string, unknown>)?.error
46
- throw new Error(typeof errorMsg === 'string' ? errorMsg : 'Failed to fetch top customers data')
47
- }
48
-
49
- return call.result as WidgetDataResponse
38
+ return fetchWidgetData<WidgetDataResponse>(body)
50
39
  }
51
40
 
52
41
  function formatCustomerName(name: string | null, unknownLabel: string): string {
@@ -90,12 +79,13 @@ const TopCustomersWidget: React.FC<DashboardWidgetComponentProps<TopCustomersSet
90
79
  [t, unknownLabel],
91
80
  )
92
81
 
82
+ const fetchWidgetData = useWidgetData()
93
83
  const refresh = React.useCallback(async () => {
94
84
  onRefreshStateChange?.(true)
95
85
  setLoading(true)
96
86
  setError(null)
97
87
  try {
98
- const result = await fetchTopCustomersData(hydrated)
88
+ const result = await fetchTopCustomersData(hydrated, fetchWidgetData)
99
89
  const tableData: CustomerRow[] = result.data.map((item, index) => ({
100
90
  rank: index + 1,
101
91
  customerId: item.groupLabel || String(item.groupKey || t('dashboards.analytics.labels.unknown', 'Unknown')),
@@ -109,7 +99,7 @@ const TopCustomersWidget: React.FC<DashboardWidgetComponentProps<TopCustomersSet
109
99
  setLoading(false)
110
100
  onRefreshStateChange?.(false)
111
101
  }
112
- }, [hydrated, onRefreshStateChange, t])
102
+ }, [hydrated, fetchWidgetData, onRefreshStateChange, t])
113
103
 
114
104
  React.useEffect(() => {
115
105
  refresh().catch(() => {})
@@ -2,7 +2,7 @@
2
2
 
3
3
  import * as React from 'react'
4
4
  import type { DashboardWidgetComponentProps } from '@open-mercato/shared/modules/dashboard/widgets'
5
- import { apiCall } from '@open-mercato/ui/backend/utils/apiCall'
5
+ import { useWidgetData, type WidgetDataFetcher } from '@open-mercato/ui/backend/dashboard/widgetData'
6
6
  import { useT } from '@open-mercato/shared/lib/i18n/context'
7
7
  import { BarChart, type BarChartDataItem } from '@open-mercato/ui/backend/charts'
8
8
  import { DateRangeSelect, InlineDateRangeSelect, type DateRangePreset } from '@open-mercato/ui/backend/date-range'
@@ -18,7 +18,7 @@ import { DEFAULT_SETTINGS, hydrateSettings, type TopProductsSettings } from './c
18
18
  import type { WidgetDataResponse } from '../../../services/widgetDataService'
19
19
  import { formatCurrencyCompact } from '../../../lib/formatters'
20
20
 
21
- async function fetchTopProductsData(settings: TopProductsSettings): Promise<WidgetDataResponse> {
21
+ async function fetchTopProductsData(settings: TopProductsSettings, fetchWidgetData: WidgetDataFetcher): Promise<WidgetDataResponse> {
22
22
  const body = {
23
23
  entityType: 'sales:order_lines',
24
24
  metric: {
@@ -36,18 +36,7 @@ async function fetchTopProductsData(settings: TopProductsSettings): Promise<Widg
36
36
  },
37
37
  }
38
38
 
39
- const call = await apiCall<WidgetDataResponse>('/api/dashboards/widgets/data', {
40
- method: 'POST',
41
- headers: { 'Content-Type': 'application/json' },
42
- body: JSON.stringify(body),
43
- })
44
-
45
- if (!call.ok) {
46
- const errorMsg = (call.result as Record<string, unknown>)?.error
47
- throw new Error(typeof errorMsg === 'string' ? errorMsg : 'Failed to fetch top products data')
48
- }
49
-
50
- return call.result as WidgetDataResponse
39
+ return fetchWidgetData<WidgetDataResponse>(body)
51
40
  }
52
41
 
53
42
  function truncateLabel(
@@ -82,6 +71,7 @@ const TopProductsWidget: React.FC<DashboardWidgetComponentProps<TopProductsSetti
82
71
  const [error, setError] = React.useState<string | null>(null)
83
72
  const fetchingRef = React.useRef(false)
84
73
 
74
+ const fetchWidgetData = useWidgetData()
85
75
  const refresh = React.useCallback(async () => {
86
76
  if (fetchingRef.current) return
87
77
  fetchingRef.current = true
@@ -89,7 +79,7 @@ const TopProductsWidget: React.FC<DashboardWidgetComponentProps<TopProductsSetti
89
79
  setLoading(true)
90
80
  setError(null)
91
81
  try {
92
- const result = await fetchTopProductsData(hydrated)
82
+ const result = await fetchTopProductsData(hydrated, fetchWidgetData)
93
83
  const chartData = result.data.map((item, index) => ({
94
84
  name: truncateLabel(item.groupLabel ?? item.groupKey ?? `Product ${index + 1}`, t),
95
85
  Revenue: item.value ?? 0,
@@ -103,7 +93,7 @@ const TopProductsWidget: React.FC<DashboardWidgetComponentProps<TopProductsSetti
103
93
  onRefreshStateChange?.(false)
104
94
  fetchingRef.current = false
105
95
  }
106
- }, [hydrated, onRefreshStateChange, t])
96
+ }, [hydrated, fetchWidgetData, onRefreshStateChange, t])
107
97
 
108
98
  React.useEffect(() => {
109
99
  refresh().catch(() => {})
@@ -131,29 +131,56 @@ export function getSelectedTenantFromRequest(
131
131
  return parseSelectedTenantCookie(header)
132
132
  }
133
133
 
134
- async function collectWithDescendants(em: EntityManager, tenantId: string, ids: string[]): Promise<Set<string>> {
135
- if (!ids.length) return new Set()
136
- const unique = Array.from(new Set(
134
+ function normalizeOrganizationIds(ids: string[]): string[] {
135
+ return Array.from(new Set(
137
136
  ids.map((value) => normalizeOrganizationId(value)).filter((value): value is string => {
138
137
  if (!value) return false
139
138
  if (isAllOrganizationsSelection(value)) return false
140
139
  return true
141
140
  })
142
141
  ))
143
- if (!unique.length) return new Set()
142
+ }
143
+
144
+ // Map each organization id to itself plus its persisted descendant ids. Only
145
+ // orgs that exist for the tenant and are not soft-deleted are included, so an
146
+ // unknown/inaccessible id simply has no entry (matching the per-id query that
147
+ // returned an empty set for it).
148
+ type OrgDescendantMap = Map<string, string[]>
149
+
150
+ // Issue #2228 — single round-trip for org-scope resolution. Instead of issuing
151
+ // one `organizations` SELECT per `collectWithDescendants` call (up to 3-4
152
+ // sequential queries per request: accessible set, fallback set, selected set),
153
+ // gather every candidate id up front and fetch their descendant expansions in
154
+ // one `em.find(Organization, { id: $in })`. Expansion then happens in-memory.
155
+ async function loadOrgDescendantMap(em: EntityManager, tenantId: string, ids: string[]): Promise<OrgDescendantMap> {
156
+ const unique = normalizeOrganizationIds(ids)
157
+ if (!unique.length) return new Map()
144
158
  const filter: FilterQuery<Organization> = {
145
159
  tenant: tenantId,
146
160
  id: { $in: unique },
147
161
  deletedAt: null,
148
162
  }
149
163
  const orgs = await em.find(Organization, filter)
150
- const set = new Set<string>()
164
+ const map: OrgDescendantMap = new Map()
151
165
  for (const org of orgs) {
152
166
  const id = String(org.id)
153
- set.add(id)
167
+ const expansion = [id]
154
168
  if (Array.isArray(org.descendantIds)) {
155
- for (const desc of org.descendantIds) set.add(String(desc))
169
+ for (const desc of org.descendantIds) expansion.push(String(desc))
156
170
  }
171
+ map.set(id, expansion)
172
+ }
173
+ return map
174
+ }
175
+
176
+ function expandWithDescendants(map: OrgDescendantMap, ids: string[]): Set<string> {
177
+ const set = new Set<string>()
178
+ for (const value of ids) {
179
+ const id = normalizeOrganizationId(value)
180
+ if (!id || isAllOrganizationsSelection(id)) continue
181
+ const expansion = map.get(id)
182
+ if (!expansion) continue
183
+ for (const entry of expansion) set.add(entry)
157
184
  }
158
185
  return set
159
186
  }
@@ -214,14 +241,18 @@ export async function resolveOrganizationScope({
214
241
 
215
242
  const accountOrgId = actorTenantId && actorTenantId === tenantId ? normalizeOrganizationId(auth.orgId) : null
216
243
  const fallbackOrgId = accountOrgId ?? null
217
- let fallbackSet: Set<string> | null = null
218
- const loadFallbackSet = async (): Promise<Set<string> | null> => {
219
- if (!fallbackOrgId) return null
220
- if (!fallbackSet) {
221
- fallbackSet = await collectWithDescendants(em, tenantId, [fallbackOrgId])
222
- }
223
- return fallbackSet
224
- }
244
+
245
+ // Every id that could be expanded below accessible set, fallback (account)
246
+ // org, and the requested selection — is known up front, so fetch them all in
247
+ // a single `organizations` query and expand from the in-memory map.
248
+ const candidateIds = [
249
+ ...(accessibleList ?? []),
250
+ ...(fallbackOrgId ? [fallbackOrgId] : []),
251
+ ...(normalizedSelectedId ? [normalizedSelectedId] : []),
252
+ ]
253
+ const orgDescendants = await loadOrgDescendantMap(em, tenantId, candidateIds)
254
+ const loadFallbackSet = (): Set<string> | null =>
255
+ fallbackOrgId ? expandWithDescendants(orgDescendants, [fallbackOrgId]) : null
225
256
 
226
257
  let allowedSet: Set<string> | null = null
227
258
  if (accessibleList === null) {
@@ -229,11 +260,11 @@ export async function resolveOrganizationScope({
229
260
  } else if (accessibleList.length === 0) {
230
261
  allowedSet = new Set()
231
262
  } else {
232
- allowedSet = await collectWithDescendants(em, tenantId, accessibleList)
263
+ allowedSet = expandWithDescendants(orgDescendants, accessibleList)
233
264
  }
234
265
 
235
266
  if (allowedSet && allowedSet.size === 0 && fallbackOrgId) {
236
- const computed = await loadFallbackSet()
267
+ const computed = loadFallbackSet()
237
268
  if (computed && computed.size > 0) {
238
269
  allowedSet = computed
239
270
  }
@@ -256,17 +287,17 @@ export async function resolveOrganizationScope({
256
287
 
257
288
  let filterSet: Set<string> | null = null
258
289
  if (effectiveSelected) {
259
- filterSet = await collectWithDescendants(em, tenantId, [effectiveSelected])
290
+ filterSet = expandWithDescendants(orgDescendants, [effectiveSelected])
260
291
  } else if (allowedSet !== null) {
261
292
  filterSet = allowedSet
262
293
  } else if (widenToAllOrgs) {
263
294
  filterSet = null
264
295
  } else if (auth.orgId) {
265
- filterSet = await loadFallbackSet()
296
+ filterSet = loadFallbackSet()
266
297
  }
267
298
 
268
299
  if ((!filterSet || filterSet.size === 0) && fallbackOrgId && !widenToAllOrgs) {
269
- const computed = await loadFallbackSet()
300
+ const computed = loadFallbackSet()
270
301
  if (computed && computed.size > 0) {
271
302
  filterSet = computed
272
303
  if (!effectiveSelected) {