@amaster.ai/client 1.1.0-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.
@@ -0,0 +1,710 @@
1
+ /**
2
+ * ============================================================================
3
+ * Entity Module - Type Definitions
4
+ * ============================================================================
5
+ *
6
+ * This module provides CRUD operations for entities in the Amaster platform.
7
+ *
8
+ * ## Key Features
9
+ * - List entities with pagination, sorting, and filtering
10
+ * - Get single entity by ID
11
+ * - Create, update, and delete entities
12
+ * - Advanced filtering with AND/OR conditions
13
+ * - Full-text search across multiple fields
14
+ * - Relation loading (eager loading)
15
+ * - Field selection (only fetch specific fields)
16
+ * - Bulk operations
17
+ *
18
+ * ## Filter Operators
19
+ * - `eq` (default): Equal
20
+ * - `ne`: Not equal
21
+ * - `gt`: Greater than
22
+ * - `ge`: Greater or equal
23
+ * - `lt`: Less than
24
+ * - `le`: Less or equal
25
+ * - `like`: Fuzzy match (auto wraps with %)
26
+ * - `sw`: Starts with
27
+ * - `ew`: Ends with
28
+ * - `bt`: Between (requires {from, to})
29
+ * - `in`: In array
30
+ *
31
+ * @module entity
32
+ */
33
+
34
+ import type { ClientResult } from './common';
35
+
36
+ // ==================== Filter Types ====================
37
+
38
+ /**
39
+ * Simple filter operators for query string format
40
+ *
41
+ * Usage: `{ 'field[op]': value }`
42
+ *
43
+ * @example
44
+ * ```typescript
45
+ * {
46
+ * 'status[eq]': 'active',
47
+ * 'price[gt]': 100,
48
+ * 'name[like]': 'test',
49
+ * 'id[in]': [1, 2, 3]
50
+ * }
51
+ * ```
52
+ */
53
+ export type FilterOperator =
54
+ | 'eq' // Equal (default if no operator specified)
55
+ | 'ne' // Not equal
56
+ | 'gt' // Greater than
57
+ | 'ge' // Greater or equal
58
+ | 'lt' // Less than
59
+ | 'le' // Less or equal
60
+ | 'like' // Fuzzy match (auto wraps with %)
61
+ | 'sw' // Starts with
62
+ | 'ew' // Ends with
63
+ | 'bt' // Between (requires {from, to})
64
+ | 'in'; // In array
65
+
66
+ /**
67
+ * Advanced filter operators for condition builder
68
+ *
69
+ * @example
70
+ * ```typescript
71
+ * {
72
+ * op: 'equal',
73
+ * left: { field: 'status' },
74
+ * right: 'active'
75
+ * }
76
+ * ```
77
+ */
78
+ export type AdvancedFilterOperator =
79
+ | 'equal'
80
+ | 'not_equal'
81
+ | 'less'
82
+ | 'less_or_equal'
83
+ | 'greater'
84
+ | 'greater_or_equal'
85
+ | 'like'
86
+ | 'not_like'
87
+ | 'starts_with'
88
+ | 'ends_with'
89
+ | 'between'
90
+ | 'is_empty'
91
+ | 'is_not_empty'
92
+ | 'select_any_in'
93
+ | 'select_not_any_in';
94
+
95
+ /**
96
+ * Advanced filter item (single condition)
97
+ *
98
+ * @example
99
+ * Single condition:
100
+ * ```typescript
101
+ * {
102
+ * op: 'equal',
103
+ * left: { field: 'status' },
104
+ * right: 'active'
105
+ * }
106
+ * ```
107
+ *
108
+ * @example
109
+ * Relation field:
110
+ * ```typescript
111
+ * {
112
+ * op: 'equal',
113
+ * left: { field: 'user.email' },
114
+ * right: 'test@example.com'
115
+ * }
116
+ * ```
117
+ */
118
+ export interface FilterItem {
119
+ op: AdvancedFilterOperator;
120
+ left: {
121
+ /** Field name, supports dot notation for relations (e.g., 'user.email') */
122
+ field: string;
123
+ };
124
+ right?: string | number | boolean | Date | null | string[] | number[];
125
+ }
126
+
127
+ /**
128
+ * Advanced filter group (supports AND/OR with nesting)
129
+ *
130
+ * @example
131
+ * (status = 'active') AND (priority > 5 OR assignee IS NOT NULL):
132
+ * ```typescript
133
+ * {
134
+ * conjunction: 'and',
135
+ * children: [
136
+ * {
137
+ * op: 'equal',
138
+ * left: { field: 'status' },
139
+ * right: 'active'
140
+ * },
141
+ * {
142
+ * conjunction: 'or',
143
+ * children: [
144
+ * {
145
+ * op: 'greater',
146
+ * left: { field: 'priority' },
147
+ * right: 5
148
+ * },
149
+ * {
150
+ * op: 'is_not_empty',
151
+ * left: { field: 'assignee' }
152
+ * }
153
+ * ]
154
+ * }
155
+ * ]
156
+ * }
157
+ * ```
158
+ */
159
+ export interface FilterGroup {
160
+ conjunction: 'and' | 'or';
161
+ children: Array<FilterGroup | FilterItem>;
162
+ }
163
+
164
+ /**
165
+ * Keywords search configuration
166
+ *
167
+ * @example
168
+ * Search in specific fields:
169
+ * ```typescript
170
+ * {
171
+ * fields: ['name', 'description'],
172
+ * value: 'search term'
173
+ * }
174
+ * ```
175
+ */
176
+ export interface KeywordsSearch {
177
+ /** Fields to search in */
178
+ fields: string[];
179
+ /** Search value */
180
+ value: string;
181
+ }
182
+
183
+ /**
184
+ * Between filter value
185
+ *
186
+ * @example
187
+ * ```typescript
188
+ * {
189
+ * 'created_at[bt]': {
190
+ * from: '2024-01-01',
191
+ * to: '2024-12-31'
192
+ * }
193
+ * }
194
+ * ```
195
+ */
196
+ export interface BetweenValue {
197
+ from?: string | number | Date;
198
+ to?: string | number | Date;
199
+ }
200
+
201
+ // ==================== Query Parameters ====================
202
+
203
+ /**
204
+ * Entity query parameters
205
+ *
206
+ * Supports pagination, sorting, filtering, searching, and relation loading.
207
+ *
208
+ * @example
209
+ * Basic pagination and sorting:
210
+ * ```typescript
211
+ * {
212
+ * page: 1,
213
+ * perPage: 20,
214
+ * orderBy: 'created_at',
215
+ * orderDir: 'desc'
216
+ * }
217
+ * ```
218
+ *
219
+ * @example
220
+ * Simple field filter:
221
+ * ```typescript
222
+ * {
223
+ * status: 'active',
224
+ * 'price[gt]': 100,
225
+ * 'name[like]': 'test'
226
+ * }
227
+ * ```
228
+ *
229
+ * @example
230
+ * Keywords search:
231
+ * ```typescript
232
+ * {
233
+ * __keywords: {
234
+ * fields: ['name', 'description'],
235
+ * value: 'search term'
236
+ * }
237
+ * }
238
+ * ```
239
+ *
240
+ * @example
241
+ * Load relations and select fields:
242
+ * ```typescript
243
+ * {
244
+ * __relations: ['user', 'category'],
245
+ * __fields: ['id', 'name', 'status', 'user.email']
246
+ * }
247
+ * ```
248
+ *
249
+ * @example
250
+ * Advanced filter with AND/OR:
251
+ * ```typescript
252
+ * {
253
+ * __filter: {
254
+ * conjunction: 'and',
255
+ * children: [
256
+ * { op: 'equal', left: { field: 'status' }, right: 'active' },
257
+ * {
258
+ * conjunction: 'or',
259
+ * children: [
260
+ * { op: 'greater', left: { field: 'priority' }, right: 5 },
261
+ * { op: 'is_not_empty', left: { field: 'assignee' } }
262
+ * ]
263
+ * }
264
+ * ]
265
+ * }
266
+ * }
267
+ * ```
268
+ */
269
+ export interface EntityQueryParams {
270
+ // ==================== Pagination ====================
271
+
272
+ /**
273
+ * Page number (1-based)
274
+ * @default 1
275
+ */
276
+ page?: number;
277
+
278
+ /**
279
+ * Items per page
280
+ * @default 20
281
+ */
282
+ perPage?: number;
283
+
284
+ /**
285
+ * Maximum items to return (alternative to perPage)
286
+ */
287
+ limit?: number;
288
+
289
+ /**
290
+ * Number of items to skip (alternative to page)
291
+ */
292
+ offset?: number;
293
+
294
+ // ==================== Sorting ====================
295
+
296
+ /**
297
+ * Field to sort by
298
+ * @example 'created_at'
299
+ */
300
+ orderBy?: string;
301
+
302
+ /**
303
+ * Sort direction
304
+ * @default 'asc'
305
+ */
306
+ orderDir?: 'asc' | 'desc';
307
+
308
+ /**
309
+ * Multiple sort orders (comma-separated)
310
+ * Format: "field1:asc,field2:desc"
311
+ * @example 'priority:desc,created_at:asc'
312
+ */
313
+ __orders?: string;
314
+
315
+ // ==================== Search ====================
316
+
317
+ /**
318
+ * Keywords search
319
+ * - String: search all searchable fields (backend determines)
320
+ * - Object: search specific fields
321
+ *
322
+ * @example '__keywords=search'
323
+ * @example { __keywords: { fields: ['name', 'description'], value: 'keyword' } }
324
+ */
325
+ __keywords?: string | KeywordsSearch;
326
+
327
+ // ==================== Relations & Fields ====================
328
+
329
+ /**
330
+ * Relations to load (eager loading)
331
+ * @example ['user', 'category', 'tags']
332
+ */
333
+ __relations?: string[];
334
+
335
+ /**
336
+ * Fields to select (only return these fields)
337
+ * @example ['id', 'name', 'status', 'user.email']
338
+ */
339
+ __fields?: string[];
340
+
341
+ // ==================== Filters ====================
342
+
343
+ /**
344
+ * Advanced filter (condition builder with AND/OR)
345
+ * @example { conjunction: 'and', children: [...] }
346
+ */
347
+ __filter?: FilterGroup;
348
+
349
+ /**
350
+ * Simple filters using field=value or field[op]=value
351
+ * @example { status: 'active', 'price[gt]': 100 }
352
+ */
353
+ [key: string]: unknown;
354
+ }
355
+
356
+ // ==================== Response Types ====================
357
+
358
+ /**
359
+ * Entity list response
360
+ *
361
+ * @template T - The entity type
362
+ *
363
+ * @example
364
+ * ```typescript
365
+ * interface User {
366
+ * id: number;
367
+ * name: string;
368
+ * email: string;
369
+ * }
370
+ *
371
+ * const result = await client.entity.list<User>('default', 'users');
372
+ * const users: User[] = result.data.items;
373
+ * const total: number = result.data.total;
374
+ * ```
375
+ */
376
+ export interface EntityListResponse<T = Record<string, unknown>> {
377
+ /** Array of entities */
378
+ items: T[];
379
+ /** Total count of entities (for pagination) */
380
+ total: number;
381
+ /** Current page number */
382
+ page?: number;
383
+ /** Items per page */
384
+ perPage?: number;
385
+ }
386
+
387
+ // ==================== Entity Client API ====================
388
+
389
+ /**
390
+ * Entity CRUD Operations Client API
391
+ *
392
+ * Provides methods for creating, reading, updating, and deleting entities.
393
+ *
394
+ * @example
395
+ * Complete CRUD operations:
396
+ * ```typescript
397
+ * const client = createClient({ baseURL: 'https://api.amaster.ai' });
398
+ *
399
+ * // 1. List entities
400
+ * const list = await client.entity.list('default', 'users', {
401
+ * page: 1,
402
+ * perPage: 20,
403
+ * orderBy: 'createdAt',
404
+ * orderDir: 'desc'
405
+ * });
406
+ *
407
+ * // 2. Get single entity
408
+ * const user = await client.entity.get('default', 'users', 1);
409
+ *
410
+ * // 3. Create entity
411
+ * const newUser = await client.entity.create('default', 'users', {
412
+ * name: 'John Doe',
413
+ * email: 'john@example.com'
414
+ * });
415
+ *
416
+ * // 4. Update entity
417
+ * const updated = await client.entity.update('default', 'users', 1, {
418
+ * name: 'Jane Doe'
419
+ * });
420
+ *
421
+ * // 5. Delete entity
422
+ * await client.entity.delete('default', 'users', 1);
423
+ * ```
424
+ */
425
+ export interface EntityClientAPI {
426
+ /**
427
+ * List entities with pagination, filtering, and sorting
428
+ *
429
+ * @template T - The entity type
430
+ * @param source - Data source name (e.g., 'default', 'app-123')
431
+ * @param entity - Entity name (table name)
432
+ * @param params - Query parameters
433
+ * @returns List of entities with pagination info
434
+ *
435
+ * @example
436
+ * Basic list:
437
+ * ```typescript
438
+ * const result = await client.entity.list('default', 'users');
439
+ * console.log(result.data.items); // User array
440
+ * console.log(result.data.total); // Total count
441
+ * ```
442
+ *
443
+ * @example
444
+ * With pagination and sorting:
445
+ * ```typescript
446
+ * const result = await client.entity.list('default', 'users', {
447
+ * page: 2,
448
+ * perPage: 50,
449
+ * orderBy: 'createdAt',
450
+ * orderDir: 'desc'
451
+ * });
452
+ * ```
453
+ *
454
+ * @example
455
+ * With filtering:
456
+ * ```typescript
457
+ * const result = await client.entity.list('default', 'orders', {
458
+ * status: 'pending',
459
+ * 'amount[gt]': 1000,
460
+ * 'created_at[bt]': { from: '2024-01-01', to: '2024-12-31' }
461
+ * });
462
+ * ```
463
+ *
464
+ * @example
465
+ * With full-text search:
466
+ * ```typescript
467
+ * const result = await client.entity.list('default', 'products', {
468
+ * __keywords: {
469
+ * fields: ['name', 'description'],
470
+ * value: 'laptop'
471
+ * }
472
+ * });
473
+ * ```
474
+ *
475
+ * @example
476
+ * With relations:
477
+ * ```typescript
478
+ * const result = await client.entity.list('default', 'orders', {
479
+ * __relations: ['user', 'items'],
480
+ * __fields: ['id', 'total', 'user.name', 'items.product']
481
+ * });
482
+ * ```
483
+ */
484
+ list<T = Record<string, unknown>>(
485
+ source: string,
486
+ entity: string,
487
+ params?: EntityQueryParams
488
+ ): Promise<ClientResult<EntityListResponse<T>>>;
489
+
490
+ /**
491
+ * Get a single entity by ID
492
+ *
493
+ * @template T - The entity type
494
+ * @param source - Data source name
495
+ * @param entity - Entity name
496
+ * @param id - Entity ID
497
+ * @returns The entity data
498
+ *
499
+ * @example
500
+ * ```typescript
501
+ * const result = await client.entity.get('default', 'users', 123);
502
+ * if (result.data) {
503
+ * console.log('User:', result.data);
504
+ * }
505
+ * ```
506
+ *
507
+ * @example
508
+ * With type safety:
509
+ * ```typescript
510
+ * interface User {
511
+ * id: number;
512
+ * name: string;
513
+ * email: string;
514
+ * }
515
+ *
516
+ * const result = await client.entity.get<User>('default', 'users', 123);
517
+ * const user: User = result.data;
518
+ * ```
519
+ */
520
+ get<T = Record<string, unknown>>(
521
+ source: string,
522
+ entity: string,
523
+ id: string | number
524
+ ): Promise<ClientResult<T>>;
525
+
526
+ /**
527
+ * Create a new entity
528
+ *
529
+ * @template T - The entity type
530
+ * @param source - Data source name
531
+ * @param entity - Entity name
532
+ * @param data - Entity data to create
533
+ * @returns The created entity
534
+ *
535
+ * @example
536
+ * ```typescript
537
+ * const result = await client.entity.create('default', 'users', {
538
+ * name: 'John Doe',
539
+ * email: 'john@example.com',
540
+ * role: 'user'
541
+ * });
542
+ *
543
+ * if (result.data) {
544
+ * console.log('Created user ID:', result.data.id);
545
+ * }
546
+ * ```
547
+ *
548
+ * @example
549
+ * With Date handling:
550
+ * ```typescript
551
+ * await client.entity.create('default', 'events', {
552
+ * title: 'Meeting',
553
+ * startTime: new Date('2026-02-07T10:00:00Z'),
554
+ * endTime: new Date('2026-02-07T11:00:00Z')
555
+ * });
556
+ * // Dates are automatically converted to backend format
557
+ * ```
558
+ */
559
+ create<T = Record<string, unknown>>(
560
+ source: string,
561
+ entity: string,
562
+ data: Record<string, unknown>
563
+ ): Promise<ClientResult<T>>;
564
+
565
+ /**
566
+ * Update an existing entity
567
+ *
568
+ * @template T - The entity type
569
+ * @param source - Data source name
570
+ * @param entity - Entity name
571
+ * @param id - Entity ID to update
572
+ * @param data - Fields to update
573
+ * @returns The updated entity
574
+ *
575
+ * @example
576
+ * ```typescript
577
+ * const result = await client.entity.update('default', 'users', 123, {
578
+ * name: 'Jane Doe',
579
+ * email: 'jane@example.com'
580
+ * });
581
+ * ```
582
+ *
583
+ * @example
584
+ * Partial update:
585
+ * ```typescript
586
+ * // Only update the status field
587
+ * await client.entity.update('default', 'orders', 456, {
588
+ * status: 'completed'
589
+ * });
590
+ * ```
591
+ */
592
+ update<T = Record<string, unknown>>(
593
+ source: string,
594
+ entity: string,
595
+ id: string | number,
596
+ data: Record<string, unknown>
597
+ ): Promise<ClientResult<T>>;
598
+
599
+ /**
600
+ * Delete an entity by ID
601
+ *
602
+ * @param source - Data source name
603
+ * @param entity - Entity name
604
+ * @param id - Entity ID to delete
605
+ * @returns null on success
606
+ *
607
+ * @example
608
+ * ```typescript
609
+ * const result = await client.entity.delete('default', 'users', 123);
610
+ * if (result.error === null) {
611
+ * console.log('User deleted successfully');
612
+ * }
613
+ * ```
614
+ *
615
+ * @example
616
+ * With confirmation:
617
+ * ```typescript
618
+ * if (confirm('Are you sure?')) {
619
+ * await client.entity.delete('default', 'users', userId);
620
+ * }
621
+ * ```
622
+ */
623
+ delete(
624
+ source: string,
625
+ entity: string,
626
+ id: string | number
627
+ ): Promise<ClientResult<null>>;
628
+
629
+ /**
630
+ * Get options for select/dropdown fields
631
+ *
632
+ * @template T - The option type
633
+ * @param source - Data source name
634
+ * @param entity - Entity name
635
+ * @param fields - Fields to include in options
636
+ * @returns Array of option objects
637
+ *
638
+ * @example
639
+ * Get user options for dropdown:
640
+ * ```typescript
641
+ * const result = await client.entity.options('default', 'users', ['id', 'name']);
642
+ * // Returns: [{ id: 1, name: 'John' }, { id: 2, name: 'Jane' }, ...]
643
+ *
644
+ * // Use in select element
645
+ * result.data.forEach(user => {
646
+ * const option = document.createElement('option');
647
+ * option.value = user.id;
648
+ * option.text = user.name;
649
+ * selectElement.appendChild(option);
650
+ * });
651
+ * ```
652
+ */
653
+ options<T = Record<string, unknown>>(
654
+ source: string,
655
+ entity: string,
656
+ fields?: string[]
657
+ ): Promise<ClientResult<T[]>>;
658
+
659
+ /**
660
+ * Bulk update multiple entities
661
+ *
662
+ * @template T - The response type
663
+ * @param source - Data source name
664
+ * @param entity - Entity name
665
+ * @param items - Array of entities to update (each must have an id)
666
+ * @returns Update result
667
+ *
668
+ * @example
669
+ * ```typescript
670
+ * await client.entity.bulkUpdate('default', 'tasks', [
671
+ * { id: 1, status: 'completed' },
672
+ * { id: 2, status: 'completed' },
673
+ * { id: 3, status: 'in_progress' }
674
+ * ]);
675
+ * ```
676
+ */
677
+ bulkUpdate<T = Record<string, unknown>>(
678
+ source: string,
679
+ entity: string,
680
+ items: Array<Record<string, unknown> & { id: string | number }>
681
+ ): Promise<ClientResult<T>>;
682
+
683
+ /**
684
+ * Bulk delete multiple entities
685
+ *
686
+ * @param source - Data source name
687
+ * @param entity - Entity name
688
+ * @param ids - Array of entity IDs to delete
689
+ * @returns null on success
690
+ *
691
+ * @example
692
+ * ```typescript
693
+ * await client.entity.bulkDelete('default', 'users', [1, 2, 3, 4, 5]);
694
+ * ```
695
+ *
696
+ * @example
697
+ * Delete selected items:
698
+ * ```typescript
699
+ * const selectedIds = [123, 456, 789];
700
+ * if (confirm(`Delete ${selectedIds.length} items?`)) {
701
+ * await client.entity.bulkDelete('default', 'items', selectedIds);
702
+ * }
703
+ * ```
704
+ */
705
+ bulkDelete(
706
+ source: string,
707
+ entity: string,
708
+ ids: Array<string | number>
709
+ ): Promise<ClientResult<null>>;
710
+ }