@ram_28/kf-ai-sdk 1.0.19 → 1.0.21

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 (97) hide show
  1. package/README.md +45 -12
  2. package/dist/api/client.d.ts.map +1 -1
  3. package/dist/api/datetime.d.ts +59 -10
  4. package/dist/api/datetime.d.ts.map +1 -1
  5. package/dist/api/index.d.ts +3 -2
  6. package/dist/api/index.d.ts.map +1 -1
  7. package/dist/api.cjs +1 -1
  8. package/dist/api.d.ts +1 -1
  9. package/dist/api.d.ts.map +1 -1
  10. package/dist/api.mjs +43 -21
  11. package/dist/api.types.d.ts +2 -1
  12. package/dist/api.types.d.ts.map +1 -1
  13. package/dist/auth/AuthProvider.d.ts.map +1 -1
  14. package/dist/auth.cjs +1 -1
  15. package/dist/auth.mjs +34 -34
  16. package/dist/base-types.d.ts +1 -1
  17. package/dist/base-types.d.ts.map +1 -1
  18. package/dist/client-BIkaIr2y.js +217 -0
  19. package/dist/client-DxjRcEtN.cjs +1 -0
  20. package/dist/components/hooks/useFilter/types.d.ts +14 -11
  21. package/dist/components/hooks/useFilter/types.d.ts.map +1 -1
  22. package/dist/components/hooks/useFilter/useFilter.d.ts +1 -1
  23. package/dist/components/hooks/useFilter/useFilter.d.ts.map +1 -1
  24. package/dist/components/hooks/useForm/apiClient.d.ts +45 -4
  25. package/dist/components/hooks/useForm/apiClient.d.ts.map +1 -1
  26. package/dist/components/hooks/useForm/useForm.d.ts.map +1 -1
  27. package/dist/components/hooks/useKanban/types.d.ts +5 -22
  28. package/dist/components/hooks/useKanban/types.d.ts.map +1 -1
  29. package/dist/components/hooks/useKanban/useKanban.d.ts.map +1 -1
  30. package/dist/components/hooks/useTable/types.d.ts +19 -31
  31. package/dist/components/hooks/useTable/types.d.ts.map +1 -1
  32. package/dist/components/hooks/useTable/useTable.d.ts.map +1 -1
  33. package/dist/error-handling-CAoD0Kwb.cjs +1 -0
  34. package/dist/error-handling-CrhTtD88.js +14 -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 +736 -750
  39. package/dist/index.d.ts +18 -0
  40. package/dist/index.d.ts.map +1 -1
  41. package/dist/kanban.cjs +2 -2
  42. package/dist/kanban.mjs +333 -323
  43. package/dist/{metadata-0lZAfuTP.cjs → metadata-Bz8zJqC1.cjs} +1 -1
  44. package/dist/{metadata-B88D_pVS.js → metadata-VbQzyD2C.js} +1 -1
  45. package/dist/table.cjs +1 -1
  46. package/dist/table.mjs +113 -96
  47. package/dist/table.types.d.ts +1 -1
  48. package/dist/table.types.d.ts.map +1 -1
  49. package/dist/types/base-fields.d.ts +71 -17
  50. package/dist/types/base-fields.d.ts.map +1 -1
  51. package/dist/types/common.d.ts +26 -18
  52. package/dist/types/common.d.ts.map +1 -1
  53. package/dist/useFilter-DzpP_ag0.cjs +1 -0
  54. package/dist/useFilter-H5bgAZQF.js +120 -0
  55. package/dist/utils/api/buildListOptions.d.ts +43 -0
  56. package/dist/utils/api/buildListOptions.d.ts.map +1 -0
  57. package/dist/utils/api/index.d.ts +2 -0
  58. package/dist/utils/api/index.d.ts.map +1 -0
  59. package/dist/utils/error-handling.d.ts +41 -0
  60. package/dist/utils/error-handling.d.ts.map +1 -0
  61. package/dist/utils/index.d.ts +2 -0
  62. package/dist/utils/index.d.ts.map +1 -1
  63. package/docs/QUICK_REFERENCE.md +142 -420
  64. package/docs/useAuth.md +52 -340
  65. package/docs/useFilter.md +858 -162
  66. package/docs/useForm.md +712 -501
  67. package/docs/useKanban.md +534 -279
  68. package/docs/useTable.md +725 -214
  69. package/package.json +1 -1
  70. package/sdk/api/client.ts +3 -41
  71. package/sdk/api/datetime.ts +98 -14
  72. package/sdk/api/index.ts +12 -6
  73. package/sdk/api.ts +6 -3
  74. package/sdk/api.types.ts +3 -4
  75. package/sdk/auth/AuthProvider.tsx +22 -24
  76. package/sdk/base-types.ts +2 -0
  77. package/sdk/components/hooks/useFilter/types.ts +14 -11
  78. package/sdk/components/hooks/useFilter/useFilter.ts +20 -18
  79. package/sdk/components/hooks/useForm/apiClient.ts +120 -5
  80. package/sdk/components/hooks/useForm/useForm.ts +97 -61
  81. package/sdk/components/hooks/useKanban/types.ts +7 -23
  82. package/sdk/components/hooks/useKanban/useKanban.ts +54 -18
  83. package/sdk/components/hooks/useTable/types.ts +26 -32
  84. package/sdk/components/hooks/useTable/useTable.llm.txt +8 -22
  85. package/sdk/components/hooks/useTable/useTable.ts +70 -25
  86. package/sdk/index.ts +157 -10
  87. package/sdk/table.types.ts +3 -0
  88. package/sdk/types/base-fields.ts +71 -17
  89. package/sdk/types/common.ts +33 -19
  90. package/sdk/utils/api/buildListOptions.ts +120 -0
  91. package/sdk/utils/api/index.ts +2 -0
  92. package/sdk/utils/error-handling.ts +150 -0
  93. package/sdk/utils/index.ts +6 -0
  94. package/dist/client-DgtkT50N.cjs +0 -1
  95. package/dist/client-V-WzUb8H.js +0 -237
  96. package/dist/useFilter-Dofowpr_.cjs +0 -1
  97. package/dist/useFilter-Dv-mr9QW.js +0 -117
