@ram_28/kf-ai-sdk 2.0.13 → 2.0.15

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 (121) hide show
  1. package/README.md +2 -1
  2. package/dist/FileField-BWrSHNRq.js +296 -0
  3. package/dist/FileField-eDeuzln8.cjs +1 -0
  4. package/dist/api.cjs +1 -1
  5. package/dist/api.mjs +2 -2
  6. package/dist/auth.cjs +1 -1
  7. package/dist/auth.mjs +1 -1
  8. package/dist/bdo.cjs +1 -1
  9. package/dist/bdo.mjs +228 -472
  10. package/dist/{client-DnO2KKrw.cjs → client-D5k4SYuw.cjs} +1 -1
  11. package/dist/{client-iQTqFDNI.js → client-_ayziI1d.js} +33 -32
  12. package/dist/components/hooks/index.d.ts +9 -3
  13. package/dist/components/hooks/index.d.ts.map +1 -1
  14. package/dist/{workflow/components → components/hooks}/useActivityForm/createActivityItemProxy.d.ts +9 -5
  15. package/dist/components/hooks/useActivityForm/createActivityItemProxy.d.ts.map +1 -0
  16. package/dist/components/hooks/useActivityForm/createActivityResolver.d.ts +23 -0
  17. package/dist/components/hooks/useActivityForm/createActivityResolver.d.ts.map +1 -0
  18. package/dist/components/hooks/useActivityForm/index.d.ts.map +1 -0
  19. package/dist/{workflow/components → components/hooks}/useActivityForm/types.d.ts +11 -7
  20. package/dist/components/hooks/useActivityForm/types.d.ts.map +1 -0
  21. package/dist/{workflow/components → components/hooks}/useActivityForm/useActivityForm.d.ts +2 -2
  22. package/dist/components/hooks/useActivityForm/useActivityForm.d.ts.map +1 -0
  23. package/dist/components/hooks/useActivityTable/index.d.ts +4 -0
  24. package/dist/components/hooks/useActivityTable/index.d.ts.map +1 -0
  25. package/dist/components/hooks/useActivityTable/types.d.ts +36 -0
  26. package/dist/components/hooks/useActivityTable/types.d.ts.map +1 -0
  27. package/dist/components/hooks/useActivityTable/useActivityTable.d.ts +4 -0
  28. package/dist/components/hooks/useActivityTable/useActivityTable.d.ts.map +1 -0
  29. package/dist/components/hooks/useBDOTable/index.d.ts +3 -0
  30. package/dist/components/hooks/useBDOTable/index.d.ts.map +1 -0
  31. package/dist/components/hooks/useBDOTable/types.d.ts +26 -0
  32. package/dist/components/hooks/useBDOTable/types.d.ts.map +1 -0
  33. package/dist/components/hooks/useBDOTable/useBDOTable.d.ts +3 -0
  34. package/dist/components/hooks/useBDOTable/useBDOTable.d.ts.map +1 -0
  35. package/dist/components/hooks/useTable/index.d.ts +2 -2
  36. package/dist/components/hooks/useTable/index.d.ts.map +1 -1
  37. package/dist/components/hooks/useTable/types.d.ts +11 -10
  38. package/dist/components/hooks/useTable/types.d.ts.map +1 -1
  39. package/dist/components/hooks/useTable/useTable.d.ts +1 -1
  40. package/dist/components/hooks/useTable/useTable.d.ts.map +1 -1
  41. package/dist/createResolver-AIgUwoS6.cjs +1 -0
  42. package/dist/createResolver-ZHXQ7QMa.js +1078 -0
  43. package/dist/form.cjs +1 -1
  44. package/dist/form.mjs +252 -314
  45. package/dist/{metadata-DpfI3zRN.js → metadata-Cc1mBcLS.js} +1 -1
  46. package/dist/{metadata-DgLSJkF5.cjs → metadata-DWXQPDav.cjs} +1 -1
  47. package/dist/table.cjs +1 -1
  48. package/dist/table.d.ts +1 -0
  49. package/dist/table.d.ts.map +1 -1
  50. package/dist/table.mjs +16 -192
  51. package/dist/table.types.d.ts +2 -1
  52. package/dist/table.types.d.ts.map +1 -1
  53. package/dist/types/base-fields.d.ts +4 -4
  54. package/dist/types/base-fields.d.ts.map +1 -1
  55. package/dist/useTable-CeRklbdT.cjs +1 -0
  56. package/dist/useTable-DS0-WInw.js +203 -0
  57. package/dist/workflow/Activity.d.ts +9 -9
  58. package/dist/workflow/Activity.d.ts.map +1 -1
  59. package/dist/workflow/client.d.ts.map +1 -1
  60. package/dist/workflow/createFieldFromMeta.d.ts +29 -0
  61. package/dist/workflow/createFieldFromMeta.d.ts.map +1 -0
  62. package/dist/workflow/index.d.ts +1 -2
  63. package/dist/workflow/index.d.ts.map +1 -1
  64. package/dist/workflow/types.d.ts +12 -12
  65. package/dist/workflow/types.d.ts.map +1 -1
  66. package/dist/workflow.cjs +1 -1
  67. package/dist/workflow.d.ts +5 -2
  68. package/dist/workflow.d.ts.map +1 -1
  69. package/dist/workflow.mjs +716 -338
  70. package/dist/workflow.types.d.ts +1 -0
  71. package/dist/workflow.types.d.ts.map +1 -1
  72. package/docs/bdo.md +3 -3
  73. package/docs/gaps.md +410 -0
  74. package/docs/useActivityTable.md +481 -0
  75. package/docs/useBDOTable.md +317 -0
  76. package/docs/useForm.md +4 -1
  77. package/docs/workflow.md +143 -34
  78. package/package.json +1 -1
  79. package/sdk/bdo/fields/UserField.ts +1 -1
  80. package/sdk/components/hooks/index.ts +28 -5
  81. package/sdk/components/hooks/useActivityForm/createActivityItemProxy.ts +400 -0
  82. package/sdk/components/hooks/useActivityForm/createActivityResolver.ts +87 -0
  83. package/sdk/{workflow/components → components/hooks}/useActivityForm/types.ts +21 -8
  84. package/sdk/components/hooks/useActivityForm/useActivityForm.ts +628 -0
  85. package/sdk/components/hooks/useActivityTable/index.ts +8 -0
  86. package/sdk/components/hooks/useActivityTable/types.ts +45 -0
  87. package/sdk/components/hooks/useActivityTable/useActivityTable.ts +71 -0
  88. package/sdk/components/hooks/useBDOTable/index.ts +2 -0
  89. package/sdk/components/hooks/useBDOTable/types.ts +24 -0
  90. package/sdk/components/hooks/useBDOTable/useBDOTable.ts +15 -0
  91. package/sdk/components/hooks/useTable/index.ts +3 -3
  92. package/sdk/components/hooks/useTable/types.ts +16 -12
  93. package/sdk/components/hooks/useTable/useTable.ts +56 -49
  94. package/sdk/table.ts +4 -1
  95. package/sdk/table.types.ts +7 -4
  96. package/sdk/types/base-fields.ts +4 -4
  97. package/sdk/workflow/Activity.ts +14 -13
  98. package/sdk/workflow/client.ts +21 -8
  99. package/sdk/workflow/createFieldFromMeta.ts +110 -0
  100. package/sdk/workflow/index.ts +1 -6
  101. package/sdk/workflow/types.ts +13 -12
  102. package/sdk/workflow.ts +11 -2
  103. package/sdk/workflow.types.ts +7 -0
  104. package/dist/BaseField-B6da88U7.js +0 -40
  105. package/dist/BaseField-Drp0-OxL.cjs +0 -1
  106. package/dist/error-handling-CAoD0Kwb.cjs +0 -1
  107. package/dist/error-handling-CrhTtD88.js +0 -14
  108. package/dist/index.esm-Cj63v5ny.js +0 -1014
  109. package/dist/index.esm-DuwT11sx.cjs +0 -1
  110. package/dist/workflow/components/useActivityForm/createActivityItemProxy.d.ts.map +0 -1
  111. package/dist/workflow/components/useActivityForm/createActivityResolver.d.ts +0 -22
  112. package/dist/workflow/components/useActivityForm/createActivityResolver.d.ts.map +0 -1
  113. package/dist/workflow/components/useActivityForm/index.d.ts.map +0 -1
  114. package/dist/workflow/components/useActivityForm/types.d.ts.map +0 -1
  115. package/dist/workflow/components/useActivityForm/useActivityForm.d.ts.map +0 -1
  116. package/docs/useTable.md +0 -369
  117. package/sdk/workflow/components/useActivityForm/createActivityItemProxy.ts +0 -130
  118. package/sdk/workflow/components/useActivityForm/createActivityResolver.ts +0 -61
  119. package/sdk/workflow/components/useActivityForm/useActivityForm.ts +0 -386
  120. /package/dist/{workflow/components → components/hooks}/useActivityForm/index.d.ts +0 -0
  121. /package/sdk/{workflow/components → components/hooks}/useActivityForm/index.ts +0 -0
