@ram_28/kf-ai-sdk 1.0.4 → 1.0.5
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 +83 -87
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -9,6 +9,7 @@ npm install @ram_28/kf-ai-sdk
|
|
|
9
9
|
```
|
|
10
10
|
|
|
11
11
|
**Peer Dependencies:**
|
|
12
|
+
|
|
12
13
|
```bash
|
|
13
14
|
npm install react @tanstack/react-query
|
|
14
15
|
```
|
|
@@ -43,8 +44,8 @@ import {
|
|
|
43
44
|
|
|
44
45
|
// Utilities
|
|
45
46
|
formatCurrency,
|
|
46
|
-
formatDate
|
|
47
|
-
} from
|
|
47
|
+
formatDate,
|
|
48
|
+
} from "@ram_28/kf-ai-sdk";
|
|
48
49
|
```
|
|
49
50
|
|
|
50
51
|
## Authentication
|
|
@@ -56,8 +57,8 @@ The SDK provides a complete authentication solution with cookie-based session ma
|
|
|
56
57
|
Wrap your app with `AuthProvider` inside a `QueryClientProvider`. No configuration required - it works out of the box:
|
|
57
58
|
|
|
58
59
|
```tsx
|
|
59
|
-
import { QueryClient, QueryClientProvider } from
|
|
60
|
-
import { AuthProvider } from
|
|
60
|
+
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
|
61
|
+
import { AuthProvider } from "@ram_28/kf-ai-sdk";
|
|
61
62
|
|
|
62
63
|
const queryClient = new QueryClient();
|
|
63
64
|
|
|
@@ -77,7 +78,7 @@ function App() {
|
|
|
77
78
|
Access authentication state and operations in any component:
|
|
78
79
|
|
|
79
80
|
```tsx
|
|
80
|
-
import { useAuth } from
|
|
81
|
+
import { useAuth } from "@ram_28/kf-ai-sdk";
|
|
81
82
|
|
|
82
83
|
function UserMenu() {
|
|
83
84
|
const { user, isAuthenticated, isLoading, logout, hasRole } = useAuth();
|
|
@@ -90,11 +91,9 @@ function UserMenu() {
|
|
|
90
91
|
<span>Welcome, {user._name}</span>
|
|
91
92
|
<span>Role: {user.Role}</span>
|
|
92
93
|
|
|
93
|
-
{hasRole(
|
|
94
|
+
{hasRole("Admin") && <a href="/admin">Admin Dashboard</a>}
|
|
94
95
|
|
|
95
|
-
<button onClick={() => logout({ redirectUrl:
|
|
96
|
-
Logout
|
|
97
|
-
</button>
|
|
96
|
+
<button onClick={() => logout({ redirectUrl: "/" })}>Logout</button>
|
|
98
97
|
</div>
|
|
99
98
|
);
|
|
100
99
|
}
|
|
@@ -105,40 +104,38 @@ function UserMenu() {
|
|
|
105
104
|
```tsx
|
|
106
105
|
const {
|
|
107
106
|
// User state
|
|
108
|
-
user,
|
|
109
|
-
staticBaseUrl,
|
|
110
|
-
buildId,
|
|
111
|
-
status,
|
|
112
|
-
isAuthenticated,
|
|
113
|
-
isLoading,
|
|
107
|
+
user, // UserDetails | null
|
|
108
|
+
staticBaseUrl, // string | null
|
|
109
|
+
buildId, // string | null
|
|
110
|
+
status, // 'loading' | 'authenticated' | 'unauthenticated'
|
|
111
|
+
isAuthenticated, // boolean
|
|
112
|
+
isLoading, // boolean
|
|
114
113
|
|
|
115
114
|
// Operations
|
|
116
|
-
login,
|
|
117
|
-
logout,
|
|
118
|
-
refreshSession,
|
|
119
|
-
hasRole,
|
|
120
|
-
hasAnyRole,
|
|
115
|
+
login, // (provider?, options?) => void
|
|
116
|
+
logout, // (options?) => Promise<void>
|
|
117
|
+
refreshSession, // () => Promise<SessionResponse | null>
|
|
118
|
+
hasRole, // (role: string) => boolean
|
|
119
|
+
hasAnyRole, // (roles: string[]) => boolean
|
|
121
120
|
|
|
122
121
|
// Error handling
|
|
123
|
-
error,
|
|
124
|
-
clearError,
|
|
122
|
+
error, // Error | null
|
|
123
|
+
clearError, // () => void
|
|
125
124
|
} = useAuth();
|
|
126
125
|
```
|
|
127
126
|
|
|
128
127
|
### Multiple Auth Providers
|
|
129
128
|
|
|
130
129
|
```tsx
|
|
131
|
-
import { useAuth } from
|
|
130
|
+
import { useAuth } from "@ram_28/kf-ai-sdk";
|
|
132
131
|
|
|
133
132
|
function LoginPage() {
|
|
134
133
|
const { login } = useAuth();
|
|
135
134
|
|
|
136
135
|
return (
|
|
137
136
|
<div>
|
|
138
|
-
<button onClick={() => login(
|
|
139
|
-
|
|
140
|
-
</button>
|
|
141
|
-
<button onClick={() => login('microsoft')}>
|
|
137
|
+
<button onClick={() => login("google")}>Continue with Google</button>
|
|
138
|
+
<button onClick={() => login("microsoft")}>
|
|
142
139
|
Continue with Microsoft
|
|
143
140
|
</button>
|
|
144
141
|
</div>
|
|
@@ -149,8 +146,8 @@ function LoginPage() {
|
|
|
149
146
|
### Protected Routes
|
|
150
147
|
|
|
151
148
|
```tsx
|
|
152
|
-
import { useAuth } from
|
|
153
|
-
import { Navigate } from
|
|
149
|
+
import { useAuth } from "@ram_28/kf-ai-sdk";
|
|
150
|
+
import { Navigate } from "react-router-dom";
|
|
154
151
|
|
|
155
152
|
function ProtectedRoute({ children, requiredRoles }) {
|
|
156
153
|
const { isAuthenticated, isLoading, hasAnyRole } = useAuth();
|
|
@@ -165,9 +162,9 @@ function ProtectedRoute({ children, requiredRoles }) {
|
|
|
165
162
|
}
|
|
166
163
|
|
|
167
164
|
// Usage
|
|
168
|
-
<ProtectedRoute requiredRoles={[
|
|
165
|
+
<ProtectedRoute requiredRoles={["Admin", "Manager"]}>
|
|
169
166
|
<AdminDashboard />
|
|
170
|
-
</ProtectedRoute
|
|
167
|
+
</ProtectedRoute>;
|
|
171
168
|
```
|
|
172
169
|
|
|
173
170
|
## Hooks
|
|
@@ -177,11 +174,11 @@ function ProtectedRoute({ children, requiredRoles }) {
|
|
|
177
174
|
Data table hook with sorting, pagination, and React Query integration.
|
|
178
175
|
|
|
179
176
|
```tsx
|
|
180
|
-
import { useTable } from
|
|
177
|
+
import { useTable } from "@ram_28/kf-ai-sdk";
|
|
181
178
|
|
|
182
179
|
function ProductTable() {
|
|
183
180
|
const table = useTable({
|
|
184
|
-
source:
|
|
181
|
+
source: "products",
|
|
185
182
|
enableSorting: true,
|
|
186
183
|
enablePagination: true,
|
|
187
184
|
pageSize: 25,
|
|
@@ -191,8 +188,8 @@ function ProductTable() {
|
|
|
191
188
|
<table>
|
|
192
189
|
<thead>
|
|
193
190
|
<tr>
|
|
194
|
-
<th onClick={() => table.toggleSort(
|
|
195
|
-
<th onClick={() => table.toggleSort(
|
|
191
|
+
<th onClick={() => table.toggleSort("name")}>Name</th>
|
|
192
|
+
<th onClick={() => table.toggleSort("price")}>Price</th>
|
|
196
193
|
</tr>
|
|
197
194
|
</thead>
|
|
198
195
|
<tbody>
|
|
@@ -222,27 +219,27 @@ function ProductTable() {
|
|
|
222
219
|
Schema-driven form hook with backend validation support.
|
|
223
220
|
|
|
224
221
|
```tsx
|
|
225
|
-
import { useForm } from
|
|
222
|
+
import { useForm } from "@ram_28/kf-ai-sdk";
|
|
226
223
|
|
|
227
224
|
function ProductForm() {
|
|
228
225
|
const form = useForm({
|
|
229
|
-
source:
|
|
230
|
-
operation:
|
|
226
|
+
source: "products",
|
|
227
|
+
operation: "create",
|
|
231
228
|
onSuccess: (data) => {
|
|
232
|
-
console.log(
|
|
229
|
+
console.log("Created:", data);
|
|
233
230
|
},
|
|
234
231
|
});
|
|
235
232
|
|
|
236
233
|
return (
|
|
237
234
|
<form onSubmit={form.handleSubmit()}>
|
|
238
|
-
<input {...form.register(
|
|
235
|
+
<input {...form.register("name")} placeholder="Product Name" />
|
|
239
236
|
{form.errors.name && <span>{form.errors.name.message}</span>}
|
|
240
237
|
|
|
241
|
-
<input {...form.register(
|
|
238
|
+
<input {...form.register("price")} type="number" placeholder="Price" />
|
|
242
239
|
{form.errors.price && <span>{form.errors.price.message}</span>}
|
|
243
240
|
|
|
244
241
|
<button type="submit" disabled={form.isSubmitting}>
|
|
245
|
-
{form.isSubmitting ?
|
|
242
|
+
{form.isSubmitting ? "Creating..." : "Create Product"}
|
|
246
243
|
</button>
|
|
247
244
|
</form>
|
|
248
245
|
);
|
|
@@ -254,16 +251,16 @@ function ProductForm() {
|
|
|
254
251
|
Kanban board state management with drag-drop support.
|
|
255
252
|
|
|
256
253
|
```tsx
|
|
257
|
-
import { useKanban, Kanban, KanbanColumn, KanbanCard } from
|
|
254
|
+
import { useKanban, Kanban, KanbanColumn, KanbanCard } from "@ram_28/kf-ai-sdk";
|
|
258
255
|
|
|
259
256
|
function TaskBoard() {
|
|
260
257
|
const kanban = useKanban({
|
|
261
|
-
source:
|
|
262
|
-
groupByField:
|
|
258
|
+
source: "tasks",
|
|
259
|
+
groupByField: "status",
|
|
263
260
|
columns: [
|
|
264
|
-
{ id:
|
|
265
|
-
{ id:
|
|
266
|
-
{ id:
|
|
261
|
+
{ id: "todo", title: "To Do" },
|
|
262
|
+
{ id: "in-progress", title: "In Progress" },
|
|
263
|
+
{ id: "done", title: "Done" },
|
|
267
264
|
],
|
|
268
265
|
});
|
|
269
266
|
|
|
@@ -288,14 +285,17 @@ function TaskBoard() {
|
|
|
288
285
|
Advanced filtering with logical operators.
|
|
289
286
|
|
|
290
287
|
```tsx
|
|
291
|
-
import { useFilter, buildFilterPayload } from
|
|
288
|
+
import { useFilter, buildFilterPayload } from "@ram_28/kf-ai-sdk";
|
|
292
289
|
|
|
293
290
|
function ProductFilter() {
|
|
294
291
|
const filter = useFilter({
|
|
295
292
|
fields: {
|
|
296
|
-
name: { type:
|
|
297
|
-
price: { type:
|
|
298
|
-
category: {
|
|
293
|
+
name: { type: "string" },
|
|
294
|
+
price: { type: "number" },
|
|
295
|
+
category: {
|
|
296
|
+
type: "select",
|
|
297
|
+
options: ["electronics", "clothing", "books"],
|
|
298
|
+
},
|
|
299
299
|
},
|
|
300
300
|
});
|
|
301
301
|
|
|
@@ -306,10 +306,10 @@ function ProductFilter() {
|
|
|
306
306
|
|
|
307
307
|
return (
|
|
308
308
|
<div>
|
|
309
|
-
<button onClick={() => filter.addCondition(
|
|
309
|
+
<button onClick={() => filter.addCondition("name", "contains", "")}>
|
|
310
310
|
Add Name Filter
|
|
311
311
|
</button>
|
|
312
|
-
<button onClick={() => filter.addCondition(
|
|
312
|
+
<button onClick={() => filter.addCondition("price", "gte", 0)}>
|
|
313
313
|
Add Price Filter
|
|
314
314
|
</button>
|
|
315
315
|
<button onClick={handleApply}>Apply Filters</button>
|
|
@@ -323,54 +323,50 @@ function ProductFilter() {
|
|
|
323
323
|
Type-safe API client for CRUD operations.
|
|
324
324
|
|
|
325
325
|
```tsx
|
|
326
|
-
import { api, setApiBaseUrl } from
|
|
326
|
+
import { api, setApiBaseUrl } from "@ram_28/kf-ai-sdk";
|
|
327
327
|
|
|
328
328
|
// Configure base URL
|
|
329
|
-
setApiBaseUrl(
|
|
329
|
+
setApiBaseUrl("https://api.example.com");
|
|
330
330
|
|
|
331
331
|
// CRUD Operations
|
|
332
332
|
async function productOperations() {
|
|
333
333
|
// Get single record
|
|
334
|
-
const product = await api(
|
|
334
|
+
const product = await api("products").get("PROD_123");
|
|
335
335
|
|
|
336
336
|
// Create record
|
|
337
|
-
const created = await api(
|
|
338
|
-
name:
|
|
337
|
+
const created = await api("products").create({
|
|
338
|
+
name: "New Product",
|
|
339
339
|
price: 99.99,
|
|
340
|
-
category:
|
|
340
|
+
category: "electronics",
|
|
341
341
|
});
|
|
342
342
|
|
|
343
343
|
// Update record
|
|
344
|
-
const updated = await api(
|
|
344
|
+
const updated = await api("products").update("PROD_123", {
|
|
345
345
|
price: 89.99,
|
|
346
346
|
});
|
|
347
347
|
|
|
348
348
|
// Delete record
|
|
349
|
-
await api(
|
|
349
|
+
await api("products").delete("PROD_123");
|
|
350
350
|
|
|
351
351
|
// List with filtering and sorting
|
|
352
|
-
const products = await api(
|
|
352
|
+
const products = await api("products").list({
|
|
353
353
|
Filter: {
|
|
354
|
-
Operator:
|
|
354
|
+
Operator: "AND",
|
|
355
355
|
Condition: [
|
|
356
|
-
{ Operator:
|
|
357
|
-
{ Operator:
|
|
356
|
+
{ Operator: "EQ", LHSField: "category", RHSValue: "electronics" },
|
|
357
|
+
{ Operator: "GTE", LHSField: "price", RHSValue: 50 },
|
|
358
358
|
],
|
|
359
359
|
},
|
|
360
|
-
Sort: [
|
|
361
|
-
{ Field: 'price', Order: 'DESC' },
|
|
362
|
-
],
|
|
360
|
+
Sort: [{ Field: "price", Order: "DESC" }],
|
|
363
361
|
Page: 1,
|
|
364
362
|
PageSize: 25,
|
|
365
363
|
});
|
|
366
364
|
|
|
367
365
|
// Count records
|
|
368
|
-
const count = await api(
|
|
366
|
+
const count = await api("products").count({
|
|
369
367
|
Filter: {
|
|
370
|
-
Operator:
|
|
371
|
-
Condition: [
|
|
372
|
-
{ Operator: 'EQ', LHSField: 'inStock', RHSValue: true },
|
|
373
|
-
],
|
|
368
|
+
Operator: "AND",
|
|
369
|
+
Condition: [{ Operator: "EQ", LHSField: "inStock", RHSValue: true }],
|
|
374
370
|
},
|
|
375
371
|
});
|
|
376
372
|
}
|
|
@@ -392,7 +388,7 @@ import type {
|
|
|
392
388
|
CurrencyField,
|
|
393
389
|
PercentageField,
|
|
394
390
|
SelectField,
|
|
395
|
-
} from
|
|
391
|
+
} from "@ram_28/kf-ai-sdk";
|
|
396
392
|
|
|
397
393
|
// Define your data types
|
|
398
394
|
interface Product {
|
|
@@ -402,7 +398,7 @@ interface Product {
|
|
|
402
398
|
price: CurrencyField;
|
|
403
399
|
quantity: NumberField<0>;
|
|
404
400
|
inStock: BooleanField;
|
|
405
|
-
category: SelectField<
|
|
401
|
+
category: SelectField<"electronics" | "clothing" | "books">;
|
|
406
402
|
createdAt: DateTimeField;
|
|
407
403
|
}
|
|
408
404
|
```
|
|
@@ -417,24 +413,24 @@ import {
|
|
|
417
413
|
formatDate,
|
|
418
414
|
formatDateTime,
|
|
419
415
|
formatNumber,
|
|
420
|
-
formatPercentage
|
|
421
|
-
} from
|
|
422
|
-
|
|
423
|
-
formatCurrency(99.99);
|
|
424
|
-
formatDate(new Date());
|
|
425
|
-
formatDateTime(new Date());
|
|
426
|
-
formatNumber(1234.56, 2);
|
|
427
|
-
formatPercentage(0.156);
|
|
416
|
+
formatPercentage,
|
|
417
|
+
} from "@ram_28/kf-ai-sdk";
|
|
418
|
+
|
|
419
|
+
formatCurrency(99.99); // "$99.99"
|
|
420
|
+
formatDate(new Date()); // "Jan 11, 2024"
|
|
421
|
+
formatDateTime(new Date()); // "Jan 11, 2024, 10:30 AM"
|
|
422
|
+
formatNumber(1234.56, 2); // "1,234.56"
|
|
423
|
+
formatPercentage(0.156); // "15.6%"
|
|
428
424
|
```
|
|
429
425
|
|
|
430
426
|
### Class Names
|
|
431
427
|
|
|
432
428
|
```tsx
|
|
433
|
-
import { cn } from
|
|
429
|
+
import { cn } from "@ram_28/kf-ai-sdk";
|
|
434
430
|
|
|
435
431
|
// Merge Tailwind classes with conflict resolution
|
|
436
|
-
cn(
|
|
437
|
-
cn(
|
|
432
|
+
cn("px-4 py-2", "px-6"); // "py-2 px-6"
|
|
433
|
+
cn("text-red-500", condition && "text-blue-500");
|
|
438
434
|
```
|
|
439
435
|
|
|
440
436
|
## Documentation
|