@ram_28/kf-ai-sdk 2.0.16 → 2.0.18

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 (105) hide show
  1. package/README.md +16 -8
  2. package/dist/{FileField-BWrSHNRq.js → FileField-CZjS2uLh.js} +3 -3
  3. package/dist/{FileField-eDeuzln8.cjs → FileField-DU4UWo_t.cjs} +1 -1
  4. package/dist/api.cjs +1 -1
  5. package/dist/api.mjs +1 -1
  6. package/dist/auth/authConfig.d.ts +1 -1
  7. package/dist/auth/types.d.ts +1 -1
  8. package/dist/auth/types.d.ts.map +1 -1
  9. package/dist/auth.cjs +1 -1
  10. package/dist/auth.mjs +1 -1
  11. package/dist/bdo/core/Item.d.ts +0 -4
  12. package/dist/bdo/core/Item.d.ts.map +1 -1
  13. package/dist/bdo/fields/ReferenceField.d.ts +1 -1
  14. package/dist/bdo/fields/ReferenceField.d.ts.map +1 -1
  15. package/dist/bdo/fields/SelectField.d.ts +1 -1
  16. package/dist/bdo/fields/SelectField.d.ts.map +1 -1
  17. package/dist/bdo/fields/UserField.d.ts +1 -1
  18. package/dist/bdo/fields/UserField.d.ts.map +1 -1
  19. package/dist/bdo.cjs +1 -1
  20. package/dist/bdo.mjs +53 -62
  21. package/dist/components/hooks/useActivityForm/types.d.ts +4 -5
  22. package/dist/components/hooks/useActivityForm/types.d.ts.map +1 -1
  23. package/dist/components/hooks/useActivityForm/useActivityForm.d.ts.map +1 -1
  24. package/dist/components/hooks/useActivityTable/types.d.ts +5 -4
  25. package/dist/components/hooks/useActivityTable/types.d.ts.map +1 -1
  26. package/dist/components/hooks/useActivityTable/useActivityTable.d.ts.map +1 -1
  27. package/dist/components/hooks/useBDOForm/createItemProxy.d.ts +2 -3
  28. package/dist/components/hooks/useBDOForm/createItemProxy.d.ts.map +1 -1
  29. package/dist/components/hooks/useBDOTable/types.d.ts +20 -12
  30. package/dist/components/hooks/useBDOTable/types.d.ts.map +1 -1
  31. package/dist/components/hooks/useBDOTable/useBDOTable.d.ts +2 -2
  32. package/dist/components/hooks/useBDOTable/useBDOTable.d.ts.map +1 -1
  33. package/dist/{constants-ConHc1oS.js → constants-Cyi942Yr.js} +5 -5
  34. package/dist/constants-DEmYwKfC.cjs +1 -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 +226 -243
  39. package/dist/table.cjs +1 -1
  40. package/dist/table.mjs +15 -16
  41. package/dist/table.types.d.ts +1 -1
  42. package/dist/table.types.d.ts.map +1 -1
  43. package/dist/types/constants.d.ts +1 -1
  44. package/dist/workflow/Activity.d.ts +8 -5
  45. package/dist/workflow/Activity.d.ts.map +1 -1
  46. package/dist/workflow.cjs +1 -1
  47. package/dist/workflow.mjs +461 -476
  48. package/docs/README.md +57 -0
  49. package/docs/bdo/README.md +161 -0
  50. package/docs/bdo/api_reference.md +281 -0
  51. package/docs/examples/bdo/create-product.md +69 -0
  52. package/docs/examples/bdo/edit-product-dialog.md +95 -0
  53. package/docs/examples/bdo/filtered-product-table.md +100 -0
  54. package/docs/examples/bdo/product-listing.md +73 -0
  55. package/docs/examples/bdo/supplier-dropdown.md +60 -0
  56. package/docs/examples/fields/complex-fields.md +248 -0
  57. package/docs/examples/fields/primitive-fields.md +217 -0
  58. package/docs/examples/workflow/approve-leave-request.md +76 -0
  59. package/docs/examples/workflow/filtered-activity-table.md +101 -0
  60. package/docs/examples/workflow/my-pending-requests.md +90 -0
  61. package/docs/examples/workflow/start-new-workflow.md +47 -0
  62. package/docs/examples/workflow/submit-leave-request.md +72 -0
  63. package/docs/examples/workflow/workflow-progress.md +49 -0
  64. package/docs/fields/README.md +141 -0
  65. package/docs/fields/api_reference.md +134 -0
  66. package/docs/useActivityForm/README.md +244 -0
  67. package/docs/useActivityForm/api_reference.md +279 -0
  68. package/docs/useActivityTable/README.md +263 -0
  69. package/docs/useActivityTable/api_reference.md +294 -0
  70. package/docs/useBDOForm/README.md +175 -0
  71. package/docs/useBDOForm/api_reference.md +244 -0
  72. package/docs/useBDOTable/README.md +242 -0
  73. package/docs/useBDOTable/api_reference.md +253 -0
  74. package/docs/useFilter/README.md +323 -0
  75. package/docs/useFilter/api_reference.md +228 -0
  76. package/docs/workflow/README.md +158 -0
  77. package/docs/workflow/api_reference.md +161 -0
  78. package/package.json +1 -1
  79. package/sdk/auth/authConfig.ts +1 -1
  80. package/sdk/auth/types.ts +1 -1
  81. package/sdk/bdo/core/Item.ts +1 -10
  82. package/sdk/bdo/fields/ReferenceField.ts +1 -1
  83. package/sdk/bdo/fields/SelectField.ts +1 -1
  84. package/sdk/bdo/fields/UserField.ts +1 -1
  85. package/sdk/components/hooks/useActivityForm/types.ts +4 -6
  86. package/sdk/components/hooks/useActivityForm/useActivityForm.ts +10 -73
  87. package/sdk/components/hooks/useActivityTable/types.ts +4 -5
  88. package/sdk/components/hooks/useActivityTable/useActivityTable.ts +10 -8
  89. package/sdk/components/hooks/useBDOForm/createItemProxy.ts +17 -58
  90. package/sdk/components/hooks/useBDOTable/types.ts +20 -10
  91. package/sdk/components/hooks/useBDOTable/useBDOTable.ts +12 -8
  92. package/sdk/table.types.ts +2 -0
  93. package/sdk/types/constants.ts +1 -1
  94. package/sdk/workflow/Activity.ts +39 -7
  95. package/dist/constants-QX2RX-wu.cjs +0 -1
  96. package/docs/api.md +0 -95
  97. package/docs/bdo.md +0 -224
  98. package/docs/gaps.md +0 -360
  99. package/docs/useActivityForm.md +0 -393
  100. package/docs/useActivityTable.md +0 -418
  101. package/docs/useBDOForm.md +0 -376
  102. package/docs/useBDOTable.md +0 -284
  103. package/docs/useFilter.md +0 -188
  104. package/docs/workflow.md +0 -560
  105. /package/docs/{useAuth.md → useAuth/README.md} +0 -0
