@ram_28/kf-ai-sdk 2.0.19 → 2.0.20-beta.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.
- package/README.md +8 -16
- package/dist/{FileField-CZjS2uLh.js → FileField-BWrSHNRq.js} +3 -3
- package/dist/{FileField-DU4UWo_t.cjs → FileField-eDeuzln8.cjs} +1 -1
- package/dist/api.cjs +1 -1
- package/dist/api.mjs +1 -1
- package/dist/auth/authConfig.d.ts +1 -1
- package/dist/auth/types.d.ts +1 -1
- package/dist/auth/types.d.ts.map +1 -1
- package/dist/auth.cjs +1 -1
- package/dist/auth.mjs +1 -1
- package/dist/bdo/core/Item.d.ts +4 -0
- package/dist/bdo/core/Item.d.ts.map +1 -1
- package/dist/bdo/fields/ReferenceField.d.ts +1 -1
- package/dist/bdo/fields/ReferenceField.d.ts.map +1 -1
- package/dist/bdo/fields/SelectField.d.ts +1 -1
- package/dist/bdo/fields/SelectField.d.ts.map +1 -1
- package/dist/bdo/fields/UserField.d.ts +1 -1
- package/dist/bdo/fields/UserField.d.ts.map +1 -1
- package/dist/bdo.cjs +1 -1
- package/dist/bdo.mjs +62 -53
- package/dist/components/hooks/useActivityForm/types.d.ts +5 -4
- package/dist/components/hooks/useActivityForm/types.d.ts.map +1 -1
- package/dist/components/hooks/useActivityForm/useActivityForm.d.ts.map +1 -1
- package/dist/components/hooks/useActivityTable/types.d.ts +4 -5
- package/dist/components/hooks/useActivityTable/types.d.ts.map +1 -1
- package/dist/components/hooks/useActivityTable/useActivityTable.d.ts.map +1 -1
- package/dist/components/hooks/useBDOForm/createItemProxy.d.ts +3 -2
- package/dist/components/hooks/useBDOForm/createItemProxy.d.ts.map +1 -1
- package/dist/components/hooks/useBDOTable/types.d.ts +12 -20
- package/dist/components/hooks/useBDOTable/types.d.ts.map +1 -1
- package/dist/components/hooks/useBDOTable/useBDOTable.d.ts +2 -2
- package/dist/components/hooks/useBDOTable/useBDOTable.d.ts.map +1 -1
- package/dist/{constants-Cyi942Yr.js → constants-ConHc1oS.js} +5 -5
- package/dist/constants-QX2RX-wu.cjs +1 -0
- package/dist/filter.cjs +1 -1
- package/dist/filter.mjs +1 -1
- package/dist/form.cjs +1 -1
- package/dist/form.mjs +243 -226
- package/dist/table.cjs +1 -1
- package/dist/table.mjs +16 -15
- package/dist/table.types.d.ts +1 -1
- package/dist/table.types.d.ts.map +1 -1
- package/dist/types/constants.d.ts +1 -1
- package/dist/workflow/Activity.d.ts +5 -8
- package/dist/workflow/Activity.d.ts.map +1 -1
- package/dist/workflow.cjs +1 -1
- package/dist/workflow.mjs +476 -461
- package/docs/api.md +95 -0
- package/docs/bdo.md +224 -0
- package/docs/gaps.md +360 -0
- package/docs/useActivityForm.md +393 -0
- package/docs/useActivityTable.md +418 -0
- package/docs/useBDOForm.md +498 -0
- package/docs/useBDOTable.md +284 -0
- package/docs/useFilter.md +188 -0
- package/docs/workflow.md +560 -0
- package/package.json +14 -15
- package/sdk/auth/authConfig.ts +1 -1
- package/sdk/auth/types.ts +1 -1
- package/sdk/bdo/core/Item.ts +10 -1
- package/sdk/bdo/fields/ReferenceField.ts +1 -1
- package/sdk/bdo/fields/SelectField.ts +1 -1
- package/sdk/bdo/fields/UserField.ts +1 -1
- package/sdk/components/hooks/useActivityForm/types.ts +6 -4
- package/sdk/components/hooks/useActivityForm/useActivityForm.ts +73 -10
- package/sdk/components/hooks/useActivityTable/types.ts +5 -4
- package/sdk/components/hooks/useActivityTable/useActivityTable.ts +8 -10
- package/sdk/components/hooks/useBDOForm/createItemProxy.ts +58 -17
- package/sdk/components/hooks/useBDOTable/types.ts +10 -20
- package/sdk/components/hooks/useBDOTable/useBDOTable.ts +8 -12
- package/sdk/table.types.ts +0 -2
- package/sdk/types/constants.ts +1 -1
- package/sdk/workflow/Activity.ts +7 -39
- package/dist/constants-DEmYwKfC.cjs +0 -1
- package/docs/README.md +0 -57
- package/docs/bdo/README.md +0 -161
- package/docs/bdo/api_reference.md +0 -281
- package/docs/examples/bdo/create-product.md +0 -69
- package/docs/examples/bdo/edit-product-dialog.md +0 -95
- package/docs/examples/bdo/filtered-product-table.md +0 -100
- package/docs/examples/bdo/product-listing.md +0 -73
- package/docs/examples/bdo/supplier-dropdown.md +0 -60
- package/docs/examples/fields/complex-fields.md +0 -248
- package/docs/examples/fields/primitive-fields.md +0 -217
- package/docs/examples/workflow/approve-leave-request.md +0 -76
- package/docs/examples/workflow/filtered-activity-table.md +0 -101
- package/docs/examples/workflow/my-pending-requests.md +0 -90
- package/docs/examples/workflow/start-new-workflow.md +0 -47
- package/docs/examples/workflow/submit-leave-request.md +0 -72
- package/docs/examples/workflow/workflow-progress.md +0 -49
- package/docs/fields/README.md +0 -141
- package/docs/fields/api_reference.md +0 -134
- package/docs/useActivityForm/README.md +0 -244
- package/docs/useActivityForm/api_reference.md +0 -279
- package/docs/useActivityTable/README.md +0 -263
- package/docs/useActivityTable/api_reference.md +0 -294
- package/docs/useBDOForm/README.md +0 -175
- package/docs/useBDOForm/api_reference.md +0 -244
- package/docs/useBDOTable/README.md +0 -242
- package/docs/useBDOTable/api_reference.md +0 -253
- package/docs/useFilter/README.md +0 -323
- package/docs/useFilter/api_reference.md +0 -228
- package/docs/workflow/README.md +0 -158
- package/docs/workflow/api_reference.md +0 -161
- /package/docs/{useAuth/README.md → useAuth.md} +0 -0
package/docs/bdo/README.md
DELETED
|
@@ -1,161 +0,0 @@
|
|
|
1
|
-
# BDO (Business Data Object)
|
|
2
|
-
|
|
3
|
-
Type-safe, role-based data access layer. Each BDO class extends `BaseBdo<TEntity, TEditable, TReadonly>` and exposes CRUD methods filtered by role permissions.
|
|
4
|
-
|
|
5
|
-
## Imports
|
|
6
|
-
|
|
7
|
-
```typescript
|
|
8
|
-
// Page component — import the generated role-specific BDO class
|
|
9
|
-
import { AdminProduct } from "../bdo/admin/Product";
|
|
10
|
-
```
|
|
11
|
-
|
|
12
|
-
```typescript
|
|
13
|
-
// BDO class definition — used by the js_sdk generator
|
|
14
|
-
import { BaseBdo, StringField, NumberField, BooleanField, DateField, SelectField, ReferenceField } from "@ram_28/kf-ai-sdk/bdo";
|
|
15
|
-
import type { StringFieldType, NumberFieldType, BooleanFieldType, DateFieldType, SelectFieldType, ReferenceFieldType, SystemFieldsType } from "@ram_28/kf-ai-sdk/types";
|
|
16
|
-
import type { ListOptionsType } from "@ram_28/kf-ai-sdk/api/types";
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
## Common Mistakes (READ FIRST)
|
|
20
|
-
|
|
21
|
-
1. **`create()` returns `ItemType`, not `{ _id }`** — It returns a proxy-wrapped item with field accessors, not `CreateUpdateResponseType`. Use `item._id` to get the ID.
|
|
22
|
-
2. **Use `.get()` to read field values** — `item.Title` returns a field accessor object, not the value. Use `item.Title.get()`.
|
|
23
|
-
3. **Field names use `_name` not `name`** — System fields like `_created_by` return `{ _id, _name }`. Access the display name with `item._created_by.get()?._name`.
|
|
24
|
-
4. **Memoize BDO instances in React** — Wrap in `useMemo` to prevent re-creation on every render:
|
|
25
|
-
```typescript
|
|
26
|
-
const product = useMemo(() => new AdminProduct(), []);
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
## Quick Start
|
|
30
|
-
|
|
31
|
-
```typescript
|
|
32
|
-
const product = new AdminProduct();
|
|
33
|
-
|
|
34
|
-
// Create — returns ItemType (proxy with field accessors)
|
|
35
|
-
const item = await product.create({ Title: "Widget", Price: 29.99 });
|
|
36
|
-
item._id; // "abc123"
|
|
37
|
-
item.Title.get(); // "Widget"
|
|
38
|
-
item.Price.get(); // 29.99
|
|
39
|
-
|
|
40
|
-
// List
|
|
41
|
-
const items = await product.list({ Page: 1, PageSize: 10 });
|
|
42
|
-
items[0].Title.get();
|
|
43
|
-
|
|
44
|
-
// Get single item
|
|
45
|
-
const found = await product.get("abc123");
|
|
46
|
-
found.Title.get(); // "Widget"
|
|
47
|
-
|
|
48
|
-
// Update — returns { _id: string }
|
|
49
|
-
await product.update("abc123", { Price: 39.99 });
|
|
50
|
-
|
|
51
|
-
// Delete — returns { status: string }
|
|
52
|
-
await product.delete("abc123");
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
## Usage Guide
|
|
56
|
-
|
|
57
|
-
### CRUD Operations
|
|
58
|
-
|
|
59
|
-
```typescript
|
|
60
|
-
const product = new AdminProduct();
|
|
61
|
-
|
|
62
|
-
// Create — returns ItemType with field accessors
|
|
63
|
-
const item = await product.create({
|
|
64
|
-
Title: "Widget",
|
|
65
|
-
Price: 29.99,
|
|
66
|
-
Category: "Electronics",
|
|
67
|
-
});
|
|
68
|
-
item._id; // direct string access
|
|
69
|
-
|
|
70
|
-
// Get single item
|
|
71
|
-
const item = await product.get("abc123");
|
|
72
|
-
|
|
73
|
-
// Update — returns { _id: string }
|
|
74
|
-
const { _id } = await product.update("abc123", { Price: 39.99 });
|
|
75
|
-
|
|
76
|
-
// Delete — returns { status: string }
|
|
77
|
-
const { status } = await product.delete("abc123");
|
|
78
|
-
|
|
79
|
-
// Count
|
|
80
|
-
const total = await product.count();
|
|
81
|
-
const filtered = await product.count({
|
|
82
|
-
Filter: {
|
|
83
|
-
Operator: "And",
|
|
84
|
-
Condition: [
|
|
85
|
-
{ Operator: "eq", LHSField: "Category", RHSValue: "Electronics" },
|
|
86
|
-
],
|
|
87
|
-
},
|
|
88
|
-
});
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
### ItemType Field Accessors
|
|
92
|
-
|
|
93
|
-
Every `get()`, `list()`, and `create()` call returns `ItemType` — a proxy with typed field accessors.
|
|
94
|
-
|
|
95
|
-
```typescript
|
|
96
|
-
const item = await product.get("abc123");
|
|
97
|
-
|
|
98
|
-
// Read values
|
|
99
|
-
item._id; // string (direct, not an accessor)
|
|
100
|
-
item.Title.get(); // string | undefined
|
|
101
|
-
item.Price.getOrDefault(0); // number (never undefined)
|
|
102
|
-
|
|
103
|
-
// Write values (editable fields only)
|
|
104
|
-
item.Title.set("New Title");
|
|
105
|
-
|
|
106
|
-
// Field metadata
|
|
107
|
-
item.Title.label; // "Product Title"
|
|
108
|
-
item.Title.required; // true
|
|
109
|
-
item.Title.readOnly; // false
|
|
110
|
-
item.Title.defaultValue; // undefined
|
|
111
|
-
item.Title.meta; // raw backend field meta
|
|
112
|
-
|
|
113
|
-
// Validation
|
|
114
|
-
item.Title.validate(); // { valid: boolean, errors: string[] }
|
|
115
|
-
item.validate(); // validates all fields, returns { valid, errors }
|
|
116
|
-
|
|
117
|
-
// Serialize
|
|
118
|
-
item.toJSON(); // { Title: "New Title", Price: 29.99, ... }
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
### List with Filter, Sort, and Pagination
|
|
122
|
-
|
|
123
|
-
```typescript
|
|
124
|
-
const items = await product.list({
|
|
125
|
-
Filter: {
|
|
126
|
-
Operator: "And",
|
|
127
|
-
Condition: [
|
|
128
|
-
{ Operator: "eq", LHSField: "Category", RHSValue: "Electronics" },
|
|
129
|
-
{ Operator: "gte", LHSField: "Price", RHSValue: 10 },
|
|
130
|
-
],
|
|
131
|
-
},
|
|
132
|
-
Sort: [{ Price: "DESC" }],
|
|
133
|
-
Page: 1,
|
|
134
|
-
PageSize: 20,
|
|
135
|
-
});
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
### Metric (Aggregation)
|
|
139
|
-
|
|
140
|
-
```typescript
|
|
141
|
-
const result = await product.metric({
|
|
142
|
-
GroupBy: ["Category"],
|
|
143
|
-
Metric: [{ Field: "Price", Type: "Avg" }],
|
|
144
|
-
});
|
|
145
|
-
// result.Data = [{ Category: "Electronics", Price: 299.5 }, ...]
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
### Pivot (Cross-Tabulation)
|
|
149
|
-
|
|
150
|
-
```typescript
|
|
151
|
-
const result = await product.pivot({
|
|
152
|
-
Row: ["Category"],
|
|
153
|
-
Column: ["IsActive"],
|
|
154
|
-
Metric: [{ Field: "_id", Type: "Count" }],
|
|
155
|
-
});
|
|
156
|
-
// result.Data = { RowHeader: [...], ColumnHeader: [...], Value: [[...]] }
|
|
157
|
-
```
|
|
158
|
-
|
|
159
|
-
## Further Reading
|
|
160
|
-
|
|
161
|
-
- [API Reference](./api_reference.md) — full method signatures, parameter types, and return types
|
|
@@ -1,281 +0,0 @@
|
|
|
1
|
-
```typescript
|
|
2
|
-
import { BaseBdo, StringField, NumberField, BooleanField, DateField, SelectField, ReferenceField } from "@ram_28/kf-ai-sdk/bdo";
|
|
3
|
-
import type {
|
|
4
|
-
ItemType,
|
|
5
|
-
EditableFieldAccessorType,
|
|
6
|
-
ReadonlyFieldAccessorType,
|
|
7
|
-
ValidationResultType,
|
|
8
|
-
BdoMetaType,
|
|
9
|
-
} from "@ram_28/kf-ai-sdk/bdo/types";
|
|
10
|
-
import type {
|
|
11
|
-
ListOptionsType,
|
|
12
|
-
FilterType,
|
|
13
|
-
ConditionGroupType,
|
|
14
|
-
ConditionType,
|
|
15
|
-
SortType,
|
|
16
|
-
CreateUpdateResponseType,
|
|
17
|
-
DeleteResponseType,
|
|
18
|
-
MetricOptionsType,
|
|
19
|
-
MetricResponseType,
|
|
20
|
-
PivotOptionsType,
|
|
21
|
-
PivotResponseType,
|
|
22
|
-
} from "@ram_28/kf-ai-sdk/api/types";
|
|
23
|
-
import type {
|
|
24
|
-
StringFieldType,
|
|
25
|
-
NumberFieldType,
|
|
26
|
-
BooleanFieldType,
|
|
27
|
-
DateFieldType,
|
|
28
|
-
DateTimeFieldType,
|
|
29
|
-
TextFieldType,
|
|
30
|
-
SelectFieldType,
|
|
31
|
-
ReferenceFieldType,
|
|
32
|
-
UserFieldType,
|
|
33
|
-
FileFieldType,
|
|
34
|
-
ImageFieldType,
|
|
35
|
-
ArrayFieldType,
|
|
36
|
-
ObjectFieldType,
|
|
37
|
-
SystemFieldsType,
|
|
38
|
-
} from "@ram_28/kf-ai-sdk/types";
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
## Methods
|
|
42
|
-
|
|
43
|
-
All methods are `protected` on `BaseBdo`. Subclasses expose them as `public` per role.
|
|
44
|
-
|
|
45
|
-
| Method | Params | Returns |
|
|
46
|
-
|--------|--------|---------|
|
|
47
|
-
| `get(id)` | `id: string` | `Promise<ItemType<TEditable, TReadonly>>` |
|
|
48
|
-
| `list(options?)` | `options?: ListOptionsType` | `Promise<ItemType<TEditable, TReadonly>[]>` |
|
|
49
|
-
| `count(options?)` | `options?: ListOptionsType` | `Promise<number>` |
|
|
50
|
-
| `create(data)` | `data: Partial<TEditable>` | `Promise<ItemType<TEditable, TReadonly>>` |
|
|
51
|
-
| `update(id, data)` | `id: string, data: Partial<TEditable>` | `Promise<CreateUpdateResponseType>` |
|
|
52
|
-
| `delete(id)` | `id: string` | `Promise<DeleteResponseType>` |
|
|
53
|
-
| `metric(options)` | `options: Omit<MetricOptionsType, "Type">` | `Promise<MetricResponseType>` |
|
|
54
|
-
| `pivot(options)` | `options: Omit<PivotOptionsType, "Type">` | `Promise<PivotResponseType>` |
|
|
55
|
-
|
|
56
|
-
## Types
|
|
57
|
-
|
|
58
|
-
### ItemType\<TEditable, TReadonly\>
|
|
59
|
-
|
|
60
|
-
Proxy-wrapped record returned by `get()`, `list()`, and `create()`. Provides typed field accessors for each field.
|
|
61
|
-
|
|
62
|
-
```typescript
|
|
63
|
-
type ItemType<TEditable, TReadonly> = {
|
|
64
|
-
readonly _id: string; // direct string access
|
|
65
|
-
|
|
66
|
-
// Editable fields → EditableFieldAccessorType<T>
|
|
67
|
-
// Readonly fields → ReadonlyFieldAccessorType<T>
|
|
68
|
-
|
|
69
|
-
validate(): ValidationResultType; // validates all fields
|
|
70
|
-
toJSON(): Partial<TEditable & TReadonly>;
|
|
71
|
-
};
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
### EditableFieldAccessorType\<T\>
|
|
75
|
-
|
|
76
|
-
Accessor for fields the current role can write.
|
|
77
|
-
|
|
78
|
-
```typescript
|
|
79
|
-
interface EditableFieldAccessorType<T> {
|
|
80
|
-
get(): T | undefined;
|
|
81
|
-
getOrDefault(fallback: T): T;
|
|
82
|
-
set(value: T): void;
|
|
83
|
-
validate(): ValidationResultType;
|
|
84
|
-
readonly label: string;
|
|
85
|
-
readonly required: boolean;
|
|
86
|
-
readonly readOnly: false;
|
|
87
|
-
readonly defaultValue: unknown;
|
|
88
|
-
readonly meta: BaseFieldMetaType;
|
|
89
|
-
}
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
### ReadonlyFieldAccessorType\<T\>
|
|
93
|
-
|
|
94
|
-
Accessor for fields the current role can only read. Same as editable but no `set()`.
|
|
95
|
-
|
|
96
|
-
```typescript
|
|
97
|
-
interface ReadonlyFieldAccessorType<T> {
|
|
98
|
-
get(): T | undefined;
|
|
99
|
-
getOrDefault(fallback: T): T;
|
|
100
|
-
validate(): ValidationResultType;
|
|
101
|
-
readonly label: string;
|
|
102
|
-
readonly required: boolean;
|
|
103
|
-
readonly readOnly: true;
|
|
104
|
-
readonly defaultValue: unknown;
|
|
105
|
-
readonly meta: BaseFieldMetaType;
|
|
106
|
-
}
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
### ValidationResultType
|
|
110
|
-
|
|
111
|
-
```typescript
|
|
112
|
-
interface ValidationResultType {
|
|
113
|
-
valid: boolean;
|
|
114
|
-
errors: string[];
|
|
115
|
-
}
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
### ListOptionsType
|
|
119
|
-
|
|
120
|
-
```typescript
|
|
121
|
-
interface ListOptionsType {
|
|
122
|
-
Filter?: FilterType;
|
|
123
|
-
Sort?: SortType;
|
|
124
|
-
Page?: number; // 1-indexed
|
|
125
|
-
PageSize?: number;
|
|
126
|
-
Search?: string;
|
|
127
|
-
Field?: string[]; // specific fields to return
|
|
128
|
-
}
|
|
129
|
-
```
|
|
130
|
-
|
|
131
|
-
### FilterType / ConditionGroupType / ConditionType
|
|
132
|
-
|
|
133
|
-
```typescript
|
|
134
|
-
// Root filter — alias for ConditionGroupType
|
|
135
|
-
type FilterType = ConditionGroupType;
|
|
136
|
-
|
|
137
|
-
interface ConditionGroupType {
|
|
138
|
-
Operator: "And" | "Or" | "Not";
|
|
139
|
-
Condition: Array<ConditionType | ConditionGroupType>;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
interface ConditionType {
|
|
143
|
-
Operator: string; // "eq", "neq", "gt", "gte", "lt", "lte", "contains", "startswith", etc.
|
|
144
|
-
LHSField: string; // field name
|
|
145
|
-
RHSValue: any; // comparison value
|
|
146
|
-
RHSType?: string; // defaults to "Constant"
|
|
147
|
-
}
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
### SortType
|
|
151
|
-
|
|
152
|
-
```typescript
|
|
153
|
-
type SortType = Record<string, "ASC" | "DESC">[];
|
|
154
|
-
// Example: [{ "Price": "DESC" }, { "Title": "ASC" }]
|
|
155
|
-
```
|
|
156
|
-
|
|
157
|
-
### CreateUpdateResponseType
|
|
158
|
-
|
|
159
|
-
```typescript
|
|
160
|
-
interface CreateUpdateResponseType {
|
|
161
|
-
_id: string;
|
|
162
|
-
}
|
|
163
|
-
```
|
|
164
|
-
|
|
165
|
-
### DeleteResponseType
|
|
166
|
-
|
|
167
|
-
```typescript
|
|
168
|
-
interface DeleteResponseType {
|
|
169
|
-
status: string;
|
|
170
|
-
}
|
|
171
|
-
```
|
|
172
|
-
|
|
173
|
-
### MetricOptionsType
|
|
174
|
-
|
|
175
|
-
Omit `Type` when calling `bdo.metric()` — it is added automatically.
|
|
176
|
-
|
|
177
|
-
```typescript
|
|
178
|
-
interface MetricOptionsType {
|
|
179
|
-
Type: "Metric"; // omit when calling bdo.metric()
|
|
180
|
-
GroupBy: string[];
|
|
181
|
-
Metric: MetricFieldType[];
|
|
182
|
-
Filter?: FilterType;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
interface MetricFieldType {
|
|
186
|
-
Field: string;
|
|
187
|
-
Type: string; // "Count" | "Sum" | "Avg" | "Max" | "Min"
|
|
188
|
-
}
|
|
189
|
-
```
|
|
190
|
-
|
|
191
|
-
### MetricResponseType
|
|
192
|
-
|
|
193
|
-
```typescript
|
|
194
|
-
interface MetricResponseType {
|
|
195
|
-
Data: Record<string, any>[];
|
|
196
|
-
}
|
|
197
|
-
```
|
|
198
|
-
|
|
199
|
-
### PivotOptionsType
|
|
200
|
-
|
|
201
|
-
Omit `Type` when calling `bdo.pivot()` — it is added automatically.
|
|
202
|
-
|
|
203
|
-
```typescript
|
|
204
|
-
interface PivotOptionsType {
|
|
205
|
-
Type: "Pivot"; // omit when calling bdo.pivot()
|
|
206
|
-
Row: string[];
|
|
207
|
-
Column: string[];
|
|
208
|
-
Metric: MetricFieldType[];
|
|
209
|
-
Filter?: FilterType;
|
|
210
|
-
}
|
|
211
|
-
```
|
|
212
|
-
|
|
213
|
-
### PivotResponseType
|
|
214
|
-
|
|
215
|
-
```typescript
|
|
216
|
-
interface PivotResponseType {
|
|
217
|
-
Data: {
|
|
218
|
-
RowHeader: PivotHeaderItemType[];
|
|
219
|
-
ColumnHeader: PivotHeaderItemType[];
|
|
220
|
-
Value: (number | string | null)[][];
|
|
221
|
-
};
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
interface PivotHeaderItemType {
|
|
225
|
-
Key: string;
|
|
226
|
-
Children?: PivotHeaderItemType[] | null;
|
|
227
|
-
}
|
|
228
|
-
```
|
|
229
|
-
|
|
230
|
-
### SystemFieldsType
|
|
231
|
-
|
|
232
|
-
Seven system-managed fields inherited from `BaseBdo`. Never redeclare in subclasses.
|
|
233
|
-
|
|
234
|
-
```typescript
|
|
235
|
-
type SystemFieldsType = {
|
|
236
|
-
_id: StringFieldType;
|
|
237
|
-
_created_at: DateTimeFieldType;
|
|
238
|
-
_modified_at: DateTimeFieldType;
|
|
239
|
-
_created_by: UserFieldType;
|
|
240
|
-
_modified_by: UserFieldType;
|
|
241
|
-
_version: StringFieldType;
|
|
242
|
-
_m_version: StringFieldType;
|
|
243
|
-
};
|
|
244
|
-
```
|
|
245
|
-
|
|
246
|
-
### Field Value Types
|
|
247
|
-
|
|
248
|
-
| Type | Resolves To |
|
|
249
|
-
|------|-------------|
|
|
250
|
-
| `StringFieldType` | `string` |
|
|
251
|
-
| `TextFieldType` | `string` |
|
|
252
|
-
| `NumberFieldType` | `number` |
|
|
253
|
-
| `BooleanFieldType` | `boolean` |
|
|
254
|
-
| `DateFieldType` | `"YYYY-MM-DD"` |
|
|
255
|
-
| `DateTimeFieldType` | `"YYYY-MM-DDThh:mm:ssZ"` |
|
|
256
|
-
| `SelectFieldType<T>` | `T` |
|
|
257
|
-
| `ReferenceFieldType<T>` | `T` |
|
|
258
|
-
| `UserFieldType` | `{ _id: string; _name: string }` |
|
|
259
|
-
| `ImageFieldType` | `FileType \| null` |
|
|
260
|
-
| `FileFieldType` | `FileType[]` |
|
|
261
|
-
| `ArrayFieldType<T>` | `T[]` |
|
|
262
|
-
| `ObjectFieldType<T>` | `T` |
|
|
263
|
-
|
|
264
|
-
### Generated Type Patterns
|
|
265
|
-
|
|
266
|
-
The js_sdk generator creates these types per entity:
|
|
267
|
-
|
|
268
|
-
```typescript
|
|
269
|
-
// entities/Product.ts
|
|
270
|
-
export type ProductType = {
|
|
271
|
-
ProductId: StringFieldType;
|
|
272
|
-
Title: StringFieldType;
|
|
273
|
-
Price: NumberFieldType;
|
|
274
|
-
// ... business fields
|
|
275
|
-
} & SystemFieldsType;
|
|
276
|
-
|
|
277
|
-
// admin/Product.ts
|
|
278
|
-
type AdminProductEditableFieldType = Omit<ProductType, keyof SystemFieldsType>;
|
|
279
|
-
type AdminProductReadonlyFieldType = Record<string, never>;
|
|
280
|
-
// or Pick<ProductType, "Field1" | "Field2"> for limited access
|
|
281
|
-
```
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
# Create Product
|
|
2
|
-
|
|
3
|
-
> Create a new product using `useBDOForm` with validation, select fields, and submit handling.
|
|
4
|
-
|
|
5
|
-
```tsx
|
|
6
|
-
import { useMemo } from "react";
|
|
7
|
-
import { useBDOForm } from "@ram_28/kf-ai-sdk/form";
|
|
8
|
-
import type { UseBDOFormReturnType } from "@ram_28/kf-ai-sdk/form/types";
|
|
9
|
-
import { BuyerProduct } from "@/bdo/buyer/Product";
|
|
10
|
-
import type { BuyerProductEntityType } from "@/bdo/buyer/Product";
|
|
11
|
-
import type { FieldErrors } from "react-hook-form";
|
|
12
|
-
|
|
13
|
-
export default function CreateProductForm() {
|
|
14
|
-
const product = useMemo(() => new BuyerProduct(), []);
|
|
15
|
-
|
|
16
|
-
const { register, handleSubmit, errors, isLoading, isSubmitting, watch, setValue }: UseBDOFormReturnType<BuyerProduct> =
|
|
17
|
-
useBDOForm({ bdo: product, defaultValues: { Title: "", Price: 0 } });
|
|
18
|
-
|
|
19
|
-
if (isLoading) return <p>Loading...</p>;
|
|
20
|
-
|
|
21
|
-
const onSuccess = (data: { _id: string }) => console.log("Created:", data._id);
|
|
22
|
-
const onError = (err: FieldErrors<BuyerProductEntityType> | Error) => {
|
|
23
|
-
if (err instanceof Error) console.error(err.message);
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
return (
|
|
27
|
-
<form onSubmit={handleSubmit(onSuccess, onError)}>
|
|
28
|
-
{/* Text input with register() */}
|
|
29
|
-
<label>{product.Title.label} {product.Title.required && <span>*</span>}</label>
|
|
30
|
-
<input {...register(product.Title.id)} />
|
|
31
|
-
{errors.Title && <p>{errors.Title.message}</p>}
|
|
32
|
-
|
|
33
|
-
<label>{product.Description.label}</label>
|
|
34
|
-
<textarea {...register(product.Description.id)} rows={3} />
|
|
35
|
-
{errors.Description && <p>{errors.Description.message}</p>}
|
|
36
|
-
|
|
37
|
-
{/* Number input with register() */}
|
|
38
|
-
<label>{product.Price.label} {product.Price.required && <span>*</span>}</label>
|
|
39
|
-
<input type="number" step="0.01" {...register(product.Price.id)} />
|
|
40
|
-
{errors.Price && <p>{errors.Price.message}</p>}
|
|
41
|
-
|
|
42
|
-
{/* Select field — watch/setValue, not register */}
|
|
43
|
-
<label>{product.Category.label} {product.Category.required && <span>*</span>}</label>
|
|
44
|
-
<select
|
|
45
|
-
value={watch(product.Category.id) ?? ""}
|
|
46
|
-
onChange={(e) => setValue(product.Category.id, e.target.value)}
|
|
47
|
-
>
|
|
48
|
-
<option value="">Select category</option>
|
|
49
|
-
{product.Category.options.map((opt) => (
|
|
50
|
-
<option key={opt.value} value={opt.value}>{opt.label}</option>
|
|
51
|
-
))}
|
|
52
|
-
</select>
|
|
53
|
-
{errors.Category && <p>{errors.Category.message}</p>}
|
|
54
|
-
|
|
55
|
-
<button type="submit" disabled={isSubmitting}>
|
|
56
|
-
{isSubmitting ? "Saving..." : "Add Product"}
|
|
57
|
-
</button>
|
|
58
|
-
</form>
|
|
59
|
-
);
|
|
60
|
-
}
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
## Key Patterns
|
|
64
|
-
|
|
65
|
-
- **Create mode** -- no `recordId` passed to `useBDOForm`; a draft is allocated on mount
|
|
66
|
-
- **`register()`** -- for text and number inputs that fire native change events
|
|
67
|
-
- **`watch()` + `setValue()`** -- for select fields and other custom components
|
|
68
|
-
- **`handleSubmit(onSuccess, onError)`** -- validates, filters to editable fields, calls the API; never call `bdo.create()` manually
|
|
69
|
-
- **Validation errors** -- `errors.FieldName.message` shows constraint violations automatically
|
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
# Edit Product Dialog
|
|
2
|
-
|
|
3
|
-
> Click a table row to open an edit form in a dialog, save, and refetch the table.
|
|
4
|
-
|
|
5
|
-
```tsx
|
|
6
|
-
import { useState, useMemo } from "react";
|
|
7
|
-
import { useBDOTable } from "@ram_28/kf-ai-sdk/table";
|
|
8
|
-
import type { UseBDOTableReturnType } from "@ram_28/kf-ai-sdk/table/types";
|
|
9
|
-
import { useBDOForm } from "@ram_28/kf-ai-sdk/form";
|
|
10
|
-
import type { UseBDOFormReturnType } from "@ram_28/kf-ai-sdk/form/types";
|
|
11
|
-
import { BuyerProduct } from "@/bdo/buyer/Product";
|
|
12
|
-
import type { BuyerProductEntityType } from "@/bdo/buyer/Product";
|
|
13
|
-
import type { FieldErrors } from "react-hook-form";
|
|
14
|
-
|
|
15
|
-
export default function ProductPage() {
|
|
16
|
-
const [showForm, setShowForm] = useState(false);
|
|
17
|
-
const [selectedId, setSelectedId] = useState<string | null>(null);
|
|
18
|
-
|
|
19
|
-
const product = useMemo(() => new BuyerProduct(), []);
|
|
20
|
-
|
|
21
|
-
// ── Table ────────────────────────────────────────────────────
|
|
22
|
-
const table: UseBDOTableReturnType<BuyerProduct> = useBDOTable({
|
|
23
|
-
bdo: product,
|
|
24
|
-
initialState: { sort: [{ Title: "ASC" }], pagination: { pageNo: 1, pageSize: 10 } },
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
// ── Form (create when selectedId is null, edit when string) ──
|
|
28
|
-
const { register, handleSubmit, errors, isLoading: formLoading, isSubmitting, watch, setValue, isDirty }: UseBDOFormReturnType<BuyerProduct> =
|
|
29
|
-
useBDOForm({ bdo: product, recordId: selectedId ?? undefined });
|
|
30
|
-
|
|
31
|
-
const handleCreate = () => { setSelectedId(null); setShowForm(true); };
|
|
32
|
-
const handleEdit = (id: string) => { setSelectedId(id); setShowForm(true); };
|
|
33
|
-
const onSuccess = () => { setShowForm(false); setSelectedId(null); table.refetch(); };
|
|
34
|
-
const onError = (err: FieldErrors<BuyerProductEntityType> | Error) => {
|
|
35
|
-
if (err instanceof Error) console.error(err.message);
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
if (table.isLoading) return <p>Loading...</p>;
|
|
39
|
-
|
|
40
|
-
return (
|
|
41
|
-
<div>
|
|
42
|
-
<button onClick={handleCreate}>Add Product</button>
|
|
43
|
-
|
|
44
|
-
<table>
|
|
45
|
-
<thead>
|
|
46
|
-
<tr>
|
|
47
|
-
<th>{product.Title.label}</th>
|
|
48
|
-
<th>{product.Price.label}</th>
|
|
49
|
-
</tr>
|
|
50
|
-
</thead>
|
|
51
|
-
<tbody>
|
|
52
|
-
{table.rows.map((row) => (
|
|
53
|
-
<tr key={row._id} onClick={() => handleEdit(row._id)} style={{ cursor: "pointer" }}>
|
|
54
|
-
<td>{row.Title.get()}</td>
|
|
55
|
-
<td>${row.Price.get()?.toFixed(2)}</td>
|
|
56
|
-
</tr>
|
|
57
|
-
))}
|
|
58
|
-
</tbody>
|
|
59
|
-
</table>
|
|
60
|
-
|
|
61
|
-
{/* Dialog form */}
|
|
62
|
-
{showForm && (
|
|
63
|
-
<dialog open>
|
|
64
|
-
<h2>{selectedId ? "Edit Product" : "Add Product"}</h2>
|
|
65
|
-
{formLoading ? (
|
|
66
|
-
<p>Loading form...</p>
|
|
67
|
-
) : (
|
|
68
|
-
<form onSubmit={handleSubmit(onSuccess, onError)}>
|
|
69
|
-
<label>{product.Title.label}</label>
|
|
70
|
-
<input {...register(product.Title.id)} />
|
|
71
|
-
{errors.Title && <p>{errors.Title.message}</p>}
|
|
72
|
-
|
|
73
|
-
<label>{product.Price.label}</label>
|
|
74
|
-
<input type="number" step="0.01" {...register(product.Price.id)} />
|
|
75
|
-
{errors.Price && <p>{errors.Price.message}</p>}
|
|
76
|
-
|
|
77
|
-
<button type="button" onClick={() => setShowForm(false)}>Cancel</button>
|
|
78
|
-
<button type="submit" disabled={isSubmitting || (!!selectedId && !isDirty)}>
|
|
79
|
-
{isSubmitting ? "Saving..." : selectedId ? "Save Changes" : "Add Product"}
|
|
80
|
-
</button>
|
|
81
|
-
</form>
|
|
82
|
-
)}
|
|
83
|
-
</dialog>
|
|
84
|
-
)}
|
|
85
|
-
</div>
|
|
86
|
-
);
|
|
87
|
-
}
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
## Key Patterns
|
|
91
|
-
|
|
92
|
-
- **Shared BDO instance** -- `useMemo(() => new BuyerProduct(), [])` is passed to both `useBDOTable` and `useBDOForm`
|
|
93
|
-
- **Create vs edit mode** -- `selectedId` is `null` for create (no `recordId`), or a string for edit
|
|
94
|
-
- **`table.refetch()` after save** -- called in `onSuccess` to refresh the table data
|
|
95
|
-
- **`isDirty` guard** -- disables the submit button in edit mode when no changes have been made
|