@objectstack/client-react 3.3.0 → 4.0.0
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/.turbo/turbo-build.log +10 -10
- package/CHANGELOG.md +18 -0
- package/dist/index.d.mts +34 -12
- package/dist/index.d.ts +34 -12
- package/dist/index.js +34 -14
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +34 -14
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -5
- package/src/data-hooks.tsx +74 -35
- package/tsconfig.json +2 -1
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
> @objectstack/client-react@
|
|
2
|
+
> @objectstack/client-react@4.0.0 build /home/runner/work/spec/spec/packages/client-react
|
|
3
3
|
> tsup src/index.tsx --config ../../tsup.config.ts
|
|
4
4
|
|
|
5
5
|
[34mCLI[39m Building entry: src/index.tsx
|
|
@@ -10,13 +10,13 @@
|
|
|
10
10
|
[34mCLI[39m Cleaning output folder
|
|
11
11
|
[34mESM[39m Build start
|
|
12
12
|
[34mCJS[39m Build start
|
|
13
|
-
[32mESM[39m [1mdist/index.mjs [22m[
|
|
14
|
-
[32mESM[39m [1mdist/index.mjs.map [22m[
|
|
15
|
-
[32mESM[39m ⚡️ Build success in
|
|
16
|
-
[32mCJS[39m [1mdist/index.js [22m[
|
|
17
|
-
[32mCJS[39m [1mdist/index.js.map [22m[
|
|
18
|
-
[32mCJS[39m ⚡️ Build success in
|
|
13
|
+
[32mESM[39m [1mdist/index.mjs [22m[32m13.30 KB[39m
|
|
14
|
+
[32mESM[39m [1mdist/index.mjs.map [22m[32m38.08 KB[39m
|
|
15
|
+
[32mESM[39m ⚡️ Build success in 46ms
|
|
16
|
+
[32mCJS[39m [1mdist/index.js [22m[32m16.10 KB[39m
|
|
17
|
+
[32mCJS[39m [1mdist/index.js.map [22m[32m38.11 KB[39m
|
|
18
|
+
[32mCJS[39m ⚡️ Build success in 46ms
|
|
19
19
|
[34mDTS[39m Build start
|
|
20
|
-
[32mDTS[39m ⚡️ Build success in
|
|
21
|
-
[32mDTS[39m [1mdist/index.d.mts [22m[
|
|
22
|
-
[32mDTS[39m [1mdist/index.d.ts [22m[
|
|
20
|
+
[32mDTS[39m ⚡️ Build success in 4602ms
|
|
21
|
+
[32mDTS[39m [1mdist/index.d.mts [22m[32m12.67 KB[39m
|
|
22
|
+
[32mDTS[39m [1mdist/index.d.ts [22m[32m12.67 KB[39m
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# @objectstack/client-react
|
|
2
2
|
|
|
3
|
+
## 4.0.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies [f08ffc3]
|
|
8
|
+
- Updated dependencies [e0b0a78]
|
|
9
|
+
- @objectstack/spec@4.0.0
|
|
10
|
+
- @objectstack/client@4.0.0
|
|
11
|
+
- @objectstack/core@4.0.0
|
|
12
|
+
|
|
13
|
+
## 3.3.1
|
|
14
|
+
|
|
15
|
+
### Patch Changes
|
|
16
|
+
|
|
17
|
+
- @objectstack/spec@3.3.1
|
|
18
|
+
- @objectstack/core@3.3.1
|
|
19
|
+
- @objectstack/client@3.3.1
|
|
20
|
+
|
|
3
21
|
## 3.3.0
|
|
4
22
|
|
|
5
23
|
### Patch Changes
|
package/dist/index.d.mts
CHANGED
|
@@ -49,19 +49,41 @@ declare function useClient(): ObjectStackClient;
|
|
|
49
49
|
|
|
50
50
|
/**
|
|
51
51
|
* Query options for useQuery hook
|
|
52
|
+
*
|
|
53
|
+
* Supports both **canonical** (Spec protocol) and **legacy** field names.
|
|
54
|
+
* Canonical names are preferred; legacy names are accepted for backward
|
|
55
|
+
* compatibility and will be removed in a future major release.
|
|
56
|
+
*
|
|
57
|
+
* | Canonical | Legacy (deprecated) |
|
|
58
|
+
* |-----------|---------------------|
|
|
59
|
+
* | `where` | `filters` |
|
|
60
|
+
* | `fields` | `select` |
|
|
61
|
+
* | `orderBy` | `sort` |
|
|
62
|
+
* | `limit` | `top` |
|
|
63
|
+
* | `offset` | `skip` |
|
|
52
64
|
*/
|
|
53
65
|
interface UseQueryOptions<T = any> {
|
|
54
66
|
/** Query AST or simplified query options */
|
|
55
67
|
query?: Partial<QueryAST>;
|
|
56
|
-
/**
|
|
68
|
+
/** Filter conditions (WHERE clause). */
|
|
69
|
+
where?: FilterCondition;
|
|
70
|
+
/** Fields to retrieve (SELECT clause). */
|
|
71
|
+
fields?: string[];
|
|
72
|
+
/** Sort definition (ORDER BY clause). */
|
|
73
|
+
orderBy?: string | string[];
|
|
74
|
+
/** Maximum number of records to return (LIMIT). */
|
|
75
|
+
limit?: number;
|
|
76
|
+
/** Number of records to skip (OFFSET). */
|
|
77
|
+
offset?: number;
|
|
78
|
+
/** @deprecated Use `fields` instead. */
|
|
57
79
|
select?: string[];
|
|
58
|
-
/**
|
|
80
|
+
/** @deprecated Use `where` instead. */
|
|
59
81
|
filters?: FilterCondition;
|
|
60
|
-
/**
|
|
82
|
+
/** @deprecated Use `orderBy` instead. */
|
|
61
83
|
sort?: string | string[];
|
|
62
|
-
/**
|
|
84
|
+
/** @deprecated Use `limit` instead. */
|
|
63
85
|
top?: number;
|
|
64
|
-
/**
|
|
86
|
+
/** @deprecated Use `offset` instead. */
|
|
65
87
|
skip?: number;
|
|
66
88
|
/** Enable/disable automatic query execution */
|
|
67
89
|
enabled?: boolean;
|
|
@@ -94,9 +116,9 @@ interface UseQueryResult<T = any> {
|
|
|
94
116
|
* ```tsx
|
|
95
117
|
* function TaskList() {
|
|
96
118
|
* const { data, isLoading, error, refetch } = useQuery('todo_task', {
|
|
97
|
-
*
|
|
98
|
-
*
|
|
99
|
-
*
|
|
119
|
+
* fields: ['id', 'subject', 'priority'],
|
|
120
|
+
* orderBy: ['-created_at'],
|
|
121
|
+
* limit: 20
|
|
100
122
|
* });
|
|
101
123
|
*
|
|
102
124
|
* if (isLoading) return <div>Loading...</div>;
|
|
@@ -165,7 +187,7 @@ declare function useMutation<TData = any, TVariables = any>(object: string, oper
|
|
|
165
187
|
/**
|
|
166
188
|
* Pagination options for usePagination hook
|
|
167
189
|
*/
|
|
168
|
-
interface UsePaginationOptions<T = any> extends Omit<UseQueryOptions<T>, 'top' | 'skip'> {
|
|
190
|
+
interface UsePaginationOptions<T = any> extends Omit<UseQueryOptions<T>, 'top' | 'skip' | 'limit' | 'offset'> {
|
|
169
191
|
/** Page size */
|
|
170
192
|
pageSize?: number;
|
|
171
193
|
/** Initial page (1-based) */
|
|
@@ -209,7 +231,7 @@ interface UsePaginationResult<T = any> extends UseQueryResult<T> {
|
|
|
209
231
|
* hasPreviousPage
|
|
210
232
|
* } = usePagination('todo_task', {
|
|
211
233
|
* pageSize: 10,
|
|
212
|
-
*
|
|
234
|
+
* orderBy: ['-created_at']
|
|
213
235
|
* });
|
|
214
236
|
*
|
|
215
237
|
* return (
|
|
@@ -227,7 +249,7 @@ declare function usePagination<T = any>(object: string, options?: UsePaginationO
|
|
|
227
249
|
/**
|
|
228
250
|
* Infinite query options for useInfiniteQuery hook
|
|
229
251
|
*/
|
|
230
|
-
interface UseInfiniteQueryOptions<T = any> extends Omit<UseQueryOptions<T>, 'skip'> {
|
|
252
|
+
interface UseInfiniteQueryOptions<T = any> extends Omit<UseQueryOptions<T>, 'skip' | 'offset'> {
|
|
231
253
|
/** Page size for each fetch */
|
|
232
254
|
pageSize?: number;
|
|
233
255
|
/** Get next page parameter */
|
|
@@ -268,7 +290,7 @@ interface UseInfiniteQueryResult<T = any> {
|
|
|
268
290
|
* isFetchingNextPage
|
|
269
291
|
* } = useInfiniteQuery('todo_task', {
|
|
270
292
|
* pageSize: 20,
|
|
271
|
-
*
|
|
293
|
+
* orderBy: ['-created_at']
|
|
272
294
|
* });
|
|
273
295
|
*
|
|
274
296
|
* return (
|
package/dist/index.d.ts
CHANGED
|
@@ -49,19 +49,41 @@ declare function useClient(): ObjectStackClient;
|
|
|
49
49
|
|
|
50
50
|
/**
|
|
51
51
|
* Query options for useQuery hook
|
|
52
|
+
*
|
|
53
|
+
* Supports both **canonical** (Spec protocol) and **legacy** field names.
|
|
54
|
+
* Canonical names are preferred; legacy names are accepted for backward
|
|
55
|
+
* compatibility and will be removed in a future major release.
|
|
56
|
+
*
|
|
57
|
+
* | Canonical | Legacy (deprecated) |
|
|
58
|
+
* |-----------|---------------------|
|
|
59
|
+
* | `where` | `filters` |
|
|
60
|
+
* | `fields` | `select` |
|
|
61
|
+
* | `orderBy` | `sort` |
|
|
62
|
+
* | `limit` | `top` |
|
|
63
|
+
* | `offset` | `skip` |
|
|
52
64
|
*/
|
|
53
65
|
interface UseQueryOptions<T = any> {
|
|
54
66
|
/** Query AST or simplified query options */
|
|
55
67
|
query?: Partial<QueryAST>;
|
|
56
|
-
/**
|
|
68
|
+
/** Filter conditions (WHERE clause). */
|
|
69
|
+
where?: FilterCondition;
|
|
70
|
+
/** Fields to retrieve (SELECT clause). */
|
|
71
|
+
fields?: string[];
|
|
72
|
+
/** Sort definition (ORDER BY clause). */
|
|
73
|
+
orderBy?: string | string[];
|
|
74
|
+
/** Maximum number of records to return (LIMIT). */
|
|
75
|
+
limit?: number;
|
|
76
|
+
/** Number of records to skip (OFFSET). */
|
|
77
|
+
offset?: number;
|
|
78
|
+
/** @deprecated Use `fields` instead. */
|
|
57
79
|
select?: string[];
|
|
58
|
-
/**
|
|
80
|
+
/** @deprecated Use `where` instead. */
|
|
59
81
|
filters?: FilterCondition;
|
|
60
|
-
/**
|
|
82
|
+
/** @deprecated Use `orderBy` instead. */
|
|
61
83
|
sort?: string | string[];
|
|
62
|
-
/**
|
|
84
|
+
/** @deprecated Use `limit` instead. */
|
|
63
85
|
top?: number;
|
|
64
|
-
/**
|
|
86
|
+
/** @deprecated Use `offset` instead. */
|
|
65
87
|
skip?: number;
|
|
66
88
|
/** Enable/disable automatic query execution */
|
|
67
89
|
enabled?: boolean;
|
|
@@ -94,9 +116,9 @@ interface UseQueryResult<T = any> {
|
|
|
94
116
|
* ```tsx
|
|
95
117
|
* function TaskList() {
|
|
96
118
|
* const { data, isLoading, error, refetch } = useQuery('todo_task', {
|
|
97
|
-
*
|
|
98
|
-
*
|
|
99
|
-
*
|
|
119
|
+
* fields: ['id', 'subject', 'priority'],
|
|
120
|
+
* orderBy: ['-created_at'],
|
|
121
|
+
* limit: 20
|
|
100
122
|
* });
|
|
101
123
|
*
|
|
102
124
|
* if (isLoading) return <div>Loading...</div>;
|
|
@@ -165,7 +187,7 @@ declare function useMutation<TData = any, TVariables = any>(object: string, oper
|
|
|
165
187
|
/**
|
|
166
188
|
* Pagination options for usePagination hook
|
|
167
189
|
*/
|
|
168
|
-
interface UsePaginationOptions<T = any> extends Omit<UseQueryOptions<T>, 'top' | 'skip'> {
|
|
190
|
+
interface UsePaginationOptions<T = any> extends Omit<UseQueryOptions<T>, 'top' | 'skip' | 'limit' | 'offset'> {
|
|
169
191
|
/** Page size */
|
|
170
192
|
pageSize?: number;
|
|
171
193
|
/** Initial page (1-based) */
|
|
@@ -209,7 +231,7 @@ interface UsePaginationResult<T = any> extends UseQueryResult<T> {
|
|
|
209
231
|
* hasPreviousPage
|
|
210
232
|
* } = usePagination('todo_task', {
|
|
211
233
|
* pageSize: 10,
|
|
212
|
-
*
|
|
234
|
+
* orderBy: ['-created_at']
|
|
213
235
|
* });
|
|
214
236
|
*
|
|
215
237
|
* return (
|
|
@@ -227,7 +249,7 @@ declare function usePagination<T = any>(object: string, options?: UsePaginationO
|
|
|
227
249
|
/**
|
|
228
250
|
* Infinite query options for useInfiniteQuery hook
|
|
229
251
|
*/
|
|
230
|
-
interface UseInfiniteQueryOptions<T = any> extends Omit<UseQueryOptions<T>, 'skip'> {
|
|
252
|
+
interface UseInfiniteQueryOptions<T = any> extends Omit<UseQueryOptions<T>, 'skip' | 'offset'> {
|
|
231
253
|
/** Page size for each fetch */
|
|
232
254
|
pageSize?: number;
|
|
233
255
|
/** Get next page parameter */
|
|
@@ -268,7 +290,7 @@ interface UseInfiniteQueryResult<T = any> {
|
|
|
268
290
|
* isFetchingNextPage
|
|
269
291
|
* } = useInfiniteQuery('todo_task', {
|
|
270
292
|
* pageSize: 20,
|
|
271
|
-
*
|
|
293
|
+
* orderBy: ['-created_at']
|
|
272
294
|
* });
|
|
273
295
|
*
|
|
274
296
|
* return (
|
package/dist/index.js
CHANGED
|
@@ -73,6 +73,13 @@ function useQuery(object, options = {}) {
|
|
|
73
73
|
const intervalRef = (0, import_react2.useRef)(void 0);
|
|
74
74
|
const {
|
|
75
75
|
query,
|
|
76
|
+
// Canonical names take precedence over legacy names
|
|
77
|
+
where,
|
|
78
|
+
fields,
|
|
79
|
+
orderBy,
|
|
80
|
+
limit,
|
|
81
|
+
offset,
|
|
82
|
+
// Legacy names (deprecated fallbacks)
|
|
76
83
|
select,
|
|
77
84
|
filters,
|
|
78
85
|
sort,
|
|
@@ -83,6 +90,11 @@ function useQuery(object, options = {}) {
|
|
|
83
90
|
onSuccess,
|
|
84
91
|
onError
|
|
85
92
|
} = options;
|
|
93
|
+
const resolvedFields = fields ?? select;
|
|
94
|
+
const resolvedWhere = where ?? filters;
|
|
95
|
+
const resolvedSort = orderBy ?? sort;
|
|
96
|
+
const resolvedLimit = limit ?? top;
|
|
97
|
+
const resolvedOffset = offset ?? skip;
|
|
86
98
|
const fetchData = (0, import_react2.useCallback)(async (isRefetch = false) => {
|
|
87
99
|
if (!enabled) return;
|
|
88
100
|
try {
|
|
@@ -97,11 +109,11 @@ function useQuery(object, options = {}) {
|
|
|
97
109
|
result = await client.data.query(object, query);
|
|
98
110
|
} else {
|
|
99
111
|
result = await client.data.find(object, {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
112
|
+
where: resolvedWhere,
|
|
113
|
+
fields: resolvedFields,
|
|
114
|
+
orderBy: resolvedSort,
|
|
115
|
+
limit: resolvedLimit,
|
|
116
|
+
offset: resolvedOffset
|
|
105
117
|
});
|
|
106
118
|
}
|
|
107
119
|
setData(result);
|
|
@@ -114,7 +126,7 @@ function useQuery(object, options = {}) {
|
|
|
114
126
|
setIsLoading(false);
|
|
115
127
|
setIsRefetching(false);
|
|
116
128
|
}
|
|
117
|
-
}, [client, object, query,
|
|
129
|
+
}, [client, object, query, resolvedFields, resolvedWhere, resolvedSort, resolvedLimit, resolvedOffset, enabled, onSuccess, onError]);
|
|
118
130
|
(0, import_react2.useEffect)(() => {
|
|
119
131
|
fetchData();
|
|
120
132
|
}, [fetchData]);
|
|
@@ -217,8 +229,8 @@ function usePagination(object, options = {}) {
|
|
|
217
229
|
const [page, setPage] = (0, import_react2.useState)(initialPage);
|
|
218
230
|
const queryResult = useQuery(object, {
|
|
219
231
|
...queryOptions,
|
|
220
|
-
|
|
221
|
-
|
|
232
|
+
limit: pageSize,
|
|
233
|
+
offset: (page - 1) * pageSize
|
|
222
234
|
});
|
|
223
235
|
const totalCount = queryResult.data?.total || 0;
|
|
224
236
|
const totalPages = Math.ceil(totalCount / pageSize);
|
|
@@ -256,6 +268,11 @@ function useInfiniteQuery(object, options = {}) {
|
|
|
256
268
|
pageSize = 20,
|
|
257
269
|
// getNextPageParam is reserved for future use
|
|
258
270
|
query,
|
|
271
|
+
// Canonical names take precedence over legacy names
|
|
272
|
+
where,
|
|
273
|
+
fields,
|
|
274
|
+
orderBy,
|
|
275
|
+
// Legacy names (deprecated fallbacks)
|
|
259
276
|
select,
|
|
260
277
|
filters,
|
|
261
278
|
sort,
|
|
@@ -263,6 +280,9 @@ function useInfiniteQuery(object, options = {}) {
|
|
|
263
280
|
onSuccess,
|
|
264
281
|
onError
|
|
265
282
|
} = options;
|
|
283
|
+
const resolvedFields = fields ?? select;
|
|
284
|
+
const resolvedWhere = where ?? filters;
|
|
285
|
+
const resolvedSort = orderBy ?? sort;
|
|
266
286
|
const [pages, setPages] = (0, import_react2.useState)([]);
|
|
267
287
|
const [isLoading, setIsLoading] = (0, import_react2.useState)(true);
|
|
268
288
|
const [isFetchingNextPage, setIsFetchingNextPage] = (0, import_react2.useState)(false);
|
|
@@ -285,11 +305,11 @@ function useInfiniteQuery(object, options = {}) {
|
|
|
285
305
|
});
|
|
286
306
|
} else {
|
|
287
307
|
result = await client.data.find(object, {
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
skip
|
|
308
|
+
where: resolvedWhere,
|
|
309
|
+
fields: resolvedFields,
|
|
310
|
+
orderBy: resolvedSort,
|
|
311
|
+
limit: pageSize,
|
|
312
|
+
offset: skip
|
|
293
313
|
});
|
|
294
314
|
}
|
|
295
315
|
if (isNextPage) {
|
|
@@ -309,7 +329,7 @@ function useInfiniteQuery(object, options = {}) {
|
|
|
309
329
|
setIsLoading(false);
|
|
310
330
|
setIsFetchingNextPage(false);
|
|
311
331
|
}
|
|
312
|
-
}, [client, object, query,
|
|
332
|
+
}, [client, object, query, resolvedFields, resolvedWhere, resolvedSort, pageSize, onSuccess, onError]);
|
|
313
333
|
(0, import_react2.useEffect)(() => {
|
|
314
334
|
if (enabled) {
|
|
315
335
|
fetchPage(0);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.tsx","../src/context.tsx","../src/data-hooks.tsx","../src/metadata-hooks.tsx"],"sourcesContent":["// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * @objectstack/client-react\n * \n * React hooks for ObjectStack Client SDK\n * \n * Provides type-safe React hooks for:\n * - Data queries (useQuery, useMutation, usePagination, useInfiniteQuery)\n * - Metadata access (useObject, useView, useFields, useMetadata)\n * - Client context (ObjectStackProvider, useClient)\n */\n\n// Context & Provider\nexport {\n ObjectStackProvider,\n ObjectStackContext,\n useClient,\n type ObjectStackProviderProps\n} from './context';\n\n// Data Hooks\nexport {\n useQuery,\n useMutation,\n usePagination,\n useInfiniteQuery,\n type UseQueryOptions,\n type UseQueryResult,\n type UseMutationOptions,\n type UseMutationResult,\n type UsePaginationOptions,\n type UsePaginationResult,\n type UseInfiniteQueryOptions,\n type UseInfiniteQueryResult\n} from './data-hooks';\n\n// Metadata Hooks\nexport {\n useObject,\n useView,\n useFields,\n useMetadata,\n type UseMetadataOptions,\n type UseMetadataResult\n} from './metadata-hooks';\n\n// Re-export ObjectStackClient and types from @objectstack/client\nexport { ObjectStackClient, type ClientConfig } from '@objectstack/client';\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * ObjectStack React Context\n * \n * Provides ObjectStackClient instance to React components via Context API\n */\n\nimport * as React from 'react';\nimport { createContext, useContext, ReactNode } from 'react';\nimport { ObjectStackClient } from '@objectstack/client';\n\nexport interface ObjectStackProviderProps {\n client: ObjectStackClient;\n children: ReactNode;\n}\n\nexport const ObjectStackContext = createContext<ObjectStackClient | null>(null);\n\n/**\n * Provider component that makes ObjectStackClient available to all child components\n * \n * @example\n * ```tsx\n * const client = new ObjectStackClient({ baseUrl: 'http://localhost:3000' });\n * \n * function App() {\n * return (\n * <ObjectStackProvider client={client}>\n * <YourComponents />\n * </ObjectStackProvider>\n * );\n * }\n * ```\n */\nexport function ObjectStackProvider({ client, children }: ObjectStackProviderProps) {\n return (\n <ObjectStackContext.Provider value={client}>\n {children}\n </ObjectStackContext.Provider>\n );\n}\n\n/**\n * Hook to access the ObjectStackClient instance from context\n * \n * @throws Error if used outside of ObjectStackProvider\n * \n * @example\n * ```tsx\n * function MyComponent() {\n * const client = useClient();\n * // Use client.data.find(), etc.\n * }\n * ```\n */\nexport function useClient(): ObjectStackClient {\n const client = useContext(ObjectStackContext);\n \n if (!client) {\n throw new Error(\n 'useClient must be used within an ObjectStackProvider. ' +\n 'Make sure your component is wrapped with <ObjectStackProvider client={...}>.'\n );\n }\n \n return client;\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Data Query Hooks\n * \n * React hooks for querying and mutating ObjectStack data\n */\n\nimport { useState, useEffect, useCallback, useRef } from 'react';\nimport { QueryAST, FilterCondition } from '@objectstack/spec/data';\nimport { PaginatedResult } from '@objectstack/client';\nimport { useClient } from './context';\n\n/**\n * Query options for useQuery hook\n */\nexport interface UseQueryOptions<T = any> {\n /** Query AST or simplified query options */\n query?: Partial<QueryAST>;\n /** Simple field selection */\n select?: string[];\n /** Simple filters */\n filters?: FilterCondition;\n /** Sort configuration */\n sort?: string | string[];\n /** Limit results */\n top?: number;\n /** Skip results (for pagination) */\n skip?: number;\n /** Enable/disable automatic query execution */\n enabled?: boolean;\n /** Refetch interval in milliseconds */\n refetchInterval?: number;\n /** Callback on successful query */\n onSuccess?: (data: PaginatedResult<T>) => void;\n /** Callback on error */\n onError?: (error: Error) => void;\n}\n\n/**\n * Query result for useQuery hook\n */\nexport interface UseQueryResult<T = any> {\n /** Query result data */\n data: PaginatedResult<T> | null;\n /** Loading state */\n isLoading: boolean;\n /** Error state */\n error: Error | null;\n /** Refetch the query */\n refetch: () => Promise<void>;\n /** Is currently refetching */\n isRefetching: boolean;\n}\n\n/**\n * Hook for querying ObjectStack data with automatic caching and refetching\n * \n * @example\n * ```tsx\n * function TaskList() {\n * const { data, isLoading, error, refetch } = useQuery('todo_task', {\n * select: ['id', 'subject', 'priority'],\n * sort: ['-created_at'],\n * top: 20\n * });\n * \n * if (isLoading) return <div>Loading...</div>;\n * if (error) return <div>Error: {error.message}</div>;\n * \n * return (\n * <div>\n * {data?.value.map(task => (\n * <div key={task.id}>{task.subject}</div>\n * ))}\n * </div>\n * );\n * }\n * ```\n */\nexport function useQuery<T = any>(\n object: string,\n options: UseQueryOptions<T> = {}\n): UseQueryResult<T> {\n const client = useClient();\n const [data, setData] = useState<PaginatedResult<T> | null>(null);\n const [isLoading, setIsLoading] = useState(true);\n const [isRefetching, setIsRefetching] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const intervalRef = useRef<NodeJS.Timeout | undefined>(undefined);\n \n const {\n query,\n select,\n filters,\n sort,\n top,\n skip,\n enabled = true,\n refetchInterval,\n onSuccess,\n onError\n } = options;\n\n const fetchData = useCallback(async (isRefetch = false) => {\n if (!enabled) return;\n \n try {\n if (isRefetch) {\n setIsRefetching(true);\n } else {\n setIsLoading(true);\n }\n setError(null);\n\n let result: PaginatedResult<T>;\n \n if (query) {\n // Use advanced query API\n result = await client.data.query<T>(object, query);\n } else {\n // Use simplified find API\n result = await client.data.find<T>(object, {\n select,\n filters: filters as any,\n sort,\n top,\n skip\n });\n }\n\n setData(result);\n onSuccess?.(result);\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Query failed');\n setError(error);\n onError?.(error);\n } finally {\n setIsLoading(false);\n setIsRefetching(false);\n }\n }, [client, object, query, select, filters, sort, top, skip, enabled, onSuccess, onError]);\n\n // Initial fetch and dependency-based refetch\n useEffect(() => {\n fetchData();\n }, [fetchData]);\n\n // Setup refetch interval\n useEffect(() => {\n if (refetchInterval && enabled) {\n intervalRef.current = setInterval(() => {\n fetchData(true);\n }, refetchInterval);\n\n return () => {\n if (intervalRef.current) {\n clearInterval(intervalRef.current);\n }\n };\n }\n return undefined;\n }, [refetchInterval, enabled, fetchData]);\n\n const refetch = useCallback(async () => {\n await fetchData(true);\n }, [fetchData]);\n\n return {\n data,\n isLoading,\n error,\n refetch,\n isRefetching\n };\n}\n\n/**\n * Mutation options for useMutation hook\n */\nexport interface UseMutationOptions<TData = any, TVariables = any> {\n /** Callback on successful mutation */\n onSuccess?: (data: TData, variables: TVariables) => void;\n /** Callback on error */\n onError?: (error: Error, variables: TVariables) => void;\n /** Callback when mutation is settled (success or error) */\n onSettled?: (data: TData | undefined, error: Error | null, variables: TVariables) => void;\n}\n\n/**\n * Mutation result for useMutation hook\n */\nexport interface UseMutationResult<TData = any, TVariables = any> {\n /** Execute the mutation */\n mutate: (variables: TVariables) => Promise<TData>;\n /** Async version of mutate that throws errors */\n mutateAsync: (variables: TVariables) => Promise<TData>;\n /** Mutation result data */\n data: TData | null;\n /** Loading state */\n isLoading: boolean;\n /** Error state */\n error: Error | null;\n /** Reset mutation state */\n reset: () => void;\n}\n\n/**\n * Hook for creating, updating, or deleting ObjectStack data\n * \n * @example\n * ```tsx\n * function CreateTaskForm() {\n * const { mutate, isLoading, error } = useMutation('todo_task', 'create', {\n * onSuccess: (data) => {\n * console.log('Task created:', data);\n * }\n * });\n * \n * const handleSubmit = (formData) => {\n * mutate(formData);\n * };\n * \n * return <form onSubmit={handleSubmit}>...</form>;\n * }\n * ```\n */\nexport function useMutation<TData = any, TVariables = any>(\n object: string,\n operation: 'create' | 'update' | 'delete' | 'createMany' | 'updateMany' | 'deleteMany',\n options: UseMutationOptions<TData, TVariables> = {}\n): UseMutationResult<TData, TVariables> {\n const client = useClient();\n const [data, setData] = useState<TData | null>(null);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const { onSuccess, onError, onSettled } = options;\n\n const mutateAsync = useCallback(async (variables: TVariables): Promise<TData> => {\n setIsLoading(true);\n setError(null);\n\n try {\n let result: TData;\n\n switch (operation) {\n case 'create':\n result = (await client.data.create(object, variables as any)) as TData;\n break;\n case 'update':\n // Expect variables to be { id: string, data: Partial<T> }\n const updateVars = variables as any;\n result = (await client.data.update(object, updateVars.id, updateVars.data)) as TData;\n break;\n case 'delete':\n // Expect variables to be { id: string }\n const deleteVars = variables as any;\n result = await client.data.delete(object, deleteVars.id) as any;\n break;\n case 'createMany':\n // createMany returns an array, which may not match TData type\n result = await client.data.createMany(object, variables as any) as any;\n break;\n case 'updateMany':\n // Expect variables to be { records: Array<{ id: string, data: Partial<T> }> }\n const updateManyVars = variables as any;\n result = await client.data.updateMany(object, updateManyVars.records, updateManyVars.options) as any;\n break;\n case 'deleteMany':\n // Expect variables to be { ids: string[] }\n const deleteManyVars = variables as any;\n result = await client.data.deleteMany(object, deleteManyVars.ids, deleteManyVars.options) as any;\n break;\n default:\n throw new Error(`Unknown operation: ${operation}`);\n }\n\n setData(result);\n onSuccess?.(result, variables);\n onSettled?.(result, null, variables);\n \n return result;\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Mutation failed');\n setError(error);\n onError?.(error, variables);\n onSettled?.(undefined, error, variables);\n throw error;\n } finally {\n setIsLoading(false);\n }\n }, [client, object, operation, onSuccess, onError, onSettled]);\n\n const mutate = useCallback((variables: TVariables): Promise<TData> => {\n return mutateAsync(variables).catch(() => {\n // Swallow error for non-async version\n // Error is still available in the error state\n return null as any;\n });\n }, [mutateAsync]);\n\n const reset = useCallback(() => {\n setData(null);\n setError(null);\n setIsLoading(false);\n }, []);\n\n return {\n mutate,\n mutateAsync,\n data,\n isLoading,\n error,\n reset\n };\n}\n\n/**\n * Pagination options for usePagination hook\n */\nexport interface UsePaginationOptions<T = any> extends Omit<UseQueryOptions<T>, 'top' | 'skip'> {\n /** Page size */\n pageSize?: number;\n /** Initial page (1-based) */\n initialPage?: number;\n}\n\n/**\n * Pagination result for usePagination hook\n */\nexport interface UsePaginationResult<T = any> extends UseQueryResult<T> {\n /** Current page (1-based) */\n page: number;\n /** Total number of pages */\n totalPages: number;\n /** Total number of records */\n totalCount: number;\n /** Go to next page */\n nextPage: () => void;\n /** Go to previous page */\n previousPage: () => void;\n /** Go to specific page */\n goToPage: (page: number) => void;\n /** Whether there is a next page */\n hasNextPage: boolean;\n /** Whether there is a previous page */\n hasPreviousPage: boolean;\n}\n\n/**\n * Hook for paginated data queries\n * \n * @example\n * ```tsx\n * function PaginatedTaskList() {\n * const {\n * data,\n * isLoading,\n * page,\n * totalPages,\n * nextPage,\n * previousPage,\n * hasNextPage,\n * hasPreviousPage\n * } = usePagination('todo_task', {\n * pageSize: 10,\n * sort: ['-created_at']\n * });\n * \n * return (\n * <div>\n * {data?.value.map(task => <div key={task.id}>{task.subject}</div>)}\n * <button onClick={previousPage} disabled={!hasPreviousPage}>Previous</button>\n * <span>Page {page} of {totalPages}</span>\n * <button onClick={nextPage} disabled={!hasNextPage}>Next</button>\n * </div>\n * );\n * }\n * ```\n */\nexport function usePagination<T = any>(\n object: string,\n options: UsePaginationOptions<T> = {}\n): UsePaginationResult<T> {\n const { pageSize = 20, initialPage = 1, ...queryOptions } = options;\n const [page, setPage] = useState(initialPage);\n\n const queryResult = useQuery<T>(object, {\n ...queryOptions,\n top: pageSize,\n skip: (page - 1) * pageSize\n });\n\n const totalCount = queryResult.data?.total || 0;\n const totalPages = Math.ceil(totalCount / pageSize);\n const hasNextPage = page < totalPages;\n const hasPreviousPage = page > 1;\n\n const nextPage = useCallback(() => {\n if (hasNextPage) {\n setPage(p => p + 1);\n }\n }, [hasNextPage]);\n\n const previousPage = useCallback(() => {\n if (hasPreviousPage) {\n setPage(p => p - 1);\n }\n }, [hasPreviousPage]);\n\n const goToPage = useCallback((newPage: number) => {\n const clampedPage = Math.max(1, Math.min(newPage, totalPages));\n setPage(clampedPage);\n }, [totalPages]);\n\n return {\n ...queryResult,\n page,\n totalPages,\n totalCount,\n nextPage,\n previousPage,\n goToPage,\n hasNextPage,\n hasPreviousPage\n };\n}\n\n/**\n * Infinite query options for useInfiniteQuery hook\n */\nexport interface UseInfiniteQueryOptions<T = any> extends Omit<UseQueryOptions<T>, 'skip'> {\n /** Page size for each fetch */\n pageSize?: number;\n /** Get next page parameter */\n getNextPageParam?: (lastPage: PaginatedResult<T>, allPages: PaginatedResult<T>[]) => number | undefined;\n}\n\n/**\n * Infinite query result for useInfiniteQuery hook\n */\nexport interface UseInfiniteQueryResult<T = any> {\n /** All pages of data */\n data: PaginatedResult<T>[];\n /** Flattened data from all pages */\n flatData: T[];\n /** Loading state */\n isLoading: boolean;\n /** Error state */\n error: Error | null;\n /** Load the next page */\n fetchNextPage: () => Promise<void>;\n /** Whether there are more pages */\n hasNextPage: boolean;\n /** Is currently fetching next page */\n isFetchingNextPage: boolean;\n /** Refetch all pages */\n refetch: () => Promise<void>;\n}\n\n/**\n * Hook for infinite scrolling / load more functionality\n * \n * @example\n * ```tsx\n * function InfiniteTaskList() {\n * const {\n * flatData,\n * isLoading,\n * fetchNextPage,\n * hasNextPage,\n * isFetchingNextPage\n * } = useInfiniteQuery('todo_task', {\n * pageSize: 20,\n * sort: ['-created_at']\n * });\n * \n * return (\n * <div>\n * {flatData.map(task => <div key={task.id}>{task.subject}</div>)}\n * {hasNextPage && (\n * <button onClick={fetchNextPage} disabled={isFetchingNextPage}>\n * {isFetchingNextPage ? 'Loading...' : 'Load More'}\n * </button>\n * )}\n * </div>\n * );\n * }\n * ```\n */\nexport function useInfiniteQuery<T = any>(\n object: string,\n options: UseInfiniteQueryOptions<T> = {}\n): UseInfiniteQueryResult<T> {\n const client = useClient();\n const {\n pageSize = 20,\n // getNextPageParam is reserved for future use\n query,\n select,\n filters,\n sort,\n enabled = true,\n onSuccess,\n onError\n } = options;\n\n const [pages, setPages] = useState<PaginatedResult<T>[]>([]);\n const [isLoading, setIsLoading] = useState(true);\n const [isFetchingNextPage, setIsFetchingNextPage] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const [hasNextPage, setHasNextPage] = useState(true);\n\n const fetchPage = useCallback(async (skip: number, isNextPage = false) => {\n try {\n if (isNextPage) {\n setIsFetchingNextPage(true);\n } else {\n setIsLoading(true);\n }\n setError(null);\n\n let result: PaginatedResult<T>;\n\n if (query) {\n result = await client.data.query<T>(object, {\n ...query,\n limit: pageSize,\n offset: skip\n });\n } else {\n result = await client.data.find<T>(object, {\n select,\n filters: filters as any,\n sort,\n top: pageSize,\n skip\n });\n }\n\n if (isNextPage) {\n setPages(prev => [...prev, result]);\n } else {\n setPages([result]);\n }\n\n // Determine if there's a next page\n const fetchedCount = result.records?.length ?? 0;\n const hasMore = fetchedCount === pageSize;\n setHasNextPage(hasMore);\n\n onSuccess?.(result);\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Query failed');\n setError(error);\n onError?.(error);\n } finally {\n setIsLoading(false);\n setIsFetchingNextPage(false);\n }\n }, [client, object, query, select, filters, sort, pageSize, onSuccess, onError]);\n\n // Initial fetch\n useEffect(() => {\n if (enabled) {\n fetchPage(0);\n }\n }, [enabled, fetchPage]);\n\n const fetchNextPage = useCallback(async () => {\n if (!hasNextPage || isFetchingNextPage) return;\n\n const nextSkip = pages.length * pageSize;\n await fetchPage(nextSkip, true);\n }, [hasNextPage, isFetchingNextPage, pages.length, pageSize, fetchPage]);\n\n const refetch = useCallback(async () => {\n setPages([]);\n await fetchPage(0);\n }, [fetchPage]);\n\n const flatData = pages.flatMap(page => page.records ?? []);\n\n return {\n data: pages,\n flatData,\n isLoading,\n error,\n fetchNextPage,\n hasNextPage,\n isFetchingNextPage,\n refetch\n };\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Metadata Hooks\n * \n * React hooks for accessing ObjectStack metadata (schemas, views, fields)\n */\n\nimport { useState, useEffect, useCallback } from 'react';\nimport { useClient } from './context';\n\n/**\n * Metadata query options\n */\nexport interface UseMetadataOptions {\n /** Enable/disable automatic query execution */\n enabled?: boolean;\n /** Use cached metadata if available */\n useCache?: boolean;\n /** ETag for conditional requests */\n ifNoneMatch?: string;\n /** If-Modified-Since header for conditional requests */\n ifModifiedSince?: string;\n /** Callback on successful query */\n onSuccess?: (data: any) => void;\n /** Callback on error */\n onError?: (error: Error) => void;\n}\n\n/**\n * Metadata query result\n */\nexport interface UseMetadataResult<T = any> {\n /** Metadata data */\n data: T | null;\n /** Loading state */\n isLoading: boolean;\n /** Error state */\n error: Error | null;\n /** Refetch the metadata */\n refetch: () => Promise<void>;\n /** ETag from last fetch */\n etag?: string;\n /** Whether data came from cache (304 Not Modified) */\n fromCache: boolean;\n}\n\n/**\n * Hook for fetching object schema/metadata\n * \n * @example\n * ```tsx\n * function ObjectSchemaViewer({ objectName }: { objectName: string }) {\n * const { data: schema, isLoading, error } = useObject(objectName);\n * \n * if (isLoading) return <div>Loading schema...</div>;\n * if (error) return <div>Error: {error.message}</div>;\n * \n * return (\n * <div>\n * <h2>{schema.label}</h2>\n * <p>Fields: {Object.keys(schema.fields).length}</p>\n * </div>\n * );\n * }\n * ```\n */\nexport function useObject(\n objectName: string,\n options: UseMetadataOptions = {}\n): UseMetadataResult {\n const client = useClient();\n const [data, setData] = useState<any>(null);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n const [etag, setEtag] = useState<string>();\n const [fromCache, setFromCache] = useState(false);\n\n const {\n enabled = true,\n useCache = true,\n ifNoneMatch,\n ifModifiedSince,\n onSuccess,\n onError\n } = options;\n\n const fetchMetadata = useCallback(async () => {\n if (!enabled) return;\n\n try {\n setIsLoading(true);\n setError(null);\n setFromCache(false);\n\n if (useCache) {\n // Use cached metadata endpoint\n const result = await client.meta.getCached(objectName, {\n ifNoneMatch: ifNoneMatch || etag,\n ifModifiedSince\n });\n\n if (result.notModified) {\n setFromCache(true);\n } else {\n setData(result.data);\n if (result.etag) {\n setEtag(result.etag.value);\n }\n }\n\n onSuccess?.(result.data || data);\n } else {\n // Direct fetch without cache\n const result = await client.meta.getItem('object', objectName);\n setData(result);\n onSuccess?.(result);\n }\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Failed to fetch object metadata');\n setError(error);\n onError?.(error);\n } finally {\n setIsLoading(false);\n }\n }, [client, objectName, enabled, useCache, ifNoneMatch, ifModifiedSince, etag, data, onSuccess, onError]);\n\n useEffect(() => {\n fetchMetadata();\n }, [fetchMetadata]);\n\n const refetch = useCallback(async () => {\n await fetchMetadata();\n }, [fetchMetadata]);\n\n return {\n data,\n isLoading,\n error,\n refetch,\n etag,\n fromCache\n };\n}\n\n/**\n * Hook for fetching view configuration\n * \n * @example\n * ```tsx\n * function ViewConfiguration({ objectName }: { objectName: string }) {\n * const { data: view, isLoading } = useView(objectName, 'list');\n * \n * if (isLoading) return <div>Loading view...</div>;\n * \n * return (\n * <div>\n * <h3>List View for {objectName}</h3>\n * <p>Columns: {view?.columns?.length}</p>\n * </div>\n * );\n * }\n * ```\n */\nexport function useView(\n objectName: string,\n viewType: 'list' | 'form' = 'list',\n options: UseMetadataOptions = {}\n): UseMetadataResult {\n const client = useClient();\n const [data, setData] = useState<any>(null);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n\n const { enabled = true, onSuccess, onError } = options;\n\n const fetchView = useCallback(async () => {\n if (!enabled) return;\n\n try {\n setIsLoading(true);\n setError(null);\n\n const result = await client.meta.getView(objectName, viewType);\n setData(result);\n onSuccess?.(result);\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Failed to fetch view configuration');\n setError(error);\n onError?.(error);\n } finally {\n setIsLoading(false);\n }\n }, [client, objectName, viewType, enabled, onSuccess, onError]);\n\n useEffect(() => {\n fetchView();\n }, [fetchView]);\n\n const refetch = useCallback(async () => {\n await fetchView();\n }, [fetchView]);\n\n return {\n data,\n isLoading,\n error,\n refetch,\n fromCache: false\n };\n}\n\n/**\n * Hook for extracting fields from object schema\n * \n * @example\n * ```tsx\n * function FieldList({ objectName }: { objectName: string }) {\n * const { data: fields, isLoading } = useFields(objectName);\n * \n * if (isLoading) return <div>Loading fields...</div>;\n * \n * return (\n * <ul>\n * {fields?.map(field => (\n * <li key={field.name}>{field.label} ({field.type})</li>\n * ))}\n * </ul>\n * );\n * }\n * ```\n */\nexport function useFields(\n objectName: string,\n options: UseMetadataOptions = {}\n): UseMetadataResult<any[]> {\n const objectResult = useObject(objectName, options);\n\n const fields = objectResult.data?.fields\n ? Object.entries(objectResult.data.fields).map(([name, field]: [string, any]) => ({\n name,\n ...field\n }))\n : null;\n\n return {\n ...objectResult,\n data: fields\n };\n}\n\n/**\n * Generic metadata hook for custom metadata queries\n * \n * @example\n * ```tsx\n * function CustomMetadata() {\n * const { data, isLoading } = useMetadata(async (client) => {\n * // Custom metadata fetching logic\n * const object = await client.meta.getObject('custom_object');\n * const view = await client.meta.getView('custom_object', 'list');\n * return { object, view };\n * });\n * \n * return <pre>{JSON.stringify(data, null, 2)}</pre>;\n * }\n * ```\n */\nexport function useMetadata<T = any>(\n fetcher: (client: ReturnType<typeof useClient>) => Promise<T>,\n options: Omit<UseMetadataOptions, 'useCache' | 'ifNoneMatch' | 'ifModifiedSince'> = {}\n): UseMetadataResult<T> {\n const client = useClient();\n const [data, setData] = useState<T | null>(null);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n\n const { enabled = true, onSuccess, onError } = options;\n\n const fetchMetadata = useCallback(async () => {\n if (!enabled) return;\n\n try {\n setIsLoading(true);\n setError(null);\n\n const result = await fetcher(client);\n setData(result);\n onSuccess?.(result);\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Failed to fetch metadata');\n setError(error);\n onError?.(error);\n } finally {\n setIsLoading(false);\n }\n }, [client, fetcher, enabled, onSuccess, onError]);\n\n useEffect(() => {\n fetchMetadata();\n }, [fetchMetadata]);\n\n const refetch = useCallback(async () => {\n await fetchMetadata();\n }, [fetchMetadata]);\n\n return {\n data,\n isLoading,\n error,\n refetch,\n fromCache: false\n };\n}\n"],"mappings":"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","names":["import_react","error","import_react","error"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.tsx","../src/context.tsx","../src/data-hooks.tsx","../src/metadata-hooks.tsx"],"sourcesContent":["// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * @objectstack/client-react\n * \n * React hooks for ObjectStack Client SDK\n * \n * Provides type-safe React hooks for:\n * - Data queries (useQuery, useMutation, usePagination, useInfiniteQuery)\n * - Metadata access (useObject, useView, useFields, useMetadata)\n * - Client context (ObjectStackProvider, useClient)\n */\n\n// Context & Provider\nexport {\n ObjectStackProvider,\n ObjectStackContext,\n useClient,\n type ObjectStackProviderProps\n} from './context';\n\n// Data Hooks\nexport {\n useQuery,\n useMutation,\n usePagination,\n useInfiniteQuery,\n type UseQueryOptions,\n type UseQueryResult,\n type UseMutationOptions,\n type UseMutationResult,\n type UsePaginationOptions,\n type UsePaginationResult,\n type UseInfiniteQueryOptions,\n type UseInfiniteQueryResult\n} from './data-hooks';\n\n// Metadata Hooks\nexport {\n useObject,\n useView,\n useFields,\n useMetadata,\n type UseMetadataOptions,\n type UseMetadataResult\n} from './metadata-hooks';\n\n// Re-export ObjectStackClient and types from @objectstack/client\nexport { ObjectStackClient, type ClientConfig } from '@objectstack/client';\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * ObjectStack React Context\n * \n * Provides ObjectStackClient instance to React components via Context API\n */\n\nimport * as React from 'react';\nimport { createContext, useContext, ReactNode } from 'react';\nimport { ObjectStackClient } from '@objectstack/client';\n\nexport interface ObjectStackProviderProps {\n client: ObjectStackClient;\n children: ReactNode;\n}\n\nexport const ObjectStackContext = createContext<ObjectStackClient | null>(null);\n\n/**\n * Provider component that makes ObjectStackClient available to all child components\n * \n * @example\n * ```tsx\n * const client = new ObjectStackClient({ baseUrl: 'http://localhost:3000' });\n * \n * function App() {\n * return (\n * <ObjectStackProvider client={client}>\n * <YourComponents />\n * </ObjectStackProvider>\n * );\n * }\n * ```\n */\nexport function ObjectStackProvider({ client, children }: ObjectStackProviderProps) {\n return (\n <ObjectStackContext.Provider value={client}>\n {children}\n </ObjectStackContext.Provider>\n );\n}\n\n/**\n * Hook to access the ObjectStackClient instance from context\n * \n * @throws Error if used outside of ObjectStackProvider\n * \n * @example\n * ```tsx\n * function MyComponent() {\n * const client = useClient();\n * // Use client.data.find(), etc.\n * }\n * ```\n */\nexport function useClient(): ObjectStackClient {\n const client = useContext(ObjectStackContext);\n \n if (!client) {\n throw new Error(\n 'useClient must be used within an ObjectStackProvider. ' +\n 'Make sure your component is wrapped with <ObjectStackProvider client={...}>.'\n );\n }\n \n return client;\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Data Query Hooks\n * \n * React hooks for querying and mutating ObjectStack data\n */\n\nimport { useState, useEffect, useCallback, useRef } from 'react';\nimport { QueryAST, FilterCondition } from '@objectstack/spec/data';\nimport { PaginatedResult } from '@objectstack/client';\nimport { useClient } from './context';\n\n/**\n * Query options for useQuery hook\n *\n * Supports both **canonical** (Spec protocol) and **legacy** field names.\n * Canonical names are preferred; legacy names are accepted for backward\n * compatibility and will be removed in a future major release.\n *\n * | Canonical | Legacy (deprecated) |\n * |-----------|---------------------|\n * | `where` | `filters` |\n * | `fields` | `select` |\n * | `orderBy` | `sort` |\n * | `limit` | `top` |\n * | `offset` | `skip` |\n */\nexport interface UseQueryOptions<T = any> {\n /** Query AST or simplified query options */\n query?: Partial<QueryAST>;\n\n // ── Canonical (Spec protocol) field names ──────────────────────────\n /** Filter conditions (WHERE clause). */\n where?: FilterCondition;\n /** Fields to retrieve (SELECT clause). */\n fields?: string[];\n /** Sort definition (ORDER BY clause). */\n orderBy?: string | string[];\n /** Maximum number of records to return (LIMIT). */\n limit?: number;\n /** Number of records to skip (OFFSET). */\n offset?: number;\n\n // ── Legacy field names (deprecated) ────────────────────────────────\n /** @deprecated Use `fields` instead. */\n select?: string[];\n /** @deprecated Use `where` instead. */\n filters?: FilterCondition;\n /** @deprecated Use `orderBy` instead. */\n sort?: string | string[];\n /** @deprecated Use `limit` instead. */\n top?: number;\n /** @deprecated Use `offset` instead. */\n skip?: number;\n\n /** Enable/disable automatic query execution */\n enabled?: boolean;\n /** Refetch interval in milliseconds */\n refetchInterval?: number;\n /** Callback on successful query */\n onSuccess?: (data: PaginatedResult<T>) => void;\n /** Callback on error */\n onError?: (error: Error) => void;\n}\n\n/**\n * Query result for useQuery hook\n */\nexport interface UseQueryResult<T = any> {\n /** Query result data */\n data: PaginatedResult<T> | null;\n /** Loading state */\n isLoading: boolean;\n /** Error state */\n error: Error | null;\n /** Refetch the query */\n refetch: () => Promise<void>;\n /** Is currently refetching */\n isRefetching: boolean;\n}\n\n/**\n * Hook for querying ObjectStack data with automatic caching and refetching\n * \n * @example\n * ```tsx\n * function TaskList() {\n * const { data, isLoading, error, refetch } = useQuery('todo_task', {\n * fields: ['id', 'subject', 'priority'],\n * orderBy: ['-created_at'],\n * limit: 20\n * });\n * \n * if (isLoading) return <div>Loading...</div>;\n * if (error) return <div>Error: {error.message}</div>;\n * \n * return (\n * <div>\n * {data?.value.map(task => (\n * <div key={task.id}>{task.subject}</div>\n * ))}\n * </div>\n * );\n * }\n * ```\n */\nexport function useQuery<T = any>(\n object: string,\n options: UseQueryOptions<T> = {}\n): UseQueryResult<T> {\n const client = useClient();\n const [data, setData] = useState<PaginatedResult<T> | null>(null);\n const [isLoading, setIsLoading] = useState(true);\n const [isRefetching, setIsRefetching] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const intervalRef = useRef<NodeJS.Timeout | undefined>(undefined);\n \n const {\n query,\n // Canonical names take precedence over legacy names\n where, fields, orderBy, limit, offset,\n // Legacy names (deprecated fallbacks)\n select, filters, sort, top, skip,\n enabled = true,\n refetchInterval,\n onSuccess,\n onError\n } = options;\n\n // Resolve canonical vs legacy: canonical wins when both are provided\n const resolvedFields = fields ?? select;\n const resolvedWhere = where ?? filters;\n const resolvedSort = orderBy ?? sort;\n const resolvedLimit = limit ?? top;\n const resolvedOffset = offset ?? skip;\n\n const fetchData = useCallback(async (isRefetch = false) => {\n if (!enabled) return;\n \n try {\n if (isRefetch) {\n setIsRefetching(true);\n } else {\n setIsLoading(true);\n }\n setError(null);\n\n let result: PaginatedResult<T>;\n \n if (query) {\n // Use advanced query API\n result = await client.data.query<T>(object, query);\n } else {\n // Use canonical QueryOptionsV2 for the find call\n result = await client.data.find<T>(object, {\n where: resolvedWhere as any,\n fields: resolvedFields,\n orderBy: resolvedSort,\n limit: resolvedLimit,\n offset: resolvedOffset,\n });\n }\n\n setData(result);\n onSuccess?.(result);\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Query failed');\n setError(error);\n onError?.(error);\n } finally {\n setIsLoading(false);\n setIsRefetching(false);\n }\n }, [client, object, query, resolvedFields, resolvedWhere, resolvedSort, resolvedLimit, resolvedOffset, enabled, onSuccess, onError]);\n\n // Initial fetch and dependency-based refetch\n useEffect(() => {\n fetchData();\n }, [fetchData]);\n\n // Setup refetch interval\n useEffect(() => {\n if (refetchInterval && enabled) {\n intervalRef.current = setInterval(() => {\n fetchData(true);\n }, refetchInterval);\n\n return () => {\n if (intervalRef.current) {\n clearInterval(intervalRef.current);\n }\n };\n }\n return undefined;\n }, [refetchInterval, enabled, fetchData]);\n\n const refetch = useCallback(async () => {\n await fetchData(true);\n }, [fetchData]);\n\n return {\n data,\n isLoading,\n error,\n refetch,\n isRefetching\n };\n}\n\n/**\n * Mutation options for useMutation hook\n */\nexport interface UseMutationOptions<TData = any, TVariables = any> {\n /** Callback on successful mutation */\n onSuccess?: (data: TData, variables: TVariables) => void;\n /** Callback on error */\n onError?: (error: Error, variables: TVariables) => void;\n /** Callback when mutation is settled (success or error) */\n onSettled?: (data: TData | undefined, error: Error | null, variables: TVariables) => void;\n}\n\n/**\n * Mutation result for useMutation hook\n */\nexport interface UseMutationResult<TData = any, TVariables = any> {\n /** Execute the mutation */\n mutate: (variables: TVariables) => Promise<TData>;\n /** Async version of mutate that throws errors */\n mutateAsync: (variables: TVariables) => Promise<TData>;\n /** Mutation result data */\n data: TData | null;\n /** Loading state */\n isLoading: boolean;\n /** Error state */\n error: Error | null;\n /** Reset mutation state */\n reset: () => void;\n}\n\n/**\n * Hook for creating, updating, or deleting ObjectStack data\n * \n * @example\n * ```tsx\n * function CreateTaskForm() {\n * const { mutate, isLoading, error } = useMutation('todo_task', 'create', {\n * onSuccess: (data) => {\n * console.log('Task created:', data);\n * }\n * });\n * \n * const handleSubmit = (formData) => {\n * mutate(formData);\n * };\n * \n * return <form onSubmit={handleSubmit}>...</form>;\n * }\n * ```\n */\nexport function useMutation<TData = any, TVariables = any>(\n object: string,\n operation: 'create' | 'update' | 'delete' | 'createMany' | 'updateMany' | 'deleteMany',\n options: UseMutationOptions<TData, TVariables> = {}\n): UseMutationResult<TData, TVariables> {\n const client = useClient();\n const [data, setData] = useState<TData | null>(null);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const { onSuccess, onError, onSettled } = options;\n\n const mutateAsync = useCallback(async (variables: TVariables): Promise<TData> => {\n setIsLoading(true);\n setError(null);\n\n try {\n let result: TData;\n\n switch (operation) {\n case 'create':\n result = (await client.data.create(object, variables as any)) as TData;\n break;\n case 'update':\n // Expect variables to be { id: string, data: Partial<T> }\n const updateVars = variables as any;\n result = (await client.data.update(object, updateVars.id, updateVars.data)) as TData;\n break;\n case 'delete':\n // Expect variables to be { id: string }\n const deleteVars = variables as any;\n result = await client.data.delete(object, deleteVars.id) as any;\n break;\n case 'createMany':\n // createMany returns an array, which may not match TData type\n result = await client.data.createMany(object, variables as any) as any;\n break;\n case 'updateMany':\n // Expect variables to be { records: Array<{ id: string, data: Partial<T> }> }\n const updateManyVars = variables as any;\n result = await client.data.updateMany(object, updateManyVars.records, updateManyVars.options) as any;\n break;\n case 'deleteMany':\n // Expect variables to be { ids: string[] }\n const deleteManyVars = variables as any;\n result = await client.data.deleteMany(object, deleteManyVars.ids, deleteManyVars.options) as any;\n break;\n default:\n throw new Error(`Unknown operation: ${operation}`);\n }\n\n setData(result);\n onSuccess?.(result, variables);\n onSettled?.(result, null, variables);\n \n return result;\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Mutation failed');\n setError(error);\n onError?.(error, variables);\n onSettled?.(undefined, error, variables);\n throw error;\n } finally {\n setIsLoading(false);\n }\n }, [client, object, operation, onSuccess, onError, onSettled]);\n\n const mutate = useCallback((variables: TVariables): Promise<TData> => {\n return mutateAsync(variables).catch(() => {\n // Swallow error for non-async version\n // Error is still available in the error state\n return null as any;\n });\n }, [mutateAsync]);\n\n const reset = useCallback(() => {\n setData(null);\n setError(null);\n setIsLoading(false);\n }, []);\n\n return {\n mutate,\n mutateAsync,\n data,\n isLoading,\n error,\n reset\n };\n}\n\n/**\n * Pagination options for usePagination hook\n */\nexport interface UsePaginationOptions<T = any> extends Omit<UseQueryOptions<T>, 'top' | 'skip' | 'limit' | 'offset'> {\n /** Page size */\n pageSize?: number;\n /** Initial page (1-based) */\n initialPage?: number;\n}\n\n/**\n * Pagination result for usePagination hook\n */\nexport interface UsePaginationResult<T = any> extends UseQueryResult<T> {\n /** Current page (1-based) */\n page: number;\n /** Total number of pages */\n totalPages: number;\n /** Total number of records */\n totalCount: number;\n /** Go to next page */\n nextPage: () => void;\n /** Go to previous page */\n previousPage: () => void;\n /** Go to specific page */\n goToPage: (page: number) => void;\n /** Whether there is a next page */\n hasNextPage: boolean;\n /** Whether there is a previous page */\n hasPreviousPage: boolean;\n}\n\n/**\n * Hook for paginated data queries\n * \n * @example\n * ```tsx\n * function PaginatedTaskList() {\n * const {\n * data,\n * isLoading,\n * page,\n * totalPages,\n * nextPage,\n * previousPage,\n * hasNextPage,\n * hasPreviousPage\n * } = usePagination('todo_task', {\n * pageSize: 10,\n * orderBy: ['-created_at']\n * });\n * \n * return (\n * <div>\n * {data?.value.map(task => <div key={task.id}>{task.subject}</div>)}\n * <button onClick={previousPage} disabled={!hasPreviousPage}>Previous</button>\n * <span>Page {page} of {totalPages}</span>\n * <button onClick={nextPage} disabled={!hasNextPage}>Next</button>\n * </div>\n * );\n * }\n * ```\n */\nexport function usePagination<T = any>(\n object: string,\n options: UsePaginationOptions<T> = {}\n): UsePaginationResult<T> {\n const { pageSize = 20, initialPage = 1, ...queryOptions } = options;\n const [page, setPage] = useState(initialPage);\n\n const queryResult = useQuery<T>(object, {\n ...queryOptions,\n limit: pageSize,\n offset: (page - 1) * pageSize\n });\n\n const totalCount = queryResult.data?.total || 0;\n const totalPages = Math.ceil(totalCount / pageSize);\n const hasNextPage = page < totalPages;\n const hasPreviousPage = page > 1;\n\n const nextPage = useCallback(() => {\n if (hasNextPage) {\n setPage(p => p + 1);\n }\n }, [hasNextPage]);\n\n const previousPage = useCallback(() => {\n if (hasPreviousPage) {\n setPage(p => p - 1);\n }\n }, [hasPreviousPage]);\n\n const goToPage = useCallback((newPage: number) => {\n const clampedPage = Math.max(1, Math.min(newPage, totalPages));\n setPage(clampedPage);\n }, [totalPages]);\n\n return {\n ...queryResult,\n page,\n totalPages,\n totalCount,\n nextPage,\n previousPage,\n goToPage,\n hasNextPage,\n hasPreviousPage\n };\n}\n\n/**\n * Infinite query options for useInfiniteQuery hook\n */\nexport interface UseInfiniteQueryOptions<T = any> extends Omit<UseQueryOptions<T>, 'skip' | 'offset'> {\n /** Page size for each fetch */\n pageSize?: number;\n /** Get next page parameter */\n getNextPageParam?: (lastPage: PaginatedResult<T>, allPages: PaginatedResult<T>[]) => number | undefined;\n}\n\n/**\n * Infinite query result for useInfiniteQuery hook\n */\nexport interface UseInfiniteQueryResult<T = any> {\n /** All pages of data */\n data: PaginatedResult<T>[];\n /** Flattened data from all pages */\n flatData: T[];\n /** Loading state */\n isLoading: boolean;\n /** Error state */\n error: Error | null;\n /** Load the next page */\n fetchNextPage: () => Promise<void>;\n /** Whether there are more pages */\n hasNextPage: boolean;\n /** Is currently fetching next page */\n isFetchingNextPage: boolean;\n /** Refetch all pages */\n refetch: () => Promise<void>;\n}\n\n/**\n * Hook for infinite scrolling / load more functionality\n * \n * @example\n * ```tsx\n * function InfiniteTaskList() {\n * const {\n * flatData,\n * isLoading,\n * fetchNextPage,\n * hasNextPage,\n * isFetchingNextPage\n * } = useInfiniteQuery('todo_task', {\n * pageSize: 20,\n * orderBy: ['-created_at']\n * });\n * \n * return (\n * <div>\n * {flatData.map(task => <div key={task.id}>{task.subject}</div>)}\n * {hasNextPage && (\n * <button onClick={fetchNextPage} disabled={isFetchingNextPage}>\n * {isFetchingNextPage ? 'Loading...' : 'Load More'}\n * </button>\n * )}\n * </div>\n * );\n * }\n * ```\n */\nexport function useInfiniteQuery<T = any>(\n object: string,\n options: UseInfiniteQueryOptions<T> = {}\n): UseInfiniteQueryResult<T> {\n const client = useClient();\n const {\n pageSize = 20,\n // getNextPageParam is reserved for future use\n query,\n // Canonical names take precedence over legacy names\n where, fields, orderBy,\n // Legacy names (deprecated fallbacks)\n select, filters, sort,\n enabled = true,\n onSuccess,\n onError\n } = options;\n\n // Resolve canonical vs legacy: canonical wins\n const resolvedFields = fields ?? select;\n const resolvedWhere = where ?? filters;\n const resolvedSort = orderBy ?? sort;\n\n const [pages, setPages] = useState<PaginatedResult<T>[]>([]);\n const [isLoading, setIsLoading] = useState(true);\n const [isFetchingNextPage, setIsFetchingNextPage] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const [hasNextPage, setHasNextPage] = useState(true);\n\n const fetchPage = useCallback(async (skip: number, isNextPage = false) => {\n try {\n if (isNextPage) {\n setIsFetchingNextPage(true);\n } else {\n setIsLoading(true);\n }\n setError(null);\n\n let result: PaginatedResult<T>;\n\n if (query) {\n result = await client.data.query<T>(object, {\n ...query,\n limit: pageSize,\n offset: skip\n });\n } else {\n result = await client.data.find<T>(object, {\n where: resolvedWhere as any,\n fields: resolvedFields,\n orderBy: resolvedSort,\n limit: pageSize,\n offset: skip,\n });\n }\n\n if (isNextPage) {\n setPages(prev => [...prev, result]);\n } else {\n setPages([result]);\n }\n\n // Determine if there's a next page\n const fetchedCount = result.records?.length ?? 0;\n const hasMore = fetchedCount === pageSize;\n setHasNextPage(hasMore);\n\n onSuccess?.(result);\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Query failed');\n setError(error);\n onError?.(error);\n } finally {\n setIsLoading(false);\n setIsFetchingNextPage(false);\n }\n }, [client, object, query, resolvedFields, resolvedWhere, resolvedSort, pageSize, onSuccess, onError]);\n\n // Initial fetch\n useEffect(() => {\n if (enabled) {\n fetchPage(0);\n }\n }, [enabled, fetchPage]);\n\n const fetchNextPage = useCallback(async () => {\n if (!hasNextPage || isFetchingNextPage) return;\n\n const nextSkip = pages.length * pageSize;\n await fetchPage(nextSkip, true);\n }, [hasNextPage, isFetchingNextPage, pages.length, pageSize, fetchPage]);\n\n const refetch = useCallback(async () => {\n setPages([]);\n await fetchPage(0);\n }, [fetchPage]);\n\n const flatData = pages.flatMap(page => page.records ?? []);\n\n return {\n data: pages,\n flatData,\n isLoading,\n error,\n fetchNextPage,\n hasNextPage,\n isFetchingNextPage,\n refetch\n };\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Metadata Hooks\n * \n * React hooks for accessing ObjectStack metadata (schemas, views, fields)\n */\n\nimport { useState, useEffect, useCallback } from 'react';\nimport { useClient } from './context';\n\n/**\n * Metadata query options\n */\nexport interface UseMetadataOptions {\n /** Enable/disable automatic query execution */\n enabled?: boolean;\n /** Use cached metadata if available */\n useCache?: boolean;\n /** ETag for conditional requests */\n ifNoneMatch?: string;\n /** If-Modified-Since header for conditional requests */\n ifModifiedSince?: string;\n /** Callback on successful query */\n onSuccess?: (data: any) => void;\n /** Callback on error */\n onError?: (error: Error) => void;\n}\n\n/**\n * Metadata query result\n */\nexport interface UseMetadataResult<T = any> {\n /** Metadata data */\n data: T | null;\n /** Loading state */\n isLoading: boolean;\n /** Error state */\n error: Error | null;\n /** Refetch the metadata */\n refetch: () => Promise<void>;\n /** ETag from last fetch */\n etag?: string;\n /** Whether data came from cache (304 Not Modified) */\n fromCache: boolean;\n}\n\n/**\n * Hook for fetching object schema/metadata\n * \n * @example\n * ```tsx\n * function ObjectSchemaViewer({ objectName }: { objectName: string }) {\n * const { data: schema, isLoading, error } = useObject(objectName);\n * \n * if (isLoading) return <div>Loading schema...</div>;\n * if (error) return <div>Error: {error.message}</div>;\n * \n * return (\n * <div>\n * <h2>{schema.label}</h2>\n * <p>Fields: {Object.keys(schema.fields).length}</p>\n * </div>\n * );\n * }\n * ```\n */\nexport function useObject(\n objectName: string,\n options: UseMetadataOptions = {}\n): UseMetadataResult {\n const client = useClient();\n const [data, setData] = useState<any>(null);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n const [etag, setEtag] = useState<string>();\n const [fromCache, setFromCache] = useState(false);\n\n const {\n enabled = true,\n useCache = true,\n ifNoneMatch,\n ifModifiedSince,\n onSuccess,\n onError\n } = options;\n\n const fetchMetadata = useCallback(async () => {\n if (!enabled) return;\n\n try {\n setIsLoading(true);\n setError(null);\n setFromCache(false);\n\n if (useCache) {\n // Use cached metadata endpoint\n const result = await client.meta.getCached(objectName, {\n ifNoneMatch: ifNoneMatch || etag,\n ifModifiedSince\n });\n\n if (result.notModified) {\n setFromCache(true);\n } else {\n setData(result.data);\n if (result.etag) {\n setEtag(result.etag.value);\n }\n }\n\n onSuccess?.(result.data || data);\n } else {\n // Direct fetch without cache\n const result = await client.meta.getItem('object', objectName);\n setData(result);\n onSuccess?.(result);\n }\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Failed to fetch object metadata');\n setError(error);\n onError?.(error);\n } finally {\n setIsLoading(false);\n }\n }, [client, objectName, enabled, useCache, ifNoneMatch, ifModifiedSince, etag, data, onSuccess, onError]);\n\n useEffect(() => {\n fetchMetadata();\n }, [fetchMetadata]);\n\n const refetch = useCallback(async () => {\n await fetchMetadata();\n }, [fetchMetadata]);\n\n return {\n data,\n isLoading,\n error,\n refetch,\n etag,\n fromCache\n };\n}\n\n/**\n * Hook for fetching view configuration\n * \n * @example\n * ```tsx\n * function ViewConfiguration({ objectName }: { objectName: string }) {\n * const { data: view, isLoading } = useView(objectName, 'list');\n * \n * if (isLoading) return <div>Loading view...</div>;\n * \n * return (\n * <div>\n * <h3>List View for {objectName}</h3>\n * <p>Columns: {view?.columns?.length}</p>\n * </div>\n * );\n * }\n * ```\n */\nexport function useView(\n objectName: string,\n viewType: 'list' | 'form' = 'list',\n options: UseMetadataOptions = {}\n): UseMetadataResult {\n const client = useClient();\n const [data, setData] = useState<any>(null);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n\n const { enabled = true, onSuccess, onError } = options;\n\n const fetchView = useCallback(async () => {\n if (!enabled) return;\n\n try {\n setIsLoading(true);\n setError(null);\n\n const result = await client.meta.getView(objectName, viewType);\n setData(result);\n onSuccess?.(result);\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Failed to fetch view configuration');\n setError(error);\n onError?.(error);\n } finally {\n setIsLoading(false);\n }\n }, [client, objectName, viewType, enabled, onSuccess, onError]);\n\n useEffect(() => {\n fetchView();\n }, [fetchView]);\n\n const refetch = useCallback(async () => {\n await fetchView();\n }, [fetchView]);\n\n return {\n data,\n isLoading,\n error,\n refetch,\n fromCache: false\n };\n}\n\n/**\n * Hook for extracting fields from object schema\n * \n * @example\n * ```tsx\n * function FieldList({ objectName }: { objectName: string }) {\n * const { data: fields, isLoading } = useFields(objectName);\n * \n * if (isLoading) return <div>Loading fields...</div>;\n * \n * return (\n * <ul>\n * {fields?.map(field => (\n * <li key={field.name}>{field.label} ({field.type})</li>\n * ))}\n * </ul>\n * );\n * }\n * ```\n */\nexport function useFields(\n objectName: string,\n options: UseMetadataOptions = {}\n): UseMetadataResult<any[]> {\n const objectResult = useObject(objectName, options);\n\n const fields = objectResult.data?.fields\n ? Object.entries(objectResult.data.fields).map(([name, field]: [string, any]) => ({\n name,\n ...field\n }))\n : null;\n\n return {\n ...objectResult,\n data: fields\n };\n}\n\n/**\n * Generic metadata hook for custom metadata queries\n * \n * @example\n * ```tsx\n * function CustomMetadata() {\n * const { data, isLoading } = useMetadata(async (client) => {\n * // Custom metadata fetching logic\n * const object = await client.meta.getObject('custom_object');\n * const view = await client.meta.getView('custom_object', 'list');\n * return { object, view };\n * });\n * \n * return <pre>{JSON.stringify(data, null, 2)}</pre>;\n * }\n * ```\n */\nexport function useMetadata<T = any>(\n fetcher: (client: ReturnType<typeof useClient>) => Promise<T>,\n options: Omit<UseMetadataOptions, 'useCache' | 'ifNoneMatch' | 'ifModifiedSince'> = {}\n): UseMetadataResult<T> {\n const client = useClient();\n const [data, setData] = useState<T | null>(null);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n\n const { enabled = true, onSuccess, onError } = options;\n\n const fetchMetadata = useCallback(async () => {\n if (!enabled) return;\n\n try {\n setIsLoading(true);\n setError(null);\n\n const result = await fetcher(client);\n setData(result);\n onSuccess?.(result);\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Failed to fetch metadata');\n setError(error);\n onError?.(error);\n } finally {\n setIsLoading(false);\n }\n }, [client, fetcher, enabled, onSuccess, onError]);\n\n useEffect(() => {\n fetchMetadata();\n }, [fetchMetadata]);\n\n const refetch = useCallback(async () => {\n await fetchMetadata();\n }, [fetchMetadata]);\n\n return {\n data,\n isLoading,\n error,\n refetch,\n fromCache: false\n };\n}\n"],"mappings":"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","names":["import_react","error","import_react","error"]}
|
package/dist/index.mjs
CHANGED
|
@@ -26,6 +26,13 @@ function useQuery(object, options = {}) {
|
|
|
26
26
|
const intervalRef = useRef(void 0);
|
|
27
27
|
const {
|
|
28
28
|
query,
|
|
29
|
+
// Canonical names take precedence over legacy names
|
|
30
|
+
where,
|
|
31
|
+
fields,
|
|
32
|
+
orderBy,
|
|
33
|
+
limit,
|
|
34
|
+
offset,
|
|
35
|
+
// Legacy names (deprecated fallbacks)
|
|
29
36
|
select,
|
|
30
37
|
filters,
|
|
31
38
|
sort,
|
|
@@ -36,6 +43,11 @@ function useQuery(object, options = {}) {
|
|
|
36
43
|
onSuccess,
|
|
37
44
|
onError
|
|
38
45
|
} = options;
|
|
46
|
+
const resolvedFields = fields ?? select;
|
|
47
|
+
const resolvedWhere = where ?? filters;
|
|
48
|
+
const resolvedSort = orderBy ?? sort;
|
|
49
|
+
const resolvedLimit = limit ?? top;
|
|
50
|
+
const resolvedOffset = offset ?? skip;
|
|
39
51
|
const fetchData = useCallback(async (isRefetch = false) => {
|
|
40
52
|
if (!enabled) return;
|
|
41
53
|
try {
|
|
@@ -50,11 +62,11 @@ function useQuery(object, options = {}) {
|
|
|
50
62
|
result = await client.data.query(object, query);
|
|
51
63
|
} else {
|
|
52
64
|
result = await client.data.find(object, {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
65
|
+
where: resolvedWhere,
|
|
66
|
+
fields: resolvedFields,
|
|
67
|
+
orderBy: resolvedSort,
|
|
68
|
+
limit: resolvedLimit,
|
|
69
|
+
offset: resolvedOffset
|
|
58
70
|
});
|
|
59
71
|
}
|
|
60
72
|
setData(result);
|
|
@@ -67,7 +79,7 @@ function useQuery(object, options = {}) {
|
|
|
67
79
|
setIsLoading(false);
|
|
68
80
|
setIsRefetching(false);
|
|
69
81
|
}
|
|
70
|
-
}, [client, object, query,
|
|
82
|
+
}, [client, object, query, resolvedFields, resolvedWhere, resolvedSort, resolvedLimit, resolvedOffset, enabled, onSuccess, onError]);
|
|
71
83
|
useEffect(() => {
|
|
72
84
|
fetchData();
|
|
73
85
|
}, [fetchData]);
|
|
@@ -170,8 +182,8 @@ function usePagination(object, options = {}) {
|
|
|
170
182
|
const [page, setPage] = useState(initialPage);
|
|
171
183
|
const queryResult = useQuery(object, {
|
|
172
184
|
...queryOptions,
|
|
173
|
-
|
|
174
|
-
|
|
185
|
+
limit: pageSize,
|
|
186
|
+
offset: (page - 1) * pageSize
|
|
175
187
|
});
|
|
176
188
|
const totalCount = queryResult.data?.total || 0;
|
|
177
189
|
const totalPages = Math.ceil(totalCount / pageSize);
|
|
@@ -209,6 +221,11 @@ function useInfiniteQuery(object, options = {}) {
|
|
|
209
221
|
pageSize = 20,
|
|
210
222
|
// getNextPageParam is reserved for future use
|
|
211
223
|
query,
|
|
224
|
+
// Canonical names take precedence over legacy names
|
|
225
|
+
where,
|
|
226
|
+
fields,
|
|
227
|
+
orderBy,
|
|
228
|
+
// Legacy names (deprecated fallbacks)
|
|
212
229
|
select,
|
|
213
230
|
filters,
|
|
214
231
|
sort,
|
|
@@ -216,6 +233,9 @@ function useInfiniteQuery(object, options = {}) {
|
|
|
216
233
|
onSuccess,
|
|
217
234
|
onError
|
|
218
235
|
} = options;
|
|
236
|
+
const resolvedFields = fields ?? select;
|
|
237
|
+
const resolvedWhere = where ?? filters;
|
|
238
|
+
const resolvedSort = orderBy ?? sort;
|
|
219
239
|
const [pages, setPages] = useState([]);
|
|
220
240
|
const [isLoading, setIsLoading] = useState(true);
|
|
221
241
|
const [isFetchingNextPage, setIsFetchingNextPage] = useState(false);
|
|
@@ -238,11 +258,11 @@ function useInfiniteQuery(object, options = {}) {
|
|
|
238
258
|
});
|
|
239
259
|
} else {
|
|
240
260
|
result = await client.data.find(object, {
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
skip
|
|
261
|
+
where: resolvedWhere,
|
|
262
|
+
fields: resolvedFields,
|
|
263
|
+
orderBy: resolvedSort,
|
|
264
|
+
limit: pageSize,
|
|
265
|
+
offset: skip
|
|
246
266
|
});
|
|
247
267
|
}
|
|
248
268
|
if (isNextPage) {
|
|
@@ -262,7 +282,7 @@ function useInfiniteQuery(object, options = {}) {
|
|
|
262
282
|
setIsLoading(false);
|
|
263
283
|
setIsFetchingNextPage(false);
|
|
264
284
|
}
|
|
265
|
-
}, [client, object, query,
|
|
285
|
+
}, [client, object, query, resolvedFields, resolvedWhere, resolvedSort, pageSize, onSuccess, onError]);
|
|
266
286
|
useEffect(() => {
|
|
267
287
|
if (enabled) {
|
|
268
288
|
fetchPage(0);
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/context.tsx","../src/data-hooks.tsx","../src/metadata-hooks.tsx","../src/index.tsx"],"sourcesContent":["// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * ObjectStack React Context\n * \n * Provides ObjectStackClient instance to React components via Context API\n */\n\nimport * as React from 'react';\nimport { createContext, useContext, ReactNode } from 'react';\nimport { ObjectStackClient } from '@objectstack/client';\n\nexport interface ObjectStackProviderProps {\n client: ObjectStackClient;\n children: ReactNode;\n}\n\nexport const ObjectStackContext = createContext<ObjectStackClient | null>(null);\n\n/**\n * Provider component that makes ObjectStackClient available to all child components\n * \n * @example\n * ```tsx\n * const client = new ObjectStackClient({ baseUrl: 'http://localhost:3000' });\n * \n * function App() {\n * return (\n * <ObjectStackProvider client={client}>\n * <YourComponents />\n * </ObjectStackProvider>\n * );\n * }\n * ```\n */\nexport function ObjectStackProvider({ client, children }: ObjectStackProviderProps) {\n return (\n <ObjectStackContext.Provider value={client}>\n {children}\n </ObjectStackContext.Provider>\n );\n}\n\n/**\n * Hook to access the ObjectStackClient instance from context\n * \n * @throws Error if used outside of ObjectStackProvider\n * \n * @example\n * ```tsx\n * function MyComponent() {\n * const client = useClient();\n * // Use client.data.find(), etc.\n * }\n * ```\n */\nexport function useClient(): ObjectStackClient {\n const client = useContext(ObjectStackContext);\n \n if (!client) {\n throw new Error(\n 'useClient must be used within an ObjectStackProvider. ' +\n 'Make sure your component is wrapped with <ObjectStackProvider client={...}>.'\n );\n }\n \n return client;\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Data Query Hooks\n * \n * React hooks for querying and mutating ObjectStack data\n */\n\nimport { useState, useEffect, useCallback, useRef } from 'react';\nimport { QueryAST, FilterCondition } from '@objectstack/spec/data';\nimport { PaginatedResult } from '@objectstack/client';\nimport { useClient } from './context';\n\n/**\n * Query options for useQuery hook\n */\nexport interface UseQueryOptions<T = any> {\n /** Query AST or simplified query options */\n query?: Partial<QueryAST>;\n /** Simple field selection */\n select?: string[];\n /** Simple filters */\n filters?: FilterCondition;\n /** Sort configuration */\n sort?: string | string[];\n /** Limit results */\n top?: number;\n /** Skip results (for pagination) */\n skip?: number;\n /** Enable/disable automatic query execution */\n enabled?: boolean;\n /** Refetch interval in milliseconds */\n refetchInterval?: number;\n /** Callback on successful query */\n onSuccess?: (data: PaginatedResult<T>) => void;\n /** Callback on error */\n onError?: (error: Error) => void;\n}\n\n/**\n * Query result for useQuery hook\n */\nexport interface UseQueryResult<T = any> {\n /** Query result data */\n data: PaginatedResult<T> | null;\n /** Loading state */\n isLoading: boolean;\n /** Error state */\n error: Error | null;\n /** Refetch the query */\n refetch: () => Promise<void>;\n /** Is currently refetching */\n isRefetching: boolean;\n}\n\n/**\n * Hook for querying ObjectStack data with automatic caching and refetching\n * \n * @example\n * ```tsx\n * function TaskList() {\n * const { data, isLoading, error, refetch } = useQuery('todo_task', {\n * select: ['id', 'subject', 'priority'],\n * sort: ['-created_at'],\n * top: 20\n * });\n * \n * if (isLoading) return <div>Loading...</div>;\n * if (error) return <div>Error: {error.message}</div>;\n * \n * return (\n * <div>\n * {data?.value.map(task => (\n * <div key={task.id}>{task.subject}</div>\n * ))}\n * </div>\n * );\n * }\n * ```\n */\nexport function useQuery<T = any>(\n object: string,\n options: UseQueryOptions<T> = {}\n): UseQueryResult<T> {\n const client = useClient();\n const [data, setData] = useState<PaginatedResult<T> | null>(null);\n const [isLoading, setIsLoading] = useState(true);\n const [isRefetching, setIsRefetching] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const intervalRef = useRef<NodeJS.Timeout | undefined>(undefined);\n \n const {\n query,\n select,\n filters,\n sort,\n top,\n skip,\n enabled = true,\n refetchInterval,\n onSuccess,\n onError\n } = options;\n\n const fetchData = useCallback(async (isRefetch = false) => {\n if (!enabled) return;\n \n try {\n if (isRefetch) {\n setIsRefetching(true);\n } else {\n setIsLoading(true);\n }\n setError(null);\n\n let result: PaginatedResult<T>;\n \n if (query) {\n // Use advanced query API\n result = await client.data.query<T>(object, query);\n } else {\n // Use simplified find API\n result = await client.data.find<T>(object, {\n select,\n filters: filters as any,\n sort,\n top,\n skip\n });\n }\n\n setData(result);\n onSuccess?.(result);\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Query failed');\n setError(error);\n onError?.(error);\n } finally {\n setIsLoading(false);\n setIsRefetching(false);\n }\n }, [client, object, query, select, filters, sort, top, skip, enabled, onSuccess, onError]);\n\n // Initial fetch and dependency-based refetch\n useEffect(() => {\n fetchData();\n }, [fetchData]);\n\n // Setup refetch interval\n useEffect(() => {\n if (refetchInterval && enabled) {\n intervalRef.current = setInterval(() => {\n fetchData(true);\n }, refetchInterval);\n\n return () => {\n if (intervalRef.current) {\n clearInterval(intervalRef.current);\n }\n };\n }\n return undefined;\n }, [refetchInterval, enabled, fetchData]);\n\n const refetch = useCallback(async () => {\n await fetchData(true);\n }, [fetchData]);\n\n return {\n data,\n isLoading,\n error,\n refetch,\n isRefetching\n };\n}\n\n/**\n * Mutation options for useMutation hook\n */\nexport interface UseMutationOptions<TData = any, TVariables = any> {\n /** Callback on successful mutation */\n onSuccess?: (data: TData, variables: TVariables) => void;\n /** Callback on error */\n onError?: (error: Error, variables: TVariables) => void;\n /** Callback when mutation is settled (success or error) */\n onSettled?: (data: TData | undefined, error: Error | null, variables: TVariables) => void;\n}\n\n/**\n * Mutation result for useMutation hook\n */\nexport interface UseMutationResult<TData = any, TVariables = any> {\n /** Execute the mutation */\n mutate: (variables: TVariables) => Promise<TData>;\n /** Async version of mutate that throws errors */\n mutateAsync: (variables: TVariables) => Promise<TData>;\n /** Mutation result data */\n data: TData | null;\n /** Loading state */\n isLoading: boolean;\n /** Error state */\n error: Error | null;\n /** Reset mutation state */\n reset: () => void;\n}\n\n/**\n * Hook for creating, updating, or deleting ObjectStack data\n * \n * @example\n * ```tsx\n * function CreateTaskForm() {\n * const { mutate, isLoading, error } = useMutation('todo_task', 'create', {\n * onSuccess: (data) => {\n * console.log('Task created:', data);\n * }\n * });\n * \n * const handleSubmit = (formData) => {\n * mutate(formData);\n * };\n * \n * return <form onSubmit={handleSubmit}>...</form>;\n * }\n * ```\n */\nexport function useMutation<TData = any, TVariables = any>(\n object: string,\n operation: 'create' | 'update' | 'delete' | 'createMany' | 'updateMany' | 'deleteMany',\n options: UseMutationOptions<TData, TVariables> = {}\n): UseMutationResult<TData, TVariables> {\n const client = useClient();\n const [data, setData] = useState<TData | null>(null);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const { onSuccess, onError, onSettled } = options;\n\n const mutateAsync = useCallback(async (variables: TVariables): Promise<TData> => {\n setIsLoading(true);\n setError(null);\n\n try {\n let result: TData;\n\n switch (operation) {\n case 'create':\n result = (await client.data.create(object, variables as any)) as TData;\n break;\n case 'update':\n // Expect variables to be { id: string, data: Partial<T> }\n const updateVars = variables as any;\n result = (await client.data.update(object, updateVars.id, updateVars.data)) as TData;\n break;\n case 'delete':\n // Expect variables to be { id: string }\n const deleteVars = variables as any;\n result = await client.data.delete(object, deleteVars.id) as any;\n break;\n case 'createMany':\n // createMany returns an array, which may not match TData type\n result = await client.data.createMany(object, variables as any) as any;\n break;\n case 'updateMany':\n // Expect variables to be { records: Array<{ id: string, data: Partial<T> }> }\n const updateManyVars = variables as any;\n result = await client.data.updateMany(object, updateManyVars.records, updateManyVars.options) as any;\n break;\n case 'deleteMany':\n // Expect variables to be { ids: string[] }\n const deleteManyVars = variables as any;\n result = await client.data.deleteMany(object, deleteManyVars.ids, deleteManyVars.options) as any;\n break;\n default:\n throw new Error(`Unknown operation: ${operation}`);\n }\n\n setData(result);\n onSuccess?.(result, variables);\n onSettled?.(result, null, variables);\n \n return result;\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Mutation failed');\n setError(error);\n onError?.(error, variables);\n onSettled?.(undefined, error, variables);\n throw error;\n } finally {\n setIsLoading(false);\n }\n }, [client, object, operation, onSuccess, onError, onSettled]);\n\n const mutate = useCallback((variables: TVariables): Promise<TData> => {\n return mutateAsync(variables).catch(() => {\n // Swallow error for non-async version\n // Error is still available in the error state\n return null as any;\n });\n }, [mutateAsync]);\n\n const reset = useCallback(() => {\n setData(null);\n setError(null);\n setIsLoading(false);\n }, []);\n\n return {\n mutate,\n mutateAsync,\n data,\n isLoading,\n error,\n reset\n };\n}\n\n/**\n * Pagination options for usePagination hook\n */\nexport interface UsePaginationOptions<T = any> extends Omit<UseQueryOptions<T>, 'top' | 'skip'> {\n /** Page size */\n pageSize?: number;\n /** Initial page (1-based) */\n initialPage?: number;\n}\n\n/**\n * Pagination result for usePagination hook\n */\nexport interface UsePaginationResult<T = any> extends UseQueryResult<T> {\n /** Current page (1-based) */\n page: number;\n /** Total number of pages */\n totalPages: number;\n /** Total number of records */\n totalCount: number;\n /** Go to next page */\n nextPage: () => void;\n /** Go to previous page */\n previousPage: () => void;\n /** Go to specific page */\n goToPage: (page: number) => void;\n /** Whether there is a next page */\n hasNextPage: boolean;\n /** Whether there is a previous page */\n hasPreviousPage: boolean;\n}\n\n/**\n * Hook for paginated data queries\n * \n * @example\n * ```tsx\n * function PaginatedTaskList() {\n * const {\n * data,\n * isLoading,\n * page,\n * totalPages,\n * nextPage,\n * previousPage,\n * hasNextPage,\n * hasPreviousPage\n * } = usePagination('todo_task', {\n * pageSize: 10,\n * sort: ['-created_at']\n * });\n * \n * return (\n * <div>\n * {data?.value.map(task => <div key={task.id}>{task.subject}</div>)}\n * <button onClick={previousPage} disabled={!hasPreviousPage}>Previous</button>\n * <span>Page {page} of {totalPages}</span>\n * <button onClick={nextPage} disabled={!hasNextPage}>Next</button>\n * </div>\n * );\n * }\n * ```\n */\nexport function usePagination<T = any>(\n object: string,\n options: UsePaginationOptions<T> = {}\n): UsePaginationResult<T> {\n const { pageSize = 20, initialPage = 1, ...queryOptions } = options;\n const [page, setPage] = useState(initialPage);\n\n const queryResult = useQuery<T>(object, {\n ...queryOptions,\n top: pageSize,\n skip: (page - 1) * pageSize\n });\n\n const totalCount = queryResult.data?.total || 0;\n const totalPages = Math.ceil(totalCount / pageSize);\n const hasNextPage = page < totalPages;\n const hasPreviousPage = page > 1;\n\n const nextPage = useCallback(() => {\n if (hasNextPage) {\n setPage(p => p + 1);\n }\n }, [hasNextPage]);\n\n const previousPage = useCallback(() => {\n if (hasPreviousPage) {\n setPage(p => p - 1);\n }\n }, [hasPreviousPage]);\n\n const goToPage = useCallback((newPage: number) => {\n const clampedPage = Math.max(1, Math.min(newPage, totalPages));\n setPage(clampedPage);\n }, [totalPages]);\n\n return {\n ...queryResult,\n page,\n totalPages,\n totalCount,\n nextPage,\n previousPage,\n goToPage,\n hasNextPage,\n hasPreviousPage\n };\n}\n\n/**\n * Infinite query options for useInfiniteQuery hook\n */\nexport interface UseInfiniteQueryOptions<T = any> extends Omit<UseQueryOptions<T>, 'skip'> {\n /** Page size for each fetch */\n pageSize?: number;\n /** Get next page parameter */\n getNextPageParam?: (lastPage: PaginatedResult<T>, allPages: PaginatedResult<T>[]) => number | undefined;\n}\n\n/**\n * Infinite query result for useInfiniteQuery hook\n */\nexport interface UseInfiniteQueryResult<T = any> {\n /** All pages of data */\n data: PaginatedResult<T>[];\n /** Flattened data from all pages */\n flatData: T[];\n /** Loading state */\n isLoading: boolean;\n /** Error state */\n error: Error | null;\n /** Load the next page */\n fetchNextPage: () => Promise<void>;\n /** Whether there are more pages */\n hasNextPage: boolean;\n /** Is currently fetching next page */\n isFetchingNextPage: boolean;\n /** Refetch all pages */\n refetch: () => Promise<void>;\n}\n\n/**\n * Hook for infinite scrolling / load more functionality\n * \n * @example\n * ```tsx\n * function InfiniteTaskList() {\n * const {\n * flatData,\n * isLoading,\n * fetchNextPage,\n * hasNextPage,\n * isFetchingNextPage\n * } = useInfiniteQuery('todo_task', {\n * pageSize: 20,\n * sort: ['-created_at']\n * });\n * \n * return (\n * <div>\n * {flatData.map(task => <div key={task.id}>{task.subject}</div>)}\n * {hasNextPage && (\n * <button onClick={fetchNextPage} disabled={isFetchingNextPage}>\n * {isFetchingNextPage ? 'Loading...' : 'Load More'}\n * </button>\n * )}\n * </div>\n * );\n * }\n * ```\n */\nexport function useInfiniteQuery<T = any>(\n object: string,\n options: UseInfiniteQueryOptions<T> = {}\n): UseInfiniteQueryResult<T> {\n const client = useClient();\n const {\n pageSize = 20,\n // getNextPageParam is reserved for future use\n query,\n select,\n filters,\n sort,\n enabled = true,\n onSuccess,\n onError\n } = options;\n\n const [pages, setPages] = useState<PaginatedResult<T>[]>([]);\n const [isLoading, setIsLoading] = useState(true);\n const [isFetchingNextPage, setIsFetchingNextPage] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const [hasNextPage, setHasNextPage] = useState(true);\n\n const fetchPage = useCallback(async (skip: number, isNextPage = false) => {\n try {\n if (isNextPage) {\n setIsFetchingNextPage(true);\n } else {\n setIsLoading(true);\n }\n setError(null);\n\n let result: PaginatedResult<T>;\n\n if (query) {\n result = await client.data.query<T>(object, {\n ...query,\n limit: pageSize,\n offset: skip\n });\n } else {\n result = await client.data.find<T>(object, {\n select,\n filters: filters as any,\n sort,\n top: pageSize,\n skip\n });\n }\n\n if (isNextPage) {\n setPages(prev => [...prev, result]);\n } else {\n setPages([result]);\n }\n\n // Determine if there's a next page\n const fetchedCount = result.records?.length ?? 0;\n const hasMore = fetchedCount === pageSize;\n setHasNextPage(hasMore);\n\n onSuccess?.(result);\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Query failed');\n setError(error);\n onError?.(error);\n } finally {\n setIsLoading(false);\n setIsFetchingNextPage(false);\n }\n }, [client, object, query, select, filters, sort, pageSize, onSuccess, onError]);\n\n // Initial fetch\n useEffect(() => {\n if (enabled) {\n fetchPage(0);\n }\n }, [enabled, fetchPage]);\n\n const fetchNextPage = useCallback(async () => {\n if (!hasNextPage || isFetchingNextPage) return;\n\n const nextSkip = pages.length * pageSize;\n await fetchPage(nextSkip, true);\n }, [hasNextPage, isFetchingNextPage, pages.length, pageSize, fetchPage]);\n\n const refetch = useCallback(async () => {\n setPages([]);\n await fetchPage(0);\n }, [fetchPage]);\n\n const flatData = pages.flatMap(page => page.records ?? []);\n\n return {\n data: pages,\n flatData,\n isLoading,\n error,\n fetchNextPage,\n hasNextPage,\n isFetchingNextPage,\n refetch\n };\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Metadata Hooks\n * \n * React hooks for accessing ObjectStack metadata (schemas, views, fields)\n */\n\nimport { useState, useEffect, useCallback } from 'react';\nimport { useClient } from './context';\n\n/**\n * Metadata query options\n */\nexport interface UseMetadataOptions {\n /** Enable/disable automatic query execution */\n enabled?: boolean;\n /** Use cached metadata if available */\n useCache?: boolean;\n /** ETag for conditional requests */\n ifNoneMatch?: string;\n /** If-Modified-Since header for conditional requests */\n ifModifiedSince?: string;\n /** Callback on successful query */\n onSuccess?: (data: any) => void;\n /** Callback on error */\n onError?: (error: Error) => void;\n}\n\n/**\n * Metadata query result\n */\nexport interface UseMetadataResult<T = any> {\n /** Metadata data */\n data: T | null;\n /** Loading state */\n isLoading: boolean;\n /** Error state */\n error: Error | null;\n /** Refetch the metadata */\n refetch: () => Promise<void>;\n /** ETag from last fetch */\n etag?: string;\n /** Whether data came from cache (304 Not Modified) */\n fromCache: boolean;\n}\n\n/**\n * Hook for fetching object schema/metadata\n * \n * @example\n * ```tsx\n * function ObjectSchemaViewer({ objectName }: { objectName: string }) {\n * const { data: schema, isLoading, error } = useObject(objectName);\n * \n * if (isLoading) return <div>Loading schema...</div>;\n * if (error) return <div>Error: {error.message}</div>;\n * \n * return (\n * <div>\n * <h2>{schema.label}</h2>\n * <p>Fields: {Object.keys(schema.fields).length}</p>\n * </div>\n * );\n * }\n * ```\n */\nexport function useObject(\n objectName: string,\n options: UseMetadataOptions = {}\n): UseMetadataResult {\n const client = useClient();\n const [data, setData] = useState<any>(null);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n const [etag, setEtag] = useState<string>();\n const [fromCache, setFromCache] = useState(false);\n\n const {\n enabled = true,\n useCache = true,\n ifNoneMatch,\n ifModifiedSince,\n onSuccess,\n onError\n } = options;\n\n const fetchMetadata = useCallback(async () => {\n if (!enabled) return;\n\n try {\n setIsLoading(true);\n setError(null);\n setFromCache(false);\n\n if (useCache) {\n // Use cached metadata endpoint\n const result = await client.meta.getCached(objectName, {\n ifNoneMatch: ifNoneMatch || etag,\n ifModifiedSince\n });\n\n if (result.notModified) {\n setFromCache(true);\n } else {\n setData(result.data);\n if (result.etag) {\n setEtag(result.etag.value);\n }\n }\n\n onSuccess?.(result.data || data);\n } else {\n // Direct fetch without cache\n const result = await client.meta.getItem('object', objectName);\n setData(result);\n onSuccess?.(result);\n }\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Failed to fetch object metadata');\n setError(error);\n onError?.(error);\n } finally {\n setIsLoading(false);\n }\n }, [client, objectName, enabled, useCache, ifNoneMatch, ifModifiedSince, etag, data, onSuccess, onError]);\n\n useEffect(() => {\n fetchMetadata();\n }, [fetchMetadata]);\n\n const refetch = useCallback(async () => {\n await fetchMetadata();\n }, [fetchMetadata]);\n\n return {\n data,\n isLoading,\n error,\n refetch,\n etag,\n fromCache\n };\n}\n\n/**\n * Hook for fetching view configuration\n * \n * @example\n * ```tsx\n * function ViewConfiguration({ objectName }: { objectName: string }) {\n * const { data: view, isLoading } = useView(objectName, 'list');\n * \n * if (isLoading) return <div>Loading view...</div>;\n * \n * return (\n * <div>\n * <h3>List View for {objectName}</h3>\n * <p>Columns: {view?.columns?.length}</p>\n * </div>\n * );\n * }\n * ```\n */\nexport function useView(\n objectName: string,\n viewType: 'list' | 'form' = 'list',\n options: UseMetadataOptions = {}\n): UseMetadataResult {\n const client = useClient();\n const [data, setData] = useState<any>(null);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n\n const { enabled = true, onSuccess, onError } = options;\n\n const fetchView = useCallback(async () => {\n if (!enabled) return;\n\n try {\n setIsLoading(true);\n setError(null);\n\n const result = await client.meta.getView(objectName, viewType);\n setData(result);\n onSuccess?.(result);\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Failed to fetch view configuration');\n setError(error);\n onError?.(error);\n } finally {\n setIsLoading(false);\n }\n }, [client, objectName, viewType, enabled, onSuccess, onError]);\n\n useEffect(() => {\n fetchView();\n }, [fetchView]);\n\n const refetch = useCallback(async () => {\n await fetchView();\n }, [fetchView]);\n\n return {\n data,\n isLoading,\n error,\n refetch,\n fromCache: false\n };\n}\n\n/**\n * Hook for extracting fields from object schema\n * \n * @example\n * ```tsx\n * function FieldList({ objectName }: { objectName: string }) {\n * const { data: fields, isLoading } = useFields(objectName);\n * \n * if (isLoading) return <div>Loading fields...</div>;\n * \n * return (\n * <ul>\n * {fields?.map(field => (\n * <li key={field.name}>{field.label} ({field.type})</li>\n * ))}\n * </ul>\n * );\n * }\n * ```\n */\nexport function useFields(\n objectName: string,\n options: UseMetadataOptions = {}\n): UseMetadataResult<any[]> {\n const objectResult = useObject(objectName, options);\n\n const fields = objectResult.data?.fields\n ? Object.entries(objectResult.data.fields).map(([name, field]: [string, any]) => ({\n name,\n ...field\n }))\n : null;\n\n return {\n ...objectResult,\n data: fields\n };\n}\n\n/**\n * Generic metadata hook for custom metadata queries\n * \n * @example\n * ```tsx\n * function CustomMetadata() {\n * const { data, isLoading } = useMetadata(async (client) => {\n * // Custom metadata fetching logic\n * const object = await client.meta.getObject('custom_object');\n * const view = await client.meta.getView('custom_object', 'list');\n * return { object, view };\n * });\n * \n * return <pre>{JSON.stringify(data, null, 2)}</pre>;\n * }\n * ```\n */\nexport function useMetadata<T = any>(\n fetcher: (client: ReturnType<typeof useClient>) => Promise<T>,\n options: Omit<UseMetadataOptions, 'useCache' | 'ifNoneMatch' | 'ifModifiedSince'> = {}\n): UseMetadataResult<T> {\n const client = useClient();\n const [data, setData] = useState<T | null>(null);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n\n const { enabled = true, onSuccess, onError } = options;\n\n const fetchMetadata = useCallback(async () => {\n if (!enabled) return;\n\n try {\n setIsLoading(true);\n setError(null);\n\n const result = await fetcher(client);\n setData(result);\n onSuccess?.(result);\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Failed to fetch metadata');\n setError(error);\n onError?.(error);\n } finally {\n setIsLoading(false);\n }\n }, [client, fetcher, enabled, onSuccess, onError]);\n\n useEffect(() => {\n fetchMetadata();\n }, [fetchMetadata]);\n\n const refetch = useCallback(async () => {\n await fetchMetadata();\n }, [fetchMetadata]);\n\n return {\n data,\n isLoading,\n error,\n refetch,\n fromCache: false\n };\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * @objectstack/client-react\n * \n * React hooks for ObjectStack Client SDK\n * \n * Provides type-safe React hooks for:\n * - Data queries (useQuery, useMutation, usePagination, useInfiniteQuery)\n * - Metadata access (useObject, useView, useFields, useMetadata)\n * - Client context (ObjectStackProvider, useClient)\n */\n\n// Context & Provider\nexport {\n ObjectStackProvider,\n ObjectStackContext,\n useClient,\n type ObjectStackProviderProps\n} from './context';\n\n// Data Hooks\nexport {\n useQuery,\n useMutation,\n usePagination,\n useInfiniteQuery,\n type UseQueryOptions,\n type UseQueryResult,\n type UseMutationOptions,\n type UseMutationResult,\n type UsePaginationOptions,\n type UsePaginationResult,\n type UseInfiniteQueryOptions,\n type UseInfiniteQueryResult\n} from './data-hooks';\n\n// Metadata Hooks\nexport {\n useObject,\n useView,\n useFields,\n useMetadata,\n type UseMetadataOptions,\n type UseMetadataResult\n} from './metadata-hooks';\n\n// Re-export ObjectStackClient and types from @objectstack/client\nexport { ObjectStackClient, type ClientConfig } from '@objectstack/client';\n"],"mappings":"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","names":["error","useState","useEffect","useCallback","useState","useCallback","error","useEffect"]}
|
|
1
|
+
{"version":3,"sources":["../src/context.tsx","../src/data-hooks.tsx","../src/metadata-hooks.tsx","../src/index.tsx"],"sourcesContent":["// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * ObjectStack React Context\n * \n * Provides ObjectStackClient instance to React components via Context API\n */\n\nimport * as React from 'react';\nimport { createContext, useContext, ReactNode } from 'react';\nimport { ObjectStackClient } from '@objectstack/client';\n\nexport interface ObjectStackProviderProps {\n client: ObjectStackClient;\n children: ReactNode;\n}\n\nexport const ObjectStackContext = createContext<ObjectStackClient | null>(null);\n\n/**\n * Provider component that makes ObjectStackClient available to all child components\n * \n * @example\n * ```tsx\n * const client = new ObjectStackClient({ baseUrl: 'http://localhost:3000' });\n * \n * function App() {\n * return (\n * <ObjectStackProvider client={client}>\n * <YourComponents />\n * </ObjectStackProvider>\n * );\n * }\n * ```\n */\nexport function ObjectStackProvider({ client, children }: ObjectStackProviderProps) {\n return (\n <ObjectStackContext.Provider value={client}>\n {children}\n </ObjectStackContext.Provider>\n );\n}\n\n/**\n * Hook to access the ObjectStackClient instance from context\n * \n * @throws Error if used outside of ObjectStackProvider\n * \n * @example\n * ```tsx\n * function MyComponent() {\n * const client = useClient();\n * // Use client.data.find(), etc.\n * }\n * ```\n */\nexport function useClient(): ObjectStackClient {\n const client = useContext(ObjectStackContext);\n \n if (!client) {\n throw new Error(\n 'useClient must be used within an ObjectStackProvider. ' +\n 'Make sure your component is wrapped with <ObjectStackProvider client={...}>.'\n );\n }\n \n return client;\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Data Query Hooks\n * \n * React hooks for querying and mutating ObjectStack data\n */\n\nimport { useState, useEffect, useCallback, useRef } from 'react';\nimport { QueryAST, FilterCondition } from '@objectstack/spec/data';\nimport { PaginatedResult } from '@objectstack/client';\nimport { useClient } from './context';\n\n/**\n * Query options for useQuery hook\n *\n * Supports both **canonical** (Spec protocol) and **legacy** field names.\n * Canonical names are preferred; legacy names are accepted for backward\n * compatibility and will be removed in a future major release.\n *\n * | Canonical | Legacy (deprecated) |\n * |-----------|---------------------|\n * | `where` | `filters` |\n * | `fields` | `select` |\n * | `orderBy` | `sort` |\n * | `limit` | `top` |\n * | `offset` | `skip` |\n */\nexport interface UseQueryOptions<T = any> {\n /** Query AST or simplified query options */\n query?: Partial<QueryAST>;\n\n // ── Canonical (Spec protocol) field names ──────────────────────────\n /** Filter conditions (WHERE clause). */\n where?: FilterCondition;\n /** Fields to retrieve (SELECT clause). */\n fields?: string[];\n /** Sort definition (ORDER BY clause). */\n orderBy?: string | string[];\n /** Maximum number of records to return (LIMIT). */\n limit?: number;\n /** Number of records to skip (OFFSET). */\n offset?: number;\n\n // ── Legacy field names (deprecated) ────────────────────────────────\n /** @deprecated Use `fields` instead. */\n select?: string[];\n /** @deprecated Use `where` instead. */\n filters?: FilterCondition;\n /** @deprecated Use `orderBy` instead. */\n sort?: string | string[];\n /** @deprecated Use `limit` instead. */\n top?: number;\n /** @deprecated Use `offset` instead. */\n skip?: number;\n\n /** Enable/disable automatic query execution */\n enabled?: boolean;\n /** Refetch interval in milliseconds */\n refetchInterval?: number;\n /** Callback on successful query */\n onSuccess?: (data: PaginatedResult<T>) => void;\n /** Callback on error */\n onError?: (error: Error) => void;\n}\n\n/**\n * Query result for useQuery hook\n */\nexport interface UseQueryResult<T = any> {\n /** Query result data */\n data: PaginatedResult<T> | null;\n /** Loading state */\n isLoading: boolean;\n /** Error state */\n error: Error | null;\n /** Refetch the query */\n refetch: () => Promise<void>;\n /** Is currently refetching */\n isRefetching: boolean;\n}\n\n/**\n * Hook for querying ObjectStack data with automatic caching and refetching\n * \n * @example\n * ```tsx\n * function TaskList() {\n * const { data, isLoading, error, refetch } = useQuery('todo_task', {\n * fields: ['id', 'subject', 'priority'],\n * orderBy: ['-created_at'],\n * limit: 20\n * });\n * \n * if (isLoading) return <div>Loading...</div>;\n * if (error) return <div>Error: {error.message}</div>;\n * \n * return (\n * <div>\n * {data?.value.map(task => (\n * <div key={task.id}>{task.subject}</div>\n * ))}\n * </div>\n * );\n * }\n * ```\n */\nexport function useQuery<T = any>(\n object: string,\n options: UseQueryOptions<T> = {}\n): UseQueryResult<T> {\n const client = useClient();\n const [data, setData] = useState<PaginatedResult<T> | null>(null);\n const [isLoading, setIsLoading] = useState(true);\n const [isRefetching, setIsRefetching] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const intervalRef = useRef<NodeJS.Timeout | undefined>(undefined);\n \n const {\n query,\n // Canonical names take precedence over legacy names\n where, fields, orderBy, limit, offset,\n // Legacy names (deprecated fallbacks)\n select, filters, sort, top, skip,\n enabled = true,\n refetchInterval,\n onSuccess,\n onError\n } = options;\n\n // Resolve canonical vs legacy: canonical wins when both are provided\n const resolvedFields = fields ?? select;\n const resolvedWhere = where ?? filters;\n const resolvedSort = orderBy ?? sort;\n const resolvedLimit = limit ?? top;\n const resolvedOffset = offset ?? skip;\n\n const fetchData = useCallback(async (isRefetch = false) => {\n if (!enabled) return;\n \n try {\n if (isRefetch) {\n setIsRefetching(true);\n } else {\n setIsLoading(true);\n }\n setError(null);\n\n let result: PaginatedResult<T>;\n \n if (query) {\n // Use advanced query API\n result = await client.data.query<T>(object, query);\n } else {\n // Use canonical QueryOptionsV2 for the find call\n result = await client.data.find<T>(object, {\n where: resolvedWhere as any,\n fields: resolvedFields,\n orderBy: resolvedSort,\n limit: resolvedLimit,\n offset: resolvedOffset,\n });\n }\n\n setData(result);\n onSuccess?.(result);\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Query failed');\n setError(error);\n onError?.(error);\n } finally {\n setIsLoading(false);\n setIsRefetching(false);\n }\n }, [client, object, query, resolvedFields, resolvedWhere, resolvedSort, resolvedLimit, resolvedOffset, enabled, onSuccess, onError]);\n\n // Initial fetch and dependency-based refetch\n useEffect(() => {\n fetchData();\n }, [fetchData]);\n\n // Setup refetch interval\n useEffect(() => {\n if (refetchInterval && enabled) {\n intervalRef.current = setInterval(() => {\n fetchData(true);\n }, refetchInterval);\n\n return () => {\n if (intervalRef.current) {\n clearInterval(intervalRef.current);\n }\n };\n }\n return undefined;\n }, [refetchInterval, enabled, fetchData]);\n\n const refetch = useCallback(async () => {\n await fetchData(true);\n }, [fetchData]);\n\n return {\n data,\n isLoading,\n error,\n refetch,\n isRefetching\n };\n}\n\n/**\n * Mutation options for useMutation hook\n */\nexport interface UseMutationOptions<TData = any, TVariables = any> {\n /** Callback on successful mutation */\n onSuccess?: (data: TData, variables: TVariables) => void;\n /** Callback on error */\n onError?: (error: Error, variables: TVariables) => void;\n /** Callback when mutation is settled (success or error) */\n onSettled?: (data: TData | undefined, error: Error | null, variables: TVariables) => void;\n}\n\n/**\n * Mutation result for useMutation hook\n */\nexport interface UseMutationResult<TData = any, TVariables = any> {\n /** Execute the mutation */\n mutate: (variables: TVariables) => Promise<TData>;\n /** Async version of mutate that throws errors */\n mutateAsync: (variables: TVariables) => Promise<TData>;\n /** Mutation result data */\n data: TData | null;\n /** Loading state */\n isLoading: boolean;\n /** Error state */\n error: Error | null;\n /** Reset mutation state */\n reset: () => void;\n}\n\n/**\n * Hook for creating, updating, or deleting ObjectStack data\n * \n * @example\n * ```tsx\n * function CreateTaskForm() {\n * const { mutate, isLoading, error } = useMutation('todo_task', 'create', {\n * onSuccess: (data) => {\n * console.log('Task created:', data);\n * }\n * });\n * \n * const handleSubmit = (formData) => {\n * mutate(formData);\n * };\n * \n * return <form onSubmit={handleSubmit}>...</form>;\n * }\n * ```\n */\nexport function useMutation<TData = any, TVariables = any>(\n object: string,\n operation: 'create' | 'update' | 'delete' | 'createMany' | 'updateMany' | 'deleteMany',\n options: UseMutationOptions<TData, TVariables> = {}\n): UseMutationResult<TData, TVariables> {\n const client = useClient();\n const [data, setData] = useState<TData | null>(null);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const { onSuccess, onError, onSettled } = options;\n\n const mutateAsync = useCallback(async (variables: TVariables): Promise<TData> => {\n setIsLoading(true);\n setError(null);\n\n try {\n let result: TData;\n\n switch (operation) {\n case 'create':\n result = (await client.data.create(object, variables as any)) as TData;\n break;\n case 'update':\n // Expect variables to be { id: string, data: Partial<T> }\n const updateVars = variables as any;\n result = (await client.data.update(object, updateVars.id, updateVars.data)) as TData;\n break;\n case 'delete':\n // Expect variables to be { id: string }\n const deleteVars = variables as any;\n result = await client.data.delete(object, deleteVars.id) as any;\n break;\n case 'createMany':\n // createMany returns an array, which may not match TData type\n result = await client.data.createMany(object, variables as any) as any;\n break;\n case 'updateMany':\n // Expect variables to be { records: Array<{ id: string, data: Partial<T> }> }\n const updateManyVars = variables as any;\n result = await client.data.updateMany(object, updateManyVars.records, updateManyVars.options) as any;\n break;\n case 'deleteMany':\n // Expect variables to be { ids: string[] }\n const deleteManyVars = variables as any;\n result = await client.data.deleteMany(object, deleteManyVars.ids, deleteManyVars.options) as any;\n break;\n default:\n throw new Error(`Unknown operation: ${operation}`);\n }\n\n setData(result);\n onSuccess?.(result, variables);\n onSettled?.(result, null, variables);\n \n return result;\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Mutation failed');\n setError(error);\n onError?.(error, variables);\n onSettled?.(undefined, error, variables);\n throw error;\n } finally {\n setIsLoading(false);\n }\n }, [client, object, operation, onSuccess, onError, onSettled]);\n\n const mutate = useCallback((variables: TVariables): Promise<TData> => {\n return mutateAsync(variables).catch(() => {\n // Swallow error for non-async version\n // Error is still available in the error state\n return null as any;\n });\n }, [mutateAsync]);\n\n const reset = useCallback(() => {\n setData(null);\n setError(null);\n setIsLoading(false);\n }, []);\n\n return {\n mutate,\n mutateAsync,\n data,\n isLoading,\n error,\n reset\n };\n}\n\n/**\n * Pagination options for usePagination hook\n */\nexport interface UsePaginationOptions<T = any> extends Omit<UseQueryOptions<T>, 'top' | 'skip' | 'limit' | 'offset'> {\n /** Page size */\n pageSize?: number;\n /** Initial page (1-based) */\n initialPage?: number;\n}\n\n/**\n * Pagination result for usePagination hook\n */\nexport interface UsePaginationResult<T = any> extends UseQueryResult<T> {\n /** Current page (1-based) */\n page: number;\n /** Total number of pages */\n totalPages: number;\n /** Total number of records */\n totalCount: number;\n /** Go to next page */\n nextPage: () => void;\n /** Go to previous page */\n previousPage: () => void;\n /** Go to specific page */\n goToPage: (page: number) => void;\n /** Whether there is a next page */\n hasNextPage: boolean;\n /** Whether there is a previous page */\n hasPreviousPage: boolean;\n}\n\n/**\n * Hook for paginated data queries\n * \n * @example\n * ```tsx\n * function PaginatedTaskList() {\n * const {\n * data,\n * isLoading,\n * page,\n * totalPages,\n * nextPage,\n * previousPage,\n * hasNextPage,\n * hasPreviousPage\n * } = usePagination('todo_task', {\n * pageSize: 10,\n * orderBy: ['-created_at']\n * });\n * \n * return (\n * <div>\n * {data?.value.map(task => <div key={task.id}>{task.subject}</div>)}\n * <button onClick={previousPage} disabled={!hasPreviousPage}>Previous</button>\n * <span>Page {page} of {totalPages}</span>\n * <button onClick={nextPage} disabled={!hasNextPage}>Next</button>\n * </div>\n * );\n * }\n * ```\n */\nexport function usePagination<T = any>(\n object: string,\n options: UsePaginationOptions<T> = {}\n): UsePaginationResult<T> {\n const { pageSize = 20, initialPage = 1, ...queryOptions } = options;\n const [page, setPage] = useState(initialPage);\n\n const queryResult = useQuery<T>(object, {\n ...queryOptions,\n limit: pageSize,\n offset: (page - 1) * pageSize\n });\n\n const totalCount = queryResult.data?.total || 0;\n const totalPages = Math.ceil(totalCount / pageSize);\n const hasNextPage = page < totalPages;\n const hasPreviousPage = page > 1;\n\n const nextPage = useCallback(() => {\n if (hasNextPage) {\n setPage(p => p + 1);\n }\n }, [hasNextPage]);\n\n const previousPage = useCallback(() => {\n if (hasPreviousPage) {\n setPage(p => p - 1);\n }\n }, [hasPreviousPage]);\n\n const goToPage = useCallback((newPage: number) => {\n const clampedPage = Math.max(1, Math.min(newPage, totalPages));\n setPage(clampedPage);\n }, [totalPages]);\n\n return {\n ...queryResult,\n page,\n totalPages,\n totalCount,\n nextPage,\n previousPage,\n goToPage,\n hasNextPage,\n hasPreviousPage\n };\n}\n\n/**\n * Infinite query options for useInfiniteQuery hook\n */\nexport interface UseInfiniteQueryOptions<T = any> extends Omit<UseQueryOptions<T>, 'skip' | 'offset'> {\n /** Page size for each fetch */\n pageSize?: number;\n /** Get next page parameter */\n getNextPageParam?: (lastPage: PaginatedResult<T>, allPages: PaginatedResult<T>[]) => number | undefined;\n}\n\n/**\n * Infinite query result for useInfiniteQuery hook\n */\nexport interface UseInfiniteQueryResult<T = any> {\n /** All pages of data */\n data: PaginatedResult<T>[];\n /** Flattened data from all pages */\n flatData: T[];\n /** Loading state */\n isLoading: boolean;\n /** Error state */\n error: Error | null;\n /** Load the next page */\n fetchNextPage: () => Promise<void>;\n /** Whether there are more pages */\n hasNextPage: boolean;\n /** Is currently fetching next page */\n isFetchingNextPage: boolean;\n /** Refetch all pages */\n refetch: () => Promise<void>;\n}\n\n/**\n * Hook for infinite scrolling / load more functionality\n * \n * @example\n * ```tsx\n * function InfiniteTaskList() {\n * const {\n * flatData,\n * isLoading,\n * fetchNextPage,\n * hasNextPage,\n * isFetchingNextPage\n * } = useInfiniteQuery('todo_task', {\n * pageSize: 20,\n * orderBy: ['-created_at']\n * });\n * \n * return (\n * <div>\n * {flatData.map(task => <div key={task.id}>{task.subject}</div>)}\n * {hasNextPage && (\n * <button onClick={fetchNextPage} disabled={isFetchingNextPage}>\n * {isFetchingNextPage ? 'Loading...' : 'Load More'}\n * </button>\n * )}\n * </div>\n * );\n * }\n * ```\n */\nexport function useInfiniteQuery<T = any>(\n object: string,\n options: UseInfiniteQueryOptions<T> = {}\n): UseInfiniteQueryResult<T> {\n const client = useClient();\n const {\n pageSize = 20,\n // getNextPageParam is reserved for future use\n query,\n // Canonical names take precedence over legacy names\n where, fields, orderBy,\n // Legacy names (deprecated fallbacks)\n select, filters, sort,\n enabled = true,\n onSuccess,\n onError\n } = options;\n\n // Resolve canonical vs legacy: canonical wins\n const resolvedFields = fields ?? select;\n const resolvedWhere = where ?? filters;\n const resolvedSort = orderBy ?? sort;\n\n const [pages, setPages] = useState<PaginatedResult<T>[]>([]);\n const [isLoading, setIsLoading] = useState(true);\n const [isFetchingNextPage, setIsFetchingNextPage] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const [hasNextPage, setHasNextPage] = useState(true);\n\n const fetchPage = useCallback(async (skip: number, isNextPage = false) => {\n try {\n if (isNextPage) {\n setIsFetchingNextPage(true);\n } else {\n setIsLoading(true);\n }\n setError(null);\n\n let result: PaginatedResult<T>;\n\n if (query) {\n result = await client.data.query<T>(object, {\n ...query,\n limit: pageSize,\n offset: skip\n });\n } else {\n result = await client.data.find<T>(object, {\n where: resolvedWhere as any,\n fields: resolvedFields,\n orderBy: resolvedSort,\n limit: pageSize,\n offset: skip,\n });\n }\n\n if (isNextPage) {\n setPages(prev => [...prev, result]);\n } else {\n setPages([result]);\n }\n\n // Determine if there's a next page\n const fetchedCount = result.records?.length ?? 0;\n const hasMore = fetchedCount === pageSize;\n setHasNextPage(hasMore);\n\n onSuccess?.(result);\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Query failed');\n setError(error);\n onError?.(error);\n } finally {\n setIsLoading(false);\n setIsFetchingNextPage(false);\n }\n }, [client, object, query, resolvedFields, resolvedWhere, resolvedSort, pageSize, onSuccess, onError]);\n\n // Initial fetch\n useEffect(() => {\n if (enabled) {\n fetchPage(0);\n }\n }, [enabled, fetchPage]);\n\n const fetchNextPage = useCallback(async () => {\n if (!hasNextPage || isFetchingNextPage) return;\n\n const nextSkip = pages.length * pageSize;\n await fetchPage(nextSkip, true);\n }, [hasNextPage, isFetchingNextPage, pages.length, pageSize, fetchPage]);\n\n const refetch = useCallback(async () => {\n setPages([]);\n await fetchPage(0);\n }, [fetchPage]);\n\n const flatData = pages.flatMap(page => page.records ?? []);\n\n return {\n data: pages,\n flatData,\n isLoading,\n error,\n fetchNextPage,\n hasNextPage,\n isFetchingNextPage,\n refetch\n };\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Metadata Hooks\n * \n * React hooks for accessing ObjectStack metadata (schemas, views, fields)\n */\n\nimport { useState, useEffect, useCallback } from 'react';\nimport { useClient } from './context';\n\n/**\n * Metadata query options\n */\nexport interface UseMetadataOptions {\n /** Enable/disable automatic query execution */\n enabled?: boolean;\n /** Use cached metadata if available */\n useCache?: boolean;\n /** ETag for conditional requests */\n ifNoneMatch?: string;\n /** If-Modified-Since header for conditional requests */\n ifModifiedSince?: string;\n /** Callback on successful query */\n onSuccess?: (data: any) => void;\n /** Callback on error */\n onError?: (error: Error) => void;\n}\n\n/**\n * Metadata query result\n */\nexport interface UseMetadataResult<T = any> {\n /** Metadata data */\n data: T | null;\n /** Loading state */\n isLoading: boolean;\n /** Error state */\n error: Error | null;\n /** Refetch the metadata */\n refetch: () => Promise<void>;\n /** ETag from last fetch */\n etag?: string;\n /** Whether data came from cache (304 Not Modified) */\n fromCache: boolean;\n}\n\n/**\n * Hook for fetching object schema/metadata\n * \n * @example\n * ```tsx\n * function ObjectSchemaViewer({ objectName }: { objectName: string }) {\n * const { data: schema, isLoading, error } = useObject(objectName);\n * \n * if (isLoading) return <div>Loading schema...</div>;\n * if (error) return <div>Error: {error.message}</div>;\n * \n * return (\n * <div>\n * <h2>{schema.label}</h2>\n * <p>Fields: {Object.keys(schema.fields).length}</p>\n * </div>\n * );\n * }\n * ```\n */\nexport function useObject(\n objectName: string,\n options: UseMetadataOptions = {}\n): UseMetadataResult {\n const client = useClient();\n const [data, setData] = useState<any>(null);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n const [etag, setEtag] = useState<string>();\n const [fromCache, setFromCache] = useState(false);\n\n const {\n enabled = true,\n useCache = true,\n ifNoneMatch,\n ifModifiedSince,\n onSuccess,\n onError\n } = options;\n\n const fetchMetadata = useCallback(async () => {\n if (!enabled) return;\n\n try {\n setIsLoading(true);\n setError(null);\n setFromCache(false);\n\n if (useCache) {\n // Use cached metadata endpoint\n const result = await client.meta.getCached(objectName, {\n ifNoneMatch: ifNoneMatch || etag,\n ifModifiedSince\n });\n\n if (result.notModified) {\n setFromCache(true);\n } else {\n setData(result.data);\n if (result.etag) {\n setEtag(result.etag.value);\n }\n }\n\n onSuccess?.(result.data || data);\n } else {\n // Direct fetch without cache\n const result = await client.meta.getItem('object', objectName);\n setData(result);\n onSuccess?.(result);\n }\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Failed to fetch object metadata');\n setError(error);\n onError?.(error);\n } finally {\n setIsLoading(false);\n }\n }, [client, objectName, enabled, useCache, ifNoneMatch, ifModifiedSince, etag, data, onSuccess, onError]);\n\n useEffect(() => {\n fetchMetadata();\n }, [fetchMetadata]);\n\n const refetch = useCallback(async () => {\n await fetchMetadata();\n }, [fetchMetadata]);\n\n return {\n data,\n isLoading,\n error,\n refetch,\n etag,\n fromCache\n };\n}\n\n/**\n * Hook for fetching view configuration\n * \n * @example\n * ```tsx\n * function ViewConfiguration({ objectName }: { objectName: string }) {\n * const { data: view, isLoading } = useView(objectName, 'list');\n * \n * if (isLoading) return <div>Loading view...</div>;\n * \n * return (\n * <div>\n * <h3>List View for {objectName}</h3>\n * <p>Columns: {view?.columns?.length}</p>\n * </div>\n * );\n * }\n * ```\n */\nexport function useView(\n objectName: string,\n viewType: 'list' | 'form' = 'list',\n options: UseMetadataOptions = {}\n): UseMetadataResult {\n const client = useClient();\n const [data, setData] = useState<any>(null);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n\n const { enabled = true, onSuccess, onError } = options;\n\n const fetchView = useCallback(async () => {\n if (!enabled) return;\n\n try {\n setIsLoading(true);\n setError(null);\n\n const result = await client.meta.getView(objectName, viewType);\n setData(result);\n onSuccess?.(result);\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Failed to fetch view configuration');\n setError(error);\n onError?.(error);\n } finally {\n setIsLoading(false);\n }\n }, [client, objectName, viewType, enabled, onSuccess, onError]);\n\n useEffect(() => {\n fetchView();\n }, [fetchView]);\n\n const refetch = useCallback(async () => {\n await fetchView();\n }, [fetchView]);\n\n return {\n data,\n isLoading,\n error,\n refetch,\n fromCache: false\n };\n}\n\n/**\n * Hook for extracting fields from object schema\n * \n * @example\n * ```tsx\n * function FieldList({ objectName }: { objectName: string }) {\n * const { data: fields, isLoading } = useFields(objectName);\n * \n * if (isLoading) return <div>Loading fields...</div>;\n * \n * return (\n * <ul>\n * {fields?.map(field => (\n * <li key={field.name}>{field.label} ({field.type})</li>\n * ))}\n * </ul>\n * );\n * }\n * ```\n */\nexport function useFields(\n objectName: string,\n options: UseMetadataOptions = {}\n): UseMetadataResult<any[]> {\n const objectResult = useObject(objectName, options);\n\n const fields = objectResult.data?.fields\n ? Object.entries(objectResult.data.fields).map(([name, field]: [string, any]) => ({\n name,\n ...field\n }))\n : null;\n\n return {\n ...objectResult,\n data: fields\n };\n}\n\n/**\n * Generic metadata hook for custom metadata queries\n * \n * @example\n * ```tsx\n * function CustomMetadata() {\n * const { data, isLoading } = useMetadata(async (client) => {\n * // Custom metadata fetching logic\n * const object = await client.meta.getObject('custom_object');\n * const view = await client.meta.getView('custom_object', 'list');\n * return { object, view };\n * });\n * \n * return <pre>{JSON.stringify(data, null, 2)}</pre>;\n * }\n * ```\n */\nexport function useMetadata<T = any>(\n fetcher: (client: ReturnType<typeof useClient>) => Promise<T>,\n options: Omit<UseMetadataOptions, 'useCache' | 'ifNoneMatch' | 'ifModifiedSince'> = {}\n): UseMetadataResult<T> {\n const client = useClient();\n const [data, setData] = useState<T | null>(null);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n\n const { enabled = true, onSuccess, onError } = options;\n\n const fetchMetadata = useCallback(async () => {\n if (!enabled) return;\n\n try {\n setIsLoading(true);\n setError(null);\n\n const result = await fetcher(client);\n setData(result);\n onSuccess?.(result);\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Failed to fetch metadata');\n setError(error);\n onError?.(error);\n } finally {\n setIsLoading(false);\n }\n }, [client, fetcher, enabled, onSuccess, onError]);\n\n useEffect(() => {\n fetchMetadata();\n }, [fetchMetadata]);\n\n const refetch = useCallback(async () => {\n await fetchMetadata();\n }, [fetchMetadata]);\n\n return {\n data,\n isLoading,\n error,\n refetch,\n fromCache: false\n };\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * @objectstack/client-react\n * \n * React hooks for ObjectStack Client SDK\n * \n * Provides type-safe React hooks for:\n * - Data queries (useQuery, useMutation, usePagination, useInfiniteQuery)\n * - Metadata access (useObject, useView, useFields, useMetadata)\n * - Client context (ObjectStackProvider, useClient)\n */\n\n// Context & Provider\nexport {\n ObjectStackProvider,\n ObjectStackContext,\n useClient,\n type ObjectStackProviderProps\n} from './context';\n\n// Data Hooks\nexport {\n useQuery,\n useMutation,\n usePagination,\n useInfiniteQuery,\n type UseQueryOptions,\n type UseQueryResult,\n type UseMutationOptions,\n type UseMutationResult,\n type UsePaginationOptions,\n type UsePaginationResult,\n type UseInfiniteQueryOptions,\n type UseInfiniteQueryResult\n} from './data-hooks';\n\n// Metadata Hooks\nexport {\n useObject,\n useView,\n useFields,\n useMetadata,\n type UseMetadataOptions,\n type UseMetadataResult\n} from './metadata-hooks';\n\n// Re-export ObjectStackClient and types from @objectstack/client\nexport { ObjectStackClient, type ClientConfig } from '@objectstack/client';\n"],"mappings":"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","names":["error","useState","useEffect","useCallback","useState","useCallback","error","useEffect"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@objectstack/client-react",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"description": "React hooks for ObjectStack Client SDK",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -16,13 +16,13 @@
|
|
|
16
16
|
"react": ">=18.0.0"
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@objectstack/client": "
|
|
20
|
-
"@objectstack/
|
|
21
|
-
"@objectstack/
|
|
19
|
+
"@objectstack/client": "4.0.0",
|
|
20
|
+
"@objectstack/core": "4.0.0",
|
|
21
|
+
"@objectstack/spec": "4.0.0"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
24
|
"@types/react": "^19.2.14",
|
|
25
|
-
"typescript": "^
|
|
25
|
+
"typescript": "^6.0.2"
|
|
26
26
|
},
|
|
27
27
|
"scripts": {
|
|
28
28
|
"build": "tsup src/index.tsx --config ../../tsup.config.ts"
|
package/src/data-hooks.tsx
CHANGED
|
@@ -13,20 +13,47 @@ import { useClient } from './context';
|
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* Query options for useQuery hook
|
|
16
|
+
*
|
|
17
|
+
* Supports both **canonical** (Spec protocol) and **legacy** field names.
|
|
18
|
+
* Canonical names are preferred; legacy names are accepted for backward
|
|
19
|
+
* compatibility and will be removed in a future major release.
|
|
20
|
+
*
|
|
21
|
+
* | Canonical | Legacy (deprecated) |
|
|
22
|
+
* |-----------|---------------------|
|
|
23
|
+
* | `where` | `filters` |
|
|
24
|
+
* | `fields` | `select` |
|
|
25
|
+
* | `orderBy` | `sort` |
|
|
26
|
+
* | `limit` | `top` |
|
|
27
|
+
* | `offset` | `skip` |
|
|
16
28
|
*/
|
|
17
29
|
export interface UseQueryOptions<T = any> {
|
|
18
30
|
/** Query AST or simplified query options */
|
|
19
31
|
query?: Partial<QueryAST>;
|
|
20
|
-
|
|
32
|
+
|
|
33
|
+
// ── Canonical (Spec protocol) field names ──────────────────────────
|
|
34
|
+
/** Filter conditions (WHERE clause). */
|
|
35
|
+
where?: FilterCondition;
|
|
36
|
+
/** Fields to retrieve (SELECT clause). */
|
|
37
|
+
fields?: string[];
|
|
38
|
+
/** Sort definition (ORDER BY clause). */
|
|
39
|
+
orderBy?: string | string[];
|
|
40
|
+
/** Maximum number of records to return (LIMIT). */
|
|
41
|
+
limit?: number;
|
|
42
|
+
/** Number of records to skip (OFFSET). */
|
|
43
|
+
offset?: number;
|
|
44
|
+
|
|
45
|
+
// ── Legacy field names (deprecated) ────────────────────────────────
|
|
46
|
+
/** @deprecated Use `fields` instead. */
|
|
21
47
|
select?: string[];
|
|
22
|
-
/**
|
|
48
|
+
/** @deprecated Use `where` instead. */
|
|
23
49
|
filters?: FilterCondition;
|
|
24
|
-
/**
|
|
50
|
+
/** @deprecated Use `orderBy` instead. */
|
|
25
51
|
sort?: string | string[];
|
|
26
|
-
/**
|
|
52
|
+
/** @deprecated Use `limit` instead. */
|
|
27
53
|
top?: number;
|
|
28
|
-
/**
|
|
54
|
+
/** @deprecated Use `offset` instead. */
|
|
29
55
|
skip?: number;
|
|
56
|
+
|
|
30
57
|
/** Enable/disable automatic query execution */
|
|
31
58
|
enabled?: boolean;
|
|
32
59
|
/** Refetch interval in milliseconds */
|
|
@@ -60,9 +87,9 @@ export interface UseQueryResult<T = any> {
|
|
|
60
87
|
* ```tsx
|
|
61
88
|
* function TaskList() {
|
|
62
89
|
* const { data, isLoading, error, refetch } = useQuery('todo_task', {
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
90
|
+
* fields: ['id', 'subject', 'priority'],
|
|
91
|
+
* orderBy: ['-created_at'],
|
|
92
|
+
* limit: 20
|
|
66
93
|
* });
|
|
67
94
|
*
|
|
68
95
|
* if (isLoading) return <div>Loading...</div>;
|
|
@@ -91,17 +118,23 @@ export function useQuery<T = any>(
|
|
|
91
118
|
|
|
92
119
|
const {
|
|
93
120
|
query,
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
top,
|
|
98
|
-
skip,
|
|
121
|
+
// Canonical names take precedence over legacy names
|
|
122
|
+
where, fields, orderBy, limit, offset,
|
|
123
|
+
// Legacy names (deprecated fallbacks)
|
|
124
|
+
select, filters, sort, top, skip,
|
|
99
125
|
enabled = true,
|
|
100
126
|
refetchInterval,
|
|
101
127
|
onSuccess,
|
|
102
128
|
onError
|
|
103
129
|
} = options;
|
|
104
130
|
|
|
131
|
+
// Resolve canonical vs legacy: canonical wins when both are provided
|
|
132
|
+
const resolvedFields = fields ?? select;
|
|
133
|
+
const resolvedWhere = where ?? filters;
|
|
134
|
+
const resolvedSort = orderBy ?? sort;
|
|
135
|
+
const resolvedLimit = limit ?? top;
|
|
136
|
+
const resolvedOffset = offset ?? skip;
|
|
137
|
+
|
|
105
138
|
const fetchData = useCallback(async (isRefetch = false) => {
|
|
106
139
|
if (!enabled) return;
|
|
107
140
|
|
|
@@ -119,13 +152,13 @@ export function useQuery<T = any>(
|
|
|
119
152
|
// Use advanced query API
|
|
120
153
|
result = await client.data.query<T>(object, query);
|
|
121
154
|
} else {
|
|
122
|
-
// Use
|
|
155
|
+
// Use canonical QueryOptionsV2 for the find call
|
|
123
156
|
result = await client.data.find<T>(object, {
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
157
|
+
where: resolvedWhere as any,
|
|
158
|
+
fields: resolvedFields,
|
|
159
|
+
orderBy: resolvedSort,
|
|
160
|
+
limit: resolvedLimit,
|
|
161
|
+
offset: resolvedOffset,
|
|
129
162
|
});
|
|
130
163
|
}
|
|
131
164
|
|
|
@@ -139,7 +172,7 @@ export function useQuery<T = any>(
|
|
|
139
172
|
setIsLoading(false);
|
|
140
173
|
setIsRefetching(false);
|
|
141
174
|
}
|
|
142
|
-
}, [client, object, query,
|
|
175
|
+
}, [client, object, query, resolvedFields, resolvedWhere, resolvedSort, resolvedLimit, resolvedOffset, enabled, onSuccess, onError]);
|
|
143
176
|
|
|
144
177
|
// Initial fetch and dependency-based refetch
|
|
145
178
|
useEffect(() => {
|
|
@@ -319,7 +352,7 @@ export function useMutation<TData = any, TVariables = any>(
|
|
|
319
352
|
/**
|
|
320
353
|
* Pagination options for usePagination hook
|
|
321
354
|
*/
|
|
322
|
-
export interface UsePaginationOptions<T = any> extends Omit<UseQueryOptions<T>, 'top' | 'skip'> {
|
|
355
|
+
export interface UsePaginationOptions<T = any> extends Omit<UseQueryOptions<T>, 'top' | 'skip' | 'limit' | 'offset'> {
|
|
323
356
|
/** Page size */
|
|
324
357
|
pageSize?: number;
|
|
325
358
|
/** Initial page (1-based) */
|
|
@@ -365,7 +398,7 @@ export interface UsePaginationResult<T = any> extends UseQueryResult<T> {
|
|
|
365
398
|
* hasPreviousPage
|
|
366
399
|
* } = usePagination('todo_task', {
|
|
367
400
|
* pageSize: 10,
|
|
368
|
-
*
|
|
401
|
+
* orderBy: ['-created_at']
|
|
369
402
|
* });
|
|
370
403
|
*
|
|
371
404
|
* return (
|
|
@@ -388,8 +421,8 @@ export function usePagination<T = any>(
|
|
|
388
421
|
|
|
389
422
|
const queryResult = useQuery<T>(object, {
|
|
390
423
|
...queryOptions,
|
|
391
|
-
|
|
392
|
-
|
|
424
|
+
limit: pageSize,
|
|
425
|
+
offset: (page - 1) * pageSize
|
|
393
426
|
});
|
|
394
427
|
|
|
395
428
|
const totalCount = queryResult.data?.total || 0;
|
|
@@ -430,7 +463,7 @@ export function usePagination<T = any>(
|
|
|
430
463
|
/**
|
|
431
464
|
* Infinite query options for useInfiniteQuery hook
|
|
432
465
|
*/
|
|
433
|
-
export interface UseInfiniteQueryOptions<T = any> extends Omit<UseQueryOptions<T>, 'skip'> {
|
|
466
|
+
export interface UseInfiniteQueryOptions<T = any> extends Omit<UseQueryOptions<T>, 'skip' | 'offset'> {
|
|
434
467
|
/** Page size for each fetch */
|
|
435
468
|
pageSize?: number;
|
|
436
469
|
/** Get next page parameter */
|
|
@@ -473,7 +506,7 @@ export interface UseInfiniteQueryResult<T = any> {
|
|
|
473
506
|
* isFetchingNextPage
|
|
474
507
|
* } = useInfiniteQuery('todo_task', {
|
|
475
508
|
* pageSize: 20,
|
|
476
|
-
*
|
|
509
|
+
* orderBy: ['-created_at']
|
|
477
510
|
* });
|
|
478
511
|
*
|
|
479
512
|
* return (
|
|
@@ -498,14 +531,20 @@ export function useInfiniteQuery<T = any>(
|
|
|
498
531
|
pageSize = 20,
|
|
499
532
|
// getNextPageParam is reserved for future use
|
|
500
533
|
query,
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
534
|
+
// Canonical names take precedence over legacy names
|
|
535
|
+
where, fields, orderBy,
|
|
536
|
+
// Legacy names (deprecated fallbacks)
|
|
537
|
+
select, filters, sort,
|
|
504
538
|
enabled = true,
|
|
505
539
|
onSuccess,
|
|
506
540
|
onError
|
|
507
541
|
} = options;
|
|
508
542
|
|
|
543
|
+
// Resolve canonical vs legacy: canonical wins
|
|
544
|
+
const resolvedFields = fields ?? select;
|
|
545
|
+
const resolvedWhere = where ?? filters;
|
|
546
|
+
const resolvedSort = orderBy ?? sort;
|
|
547
|
+
|
|
509
548
|
const [pages, setPages] = useState<PaginatedResult<T>[]>([]);
|
|
510
549
|
const [isLoading, setIsLoading] = useState(true);
|
|
511
550
|
const [isFetchingNextPage, setIsFetchingNextPage] = useState(false);
|
|
@@ -531,11 +570,11 @@ export function useInfiniteQuery<T = any>(
|
|
|
531
570
|
});
|
|
532
571
|
} else {
|
|
533
572
|
result = await client.data.find<T>(object, {
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
skip
|
|
573
|
+
where: resolvedWhere as any,
|
|
574
|
+
fields: resolvedFields,
|
|
575
|
+
orderBy: resolvedSort,
|
|
576
|
+
limit: pageSize,
|
|
577
|
+
offset: skip,
|
|
539
578
|
});
|
|
540
579
|
}
|
|
541
580
|
|
|
@@ -559,7 +598,7 @@ export function useInfiniteQuery<T = any>(
|
|
|
559
598
|
setIsLoading(false);
|
|
560
599
|
setIsFetchingNextPage(false);
|
|
561
600
|
}
|
|
562
|
-
}, [client, object, query,
|
|
601
|
+
}, [client, object, query, resolvedFields, resolvedWhere, resolvedSort, pageSize, onSuccess, onError]);
|
|
563
602
|
|
|
564
603
|
// Initial fetch
|
|
565
604
|
useEffect(() => {
|
package/tsconfig.json
CHANGED
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
"declaration": true,
|
|
7
7
|
"declarationMap": true,
|
|
8
8
|
"jsx": "react",
|
|
9
|
-
"lib": ["ES2020", "DOM", "DOM.Iterable"]
|
|
9
|
+
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
|
10
|
+
"types": ["node", "react"]
|
|
10
11
|
},
|
|
11
12
|
"include": ["src/**/*"],
|
|
12
13
|
"exclude": ["node_modules", "dist", "**/*.test.ts"]
|