@blocksdiy/blocks-client-sdk 1.18.2 → 1.18.3

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.
package/dist/Entity.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { type EntityPage, type EntityQuery } from "./EntityQuery.js";
1
2
  /**
2
3
  * Base entity properties automatically included in all entity instances
3
4
  * These system fields are managed by the backend and available on all entities
@@ -122,12 +123,14 @@ export declare class Entity<EC extends EntityConfig = EntityConfig> {
122
123
  */
123
124
  findOne(filters: Record<string, any>): Promise<EntityType<EC> | null>;
124
125
  /**
125
- * Retrieves multiple entities that match the provided filters
126
+ * Retrieves the entities that match a query
126
127
  *
127
- * Fetches entities from the database and transforms them to the frontend format
128
- * with properly mapped property names.
128
+ * Pass an {@link EntityQuery}: `where` picks the rows, `orderBy` orders them, and `page.size`
129
+ * caps the result at one page. Without `page`, the server's default row limit applies — use
130
+ * {@link findPage} to read past it. Legacy key/value filters (`{ category: "electronics" }`)
131
+ * are still accepted and keep their meaning; new code should use a query.
129
132
  *
130
- * @param {any} [filters] - Optional filters to apply to the query
133
+ * @param {EntityQuery<EC> | Record<string, any>} [query] - The query (or legacy filters)
131
134
  * @returns {Promise<Array<EntityType<EC>>>} Array of matching entities
132
135
  * @example
133
136
  * ```ts
@@ -135,16 +138,39 @@ export declare class Entity<EC extends EntityConfig = EntityConfig> {
135
138
  *
136
139
  * const productEntity = new Entity(ProductEntity);
137
140
  *
138
- * // Find all products in a specific category
139
- * const products = await productEntity.findMany({ category: 'electronics' });
140
- *
141
- * // Process the results
142
- * products.forEach(product => {
143
- * console.log(`${product.name}: $${product.price}`);
141
+ * const products = await productEntity.findMany({
142
+ * where: { and: [
143
+ * { column: 'category', value: 'electronics' },
144
+ * { column: 'price', operator: '<', value: 100 },
145
+ * ]},
146
+ * orderBy: [{ column: 'price', direction: 'asc' }],
144
147
  * });
145
148
  * ```
146
149
  */
147
- findMany(filters?: any): Promise<any[]>;
150
+ findMany(query?: EntityQuery<EC> | Record<string, any>): Promise<any[]>;
151
+ /**
152
+ * Retrieves one page of the entities that match a query
153
+ *
154
+ * Pages are cursor based: pass `null` (or nothing) for the first page, then the returned
155
+ * `nextCursor` for the next one; `nextCursor` is `null` after the last page. Pass the same
156
+ * query for every page of a sequence. `page.size` sets the rows per page (server default when
157
+ * omitted). Only tables can be paged: the server rejects a cursor on views and on the users table.
158
+ *
159
+ * @param {EntityQuery<EC>} query - The query to page through
160
+ * @param {string | null} [cursor] - The `nextCursor` of the previous page; `null` for the first
161
+ * @returns {Promise<EntityPage<EC>>} The page's rows and the next page's cursor
162
+ * @example
163
+ * ```ts
164
+ * const query = { where: { column: 'status', value: 'open' }, page: { size: 100 } };
165
+ * let cursor = null;
166
+ * do {
167
+ * const { rows, nextCursor } = await taskEntity.findPage(query, cursor);
168
+ * rows.forEach(processTask);
169
+ * cursor = nextCursor;
170
+ * } while (cursor);
171
+ * ```
172
+ */
173
+ findPage(query?: EntityQuery<EC>, cursor?: string | null): Promise<EntityPage<EC>>;
148
174
  /**
149
175
  * Retrieves which agents created and last changed an entity
150
176
  *
@@ -1 +1 @@
1
- {"version":3,"file":"Entity.d.ts","sourceRoot":"","sources":["../src/Entity.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Entity.d.ts","sourceRoot":"","sources":["../src/Entity.ts"],"names":[],"mappings":"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"}
package/dist/Entity.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { DataApiService } from "@blocksdiy/blocks-client-api";
2
+ import { isEntityQuery, toQueryOptions } from "./EntityQuery.js";
2
3
  const DATA_OPERATIONS_CHUNK_SIZE = 500;
3
4
  const arrayToChunks = (array, chunkSize) => {
4
5
  const chunks = [];
@@ -61,12 +62,14 @@ export class Entity {
61
62
  }
62
63
  }
63
64
  /**
64
- * Retrieves multiple entities that match the provided filters
65
+ * Retrieves the entities that match a query
65
66
  *
66
- * Fetches entities from the database and transforms them to the frontend format
67
- * with properly mapped property names.
67
+ * Pass an {@link EntityQuery}: `where` picks the rows, `orderBy` orders them, and `page.size`
68
+ * caps the result at one page. Without `page`, the server's default row limit applies — use
69
+ * {@link findPage} to read past it. Legacy key/value filters (`{ category: "electronics" }`)
70
+ * are still accepted and keep their meaning; new code should use a query.
68
71
  *
69
- * @param {any} [filters] - Optional filters to apply to the query
72
+ * @param {EntityQuery<EC> | Record<string, any>} [query] - The query (or legacy filters)
70
73
  * @returns {Promise<Array<EntityType<EC>>>} Array of matching entities
71
74
  * @example
72
75
  * ```ts
@@ -74,21 +77,55 @@ export class Entity {
74
77
  *
75
78
  * const productEntity = new Entity(ProductEntity);
76
79
  *
77
- * // Find all products in a specific category
78
- * const products = await productEntity.findMany({ category: 'electronics' });
79
- *
80
- * // Process the results
81
- * products.forEach(product => {
82
- * console.log(`${product.name}: $${product.price}`);
80
+ * const products = await productEntity.findMany({
81
+ * where: { and: [
82
+ * { column: 'category', value: 'electronics' },
83
+ * { column: 'price', operator: '<', value: 100 },
84
+ * ]},
85
+ * orderBy: [{ column: 'price', direction: 'asc' }],
83
86
  * });
84
87
  * ```
85
88
  */
