@ram_28/kf-ai-sdk 2.0.14 → 2.0.16

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 (157) hide show
  1. package/README.md +10 -9
  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/core/BaseBdo.d.ts +1 -1
  9. package/dist/bdo.cjs +1 -1
  10. package/dist/bdo.mjs +230 -474
  11. package/dist/{client-DnO2KKrw.cjs → client-D5k4SYuw.cjs} +1 -1
  12. package/dist/{client-iQTqFDNI.js → client-_ayziI1d.js} +33 -32
  13. package/dist/components/hooks/index.d.ts +9 -3
  14. package/dist/components/hooks/index.d.ts.map +1 -1
  15. package/dist/{workflow/components → components/hooks}/useActivityForm/createActivityItemProxy.d.ts +9 -5
  16. package/dist/components/hooks/useActivityForm/createActivityItemProxy.d.ts.map +1 -0
  17. package/dist/components/hooks/useActivityForm/createActivityResolver.d.ts +23 -0
  18. package/dist/components/hooks/useActivityForm/createActivityResolver.d.ts.map +1 -0
  19. package/dist/components/hooks/useActivityForm/index.d.ts.map +1 -0
  20. package/dist/{workflow/components → components/hooks}/useActivityForm/types.d.ts +12 -8
  21. package/dist/components/hooks/useActivityForm/types.d.ts.map +1 -0
  22. package/dist/{workflow/components → components/hooks}/useActivityForm/useActivityForm.d.ts +2 -2
  23. package/dist/components/hooks/useActivityForm/useActivityForm.d.ts.map +1 -0
  24. package/dist/components/hooks/useActivityTable/index.d.ts +4 -0
  25. package/dist/components/hooks/useActivityTable/index.d.ts.map +1 -0
  26. package/dist/components/hooks/useActivityTable/types.d.ts +36 -0
  27. package/dist/components/hooks/useActivityTable/types.d.ts.map +1 -0
  28. package/dist/components/hooks/useActivityTable/useActivityTable.d.ts +4 -0
  29. package/dist/components/hooks/useActivityTable/useActivityTable.d.ts.map +1 -0
  30. package/dist/components/hooks/useBDOForm/createItemProxy.d.ts.map +1 -0
  31. package/dist/components/hooks/useBDOForm/createResolver.d.ts.map +1 -0
  32. package/dist/components/hooks/useBDOForm/index.d.ts +6 -0
  33. package/dist/components/hooks/useBDOForm/index.d.ts.map +1 -0
  34. package/dist/components/hooks/useBDOForm/shared.d.ts +50 -0
  35. package/dist/components/hooks/useBDOForm/shared.d.ts.map +1 -0
  36. package/dist/components/hooks/{useForm → useBDOForm}/types.d.ts +6 -6
  37. package/dist/components/hooks/useBDOForm/types.d.ts.map +1 -0
  38. package/dist/components/hooks/{useForm/useForm.d.ts → useBDOForm/useBDOForm.d.ts} +4 -4
  39. package/dist/components/hooks/useBDOForm/useBDOForm.d.ts.map +1 -0
  40. package/dist/components/hooks/useBDOTable/index.d.ts +3 -0
  41. package/dist/components/hooks/useBDOTable/index.d.ts.map +1 -0
  42. package/dist/components/hooks/useBDOTable/types.d.ts +24 -0
  43. package/dist/components/hooks/useBDOTable/types.d.ts.map +1 -0
  44. package/dist/components/hooks/useBDOTable/useBDOTable.d.ts +3 -0
  45. package/dist/components/hooks/useBDOTable/useBDOTable.d.ts.map +1 -0
  46. package/dist/components/hooks/useTable/index.d.ts +2 -2
  47. package/dist/components/hooks/useTable/index.d.ts.map +1 -1
  48. package/dist/components/hooks/useTable/types.d.ts +11 -10
  49. package/dist/components/hooks/useTable/types.d.ts.map +1 -1
  50. package/dist/components/hooks/useTable/useTable.d.ts +1 -1
  51. package/dist/components/hooks/useTable/useTable.d.ts.map +1 -1
  52. package/dist/form.cjs +1 -1
  53. package/dist/form.d.ts +1 -1
  54. package/dist/form.d.ts.map +1 -1
  55. package/dist/form.mjs +279 -344
  56. package/dist/form.types.d.ts +1 -1
  57. package/dist/form.types.d.ts.map +1 -1
  58. package/dist/{metadata-DpfI3zRN.js → metadata-Cc1mBcLS.js} +1 -1
  59. package/dist/{metadata-DgLSJkF5.cjs → metadata-DWXQPDav.cjs} +1 -1
  60. package/dist/shared-5a7UkED1.js +1180 -0
  61. package/dist/shared-nnmlRVs7.cjs +1 -0
  62. package/dist/table.cjs +1 -1
  63. package/dist/table.d.ts +1 -0
  64. package/dist/table.d.ts.map +1 -1
  65. package/dist/table.mjs +17 -192
  66. package/dist/table.types.d.ts +2 -1
  67. package/dist/table.types.d.ts.map +1 -1
  68. package/dist/types/base-fields.d.ts +4 -4
  69. package/dist/types/base-fields.d.ts.map +1 -1
  70. package/dist/types/constants.d.ts +3 -3
  71. package/dist/useTable-CeRklbdT.cjs +1 -0
  72. package/dist/useTable-DS0-WInw.js +203 -0
  73. package/dist/workflow/Activity.d.ts +19 -7
  74. package/dist/workflow/Activity.d.ts.map +1 -1
  75. package/dist/workflow/client.d.ts +2 -2
  76. package/dist/workflow/client.d.ts.map +1 -1
  77. package/dist/workflow/createFieldFromMeta.d.ts +29 -0
  78. package/dist/workflow/createFieldFromMeta.d.ts.map +1 -0
  79. package/dist/workflow/index.d.ts +1 -2
  80. package/dist/workflow/index.d.ts.map +1 -1
  81. package/dist/workflow/types.d.ts +16 -12
  82. package/dist/workflow/types.d.ts.map +1 -1
  83. package/dist/workflow.cjs +1 -1
  84. package/dist/workflow.d.ts +5 -2
  85. package/dist/workflow.d.ts.map +1 -1
  86. package/dist/workflow.mjs +687 -352
  87. package/dist/workflow.types.d.ts +1 -0
  88. package/dist/workflow.types.d.ts.map +1 -1
  89. package/docs/bdo.md +1 -1
  90. package/docs/gaps.md +360 -0
  91. package/docs/useActivityForm.md +393 -0
  92. package/docs/useActivityTable.md +418 -0
  93. package/docs/{useForm.md → useBDOForm.md} +24 -24
  94. package/docs/useBDOTable.md +284 -0
  95. package/docs/workflow.md +148 -297
  96. package/package.json +2 -2
  97. package/sdk/bdo/core/BaseBdo.ts +2 -2
  98. package/sdk/bdo/fields/UserField.ts +1 -1
  99. package/sdk/components/hooks/index.ts +28 -5
  100. package/sdk/components/hooks/useActivityForm/createActivityItemProxy.ts +400 -0
  101. package/sdk/components/hooks/useActivityForm/createActivityResolver.ts +87 -0
  102. package/sdk/{workflow/components → components/hooks}/useActivityForm/types.ts +24 -11
  103. package/sdk/components/hooks/useActivityForm/useActivityForm.ts +478 -0
  104. package/sdk/components/hooks/useActivityTable/index.ts +8 -0
  105. package/sdk/components/hooks/useActivityTable/types.ts +47 -0
  106. package/sdk/components/hooks/useActivityTable/useActivityTable.ts +40 -0
  107. package/sdk/components/hooks/{useForm → useBDOForm}/index.ts +4 -3
  108. package/sdk/components/hooks/useBDOForm/shared.ts +250 -0
  109. package/sdk/components/hooks/{useForm → useBDOForm}/types.ts +9 -9
  110. package/sdk/components/hooks/{useForm/useForm.ts → useBDOForm/useBDOForm.ts} +70 -96
  111. package/sdk/components/hooks/useBDOTable/index.ts +2 -0
  112. package/sdk/components/hooks/useBDOTable/types.ts +22 -0
  113. package/sdk/components/hooks/useBDOTable/useBDOTable.ts +16 -0
  114. package/sdk/components/hooks/useTable/index.ts +3 -3
  115. package/sdk/components/hooks/useTable/types.ts +16 -12
  116. package/sdk/components/hooks/useTable/useTable.ts +56 -49
  117. package/sdk/form.ts +2 -2
  118. package/sdk/form.types.ts +4 -4
  119. package/sdk/table.ts +4 -1
  120. package/sdk/table.types.ts +7 -4
  121. package/sdk/types/base-fields.ts +4 -4
  122. package/sdk/types/constants.ts +3 -3
  123. package/sdk/workflow/Activity.ts +36 -12
  124. package/sdk/workflow/client.ts +65 -12
  125. package/sdk/workflow/createFieldFromMeta.ts +110 -0
  126. package/sdk/workflow/index.ts +1 -6
  127. package/sdk/workflow/types.ts +20 -11
  128. package/sdk/workflow.ts +11 -2
  129. package/sdk/workflow.types.ts +7 -0
  130. package/dist/BaseField-B6da88U7.js +0 -40
  131. package/dist/BaseField-Drp0-OxL.cjs +0 -1
  132. package/dist/components/hooks/useForm/createItemProxy.d.ts.map +0 -1
  133. package/dist/components/hooks/useForm/createResolver.d.ts.map +0 -1
  134. package/dist/components/hooks/useForm/index.d.ts +0 -5
  135. package/dist/components/hooks/useForm/index.d.ts.map +0 -1
  136. package/dist/components/hooks/useForm/types.d.ts.map +0 -1
  137. package/dist/components/hooks/useForm/useForm.d.ts.map +0 -1
  138. package/dist/error-handling-CAoD0Kwb.cjs +0 -1
  139. package/dist/error-handling-CrhTtD88.js +0 -14
  140. package/dist/index.esm-Cj63v5ny.js +0 -1014
  141. package/dist/index.esm-DuwT11sx.cjs +0 -1
  142. package/dist/workflow/components/useActivityForm/createActivityItemProxy.d.ts.map +0 -1
  143. package/dist/workflow/components/useActivityForm/createActivityResolver.d.ts +0 -22
  144. package/dist/workflow/components/useActivityForm/createActivityResolver.d.ts.map +0 -1
  145. package/dist/workflow/components/useActivityForm/index.d.ts.map +0 -1
  146. package/dist/workflow/components/useActivityForm/types.d.ts.map +0 -1
  147. package/dist/workflow/components/useActivityForm/useActivityForm.d.ts.map +0 -1
  148. package/docs/useTable.md +0 -369
  149. package/sdk/workflow/components/useActivityForm/createActivityItemProxy.ts +0 -130
  150. package/sdk/workflow/components/useActivityForm/createActivityResolver.ts +0 -61
  151. package/sdk/workflow/components/useActivityForm/useActivityForm.ts +0 -386
  152. /package/dist/{workflow/components → components/hooks}/useActivityForm/index.d.ts +0 -0
  153. /package/dist/components/hooks/{useForm → useBDOForm}/createItemProxy.d.ts +0 -0
  154. /package/dist/components/hooks/{useForm → useBDOForm}/createResolver.d.ts +0 -0
  155. /package/sdk/{workflow/components → components/hooks}/useActivityForm/index.ts +0 -0
  156. /package/sdk/components/hooks/{useForm → useBDOForm}/createItemProxy.ts +0 -0
  157. /package/sdk/components/hooks/{useForm → useBDOForm}/createResolver.ts +0 -0