package/sdk/index.ts CHANGED
@@ -1,16 +1,163 @@
1
- // Core SDK exports
1
+ // ============================================================
2
+ // @ram_28/kf-ai-sdk - Main Entry Point
3
+ // ============================================================
4
+ // This is the primary export file for the SDK, providing a unified
5
+ // interface to all hooks, types, utilities, and API functions.
2
6
 
3
- // Type system
4
- export * from './types';
7
+ // ============================================================
8
+ // HOOKS - Core functionality for building applications
9
+ // ============================================================
5
10
 
6
- // API client
7
- export * from './api';
11
+ // Table hook - Data tables with sorting, pagination, and filtering
12
+ export { useTable } from './components/hooks/useTable';
13
+ export type {
14
+ UseTableOptionsType,
15
+ UseTableReturnType,
16
+ } from './components/hooks/useTable';
8
17
 
9
- // Utilities
10
- export * from './utils';
18
+ // Form hook - Schema-driven forms with validation
19
+ export { useForm } from './components/hooks/useForm';
20
+ export type {
21
+ UseFormOptionsType,
22
+ UseFormReturnType,
23
+ FormFieldConfigType,
24
+ FormSchemaConfigType,
25
+ } from './components/hooks/useForm';
11
26
 
12
- // Components
13
- export * from './components';
27
+ // Kanban hook - Kanban board state management
28
+ export { useKanban } from './components/hooks/useKanban';
29
+ export type {
30
+ UseKanbanOptionsType,
31
+ UseKanbanReturnType,
32
+ KanbanCardType,
33
+ KanbanColumnType,
34
+ ColumnConfigType,
35
+ } from './components/hooks/useKanban';
36
+
37
+ // Filter hook - Advanced filtering with logical operators
38
+ export { useFilter, isCondition, isConditionGroup } from './components/hooks/useFilter';
39
+ export type {
40
+ UseFilterOptionsType,
41
+ UseFilterReturnType,
42
+ } from './components/hooks/useFilter';
43
+
44
+ // ============================================================
45
+ // AUTHENTICATION - User authentication and authorization
46
+ // ============================================================
47
+
48
+ export { AuthProvider, useAuth } from './auth';
49
+ export type {
50
+ UseAuthReturnType,
51
+ UserDetailsType,
52
+ AuthStatusType,
53
+ AuthProviderPropsType,
54
+ } from './auth/types';
55
+
56
+ // ============================================================
57
+ // API CLIENT - Type-safe CRUD operations
58
+ // ============================================================
59
+
60
+ export { api, setApiBaseUrl, getApiBaseUrl, getBdoSchema } from './api';
61
+
62
+ // ============================================================
63
+ // TYPES - Core type definitions
64
+ // ============================================================
65
+
66
+ // Common types
67
+ export type {
68
+ SortType,
69
+ SortDirectionType,
70
+ FilterType,
71
+ ConditionType,
72
+ ConditionGroupType,
73
+ ConditionOperatorType,
74
+ ConditionGroupOperatorType,
75
+ ListResponseType,
76
+ ListOptionsType,
77
+ ColumnDefinitionType,
78
+ } from './types/common';
79
+
80
+ // Base field types
81
+ export type {
82
+ IdFieldType,
83
+ StringFieldType,
84
+ TextAreaFieldType,
85
+ NumberFieldType,
86
+ LongFieldType,
87
+ BooleanFieldType,
88
+ DateFieldType,
89
+ DateTimeFieldType,
90
+ CurrencyFieldType,
91
+ SelectFieldType,
92
+ LookupFieldType,
93
+ ArrayFieldType,
94
+ JSONFieldType,
95
+ ReferenceFieldType,
96
+ ExtractReferenceType,
97
+ ExtractFetchFieldType,
98
+ } from './types/base-fields';
14
99
 
