@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,447 @@
1
+ // ============================================================
2
+ // API Client - Simple CRUD Operations
3
+ // ============================================================
4
+
5
+ import type {
6
+ ListOptions,
7
+ ListResponse,
8
+ ReadResponse,
9
+ CreateUpdateResponse,
10
+ DeleteResponse,
11
+ CountResponse,
12
+ DateTimeEncoded,
13
+ DateEncoded,
14
+ MetricOptions,
15
+ MetricResponse,
16
+ PivotOptions,
17
+ PivotResponse,
18
+ DraftResponse,
19
+ FieldsResponse,
20
+ FetchFieldOption,
21
+ FetchFieldResponse,
22
+ } from "../types/common";
23
+
24
+ /**
25
+ * API client interface for a specific Business Object
26
+ */
27
+ export interface ResourceClient<T = any> {
28
+ // ============================================================
29
+ // BASIC CRUD OPERATIONS
30
+ // ============================================================
31
+
32
+ /** Get single record by ID */
33
+ get(id: string): Promise<T>;
34
+
35
+ /** Create new record */
36
+ create(data: Partial<T> & { _id?: string }): Promise<CreateUpdateResponse>;
37
+
38
+ /** Update existing record */
39
+ update(id: string, data: Partial<T>): Promise<CreateUpdateResponse>;
40
+
41
+ /** Delete record by ID */
42
+ delete(id: string): Promise<DeleteResponse>;
43
+
44
+ /** List records with optional filtering, sorting, and pagination */
45
+ list(options?: ListOptions): Promise<ListResponse<T>>;
46
+
47
+ /** Get count of records matching the same criteria as list */
48
+ count(options?: ListOptions): Promise<CountResponse>;
49
+
50
+ // ============================================================
51
+ // DRAFT/INTERACTIVE OPERATIONS
52
+ // ============================================================
53
+
54
+ /**
55
+ * Create draft - compute fields without persisting
56
+ * POST /{bo_id}/draft
57
+ */
58
+ draft(data: Partial<T>): Promise<DraftResponse>;
59
+
60
+ /**
61
+ * Update draft (commit) - compute and prepare for update
62
+ * POST /{bo_id}/{instance_id}/draft
63
+ */
64
+ draftUpdate(id: string, data: Partial<T>): Promise<CreateUpdateResponse>;
65
+
66
+ /**
67
+ * Update draft (patch) - compute fields during editing
68
+ * PATCH /{bo_id}/{instance_id}/draft
69
+ */
70
+ draftPatch(id: string, data: Partial<T>): Promise<DraftResponse>;
71
+
72
+ // ============================================================
73
+ // QUERY OPERATIONS
74
+ // ============================================================
75
+
76
+ /**
77
+ * Get aggregated metrics grouped by dimensions
78
+ * POST /{bo_id}/metric
79
+ */
80
+ metric(options: Omit<MetricOptions, "Type">): Promise<MetricResponse>;
81
+
82
+ /**
83
+ * Get pivot table data
84
+ * POST /{bo_id}/pivot
85
+ */
86
+ pivot(options: Omit<PivotOptions, "Type">): Promise<PivotResponse>;
87
+
88
+ // ============================================================
89
+ // METADATA OPERATIONS
90
+ // ============================================================
91
+
92
+ /**
93
+ * Get field definitions for this Business Object
94
+ * GET /{bo_id}/fields
95
+ */
96
+ fields(): Promise<FieldsResponse>;
97
+
98
+ /**
99
+ * Fetch reference data for a specific field (for lookup and dropdown fields)
100
+ * GET /{bo_id}/{instance_id}/field/{field_id}/fetch
101
+ */
102
+ fetchField(instanceId: string, fieldId: string): Promise<FetchFieldOption[]>;
103
+ }
104
+
105
+ /**
106
+ * Configuration options for the API client
107
+ */
108
+ interface ApiConfig {
109
+ baseUrl?: string;
110
+ headers?: Record<string, string>;
111
+ }
112
+
113
+ /**
114
+ * Global API configuration
115
+ */
116
+ let apiConfig: ApiConfig = {
117
+ baseUrl: "",
118
+ headers: {
119
+ "Content-Type": "application/json",
120
+ },
121
+ };
122
+
123
+ /**
124
+ * Set the base URL for all API requests
125
+ */
126
+ export function setApiBaseUrl(baseUrl: string): void {
127
+ apiConfig.baseUrl = baseUrl;
128
+ }
129
+
130
+ /**
131
+ * Set default headers for all requests
132
+ */
133
+ export function setDefaultHeaders(headers: Record<string, string>): void {
134
+ apiConfig.headers = { ...apiConfig.headers, ...headers };
135
+ }
136
+
137
+ /**
138
+ * Get current default headers
139
+ */
140
+ export function getDefaultHeaders(): Record<string, string> {
141
+ return { ...apiConfig.headers };
142
+ }
143
+
144
+ /**
145
+ * Get current base URL
146
+ */
147
+ export function getApiBaseUrl(): string {
148
+ return apiConfig.baseUrl || "";
149
+ }
150
+
151
+ /**
152
+ * Recursively process an object to decode datetime fields
153
+ */
154
+ function decodeResponseData<T>(data: any): T {
155
+ if (data === null || data === undefined) {
156
+ return data;
157
+ }
158
+
159
+ if (Array.isArray(data)) {
160
+ return data.map((item) => decodeResponseData(item)) as T;
161
+ }
162
+
163
+ if (typeof data === "object") {
164
+ // Check for datetime encoding
165
+ if ("$__dt__" in data) {
166
+ return new Date((data as DateTimeEncoded).$__dt__ * 1000) as T;
167
+ }
168
+
169
+ // Check for date encoding
170
+ if ("$__d__" in data) {
171
+ return new Date((data as DateEncoded).$__d__) as T;
172
+ }
173
+
174
+ // Recursively process object properties
175
+ const result: any = {};
176
+ for (const [key, value] of Object.entries(data)) {
177
+ result[key] = decodeResponseData(value);
178
+ }
179
+ return result as T;
180
+ }
181
+
182
+ return data as T;
183
+ }
184
+
185
+ /**
186
+ * Create a resource client for the specified Business Object
187
+ * @param bo_id - Business Object identifier (e.g., "user", "leave", "vendor")
188
+ * @returns Resource client with CRUD operations matching API spec
189
+ */
190
+ export function api<T = any>(bo_id: string): ResourceClient<T> {
191
+ const baseUrl = apiConfig.baseUrl;
192
+ const defaultHeaders = apiConfig.headers;
193
+
194
+ return {
195
+ async get(id: string): Promise<T> {
196
+ const response = await fetch(`${baseUrl}/api/app/${bo_id}/${id}/read`, {
197
+ method: "GET",
198
+ headers: defaultHeaders,
199
+ });
200
+
201
+ if (!response.ok) {
202
+ throw new Error(`Failed to get ${bo_id} ${id}: ${response.statusText}`);
203
+ }
204
+
205
+ const responseData: ReadResponse<T> = await response.json();
206
+ return decodeResponseData<T>(responseData.Data);
207
+ },
208
+
209
+ async create(
210
+ data: Partial<T> & { _id?: string }
211
+ ): Promise<CreateUpdateResponse> {
212
+ const response = await fetch(`${baseUrl}/api/app/${bo_id}/create`, {
213
+ method: "POST",
214
+ headers: defaultHeaders,
215
+ body: JSON.stringify(data),
216
+ });
217
+
218
+ if (!response.ok) {
219
+ throw new Error(`Failed to create ${bo_id}: ${response.statusText}`);
220
+ }
221
+
222
+ return response.json();
223
+ },
224
+
225
+ async update(id: string, data: Partial<T>): Promise<CreateUpdateResponse> {
226
+ const response = await fetch(`${baseUrl}/api/app/${bo_id}/${id}/update`, {
227
+ method: "POST",
228
+ headers: defaultHeaders,
229
+ body: JSON.stringify(data),
230
+ });
231
+
232
+ if (!response.ok) {
233
+ throw new Error(
234
+ `Failed to update ${bo_id} ${id}: ${response.statusText}`
235
+ );
236
+ }
237
+
238
+ return response.json();
239
+ },
240
+
241
+ async delete(id: string): Promise<DeleteResponse> {
242
+ const response = await fetch(`${baseUrl}/api/app/${bo_id}/${id}/delete`, {
243
+ method: "DELETE",
244
+ headers: defaultHeaders,
245
+ });
246
+
247
+ if (!response.ok) {
248
+ throw new Error(
249
+ `Failed to delete ${bo_id} ${id}: ${response.statusText}`
250
+ );
251
+ }
252
+
253
+ return response.json();
254
+ },
255
+
256
+ async list(options?: ListOptions): Promise<ListResponse<T>> {
257
+ const requestBody: ListOptions = {
258
+ Type: "List",
259
+ ...options,
260
+ };
261
+
262
+ const response = await fetch(`${baseUrl}/api/app/${bo_id}/list`, {
263
+ method: "POST",
264
+ headers: defaultHeaders,
265
+ body: JSON.stringify(requestBody),
266
+ });
267
+
268
+ if (!response.ok) {
269
+ throw new Error(`Failed to list ${bo_id}: ${response.statusText}`);
270
+ }
271
+
272
+ const responseData: ListResponse<any> = await response.json();
273
+ return {
274
+ Data: responseData.Data.map((item) => decodeResponseData<T>(item)),
275
+ };
276
+ },
277
+
278
+ async count(options?: ListOptions): Promise<CountResponse> {
279
+ // Note: Count uses metric endpoint with Count aggregation
280
+ const requestBody = {
281
+ Type: "Metric",
282
+ GroupBy: [],
283
+ Metric: [{ Field: "_id", Type: "Count" }],
284
+ ...(options?.Filter && { Filter: options.Filter }),
285
+ };
286
+
287
+ const response = await fetch(`${baseUrl}/api/app/${bo_id}/metric`, {
288
+ method: "POST",
289
+ headers: defaultHeaders,
290
+ body: JSON.stringify(requestBody),
291
+ });
292
+
293
+ if (!response.ok) {
294
+ throw new Error(`Failed to count ${bo_id}: ${response.statusText}`);
295
+ }
296
+
297
+ const result = await response.json();
298
+ // Extract count from metric response
299
+ const count = result.Data?.[0]?.count__id ?? 0;
300
+ return { Count: count };
301
+ },
302
+
303
+ // ============================================================
304
+ // DRAFT/INTERACTIVE OPERATIONS
305
+ // ============================================================
306
+
307
+ async draft(data: Partial<T>): Promise<DraftResponse> {
308
+ const response = await fetch(`${baseUrl}/api/app/${bo_id}/draft`, {
309
+ method: "POST",
310
+ headers: defaultHeaders,
311
+ body: JSON.stringify(data),
312
+ });
313
+
314
+ if (!response.ok) {
315
+ throw new Error(
316
+ `Failed to create draft for ${bo_id}: ${response.statusText}`
317
+ );
318
+ }
319
+
320
+ return response.json();
321
+ },
322
+
323
+ async draftUpdate(
324
+ id: string,
325
+ data: Partial<T>
326
+ ): Promise<CreateUpdateResponse> {
327
+ const response = await fetch(`${baseUrl}/api/app/${bo_id}/${id}/draft`, {
328
+ method: "POST",
329
+ headers: defaultHeaders,
330
+ body: JSON.stringify(data),
331
+ });
332
+
333
+ if (!response.ok) {
334
+ throw new Error(
335
+ `Failed to update draft for ${bo_id} ${id}: ${response.statusText}`
336
+ );
337
+ }
338
+
339
+ return response.json();
340
+ },
341
+
342
+ async draftPatch(id: string, data: Partial<T>): Promise<DraftResponse> {
343
+ const response = await fetch(`${baseUrl}/api/app/${bo_id}/${id}/draft`, {
344
+ method: "PATCH",
345
+ headers: defaultHeaders,
346
+ body: JSON.stringify(data),
347
+ });
348
+
349
+ if (!response.ok) {
350
+ throw new Error(
351
+ `Failed to patch draft for ${bo_id} ${id}: ${response.statusText}`
352
+ );
353
+ }
354
+
355
+ return response.json();
356
+ },
357
+
358
+ // ============================================================
359
+ // QUERY OPERATIONS
360
+ // ============================================================
361
+
362
+ async metric(
363
+ options: Omit<MetricOptions, "Type">
364
+ ): Promise<MetricResponse> {
365
+ const requestBody: MetricOptions = {
366
+ Type: "Metric",
367
+ ...options,
368
+ };
369
+
370
+ const response = await fetch(`${baseUrl}/api/app/${bo_id}/metric`, {
371
+ method: "POST",
372
+ headers: defaultHeaders,
373
+ body: JSON.stringify(requestBody),
374
+ });
375
+
376
+ if (!response.ok) {
377
+ throw new Error(
378
+ `Failed to get metrics for ${bo_id}: ${response.statusText}`
379
+ );
380
+ }
381
+
382
+ return response.json();
383
+ },
384
+
385
+ async pivot(options: Omit<PivotOptions, "Type">): Promise<PivotResponse> {
386
+ const requestBody: PivotOptions = {
387
+ Type: "Pivot",
388
+ ...options,
389
+ };
390
+
391
+ const response = await fetch(`${baseUrl}/api/app/${bo_id}/pivot`, {
392
+ method: "POST",
393
+ headers: defaultHeaders,
394
+ body: JSON.stringify(requestBody),
395
+ });
396
+
397
+ if (!response.ok) {
398
+ throw new Error(
399
+ `Failed to get pivot data for ${bo_id}: ${response.statusText}`
400
+ );
401
+ }
402
+
403
+ return response.json();
404
+ },
405
+
406
+ // ============================================================
407
+ // METADATA OPERATIONS
408
+ // ============================================================
409
+
410
+ async fields(): Promise<FieldsResponse> {
411
+ const response = await fetch(`${baseUrl}/api/app/${bo_id}/fields`, {
412
+ method: "GET",
413
+ headers: defaultHeaders,
414
+ });
415
+
416
+ if (!response.ok) {
417
+ throw new Error(
418
+ `Failed to get fields for ${bo_id}: ${response.statusText}`
419
+ );
420
+ }
421
+
422
+ return response.json();
423
+ },
424
+
425
+ async fetchField(
426
+ instanceId: string,
427
+ fieldId: string
428
+ ): Promise<FetchFieldOption[]> {
429
+ const response = await fetch(
430
+ `${baseUrl}/api/app/${bo_id}/${instanceId}/field/${fieldId}/fetch`,
431
+ {
432
+ method: "GET",
433
+ headers: defaultHeaders,
434
+ }
435
+ );
436
+
437
+ if (!response.ok) {
438
+ throw new Error(
439
+ `Failed to fetch field ${fieldId} for ${bo_id}: ${response.statusText}`
440
+ );
441
+ }
442
+
443
+ const responseData: FetchFieldResponse = await response.json();
444
+ return responseData.Data;
445
+ },
446
+ };
447
+ }
@@ -0,0 +1,33 @@
1
+ import type { DateTimeEncoded, DateEncoded } from '../types/common';
2
+
3
+ /**
4
+ * Utility functions for datetime encoding/decoding
5
+ */
6
+
7
+ /**
8
+ * Encode a Date object to API datetime format
9
+ */
10
+ export function encodeDatetime(date: Date): DateTimeEncoded {
11
+ return { $__dt__: date.getTime() / 1000 };
12
+ }
13
+
14
+ /**
15
+ * Decode API datetime format to Date object
16
+ */
17
+ export function decodeDatetime(encoded: DateTimeEncoded): Date {
18
+ return new Date(encoded.$__dt__ * 1000);
19
+ }
20
+
21
+ /**
22
+ * Encode a Date object to API date format (YYYY-MM-DD)
23
+ */
24
+ export function encodeDate(date: Date): DateEncoded {
25
+ return { $__d__: date.toISOString().split('T')[0] };
26
+ }
27
+
28
+ /**
29
+ * Decode API date format to Date object
30
+ */
31
+ export function decodeDate(encoded: DateEncoded): Date {
32
+ return new Date(encoded.$__d__);
33
+ }
@@ -0,0 +1,61 @@
1
+ // Main API client
2
+ export {
3
+ api,
4
+ setApiBaseUrl,
5
+ setDefaultHeaders,
6
+ getDefaultHeaders,
7
+ getApiBaseUrl,
8
+ } from "./client";
9
+ export type { ResourceClient } from "./client";
10
+
11
+ // DateTime utilities
12
+ export {
13
+ encodeDatetime,
14
+ decodeDatetime,
15
+ encodeDate,
16
+ decodeDate,
17
+ } from "./datetime";
18
+
19
+ // Metadata API client
20
+ export { getBdoSchema, listMetadata } from "./metadata";
21
+ export type { BackendSchema, MetadataItem, FieldMetadata } from "./metadata";
22
+
23
+ // Re-export common types for convenience
24
+ export type {
25
+ // Sort types
26
+ SortDirection,
27
+ SortOption,
28
+ Sort,
29
+ // Filter types
30
+ Filter,
31
+ FilterCondition,
32
+ FilterOperator,
33
+ FilterRHSType,
34
+ LogicalOperator,
35
+ FilterLogical,
36
+ FilterNode,
37
+ // List types
38
+ ListOptions,
39
+ ListResponse,
40
+ ReadResponse,
41
+ CreateUpdateResponse,
42
+ DeleteResponse,
43
+ CountResponse,
44
+ // DateTime types
45
+ DateTimeEncoded,
46
+ DateEncoded,
47
+ // Metric types
48
+ MetricType,
49
+ MetricField,
50
+ MetricOptions,
51
+ MetricResponse,
52
+ // Pivot types
53
+ PivotHeaderItem,
54
+ PivotResponseData,
55
+ PivotOptions,
56
+ PivotResponse,
57
+ // Draft types
58
+ DraftResponse,
59
+ // Fields types
60
+ FieldsResponse,
61
+ } from "../types/common";
@@ -0,0 +1,148 @@
1
+ // ============================================================
2
+ // METADATA API CLIENT
3
+ // ============================================================
4
+ // Handles metadata/schema fetching operations for Business Objects
5
+
6
+ import type { ListOptions, ListResponse } from "../types/common";
7
+ import { getApiBaseUrl, getDefaultHeaders } from "./client";
8
+
9
+ // ============================================================
10
+ // METADATA API OPERATIONS
11
+ // ============================================================
12
+
13
+ /**
14
+ * BDO Schema Structure (Business Object Metadata)
15
+ */
16
+ export interface BackendSchema {
17
+ [fieldName: string]: any;
18
+ }
19
+
20
+ /**
21
+ * Get BDO schema/metadata by ID
22
+ *
23
+ * Endpoint: GET //api/app/meta/bdo/${metaId}
24
+ *
25
+ * @param metaId - The Business Object metadata ID (e.g., "Product", "Order")
26
+ * @returns Promise resolving to the BDO schema
27
+ *
28
+ * @example
29
+ * ```typescript
30
+ * const schema = await getBdoSchema("Product");
31
+ * console.log(schema.Fields); // Access field definitions
32
+ * ```
33
+ */
34
+ export async function getBdoSchema(metaId: string): Promise<BackendSchema> {
35
+ try {
36
+ const baseUrl = getApiBaseUrl();
37
+ const headers = getDefaultHeaders();
38
+
39
+ const response = await fetch(`${baseUrl}/api/app/meta/bdo/${metaId}`, {
40
+ method: "GET",
41
+ headers,
42
+ });
43
+
44
+ if (!response.ok) {
45
+ throw new Error(
46
+ `Failed to fetch schema for ${metaId}: ${response.statusText}`
47
+ );
48
+ }
49
+
50
+ const bdoSchema = await response.json();
51
+
52
+ // Validate that response is a valid BDO schema object
53
+ if (!bdoSchema || typeof bdoSchema !== "object") {
54
+ throw new Error(`Invalid BDO schema response for ${metaId}`);
55
+ }
56
+
57
+ return bdoSchema as BackendSchema;
58
+ } catch (error) {
59
+ console.error(`Schema fetch error for ${metaId}:`, error);
60
+ throw new Error(
61
+ `Failed to load BDO schema: ${error instanceof Error ? error.message : "Unknown error"}`
62
+ );
63
+ }
64
+ }
65
+
66
+ /**
67
+ * Metadata item structure
68
+ */
69
+ export interface MetadataItem {
70
+ _id: string;
71
+ Name: string;
72
+ Kind: string;
73
+ Description?: string;
74
+ [key: string]: any;
75
+ }
76
+
77
+ /**
78
+ * List all metadata items with optional filtering and pagination
79
+ *
80
+ * Endpoint: GET or POST /api/app/metadata/list
81
+ *
82
+ * @param options - Optional list options (filters, sorting, pagination)
83
+ * @returns Promise resolving to list of metadata items
84
+ *
85
+ * @example
86
+ * ```typescript
87
+ * // List all metadata
88
+ * const all = await listMetadata();
89
+ *
90
+ * // List with filters
91
+ * const businessObjects = await listMetadata({
92
+ * Filter: {
93
+ * Operator: "AND",
94
+ * Condition: [{ LhsField: "Kind", Operator: "eq", RhsValue: "BusinessObject" }]
95
+ * }
96
+ * });
97
+ * ```
98
+ */
99
+ export async function listMetadata(
100
+ options?: ListOptions
101
+ ): Promise<ListResponse<MetadataItem>> {
102
+ try {
103
+ const baseUrl = getApiBaseUrl();
104
+ const headers = getDefaultHeaders();
105
+
106
+ // Use GET for simple requests, POST for complex filters
107
+ const method = options?.Filter || options?.Sort ? "POST" : "GET";
108
+
109
+ const response = await fetch(`${baseUrl}/api/app/metadata/list`, {
110
+ method,
111
+ headers,
112
+ ...(method === "POST" &&
113
+ options && {
114
+ body: JSON.stringify(options),
115
+ }),
116
+ });
117
+
118
+ if (!response.ok) {
119
+ throw new Error(`Failed to list metadata: ${response.statusText}`);
120
+ }
121
+
122
+ const result = await response.json();
123
+
124
+ return result as ListResponse<MetadataItem>;
125
+ } catch (error) {
126
+ console.error("Metadata list error:", error);
127
+ throw new Error(
128
+ `Failed to list metadata: ${error instanceof Error ? error.message : "Unknown error"}`
129
+ );
130
+ }
131
+ }
132
+
133
+ /**
134
+ * Field metadata structure
135
+ */
136
+ export interface FieldMetadata {
137
+ Id: string;
138
+ Name: string;
139
+ Type: string;
140
+ Required?: boolean;
141
+ Unique?: boolean;
142
+ Computed?: boolean;
143
+ Values?: {
144
+ Mode: "Static" | "Dynamic";
145
+ Items?: Array<{ Value: string; Label: string }>;
146
+ };
147
+ [key: string]: any;
148
+ }