@gooddata/sdk-ui-catalog 11.32.0-alpha.2 → 11.32.0-alpha.4

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 (55) hide show
  1. package/esm/AnalyticsCatalog.d.ts.map +1 -1
  2. package/esm/AnalyticsCatalog.js +1 -2
  3. package/esm/AnalyticsCatalog.js.map +1 -1
  4. package/esm/catalogDetail/CatalogDetailTabQuality.js +1 -1
  5. package/esm/catalogDetail/CatalogDetailTabQuality.js.map +1 -1
  6. package/esm/catalogItem/CatalogFeedContext.d.ts +1 -0
  7. package/esm/catalogItem/CatalogFeedContext.d.ts.map +1 -1
  8. package/esm/catalogItem/CatalogFeedContext.js +6 -3
  9. package/esm/catalogItem/CatalogFeedContext.js.map +1 -1
  10. package/esm/catalogItem/useCatalogEndpoints.d.ts +29 -0
  11. package/esm/catalogItem/useCatalogEndpoints.d.ts.map +1 -0
  12. package/esm/catalogItem/useCatalogEndpoints.js +105 -0
  13. package/esm/catalogItem/useCatalogEndpoints.js.map +1 -0
  14. package/esm/catalogItem/useCatalogItemFeed.d.ts +5 -6
  15. package/esm/catalogItem/useCatalogItemFeed.d.ts.map +1 -1
  16. package/esm/catalogItem/useCatalogItemFeed.js +16 -336
  17. package/esm/catalogItem/useCatalogItemFeed.js.map +1 -1
  18. package/esm/catalogItem/useEndpointPaginator.d.ts +24 -0
  19. package/esm/catalogItem/useEndpointPaginator.d.ts.map +1 -0
  20. package/esm/catalogItem/useEndpointPaginator.js +228 -0
  21. package/esm/catalogItem/useEndpointPaginator.js.map +1 -0
  22. package/esm/filter/FilterObjectType.js +2 -2
  23. package/esm/filter/FilterObjectType.js.map +1 -1
  24. package/esm/localization/bundles/en-US.localization-bundle.js +1 -1
  25. package/esm/localization/bundles/en-US.localization-bundle.js.map +1 -1
  26. package/esm/main/Main.d.ts.map +1 -1
  27. package/esm/main/Main.js +4 -4
  28. package/esm/main/Main.js.map +1 -1
  29. package/esm/quality/QualityScoreCardAction.d.ts.map +1 -1
  30. package/esm/quality/QualityScoreCardAction.js +10 -4
  31. package/esm/quality/QualityScoreCardAction.js.map +1 -1
  32. package/esm/search/FullTextSearchInput.d.ts.map +1 -1
  33. package/esm/search/FullTextSearchInput.js +8 -8
  34. package/esm/search/FullTextSearchInput.js.map +1 -1
  35. package/esm/table/Table.d.ts.map +1 -1
  36. package/esm/table/Table.js +4 -0
  37. package/esm/table/Table.js.map +1 -1
  38. package/esm/table/columns/TagsColumn.js +2 -2
  39. package/esm/table/columns/TagsColumn.js.map +1 -1
  40. package/package.json +13 -13
  41. package/styles/css/main.css +7 -0
  42. package/styles/css/main.css.map +1 -1
  43. package/styles/scss/main.scss +8 -0
  44. package/esm/catalogItem/CatalogItemFeed.d.ts +0 -15
  45. package/esm/catalogItem/CatalogItemFeed.d.ts.map +0 -1
  46. package/esm/catalogItem/CatalogItemFeed.js +0 -17
  47. package/esm/catalogItem/CatalogItemFeed.js.map +0 -1
  48. package/esm/catalogItem/useCatalogItemMutations.d.ts +0 -5
  49. package/esm/catalogItem/useCatalogItemMutations.d.ts.map +0 -1
  50. package/esm/catalogItem/useCatalogItemMutations.js +0 -37
  51. package/esm/catalogItem/useCatalogItemMutations.js.map +0 -1
  52. package/esm/objectType/ObjectTypeContext.d.ts +0 -16
  53. package/esm/objectType/ObjectTypeContext.d.ts.map +0 -1
  54. package/esm/objectType/ObjectTypeContext.js +0 -37
  55. package/esm/objectType/ObjectTypeContext.js.map +0 -1
@@ -1,76 +1,38 @@
1
1
  // (C) 2025-2026 GoodData Corporation
2
- import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
3
- import {} from "../async/types.js";
2
+ import { useCallback, useMemo } from "react";
3
+ import { areObjRefsEqual } from "@gooddata/sdk-model";
4
4
  import { useFilterState, useQualityFilter } from "../filter/FilterContext.js";
