@objectstack/client-react 3.3.1 → 4.0.1

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.
@@ -1,5 +1,5 @@
1
1
 
2
- > @objectstack/client-react@3.3.1 build /home/runner/work/spec/spec/packages/client-react
2
+ > @objectstack/client-react@4.0.1 build /home/runner/work/spec/spec/packages/client-react
3
3
  > tsup src/index.tsx --config ../../tsup.config.ts
4
4
 
5
5
  CLI Building entry: src/index.tsx
@@ -10,13 +10,13 @@
10
10
  CLI Cleaning output folder
11
11
  ESM Build start
12
12
  CJS Build start
13
- ESM dist/index.mjs 12.49 KB
14
- ESM dist/index.mjs.map 35.75 KB
13
+ CJS dist/index.js 16.10 KB
14
+ CJS dist/index.js.map 38.11 KB
15
+ CJS ⚡️ Build success in 53ms
16
+ ESM dist/index.mjs 13.30 KB
17
+ ESM dist/index.mjs.map 38.08 KB
15
18
  ESM ⚡️ Build success in 54ms
16
- CJS dist/index.js 15.29 KB
17
- CJS dist/index.js.map 35.78 KB
18
- CJS ⚡️ Build success in 55ms
19
19
  DTS Build start
20
- DTS ⚡️ Build success in 4901ms
21
- DTS dist/index.d.mts 11.73 KB
22
- DTS dist/index.d.ts 11.73 KB
20
+ DTS ⚡️ Build success in 5032ms
21
+ DTS dist/index.d.mts 12.67 KB
22
+ DTS dist/index.d.ts 12.67 KB
package/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
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
+
3
13
  ## 3.3.1
4
14
 
5
15
  ### 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
- /** Simple field selection */
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
- /** Simple filters */
80
+ /** @deprecated Use `where` instead. */
59
81
  filters?: FilterCondition;
60
- /** Sort configuration */
82
+ /** @deprecated Use `orderBy` instead. */
61
83
  sort?: string | string[];
62
- /** Limit results */
84
+ /** @deprecated Use `limit` instead. */
63
85
  top?: number;
64
- /** Skip results (for pagination) */
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
- * select: ['id', 'subject', 'priority'],
98
- * sort: ['-created_at'],
99
- * top: 20
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
- * sort: ['-created_at']
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
- * sort: ['-created_at']
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
- /** Simple field selection */
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
- /** Simple filters */
80
+ /** @deprecated Use `where` instead. */
59
81
  filters?: FilterCondition;
60
- /** Sort configuration */
82
+ /** @deprecated Use `orderBy` instead. */
61
83
  sort?: string | string[];
62
- /** Limit results */
84
+ /** @deprecated Use `limit` instead. */
63
85
  top?: number;
64
- /** Skip results (for pagination) */
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
- * select: ['id', 'subject', 'priority'],
98
- * sort: ['-created_at'],
99
- * top: 20
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
- * sort: ['-created_at']
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
- * sort: ['-created_at']
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
- select,
101
- filters,
102
- sort,
103
- top,
104
- skip
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, select, filters, sort, top, skip, enabled, onSuccess, onError]);
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
- top: pageSize,
221
- skip: (page - 1) * pageSize
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
- select,
289
- filters,
290
- sort,
291
- top: pageSize,
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, select, filters, sort, pageSize, onSuccess, onError]);
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
- select,
54
- filters,
55
- sort,
56
- top,
57
- skip
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, select, filters, sort, top, skip, enabled, onSuccess, onError]);
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
- top: pageSize,
174
- skip: (page - 1) * pageSize
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
- select,
242
- filters,
243
- sort,
244
- top: pageSize,
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, select, filters, sort, pageSize, onSuccess, onError]);
285
+ }, [client, object, query, resolvedFields, resolvedWhere, resolvedSort, pageSize, onSuccess, onError]);
266
286
  useEffect(() => {
267
287
  if (enabled) {
268
288
  fetchPage(0);
@@ -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.3.1",
3
+ "version": "4.0.1",
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": "3.3.1",
20
- "@objectstack/spec": "3.3.1",
21
- "@objectstack/core": "3.3.1"
19
+ "@objectstack/client": "4.0.1",
20
+ "@objectstack/core": "4.0.1",
21
+ "@objectstack/spec": "4.0.1"
22
22
  },
23
23
  "devDependencies": {
24
24
  "@types/react": "^19.2.14",
25
- "typescript": "^5.0.0"
25
+ "typescript": "^6.0.2"
26
26
  },
27
27
  "scripts": {
28
28
  "build": "tsup src/index.tsx --config ../../tsup.config.ts"
@@ -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
- /** Simple field selection */
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
- /** Simple filters */
48
+ /** @deprecated Use `where` instead. */
23
49
  filters?: FilterCondition;
24
- /** Sort configuration */
50
+ /** @deprecated Use `orderBy` instead. */
25
51
  sort?: string | string[];
26
- /** Limit results */
52
+ /** @deprecated Use `limit` instead. */
27
53
  top?: number;
28
- /** Skip results (for pagination) */
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
- * select: ['id', 'subject', 'priority'],
64
- * sort: ['-created_at'],
65
- * top: 20
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
- select,
95
- filters,
96
- sort,
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 simplified find API
155
+ // Use canonical QueryOptionsV2 for the find call
123
156
  result = await client.data.find<T>(object, {
124
- select,
125
- filters: filters as any,
126
- sort,
127
- top,
128
- skip
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, select, filters, sort, top, skip, enabled, onSuccess, onError]);
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
- * sort: ['-created_at']
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
- top: pageSize,
392
- skip: (page - 1) * pageSize
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
- * sort: ['-created_at']
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
- select,
502
- filters,
503
- sort,
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
- select,
535
- filters: filters as any,
536
- sort,
537
- top: pageSize,
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, select, filters, sort, pageSize, onSuccess, onError]);
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"]