@ram_28/kf-ai-sdk 2.0.1 → 2.0.3

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 (193) hide show
  1. package/README.md +36 -39
  2. package/dist/BaseField-B6da88U7.js +40 -0
  3. package/dist/BaseField-Drp0-OxL.cjs +1 -0
  4. package/dist/api/client.d.ts +7 -0
  5. package/dist/api/client.d.ts.map +1 -1
  6. package/dist/api/index.d.ts +1 -1
  7. package/dist/api/index.d.ts.map +1 -1
  8. package/dist/api/metadata.d.ts +26 -22
  9. package/dist/api/metadata.d.ts.map +1 -1
  10. package/dist/api.cjs +1 -1
  11. package/dist/api.mjs +3 -3
  12. package/dist/auth.cjs +1 -1
  13. package/dist/auth.mjs +2 -2
  14. package/dist/base-types.d.ts +1 -1
  15. package/dist/base-types.d.ts.map +1 -1
  16. package/dist/bdo/core/BaseBdo.d.ts +12 -20
  17. package/dist/bdo/core/BaseBdo.d.ts.map +1 -1
  18. package/dist/bdo/core/Item.d.ts +8 -44
  19. package/dist/bdo/core/Item.d.ts.map +1 -1
  20. package/dist/bdo/core/types.d.ts +124 -41
  21. package/dist/bdo/core/types.d.ts.map +1 -1
  22. package/dist/bdo/fields/ArrayField.d.ts +5 -4
  23. package/dist/bdo/fields/ArrayField.d.ts.map +1 -1
  24. package/dist/bdo/fields/BaseField.d.ts +14 -19
  25. package/dist/bdo/fields/BaseField.d.ts.map +1 -1
  26. package/dist/bdo/fields/BooleanField.d.ts +3 -4
  27. package/dist/bdo/fields/BooleanField.d.ts.map +1 -1
  28. package/dist/bdo/fields/DateField.d.ts +3 -4
  29. package/dist/bdo/fields/DateField.d.ts.map +1 -1
  30. package/dist/bdo/fields/DateTimeField.d.ts +5 -4
  31. package/dist/bdo/fields/DateTimeField.d.ts.map +1 -1
  32. package/dist/bdo/fields/FileField.d.ts +18 -0
  33. package/dist/bdo/fields/FileField.d.ts.map +1 -0
  34. package/dist/bdo/fields/NumberField.d.ts +6 -4
  35. package/dist/bdo/fields/NumberField.d.ts.map +1 -1
  36. package/dist/bdo/fields/ObjectField.d.ts +5 -4
  37. package/dist/bdo/fields/ObjectField.d.ts.map +1 -1
  38. package/dist/bdo/fields/ReferenceField.d.ts +13 -14
  39. package/dist/bdo/fields/ReferenceField.d.ts.map +1 -1
  40. package/dist/bdo/fields/SelectField.d.ts +9 -16
  41. package/dist/bdo/fields/SelectField.d.ts.map +1 -1
  42. package/dist/bdo/fields/StringField.d.ts +6 -4
  43. package/dist/bdo/fields/StringField.d.ts.map +1 -1
  44. package/dist/bdo/fields/TextAreaField.d.ts +1 -18
  45. package/dist/bdo/fields/TextAreaField.d.ts.map +1 -1
  46. package/dist/bdo/fields/TextField.d.ts +22 -0
  47. package/dist/bdo/fields/TextField.d.ts.map +1 -0
  48. package/dist/bdo/fields/UserField.d.ts +20 -0
  49. package/dist/bdo/fields/UserField.d.ts.map +1 -0
  50. package/dist/bdo/fields/index.d.ts +5 -2
  51. package/dist/bdo/fields/index.d.ts.map +1 -1
  52. package/dist/bdo/index.d.ts +2 -2
  53. package/dist/bdo/index.d.ts.map +1 -1
  54. package/dist/bdo.cjs +1 -1
  55. package/dist/bdo.d.ts +1 -5
  56. package/dist/bdo.d.ts.map +1 -1
  57. package/dist/bdo.mjs +286 -243
  58. package/dist/bdo.types.d.ts +2 -3
  59. package/dist/bdo.types.d.ts.map +1 -1
  60. package/dist/{client-BIkaIr2y.js → client-BULEEaCP.js} +84 -79
  61. package/dist/client-DtPpfJc1.cjs +1 -0
  62. package/dist/components/hooks/useFilter/useFilter.d.ts.map +1 -1
  63. package/dist/components/hooks/useForm/createItemProxy.d.ts.map +1 -1
  64. package/dist/components/hooks/useForm/createResolver.d.ts +12 -2
  65. package/dist/components/hooks/useForm/createResolver.d.ts.map +1 -1
  66. package/dist/components/hooks/useForm/index.d.ts +1 -1
  67. package/dist/components/hooks/useForm/index.d.ts.map +1 -1
  68. package/dist/components/hooks/useForm/types.d.ts +77 -8
  69. package/dist/components/hooks/useForm/types.d.ts.map +1 -1
  70. package/dist/components/hooks/useForm/useDraftInteraction.d.ts +26 -0
  71. package/dist/components/hooks/useForm/useDraftInteraction.d.ts.map +1 -0
  72. package/dist/components/hooks/useForm/useForm.d.ts +2 -27
  73. package/dist/components/hooks/useForm/useForm.d.ts.map +1 -1
  74. package/dist/components/hooks/useTable/useTable.d.ts.map +1 -1
  75. package/dist/{constants-DaX7GLgl.js → constants-BQrBcCON.js} +37 -13
  76. package/dist/constants-D0J69if5.cjs +1 -0
  77. package/dist/error-handling-CAoD0Kwb.cjs +1 -0
  78. package/dist/error-handling-CrhTtD88.js +14 -0
  79. package/dist/filter.cjs +1 -1
  80. package/dist/filter.mjs +2 -2
  81. package/dist/form.cjs +1 -1
  82. package/dist/form.d.ts +1 -1
  83. package/dist/form.d.ts.map +1 -1
  84. package/dist/form.mjs +333 -1142
  85. package/dist/form.types.d.ts +1 -1
  86. package/dist/form.types.d.ts.map +1 -1
  87. package/dist/index.d.ts +2 -1
  88. package/dist/index.d.ts.map +1 -1
  89. package/dist/index.esm-Cj63v5ny.js +1014 -0
  90. package/dist/index.esm-DuwT11sx.cjs +1 -0
  91. package/dist/{metadata-Bz8zJqC1.cjs → metadata-BJWukIqS.cjs} +1 -1
  92. package/dist/{metadata-VbQzyD2C.js → metadata-CJuFxytC.js} +1 -1
  93. package/dist/table.cjs +1 -1
  94. package/dist/table.mjs +116 -122
  95. package/dist/types/base-fields.d.ts +24 -59
  96. package/dist/types/base-fields.d.ts.map +1 -1
  97. package/dist/types/constants.d.ts +2 -2
  98. package/dist/types/constants.d.ts.map +1 -1
  99. package/dist/useFilter-Bg0jvIL6.cjs +1 -0
  100. package/dist/useFilter-DPNLKY3H.js +118 -0
  101. package/dist/utils/formatting.d.ts +10 -1
  102. package/dist/utils/formatting.d.ts.map +1 -1
  103. package/dist/workflow/Activity.d.ts +85 -0
  104. package/dist/workflow/Activity.d.ts.map +1 -0
  105. package/dist/workflow/ActivityInstance.d.ts +96 -0
  106. package/dist/workflow/ActivityInstance.d.ts.map +1 -0
  107. package/dist/workflow/client.d.ts +39 -0
  108. package/dist/workflow/client.d.ts.map +1 -0
  109. package/dist/workflow/components/useActivityForm/createActivityItemProxy.d.ts +16 -0
  110. package/dist/workflow/components/useActivityForm/createActivityItemProxy.d.ts.map +1 -0
  111. package/dist/workflow/components/useActivityForm/createActivityResolver.d.ts +22 -0
  112. package/dist/workflow/components/useActivityForm/createActivityResolver.d.ts.map +1 -0
  113. package/dist/workflow/components/useActivityForm/index.d.ts +3 -0
  114. package/dist/workflow/components/useActivityForm/index.d.ts.map +1 -0
  115. package/dist/workflow/components/useActivityForm/types.d.ts +80 -0
  116. package/dist/workflow/components/useActivityForm/types.d.ts.map +1 -0
  117. package/dist/workflow/components/useActivityForm/useActivityForm.d.ts +4 -0
  118. package/dist/workflow/components/useActivityForm/useActivityForm.d.ts.map +1 -0
  119. package/dist/workflow/index.d.ts +8 -0
  120. package/dist/workflow/index.d.ts.map +1 -0
  121. package/dist/workflow/types.d.ts +53 -0
  122. package/dist/workflow/types.d.ts.map +1 -0
  123. package/dist/workflow.cjs +1 -0
  124. package/dist/workflow.d.ts +8 -0
  125. package/dist/workflow.d.ts.map +1 -0
  126. package/dist/workflow.mjs +565 -0
  127. package/dist/workflow.types.cjs +1 -0
  128. package/dist/workflow.types.d.ts +2 -0
  129. package/dist/workflow.types.d.ts.map +1 -0
  130. package/dist/workflow.types.mjs +1 -0
  131. package/docs/api.md +140 -572
  132. package/docs/bdo.md +742 -0
  133. package/docs/useAuth.md +10 -4
  134. package/docs/useFilter.md +40 -40
  135. package/docs/useForm.md +91 -62
  136. package/docs/useTable.md +38 -38
  137. package/docs/workflow.md +703 -0
  138. package/package.json +21 -1
  139. package/sdk/api/client.ts +77 -57
  140. package/sdk/api/index.ts +1 -0
  141. package/sdk/api/metadata.ts +22 -20
  142. package/sdk/base-types.ts +5 -9
  143. package/sdk/bdo/core/BaseBdo.ts +23 -38
  144. package/sdk/bdo/core/Item.ts +34 -56
  145. package/sdk/bdo/core/types.ts +147 -45
  146. package/sdk/bdo/fields/ArrayField.ts +9 -5
  147. package/sdk/bdo/fields/BaseField.ts +19 -29
  148. package/sdk/bdo/fields/BooleanField.ts +4 -5
  149. package/sdk/bdo/fields/DateField.ts +4 -5
  150. package/sdk/bdo/fields/DateTimeField.ts +9 -5
  151. package/sdk/bdo/fields/FileField.ts +39 -0
  152. package/sdk/bdo/fields/NumberField.ts +8 -5
  153. package/sdk/bdo/fields/ObjectField.ts +9 -5
  154. package/sdk/bdo/fields/ReferenceField.ts +22 -28
  155. package/sdk/bdo/fields/SelectField.ts +13 -26
  156. package/sdk/bdo/fields/StringField.ts +10 -5
  157. package/sdk/bdo/fields/TextAreaField.ts +3 -32
  158. package/sdk/bdo/fields/TextField.ts +42 -0
  159. package/sdk/bdo/fields/UserField.ts +52 -0
  160. package/sdk/bdo/fields/index.ts +5 -2
  161. package/sdk/bdo/index.ts +19 -4
  162. package/sdk/bdo.ts +4 -31
  163. package/sdk/bdo.types.ts +26 -21
  164. package/sdk/components/hooks/useFilter/useFilter.ts +13 -30
  165. package/sdk/components/hooks/useForm/createItemProxy.ts +47 -11
  166. package/sdk/components/hooks/useForm/createResolver.ts +65 -6
  167. package/sdk/components/hooks/useForm/index.ts +4 -0
  168. package/sdk/components/hooks/useForm/types.ts +92 -9
  169. package/sdk/components/hooks/useForm/useDraftInteraction.ts +251 -0
  170. package/sdk/components/hooks/useForm/useForm.ts +132 -60
  171. package/sdk/components/hooks/useTable/useTable.ts +10 -2
  172. package/sdk/form.ts +1 -12
  173. package/sdk/form.types.ts +1 -0
  174. package/sdk/index.ts +9 -3
  175. package/sdk/types/base-fields.ts +28 -72
  176. package/sdk/types/constants.ts +2 -2
  177. package/sdk/utils/formatting.ts +13 -1
  178. package/sdk/workflow/Activity.ts +181 -0
  179. package/sdk/workflow/ActivityInstance.ts +339 -0
  180. package/sdk/workflow/client.ts +208 -0
  181. package/sdk/workflow/components/useActivityForm/createActivityItemProxy.ts +126 -0
  182. package/sdk/workflow/components/useActivityForm/createActivityResolver.ts +61 -0
  183. package/sdk/workflow/components/useActivityForm/index.ts +5 -0
  184. package/sdk/workflow/components/useActivityForm/types.ts +166 -0
  185. package/sdk/workflow/components/useActivityForm/useActivityForm.ts +386 -0
  186. package/sdk/workflow/index.ts +20 -0
  187. package/sdk/workflow/types.ts +84 -0
  188. package/sdk/workflow.ts +25 -0
  189. package/sdk/workflow.types.ts +11 -0
  190. package/dist/client-DxjRcEtN.cjs +0 -1
  191. package/dist/constants-C49b9Exc.cjs +0 -1
  192. package/dist/useFilter-DzpP_ag0.cjs +0 -1
  193. package/dist/useFilter-H5bgAZQF.js +0 -120
