@ram_28/kf-ai-sdk 1.0.19 → 1.0.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. package/README.md +45 -12
  2. package/dist/api/client.d.ts.map +1 -1
  3. package/dist/api/datetime.d.ts +59 -10
  4. package/dist/api/datetime.d.ts.map +1 -1
  5. package/dist/api/index.d.ts +3 -2
  6. package/dist/api/index.d.ts.map +1 -1
  7. package/dist/api.cjs +1 -1
  8. package/dist/api.d.ts +1 -1
  9. package/dist/api.d.ts.map +1 -1
  10. package/dist/api.mjs +43 -21
  11. package/dist/api.types.d.ts +2 -1
  12. package/dist/api.types.d.ts.map +1 -1
  13. package/dist/auth/AuthProvider.d.ts.map +1 -1
  14. package/dist/auth.cjs +1 -1
  15. package/dist/auth.mjs +34 -34
  16. package/dist/base-types.d.ts +1 -1
  17. package/dist/base-types.d.ts.map +1 -1
  18. package/dist/client-BIkaIr2y.js +217 -0
  19. package/dist/client-DxjRcEtN.cjs +1 -0
  20. package/dist/components/hooks/useFilter/types.d.ts +14 -11
  21. package/dist/components/hooks/useFilter/types.d.ts.map +1 -1
  22. package/dist/components/hooks/useFilter/useFilter.d.ts +1 -1
  23. package/dist/components/hooks/useFilter/useFilter.d.ts.map +1 -1
  24. package/dist/components/hooks/useForm/apiClient.d.ts +45 -4
  25. package/dist/components/hooks/useForm/apiClient.d.ts.map +1 -1
  26. package/dist/components/hooks/useForm/useForm.d.ts.map +1 -1
  27. package/dist/components/hooks/useKanban/types.d.ts +5 -22
  28. package/dist/components/hooks/useKanban/types.d.ts.map +1 -1
  29. package/dist/components/hooks/useKanban/useKanban.d.ts.map +1 -1
  30. package/dist/components/hooks/useTable/types.d.ts +19 -31
  31. package/dist/components/hooks/useTable/types.d.ts.map +1 -1
  32. package/dist/components/hooks/useTable/useTable.d.ts.map +1 -1
  33. package/dist/error-handling-CAoD0Kwb.cjs +1 -0
  34. package/dist/error-handling-CrhTtD88.js +14 -0
  35. package/dist/filter.cjs +1 -1
  36. package/dist/filter.mjs +1 -1
  37. package/dist/form.cjs +1 -1
  38. package/dist/form.mjs +736 -750
  39. package/dist/index.d.ts +18 -0
  40. package/dist/index.d.ts.map +1 -1
  41. package/dist/kanban.cjs +2 -2
  42. package/dist/kanban.mjs +333 -323
  43. package/dist/{metadata-0lZAfuTP.cjs → metadata-Bz8zJqC1.cjs} +1 -1
  44. package/dist/{metadata-B88D_pVS.js → metadata-VbQzyD2C.js} +1 -1
  45. package/dist/table.cjs +1 -1
  46. package/dist/table.mjs +113 -96
  47. package/dist/table.types.d.ts +1 -1
  48. package/dist/table.types.d.ts.map +1 -1
  49. package/dist/types/base-fields.d.ts +71 -17
  50. package/dist/types/base-fields.d.ts.map +1 -1
  51. package/dist/types/common.d.ts +26 -18
  52. package/dist/types/common.d.ts.map +1 -1
  53. package/dist/useFilter-DzpP_ag0.cjs +1 -0
  54. package/dist/useFilter-H5bgAZQF.js +120 -0
  55. package/dist/utils/api/buildListOptions.d.ts +43 -0
  56. package/dist/utils/api/buildListOptions.d.ts.map +1 -0
  57. package/dist/utils/api/index.d.ts +2 -0
  58. package/dist/utils/api/index.d.ts.map +1 -0
  59. package/dist/utils/error-handling.d.ts +41 -0
  60. package/dist/utils/error-handling.d.ts.map +1 -0
  61. package/dist/utils/index.d.ts +2 -0
  62. package/dist/utils/index.d.ts.map +1 -1
  63. package/docs/QUICK_REFERENCE.md +142 -420
  64. package/docs/useAuth.md +52 -340
  65. package/docs/useFilter.md +858 -162
  66. package/docs/useForm.md +712 -501
  67. package/docs/useKanban.md +534 -279
  68. package/docs/useTable.md +725 -214
  69. package/package.json +1 -1
  70. package/sdk/api/client.ts +3 -41
  71. package/sdk/api/datetime.ts +98 -14
  72. package/sdk/api/index.ts +12 -6
  73. package/sdk/api.ts +6 -3
  74. package/sdk/api.types.ts +3 -4
  75. package/sdk/auth/AuthProvider.tsx +22 -24
  76. package/sdk/base-types.ts +2 -0
  77. package/sdk/components/hooks/useFilter/types.ts +14 -11
  78. package/sdk/components/hooks/useFilter/useFilter.ts +20 -18
  79. package/sdk/components/hooks/useForm/apiClient.ts +120 -5
  80. package/sdk/components/hooks/useForm/useForm.ts +97 -61
  81. package/sdk/components/hooks/useKanban/types.ts +7 -23
  82. package/sdk/components/hooks/useKanban/useKanban.ts +54 -18
  83. package/sdk/components/hooks/useTable/types.ts +26 -32
  84. package/sdk/components/hooks/useTable/useTable.llm.txt +8 -22
  85. package/sdk/components/hooks/useTable/useTable.ts +70 -25
  86. package/sdk/index.ts +157 -10
  87. package/sdk/table.types.ts +3 -0
  88. package/sdk/types/base-fields.ts +71 -17
  89. package/sdk/types/common.ts +33 -19
  90. package/sdk/utils/api/buildListOptions.ts +120 -0
  91. package/sdk/utils/api/index.ts +2 -0
  92. package/sdk/utils/error-handling.ts +150 -0
  93. package/sdk/utils/index.ts +6 -0
  94. package/dist/client-DgtkT50N.cjs +0 -1
  95. package/dist/client-V-WzUb8H.js +0 -237
  96. package/dist/useFilter-Dofowpr_.cjs +0 -1
  97. package/dist/useFilter-Dv-mr9QW.js +0 -117
