@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.
- package/LICENSE +21 -0
- package/README.md +840 -0
- package/dist/api/client.d.ts +78 -0
- package/dist/api/client.d.ts.map +1 -0
- package/dist/api/datetime.d.ts +21 -0
- package/dist/api/datetime.d.ts.map +1 -0
- package/dist/api/index.d.ts +7 -0
- package/dist/api/index.d.ts.map +1 -0
- package/dist/api/metadata.d.ts +75 -0
- package/dist/api/metadata.d.ts.map +1 -0
- package/dist/components/hooks/index.d.ts +8 -0
- package/dist/components/hooks/index.d.ts.map +1 -0
- package/dist/components/hooks/useFilter/index.d.ts +5 -0
- package/dist/components/hooks/useFilter/index.d.ts.map +1 -0
- package/dist/components/hooks/useFilter/payloadBuilder.utils.d.ts +33 -0
- package/dist/components/hooks/useFilter/payloadBuilder.utils.d.ts.map +1 -0
- package/dist/components/hooks/useFilter/types.d.ts +137 -0
- package/dist/components/hooks/useFilter/types.d.ts.map +1 -0
- package/dist/components/hooks/useFilter/useFilter.d.ts +3 -0
- package/dist/components/hooks/useFilter/useFilter.d.ts.map +1 -0
- package/dist/components/hooks/useFilter/validation.utils.d.ts +38 -0
- package/dist/components/hooks/useFilter/validation.utils.d.ts.map +1 -0
- package/dist/components/hooks/useForm/apiClient.d.ts +71 -0
- package/dist/components/hooks/useForm/apiClient.d.ts.map +1 -0
- package/dist/components/hooks/useForm/expressionValidator.utils.d.ts +28 -0
- package/dist/components/hooks/useForm/expressionValidator.utils.d.ts.map +1 -0
- package/dist/components/hooks/useForm/index.d.ts +6 -0
- package/dist/components/hooks/useForm/index.d.ts.map +1 -0
- package/dist/components/hooks/useForm/optimizedExpressionValidator.utils.d.ts +88 -0
- package/dist/components/hooks/useForm/optimizedExpressionValidator.utils.d.ts.map +1 -0
- package/dist/components/hooks/useForm/ruleClassifier.utils.d.ts +28 -0
- package/dist/components/hooks/useForm/ruleClassifier.utils.d.ts.map +1 -0
- package/dist/components/hooks/useForm/schemaParser.utils.d.ts +29 -0
- package/dist/components/hooks/useForm/schemaParser.utils.d.ts.map +1 -0
- package/dist/components/hooks/useForm/types.d.ts +412 -0
- package/dist/components/hooks/useForm/types.d.ts.map +1 -0
- package/dist/components/hooks/useForm/useForm.d.ts +3 -0
- package/dist/components/hooks/useForm/useForm.d.ts.map +1 -0
- package/dist/components/hooks/useKanban/apiClient.d.ts +99 -0
- package/dist/components/hooks/useKanban/apiClient.d.ts.map +1 -0
- package/dist/components/hooks/useKanban/context.d.ts +4 -0
- package/dist/components/hooks/useKanban/context.d.ts.map +1 -0
- package/dist/components/hooks/useKanban/dragDropManager.d.ts +27 -0
- package/dist/components/hooks/useKanban/dragDropManager.d.ts.map +1 -0
- package/dist/components/hooks/useKanban/index.d.ts +6 -0
- package/dist/components/hooks/useKanban/index.d.ts.map +1 -0
- package/dist/components/hooks/useKanban/types.d.ts +438 -0
- package/dist/components/hooks/useKanban/types.d.ts.map +1 -0
- package/dist/components/hooks/useKanban/useKanban.d.ts +3 -0
- package/dist/components/hooks/useKanban/useKanban.d.ts.map +1 -0
- package/dist/components/hooks/useKanban/useKanbanSimple.d.ts +62 -0
- package/dist/components/hooks/useKanban/useKanbanSimple.d.ts.map +1 -0
- package/dist/components/hooks/useTable/index.d.ts +3 -0
- package/dist/components/hooks/useTable/index.d.ts.map +1 -0
- package/dist/components/hooks/useTable/types.d.ts +107 -0
- package/dist/components/hooks/useTable/types.d.ts.map +1 -0
- package/dist/components/hooks/useTable/useTable.d.ts +8 -0
- package/dist/components/hooks/useTable/useTable.d.ts.map +1 -0
- package/dist/components/index.d.ts +3 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/ui/index.d.ts +2 -0
- package/dist/components/ui/index.d.ts.map +1 -0
- package/dist/components/ui/kanban/Kanban.d.ts +12 -0
- package/dist/components/ui/kanban/Kanban.d.ts.map +1 -0
- package/dist/components/ui/kanban/index.d.ts +2 -0
- package/dist/components/ui/kanban/index.d.ts.map +1 -0
- package/dist/index.cjs +45 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.mjs +6522 -0
- package/dist/types/base-fields.d.ts +182 -0
- package/dist/types/base-fields.d.ts.map +1 -0
- package/dist/types/common.d.ts +238 -0
- package/dist/types/common.d.ts.map +1 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/utils/cn.d.ts +7 -0
- package/dist/utils/cn.d.ts.map +1 -0
- package/dist/utils/formatting.d.ts +52 -0
- package/dist/utils/formatting.d.ts.map +1 -0
- package/dist/utils/index.d.ts +3 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/package.json +98 -0
- package/sdk/api/client.ts +447 -0
- package/sdk/api/datetime.ts +33 -0
- package/sdk/api/index.ts +61 -0
- package/sdk/api/metadata.ts +148 -0
- package/sdk/components/hooks/index.ts +34 -0
- package/sdk/components/hooks/useFilter/index.ts +37 -0
- package/sdk/components/hooks/useFilter/payloadBuilder.utils.ts +298 -0
- package/sdk/components/hooks/useFilter/types.ts +158 -0
- package/sdk/components/hooks/useFilter/useFilter.llm.txt +497 -0
- package/sdk/components/hooks/useFilter/useFilter.ts +494 -0
- package/sdk/components/hooks/useFilter/validation.utils.ts +401 -0
- package/sdk/components/hooks/useForm/apiClient.ts +441 -0
- package/sdk/components/hooks/useForm/expressionValidator.utils.ts +444 -0
- package/sdk/components/hooks/useForm/index.ts +64 -0
- package/sdk/components/hooks/useForm/optimizedExpressionValidator.utils.ts +482 -0
- package/sdk/components/hooks/useForm/ruleClassifier.utils.ts +424 -0
- package/sdk/components/hooks/useForm/schemaParser.utils.ts +519 -0
- package/sdk/components/hooks/useForm/types.ts +630 -0
- package/sdk/components/hooks/useForm/useForm.llm.txt +340 -0
- package/sdk/components/hooks/useForm/useForm.ts +821 -0
- package/sdk/components/hooks/useKanban/apiClient.ts +494 -0
- package/sdk/components/hooks/useKanban/context.ts +14 -0
- package/sdk/components/hooks/useKanban/dragDropManager.ts +529 -0
- package/sdk/components/hooks/useKanban/index.ts +63 -0
- package/sdk/components/hooks/useKanban/types.ts +606 -0
- package/sdk/components/hooks/useKanban/useKanban.llm.txt +482 -0
- package/sdk/components/hooks/useKanban/useKanban.ts +725 -0
- package/sdk/components/hooks/useKanban/useKanbanSimple.ts +389 -0
- package/sdk/components/hooks/useTable/index.ts +5 -0
- package/sdk/components/hooks/useTable/types.ts +154 -0
- package/sdk/components/hooks/useTable/useTable.llm.txt +344 -0
- package/sdk/components/hooks/useTable/useTable.ts +413 -0
- package/sdk/components/index.ts +15 -0
- package/sdk/components/ui/index.ts +2 -0
- package/sdk/components/ui/kanban/Kanban.tsx +134 -0
- package/sdk/components/ui/kanban/index.ts +11 -0
- package/sdk/index.ts +13 -0
- package/sdk/types/base-fields.ts +221 -0
- package/sdk/types/common.ts +306 -0
- package/sdk/types/index.ts +5 -0
- package/sdk/utils/cn.ts +10 -0
- package/sdk/utils/formatting.ts +212 -0
- package/sdk/utils/index.ts +5 -0
package/README.md
ADDED
|
@@ -0,0 +1,840 @@
|
|
|
1
|
+
# KF AI SDK - Enhanced Business Object Framework
|
|
2
|
+
|
|
3
|
+
A comprehensive TypeScript SDK for building enterprise applications with sophisticated business rules, role-based access control, and optimized client-side validation. Features complete BDO (Business Data Object) support with rule classification, field permissions, and expression evaluation.
|
|
4
|
+
|
|
5
|
+
## 🚀 Latest Enhancements
|
|
6
|
+
|
|
7
|
+
### ✅ **Complete Rule System (NEW)**
|
|
8
|
+
- **Rule Classification**: Validation (client-side), Computation (server-side), Business Logic (server-side)
|
|
9
|
+
- **Smart Execution**: Automatic determination of client vs server rule execution
|
|
10
|
+
- **Expression Caching**: LRU cache with dependency tracking for optimized performance
|
|
11
|
+
- **BDO Schema Support**: Full compatibility with Business Data Object schemas
|
|
12
|
+
|
|
13
|
+
### ✅ **Role-Based Field Permissions (NEW)**
|
|
14
|
+
- **Field-Level Control**: Editable, readable, and hidden field permissions per role
|
|
15
|
+
- **Compile-Time Safety**: TypeScript enforcement of permission boundaries
|
|
16
|
+
- **Dynamic UI**: Automatic form field disable/hide based on permissions
|
|
17
|
+
|
|
18
|
+
### ✅ **Optimized API Integration (NEW)**
|
|
19
|
+
- **POST-Based Operations**: Correct implementation per BDO specification
|
|
20
|
+
- **Enhanced Count API**: Efficient counting with same payload structure as list
|
|
21
|
+
- **Advanced Filtering**: Complex filter conditions with logical operators
|
|
22
|
+
- **Type-Safe Responses**: Full TypeScript coverage for all operations
|
|
23
|
+
|
|
24
|
+
### ✅ **Amazon Product Master Implementation (NEW)**
|
|
25
|
+
- **Complete BDO Example**: Full implementation of Amazon Product Master schema
|
|
26
|
+
- **Business Rules**: Auto-calculations, validation, and permission enforcement
|
|
27
|
+
- **Role-Based Views**: Admin, Seller, Buyer, InventoryManager, WarehouseStaff access levels
|
|
28
|
+
- **Real-World Example**: Production-ready e-commerce product management
|
|
29
|
+
|
|
30
|
+
## 📚 Documentation
|
|
31
|
+
|
|
32
|
+
- **[Implementation Guide](./IMPLEMENTATION_GUIDE.md)** - Comprehensive setup and usage guide
|
|
33
|
+
- **[Quick Reference](./QUICK_REFERENCE.md)** - Developer cheat sheet and API reference
|
|
34
|
+
- **[Examples](./examples/)** - Real-world usage examples including Amazon Product demo
|
|
35
|
+
|
|
36
|
+
## Architecture Overview
|
|
37
|
+
|
|
38
|
+
The KF AI SDK is built on a clear separation between reusable SDK core and user-configurable application logic:
|
|
39
|
+
|
|
40
|
+
### 🔧 SDK Core (`sdk/`)
|
|
41
|
+
|
|
42
|
+
**Fixed, Reusable Components**
|
|
43
|
+
|
|
44
|
+
- **Types**: 11 Backend BO field types (IdField, StringField, CurrencyField, etc.)
|
|
45
|
+
- **API Client**: Runtime CRUD operations with structured filtering and sorting
|
|
46
|
+
- **Utilities**: Validation and formatting helpers
|
|
47
|
+
- **Components**: React hooks for forms and tables (Phase 2)
|
|
48
|
+
|
|
49
|
+
### 🏗️ App Layer (`app/`)
|
|
50
|
+
|
|
51
|
+
**User-Configurable Business Logic**
|
|
52
|
+
|
|
53
|
+
- **Roles**: User-defined role system (Admin, Manager, User, etc.)
|
|
54
|
+
- **Sources**: Business object definitions (Product, Order, etc.)
|
|
55
|
+
- **Role-based Access**: Type-safe field visibility per role
|
|
56
|
+
- **AI-readable Contracts**: Single source of truth for code generation
|
|
57
|
+
|
|
58
|
+
### 📁 Project Structure
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
kf-ai-sdk/
|
|
62
|
+
├── sdk/ # Fixed SDK core
|
|
63
|
+
│ ├── types/ # Field types and common interfaces
|
|
64
|
+
│ ├── api/ # API client and utilities
|
|
65
|
+
│ ├── utils/ # Validation and formatting
|
|
66
|
+
│ └── index.ts # SDK exports
|
|
67
|
+
├── app/ # User-configurable layer
|
|
68
|
+
│ ├── types/roles.ts # Role definitions
|
|
69
|
+
│ ├── sources/ # Business objects
|
|
70
|
+
│ └── index.ts # App exports
|
|
71
|
+
├── config/ # Development configuration
|
|
72
|
+
└── examples/ # Usage examples
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Quick Start
|
|
76
|
+
|
|
77
|
+
### Usage Example
|
|
78
|
+
|
|
79
|
+
```tsx
|
|
80
|
+
// 1. Import SDK core utilities
|
|
81
|
+
import { api, formatCurrency, isValidCurrencyField } from "./sdk";
|
|
82
|
+
|
|
83
|
+
// 2. Import app-specific business logic
|
|
84
|
+
import { Order, Roles, AdminOrder } from "./app";
|
|
85
|
+
|
|
86
|
+
// 3. Use together for type-safe operations
|
|
87
|
+
const order = new Order(Roles.Admin);
|
|
88
|
+
const orderData = await order.list();
|
|
89
|
+
|
|
90
|
+
// SDK utilities work with app types
|
|
91
|
+
const isValid = isValidCurrencyField(orderData.Data[0].totalAmount);
|
|
92
|
+
const formatted = formatCurrency(orderData.Data[0].totalAmount);
|
|
93
|
+
|
|
94
|
+
function AdminOrderManagement() {
|
|
95
|
+
// Type-safe order client with role-based access
|
|
96
|
+
const order = new Order(Roles.Admin);
|
|
97
|
+
|
|
98
|
+
// Table with automatic type inference
|
|
99
|
+
const table = useTable<AdminOrder>({
|
|
100
|
+
source: "orders",
|
|
101
|
+
enableSorting: true,
|
|
102
|
+
enablePagination: true,
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
// Form with backend-driven validation
|
|
106
|
+
const form = useForm<AdminOrder>({
|
|
107
|
+
source: "order-validation",
|
|
108
|
+
operation: "create",
|
|
109
|
+
onSuccess: () => table.refetch(),
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
return (
|
|
113
|
+
<div>
|
|
114
|
+
{/* Create Form */}
|
|
115
|
+
<form onSubmit={form.handleSubmit()}>
|
|
116
|
+
<input {...form.register("customerId")} placeholder="Customer ID" />
|
|
117
|
+
<input {...form.register("totalAmount")} placeholder="Total Amount" type="number" />
|
|
118
|
+
<input {...form.register("profitMargin")} placeholder="Profit Margin" type="number" />{" "}
|
|
119
|
+
{/* Admin can see profit margin */}
|
|
120
|
+
<button type="submit">Create Order</button>
|
|
121
|
+
</form>
|
|
122
|
+
|
|
123
|
+
{/* Orders Table */}
|
|
124
|
+
<table>
|
|
125
|
+
<thead>
|
|
126
|
+
<tr>
|
|
127
|
+
<th>ID</th>
|
|
128
|
+
<th>Customer</th>
|
|
129
|
+
<th>Amount</th>
|
|
130
|
+
<th>Profit Margin</th> {/* Admin can see profit margin */}
|
|
131
|
+
<th>Actions</th>
|
|
132
|
+
</tr>
|
|
133
|
+
</thead>
|
|
134
|
+
<tbody>
|
|
135
|
+
{table.rows.map((order: AdminOrder) => (
|
|
136
|
+
<tr key={order._id}>
|
|
137
|
+
<td>{order._id}</td>
|
|
138
|
+
<td>{order.customerId}</td>
|
|
139
|
+
<td>${order.totalAmount}</td>
|
|
140
|
+
<td>{order.profitMargin}%</td>{" "}
|
|
141
|
+
{/* TypeScript knows this exists for Admin */}
|
|
142
|
+
<td>
|
|
143
|
+
<button onClick={() => order.delete(order._id)}>Delete</button>
|
|
144
|
+
</td>
|
|
145
|
+
</tr>
|
|
146
|
+
))}
|
|
147
|
+
</tbody>
|
|
148
|
+
</table>
|
|
149
|
+
</div>
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Role-Based Access Control
|
|
155
|
+
|
|
156
|
+
```tsx
|
|
157
|
+
// User gets limited access to the same data
|
|
158
|
+
import { Order, Roles, UserOrder } from "@ram_28/kf-ai-sdk";
|
|
159
|
+
|
|
160
|
+
function UserOrderList() {
|
|
161
|
+
const order = new Order(Roles.User);
|
|
162
|
+
|
|
163
|
+
const table = useTable<UserOrder>({
|
|
164
|
+
source: "orders",
|
|
165
|
+
enableSorting: true,
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
return (
|
|
169
|
+
<table>
|
|
170
|
+
<thead>
|
|
171
|
+
<tr>
|
|
172
|
+
<th>ID</th>
|
|
173
|
+
<th>Customer</th>
|
|
174
|
+
<th>Amount</th>
|
|
175
|
+
{/* <th>Profit Margin</th> */} {/* User cannot see profit margin */}
|
|
176
|
+
</tr>
|
|
177
|
+
</thead>
|
|
178
|
+
<tbody>
|
|
179
|
+
{table.rows.map((order: UserOrder) => (
|
|
180
|
+
<tr key={order._id}>
|
|
181
|
+
<td>{order._id}</td>
|
|
182
|
+
<td>{order.customerId}</td>
|
|
183
|
+
<td>${order.totalAmount}</td>
|
|
184
|
+
{/* <td>{order.profitMargin}%</td> */}{" "}
|
|
185
|
+
{/* ❌ TypeScript Error: Property doesn't exist */}
|
|
186
|
+
</tr>
|
|
187
|
+
))}
|
|
188
|
+
</tbody>
|
|
189
|
+
</table>
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### Runtime API Operations
|
|
195
|
+
|
|
196
|
+
```tsx
|
|
197
|
+
import { api } from "./sdk";
|
|
198
|
+
|
|
199
|
+
// Runtime CRUD operations
|
|
200
|
+
async function orderOperations() {
|
|
201
|
+
// Get single order by ID
|
|
202
|
+
const order = await api("order").get("ORDER_123");
|
|
203
|
+
|
|
204
|
+
// Create new order (with optional custom ID)
|
|
205
|
+
const createResponse = await api("order").create({
|
|
206
|
+
_id: "ORDER_456", // Optional custom ID
|
|
207
|
+
customerId: "CUST_001",
|
|
208
|
+
totalAmount: 299.99,
|
|
209
|
+
status: "pending",
|
|
210
|
+
});
|
|
211
|
+
console.log(createResponse._id); // "ORDER_456"
|
|
212
|
+
|
|
213
|
+
// Update order (partial updates supported)
|
|
214
|
+
const updateResponse = await api("order").update("ORDER_123", {
|
|
215
|
+
status: "completed",
|
|
216
|
+
totalAmount: 325.50,
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
// Delete order
|
|
220
|
+
const deleteResponse = await api("order").delete("ORDER_123");
|
|
221
|
+
console.log(deleteResponse.status); // "success"
|
|
222
|
+
|
|
223
|
+
// List orders with structured filtering and sorting
|
|
224
|
+
const ordersList = await api("order").list({
|
|
225
|
+
Filter: {
|
|
226
|
+
Operator: "AND",
|
|
227
|
+
Condition: [
|
|
228
|
+
{
|
|
229
|
+
Operator: "EQ",
|
|
230
|
+
LHSField: "status",
|
|
231
|
+
RHSValue: "pending"
|
|
232
|
+
},
|
|
233
|
+
{
|
|
234
|
+
Operator: "GTE",
|
|
235
|
+
LHSField: "totalAmount",
|
|
236
|
+
RHSValue: 100
|
|
237
|
+
}
|
|
238
|
+
]
|
|
239
|
+
},
|
|
240
|
+
Sort: [
|
|
241
|
+
{ Field: "_created_at", Order: "DESC" },
|
|
242
|
+
{ Field: "totalAmount", Order: "ASC" }
|
|
243
|
+
],
|
|
244
|
+
Page: 1,
|
|
245
|
+
PageSize: 50
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
## Advanced Filtering and Sorting Examples
|
|
251
|
+
|
|
252
|
+
The KF AI SDK supports comprehensive filtering and sorting through the Runtime API. Here are detailed examples using both Order and Product models:
|
|
253
|
+
|
|
254
|
+
### Basic Filtering Examples
|
|
255
|
+
|
|
256
|
+
```tsx
|
|
257
|
+
import { Order, Product, Roles } from "./app";
|
|
258
|
+
|
|
259
|
+
// Simple equality filter
|
|
260
|
+
const completedOrders = await new Order(Roles.Admin).list({
|
|
261
|
+
Filter: {
|
|
262
|
+
Operator: "AND",
|
|
263
|
+
Condition: [
|
|
264
|
+
{
|
|
265
|
+
Operator: "EQ",
|
|
266
|
+
LHSField: "status",
|
|
267
|
+
RHSValue: "completed"
|
|
268
|
+
}
|
|
269
|
+
]
|
|
270
|
+
}
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
// Numeric range filter
|
|
274
|
+
const highValueOrders = await new Order(Roles.Admin).list({
|
|
275
|
+
Filter: {
|
|
276
|
+
Operator: "AND",
|
|
277
|
+
Condition: [
|
|
278
|
+
{
|
|
279
|
+
Operator: "GTE",
|
|
280
|
+
LHSField: "totalAmount",
|
|
281
|
+
RHSValue: 500
|
|
282
|
+
}
|
|
283
|
+
]
|
|
284
|
+
}
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
// String contains filter
|
|
288
|
+
const electronicsProducts = await new Product(Roles.Admin).list({
|
|
289
|
+
Filter: {
|
|
290
|
+
Operator: "AND",
|
|
291
|
+
Condition: [
|
|
292
|
+
{
|
|
293
|
+
Operator: "Contains",
|
|
294
|
+
LHSField: "description",
|
|
295
|
+
RHSValue: "electronic"
|
|
296
|
+
}
|
|
297
|
+
]
|
|
298
|
+
}
|
|
299
|
+
});
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
### Complex Multi-Condition Filters
|
|
303
|
+
|
|
304
|
+
```tsx
|
|
305
|
+
// AND conditions - all must be true
|
|
306
|
+
const premiumCompletedOrders = await new Order(Roles.Admin).list({
|
|
307
|
+
Filter: {
|
|
308
|
+
Operator: "AND",
|
|
309
|
+
Condition: [
|
|
310
|
+
{
|
|
311
|
+
Operator: "EQ",
|
|
312
|
+
LHSField: "status",
|
|
313
|
+
RHSValue: "completed"
|
|
314
|
+
},
|
|
315
|
+
{
|
|
316
|
+
Operator: "GTE",
|
|
317
|
+
LHSField: "totalAmount",
|
|
318
|
+
RHSValue: 1000
|
|
319
|
+
},
|
|
320
|
+
{
|
|
321
|
+
Operator: "GTE",
|
|
322
|
+
LHSField: "profitMargin",
|
|
323
|
+
RHSValue: 20
|
|
324
|
+
}
|
|
325
|
+
]
|
|
326
|
+
}
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
// OR conditions - any can be true
|
|
330
|
+
const urgentOrders = await new Order(Roles.Admin).list({
|
|
331
|
+
Filter: {
|
|
332
|
+
Operator: "OR",
|
|
333
|
+
Condition: [
|
|
334
|
+
{
|
|
335
|
+
Operator: "EQ",
|
|
336
|
+
LHSField: "status",
|
|
337
|
+
RHSValue: "pending"
|
|
338
|
+
},
|
|
339
|
+
{
|
|
340
|
+
Operator: "EQ",
|
|
341
|
+
LHSField: "status",
|
|
342
|
+
RHSValue: "processing"
|
|
343
|
+
}
|
|
344
|
+
]
|
|
345
|
+
}
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
// Nested AND/OR conditions
|
|
349
|
+
const complexProductFilter = await new Product(Roles.Admin).list({
|
|
350
|
+
Filter: {
|
|
351
|
+
Operator: "AND",
|
|
352
|
+
Condition: [
|
|
353
|
+
{
|
|
354
|
+
Operator: "EQ",
|
|
355
|
+
LHSField: "inStock",
|
|
356
|
+
RHSValue: true
|
|
357
|
+
},
|
|
358
|
+
{
|
|
359
|
+
Operator: "OR",
|
|
360
|
+
Condition: [
|
|
361
|
+
{
|
|
362
|
+
Operator: "EQ",
|
|
363
|
+
LHSField: "category",
|
|
364
|
+
RHSValue: "electronics"
|
|
365
|
+
},
|
|
366
|
+
{
|
|
367
|
+
Operator: "EQ",
|
|
368
|
+
LHSField: "category",
|
|
369
|
+
RHSValue: "clothing"
|
|
370
|
+
}
|
|
371
|
+
]
|
|
372
|
+
},
|
|
373
|
+
{
|
|
374
|
+
Operator: "Between",
|
|
375
|
+
LHSField: "price",
|
|
376
|
+
RHSValue: [50, 500]
|
|
377
|
+
}
|
|
378
|
+
]
|
|
379
|
+
}
|
|
380
|
+
});
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
### Advanced Filter Operators
|
|
384
|
+
|
|
385
|
+
```tsx
|
|
386
|
+
// Range queries
|
|
387
|
+
const midRangeProducts = await new Product(Roles.Admin).list({
|
|
388
|
+
Filter: {
|
|
389
|
+
Operator: "AND",
|
|
390
|
+
Condition: [
|
|
391
|
+
{
|
|
392
|
+
Operator: "Between",
|
|
393
|
+
LHSField: "price",
|
|
394
|
+
RHSValue: [100, 1000]
|
|
395
|
+
}
|
|
396
|
+
]
|
|
397
|
+
}
|
|
398
|
+
});
|
|
399
|
+
|
|
400
|
+
// List membership
|
|
401
|
+
const specificCategories = await new Product(Roles.Admin).list({
|
|
402
|
+
Filter: {
|
|
403
|
+
Operator: "AND",
|
|
404
|
+
Condition: [
|
|
405
|
+
{
|
|
406
|
+
Operator: "IN",
|
|
407
|
+
LHSField: "category",
|
|
408
|
+
RHSValue: ["electronics", "books", "sports"]
|
|
409
|
+
}
|
|
410
|
+
]
|
|
411
|
+
}
|
|
412
|
+
});
|
|
413
|
+
|
|
414
|
+
// Exclusion filters
|
|
415
|
+
const nonCancelledOrders = await new Order(Roles.Admin).list({
|
|
416
|
+
Filter: {
|
|
417
|
+
Operator: "AND",
|
|
418
|
+
Condition: [
|
|
419
|
+
{
|
|
420
|
+
Operator: "NE",
|
|
421
|
+
LHSField: "status",
|
|
422
|
+
RHSValue: "cancelled"
|
|
423
|
+
}
|
|
424
|
+
]
|
|
425
|
+
}
|
|
426
|
+
});
|
|
427
|
+
|
|
428
|
+
// Empty/Non-empty checks
|
|
429
|
+
const ordersWithNotes = await new Order(Roles.Admin).list({
|
|
430
|
+
Filter: {
|
|
431
|
+
Operator: "AND",
|
|
432
|
+
Condition: [
|
|
433
|
+
{
|
|
434
|
+
Operator: "NotEmpty",
|
|
435
|
+
LHSField: "internalNotes"
|
|
436
|
+
}
|
|
437
|
+
]
|
|
438
|
+
}
|
|
439
|
+
});
|
|
440
|
+
|
|
441
|
+
// String length validation
|
|
442
|
+
const detailedProducts = await new Product(Roles.Admin).list({
|
|
443
|
+
Filter: {
|
|
444
|
+
Operator: "AND",
|
|
445
|
+
Condition: [
|
|
446
|
+
{
|
|
447
|
+
Operator: "MinLength",
|
|
448
|
+
LHSField: "description",
|
|
449
|
+
RHSValue: 50
|
|
450
|
+
}
|
|
451
|
+
]
|
|
452
|
+
}
|
|
453
|
+
});
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
### Comprehensive Sorting Examples
|
|
457
|
+
|
|
458
|
+
```tsx
|
|
459
|
+
// Single field sorting
|
|
460
|
+
const ordersByDate = await new Order(Roles.Admin).list({
|
|
461
|
+
Sort: [
|
|
462
|
+
{ Field: "_created_at", Order: "DESC" }
|
|
463
|
+
]
|
|
464
|
+
});
|
|
465
|
+
|
|
466
|
+
// Multi-field sorting
|
|
467
|
+
const productsCatalog = await new Product(Roles.Admin).list({
|
|
468
|
+
Sort: [
|
|
469
|
+
{ Field: "category", Order: "ASC" }, // First by category
|
|
470
|
+
{ Field: "price", Order: "DESC" }, // Then by price (high to low)
|
|
471
|
+
{ Field: "name", Order: "ASC" } // Finally by name
|
|
472
|
+
]
|
|
473
|
+
});
|
|
474
|
+
|
|
475
|
+
// Sorting with filtering
|
|
476
|
+
const topSellingProducts = await new Product(Roles.Admin).list({
|
|
477
|
+
Filter: {
|
|
478
|
+
Operator: "AND",
|
|
479
|
+
Condition: [
|
|
480
|
+
{
|
|
481
|
+
Operator: "EQ",
|
|
482
|
+
LHSField: "inStock",
|
|
483
|
+
RHSValue: true
|
|
484
|
+
},
|
|
485
|
+
{
|
|
486
|
+
Operator: "GTE",
|
|
487
|
+
LHSField: "price",
|
|
488
|
+
RHSValue: 100
|
|
489
|
+
}
|
|
490
|
+
]
|
|
491
|
+
},
|
|
492
|
+
Sort: [
|
|
493
|
+
{ Field: "margin", Order: "DESC" },
|
|
494
|
+
{ Field: "price", Order: "ASC" }
|
|
495
|
+
]
|
|
496
|
+
});
|
|
497
|
+
```
|
|
498
|
+
|
|
499
|
+
### Pagination with Filtering and Sorting
|
|
500
|
+
|
|
501
|
+
```tsx
|
|
502
|
+
// Complete query with all features
|
|
503
|
+
const paginatedResults = await new Order(Roles.Admin).list({
|
|
504
|
+
// Complex filtering
|
|
505
|
+
Filter: {
|
|
506
|
+
Operator: "AND",
|
|
507
|
+
Condition: [
|
|
508
|
+
{
|
|
509
|
+
Operator: "GTE",
|
|
510
|
+
LHSField: "totalAmount",
|
|
511
|
+
RHSValue: 200
|
|
512
|
+
},
|
|
513
|
+
{
|
|
514
|
+
Operator: "OR",
|
|
515
|
+
Condition: [
|
|
516
|
+
{
|
|
517
|
+
Operator: "EQ",
|
|
518
|
+
LHSField: "status",
|
|
519
|
+
RHSValue: "completed"
|
|
520
|
+
},
|
|
521
|
+
{
|
|
522
|
+
Operator: "EQ",
|
|
523
|
+
LHSField: "status",
|
|
524
|
+
RHSValue: "pending"
|
|
525
|
+
}
|
|
526
|
+
]
|
|
527
|
+
}
|
|
528
|
+
]
|
|
529
|
+
},
|
|
530
|
+
// Multi-field sorting
|
|
531
|
+
Sort: [
|
|
532
|
+
{ Field: "totalAmount", Order: "DESC" },
|
|
533
|
+
{ Field: "_created_at", Order: "DESC" }
|
|
534
|
+
],
|
|
535
|
+
// Pagination
|
|
536
|
+
Page: 1,
|
|
537
|
+
PageSize: 25,
|
|
538
|
+
// Specific fields only (optional)
|
|
539
|
+
Field: ["_id", "customerId", "totalAmount", "status", "_created_at"]
|
|
540
|
+
});
|
|
541
|
+
|
|
542
|
+
// Process results
|
|
543
|
+
console.log(`Found ${paginatedResults.Data.length} orders`);
|
|
544
|
+
paginatedResults.Data.forEach(order => {
|
|
545
|
+
console.log(`Order ${order._id}: $${order.totalAmount} - ${order.status}`);
|
|
546
|
+
});
|
|
547
|
+
```
|
|
548
|
+
|
|
549
|
+
### Role-Based Query Examples
|
|
550
|
+
|
|
551
|
+
```tsx
|
|
552
|
+
// Admin can see all fields and use sensitive filters
|
|
553
|
+
const adminProductAnalysis = await new Product(Roles.Admin).list({
|
|
554
|
+
Filter: {
|
|
555
|
+
Operator: "AND",
|
|
556
|
+
Condition: [
|
|
557
|
+
{
|
|
558
|
+
Operator: "GTE",
|
|
559
|
+
LHSField: "margin", // Admin-only field
|
|
560
|
+
RHSValue: 25
|
|
561
|
+
},
|
|
562
|
+
{
|
|
563
|
+
Operator: "Contains",
|
|
564
|
+
LHSField: "supplier", // Admin-only field
|
|
565
|
+
RHSValue: "Premium"
|
|
566
|
+
}
|
|
567
|
+
]
|
|
568
|
+
},
|
|
569
|
+
Sort: [
|
|
570
|
+
{ Field: "margin", Order: "DESC" },
|
|
571
|
+
{ Field: "cost", Order: "ASC" } // Admin-only field
|
|
572
|
+
]
|
|
573
|
+
});
|
|
574
|
+
|
|
575
|
+
// User sees limited data and can only filter on public fields
|
|
576
|
+
const userProducts = await new Product(Roles.User).list({
|
|
577
|
+
Filter: {
|
|
578
|
+
Operator: "AND",
|
|
579
|
+
Condition: [
|
|
580
|
+
{
|
|
581
|
+
Operator: "EQ",
|
|
582
|
+
LHSField: "category", // Public field
|
|
583
|
+
RHSValue: "electronics"
|
|
584
|
+
},
|
|
585
|
+
{
|
|
586
|
+
Operator: "EQ",
|
|
587
|
+
LHSField: "inStock", // Public field
|
|
588
|
+
RHSValue: true
|
|
589
|
+
}
|
|
590
|
+
]
|
|
591
|
+
},
|
|
592
|
+
Sort: [
|
|
593
|
+
{ Field: "price", Order: "ASC" }, // Public field
|
|
594
|
+
{ Field: "name", Order: "ASC" } // Public field
|
|
595
|
+
]
|
|
596
|
+
});
|
|
597
|
+
|
|
598
|
+
// Note: User cannot filter by margin, cost, or supplier - those fields don't exist in UserProduct type
|
|
599
|
+
```
|
|
600
|
+
|
|
601
|
+
### Real-World Query Patterns
|
|
602
|
+
|
|
603
|
+
```tsx
|
|
604
|
+
// E-commerce product search
|
|
605
|
+
async function searchProducts(searchTerm: string, category?: string, maxPrice?: number) {
|
|
606
|
+
const conditions = [
|
|
607
|
+
{
|
|
608
|
+
Operator: "EQ" as const,
|
|
609
|
+
LHSField: "inStock",
|
|
610
|
+
RHSValue: true
|
|
611
|
+
}
|
|
612
|
+
];
|
|
613
|
+
|
|
614
|
+
if (searchTerm) {
|
|
615
|
+
conditions.push({
|
|
616
|
+
Operator: "Contains" as const,
|
|
617
|
+
LHSField: "name",
|
|
618
|
+
RHSValue: searchTerm
|
|
619
|
+
});
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
if (category) {
|
|
623
|
+
conditions.push({
|
|
624
|
+
Operator: "EQ" as const,
|
|
625
|
+
LHSField: "category",
|
|
626
|
+
RHSValue: category
|
|
627
|
+
});
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
if (maxPrice) {
|
|
631
|
+
conditions.push({
|
|
632
|
+
Operator: "LTE" as const,
|
|
633
|
+
LHSField: "price",
|
|
634
|
+
RHSValue: maxPrice
|
|
635
|
+
});
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
return new Product(Roles.User).list({
|
|
639
|
+
Filter: {
|
|
640
|
+
Operator: "AND",
|
|
641
|
+
Condition: conditions
|
|
642
|
+
},
|
|
643
|
+
Sort: [
|
|
644
|
+
{ Field: "name", Order: "ASC" }
|
|
645
|
+
],
|
|
646
|
+
PageSize: 20
|
|
647
|
+
});
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
// Order dashboard with filters
|
|
651
|
+
async function getOrderDashboard(dateRange: { start: string, end: string }, minAmount?: number) {
|
|
652
|
+
const conditions = [
|
|
653
|
+
{
|
|
654
|
+
Operator: "Between" as const,
|
|
655
|
+
LHSField: "_created_at",
|
|
656
|
+
RHSValue: [dateRange.start, dateRange.end]
|
|
657
|
+
}
|
|
658
|
+
];
|
|
659
|
+
|
|
660
|
+
if (minAmount) {
|
|
661
|
+
conditions.push({
|
|
662
|
+
Operator: "GTE" as const,
|
|
663
|
+
LHSField: "totalAmount",
|
|
664
|
+
RHSValue: minAmount
|
|
665
|
+
});
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
return new Order(Roles.Admin).list({
|
|
669
|
+
Filter: {
|
|
670
|
+
Operator: "AND",
|
|
671
|
+
Condition: conditions
|
|
672
|
+
},
|
|
673
|
+
Sort: [
|
|
674
|
+
{ Field: "totalAmount", Order: "DESC" },
|
|
675
|
+
{ Field: "_created_at", Order: "DESC" }
|
|
676
|
+
],
|
|
677
|
+
PageSize: 50
|
|
678
|
+
});
|
|
679
|
+
}
|
|
680
|
+
```
|
|
681
|
+
|
|
682
|
+
## Documentation
|
|
683
|
+
|
|
684
|
+
## Development Setup
|
|
685
|
+
|
|
686
|
+
### Prerequisites
|
|
687
|
+
- Node.js 18+
|
|
688
|
+
- npm or yarn
|
|
689
|
+
|
|
690
|
+
### Installation
|
|
691
|
+
```bash
|
|
692
|
+
# Clone or download the SDK template
|
|
693
|
+
git clone kf-ai-sdk my-project
|
|
694
|
+
cd my-project
|
|
695
|
+
|
|
696
|
+
# Install dependencies
|
|
697
|
+
npm install
|
|
698
|
+
|
|
699
|
+
# Start development server
|
|
700
|
+
npm run dev
|
|
701
|
+
```
|
|
702
|
+
|
|
703
|
+
### Development Commands
|
|
704
|
+
```bash
|
|
705
|
+
npm run dev # Start development server
|
|
706
|
+
npm run build # Build for production
|
|
707
|
+
npm run typecheck # Run TypeScript checks
|
|
708
|
+
npm run lint # Run ESLint
|
|
709
|
+
npm run format # Format code with Prettier
|
|
710
|
+
npm run test # Run tests
|
|
711
|
+
```
|
|
712
|
+
|
|
713
|
+
### Configuration
|
|
714
|
+
The SDK uses configuration files in the `config/` directory:
|
|
715
|
+
- `tsconfig.json` - TypeScript configuration with path mapping
|
|
716
|
+
- `vite.config.js` - Build and development server config
|
|
717
|
+
- `eslint.config.js` - Code linting rules
|
|
718
|
+
- `prettier.config.js` - Code formatting rules
|
|
719
|
+
|
|
720
|
+
### Layer Documentation
|
|
721
|
+
|
|
722
|
+
- **[SDK Core](docs/sdk-core.md)** - Field types, API client, and utilities
|
|
723
|
+
- **[App Layer](docs/app-layer.md)** - Roles and business object creation
|
|
724
|
+
- **[Examples](docs/examples.md)** - Usage patterns and best practices
|
|
725
|
+
|
|
726
|
+
### Migration Guide
|
|
727
|
+
|
|
728
|
+
- **[Migration Guide](MIGRATION.md)** - Upgrading from the previous structure
|
|
729
|
+
|
|
730
|
+
## Features
|
|
731
|
+
|
|
732
|
+
### SDK Core (`sdk/`)
|
|
733
|
+
|
|
734
|
+
- ✅ **Field Type System** - 11 Backend BO field types with semantic meaning
|
|
735
|
+
- ✅ **Runtime API Client** - Full CRUD operations with structured filtering
|
|
736
|
+
- ✅ **Datetime Handling** - Automatic encoding/decoding of API formats
|
|
737
|
+
- ✅ **Validation Utilities** - Runtime type checking and field validation
|
|
738
|
+
- ✅ **Formatting Helpers** - Display formatting for all field types
|
|
739
|
+
- ✅ **TypeScript Support** - Full type safety across all operations
|
|
740
|
+
|
|
741
|
+
### App Layer (`app/`)
|
|
742
|
+
|
|
743
|
+
- ✅ **Role-Based Access Control** - Compile-time enforcement of field visibility
|
|
744
|
+
- ✅ **AI Code Generation** - Single source of truth for AI-readable contracts
|
|
745
|
+
- ✅ **Dynamic Business Objects** - User-configurable source definitions
|
|
746
|
+
- ✅ **Custom Role System** - User-defined role hierarchies
|
|
747
|
+
- ✅ **Type Safety** - TypeScript validation of all generated code
|
|
748
|
+
- ✅ **Single File Per Source** - All logic for a data model in one place
|
|
749
|
+
|
|
750
|
+
### Development Experience
|
|
751
|
+
|
|
752
|
+
- ✅ **Modern Build Tools** - Vite, TypeScript, ESLint, Prettier
|
|
753
|
+
- ✅ **Path Mapping** - Clean imports with `@sdk/` and `@app/` aliases
|
|
754
|
+
- ✅ **Hot Reload** - Fast development with instant feedback
|
|
755
|
+
- ✅ **Type Checking** - Comprehensive TypeScript validation
|
|
756
|
+
- ✅ **Code Quality** - Automated linting and formatting
|
|
757
|
+
|
|
758
|
+
## Key Benefits
|
|
759
|
+
|
|
760
|
+
### For AI Code Generation
|
|
761
|
+
|
|
762
|
+
- **Single Source of Truth**: App layer provides all type definitions in one place
|
|
763
|
+
- **Role Awareness**: AI generates code that respects user permissions
|
|
764
|
+
- **Type Safety**: Any TypeScript error indicates incorrect AI generation
|
|
765
|
+
- **Self-Documenting**: Type definitions serve as API documentation
|
|
766
|
+
|
|
767
|
+
### For Developers
|
|
768
|
+
|
|
769
|
+
- **Three-Layer Architecture**: Clear separation of concerns
|
|
770
|
+
- **Role-Based Security**: Compile-time enforcement of data access
|
|
771
|
+
- **Modern React**: Hooks, React Query, and TypeScript throughout
|
|
772
|
+
- **Extensible**: Easy to add new data sources and roles
|
|
773
|
+
|
|
774
|
+
### For Applications
|
|
775
|
+
|
|
776
|
+
- **Performance**: React Query caching and background updates
|
|
777
|
+
- **Reliability**: Type-safe operations prevent runtime errors
|
|
778
|
+
- **Scalability**: Consistent patterns across all data operations
|
|
779
|
+
- **Maintainability**: Single file per data model, clear structure
|
|
780
|
+
|
|
781
|
+
## Example: AI-Generated Admin Page
|
|
782
|
+
|
|
783
|
+
When AI generates an admin page for "Order Management", it reads the App layer and produces:
|
|
784
|
+
|
|
785
|
+
```tsx
|
|
786
|
+
import { Order, Roles, AdminOrder } from "@ram_28/kf-ai-sdk";
|
|
787
|
+
import { useTable, useForm } from "@ram_28/kf-ai-sdk";
|
|
788
|
+
|
|
789
|
+
// AI generates type-safe code based on role
|
|
790
|
+
function AdminOrderManagement() {
|
|
791
|
+
const order = new Order(Roles.Admin); // Type-safe role
|
|
792
|
+
|
|
793
|
+
const table = useTable<AdminOrder>({
|
|
794
|
+
source: "orders",
|
|
795
|
+
enableSorting: true,
|
|
796
|
+
});
|
|
797
|
+
|
|
798
|
+
return (
|
|
799
|
+
<table>
|
|
800
|
+
<thead>
|
|
801
|
+
<tr>
|
|
802
|
+
<th>ID</th>
|
|
803
|
+
<th>Customer</th>
|
|
804
|
+
<th>Total Amount</th> {/* Admin can see financial data */}
|
|
805
|
+
<th>Profit Margin</th> {/* Admin can see profit */}
|
|
806
|
+
<th>Internal Notes</th> {/* Admin can see internal notes */}
|
|
807
|
+
</tr>
|
|
808
|
+
</thead>
|
|
809
|
+
<tbody>
|
|
810
|
+
{table.rows.map((order: AdminOrder) => (
|
|
811
|
+
<tr key={order._id}>
|
|
812
|
+
<td>{order._id}</td>
|
|
813
|
+
<td>{order.customerId}</td>
|
|
814
|
+
<td>${order.totalAmount}</td>{" "}
|
|
815
|
+
{/* ✅ TypeScript knows this exists */}
|
|
816
|
+
<td>{order.profitMargin}%</td> {/* ✅ TypeScript knows this exists */}
|
|
817
|
+
<td>{order.internalNotes}</td>{" "}
|
|
818
|
+
{/* ✅ TypeScript knows this exists */}
|
|
819
|
+
</tr>
|
|
820
|
+
))}
|
|
821
|
+
</tbody>
|
|
822
|
+
</table>
|
|
823
|
+
);
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
// If AI tries to generate user code that accesses admin fields:
|
|
827
|
+
function UserOrderList() {
|
|
828
|
+
const order = new Order(Roles.User);
|
|
829
|
+
const data = await order.get("123");
|
|
830
|
+
|
|
831
|
+
return <div>{data.profitMargin}</div>; // ❌ TypeScript Error!
|
|
832
|
+
// Property 'profitMargin' does not exist on type 'UserOrder'
|
|
833
|
+
}
|
|
834
|
+
```
|
|
835
|
+
|
|
836
|
+
**The AI sees the TypeScript error and automatically regenerates correct code.**
|
|
837
|
+
|
|
838
|
+
## License
|
|
839
|
+
|
|
840
|
+
MIT
|