86
- async findMany(filters) {
89
+ // The return type stays `any[]` as it always was: narrowing it could turn existing app code
90
+ // into type errors on its next compile.
91
+ async findMany(query) {
92
+ try {
93
+ const { rows } = isEntityQuery(query)
94
+ ? await this.dataApiService.queryTableDataV2(this.tableBlockId, toQueryOptions(query))
95
+ : await this.dataApiService.getTableDataV2(this.tableBlockId, query);
96
+ return rows;
97
+ }
98
+ catch (error) {
99
+ console.warn(error);
100
+ throw error;
101
+ }
102
+ }
103
+ /**
104
+ * Retrieves one page of the entities that match a query
105
+ *
106
+ * Pages are cursor based: pass `null` (or nothing) for the first page, then the returned
107
+ * `nextCursor` for the next one; `nextCursor` is `null` after the last page. Pass the same
108
+ * query for every page of a sequence. `page.size` sets the rows per page (server default when
109
+ * omitted). Only tables can be paged: the server rejects a cursor on views and on the users table.
110
+ *
111
+ * @param {EntityQuery<EC>} query - The query to page through
112
+ * @param {string | null} [cursor] - The `nextCursor` of the previous page; `null` for the first
113
+ * @returns {Promise<EntityPage<EC>>} The page's rows and the next page's cursor
114
+ * @example
115
+ * ```ts
116
+ * const query = { where: { column: 'status', value: 'open' }, page: { size: 100 } };
117
+ * let cursor = null;
118
+ * do {
119
+ * const { rows, nextCursor } = await taskEntity.findPage(query, cursor);
120
+ * rows.forEach(processTask);
121
+ * cursor = nextCursor;
122
+ * } while (cursor);
123
+ * ```
124
+ */
125
+ async findPage(query = {}, cursor = null) {
87
126
  try {
88
- const response = await this.dataApiService.getTableData(this.tableBlockId, filters);
89
- // Ensure we're working with an array
90
- const instances = Array.isArray(response) ? response : response ? [response] : [];
91
- return instances;
127
+ const { rows, nextCursor } = await this.dataApiService.queryTableDataV2(this.tableBlockId, toQueryOptions(query, cursor ?? ""));
128
+ return { rows: rows, nextCursor };
92
129
  }
93
130
  catch (error) {
94
131
  console.warn(error);
@@ -1,4 +1,5 @@
1
1
  import { QueryClient, QueryKey } from "@tanstack/react-query";
2
+ import type { EntityQuery } from "./EntityQuery.js";
2
3
  export declare const ENTITIES_QUERY_KEY = "entities";
3
4
  /**
4
5
  * Minimal shape of a server row required for cache reconciliation.
@@ -36,14 +37,34 @@ export declare const sameId: (a: unknown, b: unknown) => boolean;
36
37
  * is more trustworthy than an undecidable comparison).
37
38
  */
38
39
  export declare const isIncomingRowNewer: (existing: unknown, incoming: EntityCacheRow) => boolean;
40
+ export declare const entityPagesKey: (tableBlockId: string, query: unknown) => QueryKey;
39
41
  export declare const entityAttributionKey: (tableBlockId: string, rowId: string | number) => QueryKey;
40
42
  export declare const isAttributionQueryKey: (queryKey: QueryKey, tableBlockId: string) => boolean;
43
+ export declare const isPagedListQueryKey: (queryKey: QueryKey, tableBlockId: string) => boolean;
44
+ /** Any list of rows: a plain list or a paged one. */
41
45
  export declare const isListQueryKey: (queryKey: QueryKey, tableBlockId: string) => boolean;
42
46
  export declare const isUnfilteredListQueryKey: (queryKey: QueryKey, tableBlockId: string) => boolean;
47
+ /** Lists whose membership only the server can decide: filtered/queried lists and every paged list. */
43
48
  export declare const isFilteredListQueryKey: (queryKey: QueryKey, tableBlockId: string) => boolean;
44
49
  export declare const isOneQueryKey: (queryKey: QueryKey, tableBlockId: string) => boolean;
45
50
  /** Returns the id of a one-query keyed strictly by { id }, undefined for any other filter shape. */
46
51
  export declare const getOneQueryKeyId: (queryKey: QueryKey) => string | number | undefined;
52
+ /**
53
+ * The page param of a paged list's first page once its loaded pages were collapsed into one
54
+ * (see {@link collapsePagedListForRefetch}): re-read `size` rows starting at `cursor`.
55
+ */
56
+ export interface EntityCollapsedPageParam {
57
+ cursor: string | null;
58
+ size: number;
59
+ }
60
+ /** A paged list's page param: a cursor (`null` for the first page), or a collapsed first page. */
61
+ export type EntityPageParam = string | null | EntityCollapsedPageParam;
62
+ export declare const isCollapsedPageParam: (value: unknown) => value is EntityCollapsedPageParam;
63
+ /**
64
+ * Fetches one page of a paged list. A collapsed page param re-reads every row it covers in one
65
+ * request, keeping the query's `where` / `orderBy` but replacing its page size.
66
+ */
67
+ export declare const fetchEntityPagedListPage: <TPage>(findPage: (query: EntityQuery<any>, cursor: string | null) => Promise<TPage>, query: EntityQuery<any>, pageParam: EntityPageParam) => Promise<TPage>;
47
68
  /**
48
69
  * Writes canonical server rows into every cached query of the table.
49
70
  *
@@ -95,7 +116,9 @@ export declare const restoreEntityQueriesSnapshot: (queryClient: QueryClient, sn
95
116
  * snapshotted before the mutation cannot overwrite the rows we are about to write.
96
117
  *
97
118
  * Fetches of queries without data (initial loads) are left running: cancelling them
98
- * would strand the query in a non-fetching pending state.
119
+ * would strand the query in a non-fetching pending state. A cancelled "load more" of a
120
+ * paged list is not lost: the list is collapsed to re-read its loaded rows plus one more
121
+ * page, so the refetch that follows the write also delivers the page that was asked for.
99
122
  */
100
123
  export declare const prepareEntityCacheWrite: (queryClient: QueryClient, tableBlockId: string) => Promise<EntityWritePreparation>;
101
124
  /**
@@ -108,6 +131,7 @@ export declare const prepareEntityCacheWrite: (queryClient: QueryClient, tableBl
108
131
  *
109
132
  * Unfiltered lists and id-keyed one-queries are NOT invalidated - they were fully
110
133
  * reconciled from the server response, which is what saves the refetch round trips.
134
+ * Paged lists are collapsed before they are invalidated, so each refetches in one request.
111
135
  */
112
136
  export declare const invalidateEntityQueriesAfterWrite: (queryClient: QueryClient, tableBlockId: string, { staleKeys, filteredLists, nonIdOneQueries, deletedRowIds, }: {
113
137
  staleKeys?: QueryKey[];
@@ -1 +1 @@
1
- {"version":3,"file":"EntityCache.d.ts","sourceRoot":"","sources":["../src/EntityCache.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"EntityCache.d.ts","sourceRoot":"","sources":["../src/EntityCache.ts"],"names":[],"mappings":"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"}
@@ -2,6 +2,7 @@ import { hashKey } from "@tanstack/react-query";
2
2
  export const ENTITIES_QUERY_KEY = "entities";
3
3
  const ONE_SEGMENT = "one";
4
4
  const ATTRIBUTION_SEGMENT = "attribution";
5
+ const PAGES_SEGMENT = "pages";
5
6
  export const entityTableKey = (tableBlockId) => [ENTITIES_QUERY_KEY, tableBlockId];
6
7
  const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
7
8
  const isValidRow = (value) => isRecord(value) && (typeof value.id === "string" || typeof value.id === "number");
@@ -44,7 +45,16 @@ export const isIncomingRowNewer = (existing, incoming) => {
44
45
  * One queries: [ENTITIES_QUERY_KEY, tableBlockId, "one", filters] (length 4)
45
46
  * Attribution queries: [ENTITIES_QUERY_KEY, tableBlockId, "attribution", rowId] (length 4) — never
46
47
  * written to from rows (they hold no row), only invalidated on every write to the table.
48
+ * Paged list queries: [ENTITIES_QUERY_KEY, tableBlockId, "pages", query] (length 4) — infinite
49
+ * queries (`{ pages: [{ rows, nextCursor }], pageParams }`); maintained like filtered lists,
50
+ * and collapsed into one page before every refetch (see `collapsePagedListForRefetch`).
47
51
  */
52
+ export const entityPagesKey = (tableBlockId, query) => [
53
+ ENTITIES_QUERY_KEY,
54
+ tableBlockId,
55
+ PAGES_SEGMENT,
56
+ query,
57
+ ];
48
58
  export const entityAttributionKey = (tableBlockId, rowId) => [
49
59
  ENTITIES_QUERY_KEY,
50
60
  tableBlockId,
@@ -53,9 +63,13 @@ export const entityAttributionKey = (tableBlockId, rowId) => [
53
63
  ];
54
64
  export const isAttributionQueryKey = (queryKey, tableBlockId) => isTableKey(queryKey, tableBlockId) && queryKey.length === 4 && queryKey[2] === ATTRIBUTION_SEGMENT;
55
65
  const isTableKey = (queryKey, tableBlockId) => Array.isArray(queryKey) && queryKey[0] === ENTITIES_QUERY_KEY && queryKey[1] === tableBlockId;
56
- export const isListQueryKey = (queryKey, tableBlockId) => isTableKey(queryKey, tableBlockId) && queryKey.length === 3 && queryKey[2] !== ONE_SEGMENT;
57
- export const isUnfilteredListQueryKey = (queryKey, tableBlockId) => isListQueryKey(queryKey, tableBlockId) && queryKey[2] == null;
58
- export const isFilteredListQueryKey = (queryKey, tableBlockId) => isListQueryKey(queryKey, tableBlockId) && queryKey[2] != null;
66
+ const isPlainListQueryKey = (queryKey, tableBlockId) => isTableKey(queryKey, tableBlockId) && queryKey.length === 3 && queryKey[2] !== ONE_SEGMENT;
67
+ export const isPagedListQueryKey = (queryKey, tableBlockId) => isTableKey(queryKey, tableBlockId) && queryKey.length === 4 && queryKey[2] === PAGES_SEGMENT;
68
+ /** Any list of rows: a plain list or a paged one. */
69
+ export const isListQueryKey = (queryKey, tableBlockId) => isPlainListQueryKey(queryKey, tableBlockId) || isPagedListQueryKey(queryKey, tableBlockId);
70
+ export const isUnfilteredListQueryKey = (queryKey, tableBlockId) => isPlainListQueryKey(queryKey, tableBlockId) && queryKey[2] == null;
71
+ /** Lists whose membership only the server can decide: filtered/queried lists and every paged list. */
72
+ export const isFilteredListQueryKey = (queryKey, tableBlockId) => isListQueryKey(queryKey, tableBlockId) && !isUnfilteredListQueryKey(queryKey, tableBlockId);
59
73
  export const isOneQueryKey = (queryKey, tableBlockId) => isTableKey(queryKey, tableBlockId) && queryKey.length === 4 && queryKey[2] === ONE_SEGMENT;
60
74
  /** Returns the id of a one-query keyed strictly by { id }, undefined for any other filter shape. */
61
75
  export const getOneQueryKeyId = (queryKey) => {
@@ -70,12 +84,85 @@ export const getOneQueryKeyId = (queryKey) => {
70
84
  const id = filters.id;
71
85
  return typeof id === "string" || typeof id === "number" ? id : undefined;
72
86
  };
87
+ const isPagedListData = (data) => typeof data === "object" &&
88
+ data !== null &&
89
+ Array.isArray(data.pages) &&
90
+ data.pages.every((page) => Array.isArray(page?.rows));
91
+ export const isCollapsedPageParam = (value) => isRecord(value) && typeof value.size === "number" && (value.cursor === null || typeof value.cursor === "string");
92
+ /**
93
+ * Fetches one page of a paged list. A collapsed page param re-reads every row it covers in one
94
+ * request, keeping the query's `where` / `orderBy` but replacing its page size.
95
+ */
96
+ export const fetchEntityPagedListPage = (findPage, query, pageParam) => isCollapsedPageParam(pageParam)
97
+ ? findPage({ ...query, page: { size: pageParam.size } }, pageParam.cursor)
98
+ : findPage(query, pageParam);
99
+ /** The `page.size` of a paged list's query key, undefined when it has none. */
100
+ const pagedListPageSize = (queryKey) => {
101
+ const query = queryKey[3];
102
+ const size = isRecord(query) && isRecord(query.page) ? query.page.size : undefined;
103
+ return typeof size === "number" && size > 0 ? size : undefined;
104
+ };
105
+ /**
106
+ * Folds a paged list's loaded pages into a single page whose param re-reads all of their rows
107
+ * (plus `extraRows`) in one request. React Query refetches an infinite query page by page,
108
+ * one request after another from `pageParams[0]`, as many pages as it holds — so a list
109
+ * paged 20 deep would cost 20 sequential requests on every refetch. Collapsed, the refetch is
110
+ * one request, and the rows, their order and the next cursor stay exactly as rendered.
111
+ *
112
+ * `extraRows` grows the re-read past what is loaded: a "load more" cancelled by a cache write
113
+ * is folded into the refetch instead of being lost.
114
+ */
115
+ const collapsePagedListForRefetch = (queryClient, queryKey, { extraRows = 0 } = {}) => {
116
+ const pageSize = pagedListPageSize(queryKey);
117
+ if (pageSize === undefined) {
118
+ return;
119
+ }
120
+ queryClient.setQueryData(queryKey, (oldData) => {
121
+ if (!isPagedListData(oldData) || oldData.pages.length === 0) {
122
+ return undefined;
123
+ }
124
+ if (oldData.pages.length === 1 && extraRows === 0) {
125
+ return undefined;
126
+ }
127
+ const firstParam = oldData.pageParams[0];
128
+ const cursor = isCollapsedPageParam(firstParam)
129
+ ? firstParam.cursor
130
+ : typeof firstParam === "string"
131
+ ? firstParam
132
+ : null;
133
+ const rows = oldData.pages.flatMap((page) => page.rows);
134
+ const collapsedParam = {
135
+ cursor,
136
+ size: Math.max(rows.length, pageSize) + extraRows,
137
+ };
138
+ return {
139
+ pages: [{ rows, nextCursor: oldData.pages[oldData.pages.length - 1].nextCursor }],
140
+ pageParams: [collapsedParam],
141
+ };
142
+ });
143
+ };
144
+ /**
145
+ * Applies a rows transform to list data: a plain rows array, or each page of a paged list.
146
+ * `undefined` from the transform (and for any other data shape) leaves the cache untouched.
147
+ */
73
148
  const updateListData = (oldData, transform) => {
74
- if (!Array.isArray(oldData)) {
75
- // Bail out (undefined keeps the cache untouched) instead of corrupting non-list data.
76
- return undefined;
149
+ if (Array.isArray(oldData)) {
150
+ return transform(oldData);
77
151
  }
78
- return transform(oldData);
152
+ if (isPagedListData(oldData)) {
153
+ let changed = false;
154
+ const pages = oldData.pages.map((page) => {
155
+ const rows = transform(page.rows);
156
+ if (rows === undefined) {
157
+ return page;
158
+ }
159
+ changed = true;
160
+ return { ...page, rows };
161
+ });
162
+ return changed ? { ...oldData, pages } : undefined;
163
+ }
164
+ // Bail out instead of corrupting non-list data.
165
+ return undefined;
79
166
  };
80
167
  /**
81
168
  * Writes canonical server rows into every cached query of the table.
@@ -239,21 +326,31 @@ export const restoreEntityQueriesSnapshot = (queryClient, snapshot) => {
239
326
  * snapshotted before the mutation cannot overwrite the rows we are about to write.
240
327
  *
241
328
  * Fetches of queries without data (initial loads) are left running: cancelling them
242
- * would strand the query in a non-fetching pending state.
329
+ * would strand the query in a non-fetching pending state. A cancelled "load more" of a
330
+ * paged list is not lost: the list is collapsed to re-read its loaded rows plus one more
331
+ * page, so the refetch that follows the write also delivers the page that was asked for.
243
332
  */
244
333
  export const prepareEntityCacheWrite = async (queryClient, tableBlockId) => {
245
334
  const tableKey = entityTableKey(tableBlockId);
246
- const staleKeys = queryClient
247
- .getQueryCache()
248
- .findAll({
335
+ const staleQueries = queryClient.getQueryCache().findAll({
249
336
  queryKey: tableKey,
250
337
  predicate: (query) => query.state.fetchStatus === "fetching" || query.state.isInvalidated,
251
- })
338
+ });
339
+ const staleKeys = staleQueries.map((query) => query.queryKey);
340
+ // Read before cancelling: the cancel reverts the query's state, fetch metadata included.
341
+ const loadingMoreKeys = staleQueries
342
+ .filter((query) => query.state.fetchStatus === "fetching" &&
343
+ query.state.data !== undefined &&
344
+ query.state.fetchMeta?.fetchMore?.direction === "forward" &&
345
+ isPagedListQueryKey(query.queryKey, tableBlockId))
252
346
  .map((query) => query.queryKey);
253
347
  await queryClient.cancelQueries({
254
348
  queryKey: tableKey,
255
349
  predicate: (query) => query.state.data !== undefined,
256
350
  });
351
+ loadingMoreKeys.forEach((queryKey) => {
352
+ collapsePagedListForRefetch(queryClient, queryKey, { extraRows: pagedListPageSize(queryKey) ?? 0 });
353
+ });
257
354
  return { staleKeys };
258
355
  };
259
356
  /**
@@ -266,10 +363,11 @@ export const prepareEntityCacheWrite = async (queryClient, tableBlockId) => {
266
363
  *
267
364
  * Unfiltered lists and id-keyed one-queries are NOT invalidated - they were fully
268
365
  * reconciled from the server response, which is what saves the refetch round trips.
366
+ * Paged lists are collapsed before they are invalidated, so each refetches in one request.
269
367
  */
270
368
  export const invalidateEntityQueriesAfterWrite = (queryClient, tableBlockId, { staleKeys = [], filteredLists = false, nonIdOneQueries = false, deletedRowIds, }) => {
271
369
  const staleHashes = new Set(staleKeys.map((queryKey) => hashKey(queryKey)));
272
- void queryClient.invalidateQueries({
370
+ const toInvalidate = queryClient.getQueryCache().findAll({
273
371
  queryKey: entityTableKey(tableBlockId),
274
372
  predicate: (query) => {
275
373
  if (staleHashes.has(hashKey(query.queryKey))) {
@@ -295,9 +393,30 @@ export const invalidateEntityQueriesAfterWrite = (queryClient, tableBlockId, { s
295
393
  return false;
296
394
  },
297
395
  });
396
+ if (toInvalidate.length === 0) {
397
+ return;
398
+ }
399
+ // Collapse first: the predicate above reads query state that the collapse rewrites.
400
+ toInvalidate.forEach((query) => {
401
+ if (isPagedListQueryKey(query.queryKey, tableBlockId)) {
402
+ collapsePagedListForRefetch(queryClient, query.queryKey);
403
+ }
404
+ });
405
+ const invalidateHashes = new Set(toInvalidate.map((query) => query.queryHash));
406
+ void queryClient.invalidateQueries({
407
+ queryKey: entityTableKey(tableBlockId),
408
+ predicate: (query) => invalidateHashes.has(query.queryHash),
409
+ });
298
410
  };
299
411
  /** Full-table invalidation - the pre-optimistic behavior, kept as the safety fallback. */
300
412
  export const invalidateEntityTable = (queryClient, tableBlockId) => {
413
+ queryClient
414
+ .getQueryCache()
415
+ .findAll({
416
+ queryKey: entityTableKey(tableBlockId),
417
+ predicate: (query) => isPagedListQueryKey(query.queryKey, tableBlockId),
418
+ })
419
+ .forEach((query) => collapsePagedListForRefetch(queryClient, query.queryKey));
301
420
  void queryClient.invalidateQueries({ queryKey: entityTableKey(tableBlockId) });
302
421
  };
303
422
  /**
@@ -0,0 +1,66 @@
1
+ import type { EntityConfig, EntityType } from "./Entity.js";
2
+ /** A column of the entity: one of its fields, system fields included (`id`, `createdAt`, ...). */
3
+ export type EntityColumn<E extends EntityConfig> = Extract<keyof EntityType<E>, string>;
4
+ export type EntityWhereOperator = "=" | "!=" | ">" | ">=" | "<" | "<=" | "in" | "not in" | "is null" | "is not null";
5
+ /**
6
+ * A where clause: one condition, or `and` / `or` of nested clauses. `operator` defaults to `"="`;
7
+ * `in` / `not in` take an array `value`; `is null` / `is not null` take no value. `not: true`
8
+ * negates the clause. `expression` is a server-validated SQL-like condition over column names,
9
+ * for comparisons a plain condition cannot express.
10
+ */
11
+ export type EntityWhereClause<E extends EntityConfig = EntityConfig> = {
12
+ column: EntityColumn<E>;
13
+ operator?: EntityWhereOperator;
14
+ value?: unknown;
15
+ not?: boolean;
16
+ } | {
17
+ and: EntityWhereClause<E>[];
18
+ not?: boolean;
19
+ } | {
20
+ or: EntityWhereClause<E>[];
21
+ not?: boolean;
22
+ } | {
23
+ expression: string;
24
+ not?: boolean;
25
+ };
26
+ export interface EntityOrderBy<E extends EntityConfig = EntityConfig> {
27
+ column: EntityColumn<E>;
28
+ direction?: "asc" | "desc";
29
+ }
30
+ /**
31
+ * Query for `findMany` / `findPage` / `useEntityGetAll`.
32
+ *
33
+ * - `where`: which rows (omit for all rows).
34
+ * - `orderBy`: row order; `id` is always the final tie-breaker, so the order is stable.
35
+ * - `page.size`: rows per page. With `useEntityGetAll` it turns on paging (`fetchNextPage`);
36
+ * with `findMany` it caps the result at the first page.
37
+ */
38
+ export interface EntityQuery<E extends EntityConfig = EntityConfig> {
39
+ where?: EntityWhereClause<E>;
40
+ orderBy?: EntityOrderBy<E>[];
41
+ page?: {
42
+ size: number;
43
+ };
44
+ }
45
+ /** One page of rows and the cursor of the next page (`null` after the last page). */
46
+ export interface EntityPage<E extends EntityConfig = EntityConfig> {
47
+ rows: EntityType<E>[];
48
+ nextCursor: string | null;
49
+ }
50
+ /**
51
+ * Whether an argument is an {@link EntityQuery} rather than legacy key/value filters.
52
+ *
53
+ * Legacy filters (`{ status: "todo" }`, `{ id: [1, 2] }`) are equality / IN matches on column
54
+ * values, which are primitives or arrays of primitives. A query uses only the keys `where`,
55
+ * `orderBy` and `page`, each holding a structure no legacy filter value can have (a clause
56
+ * object, an array of `{ column }` objects, `{ size }`), so every existing call keeps its
57
+ * meaning.
58
+ *
59
+ * A query key may also be left empty (`undefined`, `null`, or `orderBy: []`) as long as at least
60
+ * one other key holds a real query structure — otherwise a conditionally built query would be
61
+ * misread as filters on columns named `where` / `orderBy` / `page` and return the whole table.
62
+ */
63
+ export declare const isEntityQuery: (value: unknown) => value is EntityQuery<any>;
64
+ /** The data-service query options for an {@link EntityQuery}. */
65
+ export declare const toQueryOptions: (query: EntityQuery<any>, cursor?: string) => Record<string, unknown>;
66
+ //# sourceMappingURL=EntityQuery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EntityQuery.d.ts","sourceRoot":"","sources":["../src/EntityQuery.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAEzD,kGAAkG;AAClG,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS,YAAY,IAAI,OAAO,CAAC,MAAM,UAAU,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;AAExF,MAAM,MAAM,mBAAmB,GAAG,GAAG,GAAG,IAAI,GAAG,GAAG,GAAG,IAAI,GAAG,GAAG,GAAG,IAAI,GAAG,IAAI,GAAG,QAAQ,GAAG,SAAS,GAAG,aAAa,CAAC;AAErH;;;;;GAKG;AACH,MAAM,MAAM,iBAAiB,CAAC,CAAC,SAAS,YAAY,GAAG,YAAY,IAC/D;IAAE,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC;IAAC,QAAQ,CAAC,EAAE,mBAAmB,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,GAAG,CAAC,EAAE,OAAO,CAAA;CAAE,GAC3F;IAAE,GAAG,EAAE,iBAAiB,CAAC,CAAC,CAAC,EAAE,CAAC;IAAC,GAAG,CAAC,EAAE,OAAO,CAAA;CAAE,GAC9C;IAAE,EAAE,EAAE,iBAAiB,CAAC,CAAC,CAAC,EAAE,CAAC;IAAC,GAAG,CAAC,EAAE,OAAO,CAAA;CAAE,GAC7C;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAE1C,MAAM,WAAW,aAAa,CAAC,CAAC,SAAS,YAAY,GAAG,YAAY;IAClE,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC;IACxB,SAAS,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;CAC5B;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,WAAW,CAAC,CAAC,SAAS,YAAY,GAAG,YAAY;IAChE,KAAK,CAAC,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAC;IAC7B,OAAO,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC;IAC7B,IAAI,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CACzB;AAED,qFAAqF;AACrF,MAAM,WAAW,UAAU,CAAC,CAAC,SAAS,YAAY,GAAG,YAAY;IAC/D,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;IACtB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAuBD;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,aAAa,GAAI,OAAO,OAAO,KAAG,KAAK,IAAI,WAAW,CAAC,GAAG,CAatE,CAAC;AAEF,iEAAiE;AACjE,eAAO,MAAM,cAAc,GAAI,OAAO,WAAW,CAAC,GAAG,CAAC,EAAE,SAAS,MAAM,KAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAK9F,CAAC"}
@@ -0,0 +1,46 @@
1
+ const isPlainObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
2
+ const QUERY_KEY_CHECKS = {
3
+ where: (value) => isPlainObject(value) &&
4
+ (typeof value.column === "string" ||
5
+ typeof value.expression === "string" ||
6
+ Array.isArray(value.and) ||
7
+ Array.isArray(value.or)),
8
+ orderBy: (value) => Array.isArray(value) &&
9
+ value.length > 0 &&
10
+ value.every((item) => isPlainObject(item) && typeof item.column === "string"),
11
+ page: (value) => isPlainObject(value) && typeof value.size === "number",
12
+ };
13
+ /** A query key left empty by a conditional (`where: status ? {...} : undefined`, `orderBy: []`). */
14
+ const isEmptyQueryValue = (key, value) => value === undefined || value === null || (key === "orderBy" && Array.isArray(value) && value.length === 0);
15
+ /**
16
+ * Whether an argument is an {@link EntityQuery} rather than legacy key/value filters.
17
+ *
18
+ * Legacy filters (`{ status: "todo" }`, `{ id: [1, 2] }`) are equality / IN matches on column
19
+ * values, which are primitives or arrays of primitives. A query uses only the keys `where`,
20
+ * `orderBy` and `page`, each holding a structure no legacy filter value can have (a clause
21
+ * object, an array of `{ column }` objects, `{ size }`), so every existing call keeps its
22
+ * meaning.
23
+ *
24
+ * A query key may also be left empty (`undefined`, `null`, or `orderBy: []`) as long as at least
25
+ * one other key holds a real query structure — otherwise a conditionally built query would be
26
+ * misread as filters on columns named `where` / `orderBy` / `page` and return the whole table.
27
+ */
28
+ export const isEntityQuery = (value) => {
29
+ if (!isPlainObject(value)) {
30
+ return false;
31
+ }
32
+ const keys = Object.keys(value);
33
+ if (!keys.every((key) => key in QUERY_KEY_CHECKS)) {
34
+ return false;
35
+ }
36
+ const queryKeys = keys;
37
+ return (queryKeys.some((key) => QUERY_KEY_CHECKS[key](value[key])) &&
38
+ queryKeys.every((key) => QUERY_KEY_CHECKS[key](value[key]) || isEmptyQueryValue(key, value[key])));
39
+ };
40
+ /** The data-service query options for an {@link EntityQuery}. */
41
+ export const toQueryOptions = (query, cursor) => ({
42
+ ...(query.where ? { where: query.where } : {}),
43
+ ...(query.orderBy?.length ? { orderBy: query.orderBy } : {}),
44
+ ...(query.page ? { limit: query.page.size } : {}),
45
+ ...(cursor !== undefined ? { cursor } : {}),
46
+ });
@@ -3,6 +3,7 @@ import type { AgentConfig } from "./Agent.js";
3
3
  import type { AgentChatConfig } from "./AgentChat.js";
4
4
  import { ClientSdk, UpdateUserOptions } from "./ClientSdk.js";
5
5
  import type { EntityAttribution, EntityConfig, EntityType, EntityTypeOnlyMutable } from "./Entity.js";
6
+ import { type EntityQuery } from "./EntityQuery.js";
6
7
  import type { Integration } from "./Integration.js";
7
8
  import type { PageConfig } from "./Page.js";
8
9
  export declare class ReactClientSdk extends ClientSdk {
@@ -67,24 +68,23 @@ export declare const ClientProvider: ({ client, children, themeMode, setThemeMod
67
68
  */
68
69
  export declare const useClient: () => ReactClientSdk;
69
70
  /**
70
- * Hook to fetch all entities of a specific type
71
+ * Hook to fetch the entities that match a query
71
72
  *
72
- * Entities represent data objects stored in tables with standard CRUD operations.
73
- * This hook provides a React Query-powered way to fetch multiple entities.
74
- *
75
- * EntityConfig properties:
76
- * - tableBlockId: Unique identifier for the table
77
- * - instanceType: TypeScript type defining the entity's structure
73
+ * Pass an {@link EntityQuery} as the 2nd argument: `where` picks the rows, `orderBy` orders
74
+ * them, and `page.size` turns on paging — `data` then holds every page loaded so far and
75
+ * `fetchNextPage()` loads the next one. Without `page`, one request returns up to the server's
76
+ * default row limit. Legacy key/value filters (`{ status: "todo" }`) are still accepted and keep
77
+ * their meaning; new code should use a query.
78
78
  *
79
79
  * @template E - Entity configuration type
80
80
  * @param {E} entityConfig - Configuration for the entity type
81
- * @param {any} [filters] - Optional filters to apply to the query
81
+ * @param {EntityQuery<E> | Record<string, any>} [query] - The query (or legacy filters)
82
82
  * @param {Object} [queryOptions] - Optional React Query configuration options
83
83
  * @param {boolean} [queryOptions.enabled] - Whether the query should automatically execute
84
- * @param {EntityType<E>[]} [queryOptions.initialData] - Initial data to use for the query
84
+ * @param {EntityType<E>[]} [queryOptions.initialData] - Initial data to use for the query (not used when paging)
85
85
  * @param {EntityType<E>[]} [queryOptions.placeholderData] - Placeholder data to use while loading
86
86
  * @returns {Object} Query result with data, loading state, and error
87
- * @returns {EntityType<E>[] | undefined} returns.data - The fetched entities
87
+ * @returns {EntityType<E>[] | undefined} returns.data - The fetched entities (every loaded page, in order, when paging)
88
88
  * @returns {boolean} returns.isLoading - Whether the query is loading
89
89
  * @returns {Error | null} returns.error - Any error that occurred
90
90
  * @returns {Function} returns.refetch - Intentional no-op kept for API compatibility; returns the current state without fetching. Data is kept fresh automatically (mutation cache writes + websocket live sync), so manual refetching is unsupported.
@@ -93,23 +93,32 @@ export declare const useClient: () => ReactClientSdk;
93
93
  * @returns {boolean} returns.isFetching - Whether the query is currently fetching
94
94
  * @returns {boolean} returns.isSuccess - Whether the query was successful
95
95
  * @returns {string} returns.status - Current status of the query: 'pending', 'error', or 'success'
96
+ * @returns {boolean} returns.hasNextPage - Whether another page exists (always false without `page`)
97
+ * @returns {Function} returns.fetchNextPage - Loads the next page; a no-op without `page`, while one is loading, or after the last page
98
+ * @returns {boolean} returns.isFetchingNextPage - Whether the next page is loading
96
99
  * @example
97
100
  * ```tsx
98
- * import { ItemEntity } from '@/product-types';
101
+ * import { TaskEntity } from '@/product-types';
99
102
  *
100
- * function ItemsList() {
101
- * const { data: items, isLoading } = useEntityGetAll(ItemEntity);
103
+ * function OpenTasks() {
104
+ * const { data: tasks, hasNextPage, fetchNextPage, isFetchingNextPage } = useEntityGetAll(TaskEntity, {
105
+ * where: { column: 'status', operator: '!=', value: 'done' },
106
+ * orderBy: [{ column: 'createdAt', direction: 'desc' }],
107
+ * page: { size: 50 },
108
+ * });
102
109
  *
103
- * if (isLoading) return <div>Loading...</div>;
104
110
  * return (
105
- * <ul>
106
- * {items?.map(item => <li key={item.id}>{item.name}</li>)}
107
- * </ul>
111
+ * <>
112
+ * <ul>{tasks?.map(task => <li key={task.id}>{task.title}</li>)}</ul>
113
+ * {hasNextPage && (
114
+ * <button onClick={fetchNextPage} disabled={isFetchingNextPage}>Load more</button>
115
+ * )}
116
+ * </>
108
117
  * );
109
118
  * }
110
119
  * ```
111
120
  */
112
- export declare const useEntityGetAll: <E extends EntityConfig>(entityConfig: E, filters?: any, queryOptions?: {
121
+ export declare const useEntityGetAll: <E extends EntityConfig>(entityConfig: E, query?: EntityQuery<E> | Record<string, any>, queryOptions?: {
113
122
  enabled?: boolean;
114
123
  initialData?: EntityType<E>[];
115
124
  placeholderData?: EntityType<E>[];
@@ -123,6 +132,9 @@ export declare const useEntityGetAll: <E extends EntityConfig>(entityConfig: E,
123
132
  isFetching: boolean;
124
133
  isSuccess: boolean;
125
134
  status: "pending" | "error" | "success";
135
+ hasNextPage: boolean;
136
+ fetchNextPage: () => void;
137
+ isFetchingNextPage: boolean;
126
138
  };
127
139
  /**
128
140
  * Hook to fetch a single entity by filters
@@ -1 +1 @@
1
- {"version":3,"file":"ReactClientSdk.d.ts","sourceRoot":"","sources":["../src/ReactClientSdk.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ReactClientSdk.d.ts","sourceRoot":"","sources":["../src/ReactClientSdk.tsx"],"names":[],"mappings":"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"}
@@ -3,12 +3,13 @@ import { FatalAppError } from "@blocksdiy/blocks-client-api/errors";
3
3
  import { useWebsockets, useWebsocketsAppSubscribe } from "@blocksdiy/blocks-client-api/websocketService";
4
4
  import { websocketsService } from "@blocksdiy/blocks-client-api/websocketService";
5
5
  import { useAiStreamChunks } from "@blocksdiy/react-common/useAiStreamChunks";
6
- import { QueryClient, QueryClientProvider, useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
6
+ import { QueryClient, QueryClientProvider, useInfiniteQuery, useMutation, useQuery, useQueryClient, } from "@tanstack/react-query";
7
7
  import { createContext, useCallback, useContext, useEffect, useMemo, useState } from "react";
8
8
  import { agentRefOf, isBlockId, matchesAgentRef } from "./AgentRef.js";
9
9
  import { ClientSdk } from "./ClientSdk.js";
10
- import { applyEntityCreateResult, applyEntityDeleteResult, applyEntityRowPatch, applyEntityRowsDeleted, beginEntityOptimisticWrite, ENTITIES_QUERY_KEY, entityAttributionKey, rollbackEntityOptimisticWrite, } from "./EntityCache.js";
10
+ import { applyEntityCreateResult, applyEntityDeleteResult, applyEntityRowPatch, applyEntityRowsDeleted, beginEntityOptimisticWrite, ENTITIES_QUERY_KEY, entityAttributionKey, entityPagesKey, fetchEntityPagedListPage, rollbackEntityOptimisticWrite, } from "./EntityCache.js";
11
11
  import { createEntityLiveSync } from "./EntityLiveSync.js";
12
+ import { isEntityQuery } from "./EntityQuery.js";
12
13
  export class ReactClientSdk extends ClientSdk {
13
14
  }
14
15
  const CURRENT_USER_QUERY_KEY = "currentUser";
@@ -246,24 +247,23 @@ export const useClient = () => {
246
247
  return client;
247
248
  };
248
249
  /**
249
- * Hook to fetch all entities of a specific type
250
+ * Hook to fetch the entities that match a query
250
251
  *
251
- * Entities represent data objects stored in tables with standard CRUD operations.
252
- * This hook provides a React Query-powered way to fetch multiple entities.
253
- *
254
- * EntityConfig properties:
255
- * - tableBlockId: Unique identifier for the table
256
- * - instanceType: TypeScript type defining the entity's structure
252
+ * Pass an {@link EntityQuery} as the 2nd argument: `where` picks the rows, `orderBy` orders
253
+ * them, and `page.size` turns on paging — `data` then holds every page loaded so far and
254
+ * `fetchNextPage()` loads the next one. Without `page`, one request returns up to the server's
255
+ * default row limit. Legacy key/value filters (`{ status: "todo" }`) are still accepted and keep
256
+ * their meaning; new code should use a query.
257
257
  *
258
258
  * @template E - Entity configuration type
259
259
  * @param {E} entityConfig - Configuration for the entity type
260
- * @param {any} [filters] - Optional filters to apply to the query
260
+ * @param {EntityQuery<E> | Record<string, any>} [query] - The query (or legacy filters)
261
261
  * @param {Object} [queryOptions] - Optional React Query configuration options
262
262
  * @param {boolean} [queryOptions.enabled] - Whether the query should automatically execute
263
- * @param {EntityType<E>[]} [queryOptions.initialData] - Initial data to use for the query
263
+ * @param {EntityType<E>[]} [queryOptions.initialData] - Initial data to use for the query (not used when paging)
264
264
  * @param {EntityType<E>[]} [queryOptions.placeholderData] - Placeholder data to use while loading
265
265
  * @returns {Object} Query result with data, loading state, and error
266
- * @returns {EntityType<E>[] | undefined} returns.data - The fetched entities
266
+ * @returns {EntityType<E>[] | undefined} returns.data - The fetched entities (every loaded page, in order, when paging)
267
267
  * @returns {boolean} returns.isLoading - Whether the query is loading
268
268
  * @returns {Error | null} returns.error - Any error that occurred
269
269
  * @returns {Function} returns.refetch - Intentional no-op kept for API compatibility; returns the current state without fetching. Data is kept fresh automatically (mutation cache writes + websocket live sync), so manual refetching is unsupported.
@@ -272,32 +272,66 @@ export const useClient = () => {
272
272
  * @returns {boolean} returns.isFetching - Whether the query is currently fetching
273
273
  * @returns {boolean} returns.isSuccess - Whether the query was successful
274
274
  * @returns {string} returns.status - Current status of the query: 'pending', 'error', or 'success'
275
+ * @returns {boolean} returns.hasNextPage - Whether another page exists (always false without `page`)
276
+ * @returns {Function} returns.fetchNextPage - Loads the next page; a no-op without `page`, while one is loading, or after the last page
277
+ * @returns {boolean} returns.isFetchingNextPage - Whether the next page is loading
275
278
  * @example
276
279
  * ```tsx
277
- * import { ItemEntity } from '@/product-types';
280
+ * import { TaskEntity } from '@/product-types';
278
281
  *
279
- * function ItemsList() {
280
- * const { data: items, isLoading } = useEntityGetAll(ItemEntity);
282
+ * function OpenTasks() {
283
+ * const { data: tasks, hasNextPage, fetchNextPage, isFetchingNextPage } = useEntityGetAll(TaskEntity, {
284
+ * where: { column: 'status', operator: '!=', value: 'done' },
285
+ * orderBy: [{ column: 'createdAt', direction: 'desc' }],
286
+ * page: { size: 50 },
287
+ * });
281
288
  *
282
- * if (isLoading) return <div>Loading...</div>;
283
289
  * return (
284
- * <ul>
285
- * {items?.map(item => <li key={item.id}>{item.name}</li>)}
286
- * </ul>
290
+ * <>
291
+ * <ul>{tasks?.map(task => <li key={task.id}>{task.title}</li>)}</ul>
292
+ * {hasNextPage && (
293
+ * <button onClick={fetchNextPage} disabled={isFetchingNextPage}>Load more</button>
294
+ * )}
295
+ * </>
287
296
  * );
288
297
  * }
289
298
  * ```
290
299
  */
291
- export const useEntityGetAll = (entityConfig, filters, queryOptions = {}) => {
292
- const { enabled, initialData, placeholderData } = queryOptions;
300
+ export const useEntityGetAll = (entityConfig, query, queryOptions = {}) => {
301
+ const { enabled = true, initialData, placeholderData } = queryOptions;
293
302
  const client = useClient();
294
- const { data, isLoading, error, isError, isFetched, isFetching, isSuccess, status } = useQuery({
295
- queryKey: [ENTITIES_QUERY_KEY, entityConfig.tableBlockId, filters],
296
- queryFn: () => client.entity(entityConfig).findMany(filters),
297
- enabled,
298
- initialData,
303
+ const pagedQuery = isEntityQuery(query) && query.page ? query : undefined;
304
+ // Both hooks are always called (rules of hooks); exactly one is enabled. The plain list keeps
305
+ // the key every existing call has always used, so its cache entry and live sync are unchanged.
306
+ const list = useQuery({
307
+ queryKey: [ENTITIES_QUERY_KEY, entityConfig.tableBlockId, query],
308
+ queryFn: () => client.entity(entityConfig).findMany(query),
309
+ enabled: enabled && !pagedQuery,
310
+ initialData: pagedQuery ? undefined : initialData,
299
311
  placeholderData,
300
312
  });
313
+ const pages = useInfiniteQuery({
314
+ queryKey: entityPagesKey(entityConfig.tableBlockId, pagedQuery ?? null),
315
+ // A collapsed first page re-reads every loaded row in one request (see EntityCache).
316
+ queryFn: ({ pageParam }) => fetchEntityPagedListPage((pageQuery, cursor) => client.entity(entityConfig).findPage(pageQuery, cursor), pagedQuery ?? {}, pageParam),
317
+ initialPageParam: null,
318
+ getNextPageParam: (lastPage) => lastPage.nextCursor ?? undefined,
319
+ enabled: enabled && !!pagedQuery,
320
+ placeholderData: placeholderData
321
+ ? { pages: [{ rows: placeholderData, nextCursor: null }], pageParams: [null] }
322
+ : undefined,
323
+ });
324
+ const pagedData = useMemo(() => pages.data?.pages.flatMap((page) => page.rows), [pages.data]);
325
+ const active = pagedQuery ? pages : list;
326
+ const data = (pagedQuery ? pagedData : list.data);
327
+ const { isLoading, error, isError, isFetched, isFetching, isSuccess, status } = active;
328
+ const hasNextPage = !!pagedQuery && pages.hasNextPage;
329
+ const { fetchNextPage: fetchNextPageQuery, isFetchingNextPage } = pages;
330
+ const fetchNextPage = useCallback(() => {
331
+ if (hasNextPage && !isFetchingNextPage) {
332
+ void fetchNextPageQuery();
333
+ }
334
+ }, [hasNextPage, isFetchingNextPage, fetchNextPageQuery]);
301
335
  return {
302
336
  data,
303
337
  isLoading,
@@ -310,6 +344,9 @@ export const useEntityGetAll = (entityConfig, filters, queryOptions = {}) => {
310
344
  isFetching,
311
345
  isSuccess,
312
346
  status,
347
+ hasNextPage,
348
+ fetchNextPage,
349
+ isFetchingNextPage: !!pagedQuery && isFetchingNextPage,
313
350
  };
314
351
  };
315
352
  /**
package/dist/index.d.ts CHANGED
@@ -3,6 +3,7 @@ export * from "./Agent.js";
3
3
  export * from "./AgentChat.js";
4
4
  export * from "./ClientSdk.js";
5
5
  export * from "./Entity.js";
6
+ export * from "./EntityQuery.js";
6
7
  export * from "./Integration.js";
7
8
  export * from "./Page.js";
8
9
  export * from "./ReactClientSdk";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC;AACzB,cAAc,eAAe,CAAC;AAC9B,cAAc,QAAQ,CAAC;AACvB,cAAc,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC;AACzB,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,QAAQ,CAAC;AACvB,cAAc,kBAAkB,CAAC"}
package/dist/index.js CHANGED
@@ -3,6 +3,7 @@ export * from "./Agent.js";
3
3
  export * from "./AgentChat.js";
4
4
  export * from "./ClientSdk.js";
5
5
  export * from "./Entity.js";
6
+ export * from "./EntityQuery.js";
6
7
  export * from "./Integration.js";
7
8
  export * from "./Page.js";
8
9
  export * from "./ReactClientSdk";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blocksdiy/blocks-client-sdk",
3
- "version": "1.18.2",
3
+ "version": "1.18.3",
4
4
  "type": "module",
5
5
  "description": "Blocks client sdk",
6
6
  "keywords": [],
@@ -47,8 +47,8 @@
47
47
  },
48
48
  "dependencies": {
49
49
  "@tanstack/react-query": "^5.101.0",
50
- "@blocksdiy/blocks-client-api": "1.5.0",
51
- "@blocksdiy/react-common": "1.50.0"
50
+ "@blocksdiy/blocks-client-api": "1.25.1",
51
+ "@blocksdiy/react-common": "1.50.1"
52
52
  },
53
53
  "devDependencies": {
54
54
  "tsc-alias": "^1.8.10",