@@ -7,6 +7,7 @@ import { useState, useMemo, useCallback, useRef, useEffect } from "react";
7
7
  import { useQuery, useMutation, useQueryClient, useQueries, keepPreviousData } from "@tanstack/react-query";
8
8
  import { api } from "../../../api";
9
9
  import type { ListOptionsType, ListResponseType } from "../../../types/common";
10
+ import { toError } from "../../../utils/error-handling";
10
11
  import { useFilter } from "../useFilter";
11
12
 
12
13
  import type {
@@ -41,8 +42,13 @@ export function useKanban<T extends Record<string, any> = Record<string, any>>(
41
42
 
42
43
  const [search, setSearch] = useState({
43
44
  query: initialState?.search || "",
45
+ debouncedQuery: initialState?.search || "",
44
46
  });
45
47
 
48
+ // Debounce timeout ref for search
49
+ const searchDebounceRef = useRef<NodeJS.Timeout | null>(null);
50
+ const SEARCH_DEBOUNCE_MS = 300;
51
+
46
52
  const [sorting] = useState({
47
53
  field: initialState?.sorting?.field || null,
48
54
  direction: initialState?.sorting?.direction || null,
@@ -81,8 +87,8 @@ export function useKanban<T extends Record<string, any> = Record<string, any>>(
81
87
  // ============================================================
82
88
 
83
89
  const filter = useFilter({
84
- initialConditions: initialState?.filters,
85
- initialOperator: initialState?.filterOperator || "And",
90
+ conditions: initialState?.filter?.conditions,
91
+ operator: initialState?.filter?.operator || "And",
86
92
  });
87
93
 
88
94
  // Helper to generate API options for a specific column
@@ -139,13 +145,13 @@ export function useKanban<T extends Record<string, any> = Record<string, any>>(
139
145
  ];
140
146
  }
141
147
 
142
- // Add Search
143
- if (search.query) {
144
- opts.Search = search.query;
148
+ // Add Search (debounced)
149
+ if (search.debouncedQuery) {
150
+ opts.Search = search.debouncedQuery;
145
151
  }
146
152
 
147
153
  return opts;
148
- }, [filter.payload, columnPagination, sorting, search.query]);
154
+ }, [filter.payload, columnPagination, sorting, search.debouncedQuery]);
149
155
 
150
156
  // ============================================================
151
157
  // COLUMN QUERY GENERATION
@@ -180,10 +186,10 @@ export function useKanban<T extends Record<string, any> = Record<string, any>>(
180
186
  const cardApiOptions = useMemo((): ListOptionsType => {
181
187
  // This is for the GLOBAL count (ignoring column split)
182
188
  const opts: ListOptionsType = {};
183
- if (search.query) opts.Search = search.query;
189
+ if (search.debouncedQuery) opts.Search = search.debouncedQuery;
184
190
  if (filter.payload) opts.Filter = filter.payload;
185
191
  return opts;
186
- }, [search.query, filter.payload]);
192
+ }, [search.debouncedQuery, filter.payload]);
187
193
 
