@object-ui/data-objectstack 0.3.0 → 0.5.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/dist/index.cjs CHANGED
@@ -22,17 +22,366 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
22
22
  // src/index.ts
23
23
  var index_exports = {};
24
24
  __export(index_exports, {
25
+ AuthenticationError: () => AuthenticationError,
26
+ BulkOperationError: () => BulkOperationError,
27
+ ConnectionError: () => ConnectionError,
28
+ MetadataNotFoundError: () => MetadataNotFoundError,
25
29
  ObjectStackAdapter: () => ObjectStackAdapter,
26
- createObjectStackAdapter: () => createObjectStackAdapter
30
+ ObjectStackError: () => ObjectStackError,
31
+ ValidationError: () => ValidationError,
32
+ createErrorFromResponse: () => createErrorFromResponse,
33
+ createObjectStackAdapter: () => createObjectStackAdapter,
34
+ isErrorType: () => isErrorType,
35
+ isObjectStackError: () => isObjectStackError
27
36
  });
28
37
  module.exports = __toCommonJS(index_exports);
29
38
  var import_client = require("@objectstack/client");
30
39
  var import_core = require("@object-ui/core");
40
+
41
+ // src/cache/MetadataCache.ts
42
+ var MetadataCache = class {
43
+ /**
44
+ * Create a new MetadataCache instance
45
+ *
46
+ * @param options - Configuration options
47
+ * @param options.maxSize - Maximum number of entries (default: 100)
48
+ * @param options.ttl - Time to live in milliseconds (default: 5 minutes)
49
+ */
50
+ constructor(options = {}) {
51
+ __publicField(this, "cache");
52
+ __publicField(this, "maxSize");
53
+ __publicField(this, "ttl");
54
+ __publicField(this, "stats");
55
+ this.cache = /* @__PURE__ */ new Map();
56
+ this.maxSize = options.maxSize || 100;
57
+ this.ttl = options.ttl || 5 * 60 * 1e3;
58
+ this.stats = {
59
+ hits: 0,
60
+ misses: 0,
61
+ evictions: 0
62
+ };
63
+ }
64
+ /**
65
+ * Get a value from cache or fetch it using the provided fetcher function
66
+ *
67
+ * @param key - Cache key
68
+ * @param fetcher - Async function to fetch data if not in cache
69
+ * @returns Promise resolving to the cached or fetched data
70
+ */
71
+ async get(key, fetcher) {
72
+ const now = Date.now();
73
+ const cached = this.cache.get(key);
74
+ if (cached) {
75
+ const age = now - cached.timestamp;
76
+ if (age < this.ttl) {
77
+ cached.accessCount++;
78
+ cached.lastAccessed = now;
79
+ this.stats.hits++;
80
+ this.cache.delete(key);
81
+ this.cache.set(key, cached);
82
+ return cached.data;
83
+ } else {
84
+ this.cache.delete(key);
85
+ }
86
+ }
87
+ this.stats.misses++;
88
+ const data = await fetcher();
89
+ this.set(key, data);
90
+ return data;
91
+ }
92
+ /**
93
+ * Set a value in the cache
94
+ *
95
+ * @param key - Cache key
96
+ * @param data - Data to cache
97
+ */
98
+ set(key, data) {
99
+ const now = Date.now();
100
+ if (this.cache.size >= this.maxSize && !this.cache.has(key)) {
101
+ this.evictLRU();
102
+ }
103
+ this.cache.set(key, {
104
+ data,
105
+ timestamp: now,
106
+ accessCount: 1,
107
+ lastAccessed: now
108
+ });
109
+ }
110
+ /**
111
+ * Evict the least recently used entry
112
+ */
113
+ evictLRU() {
114
+ const firstKey = this.cache.keys().next().value;
115
+ if (firstKey !== void 0) {
116
+ this.cache.delete(firstKey);
117
+ this.stats.evictions++;
118
+ }
119
+ }
120
+ /**
121
+ * Invalidate a specific cache entry or all entries
122
+ *
123
+ * @param key - Optional key to invalidate. If omitted, invalidates all entries
124
+ */
125
+ invalidate(key) {
126
+ if (key) {
127
+ this.cache.delete(key);
128
+ } else {
129
+ this.cache.clear();
130
+ }
131
+ }
132
+ /**
133
+ * Clear all cache entries and reset statistics
134
+ */
135
+ clear() {
136
+ this.cache.clear();
137
+ this.stats = {
138
+ hits: 0,
139
+ misses: 0,
140
+ evictions: 0
141
+ };
142
+ }
143
+ /**
144
+ * Get cache statistics
145
+ *
146
+ * @returns Cache statistics including hit rate
147
+ */
148
+ getStats() {
149
+ const total = this.stats.hits + this.stats.misses;
150
+ const hitRate = total > 0 ? this.stats.hits / total : 0;
151
+ return {
152
+ size: this.cache.size,
153
+ maxSize: this.maxSize,
154
+ hits: this.stats.hits,
155
+ misses: this.stats.misses,
156
+ evictions: this.stats.evictions,
157
+ hitRate
158
+ };
159
+ }
160
+ /**
161
+ * Check if a key exists in the cache (and is not expired)
162
+ *
163
+ * @param key - Cache key to check
164
+ * @returns true if the key exists and is not expired
165
+ */
166
+ has(key) {
167
+ const cached = this.cache.get(key);
168
+ if (!cached) {
169
+ return false;
170
+ }
171
+ const age = Date.now() - cached.timestamp;
172
+ if (age >= this.ttl) {
173
+ this.cache.delete(key);
174
+ return false;
175
+ }
176
+ return true;
177
+ }
178
+ };
179
+
180
+ // src/errors.ts
181
+ var ObjectStackError = class extends Error {
182
+ /**
183
+ * Create a new ObjectStackError
184
+ *
185
+ * @param message - Human-readable error message
186
+ * @param code - Unique error code for programmatic handling
187
+ * @param statusCode - Optional HTTP status code
188
+ * @param details - Optional additional error details for debugging
189
+ */
190
+ constructor(message, code, statusCode, details) {
191
+ super(message);
192
+ this.code = code;
193
+ this.statusCode = statusCode;
194
+ this.details = details;
195
+ this.name = "ObjectStackError";
196
+ if (Error.captureStackTrace) {
197
+ Error.captureStackTrace(this, this.constructor);
198
+ }
199
+ }
200
+ /**
201
+ * Convert error to JSON for logging/debugging
202
+ */
203
+ toJSON() {
204
+ return {
205
+ name: this.name,
206
+ message: this.message,
207
+ code: this.code,
208
+ statusCode: this.statusCode,
209
+ details: this.details,
210
+ stack: this.stack
211
+ };
212
+ }
213
+ };
214
+ var MetadataNotFoundError = class extends ObjectStackError {
215
+ constructor(objectName, details) {
216
+ super(
217
+ `Metadata not found for object: ${objectName}`,
218
+ "METADATA_NOT_FOUND",
219
+ 404,
220
+ { objectName, ...details }
221
+ );
222
+ this.name = "MetadataNotFoundError";
223
+ }
224
+ };
225
+ var BulkOperationError = class extends ObjectStackError {
226
+ /**
227
+ * Create a new BulkOperationError
228
+ *
229
+ * @param operation - The bulk operation that failed (create, update, delete)
230
+ * @param successCount - Number of successful operations
231
+ * @param failureCount - Number of failed operations
232
+ * @param errors - Array of individual errors
233
+ * @param details - Additional error details
234
+ */
235
+ constructor(operation, successCount, failureCount, errors, details) {
236
+ super(
237
+ `Bulk ${operation} operation failed: ${successCount} succeeded, ${failureCount} failed`,
238
+ "BULK_OPERATION_ERROR",
239
+ 500,
240
+ {
241
+ operation,
242
+ successCount,
243
+ failureCount,
244
+ errors,
245
+ ...details
246
+ }
247
+ );
248
+ this.successCount = successCount;
249
+ this.failureCount = failureCount;
250
+ this.errors = errors;
251
+ this.name = "BulkOperationError";
252
+ }
253
+ /**
254
+ * Get a summary of the bulk operation failure
255
+ */
256
+ getSummary() {
257
+ const total = this.successCount + this.failureCount;
258
+ const failureRate = total > 0 ? this.failureCount / total : 0;
259
+ return {
260
+ operation: this.details?.operation,
261
+ total,
262
+ successful: this.successCount,
263
+ failed: this.failureCount,
264
+ failureRate,
265
+ errors: this.errors
266
+ };
267
+ }
268
+ };
269
+ var ConnectionError = class extends ObjectStackError {
270
+ constructor(message, url, details, statusCode) {
271
+ super(
272
+ `Connection error: ${message}`,
273
+ "CONNECTION_ERROR",
274
+ statusCode || 503,
275
+ { url, ...details }
276
+ );
277
+ this.url = url;
278
+ this.name = "ConnectionError";
279
+ }
280
+ };
281
+ var AuthenticationError = class extends ObjectStackError {
282
+ constructor(message = "Authentication failed", details, statusCode) {
283
+ super(
284
+ message,
285
+ "AUTHENTICATION_ERROR",
286
+ statusCode || 401,
287
+ details
288
+ );
289
+ this.name = "AuthenticationError";
290
+ }
291
+ };
292
+ var ValidationError = class extends ObjectStackError {
293
+ /**
294
+ * Create a new ValidationError
295
+ *
296
+ * @param message - Human-readable error message
297
+ * @param field - The field that failed validation (optional)
298
+ * @param validationErrors - Array of validation error details
299
+ * @param details - Additional error details
300
+ */
301
+ constructor(message, field, validationErrors, details) {
302
+ super(
303
+ message,
304
+ "VALIDATION_ERROR",
305
+ 400,
306
+ {
307
+ field,
308
+ validationErrors,
309
+ ...details
310
+ }
311
+ );
312
+ this.field = field;
313
+ this.validationErrors = validationErrors;
314
+ this.name = "ValidationError";
315
+ }
316
+ /**
317
+ * Get all validation errors as a formatted list
318
+ */
319
+ getValidationErrors() {
320
+ return this.validationErrors || [];
321
+ }
322
+ };
323
+ function createErrorFromResponse(response, context) {
324
+ const status = response?.status || response?.statusCode || 500;
325
+ const message = response?.message || response?.statusText || "Unknown error";
326
+ const details = {
327
+ context,
328
+ response: {
329
+ status,
330
+ data: response?.data,
331
+ headers: response?.headers
332
+ }
333
+ };
334
+ switch (status) {
335
+ case 401:
336
+ return new AuthenticationError(message, details, 401);
337
+ case 403:
338
+ return new AuthenticationError(message, details, 403);
339
+ case 404:
340
+ if (context?.includes("metadata") || context?.includes("schema") || context?.includes("getObjectSchema")) {
341
+ const objectName = extractObjectName(context);
342
+ return new MetadataNotFoundError(objectName, details);
343
+ }
344
+ return new ObjectStackError(message, "NOT_FOUND", 404, details);
345
+ case 400:
346
+ return new ValidationError(message, void 0, response?.data?.errors, details);
347
+ case 503:
348
+ return new ConnectionError(message, response?.config?.url, details, 503);
349
+ case 504:
350
+ return new ConnectionError(message, response?.config?.url, details, 504);
351
+ default:
352
+ return new ObjectStackError(message, "UNKNOWN_ERROR", status, details);
353
+ }
354
+ }
355
+ function extractObjectName(context) {
356
+ if (!context) return "unknown";
357
+ const match = context.match(/\(([^)]+)\)/);
358
+ return match ? match[1] : "unknown";
359
+ }
360
+ function isObjectStackError(error) {
361
+ return error instanceof ObjectStackError;
362
+ }
363
+ function isErrorType(error, errorClass) {
364
+ return error instanceof errorClass;
365
+ }
366
+
367
+ // src/index.ts
31
368
  var ObjectStackAdapter = class {
32
369
  constructor(config) {
33
370
  __publicField(this, "client");
34
371
  __publicField(this, "connected", false);
372
+ __publicField(this, "metadataCache");
373
+ __publicField(this, "connectionState", "disconnected");
374
+ __publicField(this, "connectionStateListeners", []);
375
+ __publicField(this, "batchProgressListeners", []);
376
+ __publicField(this, "autoReconnect");
377
+ __publicField(this, "maxReconnectAttempts");
378
+ __publicField(this, "reconnectDelay");
379
+ __publicField(this, "reconnectAttempts", 0);
35
380
  this.client = new import_client.ObjectStackClient(config);
381
+ this.metadataCache = new MetadataCache(config.cache);
382
+ this.autoReconnect = config.autoReconnect ?? true;
383
+ this.maxReconnectAttempts = config.maxReconnectAttempts ?? 3;
384
+ this.reconnectDelay = config.reconnectDelay ?? 1e3;
36
385
  }
37
386
  /**
38
387
  * Ensure the client is connected to the server.
@@ -40,10 +389,105 @@ var ObjectStackAdapter = class {
40
389
  */
41
390
  async connect() {
42
391
  if (!this.connected) {
43
- await this.client.connect();
44
- this.connected = true;
392
+ this.setConnectionState("connecting");
393
+ try {
394
+ await this.client.connect();
395
+ this.connected = true;
396
+ this.reconnectAttempts = 0;
397
+ this.setConnectionState("connected");
398
+ } catch (error) {
399
+ const errorMessage = error instanceof Error ? error.message : "Failed to connect to ObjectStack server";
400
+ const connectionError = new ConnectionError(
401
+ errorMessage,
402
+ void 0,
403
+ { originalError: error }
404
+ );
405
+ this.setConnectionState("error", connectionError);
406
+ if (this.autoReconnect && this.reconnectAttempts < this.maxReconnectAttempts) {
407
+ await this.attemptReconnect();
408
+ } else {
409
+ throw connectionError;
410
+ }
411
+ }
45
412
  }
46
413
  }
414
+ /**
415
+ * Attempt to reconnect to the server with exponential backoff
416
+ */
417
+ async attemptReconnect() {
418
+ this.reconnectAttempts++;
419
+ this.setConnectionState("reconnecting");
420
+ const delay = this.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1);
421
+ await new Promise((resolve) => setTimeout(resolve, delay));
422
+ this.connected = false;
423
+ await this.connect();
424
+ }
425
+ /**
426
+ * Get the current connection state
427
+ */
428
+ getConnectionState() {
429
+ return this.connectionState;
430
+ }
431
+ /**
432
+ * Check if the adapter is currently connected
433
+ */
434
+ isConnected() {
435
+ return this.connected && this.connectionState === "connected";
436
+ }
437
+ /**
438
+ * Register a listener for connection state changes
439
+ */
440
+ onConnectionStateChange(listener) {
441
+ this.connectionStateListeners.push(listener);
442
+ return () => {
443
+ const index = this.connectionStateListeners.indexOf(listener);
444
+ if (index > -1) {
445
+ this.connectionStateListeners.splice(index, 1);
446
+ }
447
+ };
448
+ }
449
+ /**
450
+ * Register a listener for batch operation progress
451
+ */
452
+ onBatchProgress(listener) {
453
+ this.batchProgressListeners.push(listener);
454
+ return () => {
455
+ const index = this.batchProgressListeners.indexOf(listener);
456
+ if (index > -1) {
457
+ this.batchProgressListeners.splice(index, 1);
458
+ }
459
+ };
460
+ }
461
+ /**
462
+ * Set connection state and notify listeners
463
+ */
464
+ setConnectionState(state, error) {
465
+ this.connectionState = state;
466
+ const event = {
467
+ state,
468
+ timestamp: Date.now(),
469
+ error
470
+ };
471
+ this.connectionStateListeners.forEach((listener) => {
472
+ try {
473
+ listener(event);
474
+ } catch (err) {
475
+ console.error("Error in connection state listener:", err);
476
+ }
477
+ });
478
+ }
479
+ /**
480
+ * Emit batch progress event to listeners
481
+ */
482
+ emitBatchProgress(event) {
483
+ this.batchProgressListeners.forEach((listener) => {
484
+ try {
485
+ listener(event);
486
+ } catch (err) {
487
+ console.error("Error in batch progress listener:", err);
488
+ }
489
+ });
490
+ }
47
491
  /**
48
492
  * Find multiple records with query parameters.
49
493
  * Converts OData-style params to ObjectStack query options.
@@ -52,12 +496,23 @@ var ObjectStackAdapter = class {
52
496
  await this.connect();
53
497
  const queryOptions = this.convertQueryParams(params);
54
498
  const result = await this.client.data.find(resource, queryOptions);
499
+ if (Array.isArray(result)) {
500
+ return {
501
+ data: result,
502
+ total: result.length,
503
+ page: 1,
504
+ pageSize: result.length,
505
+ hasMore: false
506
+ };
507
+ }
508
+ const resultObj = result;
55
509
  return {
56
- data: result.value,
57
- total: result.count,
58
- page: params?.$skip ? Math.floor(params.$skip / (params.$top || 20)) + 1 : 1,
510
+ data: resultObj.value || [],
511
+ total: resultObj.count || (resultObj.value ? resultObj.value.length : 0),
512
+ // Calculate page number safely
513
+ page: params?.$skip && params.$top ? Math.floor(params.$skip / params.$top) + 1 : 1,
59
514
  pageSize: params?.$top,
60
- hasMore: result.value.length === params?.$top
515
+ hasMore: params?.$top ? (resultObj.value?.length || 0) === params.$top : false
61
516
  };
62
517
  }
63
518
  /**
@@ -98,28 +553,133 @@ var ObjectStackAdapter = class {
98
553
  return result.success;
99
554
  }
100
555
  /**
101
- * Bulk operations (optional implementation).
556
+ * Bulk operations with optimized batch processing and error handling.
557
+ * Emits progress events for tracking operation status.
558
+ *
559
+ * @param resource - Resource name
560
+ * @param operation - Operation type (create, update, delete)
561
+ * @param data - Array of records to process
562
+ * @returns Promise resolving to array of results
102
563
  */
