@ram_28/kf-ai-sdk 1.0.9 → 1.0.11

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ram_28/kf-ai-sdk",
3
- "version": "1.0.9",
3
+ "version": "1.0.11",
4
4
  "description": "Type-safe, AI-driven SDK for building modern web applications with role-based access control",
5
5
  "author": "Ramprasad",
6
6
  "license": "MIT",
package/sdk/api/client.ts CHANGED
@@ -69,6 +69,15 @@ export interface ResourceClient<T = any> {
69
69
  */
70
70
  draftPatch(id: string, data: Partial<T>): Promise<DraftResponse>;
71
71
 
72
+ /**
73
+ * Interactive draft - create/update draft without instance ID
74
+ * PATCH /{bo_id}/draft
75
+ * Used in interactive mode for create operations
76
+ */
77
+ draftInteraction(
78
+ data: Partial<T> & { _id?: string }
79
+ ): Promise<DraftResponse & { _id: string }>;
80
+
72
81
  // ============================================================
73
82
  // QUERY OPERATIONS
74
83
  // ============================================================
@@ -355,6 +364,24 @@ export function api<T = any>(bo_id: string): ResourceClient<T> {
355
364
  return response.json();
356
365
  },
357
366
 
367
+ async draftInteraction(
368
+ data: Partial<T> & { _id?: string }
369
+ ): Promise<DraftResponse & { _id: string }> {
370
+ const response = await fetch(`${baseUrl}/api/app/${bo_id}/draft`, {
371
+ method: "PATCH",
372
+ headers: defaultHeaders,
373
+ body: JSON.stringify(data),
374
+ });
375
+
376
+ if (!response.ok) {
377
+ throw new Error(
378
+ `Failed to create interactive draft for ${bo_id}: ${response.statusText}`
379
+ );
380
+ }
381
+
382
+ return response.json();
383
+ },
384
+
358
385
  // ============================================================
359
386
  // QUERY OPERATIONS
360
387
  // ============================================================
@@ -6,8 +6,6 @@ import type {
6
6
  UseFormRegister,
7
7
  Mode,
8
8
  FieldValues as RHFFieldValues,
9
- SubmitHandler,
10
- SubmitErrorHandler,
11
9
  FieldErrors,
12
10
  Path,
13
11
  PathValue,
@@ -21,15 +19,23 @@ import type {
21
19
  // ============================================================
22
20
 
23
21
  /**
24
- * Extended handleSubmit that allows optional callbacks
25
- * When no callback is provided, uses the SDK's built-in submit function
22
+ * HandleSubmit follows React Hook Form's signature pattern
23
+ *
24
+ * - onSuccess: Called with the API response data on successful submission
25
+ * - onError: Called with either FieldErrors (validation failed) or Error (API failed)
26
+ *
27
+ * Internal flow:
28
+ * 1. RHF validation + Cross-field validation → FAILS → onError(fieldErrors)
29
+ * 2. Clean data & call API → FAILS → onError(apiError)
30
+ * 3. SUCCESS → onSuccess(responseData)
26
31
  */
27
- export type ExtendedHandleSubmit<T extends RHFFieldValues> = {
28
- (
29
- onValid?: SubmitHandler<T>,
30
- onInvalid?: SubmitErrorHandler<T>
31
- ): (e?: React.BaseSyntheticEvent) => Promise<void>;
32
- };
32
+ export type HandleSubmit<T extends RHFFieldValues> = (
33
+ onSuccess?: (data: T, e?: React.BaseSyntheticEvent) => void | Promise<void>,
34
+ onError?: (
35
+ error: FieldErrors<T> | Error,
36
+ e?: React.BaseSyntheticEvent
37
+ ) => void | Promise<void>
38
+ ) => (e?: React.BaseSyntheticEvent) => Promise<void>;
33
39
 
34
40
  // ============================================================
35
41
  // EXPRESSION TREE TYPES
@@ -223,6 +229,13 @@ export interface BDOSchema {
223
229
  */
224
230
  export type FormOperation = "create" | "update";
225
231
 
232
+ /**
233
+ * Form interaction mode
234
+ * - "interactive" (default): Real-time server-side validation and computation on every field blur
235
+ * - "non-interactive": Draft only for computed field dependencies (legacy behavior)
236
+ */
237
+ export type InteractionMode = "interactive" | "non-interactive";
238
+
226
239
  /**
227
240
  * Form validation mode (from react-hook-form)
228
241
  */
@@ -276,18 +289,9 @@ export interface UseFormOptions<
276
289
  /** User role for permission enforcement */
277
290
  userRole?: string;
278
291
 
279
- /** Success callback */
280
- onSuccess?: (data: T) => void;
281
-
282
- /** Error callback */
283
- onError?: (error: Error) => void;
284
-
285
- /** Schema load error callback */
292
+ /** Schema load error callback (separate concern from form submission) */
286
293
  onSchemaError?: (error: Error) => void;
287
294
 
288
- /** Submit error callback */
289
- onSubmitError?: (error: Error) => void;
290
-
291
295
  /** Skip schema fetching (use for testing) */
292
296
  skipSchemaFetch?: boolean;
293
297
 
@@ -298,8 +302,17 @@ export interface UseFormOptions<
298
302
  * Trigger draft API call on every field change (after validation passes)
299
303
  * If true: draft API is called for any field change
300
304
  * If false (default): draft API is called only when computed field dependencies change
305
+ * @deprecated Use interactionMode: "interactive" instead
301
306
  */
302
307
  draftOnEveryChange?: boolean;
308
+
309
+ /**
310
+ * Form interaction mode
311
+ * - "interactive" (default): Real-time server-side validation and computation on every field blur
312
+ * - "non-interactive": Draft only for computed field dependencies (legacy behavior)
313
+ * @default "interactive"
314
+ */
315
+ interactionMode?: InteractionMode;
303
316
  }
304
317
 
305
318
  // ============================================================
@@ -448,8 +461,38 @@ export interface UseFormReturn<
448
461
  options?: RegisterOptions<T, K>
449
462
  ) => ReturnType<UseFormRegister<T>>;
450
463
 
451
- /** Handle form submission - automatically uses SDK's submit logic */
452
- handleSubmit: () => (e?: React.BaseSyntheticEvent) => Promise<void>;
464
+ /**
465
+ * Handle form submission with optional callbacks
466
+ *
467
+ * @example
468
+ * // Basic usage - no callbacks
469
+ * <form onSubmit={form.handleSubmit()}>
470
+ *
471
+ * @example
472
+ * // With success callback
473
+ * <form onSubmit={form.handleSubmit((data) => {
474
+ * toast.success("Saved!");
475
+ * navigate("/products/" + data._id);
476
+ * })}>
477
+ *
478
+ * @example
479
+ * // With both callbacks
480
+ * <form onSubmit={form.handleSubmit(
481
+ * (data) => toast.success("Saved!"),
482
+ * (error) => {
483
+ * if (error instanceof Error) {
484
+ * toast.error(error.message); // API error
485
+ * } else {
486
+ * toast.error("Please fix the form errors"); // Validation errors
487
+ * }
488
+ * }
489
+ * )}>
490
+ *
491
+ * @example
492
+ * // Programmatic submission
493
+ * await form.handleSubmit(onSuccess, onError)();
494
+ */
495
+ handleSubmit: HandleSubmit<T>;
453
496
 
454
497
  /** Watch field values with strict typing */
455
498
  watch: <K extends Path<T> | readonly Path<T>[]>(
@@ -509,6 +552,16 @@ export interface UseFormReturn<
509
552
  /** Any loading state active */
510
553
  isLoading: boolean;
511
554
 
555
+ // ============================================================
556
+ // INTERACTIVE MODE STATE
557
+ // ============================================================
558
+
559
+ /** Draft ID for interactive create mode */
560
+ draftId: string | null;
561
+
562
+ /** Whether draft is being created (interactive create only) */
563
+ isCreatingDraft: boolean;
564
+
512
565
  // ============================================================
513
566
  // ERROR HANDLING
514
567
  // ============================================================
@@ -516,9 +569,6 @@ export interface UseFormReturn<
516
569
  /** Schema fetch error */
517
570
  loadError: Error | null;
518
571
 
519
- /** Form submission error */
520
- submitError: Error | null;
521
-
522
572
  /** Any error active */
523
573
  hasError: boolean;
524
574
 
@@ -561,9 +611,6 @@ export interface UseFormReturn<
561
611
  // OPERATIONS
562
612
  // ============================================================
563
613
 
564
- /** Submit form manually */
565
- submit: () => Promise<void>;
566
-
567
614
  /** Refresh schema */
568
615
  refreshSchema: () => Promise<void>;
569
616