@@ -0,0 +1,71 @@
1
+ import { useMemo } from 'react';
2
+ import { useTable } from '../useTable';
3
+ import type { Activity } from '../../../workflow/Activity';
4
+ import type {
5
+ UseActivityTableOptionsType,
6
+ UseActivityTableReturnType,
7
+ ActivityRowType,
8
+ } from './types';
9
+
10
+ const ACTIVITY_SYSTEM_FIELDS = new Set([
11
+ '_id',
12
+ 'BPInstanceId',
13
+ 'Status',
14
+ 'AssignedTo',
15
+ 'CompletedAt',
16
+ ]);
17
+
18
+ function nestEntityFields(
19
+ flatRow: Record<string, unknown>,
20
+ ): Record<string, unknown> {
21
+ const result: Record<string, unknown> = {};
22
+ const ado: Record<string, unknown> = {};
23
+ for (const [key, value] of Object.entries(flatRow)) {
24
+ if (ACTIVITY_SYSTEM_FIELDS.has(key)) {
25
+ result[key] = value;
26
+ } else {
27
+ ado[key] = value;
28
+ }
29
+ }
30
+ result.ADO = ado;
31
+ return result;
32
+ }
33
+
34
+ export function useActivityTable<A extends Activity<any, any, any>>(
35
+ activity: A,
36
+ options: UseActivityTableOptionsType<A>,
37
+ ): UseActivityTableReturnType<A> {
38
+ const { status, ...rest } = options;
39
+ const { businessProcessId, activityId } = activity.meta;
40
+
41
+ const ops = useMemo(() => activity._getOps(), [activity]);
42
+
43
+ const listFn = useMemo(() => {
44
+ const rawFn =
45
+ status === 'inprogress'
46
+ ? (opts: any) => ops.inProgressList(opts)
47
+ : (opts: any) => ops.completedList(opts);
48
+ return async (opts: any) => {
49
+ const result = await rawFn(opts);
50
+ return {
51
+ ...result,
52
+ Data: result.Data.map(nestEntityFields),
53
+ } as typeof result;
54
+ };
55
+ }, [ops, status]);
56
+
57
+ const countFn = useMemo(
58
+ () =>
59
+ status === 'inprogress'
60
+ ? (opts: any) => ops.inProgressMetric(opts)
61
+ : (opts: any) => ops.completedMetric(opts),
62
+ [ops, status],
63
+ );
64
+
65
+ return useTable<ActivityRowType<A>>({
66
+ queryKey: ['activity-table', businessProcessId, activityId, status],
67
+ listFn,
68
+ countFn,
69
+ ...rest,
70
+ });
71
+ }
@@ -0,0 +1,2 @@
1
+ export { useBDOTable } from './useBDOTable';
2
+ export type { UseBDOTableOptionsType, UseBDOTableReturnType } from './types';
@@ -0,0 +1,24 @@
1
+ import type { UseTableReturnType, PaginationStateType } from '../useTable/types';
2
+ import type { UseFilterOptionsType } from '../useFilter/types';
3
+ import type { SortType } from '../../../types/common';
4
+
5
+ export interface UseBDOTableOptionsType<T> {
6
+ /** BDO instance with list() and count() methods */
7
+ bdo: {
8
+ meta: { readonly _id: string; readonly name: string };
9
+ list(options?: any): Promise<any>;
10
+ count(options?: any): Promise<any>;
11
+ };
12
+ /** Initial state */
13
+ initialState?: {
14
+ sort?: SortType;
15
+ pagination?: PaginationStateType;
16
+ filter?: UseFilterOptionsType<T>;
17
+ };
18
+ /** Error callback */
19
+ onError?: (error: Error) => void;
20
+ /** Success callback — receives rows from current page */
21
+ onSuccess?: (data: T[]) => void;
22
+ }
23
+
24
+ export type UseBDOTableReturnType<T> = UseTableReturnType<T>;
@@ -0,0 +1,15 @@
1
+ import { useTable } from '../useTable';
2
+ import type { UseBDOTableOptionsType, UseBDOTableReturnType } from './types';
3
+
4
+ export function useBDOTable<T = any>(
5
+ options: UseBDOTableOptionsType<T>,
6
+ ): UseBDOTableReturnType<T> {
7
+ const { bdo, ...rest } = options;
8
+
9
+ return useTable<T>({
10
+ queryKey: ['table', bdo.meta._id],
11
+ listFn: (opts) => bdo.list(opts),
12
+ countFn: (opts) => bdo.count(opts),
13
+ ...rest,
14
+ });
15
+ }
@@ -1,9 +1,9 @@
1
1
  // Main hook