15
- // Authentication
100
+ // ============================================================
101
+ // UTILITIES - Helper functions
102
+ // ============================================================
103
+
104
+ // Formatting utilities
105
+ export {
106
+ formatCurrency,
107
+ formatDate,
108
+ formatDateTime,
109
+ formatNumber,
110
+ formatBoolean,
111
+ formatArray,
112
+ formatJSON,
113
+ formatFieldValue,
114
+ } from './utils/formatting';
115
+
116
+ // Class name utility
117
+ export { cn } from './utils/cn';
118
+
119
+ // Error handling utilities
120
+ export {
121
+ toError,
122
+ isError,
123
+ getErrorMessage,
124
+ isNetworkError,
125
+ isTimeoutError,
126
+ isAbortError,
127
+ tryCatch,
128
+ wrapError,
129
+ } from './utils/error-handling';
130
+
131
+ // API utilities
132
+ export {
133
+ buildListOptions,
134
+ buildCountOptions,
135
+ combineFilters,
136
+ } from './utils/api';
137
+
138
+ // ============================================================
139
+ // UI COMPONENTS - Pre-built React components
140
+ // ============================================================
141
+
142
+ export {
143
+ Kanban,
144
+ KanbanColumn,
145
+ KanbanColumnHeader,
146
+ KanbanColumnTitle,
147
+ KanbanColumnContent,
148
+ KanbanCard,
149
+ KanbanCardTitle,
150
+ KanbanCardDescription,
151
+ KanbanColumnFooter,
152
+ } from './components/ui';
153
+
154
+ // ============================================================
155
+ // LEGACY EXPORTS - For backwards compatibility
156
+ // ============================================================
157
+
158
+ // Re-export everything from submodules for backwards compatibility
159
+ export * from './types';
160
+ export * from './api';
161
+ export * from './utils';
162
+ export * from './components';
16
163
  export * from './auth';
@@ -10,4 +10,7 @@ export type {
10
10
 
11
11
  // Column definition
12
12
  ColumnDefinitionType,
13
+
14
+ // State types
15
+ PaginationStateType,
13
16
  } from './components/hooks/useTable/types';
@@ -67,27 +67,47 @@ export type LongFieldType = number;
67
67
  */
68
68
  export type BooleanFieldType = boolean;
69
69
 
70
+ /**
71
+ * Encoded date format from API response
72
+ * API returns: { "$__d__": "YYYY-MM-DD" }
73
+ */
74
+ export interface DateEncodedType {
75
+ $__d__: string;
76
+ }
77
+
78
+ /**
79
+ * Encoded datetime format from API response
80
+ * API returns: { "$__dt__": unix_timestamp_seconds }
81
+ */
82
+ export interface DateTimeEncodedType {
83
+ $__dt__: number;
84
+ }
85
+
70
86
  /**
71
87
  * Date field (date only, no time)
72
- * Resolves to: Date
88
+ * API Response Format: { "$__d__": "YYYY-MM-DD" }
89
+ * API Request Format: "YYYY-MM-DD"
73
90
  * Storage: DATE in database
74
91
  * Use this for birth dates, due dates, calendar events
75
92
  *
76
93
  * @example
77
- * DateFieldType // => Date (date only)
94
+ * // Response from API:
95
+ * { "$__d__": "2025-03-15" }
78
96
  */