@@ -10,12 +10,9 @@ import { useForm as useReactHookForm } from 'react-hook-form';
10
10
  import { useQuery } from '@tanstack/react-query';
11
11
 
12
12
  import type { Activity } from '../../../workflow/Activity';
13
- import type {
14
- UseActivityFormOptions,
15
- UseActivityFormReturn,
16
- AllActivityFields,
17
- } from './types';
13
+ import type { UseActivityFormOptions, UseActivityFormReturn } from './types';
18
14
 
15
+ import type { CreateUpdateResponseType } from '../../../types/common';
19
16
  import { createActivityResolver } from './createActivityResolver';
20
17
  import { createActivityItemProxy } from './createActivityItemProxy';
21
18
  import {
@@ -300,13 +297,13 @@ export function useActivityForm<A extends Activity<any, any, any>>(
300
297
  );
301
298
 
302
299
  // ============================================================
303
- // HANDLE SUBMIT — activity.update()
300
+ // HANDLE SUBMIT — activity.update() + activity.complete()
304
301
  // ============================================================
305
302
 
306
303
  const handleSubmit = useCallback(
307
304
  (
308
305
  onSuccess?: (
309
- data: AllActivityFields<A>,
306
+ data: CreateUpdateResponseType,
310
307
  e?: React.BaseSyntheticEvent,
311
308
  ) => void | Promise<void>,
312
309
  onError?: (
@@ -319,7 +316,7 @@ export function useActivityForm<A extends Activity<any, any, any>>(
319
316
  setIsSubmitting(true);
320
317
 
321
318
  try {
322
- // Only send dirty (changed) fields — matches useBDOForm update behavior
319
+ // Only send dirty (changed) fields — matches useBDOForm behavior
323
320
  // Use getValues() to capture Image/File values set via setValue()
324
321
  // that RHF resolver doesn't include in `data`
325
322
  const cleanedData: Record<string, unknown> = {};
@@ -339,7 +336,7 @@ export function useActivityForm<A extends Activity<any, any, any>>(
339
336
  : value;
340
337
  }
341
338
 
342
- // Save via activity.update()
339
+ // Send remaining dirty fields via update
343
340
  if (Object.keys(cleanedData).length > 0) {
344
341
  await activityRef.update(
345
342
  activity_instance_id,
@@ -347,69 +344,10 @@ export function useActivityForm<A extends Activity<any, any, any>>(
347
344
  );
348
345
  }
349
346
 
350
- await onSuccess?.(data as AllActivityFields<A>, event);
351
- } catch (error) {
352
- onError?.(toError(error), event);
353
- } finally {
354
- setIsSubmitting(false);
355
- }
356
- },
357
- (errors, event) => {
358
- onError?.(errors, event);
359
- },
360
- );
361
- },
362
- [rhf, activityRef, readonlyFieldNames, allFields, activity_instance_id],
363
- ) as UseActivityFormReturn<A>['handleSubmit'];
364
-
365
- // ============================================================
366
- // HANDLE COMPLETE — activity.update() + activity.complete()
367
- // ============================================================
368
-
369
- const handleComplete = useCallback(
370
- (
371
- onSuccess?: (
372
- data: AllActivityFields<A>,
373
- e?: React.BaseSyntheticEvent,
374
- ) => void | Promise<void>,
375
- onError?: (
376
- error: any,
377
- e?: React.BaseSyntheticEvent,
378
- ) => void | Promise<void>,
379
- ) => {
380
- return rhf.handleSubmit(
381
- async (data, event) => {
382
- setIsSubmitting(true);
383
-
384
- try {
385
- // Only send dirty (changed) fields — matches useBDOForm update behavior
386
- // Use getValues() to capture Image/File values set via setValue()
387
- // that RHF resolver doesn't include in `data`
388
- const cleanedData: Record<string, unknown> = {};
389
- const readonlySet = new Set(readonlyFieldNames);
390
- const dirtyFields = rhf.formState.dirtyFields;
391
- const allValues = rhf.getValues() as Record<string, unknown>;
392
-
393
- for (const key of Object.keys(allValues)) {
394
- if (readonlySet.has(key) || !dirtyFields[key]) continue;
395
- const value =
396
- allValues[key] !== undefined
397
- ? allValues[key]
398
- : (data as Record<string, unknown>)[key];
399
- const field = allFields[key];
400
- cleanedData[key] = field
401
- ? coerceFieldValue(field, value)
402
- : value;
403
- }
347
+ // Complete the activity — advances the workflow
348
+ const result = await activityRef.complete(activity_instance_id);
404
349
 
405
- if (Object.keys(cleanedData).length > 0) {
406
- await activityRef.update(
407
- activity_instance_id,
408
- cleanedData as any,
409
- );
410
- }
411
- await activityRef.complete(activity_instance_id);
412
- await onSuccess?.(data as AllActivityFields<A>, event);
350
+ await onSuccess?.(result, event);
413
351
  } catch (error) {
414
352
  onError?.(toError(error), event);
415
353
  } finally {
@@ -422,7 +360,7 @@ export function useActivityForm<A extends Activity<any, any, any>>(
422
360
  );
423
361
  },
424
362
  [rhf, activityRef, readonlyFieldNames, allFields, activity_instance_id],
425
- ) as UseActivityFormReturn<A>['handleComplete'];
363
+ ) as UseActivityFormReturn<A>['handleSubmit'];
426
364
 
427
365
  // ============================================================
428
366
  // CLEAR ERRORS
@@ -448,7 +386,6 @@ export function useActivityForm<A extends Activity<any, any, any>>(
448
386
  // Form methods
449
387
  register,
450
388
  handleSubmit,
451
- handleComplete,
452
389
  watch: rhf.watch as any,
453
390
  setValue: rhf.setValue as any,
454
391
  getValues: rhf.getValues as any,
@@ -1,5 +1,4 @@
1
1
  import type { Activity } from '../../../workflow/Activity';
2
- import type { ActivityInstanceFieldsType } from '../../../workflow/types';
3
2
  import type { UseTableReturnType, PaginationStateType } from '../useTable/types';
4
3
  import type { UseFilterOptionsType } from '../useFilter/types';
5
4
  import type { SortType } from '../../../types/common';
@@ -16,12 +15,12 @@ export type ActivityTableStatusType =
16
15
  (typeof ActivityTableStatus)[keyof typeof ActivityTableStatus];
17
16
 
18
17
  /**
19
- * Row type for activity table data.
20
- * System fields and entity fields are flat at the top level.
18
+ * Row type inferred from Activity's getInProgressList() return type.
19
+ * Resolves to ActivityInstanceType (proxy with .get()/.set()).
21
20
  */
22
21
  export type ActivityRowType<A extends Activity<any, any, any>> =
23
- A extends Activity<infer E, any, any>
24
- ? ActivityInstanceFieldsType & E
22
+ A extends { getInProgressList(opts?: any): Promise<(infer R)[]> }
23
+ ? R
25
24
  : never;
26
25
 
27
26
  export interface UseActivityTableOptionsType<
@@ -13,22 +13,24 @@ export function useActivityTable<A extends Activity<any, any, any>>(
13
13
  const { activity, status, ...rest } = options;
14
14
  const { businessProcessId, activityId } = activity.meta;
15
15
 
16
- const ops = useMemo(() => activity._getOps(), [activity]);
17
-
18
16
  const listFn = useMemo(
19
17
  () =>
20
18
  status === 'inprogress'
21
- ? (opts: any) => ops.inProgressList(opts)
22
- : (opts: any) => ops.completedList(opts),
23
- [ops, status],
19
+ ? async (opts: any) => ({
20
+ Data: (await activity.getInProgressList(opts)) as ActivityRowType<A>[],
21
+ })
22
+ : async (opts: any) => ({
23
+ Data: (await activity.getCompletedList(opts)) as ActivityRowType<A>[],
24
+ }),
25
+ [activity, status],
24
26
  );
25
27
 
26
28
  const countFn = useMemo(
27
29
  () =>
28
30
  status === 'inprogress'
29
- ? (opts: any) => ops.inProgressCount(opts)
30
- : (opts: any) => ops.completedCount(opts),
31
- [ops, status],
31
+ ? async (opts: any) => ({ Count: await activity.inProgressCount(opts) })
32
+ : async (opts: any) => ({ Count: await activity.completedCount(opts) }),
33
+ [activity, status],
32
34
  );
33
35
 
34
36
  return useTable<ActivityRowType<A>>({
@@ -21,9 +21,8 @@ import type {
21
21
  * Key principle: Item has NO state. It's a view over RHF's state.
22
22
  * Editable fields get set(), readonly fields do not.
23
23
  *
24
- * Draft-based upload: In create mode (no _id), upload() automatically creates
25
- * a draft record via draftInteraction() to get an _id, then uploads immediately.
26
- * On form submit, if a draft _id exists, update() is used instead of create().
24
+ * In create mode (no _id), attachment and fetch operations use 'draft' as the
25
+ * instanceId, which the backend accepts as a placeholder.
27
26
  *
28
27
  * @param bdo - The BDO instance for field metadata
29
28
  * @param form - The RHF useForm return object
@@ -36,34 +35,11 @@ export function createItemProxy<B extends BaseBdo<any, any, any>>(
36
35
  const fields = bdo.getFields();
37
36
  const accessorCache = new Map<string, EditableFormFieldAccessorType<unknown> | ReadonlyFormFieldAccessorType<unknown>>();
38
37
 
39
- // Draft tracking for create mode — shared across all attachment fields in this form
40
38
  const boIdShared = bdo.getBoId();
41
- let draftId: string | null = null;
42
- let draftPromise: Promise<string> | null = null;
43
-
44
- /**
45
- * Ensures a record _id exists for attachment uploads.
46
- * In edit mode, returns the existing _id.
47
- * In create mode, creates a draft record via draftInteraction() to get an _id.
48
- * The draft _id is shared across all attachment fields and only created once.
49
- */
50
- async function ensureDraft(): Promise<string> {
51
- // If form already has an _id (edit mode or previous draft), use it
52
- const existing = form.getValues("_id" as Path<FieldValues>) as string | undefined;
53
- if (existing) return existing;
54
- if (draftId) return draftId;
55
- if (!draftPromise) {
56
- draftPromise = api(boIdShared).draftInteraction({}).then((d: any) => {
57
- draftId = d._id;
58
- form.setValue("_id" as Path<FieldValues>, draftId as any, { shouldDirty: false });
59
- return draftId!;
60
- }).catch((err: Error) => {
61
- draftPromise = null;
62
- throw err;
63
- });
64
- }
65
- return draftPromise;
66
- }
39
+
40
+ /** Returns the real _id in edit mode, or 'draft' in create mode */
41
+ const getInstanceId = (): string =>
42
+ (form.getValues("_id" as Path<FieldValues>) as string) || "draft";
67
43
 
68
44
  return new Proxy({} as FormItemType<ExtractEditableType<B>, ExtractReadonlyType<B>>, {
69
45
  get(_, prop: string | symbol) {
@@ -87,11 +63,6 @@ export function createItemProxy<B extends BaseBdo<any, any, any>>(
87
63
  return () => form.trigger();
88
64
  }
89
65
 
90
- // Internal: check if a draft was created (used by handleSubmit)
91
- if (prop === "_hasDraft") {
92
- return () => !!draftId;
93
- }
94
-
95
66
  // Return cached accessor if available
96
67
  if (accessorCache.has(prop)) {
97
68
  return accessorCache.get(prop);
@@ -182,17 +153,12 @@ export function createItemProxy<B extends BaseBdo<any, any, any>>(
182
153
  // Enrich Image/File field accessors with attachment methods (draft-based upload)
183
154
  if (fieldMeta.Type === "Image" || fieldMeta.Type === "File") {
184
155
  const boId = boIdShared;
185
- const requireInstanceId = (): string => {
186
- const id = form.getValues("_id" as Path<FieldValues>) as string | undefined;
187
- if (!id) throw new Error("Save the record before attachment operations");
188
- return id;
189
- };
190
156
 
191
157
  if (fieldMeta.Type === "Image") {
192
158
  // Image: single file upload — always uploads immediately (draft in create mode)
193
159
  (accessor as any).upload = async (file: File): Promise<FileType> => {
194
160
  validateFileExtension(file.name, "Image");
195
- const id = await ensureDraft();
161
+ const id = getInstanceId();
196
162
 
197
163
  const [uploadInfo] = await api(boId).getUploadUrl(id, prop, [
198
164
  { FileName: file.name, Size: file.size, FileExtension: extractFileExtension(file.name) },
@@ -216,7 +182,7 @@ export function createItemProxy<B extends BaseBdo<any, any, any>>(
216
182
 
217
183
  (accessor as any).deleteAttachment = async (): Promise<void> => {
218
184
  const val = form.getValues(prop as Path<FieldValues>) as any;
219
- const instanceId = requireInstanceId();
185
+ const instanceId = getInstanceId();
220
186
  if (!(val?._id)) throw new Error(`${prop} has no image to delete`);
221
187
  await api(boId).deleteAttachment(instanceId, prop, val._id);
222
188
  form.setValue(prop as Path<FieldValues>, null as any, { shouldDirty: true });
@@ -224,7 +190,7 @@ export function createItemProxy<B extends BaseBdo<any, any, any>>(
224
190
 
225
191
  (accessor as any).getDownloadUrl = async (viewType?: AttachmentViewType): Promise<FileDownloadResponseType> => {
226
192
  const val = form.getValues(prop as Path<FieldValues>) as any;
227
- const instanceId = requireInstanceId();
193
+ const instanceId = getInstanceId();
228
194
  if (!(val?._id)) throw new Error(`${prop} has no image`);
229
195
  return api(boId).getDownloadUrl(instanceId, prop, val._id, viewType);
230
196
  };
@@ -232,7 +198,7 @@ export function createItemProxy<B extends BaseBdo<any, any, any>>(
232
198
  // File field — multi-file, always uploads immediately (draft in create mode)
233
199
  (accessor as any).upload = async (files: File[]): Promise<FileType[]> => {
234
200
  for (const file of files) validateFileExtension(file.name, "File");
235
- const id = await ensureDraft();
201
+ const id = getInstanceId();
236
202
 
237
203
  const requests = files.map((file) => ({
238
204
  FileName: file.name,
@@ -264,7 +230,7 @@ export function createItemProxy<B extends BaseBdo<any, any, any>>(
264
230
 
265
231
  (accessor as any).deleteAttachment = async (attachmentId: string): Promise<void> => {
266
232
  const current = (form.getValues(prop as Path<FieldValues>) as any[]) ?? [];
267
- const instanceId = requireInstanceId();
233
+ const instanceId = getInstanceId();
268
234
  await api(boId).deleteAttachment(instanceId, prop, attachmentId);
269
235
  form.setValue(
270
236
  prop as Path<FieldValues>,
@@ -277,13 +243,13 @@ export function createItemProxy<B extends BaseBdo<any, any, any>>(
277
243
  attachmentId: string,
278
244
  viewType?: AttachmentViewType,
279
245
  ): Promise<FileDownloadResponseType> => {
280
- const instanceId = requireInstanceId();
246
+ const instanceId = getInstanceId();
281
247
  return api(boId).getDownloadUrl(instanceId, prop, attachmentId, viewType);
282
248
  };
283
249
  (accessor as any).getDownloadUrls = async (
284
250
  viewType?: AttachmentViewType,
285
251
  ): Promise<FileDownloadResponseType[]> => {
286
- const instanceId = requireInstanceId();
252
+ const instanceId = getInstanceId();
287
253
  return api(boId).getDownloadUrls(instanceId, prop, viewType);
288
254
  };
289
255
  }
@@ -314,16 +280,11 @@ export function createItemProxy<B extends BaseBdo<any, any, any>>(
314
280
  // Enrich readonly Image/File field accessors with download methods
315
281
  if (fieldMeta.Type === "Image" || fieldMeta.Type === "File") {
316
282
  const boId = boIdShared;
317
- const requireInstanceId = (): string => {
318
- const id = form.getValues("_id" as Path<FieldValues>) as string | undefined;
319
- if (!id) throw new Error("Cannot perform attachment operation: item has no _id. Save the item first.");
320
- return id;
321
- };
322
283
 
323
284
  if (fieldMeta.Type === "Image") {
324
285
  (accessor as any).getDownloadUrl = async (viewType?: AttachmentViewType): Promise<FileDownloadResponseType> => {
325
286
  const val = form.getValues(prop as Path<FieldValues>) as any;
326
- const instanceId = requireInstanceId();
287
+ const instanceId = getInstanceId();
327
288
  if (!(val?._id)) throw new Error(`${prop} has no image to download`);
328
289
  return api(boId).getDownloadUrl(instanceId, prop, val._id, viewType);
329
290
  };
@@ -332,13 +293,13 @@ export function createItemProxy<B extends BaseBdo<any, any, any>>(
332
293
  attachmentId: string,
333
294
  viewType?: AttachmentViewType,
334
295
  ): Promise<FileDownloadResponseType> => {
335
- const instanceId = requireInstanceId();
296
+ const instanceId = getInstanceId();
336
297
  return api(boId).getDownloadUrl(instanceId, prop, attachmentId, viewType);
337
298
  };
338
299
  (accessor as any).getDownloadUrls = async (
339
300
  viewType?: AttachmentViewType,
340
301
  ): Promise<FileDownloadResponseType[]> => {
341
- const instanceId = requireInstanceId();
302
+ const instanceId = getInstanceId();
342
303
  return api(boId).getDownloadUrls(instanceId, prop, viewType);
343
304
  };
344
305
  }
@@ -352,8 +313,6 @@ export function createItemProxy<B extends BaseBdo<any, any, any>>(
352
313
  if (typeof prop === "symbol") return false;
353
314
  if (prop === "_id" || prop === "toJSON" || prop === "validate")
354
315
  return true;
355
- if (prop === "_hasDraft")
356
- return true;
357
316
  return prop in fields;
358
317
  },
359
318
 
@@ -365,7 +324,7 @@ export function createItemProxy<B extends BaseBdo<any, any, any>>(
365
324
  if (typeof prop === "symbol") return undefined;
366
325
  return {
367
326
  configurable: true,
368
- enumerable: prop !== "toJSON" && prop !== "validate" && prop !== "_hasDraft",
327
+ enumerable: prop !== "toJSON" && prop !== "validate",
369
328
  };
370
329
  },
371
330
  });
@@ -1,22 +1,32 @@
1
+ import type { ListOptionsType, SortType } from '../../../types/common';
1
2
  import type { UseTableReturnType, PaginationStateType } from '../useTable/types';
2
3
  import type { UseFilterOptionsType } from '../useFilter/types';
3
- import type { SortType } from '../../../types/common';
4
4
 
5
- export interface UseBDOTableOptionsType<T> {
6
- /** BDO instance — only meta._id is used (for API routing) */
7
- bdo: {
8
- meta: { readonly _id: string; readonly name: string };
9
- };
5
+ /** Structural constraint — any object with list() and count() */
6
+ export interface BDOTableSourceType {
7
+ meta: { readonly _id: string; readonly name: string };
8
+ list(options?: ListOptionsType): Promise<any[]>;
9
+ count(options?: ListOptionsType): Promise<number>;
10
+ }
11
+
12
+ /** Infer row type from BDO's list() return type */
13
+ export type BDORowType<B extends BDOTableSourceType> =
14
+ B extends { list(opts?: any): Promise<(infer R)[]> } ? R : never;
15
+
16
+ export interface UseBDOTableOptionsType<B extends BDOTableSourceType> {
17
+ /** BDO instance — list() and count() are called for data */
18
+ bdo: B;
10
19
  /** Initial state */
11
20
  initialState?: {
12
21
  sort?: SortType;
13
22
  pagination?: PaginationStateType;
14
- filter?: UseFilterOptionsType<T>;
23
+ filter?: UseFilterOptionsType<BDORowType<B>>;
15
24
  };
16
25
  /** Error callback */
17
26
  onError?: (error: Error) => void;
18
- /** Success callback — receives rows from current page */
19
- onSuccess?: (data: T[]) => void;
27
+ /** Success callback — receives Item rows from current page */
28
+ onSuccess?: (data: BDORowType<B>[]) => void;
20
29
  }
21
30
 
22
- export type UseBDOTableReturnType<T> = UseTableReturnType<T>;
31
+ export type UseBDOTableReturnType<B extends BDOTableSourceType> =
32
+ UseTableReturnType<BDORowType<B>>;
@@ -1,16 +1,20 @@
1
- import { api } from '../../../api/client';
2
1
  import { useTable } from '../useTable';
3
- import type { UseBDOTableOptionsType, UseBDOTableReturnType } from './types';
2
+ import type {
3
+ BDOTableSourceType,
4
+ BDORowType,
5
+ UseBDOTableOptionsType,
6
+ UseBDOTableReturnType,
7
+ } from './types';
4
8
 
5
- export function useBDOTable<T = any>(
6
- options: UseBDOTableOptionsType<T>,
7
- ): UseBDOTableReturnType<T> {
9
+ export function useBDOTable<B extends BDOTableSourceType>(
10
+ options: UseBDOTableOptionsType<B>,
11
+ ): UseBDOTableReturnType<B> {
8
12
  const { bdo, ...rest } = options;
9
13
 
10
- return useTable<T>({
14
+ return useTable<BDORowType<B>>({
11
15
  queryKey: ['table', bdo.meta._id],
12
- listFn: (opts) => api<T>(bdo.meta._id).list(opts),
13
- countFn: (opts) => api<T>(bdo.meta._id).count(opts),
16
+ listFn: async (opts) => ({ Data: await bdo.list(opts) }),
17
+ countFn: async (opts) => ({ Count: await bdo.count(opts) }),
14
18
  ...rest,
15
19
  });
16
20
  }
@@ -14,6 +14,8 @@ export type {
14
14
 
15
15
  export type {
16
16
  // BDO wrapper types
17
+ BDOTableSourceType,
18
+ BDORowType,
17
19
  UseBDOTableOptionsType,
18
20
  UseBDOTableReturnType,
19
21
  } from './components/hooks/useBDOTable/types';
@@ -351,7 +351,7 @@ export const AuthStatus = {
351
351
  */
352
352
  export const AuthProviderName = {
353
353
  Google: "google",
354
- Microsoft: "microsoft",
354
+ Azure: "azure",
355
355
  GitHub: "github",
356
356
  Custom: "custom",
357
357
  } as const;
@@ -23,13 +23,15 @@ import { createActivityInstance } from "./ActivityInstance";
23
23
  import type { ActivityInstanceType } from "./ActivityInstance";
24
24
  import type { ActivityInstanceFieldsType, ActivityOperations } from "./types";
25
25
  import type {
26
- ListResponseType,
27
26
  ListOptionsType,
28
27
  MetricOptionsType,
29
28
  MetricResponseType,
30
29
  } from "../types/common";
31
30
  import { BaseField } from "../bdo/fields/BaseField";
32
31
 
32
+ /** Activity system fields treated as readonly on list results */
33
+ type ActivitySystemReadonlyType = Omit<ActivityInstanceFieldsType, '_id'>;
34
+
33
35
  // ============================================================
34
36
  // ABSTRACT BASE CLASS
35
37
  // ============================================================
@@ -128,18 +130,48 @@ export abstract class Activity<
128
130
 
129
131
  /**
130
132
  * List in-progress activity instances.
131
- * Accepts optional filter/sort/pagination options.
133
+ * Each row is wrapped in an ActivityInstance proxy with field accessors.
132
134
  */
133
- async getInProgressList(options?: ListOptionsType): Promise<ListResponseType<ActivityInstanceFieldsType & TEntity>> {
134
- return this._ops().inProgressList(options);
135
+ async getInProgressList(
136
+ options?: ListOptionsType,
137
+ ): Promise<ActivityInstanceType<
138
+ ActivityInstanceFieldsType & TEntity,
139
+ TEditable,
140
+ TReadonly & ActivitySystemReadonlyType
141
+ >[]> {
142
+ const ops = this._ops();
143
+ const response = await ops.inProgressList(options);
144
+ const fields = this._discoverFields();
145
+ return response.Data.map((data) =>
146
+ createActivityInstance<
147
+ ActivityInstanceFieldsType & TEntity,
148
+ TEditable,
149
+ TReadonly & ActivitySystemReadonlyType
150
+ >(ops, (data as any)._id, data as (ActivityInstanceFieldsType & TEntity), fields),
151
+ );
135
152
  }
136
153
 
137
154
  /**
138
155
  * List completed activity instances.
139
- * Accepts optional filter/sort/pagination options.
156
+ * Each row is wrapped in an ActivityInstance proxy with field accessors.
140
157
  */
141
- async getCompletedList(options?: ListOptionsType): Promise<ListResponseType<ActivityInstanceFieldsType & TEntity>> {
142
- return this._ops().completedList(options);
158
+ async getCompletedList(
159
+ options?: ListOptionsType,
160
+ ): Promise<ActivityInstanceType<
161
+ ActivityInstanceFieldsType & TEntity,
162
+ TEditable,
163
+ TReadonly & ActivitySystemReadonlyType
164
+ >[]> {
165
+ const ops = this._ops();
166
+ const response = await ops.completedList(options);
167
+ const fields = this._discoverFields();
168
+ return response.Data.map((data) =>
169
+ createActivityInstance<
170
+ ActivityInstanceFieldsType & TEntity,
171
+ TEditable,
172
+ TReadonly & ActivitySystemReadonlyType
173
+ >(ops, (data as any)._id, data as (ActivityInstanceFieldsType & TEntity), fields),
174
+ );
143
175
  }
144
176
 
145
177
  /**
@@ -1 +0,0 @@
1
- "use strict";const t={EQ:"EQ",NE:"NE",GT:"GT",GTE:"GTE",LT:"LT",LTE:"LTE",Between:"Between",NotBetween:"NotBetween",IN:"IN",NIN:"NIN",Empty:"Empty",NotEmpty:"NotEmpty",Contains:"Contains",NotContains:"NotContains",MinLength:"MinLength",MaxLength:"MaxLength",Length:"Length"},e={And:"And",Or:"Or",Not:"Not"},n={Constant:"Constant",BDOField:"BDOField",AppVariable:"AppVariable"},o={ASC:"ASC",DESC:"DESC"},i={Sum:"Sum",Avg:"Avg",Count:"Count",Max:"Max",Min:"Min",DistinctCount:"DistinctCount",BlankCount:"BlankCount",NotBlankCount:"NotBlankCount",Concat:"Concat",DistinctConcat:"DistinctConcat"},a={List:"List",Metric:"Metric",Pivot:"Pivot"},c={Create:"create",Update:"update"},r={Interactive:"interactive",NonInteractive:"non-interactive"},s={OnBlur:"onBlur",OnChange:"onChange",OnSubmit:"onSubmit",OnTouched:"onTouched",All:"all"},d={Loading:"loading",Authenticated:"authenticated",Unauthenticated:"unauthenticated"},u={Google:"google",Microsoft:"microsoft",GitHub:"github",Custom:"custom"},C={Id:"_id",CreatedAt:"_created_at",ModifiedAt:"_modified_at",CreatedBy:"_created_by",ModifiedBy:"_modified_by",Version:"_version",MergeVersion:"_m_version"},E={GET:"GET",POST:"POST",PATCH:"PATCH",DELETE:"DELETE"},p={SEARCH_DEBOUNCE_MS:300,PAGE_SIZE:10,PAGE:1,SEARCH_MAX_LENGTH:255},T={Date:"$__d__",DateTime:"$__dt__"},l={Success:"success"};exports.AuthProviderName=u;exports.AuthStatus=d;exports.ConditionOperator=t;exports.DateEncodingKey=T;exports.Defaults=p;exports.DeleteStatus=l;exports.FormOperation=c;exports.GroupOperator=e;exports.HttpMethod=E;exports.InteractionMode=r;exports.MetricType=i;exports.QueryType=a;exports.RHSType=n;exports.SortDirection=o;exports.SystemField=C;exports.ValidationMode=s;
package/docs/api.md DELETED
@@ -1,95 +0,0 @@
1
- # API Types Reference
2
-
3
- Request and response types for BDO methods. For usage patterns, see [bdo.md](bdo.md).
4
-
5
- ## Imports
6
-
7
- ```typescript
8
- import { api } from "@ram_28/kf-ai-sdk/api";
9
- import type { ListOptionsType, CreateUpdateResponseType, DeleteResponseType, DraftResponseType, MetricOptionsType, MetricResponseType, PivotOptionsType, PivotResponseType } from "@ram_28/kf-ai-sdk/api/types";
10
- ```
11
-
12
- ---
13
-
14
- ## Common Mistakes (READ FIRST)
15
-
16
- ### 1. Calling `api` directly instead of as factory
17
-
18
- ```typescript
19
- // ❌ WRONG — api is a function, not a client
20
- api.get(id); api.delete(id);
21
-
22
- // ✅ CORRECT — call api(boId) first
23
- api(bdo.meta._id).get(id);
24
- api(bdo.meta._id).delete(id);
25
- ```
26
-
27
- ### 2. Using `api()` when BDO methods are available
28
-
29
- Prefer BDO methods when they're `public` on the role's class. Use `api()` only for `protected` methods.
30
-
31
- ```typescript
32
- // ✅ PREFERRED — BDO method
33
- const items = await bdo.list();
34
-
35
- // ✅ USE api() ONLY when BDO method is protected
36
- await api(bdo.meta._id).delete(id);
37
- ```
38
-
39
- ### 3. Wrong metric response key format
40
-
41
- Key pattern is `{lowercase_type}_{Field}` with single underscore.
42
-
43
- ```typescript
44
- // ❌ WRONG
45
- const count = result.Data[0].count;
46
-
47
- // ✅ CORRECT
48
- const count = result.Data?.[0]?.["count__id"] ?? 0; // Count of _id
49
- const total = result.Data?.[0]?.["sum_unit_price"] ?? 0; // Sum of unit_price
50
- ```
51
-
52
- ---
53
-
54
- ## Response Types
55
-
56
- ```typescript
57
- interface CreateUpdateResponseType { _id: string; }
58
- interface DeleteResponseType { status: "success"; }
59
- interface DraftResponseType { [fieldName: string]: any; }
60
-
61
- interface ListOptionsType {
62
- Field?: string[];
63
- Filter?: FilterType;
64
- Sort?: Record<string, "ASC" | "DESC">[];
65
- Page?: number; // 1-indexed
66
- PageSize?: number; // Default: 10
67
- }
68
-
69
- interface MetricOptionsType {
70
- GroupBy: string[];
71
- Metric: { Field: string; Type: AggregationType; }[];
72
- Filter?: FilterType;
73
- }
74
-
75
- interface MetricResponseType { Data: Record<string, any>[]; }
76
-
77
- interface PivotOptionsType {
78
- Row: string[];
79
- Column: string[];
80
- Metric: { Field: string; Type: AggregationType; }[];
81
- Filter?: FilterType;
82
- }
83
-
84
- interface PivotResponseType {
85
- Data: { RowHeader: { Key: string }[]; ColumnHeader: { Key: string }[]; Value: (number | string | null)[][]; };
86
- }
87
-
88
- type AggregationType = "Sum" | "Avg" | "Count" | "Max" | "Min" | "DistinctCount" | "BlankCount" | "NotBlankCount" | "Concat" | "DistinctConcat";
89
-
90
- // Filter type (for bdo.list() Filter parameter)
91
- interface FilterType { Operator: "And" | "Or" | "Not"; Condition: Array<ConditionType | ConditionGroupType>; }
92
- interface ConditionType { Operator: string; LHSField: string; RHSValue: any; RHSType?: "Constant" | "BDOField" | "AppVariable"; }
93
-
94
- type SortType = Record<string, "ASC" | "DESC">[];
95
- ```