@object-ui/data-objectstack 0.3.1 → 2.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/README.md CHANGED
@@ -16,6 +16,8 @@ npm install @object-ui/data-objectstack @objectstack/client
16
16
 
17
17
  ## Usage
18
18
 
19
+ ### Basic Setup
20
+
19
21
  ```typescript
20
22
  import { createObjectStackAdapter } from '@object-ui/data-objectstack';
21
23
  import { SchemaRenderer } from '@object-ui/react';
@@ -37,9 +39,323 @@ function App() {
37
39
  }
38
40
  ```
39
41
 
42
+ ### Advanced Configuration
43
+
44
+ ```typescript
45
+ const dataSource = createObjectStackAdapter({
46
+ baseUrl: 'https://api.example.com',
47
+ token: 'your-api-token',
48
+ // Configure metadata cache
49
+ cache: {
50
+ maxSize: 100, // Maximum number of cached schemas (default: 100)
51
+ ttl: 5 * 60 * 1000 // Time to live in ms (default: 5 minutes)
52
+ },
53
+ // Configure auto-reconnect
54
+ autoReconnect: true, // Enable auto-reconnect (default: true)
55
+ maxReconnectAttempts: 5, // Max reconnection attempts (default: 3)
56
+ reconnectDelay: 2000 // Initial delay between reconnects in ms (default: 1000)
57
+ });
58
+ ```
59
+
40
60
  ## Features
41
61
 
42
62
  - ✅ **CRUD Operations**: Implements `find`, `findOne`, `create`, `update`, `delete`.
63
+ - ✅ **Metadata Caching**: Automatic LRU caching of schema metadata with TTL expiration.
43
64
  - ✅ **Metadata Fetching**: Implements `getObjectSchema` to power auto-generated forms and grids.
44
65
  - ✅ **Query Translation**: Converts Object UI's OData-like query parameters to ObjectStack's native query format.