79
- export type DateFieldType = Date;
97
+ export type DateFieldType = DateEncodedType;
80
98
 
81
99
  /**
82
100
  * DateTime field (date and time)
83
- * Resolves to: Date
101
+ * API Response Format: { "$__dt__": unix_timestamp_seconds }
102
+ * API Request Format: "YYYY-MM-DD HH:MM:SS"
84
103
  * Storage: DATETIME/TIMESTAMP in database
85
104
  * Use this for created_at, updated_at, event timestamps
86
105
  *
87
106
  * @example
88
- * DateTimeFieldType // => Date (with time)
107
+ * // Response from API:
108
+ * { "$__dt__": 1769110463 }
89
109
  */
90
- export type DateTimeFieldType = Date;
110
+ export type DateTimeFieldType = DateTimeEncodedType;
91
111
 
92
112
  // ============================================================
93
113
  // COMPLEX FIELD TYPES
@@ -124,7 +144,47 @@ export type CurrencyValueType =
124
144
  */
125
145
  export type JSONFieldType<T = JSONValueType> = T;
126
146
 
127
- export type ReferenceFieldType = string;
147
+ /**
148
+ * Reference/Lookup field for relationships to other Business Data Objects
149
+ *
150
+ * @template TReferencedType - The full type of the referenced BDO record
151
+ *
152
+ * Runtime behavior:
153
+ * - The field stores the full referenced record (e.g., full supplier object)
154
+ * - API returns the complete record from the referenced BDO
155
+ * - On save, the full object is sent in the payload
156
+ *
157
+ * @example
158
+ * SupplierInfo: ReferenceFieldType<BaseSupplierType>;
159
+ * // At runtime: { _id: "...", SupplierId: "...", SupplierName: "...", ... }
160
+ */
161
+ export type ReferenceFieldType<TReferencedType = unknown> = TReferencedType;
162
+
163
+ /**
164
+ * Extract the referenced type from a ReferenceFieldType
165
+ * Note: Since ReferenceFieldType<T> = T, this just returns T if it has _id
166
+ */
167
+ export type ExtractReferenceType<T> = T extends { _id: string } ? T : never;
168
+
169
+ /**
170
+ * Extract the type that fetchField should return for a given field type
171
+ * - For Reference fields (objects with _id) → the full referenced record type
172
+ * - For other field types → { Value: string; Label: string } (static dropdown)
173
+ *
174
+ * Detection: All BDO types have _id: string, so we check for that property
175
+ * to distinguish reference fields from primitive fields like StringFieldType.
176
+ *
177
+ * @example
178
+ * type SupplierOptions = ExtractFetchFieldType<BaseProductType["SupplierInfo"]>;
179
+ * // Result: BaseSupplierType (has _id)
180
+ *
181
+ * type CategoryOptions = ExtractFetchFieldType<BaseProductType["Category"]>;
182
+ * // Result: { Value: string; Label: string } (string has no _id)
183
+ */
184
+ export type ExtractFetchFieldType<T> =
185
+ T extends { _id: string }
186
+ ? T
187
+ : { Value: string; Label: string };
128
188
 
129
189
  /**
130
190
  * Valid JSON value types
@@ -156,17 +216,11 @@ export interface JSONArrayType extends Array<JSONValueType> {}
156
216
  export type SelectFieldType<T extends string> = T;
157
217
 
158
218
  /**
159
- * Lookup field for references to other records
160
- * @template T - Type of the referenced record ID (defaults to string)
161
- * Resolves to: T
162
- * Storage: VARCHAR in database (stores the ID)
163
- * Use this for foreign keys, relationships, references
164
- *
165
- * @example
166
- * LookupFieldType // => string (referenced record ID)
167
- * LookupFieldType<IdFieldType> // => string (typed as IdFieldType)
219
+ * Alias for ReferenceFieldType (Lookup = Reference in the backend)
220
+ * @template TReferencedType - The full type of the referenced BDO record
221
+ * @deprecated Use ReferenceFieldType instead
168
222
  */
169
- export type LookupFieldType<T extends string = string> = T;
223
+ export type LookupFieldType<TReferencedType = unknown> = ReferenceFieldType<TReferencedType>;
170
224
 
171
225
  // ============================================================
