@ram_28/kf-ai-sdk 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +840 -0
  3. package/dist/api/client.d.ts +78 -0
  4. package/dist/api/client.d.ts.map +1 -0
  5. package/dist/api/datetime.d.ts +21 -0
  6. package/dist/api/datetime.d.ts.map +1 -0
  7. package/dist/api/index.d.ts +7 -0
  8. package/dist/api/index.d.ts.map +1 -0
  9. package/dist/api/metadata.d.ts +75 -0
  10. package/dist/api/metadata.d.ts.map +1 -0
  11. package/dist/components/hooks/index.d.ts +8 -0
  12. package/dist/components/hooks/index.d.ts.map +1 -0
  13. package/dist/components/hooks/useFilter/index.d.ts +5 -0
  14. package/dist/components/hooks/useFilter/index.d.ts.map +1 -0
  15. package/dist/components/hooks/useFilter/payloadBuilder.utils.d.ts +33 -0
  16. package/dist/components/hooks/useFilter/payloadBuilder.utils.d.ts.map +1 -0
  17. package/dist/components/hooks/useFilter/types.d.ts +137 -0
  18. package/dist/components/hooks/useFilter/types.d.ts.map +1 -0
  19. package/dist/components/hooks/useFilter/useFilter.d.ts +3 -0
  20. package/dist/components/hooks/useFilter/useFilter.d.ts.map +1 -0
  21. package/dist/components/hooks/useFilter/validation.utils.d.ts +38 -0
  22. package/dist/components/hooks/useFilter/validation.utils.d.ts.map +1 -0
  23. package/dist/components/hooks/useForm/apiClient.d.ts +71 -0
  24. package/dist/components/hooks/useForm/apiClient.d.ts.map +1 -0
  25. package/dist/components/hooks/useForm/expressionValidator.utils.d.ts +28 -0
  26. package/dist/components/hooks/useForm/expressionValidator.utils.d.ts.map +1 -0
  27. package/dist/components/hooks/useForm/index.d.ts +6 -0
  28. package/dist/components/hooks/useForm/index.d.ts.map +1 -0
  29. package/dist/components/hooks/useForm/optimizedExpressionValidator.utils.d.ts +88 -0
  30. package/dist/components/hooks/useForm/optimizedExpressionValidator.utils.d.ts.map +1 -0
  31. package/dist/components/hooks/useForm/ruleClassifier.utils.d.ts +28 -0
  32. package/dist/components/hooks/useForm/ruleClassifier.utils.d.ts.map +1 -0
  33. package/dist/components/hooks/useForm/schemaParser.utils.d.ts +29 -0
  34. package/dist/components/hooks/useForm/schemaParser.utils.d.ts.map +1 -0
  35. package/dist/components/hooks/useForm/types.d.ts +412 -0
  36. package/dist/components/hooks/useForm/types.d.ts.map +1 -0
  37. package/dist/components/hooks/useForm/useForm.d.ts +3 -0
  38. package/dist/components/hooks/useForm/useForm.d.ts.map +1 -0
  39. package/dist/components/hooks/useKanban/apiClient.d.ts +99 -0
  40. package/dist/components/hooks/useKanban/apiClient.d.ts.map +1 -0
  41. package/dist/components/hooks/useKanban/context.d.ts +4 -0
  42. package/dist/components/hooks/useKanban/context.d.ts.map +1 -0
  43. package/dist/components/hooks/useKanban/dragDropManager.d.ts +27 -0
  44. package/dist/components/hooks/useKanban/dragDropManager.d.ts.map +1 -0
  45. package/dist/components/hooks/useKanban/index.d.ts +6 -0
  46. package/dist/components/hooks/useKanban/index.d.ts.map +1 -0
  47. package/dist/components/hooks/useKanban/types.d.ts +438 -0
  48. package/dist/components/hooks/useKanban/types.d.ts.map +1 -0
  49. package/dist/components/hooks/useKanban/useKanban.d.ts +3 -0
  50. package/dist/components/hooks/useKanban/useKanban.d.ts.map +1 -0
  51. package/dist/components/hooks/useKanban/useKanbanSimple.d.ts +62 -0
  52. package/dist/components/hooks/useKanban/useKanbanSimple.d.ts.map +1 -0
  53. package/dist/components/hooks/useTable/index.d.ts +3 -0
  54. package/dist/components/hooks/useTable/index.d.ts.map +1 -0
  55. package/dist/components/hooks/useTable/types.d.ts +107 -0
  56. package/dist/components/hooks/useTable/types.d.ts.map +1 -0
  57. package/dist/components/hooks/useTable/useTable.d.ts +8 -0
  58. package/dist/components/hooks/useTable/useTable.d.ts.map +1 -0
  59. package/dist/components/index.d.ts +3 -0
  60. package/dist/components/index.d.ts.map +1 -0
  61. package/dist/components/ui/index.d.ts +2 -0
  62. package/dist/components/ui/index.d.ts.map +1 -0
  63. package/dist/components/ui/kanban/Kanban.d.ts +12 -0
  64. package/dist/components/ui/kanban/Kanban.d.ts.map +1 -0
  65. package/dist/components/ui/kanban/index.d.ts +2 -0
  66. package/dist/components/ui/kanban/index.d.ts.map +1 -0
  67. package/dist/index.cjs +45 -0
  68. package/dist/index.d.ts +5 -0
  69. package/dist/index.d.ts.map +1 -0
  70. package/dist/index.mjs +6522 -0
  71. package/dist/types/base-fields.d.ts +182 -0
  72. package/dist/types/base-fields.d.ts.map +1 -0
  73. package/dist/types/common.d.ts +238 -0
  74. package/dist/types/common.d.ts.map +1 -0
  75. package/dist/types/index.d.ts +3 -0
  76. package/dist/types/index.d.ts.map +1 -0
  77. package/dist/utils/cn.d.ts +7 -0
  78. package/dist/utils/cn.d.ts.map +1 -0
  79. package/dist/utils/formatting.d.ts +52 -0
  80. package/dist/utils/formatting.d.ts.map +1 -0
  81. package/dist/utils/index.d.ts +3 -0
  82. package/dist/utils/index.d.ts.map +1 -0
  83. package/package.json +98 -0
  84. package/sdk/api/client.ts +447 -0
  85. package/sdk/api/datetime.ts +33 -0
  86. package/sdk/api/index.ts +61 -0
  87. package/sdk/api/metadata.ts +148 -0
  88. package/sdk/components/hooks/index.ts +34 -0
  89. package/sdk/components/hooks/useFilter/index.ts +37 -0
  90. package/sdk/components/hooks/useFilter/payloadBuilder.utils.ts +298 -0
  91. package/sdk/components/hooks/useFilter/types.ts +158 -0
  92. package/sdk/components/hooks/useFilter/useFilter.llm.txt +497 -0
  93. package/sdk/components/hooks/useFilter/useFilter.ts +494 -0
  94. package/sdk/components/hooks/useFilter/validation.utils.ts +401 -0
  95. package/sdk/components/hooks/useForm/apiClient.ts +441 -0
  96. package/sdk/components/hooks/useForm/expressionValidator.utils.ts +444 -0
  97. package/sdk/components/hooks/useForm/index.ts +64 -0
  98. package/sdk/components/hooks/useForm/optimizedExpressionValidator.utils.ts +482 -0
  99. package/sdk/components/hooks/useForm/ruleClassifier.utils.ts +424 -0
  100. package/sdk/components/hooks/useForm/schemaParser.utils.ts +519 -0
  101. package/sdk/components/hooks/useForm/types.ts +630 -0
  102. package/sdk/components/hooks/useForm/useForm.llm.txt +340 -0
  103. package/sdk/components/hooks/useForm/useForm.ts +821 -0
  104. package/sdk/components/hooks/useKanban/apiClient.ts +494 -0
  105. package/sdk/components/hooks/useKanban/context.ts +14 -0
  106. package/sdk/components/hooks/useKanban/dragDropManager.ts +529 -0
  107. package/sdk/components/hooks/useKanban/index.ts +63 -0
  108. package/sdk/components/hooks/useKanban/types.ts +606 -0
  109. package/sdk/components/hooks/useKanban/useKanban.llm.txt +482 -0
  110. package/sdk/components/hooks/useKanban/useKanban.ts +725 -0
  111. package/sdk/components/hooks/useKanban/useKanbanSimple.ts +389 -0
  112. package/sdk/components/hooks/useTable/index.ts +5 -0
  113. package/sdk/components/hooks/useTable/types.ts +154 -0
  114. package/sdk/components/hooks/useTable/useTable.llm.txt +344 -0
  115. package/sdk/components/hooks/useTable/useTable.ts +413 -0
  116. package/sdk/components/index.ts +15 -0
  117. package/sdk/components/ui/index.ts +2 -0
  118. package/sdk/components/ui/kanban/Kanban.tsx +134 -0
  119. package/sdk/components/ui/kanban/index.ts +11 -0
  120. package/sdk/index.ts +13 -0
  121. package/sdk/types/base-fields.ts +221 -0
  122. package/sdk/types/common.ts +306 -0
  123. package/sdk/types/index.ts +5 -0
  124. package/sdk/utils/cn.ts +10 -0
  125. package/sdk/utils/formatting.ts +212 -0
  126. package/sdk/utils/index.ts +5 -0