@@ -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/form.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  // ============================================================
2
2
  // Form Entry Point
3
3
  // ============================================================
4
- // Exports useForm hook for forms with automatic validation and API operations.
4
+ // Exports useBDOForm hook for forms with automatic validation and API operations.
5
5
 
6
- export { useForm } from "./components/hooks/useForm";
6
+ export { useBDOForm } from "./components/hooks/useBDOForm";
7
7
  export { ValidationMode, FormOperation, InteractionMode } from "./types/constants";
package/sdk/form.types.ts CHANGED
@@ -1,11 +1,11 @@
1
1
  // ============================================================
2
2
  // Form Types Entry Point
3
3
  // ============================================================
4
- // Type-only exports for useForm hook.
4
+ // Type-only exports for useBDOForm hook.
5
5
 
6
6
  export type {
7
- UseFormOptionsType,
8
- UseFormReturnType,
7
+ UseBDOFormOptionsType,
8
+ UseBDOFormReturnType,
9
9
  FormItemType,
10
10
  EditableFormFieldAccessorType,
11
11
  ReadonlyFormFieldAccessorType,
@@ -14,4 +14,4 @@ export type {
14
14
  ExtractEditableType,
15
15
  ExtractReadonlyType,
16
16
  AllFieldsType,
17
- } from "./components/hooks/useForm";
17
+ } from "./components/hooks/useBDOForm";
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
@@ -187,7 +187,7 @@ export const QueryType = {
187
187
  * @example
188
188
  * import { FormOperation } from "@ram_28/kf-ai-sdk/form";
189
189
  *
190
- * const { handleSubmit } = useForm({
190
+ * const { handleSubmit } = useBDOForm({
191
191
  * source: "products",
192
192
  * operation: FormOperation.Create,
193
193
  * });
@@ -206,7 +206,7 @@ export const FormOperation = {
206
206
  * @example
207
207
  * import { InteractionMode } from "@ram_28/kf-ai-sdk/form";
208
208
  *
209
- * const { handleSubmit } = useForm({
209
+ * const { handleSubmit } = useBDOForm({
210
210
  * source: "products",
211
211
  * operation: "create",
212
212
  * interactionMode: InteractionMode.Interactive,
@@ -225,7 +225,7 @@ export const InteractionMode = {
225
225
  * @example
226
226
  * import { ValidationMode } from "@ram_28/kf-ai-sdk/form";
227
227
  *
228
- * const { handleSubmit } = useForm({
228
+ * const { handleSubmit } = useBDOForm({
229
229
  * source: "products",
230
230
  * operation: "create",
231
231
  * mode: ValidationMode.OnBlur,
@@ -12,8 +12,10 @@
12
12
  // Methods:
13
13
  // activity.getInProgressList() // list in-progress activity instances
14
14
  // activity.getCompletedList() // list completed activity instances
15
- // activity.inProgressMetrics() // get in-progress aggregated metrics
16
- // activity.completedMetrics() // get completed aggregated metrics
15
+ // activity.inProgressCount() // get in-progress count (returns number)
16
+ // activity.completedCount() // get completed count (returns number)
17
+ // activity.inProgressMetric(options) // get in-progress aggregated metrics
18
+ // activity.completedMetric(options) // get completed aggregated metrics
17
19
  // activity.getInstance(instanceId) // get typed ActivityInstance
18
20
 
19
21
  import { Workflow } from "./client";
@@ -22,6 +24,8 @@ import type { ActivityInstanceType } from "./ActivityInstance";
22
24
  import type { ActivityInstanceFieldsType, ActivityOperations } from "./types";
23
25
  import type {
24
26
  ListResponseType,
27
+ ListOptionsType,
28
+ MetricOptionsType,
25
29
  MetricResponseType,
26
30
  } from "../types/common";
27
31
  import { BaseField } from "../bdo/fields/BaseField";
@@ -124,32 +128,52 @@ export abstract class Activity<
124
128
 
125
129
  /**
126
130
  * List in-progress activity instances.
127
- * Filtering and pagination are handled server-side.
131
+ * Accepts optional filter/sort/pagination options.
128
132
  */
129
- async getInProgressList(): Promise<ListResponseType<ActivityInstanceFieldsType & TEntity>> {
130
- return this._ops().inProgressList();
133
+ async getInProgressList(options?: ListOptionsType): Promise<ListResponseType<ActivityInstanceFieldsType & TEntity>> {
134
+ return this._ops().inProgressList(options);
131
135
  }
132
136
 
133
137
  /**
134
138
  * List completed activity instances.
135
- * Filtering and pagination are handled server-side.
139
+ * Accepts optional filter/sort/pagination options.
136
140
  */
137
- async getCompletedList(): Promise<ListResponseType<ActivityInstanceFieldsType & TEntity>> {
138
- return this._ops().completedList();
141
+ async getCompletedList(options?: ListOptionsType): Promise<ListResponseType<ActivityInstanceFieldsType & TEntity>> {
142
+ return this._ops().completedList(options);
143
+ }
144
+
145
+ /**
146
+ * Get count of in-progress activity instances.
147
+ * Returns a number (same as BDO count()).
148
+ */
149
+ async inProgressCount(options?: ListOptionsType): Promise<number> {
150
+ const response = await this._ops().inProgressCount(options);
151
+ return response.Count;
152
+ }
153
+
154
+ /**
155
+ * Get count of completed activity instances.
156
+ * Returns a number (same as BDO count()).
157
+ */
158
+ async completedCount(options?: ListOptionsType): Promise<number> {
159
+ const response = await this._ops().completedCount(options);
160
+ return response.Count;
139
161
  }
140
162
 
141
163
  /**
142
164
  * Get aggregated metrics for in-progress activity instances.
165
+ * Accepts MetricOptionsType (without Type) for custom aggregations (Sum, Avg, etc.).
143
166
  */
144
- async inProgressMetrics(): Promise<MetricResponseType> {
145
- return this._ops().inProgressMetric();
167
+ async inProgressMetric(options: Omit<MetricOptionsType, 'Type'>): Promise<MetricResponseType> {
168
+ return this._ops().inProgressMetric(options);
146
169
  }
147
170
 
148
171
  /**
149
172
  * Get aggregated metrics for completed activity instances.
173
+ * Accepts MetricOptionsType (without Type) for custom aggregations (Sum, Avg, etc.).
150
174
  */
151
- async completedMetrics(): Promise<MetricResponseType> {
152
- return this._ops().completedMetric();
175
+ async completedMetric(options: Omit<MetricOptionsType, 'Type'>): Promise<MetricResponseType> {
176
+ return this._ops().completedMetric(options);
153
177
  }
154
178
 
155
179
  /**
@@ -8,6 +8,9 @@ import {
8
8
  } from "../api/client";
9
9
  import type {
10
10
  ListResponseType,
11
+ ListOptionsType,
12
+ CountResponseType,
13
+ MetricOptionsType,
11
14
  MetricResponseType,
12
15
  ReadResponseType,
13
16
  DraftResponseType,
@@ -42,8 +45,8 @@ import type {
42
45
  * // List operations (by status — filtering/pagination handled server-side)
43
46
  * await act.inProgressList();
44
47
  * await act.completedList();
45
- * await act.inProgressMetric();
46
- * await act.completedMetric();
48
+ * await act.inProgressCount();
49
+ * await act.completedCount();
47
50
  *
48
51
  * // Process progress (requires instance_id)
49
52
  * const progress = await wf.progress("bp_inst_123");
@@ -109,10 +112,11 @@ export class Workflow<T = any> {
109
112
  return {
110
113
  // ── List-level ────────────────────────────────────────────
111
114
 
112
- async inProgressList(): Promise<ListResponseType<ActivityInstanceFieldsType & T>> {
115
+ async inProgressList(options?: ListOptionsType): Promise<ListResponseType<ActivityInstanceFieldsType & T>> {
113
116
  const response = await fetch(`${getApiBaseUrl()}${base}/inprogress/list`, {
114
- method: "GET",
117
+ method: "POST",
115
118
  headers: getDefaultHeaders(),
119
+ body: options ? JSON.stringify(options) : undefined,
116
120
  });
117
121
 
118
122
  if (!response.ok) {
@@ -122,10 +126,11 @@ export class Workflow<T = any> {
122
126
  return response.json();
123
127
  },
124
128
 
125
- async completedList(): Promise<ListResponseType<ActivityInstanceFieldsType & T>> {
129
+ async completedList(options?: ListOptionsType): Promise<ListResponseType<ActivityInstanceFieldsType & T>> {
126
130
  const response = await fetch(`${getApiBaseUrl()}${base}/completed/list`, {
127
- method: "GET",
131
+ method: "POST",
128
132
  headers: getDefaultHeaders(),
133
+ body: options ? JSON.stringify(options) : undefined,
129
134
  });
130
135
 
131
136
  if (!response.ok) {
@@ -135,27 +140,75 @@ export class Workflow<T = any> {
135
140
  return response.json();
136
141
  },
137
142
 
138
- async inProgressMetric(): Promise<MetricResponseType> {
143
+ async inProgressCount(options?: ListOptionsType): Promise<CountResponseType> {
144
+ const requestBody = {
145
+ Type: 'Metric',
146
+ GroupBy: [],
147
+ Metric: [{ Field: '_id', Type: 'Count' }],
148
+ ...(options?.Filter && { Filter: options.Filter }),
149
+ };
139
150
  const response = await fetch(`${getApiBaseUrl()}${base}/inprogress/metric`, {
140
- method: "GET",
151
+ method: 'POST',
152
+ headers: getDefaultHeaders(),
153
+ body: JSON.stringify(requestBody),
154
+ });
155
+
156
+ if (!response.ok) {
157
+ throw new Error(`Failed to get in-progress count: ${response.statusText}`);
158
+ }
159
+
160
+ const result = await response.json();
161
+ const count = result.Data?.[0]?.count__id ?? 0;
162
+ return { Count: count };
163
+ },
164
+
165
+ async completedCount(options?: ListOptionsType): Promise<CountResponseType> {
166
+ const requestBody = {
167
+ Type: 'Metric',
168
+ GroupBy: [],
169
+ Metric: [{ Field: '_id', Type: 'Count' }],
170
+ ...(options?.Filter && { Filter: options.Filter }),
171
+ };
172
+ const response = await fetch(`${getApiBaseUrl()}${base}/completed/metric`, {
173
+ method: 'POST',
174
+ headers: getDefaultHeaders(),
175
+ body: JSON.stringify(requestBody),
176
+ });
177
+
178
+ if (!response.ok) {
179
+ throw new Error(`Failed to get completed count: ${response.statusText}`);
180
+ }
181
+
182
+ const result = await response.json();
183
+ const count = result.Data?.[0]?.count__id ?? 0;
184
+ return { Count: count };
185
+ },
186
+
187
+ async inProgressMetric(options: Omit<MetricOptionsType, 'Type'>): Promise<MetricResponseType> {
188
+ const requestBody: MetricOptionsType = { Type: 'Metric', ...options };
189
+ const response = await fetch(`${getApiBaseUrl()}${base}/inprogress/metric`, {
190
+ method: 'POST',
141
191
  headers: getDefaultHeaders(),
192
+ body: JSON.stringify(requestBody),
142
193
  });
143
194
 
144
195
  if (!response.ok) {
145
- throw new Error(`Failed to get in-progress activity metrics: ${response.statusText}`);
196
+ throw new Error(`Failed to get in-progress metrics: ${response.statusText}`);
146
197
  }
147
198
 
148
199
  return response.json();
149
200
  },
150
201
 
151
- async completedMetric(): Promise<MetricResponseType> {
202
+ async completedMetric(options: Omit<MetricOptionsType, 'Type'>): Promise<MetricResponseType> {
203
+ const requestBody: MetricOptionsType = { Type: 'Metric', ...options };
152
204
  const response = await fetch(`${getApiBaseUrl()}${base}/completed/metric`, {
153
- method: "GET",
205
+ method: 'POST',
154
206
  headers: getDefaultHeaders(),
207
+ body: JSON.stringify(requestBody),
155
208
  });
156
209
 
157
210
  if (!response.ok) {
158
- throw new Error(`Failed to get completed activity metrics: ${response.statusText}`);
211
+ throw new Error(`Failed to get completed metrics: ${response.statusText}`);
159
212
  }
160
213
 
161
214
  return response.json();
@@ -0,0 +1,110 @@
1
+ // ============================================================
2
+ // FIELD FACTORY — Runtime Field Construction from Metadata
3
+ // ============================================================
4
+ // Creates BaseField instances from raw BP activity Input metadata.
5
+ // Used by useActivityForm to dynamically build fields when BP
6
+ // metadata is fetched at runtime.
7
+
8
+ import { StringField } from '../bdo/fields/StringField';
9
+ import { NumberField } from '../bdo/fields/NumberField';
10
+ import { BooleanField } from '../bdo/fields/BooleanField';
11
+ import { DateField } from '../bdo/fields/DateField';
12
+ import { DateTimeField } from '../bdo/fields/DateTimeField';
13
+ import { TextField } from '../bdo/fields/TextField';
14
+ import { SelectField } from '../bdo/fields/SelectField';
15
+ import { ReferenceField } from '../bdo/fields/ReferenceField';
16
+ import { UserField } from '../bdo/fields/UserField';
17
+ import { FileField } from '../bdo/fields/FileField';
18
+ import type { BaseField } from '../bdo/fields/BaseField';
19
+
20
+ /**
21
+ * Create a BaseField instance from raw Input field metadata.
22
+ * Used by useActivityForm to dynamically construct fields from BP metadata.
23
+ *
24
+ * @param fieldId - The field identifier (e.g., "StartDate", "LeaveType")
25
+ * @param meta - Raw field metadata from BP Activity Input definition
26
+ * @returns A BaseField instance matching the metadata Type
27
+ */
28
+ export function createFieldFromMeta(
29
+ fieldId: string,
30
+ meta: Record<string, unknown>,
31
+ ): BaseField<unknown> {
32
+ const fullMeta = { _id: fieldId, ...meta };
33
+ const type = meta.Type as string;
34
+
35
+ // String + Enum constraint → SelectField
36
+ if (
37
+ type === 'String' &&
38
+ (meta.Constraint as Record<string, unknown> | undefined)?.Enum
39
+ ) {
40
+ return new SelectField(fullMeta as any);
41
+ }
42
+
43
+ switch (type) {
44
+ case 'String':
45
+ return new StringField(fullMeta as any);
46
+ case 'Number':
47
+ return new NumberField(fullMeta as any);
48
+ case 'Boolean':
49
+ return new BooleanField(fullMeta as any);
50
+ case 'Date':
51
+ return new DateField(fullMeta as any);
52
+ case 'DateTime':
53
+ return new DateTimeField(fullMeta as any);
54
+ case 'Text':
55
+ return new TextField(fullMeta as any);
56
+ case 'Reference':
57
+ return new ReferenceField(fullMeta as any);
58
+ case 'User':
59
+ return new UserField(fullMeta as any);
60
+ case 'File':
61
+ return new FileField(fullMeta as any);
62
+ default:
63
+ return new StringField(fullMeta as any);
64
+ }
65
+ }
66
+
67
+ /**
68
+ * Build a fields map from an Activity's Input metadata.
69
+ *
70
+ * @param input - The Input object from BP Activity definition
71
+ * (Record of fieldId → raw field metadata)
72
+ * @returns Record of fieldId → BaseField instance
73
+ */
74
+ export function buildFieldsFromInput(
75
+ input: Record<string, Record<string, unknown>>,
76
+ ): Record<string, BaseField<unknown>> {
77
+ const fields: Record<string, BaseField<unknown>> = {};
78
+ for (const [fieldId, fieldMeta] of Object.entries(input)) {
79
+ fields[fieldId] = createFieldFromMeta(fieldId, fieldMeta);
80
+ }
81
+ return fields;
82
+ }
83
+
84
+ /**
85
+ * Search all activities in a BP blob for a field definition by name.
86
+ * Used to discover field metadata for Context-derived readonly fields.
87
+ *
88
+ * @param currentActivityDef - The current activity definition (to skip)
89
+ * @param bpSchema - The full BP schema (with BDOBlob)
90
+ * @param fieldName - The field name to search for
91
+ * @returns The field metadata or null if not found
92
+ */
93
+ export function findFieldInBpActivities(
94
+ currentActivityDef: Record<string, unknown> | null,
95
+ bpSchema: Record<string, unknown> | null | undefined,
96
+ fieldName: string,
97
+ ): Record<string, unknown> | null {
98
+ const blob = (bpSchema as any)?.BDOBlob;
99
+ if (!blob?.Activity) return null;
100
+
101
+ const currentId = (currentActivityDef as any)?.Id;
102
+
103
+ for (const activity of blob.Activity as any[]) {
104
+ if (activity.Id === currentId) continue;
105
+ if (activity.Input?.[fieldName]) {
106
+ return activity.Input[fieldName];
107
+ }
108
+ }
109
+ return null;
110
+ }