172
226
  // CONTAINER AND UTILITY TYPES
@@ -37,14 +37,15 @@ export type FilterRHSTypeType = "Constant" | "BOField" | "AppVariable";
37
37
 
38
38
  /**
39
39
  * Leaf condition (actual field comparison)
40
+ * @template T - Data type for type-safe field names (defaults to any)
40
41
  */
41
- export interface ConditionType {
42
+ export interface ConditionType<T = any> {
42
43
  /** Optional ID for hook state management (omitted in API payload) */
43
44
  id?: string;
44
45
  /** Condition operator */
45
46
  Operator: ConditionOperatorType;
46
- /** Left-hand side field name */
47
- LHSField: string;
47
+ /** Left-hand side field name (keyof T when generic is provided) */
48
+ LHSField: T extends any ? keyof T | string : string;
48
49
  /** Right-hand side value */
49
50
  RHSValue: any;
50
51
  /** Right-hand side type (optional, defaults to Constant) */
@@ -53,34 +54,25 @@ export interface ConditionType {
53
54
 
54
55
  /**
55
56
  * Group combining conditions (recursive structure)
57
+ * @template T - Data type for type-safe field names (defaults to any)
56
58
  */
57
- export interface ConditionGroupType {
59
+ export interface ConditionGroupType<T = any> {
58
60
  /** Optional ID for hook state management (omitted in API payload) */
59
61
  id?: string;
60
62
  /** Group operator (And, Or, Not) */
61
63
  Operator: ConditionGroupOperatorType;
62
64
  /** Nested conditions (can be Condition or ConditionGroup) */
63
- Condition: Array<ConditionType | ConditionGroupType>;
65
+ Condition: Array<ConditionType<T> | ConditionGroupType<T>>;
64
66
  }
65
67
 
66
68
  /**
67
69
  * Root filter type (alias for ConditionGroup)
70
+ * @template T - Data type for type-safe field names (defaults to any)
68
71
  */
69
- export type FilterType = ConditionGroupType;
72
+ export type FilterType<T = any> = ConditionGroupType<T>;
70
73
 
71
- /**
72
- * DateTime encoding format used by the API
73
- */
74
- export interface DateTimeEncodedType {
75
- $__dt__: number;
76
- }
77
-
78
- /**
79
- * Date encoding format used by the API
80
- */
81
- export interface DateEncodedType {
82
- $__d__: string;
83
- }
74
+ // Note: DateTimeEncodedType and DateEncodedType are now defined in base-fields.ts
75
+ // They are re-exported from api/index.ts for convenience
84
76
 
85
77
  /**
86
78
  * Standard paginated list response
@@ -296,3 +288,25 @@ export interface FetchFieldResponseType {
296
288
  /** Array of field options */
297
289
  Data: FetchFieldOptionType[];
298
290
  }
291
+
292
+ // ============================================================
293
+ // SHARED COMPONENT TYPES
294
+ // ============================================================
295
+
296
+ /**
297
+ * Column definition for data display and behavior
298
+ * Used by useTable and useKanban for defining field configurations
299
+ * @template T - Data type for type-safe field names
300
+ */
301
+ export interface ColumnDefinitionType<T> {
302
+ /** Field name from the data type */
303
+ fieldId: keyof T;
304
+ /** Display label (optional, defaults to fieldId) */
305
+ label?: string;
306
+ /** Enable sorting for this field */
307
+ enableSorting?: boolean;
308
+ /** Enable filtering for this field */
309
+ enableFiltering?: boolean;
310
+ /** Custom transform function (overrides auto-formatting) */
311
+ transform?: (value: any, item: T) => React.ReactNode;
312
+ }
@@ -0,0 +1,120 @@
1
+ // ============================================================
2
+ // BUILD LIST OPTIONS UTILITY
3
+ // ============================================================
4
+ // Shared utility for building API list options across hooks
5
+
6
+ import type { ListOptionsType, FilterType, SortType } from "../../types/common";
7
+
8
+ /**
9
+ * Options for building list API request options
10
+ */
11
+ export interface BuildListOptionsParams<T = any> {
12
+ /** Search query string */
13
+ search?: string;
14
+ /** Filter payload */
15
+ filter?: FilterType<T>;
16
+ /** Sort configuration */
17
+ sort?: {
18
+ field: keyof T | null;
19
+ direction: "asc" | "desc" | null;
20
+ };
21
+ /** Sort array in API format */
22
+ sortArray?: SortType;
23
+ /** Pagination settings */
24
+ pagination?: {
25
+ pageNo: number;
26
+ pageSize: number;
27
+ };
28
+ }
29
+
30
+ /**
31
+ * Build list options for count queries
32
+ * Excludes pagination and sorting (they don't affect count)
33
+ */
34
+ export function buildCountOptions<T = any>(
35
+ params: Pick<BuildListOptionsParams<T>, "search" | "filter">
36
+ ): ListOptionsType {
37
+ const opts: ListOptionsType = {};
38
+
39
+ if (params.search) {
40
+ opts.Search = params.search;
41
+ }
42
+
43
+ if (params.filter) {
44
+ opts.Filter = params.filter;
45
+ }
46
+
47
+ return opts;
48
+ }
49
+
50
+ /**
51
+ * Build list options for data queries
52
+ * Includes all options: search, filter, sort, pagination
53
+ */
54
+ export function buildListOptions<T = any>(
55
+ params: BuildListOptionsParams<T>
56
+ ): ListOptionsType {
57
+ const opts: ListOptionsType = buildCountOptions({
58
+ search: params.search,
59
+ filter: params.filter,
60
+ });
61
+
62
+ // Add sorting - convert internal format to API format
63
+ if (params.sort?.field && params.sort?.direction) {
64
+ opts.Sort = [
65
+ {
66
+ [String(params.sort.field)]:
67
+ params.sort.direction === "asc" ? "ASC" : "DESC",
68
+ },
69
+ ];
70
+ } else if (params.sortArray) {
71
+ opts.Sort = params.sortArray;
72
+ }
73
+
74
+ // Add pagination
75
+ if (params.pagination) {
76
+ opts.Page = params.pagination.pageNo;
77
+ opts.PageSize = params.pagination.pageSize;
78
+ }
79
+
80
+ return opts;
81
+ }
82
+
83
+ /**
84
+ * Combine filter payload with additional column filter
85
+ * Used for kanban column-specific queries
86
+ */
87
+ export function combineFilters<T = any>(
88
+ baseFilter: FilterType<T> | undefined,
89
+ additionalCondition: {
90
+ LHSField: string;
91
+ Operator: string;
92
+ RHSValue: any;
93
+ RHSType?: string;
94
+ }
95
+ ): FilterType<T> {
96
+ const columnFilterObject = {
97
+ ...additionalCondition,
98
+ RHSType: additionalCondition.RHSType || "Constant",
99
+ };
100
+
101
+ if (!baseFilter) {
102
+ return {
103
+ Operator: "And",
104
+ Condition: [columnFilterObject],
105
+ } as FilterType<T>;
106
+ }
107
+
108
+ // If base is And, append. If base is Or/Not, wrap in new And.
109
+ if (baseFilter.Operator === "And") {
110
+ return {
111
+ ...baseFilter,
112
+ Condition: [...(baseFilter.Condition || []), columnFilterObject],
113
+ } as FilterType<T>;
114
+ }
115
+
116
+ return {
117
+ Operator: "And",
118
+ Condition: [baseFilter, columnFilterObject],
119
+ } as FilterType<T>;
120
+ }
@@ -0,0 +1,2 @@
1
+ // API utilities
2
+ export * from "./buildListOptions";
@@ -0,0 +1,150 @@
1
+ // ============================================================
2
+ // ERROR HANDLING UTILITIES
3
+ // ============================================================
4
+ // Type-safe error handling utilities for the SDK
5
+
6
+ /**
7
+ * Safely convert unknown error to Error object
8
+ * Handles all possible error types that could be thrown
9
+ */
10
+ export function toError(err: unknown): Error {
11
+ // Already an Error instance
12
+ if (err instanceof Error) {
13
+ return err;
14
+ }
15
+
16
+ // String error
17
+ if (typeof err === "string") {
18
+ return new Error(err);
19
+ }
20
+
21
+ // Object with message property
22
+ if (
23
+ err !== null &&
24
+ typeof err === "object" &&
25
+ "message" in err &&
26
+ typeof (err as { message: unknown }).message === "string"
27
+ ) {
28
+ const error = new Error((err as { message: string }).message);
29
+ // Preserve any additional properties
30
+ Object.assign(error, err);
31
+ return error;
32
+ }
33
+
34
+ // Fallback: convert to string
35
+ return new Error(String(err));
36
+ }
37
+
38
+ /**
39
+ * Type guard to check if a value is an Error
40
+ */
41
+ export function isError(value: unknown): value is Error {
42
+ return value instanceof Error;
43
+ }
44
+
45
+ /**
46
+ * Type guard to check if error has a specific code
47
+ */
48
+ export function hasErrorCode(
49
+ err: unknown,
50
+ code: string
51
+ ): err is Error & { code: string } {
52
+ return (
53
+ err instanceof Error &&
54
+ "code" in err &&
55
+ (err as Error & { code: unknown }).code === code
56
+ );
57
+ }
58
+
59
+ /**
60
+ * Type guard to check if error is a network error
61
+ */
62
+ export function isNetworkError(err: unknown): boolean {
63
+ if (!isError(err)) return false;
64
+
65
+ const message = err.message.toLowerCase();
66
+ return (
67
+ message.includes("network") ||
68
+ message.includes("fetch") ||
69
+ message.includes("connection") ||
70
+ hasErrorCode(err, "NETWORK_ERROR") ||
71
+ hasErrorCode(err, "ENOTFOUND") ||
72
+ hasErrorCode(err, "ECONNREFUSED")
73
+ );
74
+ }
75
+
76
+ /**
77
+ * Type guard to check if error is a timeout error
78
+ */
79
+ export function isTimeoutError(err: unknown): boolean {
80
+ if (!isError(err)) return false;
81
+
82
+ return (
83
+ err.message.toLowerCase().includes("timeout") ||
84
+ hasErrorCode(err, "TIMEOUT") ||
85
+ hasErrorCode(err, "ETIMEDOUT")
86
+ );
87
+ }
88
+
89
+ /**
90
+ * Type guard to check if error is an abort error
91
+ */
92
+ export function isAbortError(err: unknown): boolean {
93
+ if (!isError(err)) return false;
94
+
95
+ return err.name === "AbortError" || hasErrorCode(err, "ABORT_ERR");
96
+ }
97
+
98
+ /**
99
+ * Extract error message from unknown error
100
+ */
101
+ export function getErrorMessage(err: unknown): string {
102
+ if (isError(err)) {
103
+ return err.message;
104
+ }
105
+
106
+ if (typeof err === "string") {
107
+ return err;
108
+ }
109
+
110
+ if (
111
+ err !== null &&
112
+ typeof err === "object" &&
113
+ "message" in err &&
114
+ typeof (err as { message: unknown }).message === "string"
115
+ ) {
116
+ return (err as { message: string }).message;
117
+ }
118
+
119
+ return String(err);
120
+ }
121
+
122
+ /**
123
+ * Safe error handler wrapper for async functions
124
+ * Returns a tuple of [result, error]
125
+ */
126
+ export async function tryCatch<T>(
127
+ fn: () => Promise<T>
128
+ ): Promise<[T, null] | [null, Error]> {
129
+ try {
130
+ const result = await fn();
131
+ return [result, null];
132
+ } catch (err) {
133
+ return [null, toError(err)];
134
+ }
135
+ }
136
+
137
+ /**
138
+ * Create a wrapped error with original error as cause
139
+ */
140
+ export function wrapError(message: string, cause: unknown): Error {
141
+ const error = new Error(message);
142
+ // Use Object.defineProperty for broader compatibility
143
+ Object.defineProperty(error, 'cause', {
144
+ value: toError(cause),
145
+ writable: true,
146
+ enumerable: false,
147
+ configurable: true,
148
+ });
149
+ return error;
150
+ }
@@ -3,3 +3,9 @@ export * from "./formatting";
3
3
 
4
4
  // Class name utilities
5
5
  export * from "./cn";
6
+
7
+ // Error handling utilities
8
+ export * from "./error-handling";
9
+
10
+ // API utilities
11
+ export * from "./api";
@@ -1 +0,0 @@
1
- "use strict";let o={baseUrl:"",headers:{"Content-Type":"application/json"}};function u(e){o.baseUrl=e}function h(e){o.headers={...o.headers,...e}}function d(){return{...o.headers}}function l(){return o.baseUrl||""}function i(e){if(e==null)return e;if(Array.isArray(e))return e.map(s=>i(s));if(typeof e=="object"){if("$__dt__"in e)return new Date(e.$__dt__*1e3);if("$__d__"in e)return new Date(e.$__d__);const s={};for(const[n,t]of Object.entries(e))s[n]=i(t);return s}return e}function w(e){const s=o.baseUrl,n=o.headers;return{async get(t){const r=await fetch(`${s}/api/app/${e}/${t}/read`,{method:"GET",headers:n});if(!r.ok)throw new Error(`Failed to get ${e} ${t}: ${r.statusText}`);const a=await r.json();return i(a.Data)},async create(t){const r=await fetch(`${s}/api/app/${e}/create`,{method:"POST",headers:n,body:JSON.stringify(t)});if(!r.ok)throw new Error(`Failed to create ${e}: ${r.statusText}`);return r.json()},async update(t,r){const a=await fetch(`${s}/api/app/${e}/${t}/update`,{method:"POST",headers:n,body:JSON.stringify(r)});if(!a.ok)throw new Error(`Failed to update ${e} ${t}: ${a.statusText}`);return a.json()},async delete(t){const r=await fetch(`${s}/api/app/${e}/${t}/delete`,{method:"DELETE",headers:n});if(!r.ok)throw new Error(`Failed to delete ${e} ${t}: ${r.statusText}`);return r.json()},async list(t){const r={Type:"List",...t},a=await fetch(`${s}/api/app/${e}/list`,{method:"POST",headers:n,body:JSON.stringify(r)});if(!a.ok)throw new Error(`Failed to list ${e}: ${a.statusText}`);return{Data:(await a.json()).Data.map(f=>i(f))}},async count(t){var p,$;const r={Type:"Metric",GroupBy:[],Metric:[{Field:"_id",Type:"Count"}],...(t==null?void 0:t.Filter)&&{Filter:t.Filter}},a=await fetch(`${s}/api/app/${e}/metric`,{method:"POST",headers:n,body:JSON.stringify(r)});if(!a.ok)throw new Error(`Failed to count ${e}: ${a.statusText}`);return{Count:(($=(p=(await a.json()).Data)==null?void 0:p[0])==null?void 0:$.count__id)??0}},async draft(t){const r=await fetch(`${s}/api/app/${e}/draft`,{method:"POST",headers:n,body:JSON.stringify(t)});if(!r.ok)throw new Error(`Failed to create draft for ${e}: ${r.statusText}`);return r.json()},async draftUpdate(t,r){const a=await fetch(`${s}/api/app/${e}/${t}/draft`,{method:"POST",headers:n,body:JSON.stringify(r)});if(!a.ok)throw new Error(`Failed to update draft for ${e} ${t}: ${a.statusText}`);return a.json()},async draftPatch(t,r){const a=await fetch(`${s}/api/app/${e}/${t}/draft`,{method:"PATCH",headers:n,body:JSON.stringify(r)});if(!a.ok)throw new Error(`Failed to patch draft for ${e} ${t}: ${a.statusText}`);return a.json()},async draftInteraction(t){const r=await fetch(`${s}/api/app/${e}/draft`,{method:"PATCH",headers:n,body:JSON.stringify(t)});if(!r.ok)throw new Error(`Failed to create interactive draft for ${e}: ${r.statusText}`);const a=await r.json();return{...a.Data,_id:a.Data._id}},async metric(t){const r={Type:"Metric",...t},a=await fetch(`${s}/api/app/${e}/metric`,{method:"POST",headers:n,body:JSON.stringify(r)});if(!a.ok)throw new Error(`Failed to get metrics for ${e}: ${a.statusText}`);return a.json()},async pivot(t){const r={Type:"Pivot",...t},a=await fetch(`${s}/api/app/${e}/pivot`,{method:"POST",headers:n,body:JSON.stringify(r)});if(!a.ok)throw new Error(`Failed to get pivot data for ${e}: ${a.statusText}`);return a.json()},async fields(){const t=await fetch(`${s}/api/app/${e}/fields`,{method:"GET",headers:n});if(!t.ok)throw new Error(`Failed to get fields for ${e}: ${t.statusText}`);return t.json()},async fetchField(t,r){const a=await fetch(`${s}/api/app/${e}/${t}/field/${r}/fetch`,{method:"GET",headers:n});if(!a.ok)throw new Error(`Failed to fetch field ${r} for ${e}: ${a.statusText}`);return(await a.json()).Data}}}exports.api=w;exports.getApiBaseUrl=l;exports.getDefaultHeaders=d;exports.setApiBaseUrl=u;exports.setDefaultHeaders=h;