@@ -0,0 +1,441 @@
1
+ // ============================================================
2
+ // API CLIENT FOR FORM OPERATIONS
3
+ // ============================================================
4
+ // Handles schema fetching and form submissions
5
+
6
+ import { api, getBdoSchema } from "../../../api";
7
+ import type { BackendSchema, FormOperation, SubmissionResult } from "./types";
8
+
9
+ // ============================================================
10
+ // SCHEMA FETCHING
11
+ // ============================================================
12
+
13
+ /**
14
+ * Fetch BDO schema from backend metadata endpoint
15
+ */
16
+ export async function fetchFormSchema(source: string): Promise<BackendSchema> {
17
+ try {
18
+ // Use the new metadata API client to fetch BDO schema
19
+ const bdoResp = await getBdoSchema(source);
20
+ const bdoSchema = bdoResp.BOBlob;
21
+
22
+ // Validate that response is a valid BDO schema object
23
+ if (!bdoSchema || typeof bdoSchema !== "object" || !bdoSchema.Fields) {
24
+ throw new Error(`Invalid BDO schema response for ${source}`);
25
+ }
26
+
27
+ // Return the full BDO schema - the form processor will extract what it needs
28
+ return bdoSchema as BackendSchema;
29
+ } catch (error) {
30
+ console.error(`Schema fetch error for ${source}:`, error);
31
+ throw new Error(
32
+ `Failed to load form schema: ${error instanceof Error ? error.message : "Unknown error"}`
33
+ );
34
+ }
35
+ }
36
+
37
+ /**
38
+ * Fetch form schema with retry logic
39
+ */
40
+ export async function fetchFormSchemaWithRetry(
41
+ source: string,
42
+ maxRetries: number = 3
43
+ ): Promise<BackendSchema> {
44
+ let lastError: Error;
45
+
46
+ for (let attempt = 1; attempt <= maxRetries; attempt++) {
47
+ try {
48
+ return await fetchFormSchema(source);
49
+ } catch (error) {
50
+ lastError = error as Error;
51
+
52
+ if (attempt < maxRetries) {
53
+ // Wait before retrying (exponential backoff)
54
+ const delay = Math.min(1000 * Math.pow(2, attempt - 1), 5000);
55
+ await new Promise((resolve) => setTimeout(resolve, delay));
56
+ continue;
57
+ }
58
+ }
59
+ }
60
+
61
+ throw lastError!;
62
+ }
63
+
64
+ // ============================================================
65
+ // RECORD OPERATIONS
66
+ // ============================================================
67
+
68
+ /**
69
+ * Fetch existing record for update operations
70
+ */
71
+ export async function fetchRecord<T = any>(
72
+ source: string,
73
+ recordId: string
74
+ ): Promise<T> {
75
+ try {
76
+ const record = await api<T>(source).get(recordId);
77
+ return record;
78
+ } catch (error) {
79
+ console.error(`Record fetch error for ${source}/${recordId}:`, error);
80
+ throw new Error(
81
+ `Failed to load record: ${error instanceof Error ? error.message : "Unknown error"}`
82
+ );
83
+ }
84
+ }
85
+
86
+ /**
87
+ * Submit form data (create or update)
88
+ */
89
+ export async function submitFormData<T = any>(
90
+ source: string,
91
+ operation: FormOperation,
92
+ data: Partial<T>,
93
+ recordId?: string
94
+ ): Promise<SubmissionResult> {
95
+ try {
96
+ let result;
97
+
98
+ if (operation === "create") {
99
+ result = await api<T>(source).create(data);
100
+ return {
101
+ success: true,
102
+ data: result,
103
+ recordId: result._id || recordId,
104
+ };
105
+ } else if (operation === "update") {
106
+ if (!recordId) {
107
+ throw new Error("Record ID is required for update operations");
108
+ }
109
+
110
+ result = await api<T>(source).update(recordId, data);
111
+ return {
112
+ success: true,
113
+ data: result,
114
+ recordId: result._id || recordId,
115
+ };
116
+ } else {
117
+ throw new Error(`Unsupported operation: ${operation}`);
118
+ }
119
+ } catch (error) {
120
+ console.error(`Form submission error:`, error);
121
+ const submissionError = new Error(
122
+ `Failed to ${operation} record: ${error instanceof Error ? error.message : "Unknown error"}`
123
+ );
124
+
125
+ return {
126
+ success: false,
127
+ error: submissionError,
128
+ };
129
+ }
130
+ }
131
+
132
+ // ============================================================
133
+ // REFERENCE DATA FETCHING
134
+ // ============================================================
135
+
136
+ /**
137
+ * Fetch reference field data
138
+ */
139
+ export async function fetchReferenceData(
140
+ businessObject: string,
141
+ fields: string[] = ["_id"],
142
+ filters?: any,
143
+ sort?: any
144
+ ): Promise<any[]> {
145
+ try {
146
+ const listOptions: any = {};
147
+
148
+ // Add filters if provided
149
+ if (filters) {
150
+ listOptions.Filter = filters;
151
+ }
152
+
153
+ // Add sorting if provided
154
+ if (sort) {
155
+ listOptions.Sort = sort;
156
+ }
157
+
158
+ // Limit fields to what's needed
159
+ if (fields.length > 0) {
160
+ listOptions.Field = fields;
161
+ }
162
+
163
+ const response = await api(businessObject).list(listOptions);
164
+ return response.Data || [];
165
+ } catch (error) {
166
+ console.error(`Reference data fetch error for ${businessObject}:`, error);
167
+ // Don't throw, return empty array to allow form to continue working
168
+ return [];
169
+ }
170
+ }
171
+
172
+ /**
173
+ * Fetch all reference data for a schema
174
+ */
175
+ export async function fetchAllReferenceData(
176
+ referenceFields: Record<string, any>
177
+ ): Promise<Record<string, any[]>> {
178
+ const referenceData: Record<string, any[]> = {};
179
+
180
+ // Fetch all reference data in parallel
181
+ const fetchPromises = Object.entries(referenceFields).map(
182
+ async ([fieldName, config]) => {
183
+ try {
184
+ const data = await fetchReferenceData(
185
+ config.businessObject,
186
+ config.fields,
187
+ config.filters,
188
+ config.sort
189
+ );
190
+ return [fieldName, data];
191
+ } catch (error) {
192
+ console.warn(`Failed to fetch reference data for ${fieldName}:`, error);
193
+ return [fieldName, []];
194
+ }
195
+ }
196
+ );
197
+
198
+ const results = await Promise.allSettled(fetchPromises);
199
+
200
+ results.forEach((result) => {
201
+ if (result.status === "fulfilled") {
202
+ const [fieldName, data] = result.value;
203
+ referenceData[fieldName as string] = Array.isArray(data) ? data : [];
204
+ }
205
+ });
206
+
207
+ return referenceData;
208
+ }
209
+
210
+ // ============================================================
211
+ // VALIDATION HELPERS
212
+ // ============================================================
213
+
214
+ /**
215
+ * Validate form data before submission
216
+ */
217
+ export function validateFormData<T>(
218
+ data: Partial<T>,
219
+ requiredFields: string[]
220
+ ): { isValid: boolean; errors: string[] } {
221
+ const errors: string[] = [];
222
+
223
+ // Check required fields
224
+ for (const field of requiredFields) {
225
+ const value = data[field as keyof T];
226
+ if (value === undefined || value === null || value === "") {
227
+ errors.push(`${field} is required`);
228
+ }
229
+ }
230
+
231
+ return {
232
+ isValid: errors.length === 0,
233
+ errors,
234
+ };
235
+ }
236
+
237
+ /**
238
+ * Clean form data before submission
239
+ * - For create: returns all non-computed, non-undefined fields
240
+ * - For update: returns only fields that changed from originalData
241
+ */
242
+ export function cleanFormData<T>(
243
+ data: Partial<T>,
244
+ computedFields: string[],
245
+ operation: FormOperation = "create",
246
+ originalData?: Partial<T>
247
+ ): Partial<T> {
248
+ const cleanedData: Partial<T> = {};
249
+
250
+ Object.keys(data).forEach((key) => {
251
+ const fieldKey = key as keyof T;
252
+ const value = data[fieldKey];
253
+
254
+ // Skip computed fields
255
+ if (computedFields.includes(key)) {
256
+ return;
257
+ }
258
+
259
+ // Skip undefined values
260
+ if (value === undefined) {
261
+ return;
262
+ }
263
+
264
+ // For create: include all non-computed, non-undefined fields
265
+ if (operation === "create") {
266
+ cleanedData[fieldKey] = value;
267
+ return;
268
+ }
269
+
270
+ // For update: only include fields that changed from original
271
+ if (operation === "update") {
272
+ if (!originalData) {
273
+ // No original data to compare - include the field
274
+ cleanedData[fieldKey] = value;
275
+ return;
276
+ }
277
+
278
+ const originalValue = originalData[fieldKey];
279
+ const hasChanged =
280
+ JSON.stringify(value) !== JSON.stringify(originalValue);
281
+
282
+ if (hasChanged) {
283
+ cleanedData[fieldKey] = value;
284
+ }
285
+ }
286
+ });
287
+
288
+ return cleanedData;
289
+ }
290
+
291
+ // ============================================================
292
+ // ERROR HANDLING
293
+ // ============================================================
294
+
295
+ /**
296
+ * Parse API error response
297
+ */
298
+ export function parseApiError(error: any): string {
299
+ if (typeof error === "string") {
300
+ return error;
301
+ }
302
+
303
+ if (error?.message) {
304
+ return error.message;
305
+ }
306
+
307
+ if (error?.response?.data?.message) {
308
+ return error.response.data.message;
309
+ }
310
+
311
+ if (error?.response?.data?.error) {
312
+ return error.response.data.error;
313
+ }
314
+
315
+ return "An unexpected error occurred";
316
+ }
317
+
318
+ /**
319
+ * Check if error is a network error
320
+ */
321
+ export function isNetworkError(error: any): boolean {
322
+ return (
323
+ !navigator.onLine ||
324
+ error?.code === "NETWORK_ERROR" ||
325
+ error?.message?.toLowerCase().includes("network") ||
326
+ error?.message?.toLowerCase().includes("fetch")
327
+ );
328
+ }
329
+
330
+ /**
331
+ * Check if error is a validation error
332
+ */
333
+ export function isValidationError(error: any): boolean {
334
+ return (
335
+ error?.status === 400 ||
336
+ error?.response?.status === 400 ||
337
+ error?.message?.toLowerCase().includes("validation") ||
338
+ error?.message?.toLowerCase().includes("invalid")
339
+ );
340
+ }
341
+
342
+ // ============================================================
343
+ // CACHE MANAGEMENT
344
+ // ============================================================
345
+
346
+ /**
347
+ * Simple in-memory cache for schemas and reference data
348
+ */
349
+ const cache = new Map<string, { data: any; timestamp: number; ttl: number }>();
350
+
351
+ /**
352
+ * Cache data with TTL
353
+ */
354
+ export function setCacheData(
355
+ key: string,
356
+ data: any,
357
+ ttlMinutes: number = 10
358
+ ): void {
359
+ cache.set(key, {
360
+ data,
361
+ timestamp: Date.now(),
362
+ ttl: ttlMinutes * 60 * 1000,
363
+ });
364
+ }
365
+
366
+ /**
367
+ * Get cached data if not expired
368
+ */
369
+ export function getCacheData(key: string): any | null {
370
+ const item = cache.get(key);
371
+
372
+ if (!item) {
373
+ return null;
374
+ }
375
+
376
+ if (Date.now() - item.timestamp > item.ttl) {
377
+ cache.delete(key);
378
+ return null;
379
+ }
380
+
381
+ return item.data;
382
+ }
383
+
384
+ /**
385
+ * Clear cache
386
+ */
387
+ export function clearCache(keyPrefix?: string): void {
388
+ if (keyPrefix) {
389
+ const keysToDelete = Array.from(cache.keys()).filter((key) =>
390
+ key.startsWith(keyPrefix)
391
+ );
392
+ keysToDelete.forEach((key) => cache.delete(key));
393
+ } else {
394
+ cache.clear();
395
+ }
396
+ }
397
+
398
+ // ============================================================
399
+ // CACHED API FUNCTIONS
400
+ // ============================================================
401
+
402
+ /**
403
+ * Fetch schema with caching
404
+ */
405
+ export async function fetchFormSchemaWithCache(
406
+ source: string
407
+ ): Promise<BackendSchema> {
408
+ const cacheKey = `schema:${source}`;
409
+ const cached = getCacheData(cacheKey);
410
+
411
+ if (cached) {
412
+ return cached;
413
+ }
414
+
415
+ const schema = await fetchFormSchemaWithRetry(source);
416
+ setCacheData(cacheKey, schema, 30); // Cache for 30 minutes
417
+
418
+ return schema;
419
+ }
420
+
421
+ /**
422
+ * Fetch reference data with caching
423
+ */
424
+ export async function fetchReferenceDataWithCache(
425
+ businessObject: string,
426
+ fields: string[] = ["_id"],
427
+ filters?: any,
428
+ sort?: any
429
+ ): Promise<any[]> {
430
+ const cacheKey = `reference:${businessObject}:${JSON.stringify({ fields, filters, sort })}`;
431
+ const cached = getCacheData(cacheKey);
432
+
433
+ if (cached) {
434
+ return cached;
435
+ }
436
+
437
+ const data = await fetchReferenceData(businessObject, fields, filters, sort);
438
+ setCacheData(cacheKey, data, 5); // Cache for 5 minutes
439
+
440
+ return data;
441
+ }