2
- export { useTable } from "./useTable";
2
+ export { useTable } from './useTable';
3
3
 
4
4
  // Types
5
5
  export type {
6
- ColumnDefinitionType,
7
6
  UseTableOptionsType,
8
7
  UseTableReturnType,
9
- } from "./types";
8
+ PaginationStateType,
9
+ } from './types';
@@ -1,8 +1,10 @@
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";
1
+ import type {
2
+ ListResponseType,
3
+ ListOptionsType,
4
+ CountResponseType,
5
+ SortType,
6
+ } from '../../../types/common';
7
+ import type { UseFilterReturnType, UseFilterOptionsType } from '../useFilter';
6
8
 
7
9
  // ============================================================
8
10
  // STATE TYPE DEFINITIONS
@@ -23,10 +25,12 @@ export interface PaginationStateType {
23
25
  // ============================================================
24
26
 
25
27
  export interface UseTableOptionsType<T> {
26
- /** Data source identifier */
27
- source: string;
28
- /** Column configurations */
29
- columns: ColumnDefinitionType<T>[];
28
+ /** Unique query key for React Query caching */
29
+ queryKey: string[];
30
+ /** Fetch list data (POST with filter/sort/pagination) */
31
+ listFn: (options: ListOptionsType) => Promise<ListResponseType<T>>;
32
+ /** Fetch count (POST with filter only) */
33
+ countFn: (options: ListOptionsType) => Promise<CountResponseType>;
30
34
  /** Initial state */
31
35
  initialState?: {
32
36
  /** Sort configuration: [{ "fieldName": "ASC" }] */
@@ -38,7 +42,7 @@ export interface UseTableOptionsType<T> {
38
42
  };
39
43
  /** Error callback */
40
44
  onError?: (error: Error) => void;
41
- /** Success callback */
45
+ /** Success callback — receives rows from current page */
42
46
  onSuccess?: (data: T[]) => void;
43
47
  }
44
48
 
@@ -65,10 +69,10 @@ export interface UseTableReturnType<T> {
65
69
  // Sorting (Flat Access)
66
70
  sort: {
67
71
  field: keyof T | null;
68
- direction: "ASC" | "DESC" | null;
72
+ direction: 'ASC' | 'DESC' | null;
69
73
  toggle: (field: keyof T) => void;
70
74
  clear: () => void;
71
- set: (field: keyof T, direction: "ASC" | "DESC") => void;
75
+ set: (field: keyof T | null, direction: 'ASC' | 'DESC' | null) => void;
72
76
  };
73
77
 
74
78
  // Filter (Simplified chainable API)
@@ -1,10 +1,14 @@
1
- import { useState, useMemo, useCallback, useRef, useEffect } from "react";
2
- import { useQuery } from "@tanstack/react-query";
3
- import { api } from "../../../api";
4
- import type { ListResponseType, ListOptionsType, FilterType, ConditionType } from "../../../types/common";
5
- import { toError } from "../../../utils/error-handling";
6
- import { useFilter } from "../useFilter";
7
- import type { UseTableOptionsType, UseTableReturnType } from "./types";
1
+ import { useState, useMemo, useCallback, useRef, useEffect } from 'react';
2
+ import { useQuery } from '@tanstack/react-query';
3
+ import type {
4
+ ListResponseType,
5
+ ListOptionsType,
6
+ FilterType,
7
+ ConditionType,
8
+ } from '../../../types/common';
9
+ import { toError } from '../../../utils/error-handling';
10
+ import { useFilter } from '../useFilter';
11
+ import type { UseTableOptionsType, UseTableReturnType } from './types';
8
12
 
9
13
  // ============================================================
10
14
  // INTERNAL STATE TYPES
@@ -18,7 +22,7 @@ interface SearchState<T> {
18
22
 
19
23
  interface SortingState<T> {
20
24
  field: keyof T | null;
21
- direction: "ASC" | "DESC" | null;
25
+ direction: 'ASC' | 'DESC' | null;
22
26
  }
23
27
 
24
28
  interface PaginationState {
@@ -31,15 +35,15 @@ interface PaginationState {
31
35
  // ============================================================
32
36
 
33
37
  export function useTable<T = any>(
34
- options: UseTableOptionsType<T>
38
+ options: UseTableOptionsType<T>,
35
39
  ): UseTableReturnType<T> {
36
40
  // ============================================================
37
41
  // STATE MANAGEMENT
38
42
  // ============================================================
39
43
 
40
44
  const [search, setSearch] = useState<SearchState<T>>({
41
- query: "",
42
- debouncedQuery: "",
45
+ query: '',
46
+ debouncedQuery: '',
43
47
  field: null,
44
48
  });
45
49
 
@@ -53,8 +57,8 @@ export function useTable<T = any>(
53
57
  if (sortConfig && sortConfig.length > 0) {
54
58
  const firstSort = sortConfig[0];
55
59
  const field = Object.keys(firstSort)[0] as keyof T;
56
- const raw = firstSort[field as string]?.toUpperCase() as "ASC" | "DESC";
57
- const direction = raw === "ASC" || raw === "DESC" ? raw : "ASC";
60
+ const raw = firstSort[field as string]?.toUpperCase() as 'ASC' | 'DESC';
61
+ const direction = raw === 'ASC' || raw === 'DESC' ? raw : 'ASC';
58
62
  return { field, direction };
59
63
  }
60
64
  return { field: null, direction: null };
@@ -73,7 +77,7 @@ export function useTable<T = any>(
73
77
 
74
78
  const filter = useFilter<T>({
75
79
  conditions: options.initialState?.filter?.conditions,
76
- operator: options.initialState?.filter?.operator || "And",
80
+ operator: options.initialState?.filter?.operator || 'And',
77
81
  });
78
82
 
79
83
  // ============================================================
@@ -99,14 +103,14 @@ export function useTable<T = any>(
99
103
  if (search.debouncedQuery && search.field) {
100
104
  const searchCondition: ConditionType = {
101
105
  LHSField: search.field,
102
- Operator: "Contains",
106
+ Operator: 'Contains',
103
107
  RHSValue: search.debouncedQuery,
104
- RHSType: "Constant",
108
+ RHSType: 'Constant',
105
109
  };
106
110
 
107
111
  if (combinedFilter) {
108
112
  // Merge with existing filter
109
- if (combinedFilter.Operator === "And") {
113
+ if (combinedFilter.Operator === 'And') {
110
114
  combinedFilter = {
111
115
  ...combinedFilter,
112
116
  Condition: [...(combinedFilter.Condition || []), searchCondition],
@@ -114,14 +118,14 @@ export function useTable<T = any>(
114
118
  } else {
115
119
  // Wrap existing filter in And with search condition
116
120
  combinedFilter = {
117
- Operator: "And",
121
+ Operator: 'And',
118
122
  Condition: [combinedFilter, searchCondition],
119
123
  };
120
124
  }
121
125
  } else {
122
126
  // Create new filter with just the search condition
123
127
  combinedFilter = {
124
- Operator: "And",
128
+ Operator: 'And',
125
129
  Condition: [searchCondition],
126
130
  };
127
131
  }
@@ -166,10 +170,10 @@ export function useTable<T = any>(
166
170
  error,
167
171
  refetch: queryRefetch,
168
172
  } = useQuery({
169
- queryKey: ["table", options.source, apiOptions],
173
+ queryKey: [...options.queryKey, apiOptions],
170
174
  queryFn: async (): Promise<ListResponseType<T>> => {
171
175
  try {
172
- const response = await api<T>(options.source).list(apiOptions);
176
+ const response = await options.listFn(apiOptions);
173
177
  if (options.onSuccess) {
174
178
  options.onSuccess(response.Data);
175
179
  }
@@ -193,10 +197,10 @@ export function useTable<T = any>(
193
197
  error: countError,
194
198
  refetch: countRefetch,
195
199
  } = useQuery({
196
- queryKey: ["table-count", options.source, countApiOptions],
200
+ queryKey: [...options.queryKey, 'count', countApiOptions],
197
201
  queryFn: async () => {
198
202
  try {
199
- return await api<T>(options.source).count(countApiOptions);
203
+ return await options.countFn(countApiOptions);
200
204
  } catch (err) {
201
205
  if (options.onError) {
202
206
  options.onError(toError(err));
@@ -226,13 +230,13 @@ export function useTable<T = any>(
226
230
  const toggleSort = useCallback((field: keyof T) => {
227
231
  setSorting((prev) => {
228
232
  if (prev.field === field) {
229
- if (prev.direction === "ASC") {
230
- return { field, direction: "DESC" };
231
- } else if (prev.direction === "DESC") {
233
+ if (prev.direction === 'ASC') {
234
+ return { field, direction: 'DESC' };
235
+ } else if (prev.direction === 'DESC') {
232
236
  return { field: null, direction: null };
233
237
  }
234
238
  }
235
- return { field, direction: "ASC" };
239
+ return { field, direction: 'ASC' };
236
240
  });
237
241
  }, []);
238
242
 
@@ -241,44 +245,47 @@ export function useTable<T = any>(
241
245
  }, []);
242
246
 
243
247
  const setSort = useCallback(
244
- (field: keyof T | null, direction: "ASC" | "DESC" | null) => {
248
+ (field: keyof T | null, direction: 'ASC' | 'DESC' | null) => {
245
249
  setSorting({ field, direction });
246
250
  },
247
- []
251
+ [],
248
252
  );
249
253
 
250
254
  // ============================================================
251
255
  // SEARCH OPERATIONS
252
256
  // ============================================================
253
257
 
254
- const setSearchFieldAndQuery = useCallback((field: keyof T, query: string) => {
255
- // Validate search query length to prevent DoS
256
- if (query.length > 255) {
257
- console.warn("Search query exceeds maximum length of 255 characters");
258
- return;
259
- }
258
+ const setSearchFieldAndQuery = useCallback(
259
+ (field: keyof T, query: string) => {
260
+ // Validate search query length to prevent DoS
261
+ if (query.length > 255) {
262
+ console.warn('Search query exceeds maximum length of 255 characters');
263
+ return;
264
+ }
260
265
 
261
- // Update immediate value for UI
262
- setSearch((prev) => ({ ...prev, query, field }));
266
+ // Update immediate value for UI
267
+ setSearch((prev) => ({ ...prev, query, field }));
263
268
 
264
- // Clear existing debounce timeout
265
- if (searchDebounceRef.current) {
266
- clearTimeout(searchDebounceRef.current);
267
- }
269
+ // Clear existing debounce timeout
270
+ if (searchDebounceRef.current) {
271
+ clearTimeout(searchDebounceRef.current);
272
+ }
268
273
 
269
- // Debounce the actual API query update
270
- searchDebounceRef.current = setTimeout(() => {
271
- setSearch((prev) => ({ ...prev, debouncedQuery: query }));
272
- setPagination((prev) => ({ ...prev, pageNo: 1 }));
273
- }, SEARCH_DEBOUNCE_MS);
274
- }, []);
274
+ // Debounce the actual API query update
275
+ searchDebounceRef.current = setTimeout(() => {
276
+ setSearch((prev) => ({ ...prev, debouncedQuery: query }));
277
+ setPagination((prev) => ({ ...prev, pageNo: 1 }));
278
+ }, SEARCH_DEBOUNCE_MS);
279
+ },
280
+ [],
281
+ );
275
282
 
276
283
  const clearSearch = useCallback(() => {
277
284
  // Clear debounce timeout
278
285
  if (searchDebounceRef.current) {
279
286
  clearTimeout(searchDebounceRef.current);
280
287
  }
281
- setSearch({ query: "", debouncedQuery: "", field: null });
288
+ setSearch({ query: '', debouncedQuery: '', field: null });
282
289
  setPagination((prev) => ({ ...prev, pageNo: 1 }));
283
290
  }, []);
284
291
 
@@ -315,7 +322,7 @@ export function useTable<T = any>(
315
322
  const pageNo = Math.max(1, Math.min(page, totalPages));
316
323
  setPagination((prev) => ({ ...prev, pageNo }));
317
324
  },
318
- [totalPages]
325
+ [totalPages],
319
326
  );
320
327
 
321
328
  const setPageSize = useCallback((size: number) => {
package/sdk/table.ts CHANGED
@@ -3,9 +3,12 @@
3
3
  // @ram_28/kf-ai-sdk/table
4
4
  // ============================================================
5
5
 
6
- // Main hook
6
+ // Base hook
7
7
  export { useTable } from './components/hooks/useTable/useTable';
8
8
 
9
+ // BDO wrapper hook
10
+ export { useBDOTable } from './components/hooks/useBDOTable/useBDOTable';
11
+
9
12
  // Constants
10
13
  export {
11
14
  SortDirection,
@@ -4,13 +4,16 @@
4
4
  // ============================================================
5
5
 
6
6
  export type {
7
- // Core hook types
7
+ // Base hook types
8
8
  UseTableOptionsType,
9
9
  UseTableReturnType,
10
10
 
11
- // Column definition
12
- ColumnDefinitionType,
13
-
14
11
  // State types
15
12
  PaginationStateType,
16
13
  } from './components/hooks/useTable/types';
14
+
15
+ export type {
16
+ // BDO wrapper types
17
+ UseBDOTableOptionsType,
18
+ UseBDOTableReturnType,
19
+ } from './components/hooks/useBDOTable/types';
@@ -93,16 +93,16 @@ type Second = number;
93
93
 
94
94
  /**
95
95
  * DateTime field (date and time)
96
- * API Request Format: "YYYY-MM-DD HH:MM:SS"
96
+ * API Request Format: "YYYY-MM-DDTHH:MM:SSZ"
97
+ * API Response Format: "YYYY-MM-DDTHH:MM:SSZ" (always UTC)
97
98
  * Use this for created_at, updated_at, event timestamps
98
99
  *
99
100
  * @example
100
- * // Response from API:
101
- * "2026-01-23T01:21:33"
101
+ * "2026-01-23T01:21:33Z"
102
102
  */
103
103
 
104
104
  export type DateTimeFieldType =
105
- `${Year}-${Month}-${Day}T${Hour}:${Minute}:${Second}`;
105
+ `${Year}-${Month}-${Day}T${Hour}:${Minute}:${Second}Z`;
106
106
 
107
107
  // ============================================================
108
108
  // COMPLEX FIELD TYPES
@@ -22,7 +22,8 @@ import type { ActivityInstanceType } from "./ActivityInstance";
22
22
  import type { ActivityInstanceFieldsType, ActivityOperations } from "./types";
23
23
  import type {
24
24
  ListResponseType,
25
- MetricResponseType,
25
+ ListOptionsType,
26
+ CountResponseType,
26
27
  } from "../types/common";
27
28
  import { BaseField } from "../bdo/fields/BaseField";
28
29
 
@@ -124,32 +125,32 @@ export abstract class Activity<
124
125
 
125
126
  /**
126
127
  * List in-progress activity instances.
127
- * Filtering and pagination are handled server-side.
128
+ * Accepts optional filter/sort/pagination options.
128
129
  */
129
- async getInProgressList(): Promise<ListResponseType<ActivityInstanceFieldsType & TEntity>> {
130
- return this._ops().inProgressList();
130
+ async getInProgressList(options?: ListOptionsType): Promise<ListResponseType<ActivityInstanceFieldsType & TEntity>> {
131
+ return this._ops().inProgressList(options);
131
132
  }
132
133
 
133
134
  /**
134
135
  * List completed activity instances.
135
- * Filtering and pagination are handled server-side.
136
+ * Accepts optional filter/sort/pagination options.
136
137
  */
137
- async getCompletedList(): Promise<ListResponseType<ActivityInstanceFieldsType & TEntity>> {
138
- return this._ops().completedList();
138
+ async getCompletedList(options?: ListOptionsType): Promise<ListResponseType<ActivityInstanceFieldsType & TEntity>> {
139
+ return this._ops().completedList(options);
139
140
  }
140
141
 
141
142
  /**
142
- * Get aggregated metrics for in-progress activity instances.
143
+ * Get count of in-progress activity instances.
143
144
  */
144
- async inProgressMetrics(): Promise<MetricResponseType> {
145
- return this._ops().inProgressMetric();
145
+ async inProgressMetrics(options?: ListOptionsType): Promise<CountResponseType> {
146
+ return this._ops().inProgressMetric(options);
146
147
  }
147
148
 
148
149
  /**
149
- * Get aggregated metrics for completed activity instances.
150
+ * Get count of completed activity instances.
150
151
  */
151
- async completedMetrics(): Promise<MetricResponseType> {
152
- return this._ops().completedMetric();
152
+ async completedMetrics(options?: ListOptionsType): Promise<CountResponseType> {
153
+ return this._ops().completedMetric(options);
153
154
  }
154
155
 
155
156
  /**
@@ -8,7 +8,8 @@ import {
8
8
  } from "../api/client";
9
9
  import type {
10
10
  ListResponseType,
11
- MetricResponseType,
11
+ ListOptionsType,
12
+ CountResponseType,
12
13
  ReadResponseType,
13
14
  DraftResponseType,
14
15
  CreateUpdateResponseType,
@@ -108,8 +109,20 @@ export class Workflow<T = any> {
108
109
 
109
110
  return {
110
111
  // ── List-level ────────────────────────────────────────────
111
-
112
- async inProgressList(): Promise<ListResponseType<ActivityInstanceFieldsType & T>> {
112
+ // TODO: Backend currently only supports GET for list/metric endpoints.
113
+ // Once backend is updated to accept POST with Filter/Sort/Page body,
114
+ // switch back to POST so useTable features (search, sort, pagination) work.
115
+ //
116
+ // POST version (waiting for backend):
117
+ // async inProgressList(options?: ListOptionsType) {
118
+ // return fetch(url + "/inprogress/list", {
119
+ // method: "POST", headers: getDefaultHeaders(),
120
+ // body: options ? JSON.stringify(options) : undefined,
121
+ // });
122
+ // }
123
+ // (same pattern for completedList, inProgressMetric, completedMetric)
124
+
125
+ async inProgressList(_options?: ListOptionsType): Promise<ListResponseType<ActivityInstanceFieldsType & T>> {
113
126
  const response = await fetch(`${getApiBaseUrl()}${base}/inprogress/list`, {
114
127
  method: "GET",
115
128
  headers: getDefaultHeaders(),
@@ -122,7 +135,7 @@ export class Workflow<T = any> {
122
135
  return response.json();
123
136
  },
124
137
 
125
- async completedList(): Promise<ListResponseType<ActivityInstanceFieldsType & T>> {
138
+ async completedList(_options?: ListOptionsType): Promise<ListResponseType<ActivityInstanceFieldsType & T>> {
126
139
  const response = await fetch(`${getApiBaseUrl()}${base}/completed/list`, {
127
140
  method: "GET",
128
141
  headers: getDefaultHeaders(),
@@ -135,27 +148,27 @@ export class Workflow<T = any> {
135
148
  return response.json();
136
149
  },
137
150
 
138
- async inProgressMetric(): Promise<MetricResponseType> {
151
+ async inProgressMetric(_options?: ListOptionsType): Promise<CountResponseType> {
139
152
  const response = await fetch(`${getApiBaseUrl()}${base}/inprogress/metric`, {
140
153
  method: "GET",
141
154
  headers: getDefaultHeaders(),
142
155
  });
143
156
 
144
157
  if (!response.ok) {
145
- throw new Error(`Failed to get in-progress activity metrics: ${response.statusText}`);
158
+ throw new Error(`Failed to get in-progress activity count: ${response.statusText}`);
146
159
  }
147
160
 
148
161
  return response.json();
149
162
  },
150
163
 
151
- async completedMetric(): Promise<MetricResponseType> {
164
+ async completedMetric(_options?: ListOptionsType): Promise<CountResponseType> {
152
165
  const response = await fetch(`${getApiBaseUrl()}${base}/completed/metric`, {
153
166
  method: "GET",
154
167
  headers: getDefaultHeaders(),
155
168
  });
156
169
 
157
170
  if (!response.ok) {
158
- throw new Error(`Failed to get completed activity metrics: ${response.statusText}`);
171
+ throw new Error(`Failed to get completed activity count: ${response.statusText}`);
159
172
  }
160
173
 
161
174
  return response.json();