package/docs/bdo.md ADDED
@@ -0,0 +1,742 @@
1
+ # BDO SDK API
2
+
3
+ Type-safe, role-based data access layer for business objects.
4
+
5
+ ## Imports
6
+
7
+ ```typescript
8
+ // BDO class (from your generated code)
9
+ import { AdminProduct } from "../bdo/admin/Product";
10
+
11
+ // Field types (from your generated code)
12
+ import type {
13
+ AdminProductEditableFieldType,
14
+ AdminProductReadonlyFieldType,
15
+ AdminProductFieldType,
16
+ } from "../bdo/admin/Product";
17
+
18
+ // SDK types
19
+ import type {
20
+ ItemType,
21
+ BdoMetaType,
22
+ ValidationResultType,
23
+ SelectOptionType,
24
+ EditableFieldAccessorType,
25
+ ReadonlyFieldAccessorType,
26
+ BaseFieldMetaType,
27
+ } from "@ram_28/kf-ai-sdk/bdo/types";
28
+
29
+ // System fields
30
+ import type { SystemFieldsType } from "@ram_28/kf-ai-sdk/bdo/types";
31
+
32
+ // API types (for method params/responses)
33
+ import type {
34
+ ListOptionsType,
35
+ CreateUpdateResponseType,
36
+ DeleteResponseType,
37
+ DraftResponseType,
38
+ MetricOptionsType,
39
+ MetricResponseType,
40
+ PivotOptionsType,
41
+ PivotResponseType,
42
+ } from "@ram_28/kf-ai-sdk/api/types";
43
+ ```
44
+
45
+ ## BDO Meta
46
+
47
+ Every BDO has a `meta` property identifying the business object.
48
+
49
+ ```typescript
50
+ const product = new AdminProduct();
51
+
52
+ product.meta._id; // "BDO_Product"
53
+ product.meta.name; // "Product"
54
+ ```
55
+
56
+ Use `meta._id` anywhere a source identifier is needed (e.g., `useTable`, `useFilter`).
57
+
58
+ ---
59
+
60
+ ## Field Definitions
61
+
62
+ Fields are readonly properties on the BDO class, constructed with raw backend meta JSON.
63
+
64
+ ```typescript
65
+ // In the generated BDO class
66
+ readonly Title = new StringField({
67
+ _id: "Title",
68
+ Name: "Product Title",
69
+ Type: "String",
70
+ Constraint: { Required: true, Length: 255 },
71
+ });
72
+ ```
73
+
74
+ ### BaseField Getters
75
+
76
+ Every field exposes these getters:
77
+
78
+ | Getter | Type | Source |
79
+ |--------|------|--------|
80
+ | `field.id` | `string` | `_meta._id` |
81
+ | `field.label` | `string` | `_meta.Name` |
82
+ | `field.readOnly` | `boolean` | `_meta.ReadOnly` |
83
+ | `field.required` | `boolean` | `_meta.Constraint.Required` or `_meta.Required` |
84
+ | `field.defaultValue` | `unknown` | `_meta.DefaultValue` or `_meta.Constraint.DefaultValue` |
85
+ | `field.primaryKey` | `boolean` | `_meta.Constraint.PrimaryKey` |
86
+ | `field.meta` | `BaseFieldMetaType` | Full raw backend meta object |
87
+
88
+ ### Usage
89
+
90
+ ```typescript
91
+ const product = new AdminProduct();
92
+
93
+ // react-hook-form register
94
+ register(product.Title.id);
95
+
96
+ // UI labels
97
+ <label>{product.Title.label}</label>
98
+
99
+ // Required indicator
100
+ {product.Title.required && <span>*</span>}
101
+
102
+ // Filter by field
103
+ const items = await product.list({
104
+ Filter: {
105
+ Operator: "And",
106
+ Condition: [{
107
+ LHSField: product.Price.id,
108
+ Operator: "GT",
109
+ RHSValue: 50,
110
+ RHSType: "Constant",
111
+ }],
112
+ },
113
+ });
114
+ ```
115
+
116
+ ---
117
+
118
+ ## Methods
119
+
120
+ All `BaseBdo` methods are `protected`. Role BDOs selectively re-expose them as `public` based on permissions. For full request/response type definitions, see [api.md](api.md).
121
+
122
+ ### get
123
+
124
+ Fetches a single record by ID.
125
+
126
+ ```typescript
127
+ async get(id: string): Promise<ItemType<TEditable, TReadonly>>
128
+ ```
129
+
130
+ Returns an [ItemType](#itemtype--runtime-accessor-pattern) with field accessors.
131
+
132
+ ```typescript
133
+ const item = await product.get("prod_abc123");
134
+
135
+ console.log(item._id); // "prod_abc123"
136
+ console.log(item.Title.get()); // "Wireless Headphones"
137
+ console.log(item.Title.label); // "Product Title"
138
+ ```
139
+
140
+ ---
141
+
142
+ ### list
143
+
144
+ Fetches paginated records with optional filtering, sorting, and pagination.
145
+
146
+ ```typescript
147
+ async list(options?: ListOptionsType): Promise<ItemType<TEditable, TReadonly>[]>
148
+ ```
149
+
150
+ Returns an array of [ItemType](#itemtype--runtime-accessor-pattern).
151
+
152
+ ```typescript
153
+ const items = await product.list({
154
+ Filter: {
155
+ Operator: "And",
156
+ Condition: [{
157
+ LHSField: product.Category.id,
158
+ Operator: "EQ",
159
+ RHSValue: "Electronics",
160
+ RHSType: "Constant",
161
+ }],
162
+ },
163
+ Sort: [{ [product.Price.id]: "ASC" }],
164
+ Page: 1,
165
+ PageSize: 20,
166
+ });
167
+
168
+ items.forEach((item) => {
169
+ console.log(item.Title.get(), item.Price.get());
170
+ });
171
+ ```
172
+
173
+ ---
174
+
175
+ ### count
176
+
177
+ Returns the count of records matching filter criteria.
178
+
179
+ ```typescript
180
+ async count(options?: ListOptionsType): Promise<number>
181
+ ```
182
+
183
+ Uses the same `ListOptionsType` for filtering. Returns the count directly as a `number`.
184
+
185
+ ```typescript
186
+ const total = await product.count();
187
+ console.log(`Total products: ${total}`);
188
+
189
+ // With filter
190
+ const lowStock = await product.count({
191
+ Filter: {
192
+ Operator: "And",
193
+ Condition: [{
194
+ LHSField: product.Stock.id,
195
+ Operator: "LT",
196
+ RHSValue: 10,
197
+ RHSType: "Constant",
198
+ }],
199
+ },
200
+ });
201
+ ```
202
+
203
+ ---
204
+
205
+ ### create
206
+
207
+ Creates a new record.
208
+
209
+ ```typescript
210
+ async create(data: Partial<TEditable>): Promise<ItemType<TEditable, TReadonly>>
211
+ ```
212
+
213
+ Returns an [ItemType](#itemtype--runtime-accessor-pattern) with the new `_id` from the API response and the input data as field accessors.
214
+
215
+ ```typescript
216
+ const newItem = await product.create({
217
+ Title: "Wireless Headphones",
218
+ Price: 99.99,
219
+ Category: "Electronics",
220
+ });
221
+
222
+ console.log(newItem._id); // New record ID
223
+ console.log(newItem.Title.get()); // "Wireless Headphones"
224
+ ```
225
+
226
+ ---
227
+
228
+ ### update
229
+
230
+ Updates an existing record.
231
+
232
+ ```typescript
233
+ async update(id: string, data: Partial<TEditable>): Promise<CreateUpdateResponseType>
234
+ ```
235
+
236
+ Returns `{ _id: string }`.
237
+
238
+ ```typescript
239
+ const result = await product.update("prod_abc123", {
240
+ Price: 79.99,
241
+ Stock: 45,
242
+ });
243
+
244
+ console.log("Updated:", result._id);
245
+ ```
246
+
247
+ ---
248
+
249
+ ### delete
250
+
251
+ Deletes a record by ID.
252
+
253
+ ```typescript
254
+ async delete(id: string): Promise<DeleteResponseType>
255
+ ```
256
+
257
+ Returns `{ status: "success" }`.
258
+
259
+ ```typescript
260
+ const result = await product.delete("prod_abc123");
261
+
262
+ if (result.status === "success") {
263
+ console.log("Deleted successfully");
264
+ }
265
+ ```
266
+
267
+ ---
268
+
269
+ ### draft
270
+
271
+ Previews computed field values for a new record without saving.
272
+
273
+ ```typescript
274
+ async draft(data: Partial<TEditable>): Promise<DraftResponseType>
275
+ ```
276
+
277
+ Returns computed field values as `{ [fieldName: string]: any }`.
278
+
279
+ ```typescript
280
+ const draftResult = await product.draft({
281
+ Price: 100,
282
+ DiscountPercent: 15,
283
+ });
284
+
285
+ console.log("Computed discount:", draftResult.DiscountAmount);
286
+ console.log("Computed final price:", draftResult.FinalPrice);
287
+ ```
288
+
289
+ ---
290
+
291
+ ### draftPatch
292
+
293
+ Previews computed field values for an existing record being edited.
294
+
295
+ ```typescript
296
+ async draftPatch(id: string, data: Partial<TEditable>): Promise<DraftResponseType>
297
+ ```
298
+
299
+ ```typescript
300
+ const draftResult = await product.draftPatch("prod_abc123", {
301
+ Price: 120,
302
+ DiscountPercent: 20,
303
+ });
304
+
305
+ console.log("Updated discount:", draftResult.DiscountAmount);
306
+ ```
307
+
308
+ ---
309
+
310
+ ### draftInteraction
311
+
312
+ Creates/updates a draft without requiring an instance ID. Returns computed fields along with a temporary `_id`.
313
+
314
+ ```typescript
315
+ async draftInteraction(data: Partial<TEditable>): Promise<DraftResponseType & { _id: string }>
316
+ ```
317
+
318
+ ```typescript
319
+ const result = await product.draftInteraction({
320
+ Price: 100,
321
+ DiscountPercent: 10,
322
+ });
323
+
324
+ console.log(result._id); // Temporary draft ID
325
+ console.log(result.DiscountAmount); // Computed value
326
+ ```
327
+
328
+ ---
329
+
330
+ ### createItem
331
+
332
+ Creates an `ItemType` wrapper synchronously (no API call). Useful for creating an empty item for form binding.
333
+
334
+ ```typescript
335
+ createItem(data?: Partial<TEditable>): ItemType<TEditable, TReadonly>
336
+ ```
337
+
338
+ ```typescript
339
+ const emptyItem = product.createItem();
340
+ emptyItem.Title.set("Draft Product");
341
+ emptyItem.Price.set(0);
342
+
343
+ const validation = emptyItem.validate();
344
+ console.log(validation.valid); // false (required fields missing)
345
+ ```
346
+
347
+ ---
348
+
349
+ ### metric
350
+
351
+ Performs aggregation queries on records.
352
+
353
+ ```typescript
354
+ async metric(options: Omit<MetricOptionsType, "Type">): Promise<MetricResponseType>
355
+ ```
356
+
357
+ The `Type` field is added internally. Pass only `GroupBy`, `Metric`, and optional `Filter`.
358
+
359
+ ```typescript
360
+ // Total count
361
+ const response = await product.metric({
362
+ GroupBy: [],
363
+ Metric: [{ Field: "_id", Type: "Count" }],
364
+ });
365
+ console.log("Total:", response.Data[0]["count__id"]);
366
+
367
+ // Group by category with multiple metrics
368
+ const byCategory = await product.metric({
369
+ GroupBy: ["Category"],
370
+ Metric: [
371
+ { Field: "Stock", Type: "Sum" },
372
+ { Field: "Price", Type: "Avg" },
373
+ ],
374
+ });
375
+ byCategory.Data.forEach((row) => {
376
+ console.log(`${row.Category}: ${row["sum_Stock"]} stock, $${row["avg_Price"]} avg`);
377
+ });
378
+ ```
379
+
380
+ ---
381
+
382
+ ### pivot
383
+
384
+ Creates pivot table aggregations with row and column dimensions.
385
+
386
+ ```typescript
387
+ async pivot(options: Omit<PivotOptionsType, "Type">): Promise<PivotResponseType>
388
+ ```
389
+
390
+ The `Type` field is added internally. Pass only `Row`, `Column`, `Metric`, and optional `Filter`.
391
+
392
+ ```typescript
393
+ const response = await product.pivot({
394
+ Row: ["Category"],
395
+ Column: ["Region"],
396
+ Metric: [{ Field: "Stock", Type: "Sum" }],
397
+ });
398
+
399
+ const { RowHeader, ColumnHeader, Value } = response.Data;
400
+
401
+ RowHeader.forEach((row, ri) => {
402
+ ColumnHeader.forEach((col, ci) => {
403
+ console.log(`${row.Key} - ${col.Key}: ${Value[ri][ci]}`);
404
+ });
405
+ });
406
+ ```
407
+
408
+ ---
409
+
410
+ ## Field Classes
411
+
412
+ All field classes extend `BaseField<T>` and accept raw backend meta JSON as the constructor parameter.
413
+
414
+ | Class | Backend Type | Extra Getters |
415
+ |-------|-------------|---------------|
416
+ | `StringField` | `"String"` | `length` |
417
+ | `NumberField` | `"Number"` | `integerPart`, `fractionPart` |
418
+ | `BooleanField` | `"Boolean"` | — |
419
+ | `DateField` | `"Date"` | — |
420
+ | `DateTimeField` | `"DateTime"` | `precision` |
421
+ | `SelectField<T>` | `"String"` | `options`, `fetchOptions()` |
422
+ | `ReferenceField<T>` | `"Reference"` | `referenceBdo`, `referenceFields`, `searchFields`, `fetchOptions()` |
423
+ | `TextField` | `"Text"` | `format` |
424
+ | `UserField` | `"User"` | `businessEntity` |
425
+ | `FileField` | `"File"` | — |
426
+ | `ArrayField<T>` | `"Array"` | `elementType` |
427
+ | `ObjectField<T>` | `"Object"` | `properties` |
428
+
429
+ ### SelectField
430
+
431
+ Options from `Constraint.Enum` are available synchronously via the `options` getter:
432
+
433
+ ```typescript
434
+ product.Status.options;
435
+ // [{ value: "active", label: "active" }, { value: "inactive", label: "inactive" }]
436
+ ```
437
+
438
+ Dynamic options can be fetched from the backend via `fetchOptions()`:
439
+
440
+ ```typescript
441
+ async fetchOptions(instanceId?: string): Promise<SelectOptionType<T>[]>
442
+ ```
443
+
444
+ ```typescript
445
+ const statusOptions = await product.Status.fetchOptions();
446
+ // [{ value: "active", label: "Active" }, { value: "inactive", label: "Inactive" }]
447
+ ```
448
+
449
+ ### ReferenceField
450
+
451
+ Reference configuration is derived from `View.DataObject` in the raw meta:
452
+
453
+ ```typescript
454
+ product.SupplierInfo.referenceBdo; // "BDO_Supplier"
455
+ product.SupplierInfo.referenceFields; // ["_id", "SupplierName", "Email"]
456
+ product.SupplierInfo.searchFields; // ["SupplierName"]
457
+ ```
458
+
459
+ Referenced records can be fetched via `fetchOptions()`:
460
+
461
+ ```typescript
462
+ async fetchOptions(instanceId?: string): Promise<TRef[]>
463
+ ```
464
+
465
+ ```typescript
466
+ const suppliers = await product.SupplierInfo.fetchOptions();
467
+ // [{ _id: "sup_1", SupplierName: "Acme Corp", Email: "contact@acme.com" }, ...]
468
+ ```
469
+
470
+ ---
471
+
472
+ ## ItemType — Runtime Accessor Pattern
473
+
474
+ `ItemType<TEditable, TReadonly>` is what `get()`, `list()`, `create()`, and `createItem()` return. It wraps API response data with a Proxy, providing field accessors for every field.
475
+
476
+ ### Field Accessor Access
477
+
478
+ ```typescript
479
+ const item = await product.get("prod_abc123");
480
+
481
+ // Get value (NOT direct access — always use .get())
482
+ item.Title.get(); // "Wireless Headphones"
483
+
484
+ // Field metadata
485
+ item.Title.label; // "Product Title"
486
+ item.Title.required; // true
487
+ item.Title.readOnly; // false
488
+ item.Title.defaultValue; // undefined
489
+ item.Title.meta; // full raw backend meta (BaseFieldMetaType)
490
+
491
+ // Set value (only on editable fields)
492
+ item.Title.set("New Title");
493
+
494
+ // Validate (type + expression rules)
495
+ const result = item.Title.validate();
496
+ // { valid: true, errors: [] }
497
+ ```
498
+
499
+ ### Direct `_id` Access
500
+
501
+ `_id` is the only field accessed directly (not as an accessor):
502
+
503
+ ```typescript
504
+ item._id; // "prod_abc123"
505
+ ```
506
+
507
+ ### Editable vs Readonly Accessors
508
+
509
+ Fields in `TEditable` get a `set()` method. Fields in `TReadonly` do not.
510
+
511
+ **Editable field accessor:**
512
+
513
+ ```typescript
514
+ {
515
+ label: string,
516
+ required: boolean,
517
+ readOnly: false, // always false for editable
518
+ defaultValue: unknown,
519
+ meta: BaseFieldMetaType,
520
+ get(): T | undefined,
521
+ set(value: T): void, // only on editable fields
522
+ validate(): ValidationResultType,
523
+ }
524
+ ```
525
+
526
+ **Readonly field accessor:**
527
+
528
+ ```typescript
529
+ {
530
+ label: string,
531
+ required: boolean,
532
+ readOnly: true, // always true for readonly
533
+ defaultValue: unknown,
534
+ meta: BaseFieldMetaType,
535
+ get(): T | undefined,
536
+ validate(): ValidationResultType,
537
+ // no set()
538
+ }
539
+ ```
540
+
541
+ ### Item Methods
542
+
543
+ ```typescript
544
+ // Validate all non-readonly fields
545
+ item.validate();
546
+ // { valid: boolean, errors: string[] }
547
+
548
+ // Convert to plain object
549
+ item.toJSON();
550
+ // Partial<T> — raw data without accessors
551
+ ```
552
+
553
+ ---
554
+
555
+ ## Type Definitions
556
+
557
+ ### BdoMetaType
558
+
559
+ ```typescript
560
+ interface BdoMetaType {
561
+ readonly _id: string; // Business object ID (e.g., "BDO_Product")
562
+ readonly name: string; // Display name (e.g., "Product")
563
+ }
564
+ ```
565
+
566
+ ### ValidationResultType
567
+
568
+ ```typescript
569
+ interface ValidationResultType {
570
+ valid: boolean;
571
+ errors: string[];
572
+ }
573
+ ```
574
+
575
+ ### SelectOptionType
576
+
577
+ ```typescript
578
+ interface SelectOptionType<T = string> {
579
+ value: T;
580
+ label: string;
581
+ disabled?: boolean;
582
+ }
583
+ ```
584
+
585
+ ### SystemFieldsType
586
+
587
+ ```typescript
588
+ type SystemFieldsType = {
589
+ _id: string;
590
+ _created_at: DateTimeFieldType;
591
+ _modified_at: DateTimeFieldType;
592
+ _created_by: UserFieldType; // { _id: string; _name: string }
593
+ _modified_by: UserFieldType;
594
+ _version: string;
595
+ _m_version: string;
596
+ };
597
+
598
+ // Union of system field names (for Omit<> operations)
599
+ type SystemFields = keyof SystemFieldsType;
600
+ ```
601
+
602
+ ### BaseFieldMetaType
603
+
604
+ The raw backend meta shape stored by every field:
605
+
606
+ ```typescript
607
+ interface BaseFieldMetaType {
608
+ _id: string; // Field identifier
609
+ Name: string; // Display name
610
+ Type: string; // Field type ("String", "Number", "Reference", etc.)
611
+ ReadOnly?: boolean;
612
+ Required?: boolean;
613
+ Constraint?: BaseConstraintType;
614
+ DefaultValue?: unknown;
615
+ }
616
+ ```
617
+
618
+ ### BaseConstraintType
619
+
620
+ ```typescript
621
+ interface BaseConstraintType {
622
+ Required?: boolean;
623
+ PrimaryKey?: boolean;
624
+ DefaultValue?: unknown;
625
+ }
626
+ ```
627
+
628
+ ### EditableFieldAccessorType
629
+
630
+ ```typescript
631
+ interface EditableFieldAccessorType<T> {
632
+ readonly label: string;
633
+ readonly required: boolean;
634
+ readonly readOnly: boolean;
635
+ readonly defaultValue: unknown;
636
+ readonly meta: BaseFieldMetaType;
637
+ get(): T | undefined;
638
+ set(value: T): void;
639
+ validate(): ValidationResultType;
640
+ }
641
+ ```
642
+
643
+ ### ReadonlyFieldAccessorType
644
+
645
+ ```typescript
646
+ type ReadonlyFieldAccessorType<T> = {
647
+ readonly label: string;
648
+ readonly required: boolean;
649
+ readonly readOnly: boolean;
650
+ readonly defaultValue: unknown;
651
+ readonly meta: BaseFieldMetaType;
652
+ get(): T | undefined;
653
+ validate(): ValidationResultType;
654
+ };
655
+ ```
656
+
657
+ ---
658
+
659
+ ## Complete Example
660
+
661
+ ```typescript
662
+ import { AdminProduct } from "../bdo/admin/Product";
663
+ import type {
664
+ AdminProductEditableFieldType,
665
+ AdminProductFieldType,
666
+ } from "../bdo/admin/Product";
667
+
668
+ const product = new AdminProduct();
669
+
670
+ // ---- Field metadata ----
671
+ console.log(product.meta._id); // "BDO_Product"
672
+ console.log(product.Title.label); // "Product Title"
673
+ console.log(product.Title.required); // true
674
+
675
+ // ---- Get a single item ----
676
+ const item = await product.get("prod_abc123");
677
+ console.log(item._id); // "prod_abc123"
678
+ console.log(item.Title.get()); // "Wireless Headphones"
679
+ console.log(item.Price.get()); // 99.99
680
+
681
+ // ---- List items with filter ----
682
+ const items = await product.list({
683
+ Filter: {
684
+ Operator: "And",
685
+ Condition: [{
686
+ LHSField: product.Category.id,
687
+ Operator: "EQ",
688
+ RHSValue: "Electronics",
689
+ RHSType: "Constant",
690
+ }],
691
+ },
692
+ Sort: [{ [product.Price.id]: "ASC" }],
693
+ Page: 1,
694
+ PageSize: 20,
695
+ });
696
+
697
+ for (const item of items) {
698
+ console.log(item.Title.get(), item.Price.get());
699
+ }
700
+
701
+ // ---- Count ----
702
+ const total = await product.count();
703
+ console.log(`Total products: ${total}`);
704
+
705
+ // ---- Create ----
706
+ const newItem = await product.create({
707
+ Title: "New Product",
708
+ Price: 49.99,
709
+ Category: "Books",
710
+ });
711
+ console.log(newItem._id); // New record ID
712
+ console.log(newItem.Title.get()); // "New Product"
713
+
714
+ // ---- Update ----
715
+ const updateResult = await product.update("prod_abc123", {
716
+ Price: 79.99,
717
+ });
718
+ console.log(updateResult._id); // "prod_abc123"
719
+
720
+ // ---- Delete ----
721
+ const deleteResult = await product.delete("prod_abc123");
722
+ console.log(deleteResult.status); // "success"
723
+
724
+ // ---- Validate ----
725
+ const emptyItem = product.createItem();
726
+ emptyItem.Title.set("");
727
+ const validation = emptyItem.validate();
728
+ console.log(validation.valid); // false
729
+ console.log(validation.errors); // ["Product Title is required"]
730
+
731
+ // ---- SelectField options ----
732
+ const statusOptions = await product.Status.fetchOptions();
733
+ statusOptions.forEach((opt) => {
734
+ console.log(`${opt.value}: ${opt.label}`);
735
+ });
736
+
737
+ // ---- ReferenceField options ----
738
+ const suppliers = await product.SupplierInfo.fetchOptions();
739
+ suppliers.forEach((sup) => {
740
+ console.log(`${sup._id}: ${sup.SupplierName}`);
741
+ });
742
+ ```