188
194
  const {
189
195
  data: countData,
@@ -196,7 +202,7 @@ export function useKanban<T extends Record<string, any> = Record<string, any>>(
196
202
  return await api<KanbanCardType<T>>(source).count(cardApiOptions);
197
203
  } catch (err) {
198
204
  if (onErrorRef.current) {
199
- onErrorRef.current(err as Error);
205
+ onErrorRef.current(toError(err));
200
206
  }
201
207
  throw err;
202
208
  }
@@ -258,7 +264,7 @@ export function useKanban<T extends Record<string, any> = Record<string, any>>(
258
264
  if (context?.previousCards && context?.queryKey) {
259
265
  queryClient.setQueryData(context.queryKey, context.previousCards);
260
266
  }
261
- onErrorRef.current?.(error as Error);
267
+ onErrorRef.current?.(toError(error));
262
268
  },
263
269
  onSettled: (_data, _error, variables) => {
264
270
  const columnId = variables.columnId;
@@ -280,7 +286,7 @@ export function useKanban<T extends Record<string, any> = Record<string, any>>(
280
286
  onCardUpdateRef.current?.({ _id: result.id, ...result.updates } as any);
281
287
  },
282
288
  onError: (error, _variables, _context) => {
283
- onErrorRef.current?.(error as Error);
289
+ onErrorRef.current?.(toError(error));
284
290
  },
285
291
  onSettled: () => {
286
292
  queryClient.invalidateQueries({ queryKey: ["kanban-cards", source] });
@@ -300,7 +306,7 @@ export function useKanban<T extends Record<string, any> = Record<string, any>>(
300
306
  onCardDeleteRef.current?.(id);
301
307
  },
302
308
  onError: (error, _id, _context) => {
303
- onErrorRef.current?.(error as Error);
309
+ onErrorRef.current?.(toError(error));
304
310
  },
305
311
  onSettled: () => {
306
312
  queryClient.invalidateQueries({ queryKey: ["kanban-cards", source] });
@@ -374,7 +380,7 @@ export function useKanban<T extends Record<string, any> = Record<string, any>>(
374
380
  if (context?.previousToData && context?.toQueryKey) {
375
381
  queryClient.setQueryData(context.toQueryKey, context.previousToData);
376
382
  }
377
- onErrorRef.current?.(error as Error);
383
+ onErrorRef.current?.(toError(error));
378
384
  },
379
385
  onSettled: (_data, _error, variables) => {
380
386
  const fromOpts = getColumnApiOptions(variables.fromColumnId);
@@ -401,7 +407,7 @@ export function useKanban<T extends Record<string, any> = Record<string, any>>(
401
407
  },
402
408
  onSuccess: () => {},
403
409
  onError: (error, _variables, _context) => {
404
- onErrorRef.current?.(error as Error);
410
+ onErrorRef.current?.(toError(error));
405
411
  },
406
412
  onSettled: (_data, _error, variables) => {
407
413
  const opts = getColumnApiOptions(variables.columnId);
@@ -513,11 +519,32 @@ export function useKanban<T extends Record<string, any> = Record<string, any>>(
513
519
  // ============================================================
514
520
 
515
521
  const setSearchQuery = useCallback((value: string) => {
516
- setSearch({ query: value });
522
+ // Validate search query length to prevent DoS
523
+ if (value.length > 255) {
524
+ console.warn("Search query exceeds maximum length of 255 characters");
525
+ return;
526
+ }
527
+
528
+ // Update immediate value for UI
529
+ setSearch((prev) => ({ ...prev, query: value }));
530
+
531
+ // Clear existing debounce timeout
532
+ if (searchDebounceRef.current) {
533
+ clearTimeout(searchDebounceRef.current);
534
+ }
535
+
536
+ // Debounce the actual API query update
537
+ searchDebounceRef.current = setTimeout(() => {
538
+ setSearch((prev) => ({ ...prev, debouncedQuery: value }));
539
+ }, SEARCH_DEBOUNCE_MS);
517
540
  }, []);
518
541
 
519
542
  const clearSearch = useCallback(() => {
520
- setSearch({ query: "" });
543
+ // Clear debounce timeout
544
+ if (searchDebounceRef.current) {
545
+ clearTimeout(searchDebounceRef.current);
546
+ }
547
+ setSearch({ query: "", debouncedQuery: "" });
521
548
  }, []);
522
549
 
523
550
  const totalCards = countData?.Count || 0;
@@ -555,10 +582,19 @@ export function useKanban<T extends Record<string, any> = Record<string, any>>(
555
582
 
556
583
  useEffect(() => {
557
584
  if (error && onErrorRef.current) {
558
- onErrorRef.current(error as Error);
585
+ onErrorRef.current(toError(error));
559
586
  }
560
587
  }, [error]);
561
588
 
589
+ // Cleanup debounce timeout on unmount
590
+ useEffect(() => {
591
+ return () => {
592
+ if (searchDebounceRef.current) {
593
+ clearTimeout(searchDebounceRef.current);
594
+ }
595
+ };
596
+ }, []);
597
+
562
598
  // ============================================================
563
599
  // RETURN OBJECT
564
600
  // ============================================================
@@ -574,7 +610,7 @@ export function useKanban<T extends Record<string, any> = Record<string, any>>(
574
610
  isUpdating,
575
611
 
576
612
  // Error Handling
577
- error: error as Error | null,
613
+ error: error ? toError(error) : null,
578
614
 
579
615
  // Card Operations (Flat Access)
580
616
  createCard: createCardMutation.mutateAsync,
@@ -1,46 +1,40 @@
1
- import type { ListResponseType, ConditionGroupOperatorType } from "../../../types/common";
2
- import type { ConditionType, ConditionGroupType, UseFilterReturnType } from "../useFilter";
1
+ import type { ListResponseType, SortType, ColumnDefinitionType } from "../../../types/common";
2
+
3
+ // Re-export ColumnDefinitionType for backwards compatibility
4
+ export type { ColumnDefinitionType };
5
+ import type { UseFilterReturnType, UseFilterOptionsType } from "../useFilter";
3
6
 
4
7
  // ============================================================
5
- // TYPE DEFINITIONS
8
+ // STATE TYPE DEFINITIONS
6
9
  // ============================================================
7
10
 
8
- export interface ColumnDefinitionType<T> {
9
- /** Field name from the data type */
10
- fieldId: keyof T;
11
- /** Display label (optional, defaults to fieldId) */
12
- label?: string;
13
- /** Enable sorting for this column */
14
- enableSorting?: boolean;
15
- /** Enable filtering for this column */
16
- enableFiltering?: boolean;
17
- /** Custom transform function (overrides auto-formatting) */
18
- transform?: (value: any, row: T) => React.ReactNode;
11
+ /**
12
+ * Pagination state type
13
+ */
14
+ export interface PaginationStateType {
15
+ /** Page number (1-indexed) */
16
+ pageNo: number;
17
+ /** Number of items per page */
18
+ pageSize: number;
19
19
  }
20
20
 
21
+ // ============================================================
22
+ // TYPE DEFINITIONS
23
+ // ============================================================
24
+
21
25
  export interface UseTableOptionsType<T> {
22
26
  /** Data source identifier */
23
27
  source: string;
24
28
  /** Column configurations */
25
29
  columns: ColumnDefinitionType<T>[];
26
- /** Enable sorting functionality */
27
- enableSorting?: boolean;
28
- /** Enable filtering functionality */
29
- enableFiltering?: boolean;
30
- /** Enable pagination */
31
- enablePagination?: boolean;
32
30
  /** Initial state */
33
31
  initialState?: {
34
- pagination?: {
35
- pageNo: number;
36
- pageSize: number;
37
- };
38
- sorting?: {
39
- field: keyof T;
40
- direction: "asc" | "desc";
41
- };
42
- filters?: Array<ConditionType | ConditionGroupType>;
43
- filterOperator?: ConditionGroupOperatorType;
32
+ /** Sort configuration: [{ "fieldName": "ASC" }] */
33
+ sort?: SortType;
34
+ /** Pagination state: { pageNo, pageSize } */
35
+ pagination?: PaginationStateType;
36
+ /** Filter state: { conditions, operator } */
37
+ filter?: UseFilterOptionsType<T>;
44
38
  };
45
39
  /** Error callback */
46
40
  onError?: (error: Error) => void;
@@ -77,11 +71,11 @@ export interface UseTableReturnType<T> {
77
71
  };
78
72
 
79
73
  // Filter (Simplified chainable API)
80
- filter: UseFilterReturnType;
74
+ filter: UseFilterReturnType<T>;
81
75
 
82
76
  // Pagination (Flat Access)
83
77
  pagination: {
84
- currentPage: number;
78
+ pageNo: number;
85
79
  pageSize: number;
86
80
  totalPages: number;
87
81
  totalItems: number;
@@ -28,12 +28,9 @@ const table = useTable<ProductType>({
28
28
  { fieldId: "Category", label: "Category", enableSorting: true },
29
29
  { fieldId: "Stock", label: "Stock", enableSorting: true },
30
30
  ],
31
- enableSorting: true,
32
- enableFiltering: true,
33
- enablePagination: true,
34
31
  initialState: {
35
32
  pagination: { pageNo: 1, pageSize: 10 },
36
- sorting: { field: "Title", direction: "asc" },
33
+ sort: [{ Title: "ASC" }],
37
34
  },
38
35
  });
39
36
  ```
@@ -46,14 +43,9 @@ const table = useTable<ProductType>({
46
43
  |----------|------|----------|-------------|
47
44
  | `source` | `string` | Yes | Data source identifier (Business Data Object name) |
48
45
  | `columns` | `ColumnDefinition<T>[]` | Yes | Column configurations |
49
- | `enableSorting` | `boolean` | No | Enable sorting functionality |
50
- | `enableFiltering` | `boolean` | No | Enable filtering functionality |
51
- | `enablePagination` | `boolean` | No | Enable pagination |
52
- | `fieldDefinitions` | `Record<keyof T, FieldDefinition>` | No | Field definitions for filter validation |
53
- | `initialState` | `object` | No | Initial state for pagination, sorting, filters |
46
+ | `initialState` | `object` | No | Initial state for pagination, sorting, filters. Pagination defaults to `{ pageNo: 1, pageSize: 10 }` |
54
47
  | `onError` | `(error: Error) => void` | No | Error callback |
55
48
  | `onSuccess` | `(data: T[]) => void` | No | Success callback |
56
- | `onFilterError` | `(errors: ValidationError[]) => void` | No | Filter error callback |
57
49
 
58
50
  ### ColumnDefinition<T>
59
51
 
@@ -113,14 +105,14 @@ const table = useTable<ProductType>({
113
105
  | `filter.addCondition` | `(condition) => string` | Add a filter condition, returns ID |
114
106
  | `filter.updateCondition` | `(id, updates) => boolean` | Update a condition |
115
107
  | `filter.removeCondition` | `(id) => boolean` | Remove a condition |
116
- | `filter.clearConditions` | `() => void` | Clear all conditions |
108
+ | `filter.clearAllConditions` | `() => void` | Clear all conditions |
117
109
  | `filter.getCondition` | `(id) => FilterConditionWithId` | Get a specific condition |
118
110
  | `filter.setLogicalOperator` | `(operator) => void` | Set logical operator |
119
111
 
120
112
  #### Pagination
121
113
  | Property | Type | Description |
122
114
  |----------|------|-------------|
123
- | `pagination.currentPage` | `number` | Current page (1-indexed) |
115
+ | `pagination.pageNo` | `number` | Current page (1-indexed) |
124
116
  | `pagination.pageSize` | `number` | Items per page |
125
117
  | `pagination.totalPages` | `number` | Total number of pages |
126
118
  | `pagination.totalItems` | `number` | Total item count |
@@ -179,12 +171,9 @@ const table = useTable<SellerProduct>({
179
171
  { fieldId: "Category", label: "Category", enableSorting: true },
180
172
  { fieldId: "Stock", label: "Stock", enableSorting: true },
181
173
  ],
182
- enableSorting: true,
183
- enableFiltering: true,
184
- enablePagination: true,
185
174
  initialState: {
186
175
  pagination: { pageNo: 1, pageSize: 10 },
187
- sorting: { field: "Title", direction: "asc" },
176
+ sort: [{ Title: "ASC" }],
188
177
  },
189
178
  });
190
179
 
@@ -220,18 +209,15 @@ const table = useTable<SellerProduct>({
220
209
  const table = useTable<BuyerProduct>({
221
210
  source: "BDO_AmazonProductMaster",
222
211
  columns: [...],
223
- enableSorting: true,
224
- enableFiltering: true,
225
- enablePagination: true,
226
212
  initialState: {
227
213
  pagination: { pageNo: 1, pageSize: 10 },
228
- sorting: { field: "Title", direction: "asc" },
214
+ sort: [{ Title: "ASC" }],
229
215
  },
230
216
  });
231
217
 
232
218
  // Category filter
233
219
  const handleCategoryChange = (category: string) => {
234
- table.filter.clearConditions();
220
+ table.filter.clearAllConditions();
235
221
  if (category !== "all") {
236
222
  table.filter.addCondition({
237
223
  lhsField: "Category",
@@ -296,7 +282,7 @@ const handleSortChange = (value: string) => {
296
282
  <Button
297
283
  onClick={() => {
298
284
  table.search.clear();
299
- table.filter.clearConditions();
285
+ table.filter.clearAllConditions();
300
286
  }}
301
287
  >
302
288
  Clear All Filters
@@ -1,7 +1,8 @@
1
- import { useState, useMemo, useCallback } from "react";
1
+ import { useState, useMemo, useCallback, useRef, useEffect } from "react";
2
2
  import { useQuery } from "@tanstack/react-query";
3
3
  import { api } from "../../../api";
4
4
  import type { ListResponseType, ListOptionsType } from "../../../types/common";
5
+ import { toError } from "../../../utils/error-handling";
5
6
  import { useFilter } from "../useFilter";
6
7
  import type { UseTableOptionsType, UseTableReturnType } from "./types";
7
8
 
@@ -10,7 +11,8 @@ import type { UseTableOptionsType, UseTableReturnType } from "./types";
10
11
  // ============================================================
11
12
 
12
13
  interface SearchState {
13
- query: string;
14
+ query: string; // Immediate UI value
15
+ debouncedQuery: string; // Debounced value for API queries
14
16
  }
15
17
 
16
18
  interface SortingState<T> {
@@ -36,12 +38,26 @@ export function useTable<T = any>(
36
38
 
37
39
  const [search, setSearch] = useState<SearchState>({
38
40
  query: "",
41
+ debouncedQuery: "",
39
42
  });
40
43
 
41
- const [sorting, setSorting] = useState<SortingState<T>>({
42
- field: options.initialState?.sorting?.field || null,
43
- direction: options.initialState?.sorting?.direction || null,
44
- });
44
+ // Debounce timeout ref for search
45
+ const searchDebounceRef = useRef<NodeJS.Timeout | null>(null);
46
+ const SEARCH_DEBOUNCE_MS = 300;
47
+
48
+ // Parse initial sort from API format [{ "fieldName": "ASC" }] to internal state
49
+ const getInitialSortState = (): SortingState<T> => {
50
+ const sortConfig = options.initialState?.sort;
51
+ if (sortConfig && sortConfig.length > 0) {
52
+ const firstSort = sortConfig[0];
53
+ const field = Object.keys(firstSort)[0] as keyof T;
54
+ const direction = firstSort[field as string]?.toLowerCase() as "asc" | "desc";
55
+ return { field, direction };
56
+ }
57
+ return { field: null, direction: null };
58
+ };
59
+
60
+ const [sorting, setSorting] = useState<SortingState<T>>(getInitialSortState);
45
61
 
46
62
  const [pagination, setPagination] = useState<PaginationState>({
47
63
  pageNo: options.initialState?.pagination?.pageNo || 1,
@@ -52,9 +68,9 @@ export function useTable<T = any>(
52
68
  // FILTER HOOK INTEGRATION
53
69
  // ============================================================
54
70
 
55
- const filter = useFilter({
56
- initialConditions: options.initialState?.filters,
57
- initialOperator: options.initialState?.filterOperator || "And",
71
+ const filter = useFilter<T>({
72
+ conditions: options.initialState?.filter?.conditions,
73
+ operator: options.initialState?.filter?.operator || "And",
58
74
  });
59
75
 
60
76
  // ============================================================
@@ -65,9 +81,9 @@ export function useTable<T = any>(
65
81
  const countApiOptions = useMemo((): ListOptionsType => {
66
82
  const opts: ListOptionsType = {};
67
83
 
68
- // Add search query (affects count)
69
- if (search.query) {
70
- opts.Search = search.query;
84
+ // Add debounced search query (affects count)
85
+ if (search.debouncedQuery) {
86
+ opts.Search = search.debouncedQuery;
71
87
  }
72
88
 
73
89
  // Add filter conditions (affects count)
@@ -76,7 +92,7 @@ export function useTable<T = any>(
76
92
  }
77
93
 
78
94
  return opts;
79
- }, [search.query, filter.payload]);
95
+ }, [search.debouncedQuery, filter.payload]);
80
96
 
81
97
  // Options for list query - includes all options
82
98
  const apiOptions = useMemo((): ListOptionsType => {
@@ -92,13 +108,11 @@ export function useTable<T = any>(
92
108
  }
93
109
 
94
110
  // Add pagination
95
- if (options.enablePagination) {
96
- opts.Page = pagination.pageNo;
97
- opts.PageSize = pagination.pageSize;
98
- }
111
+ opts.Page = pagination.pageNo;
112
+ opts.PageSize = pagination.pageSize;
99
113
 
100
114
  return opts;
101
- }, [countApiOptions, sorting, pagination, options.enablePagination]);
115
+ }, [countApiOptions, sorting, pagination]);
102
116
 
103
117
  // ============================================================
104
118
  // DATA FETCHING
@@ -121,7 +135,7 @@ export function useTable<T = any>(
121
135
  return response;
122
136
  } catch (err) {
123
137
  if (options.onError) {
124
- options.onError(err as Error);
138
+ options.onError(toError(err));
125
139
  }
126
140
  throw err;
127
141
  }
@@ -144,7 +158,7 @@ export function useTable<T = any>(
144
158
  return await api<T>(options.source).count(countApiOptions);
145
159
  } catch (err) {
146
160
  if (options.onError) {
147
- options.onError(err as Error);
161
+ options.onError(toError(err));
148
162
  }
149
163
  throw err;
150
164
  }
@@ -197,12 +211,43 @@ export function useTable<T = any>(
197
211
  // ============================================================
198
212
 
199
213
  const setSearchQuery = useCallback((value: string) => {
200
- setSearch({ query: value });
201
- setPagination((prev) => ({ ...prev, pageNo: 1 }));
214
+ // Validate search query length to prevent DoS
215
+ if (value.length > 255) {
216
+ console.warn("Search query exceeds maximum length of 255 characters");
217
+ return;
218
+ }
219
+
220
+ // Update immediate value for UI
221
+ setSearch((prev) => ({ ...prev, query: value }));
222
+
223
+ // Clear existing debounce timeout
224
+ if (searchDebounceRef.current) {
225
+ clearTimeout(searchDebounceRef.current);
226
+ }
227
+
228
+ // Debounce the actual API query update
229
+ searchDebounceRef.current = setTimeout(() => {
230
+ setSearch((prev) => ({ ...prev, debouncedQuery: value }));
231
+ setPagination((prev) => ({ ...prev, pageNo: 1 }));
232
+ }, SEARCH_DEBOUNCE_MS);
202
233
  }, []);
203
234
 
204
235
  const clearSearch = useCallback(() => {
205
- setSearch({ query: "" });
236
+ // Clear debounce timeout
237
+ if (searchDebounceRef.current) {
238
+ clearTimeout(searchDebounceRef.current);
239
+ }
240
+ setSearch({ query: "", debouncedQuery: "" });
241
+ setPagination((prev) => ({ ...prev, pageNo: 1 }));
242
+ }, []);
243
+
244
+ // Cleanup debounce timeout on unmount
245
+ useEffect(() => {
246
+ return () => {
247
+ if (searchDebounceRef.current) {
248
+ clearTimeout(searchDebounceRef.current);
249
+ }
250
+ };
206
251
  }, []);
207
252
 
208
253
  // ============================================================
@@ -263,7 +308,7 @@ export function useTable<T = any>(
263
308
  isFetching: isFetching || isCountFetching,
264
309
 
265
310
  // Error Handling
266
- error: (error || countError) as Error | null,
311
+ error: error ? toError(error) : countError ? toError(countError) : null,
267
312
 
268
313
  // Search (Flat Access)
269
314
  search: {
@@ -286,7 +331,7 @@ export function useTable<T = any>(
286
331
 
287
332
  // Pagination (Flat Access)
288
333
  pagination: {
289
- currentPage: pagination.pageNo,
334
+ pageNo: pagination.pageNo,
290
335
  pageSize: pagination.pageSize,
291
336
  totalPages,
292
337
  totalItems,