5
- import { useMounted } from "../hooks/useMounted.js";
6
5
  import { ObjectTypes } from "../objectType/constants.js";
7
6
  import {} from "../objectType/types.js";
8
7
  import { useIsParametersEnabled } from "../parameter/gate.js";
9
8
  import { useFullTextSearchState } from "../search/FullTextSearchContext.js";
10
9
  import { convertEntityToCatalogItem } from "./converter.js";
11
- import { getAttributesQuery, getDashboardsQuery, getDateDatasetsQuery, getFactsQuery, getInsightsQuery, getMetricsQuery, getParametersQuery, } from "./query.js";
12
- import { useCatalogItemRemoveCallback, useCatalogItemUpdateCallback } from "./useCatalogItemMutations.js";
13
- export function useCatalogItemFeed({ backend, workspace, id, pageSize }) {
14
- const state = useFeedState();
15
- const cache = useFeedCache();
10
+ import { useCatalogEndpoints, useCatalogQueryOptions } from "./useCatalogEndpoints.js";
11
+ import { useEndpointPaginator } from "./useEndpointPaginator.js";
12
+ export function useCatalogItemFeed(feedOptions) {
16
13
  const { searchTerm: search } = useFullTextSearchState();
17
14
  const { types, origin, createdBy, tags, isHidden, certification } = useFilterState();
18
15
  const qualityIds = useQualityFilter();
19
16
  const isParametersEnabled = useIsParametersEnabled();
20
- const { status, totalCount, totalCounts, error, items, setItems, setTotalCounts } = state;
21
- const queryOptions = useMemo(() => {
22
- let includeIds = id;
23
- let excludeIds = undefined;
24
- if (qualityIds) {
25
- if (qualityIds.isInverted) {
26
- excludeIds = qualityIds.values;
27
- }
28
- else {
29
- includeIds = [...new Set([...qualityIds.values, ...(id ?? [])])];
30
- }
31
- }
32
- return {
33
- backend,
34
- workspace,
35
- search,
36
- origin,
37
- id: includeIds,
38
- excludeId: excludeIds,
39
- createdBy: createdBy.isInverted ? undefined : createdBy.values,
40
- excludeCreatedBy: createdBy.isInverted ? createdBy.values : undefined,
41
- tags: tags.isInverted ? undefined : tags.values,
42
- excludeTags: tags.isInverted ? tags.values : undefined,
43
- isHidden,
44
- certification,
45
- pageSize,
46
- };
47
- }, [
48
- backend,
49
- workspace,
17
+ const queryOptions = useCatalogQueryOptions(feedOptions, {
50
18
  search,
51
19
  origin,
52
- id,
53
20
  createdBy,
54
- pageSize,
55
21
  tags,
56
22
  qualityIds,
57
23
  isHidden,
58
24
  certification,
59
- ]);
60
- const endpoints = useEndpoints(types, queryOptions, isParametersEnabled);
61
- // reset
62
- useReset(state, cache, endpoints);
63
- // load first pages (cached)
64
- useFirstLoad(state, cache, endpoints);
65
- // refetch particular object type
66
- const refetchObjectType = useObjectTypeRefetch(state, cache, endpoints);
67
- // total count by type calculation
25
+ });
26
+ const endpoints = useCatalogEndpoints(types, queryOptions, { isParametersEnabled });
27
+ const paginator = useEndpointPaginator(endpoints, convertEntityToCatalogItem);
28
+ const { items, status, error, totalCount, totalCounts, hasNext, next, refetch, updateWhere, removeWhere, } = paginator;
68
29
  const totalCountByType = useMemo(() => getTotalCountByType(endpoints, totalCounts), [endpoints, totalCounts]);
69
- // cache update
70
- const updateItem = useCatalogItemUpdateCallback(cache.endpointItems, setItems);
71
- const removeItem = useCatalogItemRemoveCallback(cache.endpointItems, setItems, setTotalCounts);
72
- // Next page callback
73
- const { hasNext, next } = useNextCallback(state, cache, endpoints);
30
+ const refetchObjectType = useCallback((type) => {
31
+ const index = endpoints.findIndex((endpoint) => endpoint.type === type);
32
+ return index === -1 ? Promise.resolve() : refetch(index);
33
+ }, [endpoints, refetch]);
34
+ const updateItem = useCallback((item) => updateWhere((existing) => areObjRefsEqual(existing, item), item), [updateWhere]);
35
+ const removeItem = useCallback((item) => removeWhere((existing) => areObjRefsEqual(existing, item)), [removeWhere]);
74
36
  return {
75
37
  items,
76
38
  error,
@@ -84,288 +46,6 @@ export function useCatalogItemFeed({ backend, workspace, id, pageSize }) {
84
46
  refetchObjectType,
85
47
  };
86
48
  }
87
- function useReset(state, cache, endpoints) {
88
- const { initialized, endpointCache, endpointItems } = cache;
89
- const { setStatus, setError, setCurrentEndpoint, setTotalCounts, setItems } = state;
90
- useLayoutEffect(() => {
91
- if (!initialized.current) {
92
- return;
93
- }
94
- initialized.current = false;
95
- endpointCache.current = [];
96
- endpointItems.current = [];
97
- setStatus("loading");
98
- setError(null);
99
- setCurrentEndpoint(0);
100
- setTotalCounts([]);
101
- setItems([]);
102
- }, [
103
- endpointCache,
104
- endpointItems,
105
- endpoints,
106
- initialized,
107
- setCurrentEndpoint,
108
- setError,
109
- setItems,
110
- setStatus,
111
- setTotalCounts,
112
- ]);
113
- }
114
- function useEndpoints(types, queryOptions, isParametersEnabled) {
115
- return useMemo(() => {
116
- if (queryOptions.id?.length === 0) {
117
- return [];
118
- }
119
- const promises = [];
120
- if (types.includes(ObjectTypes.DASHBOARD) || types.length === 0) {
121
- promises.push({
122
- query: () => getDashboardsQuery(queryOptions).query(),
123
- type: ObjectTypes.DASHBOARD,
124
- });
125
- }
126
- if (types.includes(ObjectTypes.VISUALIZATION) || types.length === 0) {
127
- promises.push({
128
- query: () => getInsightsQuery(queryOptions).query(),
129
- type: ObjectTypes.VISUALIZATION,
130
- });
131
- }
132
- if (types.includes(ObjectTypes.METRIC) || types.length === 0) {
133
- promises.push({ query: () => getMetricsQuery(queryOptions).query(), type: ObjectTypes.METRIC });
134
- }
135
- if (isParametersEnabled && (types.includes(ObjectTypes.PARAMETER) || types.length === 0)) {
136
- promises.push({
137
- query: () => getParametersQuery(queryOptions).query(),
138
- type: ObjectTypes.PARAMETER,
139
- });
140
- }
141
- if (!queryOptions.createdBy?.length &&
142
- !queryOptions.excludeCreatedBy?.length &&
143
- !queryOptions.certification) {
144
- if (types.includes(ObjectTypes.ATTRIBUTE) || types.length === 0) {
145
- promises.push({
146
- query: () => getAttributesQuery(queryOptions).query(),
147
- type: ObjectTypes.ATTRIBUTE,
148
- });
149
- }
150
- if (types.includes(ObjectTypes.FACT) || types.length === 0) {
151
- promises.push({ query: () => getFactsQuery(queryOptions).query(), type: ObjectTypes.FACT });
152
- }
153
- if (types.includes(ObjectTypes.DATASET) || types.length === 0) {
154
- promises.push({
155
- query: () => getDateDatasetsQuery(queryOptions).query(),
156
- type: ObjectTypes.DATASET,
157
- });
158
- }
159
- }
160
- return promises;
161
- }, [isParametersEnabled, queryOptions, types]);
162
- }
163
- function useFeedCache() {
164
- const endpointCache = useRef([]);
165
- const initialized = useRef(false);
166
- const endpointItems = useRef([]);
167
- return {
168
- initialized,
169
- endpointCache,
170
- endpointItems,
171
- };
172
- }
173
- function useFeedState() {
174
- // State
175
- const [status, setStatus] = useState("idle");
176
- const [error, setError] = useState(null);
177
- const [currentEndpoint, setCurrentEndpoint] = useState(0);
178
- const [totalCounts, setTotalCounts] = useState([]);
179
- const [items, setItems] = useState([]);
180
- // Derived state
181
- const totalCount = getTotalCount(totalCounts);
182
- return {
183
- status,
184
- setStatus,
185
- error,
186
- setError,
187
- currentEndpoint,
188
- setCurrentEndpoint,
189
- totalCounts,
190
- totalCount,
191
- setTotalCounts,
192
- items,
193
- setItems,
194
- };
195
- }
196
- function useFirstLoad(state, cache, endpoints) {
197
- const { setStatus, setError, setCurrentEndpoint, setTotalCounts, setItems } = state;
198
- const { initialized, endpointCache, endpointItems } = cache;
199
- // load first pages (cached)
200
- useEffect(() => {
201
- // prevent re-init
202
- if (initialized.current) {
203
- return;
204
- }
205
- initialized.current = true;
206
- setStatus("loading");
207
- setError(null);
208
- let mounted = true;
209
- void (async () => {
210
- try {
211
- const firstPages = await Promise.all(endpoints.map((ep) => ep.query()));
212
- if (!mounted) {
213
- return;
214
- }
215
- // Set initial data for endpoints
216
- endpointCache.current = firstPages;
217
- endpointItems.current = firstPages.map((p) => p.items.map(convertEntityToCatalogItem));
218
- let currentEndpoint = firstPages.findIndex((page) => {
219
- return page.items.length < page.totalCount;
220
- });
221
- currentEndpoint = currentEndpoint === -1 ? firstPages.length : currentEndpoint;
222
- setCurrentEndpoint(currentEndpoint);
223
- setItems(getItemsThroughEndpoint(endpointItems.current, currentEndpoint));
224
- setTotalCounts(firstPages.map((page) => page.totalCount));
225
- setStatus("success");
226
- }
227
- catch (error) {
228
- console.error(error);
229
- setError(error);
230
- setItems([]);
231
- setTotalCounts([]);
232
- setStatus("error");
233
- }
234
- })();
235
- return () => {
236
- mounted = false;
237
- };
238
- }, [
239
- endpointCache,
240
- endpointItems,
241
- endpoints,
242
- initialized,
243
- setCurrentEndpoint,
244
- setError,
245
- setItems,
246
- setStatus,
247
- setTotalCounts,
248
- ]);
249
- }
250
- function useNextCallback(state, cache, endpoints) {
251
- const mounted = useMounted();
252
- const { status, totalCounts, setStatus, currentEndpoint, setCurrentEndpoint, setItems, setError } = state;
253
- const { endpointCache, endpointItems } = cache;
254
- // Check if there are more endpointItems to load
255
- const hasNext = state.items.length < state.totalCount;
256
- const nextRef = useRef(async () => { });
257
- nextRef.current = async () => {
258
- let idx = currentEndpoint;
259
- if (status !== "success" || !hasNext) {
260
- return;
261
- }
262
- setStatus("loadingMore");
263
- while (idx < endpoints.length) {
264
- const items = (endpointItems.current[idx] = endpointItems.current[idx] ?? []);
265
- const totalCount = totalCounts[idx] ?? 0;
266
- const current = endpointCache.current[idx];
267
- if (!current) {
268
- break;
269
- }
270
- if (items.length < totalCount) {
271
- try {
272
- // load next page of this endpoint
273
- const nextPage = await current.next();
274
- endpointCache.current[idx] = nextPage;
275
- // prevent updates if unmounted
276
- if (!mounted.current) {
277
- return;
278
- }
279
- let i = 0;
280
- for (let o = nextPage.offset; o < nextPage.offset + nextPage.items.length; o++) {
281
- items[o] = convertEntityToCatalogItem(nextPage.items[i++]);
282
- }
283
- setItems(getItemsThroughEndpoint(endpointItems.current, idx));
284
- setCurrentEndpoint(idx);
285
- setStatus("success");
286
- setError(null);
287
- }
288
- catch (error) {
289
- console.error(error);
290
- setStatus("error");
291
- setError(error);
292
- }
293
- return;
294
- }
295
- idx++;
296
- }
297
- setStatus("success");
298
- setCurrentEndpoint(idx); // finished last endpoint
299
- setItems(getItemsThroughEndpoint(endpointItems.current, idx));
300
- };
301
- const next = useCallback(() => nextRef.current(), []);
302
- return {
303
- next,
304
- hasNext,
305
- };
306
- }
307
- function useObjectTypeRefetch(state, cache, endpoints) {
308
- const mounted = useMounted();
309
- const { initialized, endpointCache, endpointItems } = cache;
310
- const { currentEndpoint, setCurrentEndpoint, setItems, setTotalCounts, setError } = state;
311
- const refetchRef = useRef(async (_type) => { });
312
- refetchRef.current = async (type) => {
313
- if (!initialized.current) {
314
- return;
315
- }
316
- const endpointIndex = endpoints.findIndex((endpoint) => endpoint.type === type);
317
- if (endpointIndex === -1) {
318
- return;
319
- }
320
- try {
321
- const refreshedEndpoint = await queryRefreshedEndpoint(endpoints[endpointIndex], endpointItems.current[endpointIndex]?.length ?? 0);
322
- if (!mounted.current) {
323
- return;
324
- }
325
- endpointCache.current[endpointIndex] = refreshedEndpoint.page;
326
- endpointItems.current[endpointIndex] = refreshedEndpoint.items;
327
- const nextCurrentEndpoint = endpointIndex < currentEndpoint &&
328
- refreshedEndpoint.items.length < refreshedEndpoint.page.totalCount
329
- ? endpointIndex
330
- : currentEndpoint;
331
- setCurrentEndpoint(nextCurrentEndpoint);
332
- setItems(getItemsThroughEndpoint(endpointItems.current, nextCurrentEndpoint));
333
- setTotalCounts((currentCounts) => {
334
- const nextCounts = [...currentCounts];
335
- nextCounts[endpointIndex] = refreshedEndpoint.page.totalCount;
336
- return nextCounts;
337
- });
338
- setError(null);
339
- }
340
- catch (error) {
341
- // Refetch failure should not affect other operations, using console.error instead of throwing
342
- console.error(error);
343
- }
344
- };
345
- return useCallback((type) => refetchRef.current(type), []);
346
- }
347
- async function queryRefreshedEndpoint(endpoint, loadedItemCount) {
348
- let page = await endpoint.query();
349
- const items = [];
350
- mergeEndpointPageItems(items, page);
351
- const targetItemCount = Math.min(Math.max(loadedItemCount, page.items.length), page.totalCount);
352
- while (items.length < targetItemCount) {
353
- page = await page.next();
354
- mergeEndpointPageItems(items, page);
355
- }
356
- return { page, items };
357
- }
358
- function getTotalCount(totalCounts) {
359
- return totalCounts.reduce((acc, count) => acc + count, 0);
360
- }
361
- function getItemsThroughEndpoint(endpointItems, currentEndpoint) {
362
- return endpointItems.slice(0, currentEndpoint + 1).flat();
363
- }
364
- function mergeEndpointPageItems(items, page) {
365
- page.items.forEach((item, index) => {
366
- items[page.offset + index] = convertEntityToCatalogItem(item);
367
- });
368
- }
369
49
  function getTotalCountByType(endpoints, totalCounts) {
370
50
  const base = {
371
51
  [ObjectTypes.DASHBOARD]: 0,
@@ -1 +1 @@
1
- {"version":3,"file":"useCatalogItemFeed.js","sourceRoot":"","sources":["../../src/catalogItem/useCatalogItemFeed.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useCatalogItemFeed.js","sourceRoot":"","sources":["../../src/catalogItem/useCatalogItemFeed.ts"],"names":[],"mappings":"AAAA,qCAAqC;AAErC,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAE7C,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAEtD,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAC9E,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAmB,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,sBAAsB,EAAE,MAAM,oCAAoC,CAAC;AAC5E,OAAO,EAAE,0BAA0B,EAAE,MAAM,gBAAgB,CAAC;AAE5D,OAAO,EAAqB,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAC1G,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAEjE,MAAM,UAAU,kBAAkB,CAAC,WAAoC,EAAE;IACrE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,sBAAsB,EAAE,CAAC;IACxD,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,aAAa,EAAE,GAAG,cAAc,EAAE,CAAC;IACrF,MAAM,UAAU,GAAG,gBAAgB,EAAE,CAAC;IACtC,MAAM,mBAAmB,GAAG,sBAAsB,EAAE,CAAC;IAErD,MAAM,YAAY,GAAG,sBAAsB,CAAC,WAAW,EAAE;QACrD,MAAM;QACN,MAAM;QACN,SAAS;QACT,IAAI;QACJ,UAAU;QACV,QAAQ;QACR,aAAa;KAChB,CAAC,CAAC;IACH,MAAM,SAAS,GAAG,mBAAmB,CAAC,KAAK,EAAE,YAAY,EAAE,EAAE,mBAAmB,EAAE,CAAC,CAAC;IAEpF,MAAM,SAAS,GAAG,oBAAoB,CAAC,SAAS,EAAE,0BAA0B,CAAC,CAAC;IAC9E,MAAM,EACF,KAAK,EACL,MAAM,EACN,KAAK,EACL,UAAU,EACV,WAAW,EACX,OAAO,EACP,IAAI,EACJ,OAAO,EACP,WAAW,EACX,WAAW,GACd,GAAG,SAAS,CAAC;IAEd,MAAM,gBAAgB,GAAG,OAAO,CAC5B,GAAG,EAAE,CAAC,mBAAmB,CAAC,SAAS,EAAE,WAAW,CAAC,EACjD,CAAC,SAAS,EAAE,WAAW,CAAC,CAC3B,CAAC;IAEF,MAAM,iBAAiB,GAAG,WAAW,CACjC,CAAC,IAAgB,EAAE,EAAE,CAAC;QAClB,MAAM,KAAK,GAAG,SAAS,CAAC,SAAS,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;QACxE,OAAO,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAAA,CAC5D,EACD,CAAC,SAAS,EAAE,OAAO,CAAC,CACvB,CAAC;IAEF,MAAM,UAAU,GAAG,WAAW,CAC1B,CAAC,IAAkB,EAAE,EAAE,CAAC,WAAW,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,eAAe,CAAC,QAAQ,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,EACxF,CAAC,WAAW,CAAC,CAChB,CAAC;IACF,MAAM,UAAU,GAAG,WAAW,CAC1B,CAAC,IAAqB,EAAE,EAAE,CAAC,WAAW,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,eAAe,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,EACrF,CAAC,WAAW,CAAC,CAChB,CAAC;IAEF,OAAO;QACH,KAAK;QACL,KAAK;QACL,MAAM;QACN,UAAU;QACV,gBAAgB;QAChB,OAAO;QACP,IAAI;QACJ,UAAU;QACV,UAAU;QACV,iBAAiB;KACpB,CAAC;AAAA,CACL;AAED,SAAS,mBAAmB,CAAC,SAAyB,EAAE,WAAqB,EAAE;IAC3E,MAAM,IAAI,GAAG;QACT,CAAC,WAAW,CAAC,SAAS,CAAC,EAAE,CAAC;QAC1B,CAAC,WAAW,CAAC,aAAa,CAAC,EAAE,CAAC;QAC9B,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC;QACvB,CAAC,WAAW,CAAC,SAAS,CAAC,EAAE,CAAC;QAC1B,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC;QACrB,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC;QACxB,CAAC,WAAW,CAAC,SAAS,CAAC,EAAE,CAAC;KAC7B,CAAC;IAEF,SAAS,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,GAAG,EAAE,EAAE,CAAC;QACjC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAAA,CAC/C,CAAC,CAAC;IAEH,OAAO,IAAI,CAAC;AAAA,CACf"}
@@ -0,0 +1,24 @@
1
+ import { type AsyncStatus } from "../async/types.js";
2
+ export interface IPaginatorPage<TEntity> {
3
+ readonly items: readonly TEntity[];
4
+ readonly offset: number;
5
+ readonly totalCount: number;
6
+ next(): Promise<IPaginatorPage<TEntity>>;
7
+ }
8
+ export interface IPaginatorEndpoint<TEntity> {
9
+ query(): Promise<IPaginatorPage<TEntity>>;
10
+ }
11
+ export interface IEndpointPaginator<TItem> {
12
+ items: TItem[];
13
+ status: AsyncStatus;
14
+ error: Error | null;
15
+ totalCount: number;
16
+ totalCounts: number[];
17
+ hasNext: boolean;
18
+ next: () => Promise<void>;
19
+ refetch: (index: number) => Promise<void>;
20
+ updateWhere: (predicate: (item: TItem) => boolean, replacement: TItem) => void;
21
+ removeWhere: (predicate: (item: TItem) => boolean) => void;
22
+ }
23
+ export declare function useEndpointPaginator<TEntity, TItem>(endpoints: ReadonlyArray<IPaginatorEndpoint<TEntity>>, convert: (entity: TEntity) => TItem): IEndpointPaginator<TItem>;
24
+ //# sourceMappingURL=useEndpointPaginator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useEndpointPaginator.d.ts","sourceRoot":"","sources":["../../src/catalogItem/useEndpointPaginator.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGrD,MAAM,WAAW,cAAc,CAAC,OAAO;IACnC,QAAQ,CAAC,KAAK,EAAE,SAAS,OAAO,EAAE,CAAC;IACnC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;CAC5C;AAED,MAAM,WAAW,kBAAkB,CAAC,OAAO;IACvC,KAAK,IAAI,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;CAC7C;AAED,MAAM,WAAW,kBAAkB,CAAC,KAAK;IACrC,KAAK,EAAE,KAAK,EAAE,CAAC;IACf,MAAM,EAAE,WAAW,CAAC;IACpB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1C,WAAW,EAAE,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,OAAO,EAAE,WAAW,EAAE,KAAK,KAAK,IAAI,CAAC;IAC/E,WAAW,EAAE,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,OAAO,KAAK,IAAI,CAAC;CAC9D;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,KAAK,EAC/C,SAAS,EAAE,aAAa,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC,EACrD,OAAO,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,KAAK,GACpC,kBAAkB,CAAC,KAAK,CAAC,CAsO3B"}
@@ -0,0 +1,228 @@
1
+ // (C) 2026 GoodData Corporation
2
+ // Type parameterization choice:
3
+ // The paginator is parameterized over a common page shape `IPaginatorPage<TEntity>`
4
+ // (`items` / `offset` / `totalCount` / `next`) plus a `convert: (entity) => TItem`
5
+ // callback supplied by the caller. The full backend `IPagedResource<T>` union
6
+ // is structurally assignable to this shape, so callers (e.g. `useCatalogItemFeed`)
7
+ // keep `convertEntityToCatalogItem` in the composition root rather than pushing
8
+ // catalog-domain types into this hook.
9
+ import { useCallback, useEffect, useLayoutEffect, useRef, useState } from "react";
10
+ import {} from "../async/types.js";
11
+ import { useMounted } from "../hooks/useMounted.js";
12
+ export function useEndpointPaginator(endpoints, convert) {
13
+ const mounted = useMounted();
14
+ const convertRef = useRef(convert);
15
+ convertRef.current = convert;
16
+ const [status, setStatus] = useState("idle");
17
+ const [error, setError] = useState(null);
18
+ const [currentEndpoint, setCurrentEndpoint] = useState(0);
19
+ const [totalCounts, setTotalCounts] = useState([]);
20
+ const [items, setItems] = useState([]);
21
+ const endpointCache = useRef([]);
22
+ const endpointItems = useRef([]);
23
+ const initialized = useRef(false);
24
+ // Reset whenever the endpoints array changes. useLayoutEffect runs before
25
+ // the matching useEffect, so any reset is observed by callers before the
26
+ // first-load effect kicks off the new round of queries.
27
+ useLayoutEffect(() => {
28
+ if (!initialized.current) {
29
+ return;
30
+ }
31
+ initialized.current = false;
32
+ endpointCache.current = [];
33
+ endpointItems.current = [];
34
+ setStatus("loading");
35
+ setError(null);
36
+ setCurrentEndpoint(0);
37
+ setTotalCounts([]);
38
+ setItems([]);
39
+ }, [endpoints]);
40
+ // First-load effect: in parallel, query the first page of every endpoint.
41
+ useEffect(() => {
42
+ if (initialized.current) {
43
+ return;
44
+ }
45
+ initialized.current = true;
46
+ setStatus("loading");
47
+ setError(null);
48
+ let active = true;
49
+ void (async () => {
50
+ try {
51
+ const firstPages = await Promise.all(endpoints.map((ep) => ep.query()));
52
+ if (!active) {
53
+ return;
54
+ }
55
+ endpointCache.current = firstPages;
56
+ endpointItems.current = firstPages.map((page) => page.items.map((entity) => convertRef.current(entity)));
57
+ let cursor = firstPages.findIndex((page) => page.items.length < page.totalCount);
58
+ cursor = cursor === -1 ? firstPages.length : cursor;
59
+ setCurrentEndpoint(cursor);
60
+ setItems(getItemsThroughEndpoint(endpointItems.current, cursor));
61
+ setTotalCounts(firstPages.map((page) => page.totalCount));
62
+ setStatus("success");
63
+ }
64
+ catch (loadError) {
65
+ console.error(loadError);
66
+ if (!active) {
67
+ return;
68
+ }
69
+ setError(loadError);
70
+ setItems([]);
71
+ setTotalCounts([]);
72
+ setStatus("error");
73
+ }
74
+ })();
75
+ return () => {
76
+ active = false;
77
+ };
78
+ }, [endpoints]);
79
+ const totalCount = totalCounts.reduce((acc, count) => acc + count, 0);
80
+ const hasNext = items.length < totalCount;
81
+ const nextRef = useRef(async () => { });
82
+ nextRef.current = async () => {
83
+ let idx = currentEndpoint;
84
+ if (status !== "success" || !hasNext) {
85
+ return;
86
+ }
87
+ setStatus("loadingMore");
88
+ while (idx < endpoints.length) {
89
+ const itemsForEndpoint = (endpointItems.current[idx] = endpointItems.current[idx] ?? []);
90
+ const totalForEndpoint = totalCounts[idx] ?? 0;
91
+ const cached = endpointCache.current[idx];
92
+ if (!cached) {
93
+ break;
94
+ }
95
+ if (itemsForEndpoint.length < totalForEndpoint) {
96
+ try {
97
+ const nextPage = await cached.next();
98
+ endpointCache.current[idx] = nextPage;
99
+ if (!mounted.current) {
100
+ return;
101
+ }
102
+ let i = 0;
103
+ for (let o = nextPage.offset; o < nextPage.offset + nextPage.items.length; o++) {
104
+ itemsForEndpoint[o] = convertRef.current(nextPage.items[i++]);
105
+ }
106
+ setItems(getItemsThroughEndpoint(endpointItems.current, idx));
107
+ setCurrentEndpoint(idx);
108
+ setStatus("success");
109
+ setError(null);
110
+ }
111
+ catch (nextError) {
112
+ console.error(nextError);
113
+ if (!mounted.current) {
114
+ return;
115
+ }
116
+ setStatus("error");
117
+ setError(nextError);
118
+ }
119
+ return;
120
+ }
121
+ idx++;
122
+ }
123
+ setStatus("success");
124
+ setCurrentEndpoint(idx);
125
+ setItems(getItemsThroughEndpoint(endpointItems.current, idx));
126
+ };
127
+ const next = useCallback(() => nextRef.current(), []);
128
+ const refetchRef = useRef(async (_index) => { });
129
+ refetchRef.current = async (index) => {
130
+ if (!initialized.current) {
131
+ return;
132
+ }
133
+ if (index < 0 || index >= endpoints.length) {
134
+ return;
135
+ }
136
+ const endpoint = endpoints[index];
137
+ if (!endpoint) {
138
+ return;
139
+ }
140
+ try {
141
+ const previousDepth = endpointItems.current[index]?.length ?? 0;
142
+ const refreshed = await queryRefreshedEndpoint(endpoint, previousDepth, convertRef.current);
143
+ if (!mounted.current) {
144
+ return;
145
+ }
146
+ endpointCache.current[index] = refreshed.page;
147
+ endpointItems.current[index] = refreshed.items;
148
+ const stillIncomplete = refreshed.items.length < refreshed.page.totalCount;
149
+ const nextCursor = index < currentEndpoint && stillIncomplete ? index : currentEndpoint;
150
+ setCurrentEndpoint(nextCursor);
151
+ setItems(getItemsThroughEndpoint(endpointItems.current, nextCursor));
152
+ setTotalCounts((current) => {
153
+ const updated = [...current];
154
+ updated[index] = refreshed.page.totalCount;
155
+ return updated;
156
+ });
157
+ setError(null);
158
+ }
159
+ catch (refetchError) {
160
+ // Refetch failure is non-fatal: log and leave existing state intact.
161
+ console.error(refetchError);
162
+ }
163
+ };
164
+ const refetch = useCallback((index) => refetchRef.current(index), []);
165
+ const updateWhere = useCallback((predicate, replacement) => {
166
+ let matched = false;
167
+ endpointItems.current.forEach((bucket) => {
168
+ bucket.forEach((item, idx) => {
169
+ if (predicate(item)) {
170
+ bucket[idx] = replacement;
171
+ matched = true;
172
+ }
173
+ });
174
+ });
175
+ if (!matched) {
176
+ return;
177
+ }
178
+ setItems((current) => current.map((item) => (predicate(item) ? replacement : item)));
179
+ }, []);
180
+ const removeWhere = useCallback((predicate) => {
181
+ const removedByEndpoint = new Map();
182
+ endpointItems.current.forEach((bucket, endpointIndex) => {
183
+ for (let i = bucket.length - 1; i >= 0; i -= 1) {
184
+ if (predicate(bucket[i])) {
185
+ bucket.splice(i, 1);
186
+ removedByEndpoint.set(endpointIndex, (removedByEndpoint.get(endpointIndex) ?? 0) + 1);
187
+ }
188
+ }
189
+ });
190
+ if (removedByEndpoint.size === 0) {
191
+ return;
192
+ }
193
+ setItems((current) => current.filter((item) => !predicate(item)));
194
+ setTotalCounts((counts) => counts.map((count, index) => count - (removedByEndpoint.get(index) ?? 0)));
195
+ }, []);
196
+ return {
197
+ items,
198
+ status,
199
+ error,
200
+ totalCount,
201
+ totalCounts,
202
+ hasNext,
203
+ next,
204
+ refetch,
205
+ updateWhere,
206
+ removeWhere,
207
+ };
208
+ }
209
+ async function queryRefreshedEndpoint(endpoint, previousDepth, convert) {
210
+ let page = await endpoint.query();
211
+ const items = [];
212
+ mergeEndpointPageItems(items, page, convert);
213
+ const targetDepth = Math.min(Math.max(previousDepth, page.items.length), page.totalCount);
214
+ while (items.length < targetDepth) {
215
+ page = await page.next();
216
+ mergeEndpointPageItems(items, page, convert);
217
+ }
218
+ return { page, items };
219
+ }
220
+ function mergeEndpointPageItems(items, page, convert) {
221
+ page.items.forEach((entity, index) => {
222
+ items[page.offset + index] = convert(entity);
223
+ });
224
+ }
225
+ function getItemsThroughEndpoint(endpointItems, cursor) {
226
+ return endpointItems.slice(0, cursor + 1).flat();
227
+ }
228
+ //# sourceMappingURL=useEndpointPaginator.js.map