45
- - ✅ **Bulk Operations**: Supports batch create/update/delete.
66
+ - ✅ **Bulk Operations**: Supports optimized batch create/update/delete with detailed error reporting.
67
+ - ✅ **Error Handling**: Comprehensive error hierarchy with unique error codes and debugging details.
68
+ - ✅ **Connection Monitoring**: Real-time connection state tracking with event listeners.
69
+ - ✅ **Auto-Reconnect**: Automatic reconnection with exponential backoff on connection failures.
70
+ - ✅ **Batch Progress**: Progress events for tracking bulk operation status.
71
+
72
+ ## Metadata Caching
73
+
74
+ The adapter includes built-in metadata caching to improve performance when fetching schemas:
75
+
76
+ ```typescript
77
+ // Get cache statistics
78
+ const stats = dataSource.getCacheStats();
79
+ console.log(`Cache hit rate: ${stats.hitRate * 100}%`);
80
+ console.log(`Cache size: ${stats.size}/${stats.maxSize}`);
81
+
82
+ // Manually invalidate cache entries
83
+ dataSource.invalidateCache('users'); // Invalidate specific schema
84
+ dataSource.invalidateCache(); // Invalidate all cached schemas
85
+
86
+ // Clear cache and statistics
87
+ dataSource.clearCache();
88
+ ```
89
+
90
+ ### Cache Configuration
91
+
92
+ - **LRU Eviction**: Automatically evicts least recently used entries when cache is full
93
+ - **TTL Expiration**: Entries expire after the configured time-to-live from creation (default: 5 minutes)
94
+ - Note: TTL is fixed from creation time, not sliding based on access
95
+ - **Memory Limits**: Configurable maximum cache size (default: 100 entries)
96
+ - **Concurrent Access**: Handles async operations safely. Note that concurrent requests for the same uncached key may result in multiple fetcher calls.
97
+
98
+ ## Connection State Monitoring
99
+
100
+ The adapter provides real-time connection state monitoring with automatic reconnection:
101
+
102
+ ```typescript
103
+ // Monitor connection state changes
104
+ const unsubscribe = dataSource.onConnectionStateChange((event) => {
105
+ console.log('Connection state:', event.state);
106
+ console.log('Timestamp:', new Date(event.timestamp));
107
+
108
+ if (event.error) {
109
+ console.error('Connection error:', event.error);
110
+ }
111
+ });
112
+
113
+ // Check current connection state
114
+ console.log(dataSource.getConnectionState()); // 'disconnected' | 'connecting' | 'connected' | 'reconnecting' | 'error'
115
+
116
+ // Check if connected
117
+ if (dataSource.isConnected()) {
118
+ console.log('Adapter is connected');
119
+ }
120
+
121
+ // Unsubscribe from events when done
122
+ unsubscribe();
123
+ ```
124
+
125
+ ### Connection States
126
+
127
+ - `disconnected` - Not connected to server
128
+ - `connecting` - Attempting initial connection
129
+ - `connected` - Successfully connected
130
+ - `reconnecting` - Attempting to reconnect after failure
131
+ - `error` - Connection failed (check event.error for details)
132
+
133
+ ### Auto-Reconnect
134
+
135
+ The adapter automatically attempts to reconnect on connection failures:
136
+
137
+ - **Exponential Backoff**: Delay increases with each attempt (delay × 2^(attempts-1))
138
+ - **Configurable Attempts**: Set `maxReconnectAttempts` (default: 3)
139
+ - **Configurable Delay**: Set `reconnectDelay` for initial delay (default: 1000ms)
140
+ - **Automatic**: Enabled by default, disable with `autoReconnect: false`
141
+
142
+ ## Batch Operation Progress
143
+
144
+ Track progress of bulk operations in real-time:
145
+
146
+ ```typescript
147
+ // Monitor batch operation progress
148
+ const unsubscribe = dataSource.onBatchProgress((event) => {
149
+ console.log(`${event.operation}: ${event.percentage.toFixed(1)}%`);
150
+ console.log(`Completed: ${event.completed}/${event.total}`);
151
+ console.log(`Failed: ${event.failed}`);
152
+ });
153
+
154
+ // Perform bulk operation
155
+ const users = await dataSource.bulk('users', 'create', largeDataset);
156
+
157
+ // Unsubscribe when done
158
+ unsubscribe();
159
+ ```
160
+
161
+ ### Progress Event Properties
162
+
163
+ - `operation` - Operation type ('create' | 'update' | 'delete')
164
+ - `total` - Total number of items
165
+ - `completed` - Number of successfully completed items
166
+ - `failed` - Number of failed items
167
+ - `percentage` - Completion percentage (0-100)
168
+
169
+ ## Error Handling
170
+
171
+ The adapter provides a comprehensive error hierarchy for better error handling:
172
+
173
+ ### Error Types
174
+
175
+ ```typescript
176
+ import {
177
+ ObjectStackError, // Base error class
178
+ MetadataNotFoundError, // Schema/metadata not found (404)
179
+ BulkOperationError, // Bulk operation failures with partial results
180
+ ConnectionError, // Network/connection errors (503/504)
181
+ AuthenticationError, // Authentication failures (401/403)
182
+ ValidationError, // Data validation errors (400)
183
+ } from '@object-ui/data-objectstack';
184
+ ```
185
+
186
+ ### Error Handling Example
187
+
188
+ ```typescript
189
+ try {
190
+ const schema = await dataSource.getObjectSchema('users');
191
+ } catch (error) {
192
+ if (error instanceof MetadataNotFoundError) {
193
+ console.error(`Schema not found: ${error.details.objectName}`);
194
+ } else if (error instanceof ConnectionError) {
195
+ console.error(`Connection failed to: ${error.url}`);
196
+ } else if (error instanceof AuthenticationError) {
197
+ console.error('Authentication required');
198
+ }
199
+
200
+ // All errors have consistent structure
201
+ console.error({
202
+ code: error.code,
203
+ message: error.message,
204
+ statusCode: error.statusCode,
205
+ details: error.details
206
+ });
207
+ }
208
+ ```
209
+
210
+ ### Bulk Operation Errors
211
+
212
+ Bulk operations provide detailed error reporting with partial success information:
213
+
214
+ ```typescript
215
+ try {
216
+ await dataSource.bulk('users', 'update', records);
217
+ } catch (error) {
218
+ if (error instanceof BulkOperationError) {
219
+ const summary = error.getSummary();
220
+ console.log(`${summary.successful} succeeded, ${summary.failed} failed`);
221
+ console.log(`Failure rate: ${summary.failureRate * 100}%`);
222
+
223
+ // Inspect individual failures
224
+ summary.errors.forEach(({ index, error }) => {
225
+ console.error(`Record ${index} failed:`, error);
226
+ });
227
+ }
228
+ }
229
+ ```
230
+
231
+ ### Error Codes
232
+
233
+ All errors include unique error codes for programmatic handling:
234
+
235
+ - `METADATA_NOT_FOUND` - Schema/metadata not found
236
+ - `BULK_OPERATION_ERROR` - Bulk operation failure
237
+ - `CONNECTION_ERROR` - Connection/network error
238
+ - `AUTHENTICATION_ERROR` - Authentication failure
239
+ - `VALIDATION_ERROR` - Data validation error
240
+ - `UNSUPPORTED_OPERATION` - Unsupported operation
241
+ - `NOT_FOUND` - Resource not found
242
+ - `UNKNOWN_ERROR` - Unknown error
243
+
244
+ ## Batch Operations
245
+
246
+ The adapter supports optimized batch operations with automatic fallback:
247
+
248
+ ```typescript
249
+ // Batch create
250
+ const newUsers = await dataSource.bulk('users', 'create', [
251
+ { name: 'Alice', email: 'alice@example.com' },
252
+ { name: 'Bob', email: 'bob@example.com' },
253
+ ]);
254
+
255
+ // Batch update (uses updateMany if available, falls back to individual updates)
256
+ const updated = await dataSource.bulk('users', 'update', [
257
+ { id: '1', name: 'Alice Smith' },
258
+ { id: '2', name: 'Bob Jones' },
259
+ ]);
260
+
261
+ // Batch delete
262
+ await dataSource.bulk('users', 'delete', [
263
+ { id: '1' },
264
+ { id: '2' },
265
+ ]);
266
+ ```
267
+
268
+ ### Performance Optimizations
269
+
270
+ - Automatically uses `createMany`, `updateMany`, `deleteMany` when available
271
+ - Falls back to individual operations with detailed error tracking
272
+ - Provides partial success reporting for resilient error handling
273
+ - Atomic operations where supported by the backend
274
+
275
+ ## API Reference
276
+
277
+ ### ObjectStackAdapter
278
+
279
+ #### Constructor
280
+
281
+ ```typescript
282
+ new ObjectStackAdapter(config: {
283
+ baseUrl: string;
284
+ token?: string;
285
+ fetch?: (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
286
+ cache?: {
287
+ maxSize?: number;
288
+ ttl?: number;
289
+ };
290
+ autoReconnect?: boolean;
291
+ maxReconnectAttempts?: number;
292
+ reconnectDelay?: number;
293
+ })
294
+ ```
295
+
296
+ #### Methods
297
+
298
+ - `connect()` - Establish connection to ObjectStack server
299
+ - `find(resource, params?)` - Query multiple records
300
+ - `findOne(resource, id, params?)` - Get a single record by ID
301
+ - `create(resource, data)` - Create a new record
302
+ - `update(resource, id, data)` - Update an existing record
303
+ - `delete(resource, id)` - Delete a record
304
+ - `bulk(resource, operation, data)` - Batch operations (create/update/delete)
305
+ - `getObjectSchema(objectName)` - Get schema metadata (cached)
306
+ - `getCacheStats()` - Get cache statistics
307
+ - `invalidateCache(key?)` - Invalidate cache entries
308
+ - `clearCache()` - Clear all cache entries
309
+ - `getClient()` - Access underlying ObjectStack client
310
+ - `getConnectionState()` - Get current connection state
311
+ - `isConnected()` - Check if adapter is connected
312
+ - `onConnectionStateChange(listener)` - Subscribe to connection state changes (returns unsubscribe function)
313
+ - `onBatchProgress(listener)` - Subscribe to batch operation progress (returns unsubscribe function)
314
+
315
+ ## Best Practices
316
+
317
+ 1. **Enable Caching**: Use default cache settings for optimal performance
318
+ 2. **Handle Errors**: Use typed error handling for better user experience
319
+ 3. **Batch Operations**: Use bulk methods for large datasets
320
+ 4. **Monitor Cache**: Check cache hit rates in production
321
+ 5. **Invalidate Wisely**: Clear cache after schema changes
322
+ 6. **Connection Monitoring**: Subscribe to connection state changes for better UX
323
+ 7. **Auto-Reconnect**: Use default auto-reconnect settings for resilient applications
324
+ 8. **Batch Progress**: Monitor progress for long-running bulk operations
325
+
326
+ ## Troubleshooting
327
+
328
+ ### Common Issues
329
+
330
+ #### Schema Not Found
331
+
332
+ ```typescript
333
+ // Error: MetadataNotFoundError
334
+ // Solution: Verify object name and ensure schema exists on server
335
+ const schema = await dataSource.getObjectSchema('correct_object_name');
336
+ ```
337
+
338
+ #### Connection Errors
339
+
340
+ ```typescript
341
+ // Error: ConnectionError
342
+ // Solution: Check baseUrl and network connectivity
343
+ const dataSource = createObjectStackAdapter({
344
+ baseUrl: 'https://correct-url.example.com',
345
+ token: 'valid-token'
346
+ });
347
+ ```
348
+
349
+ #### Cache Issues
350
+
351
+ ```typescript
352
+ // Clear cache if stale data is being returned
353
+ dataSource.clearCache();
354
+
355
+ // Or invalidate specific entries
356
+ dataSource.invalidateCache('users');
357
+ ```
358
+
359
+ ## License
360
+
361
+ MIT