103
564
  async bulk(resource, operation, data) {
104
565
  await this.connect();
105
- switch (operation) {
106
- case "create":
107
- return this.client.data.createMany(resource, data);
108
- case "delete": {
109
- const ids = data.map((item) => item.id).filter(Boolean);
110
- await this.client.data.deleteMany(resource, ids);
111
- return [];
112
- }
113
- case "update": {
114
- const results = await Promise.all(
115
- data.map(
116
- (item) => this.client.data.update(resource, String(item.id), item)
117
- )
118
- );
119
- return results;
566
+ if (!data || data.length === 0) {
567
+ return [];
568
+ }
569
+ const total = data.length;
570
+ let completed = 0;
571
+ let failed = 0;
572
+ const emitProgress = () => {
573
+ this.emitBatchProgress({
574
+ operation,
575
+ total,
576
+ completed,
577
+ failed,
578
+ percentage: total > 0 ? (completed + failed) / total * 100 : 0
579
+ });
580
+ };
581
+ try {
582
+ switch (operation) {
583
+ case "create": {
584
+ emitProgress();
585
+ const created = await this.client.data.createMany(resource, data);
586
+ completed = created.length;
587
+ failed = total - completed;
588
+ emitProgress();
589
+ return created;
590
+ }
591
+ case "delete": {
592
+ const ids = data.map((item) => item.id).filter(Boolean);
593
+ if (ids.length === 0) {
594
+ const errors = data.map((_, index) => ({
595
+ index,
596
+ error: `Missing ID for item at index ${index}`
597
+ }));
598
+ failed = data.length;
599
+ emitProgress();
600
+ throw new BulkOperationError("delete", 0, data.length, errors);
601
+ }
602
+ emitProgress();
603
+ await this.client.data.deleteMany(resource, ids);
604
+ completed = ids.length;
605
+ failed = total - completed;
606
+ emitProgress();
607
+ return [];
608
+ }
609
+ case "update": {
610
+ if (typeof this.client.data.updateMany === "function") {
611
+ try {
612
+ emitProgress();
613
+ const updateMany = this.client.data.updateMany;
614
+ const updated = await updateMany(resource, data);
615
+ completed = updated.length;
616
+ failed = total - completed;
617
+ emitProgress();
618
+ return updated;
619
+ } catch {
620
+ }
621
+ }
622
+ const results = [];
623
+ const errors = [];
624
+ for (let i = 0; i < data.length; i++) {
625
+ const item = data[i];
626
+ const id = item.id;
627
+ if (!id) {
628
+ errors.push({ index: i, error: "Missing ID" });
629
+ failed++;
630
+ emitProgress();
631
+ continue;
632
+ }
633
+ try {
634
+ const result = await this.client.data.update(resource, String(id), item);
635
+ results.push(result);
636
+ completed++;
637
+ emitProgress();
638
+ } catch (error) {
639
+ const errorMessage = error instanceof Error ? error.message : String(error);
640
+ errors.push({ index: i, error: errorMessage });
641
+ failed++;
642
+ emitProgress();
643
+ }
644
+ }
645
+ if (errors.length > 0) {
646
+ throw new BulkOperationError(
647
+ "update",
648
+ results.length,
649
+ errors.length,
650
+ errors,
651
+ { resource, totalRecords: data.length }
652
+ );
653
+ }
654
+ return results;
655
+ }
656
+ default:
657
+ throw new ObjectStackError(
658
+ `Unsupported bulk operation: ${operation}`,
659
+ "UNSUPPORTED_OPERATION",
660
+ 400
661
+ );
662
+ }
663
+ } catch (error) {
664
+ emitProgress();
665
+ if (error instanceof BulkOperationError) {
666
+ throw error;
120
667
  }
121
- default:
122
- throw new Error(`Unsupported bulk operation: ${operation}`);
668
+ if (error instanceof ObjectStackError) {
669
+ throw error;
670
+ }
671
+ const errorMessage = error instanceof Error ? error.message : String(error);
672
+ const errors = data.map((_, index) => ({
673
+ index,
674
+ error: errorMessage
675
+ }));
676
+ throw new BulkOperationError(
677
+ operation,
678
+ 0,
679
+ data.length,
680
+ errors,
681
+ { resource, originalError: error }
682
+ );
123
683
  }
124
684
  }
125
685
  /**
@@ -133,13 +693,26 @@ var ObjectStackAdapter = class {
133
693
  options.select = params.$select;
134
694
  }
135
695
  if (params.$filter) {
136
- options.filters = (0, import_core.convertFiltersToAST)(params.$filter);
696
+ if (Array.isArray(params.$filter)) {
697
+ options.filters = params.$filter;
698
+ } else {
699
+ options.filters = (0, import_core.convertFiltersToAST)(params.$filter);
700
+ }
137
701
  }
138
702
  if (params.$orderby) {
139
- const sortArray = Object.entries(params.$orderby).map(([field, order]) => {
140
- return order === "desc" ? `-${field}` : field;
141
- });
142
- options.sort = sortArray;
703
+ if (Array.isArray(params.$orderby)) {
704
+ options.sort = params.$orderby.map((item) => {
705
+ if (typeof item === "string") return item;
706
+ const field = item.field;
707
+ const order = item.order || "asc";
708
+ return order === "desc" ? `-${field}` : field;
709
+ });
710
+ } else {
711
+ const sortArray = Object.entries(params.$orderby).map(([field, order]) => {
712
+ return order === "desc" ? `-${field}` : field;
713
+ });
714
+ options.sort = sortArray;
715
+ }
143
716
  }
144
717
  if (params.$skip !== void 0) {
145
718
  options.skip = params.$skip;
@@ -151,6 +724,7 @@ var ObjectStackAdapter = class {
151
724
  }
152
725
  /**
153
726
  * Get object schema/metadata from ObjectStack.
727
+ * Uses caching to improve performance for repeated requests.
154
728
  *
155
729
  * @param objectName - Object name
156
730
  * @returns Promise resolving to the object schema
@@ -158,11 +732,23 @@ var ObjectStackAdapter = class {
158
732
  async getObjectSchema(objectName) {
159
733
  await this.connect();
160
734
  try {
161
- const schema = await this.client.meta.getObject(objectName);
735
+ const schema = await this.metadataCache.get(objectName, async () => {
736
+ const result = await this.client.meta.getObject(objectName);
737
+ if (result && result.item) {
738
+ return result.item;
739
+ }
740
+ return result;
741
+ });
162
742
  return schema;
163
743
  } catch (error) {
164
- console.error(`Failed to fetch schema for ${objectName}:`, error);
165
- throw error;
744
+ const errorObj = error;
745
+ if (errorObj?.status === 404 || errorObj?.statusCode === 404) {
746
+ throw new MetadataNotFoundError(objectName, { originalError: error });
747
+ }
748
+ if (error instanceof ObjectStackError) {
749
+ throw error;
750
+ }
751
+ throw createErrorFromResponse(errorObj, `getObjectSchema(${objectName})`);
166
752
  }
167
753
  }
168
754
  /**
@@ -171,12 +757,41 @@ var ObjectStackAdapter = class {
171
757
  getClient() {
172
758
  return this.client;
173
759
  }
760
+ /**
761
+ * Get cache statistics for monitoring performance.
762
+ */
763
+ getCacheStats() {
764
+ return this.metadataCache.getStats();
765
+ }
766
+ /**
767
+ * Invalidate metadata cache entries.
768
+ *
769
+ * @param key - Optional key to invalidate. If omitted, invalidates all entries.
770
+ */
771
+ invalidateCache(key) {
772
+ this.metadataCache.invalidate(key);
773
+ }
774
+ /**
775
+ * Clear all cache entries and statistics.
776
+ */
777
+ clearCache() {
778
+ this.metadataCache.clear();
779
+ }
174
780
  };
175
781
  function createObjectStackAdapter(config) {
176
782
  return new ObjectStackAdapter(config);
177
783
  }
178
784
  // Annotate the CommonJS export names for ESM import in node:
179
785
  0 && (module.exports = {
786
+ AuthenticationError,
787
+ BulkOperationError,
788
+ ConnectionError,
789
+ MetadataNotFoundError,
180
790
  ObjectStackAdapter,
181
- createObjectStackAdapter
791
+ ObjectStackError,
792
+ ValidationError,
793
+ createErrorFromResponse,
794
+ createObjectStackAdapter,
795
+ isErrorType,
796
+ isObjectStackError
182
797
  });