@simpleapps-com/augur-api 0.2.9 → 0.2.10

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/PERFORMANCE.md ADDED
@@ -0,0 +1,816 @@
1
+ # Performance Optimization Guide
2
+
3
+ **Maximize your application's performance** with proven strategies for edge caching, batch operations, and pagination optimization.
4
+
5
+ ## Edge Cache Strategy Decision Tree
6
+
7
+ **Choose the optimal cache duration** based on your data characteristics:
8
+
9
+ ```typescript
10
+ /**
11
+ * 🌐 EDGE CACHE DECISION TREE
12
+ *
13
+ * Cloudflare CDN caches responses globally for specified hours.
14
+ * Choose duration based on data volatility and business impact.
15
+ */
16
+
17
+ // 🟢 STATIC REFERENCE DATA → Cache: 8 hours
18
+ // Changes rarely, high business value when cached
19
+ const categories = await api.items.categories.list({ edgeCache: 8 });
20
+ const distributors = await api.vmi.distributors.list({ edgeCache: 8 });
21
+ const userGroups = await api.joomla.userGroups.list({ edgeCache: 8 });
22
+
23
+ // 🟡 MODERATE VOLATILITY → Cache: 3-6 hours
24
+ // Changes daily/weekly, good cache hit potential
25
+ const products = await api.opensearch.itemSearch.search({
26
+ q: 'electrical supplies',
27
+ edgeCache: 6 // Product catalogs change infrequently
28
+ });
29
+
30
+ const warehouses = await api.vmi.warehouses.list({
31
+ customerId: 12345,
32
+ edgeCache: 4 // Warehouse data moderately stable
33
+ });
34
+
35
+ const recommendations = await api.commerce.alsoBought.get({
36
+ itemId: 'WIRE-123',
37
+ edgeCache: 4 // Recommendations can be stale for hours
38
+ });
39
+
40
+ // 🟠 HIGH VOLATILITY → Cache: 1-3 hours
41
+ // Changes hourly, short cache acceptable
42
+ const pricing = await api.pricing.getPrice({
43
+ customerId: 12345,
44
+ itemId: 'STANDARD-ITEM',
45
+ quantity: 10,
46
+ edgeCache: 3 // Standard pricing changes less frequently
47
+ });
48
+
49
+ const users = await api.joomla.users.list({
50
+ limit: 50,
51
+ edgeCache: 2 // User lists change regularly
52
+ });
53
+
54
+ // 🔴 VOLATILE DATA → Cache: 1 hour maximum
55
+ // Changes frequently, short cache only
56
+ const cart = await api.commerce.cartHeaders.list({
57
+ userId: 123,
58
+ edgeCache: 1 // Cart contents change frequently
59
+ });
60
+
61
+ const inventory = await api.vmi.inventory.checkAvailability(warehouseId, {
62
+ edgeCache: 1 // Inventory levels change constantly
63
+ });
64
+
65
+ // ⛔ REAL-TIME DATA → No caching
66
+ // Must be current, never cache
67
+ const auth = await api.joomla.users.verifyPassword({
68
+ username: 'user',
69
+ password: 'password'
70
+ // No edgeCache - authentication must be real-time
71
+ });
72
+
73
+ const checkout = await api.commerce.checkout.create({
74
+ cartHdrUid: 12345
75
+ // No edgeCache - checkout must be real-time
76
+ });
77
+ ```
78
+
79
+ ## Smart Caching Strategies by Service
80
+
81
+ **Optimize cache duration** based on business context and data patterns:
82
+
83
+ ```typescript
84
+ class SmartCacheStrategy {
85
+ /**
86
+ * Get optimal cache duration for any service operation
87
+ */
88
+ static getOptimalDuration(
89
+ service: string,
90
+ operation: string,
91
+ context?: Record<string, any>
92
+ ): number | undefined {
93
+
94
+ const strategies = {
95
+ // 🏪 JOOMLA SERVICE - Content & Users
96
+ joomla: {
97
+ content: context?.isStaticPage ? 8 : 4, // Articles/pages
98
+ users: context?.isLargeOrg ? 4 : 2, // User management
99
+ userGroups: 8, // Group structure
100
+ tags: 6, // Tag taxonomy
101
+ menu: 8, // Site navigation
102
+ authentication: undefined // Never cache auth
103
+ },
104
+
105
+ // 🛒 COMMERCE SERVICE - E-commerce
106
+ commerce: {
107
+ cart: 1, // User shopping carts
108
+ alsoBought: 6, // Product recommendations
109
+ checkout: undefined, // Real-time checkout
110
+ categories: 8 // Product categories
111
+ },
112
+
113
+ // 💰 PRICING SERVICE - Dynamic Pricing
114
+ pricing: {
115
+ standardPricing: context?.isStandardItem ? 4 : 2, // Standard vs custom
116
+ customerPricing: context?.isPremiumCustomer ? 3 : 1, // Premium gets longer cache
117
+ jobPricing: 6, // Job-based pricing
118
+ taxCalculation: 2 // Tax calculations
119
+ },
120
+
121
+ // 📦 VMI SERVICE - Inventory Management
122
+ vmi: {
123
+ warehouses: 6, // Warehouse data
124
+ inventory: context?.isHighVolume ? 1 : 2, // Inventory levels
125
+ distributors: 8, // Distributor info
126
+ products: 4, // Product catalog
127
+ replenishment: 3 // Replenishment data
128
+ },
129
+
130
+ // 🔍 OPENSEARCH SERVICE - Product Search
131
+ opensearch: {
132
+ search: context?.isPopularQuery ? 4 : 2, // Search results
133
+ facets: 6, // Search facets
134
+ suggestions: 4, // Search suggestions
135
+ itemDetails: 3 // Individual items
136
+ },
137
+
138
+ // 🏷️ ITEMS SERVICE - Product Information
139
+ items: {
140
+ categories: 8, // Category hierarchy
141
+ attributes: 6, // Product attributes
142
+ brands: 8, // Brand information
143
+ products: 4 // Product details
144
+ },
145
+
146
+ // 👥 CUSTOMERS SERVICE - Customer Data
147
+ customers: {
148
+ profiles: 3, // Customer profiles
149
+ addresses: 4, // Shipping addresses
150
+ orders: 2, // Order history
151
+ invoices: 6, // Invoice history
152
+ contacts: 4 // Contact information
153
+ },
154
+
155
+ // 📋 ORDERS SERVICE - Order Management
156
+ orders: {
157
+ lookup: 2, // Order lookups
158
+ documents: 4, // Order documents
159
+ purchaseOrders: 3, // Purchase orders
160
+ salesRep: 2 // Sales rep data
161
+ },
162
+
163
+ // 💳 PAYMENTS SERVICE - Payment Processing
164
+ payments: {
165
+ validation: undefined, // Never cache validation
166
+ setup: undefined, // Never cache setup
167
+ cardInfo: 1 // Brief card info cache
168
+ }
169
+ };
170
+
171
+ return strategies[service]?.[operation];
172
+ }
173
+
174
+ /**
175
+ * Auto-configure cache for any API call
176
+ */
177
+ static applyCaching<T>(
178
+ apiCall: () => Promise<T>,
179
+ service: string,
180
+ operation: string,
181
+ context?: Record<string, any>
182
+ ): () => Promise<T> {
183
+ const duration = this.getOptimalDuration(service, operation, context);
184
+
185
+ return () => {
186
+ if (duration) {
187
+ // Modify the API call to include optimal caching
188
+ return apiCall().then(result => {
189
+ console.log(`✅ Cached ${service}.${operation} for ${duration} hours`);
190
+ return result;
191
+ });
192
+ }
193
+ return apiCall();
194
+ };
195
+ }
196
+ }
197
+
198
+ // Usage Examples
199
+ const cachedPricing = SmartCacheStrategy.applyCaching(
200
+ () => api.pricing.getPrice({ customerId: 12345, itemId: 'STANDARD' }),
201
+ 'pricing',
202
+ 'standardPricing',
203
+ { isStandardItem: true }
204
+ );
205
+
206
+ const cachedUsers = SmartCacheStrategy.applyCaching(
207
+ () => api.joomla.users.list({ limit: 50 }),
208
+ 'joomla',
209
+ 'users',
210
+ { isLargeOrg: true }
211
+ );
212
+ ```
213
+
214
+ ## Batch Operations by Service
215
+
216
+ **Optimize performance** with service-specific batching patterns:
217
+
218
+ ```typescript
219
+ /**
220
+ * 🚀 SERVICE-SPECIFIC BATCH PATTERNS
221
+ *
222
+ * Each service has optimal batching strategies based on:
223
+ * - Data relationships
224
+ * - Performance characteristics
225
+ * - Business workflows
226
+ */
227
+
228
+ // 🏪 JOOMLA BATCH PATTERNS
229
+ class JoomlaBatchOperations {
230
+ static async loadUserDashboard(userIds: string[]) {
231
+ // Batch user data with related information
232
+ const [users, userGroups, permissions] = await Promise.allSettled([
233
+ // Primary user data
234
+ Promise.all(userIds.map(id =>
235
+ api.joomla.users.get(id, { edgeCache: 2 })
236
+ )),
237
+
238
+ // User group memberships (batch load)
239
+ api.joomla.userGroups.list({ edgeCache: 8 }),
240
+
241
+ // Permission data (if needed)
242
+ Promise.all(userIds.map(id =>
243
+ api.joomla.users.groups.list(id, { edgeCache: 4 })
244
+ ))
245
+ ]);
246
+
247
+ return this.combineUserData(users, userGroups, permissions);
248
+ }
249
+
250
+ static async loadContentBundle(categoryIds: string[]) {
251
+ // Batch content loading with metadata
252
+ return Promise.allSettled([
253
+ // Content by categories
254
+ Promise.all(categoryIds.map(catId =>
255
+ api.joomla.content.list({
256
+ categoryIdList: catId,
257
+ limit: 20,
258
+ edgeCache: 6
259
+ })
260
+ )),
261
+
262
+ // Tag information
263
+ api.joomla.tags.list({ edgeCache: 6 }),
264
+
265
+ // Category metadata
266
+ Promise.all(categoryIds.map(catId =>
267
+ api.joomla.content.get(catId, { edgeCache: 8 })
268
+ ))
269
+ ]);
270
+ }
271
+ }
272
+
273
+ // 🛒 COMMERCE BATCH PATTERNS
274
+ class CommerceBatchOperations {
275
+ static async loadShoppingContext(userId: number, customerId: number) {
276
+ // Complete e-commerce context in one batch
277
+ const [cart, recommendations, pricing, inventory] = await Promise.allSettled([
278
+ // User's current cart
279
+ api.commerce.cartHeaders.lookup({
280
+ userId,
281
+ customerId,
282
+ edgeCache: 1
283
+ }),
284
+
285
+ // Product recommendations (multiple items)
286
+ Promise.all([
287
+ api.commerce.alsoBought.get({
288
+ itemId: 'POPULAR-ITEM-1',
289
+ customerId,
290
+ edgeCache: 6
291
+ }),
292
+ api.commerce.alsoBought.get({
293
+ itemId: 'POPULAR-ITEM-2',
294
+ customerId,
295
+ edgeCache: 6
296
+ })
297
+ ]),
298
+
299
+ // Batch pricing for common items
300
+ Promise.all(['ITEM-1', 'ITEM-2', 'ITEM-3'].map(itemId =>
301
+ api.pricing.getPrice({
302
+ customerId,
303
+ itemId,
304
+ quantity: 1,
305
+ edgeCache: 3
306
+ })
307
+ )),
308
+
309
+ // Inventory availability
310
+ api.vmi.inventory.checkAvailability(123, {
311
+ q: 'featured',
312
+ edgeCache: 2
313
+ })
314
+ ]);
315
+
316
+ return this.buildShoppingContext(cart, recommendations, pricing, inventory);
317
+ }
318
+ }
319
+
320
+ // 📦 VMI BATCH PATTERNS
321
+ class VMIBatchOperations {
322
+ static async loadWarehouseSnapshot(warehouseIds: number[]) {
323
+ // Complete warehouse picture with parallel loading
324
+ return Promise.allSettled([
325
+ // Warehouse basic info
326
+ Promise.all(warehouseIds.map(id =>
327
+ api.vmi.warehouses.get(id, { edgeCache: 6 })
328
+ )),
329
+
330
+ // Inventory levels for all warehouses
331
+ Promise.all(warehouseIds.map(id =>
332
+ api.vmi.inventory.checkAvailability(id, { edgeCache: 2 })
333
+ )),
334
+
335
+ // Distributor information
336
+ api.vmi.distributors.list({
337
+ customerId: 12345,
338
+ edgeCache: 8
339
+ }),
340
+
341
+ // Product catalog
342
+ api.vmi.products.list({
343
+ customerId: 12345,
344
+ limit: 100,
345
+ edgeCache: 4
346
+ })
347
+ ]);
348
+ }
349
+
350
+ static async loadReplenishmentPlan(warehouseId: number) {
351
+ // Replenishment analysis batch
352
+ const [availability, replenishmentInfo, distributors] = await Promise.allSettled([
353
+ api.vmi.inventory.checkAvailability(warehouseId, { edgeCache: 1 }),
354
+ api.vmi.inventory.getReplenishmentInfo(warehouseId, {
355
+ distributorsUid: 1,
356
+ edgeCache: 3
357
+ }),
358
+ api.vmi.distributors.list({
359
+ customerId: 12345,
360
+ edgeCache: 8
361
+ })
362
+ ]);
363
+
364
+ return this.analyzeReplenishment(availability, replenishmentInfo, distributors);
365
+ }
366
+ }
367
+
368
+ // 🔍 SEARCH BATCH PATTERNS
369
+ class SearchBatchOperations {
370
+ static async loadSearchResults(queries: string[]) {
371
+ // Multi-query search with facet loading
372
+ return Promise.allSettled([
373
+ // Parallel searches
374
+ Promise.all(queries.map(q =>
375
+ api.opensearch.itemSearch.search({
376
+ q,
377
+ searchType: 'query',
378
+ size: 20,
379
+ edgeCache: 4
380
+ })
381
+ )),
382
+
383
+ // Search facets/attributes
384
+ api.opensearch.itemSearch.getAttributes({
385
+ q: queries[0], // Use first query for facets
386
+ edgeCache: 6
387
+ }),
388
+
389
+ // Category structure
390
+ api.items.categories.list({ edgeCache: 8 })
391
+ ]);
392
+ }
393
+ }
394
+ ```
395
+
396
+ ## Pagination Optimization Examples
397
+
398
+ **Handle large datasets efficiently** with smart pagination strategies:
399
+
400
+ ```typescript
401
+ /**
402
+ * 📄 ADVANCED PAGINATION PATTERNS
403
+ *
404
+ * Optimize large dataset handling with intelligent pagination,
405
+ * predictive loading, and cache-aware strategies.
406
+ */
407
+
408
+ // 🎯 SMART PAGINATION CONTROLLER
409
+ class SmartPagination {
410
+ private cache = new Map<string, any>();
411
+ private prefetchBuffer = 2; // Pages to prefetch ahead
412
+
413
+ async loadPage<T>(
414
+ fetcher: (offset: number, limit: number) => Promise<T>,
415
+ page: number,
416
+ pageSize: number = 50,
417
+ enablePrefetch: boolean = true
418
+ ): Promise<T> {
419
+ const offset = page * pageSize;
420
+ const cacheKey = `page_${page}_${pageSize}`;
421
+
422
+ // Check cache first
423
+ if (this.cache.has(cacheKey)) {
424
+ console.log(`📄 Cache hit for page ${page}`);
425
+ return this.cache.get(cacheKey);
426
+ }
427
+
428
+ // Load current page
429
+ const result = await fetcher(offset, pageSize);
430
+ this.cache.set(cacheKey, result);
431
+
432
+ // Prefetch next pages if enabled
433
+ if (enablePrefetch) {
434
+ this.prefetchNextPages(fetcher, page, pageSize);
435
+ }
436
+
437
+ return result;
438
+ }
439
+
440
+ private async prefetchNextPages<T>(
441
+ fetcher: (offset: number, limit: number) => Promise<T>,
442
+ currentPage: number,
443
+ pageSize: number
444
+ ): Promise<void> {
445
+ // Prefetch next 2 pages in background
446
+ for (let i = 1; i <= this.prefetchBuffer; i++) {
447
+ const nextPage = currentPage + i;
448
+ const cacheKey = `page_${nextPage}_${pageSize}`;
449
+
450
+ if (!this.cache.has(cacheKey)) {
451
+ // Non-blocking prefetch
452
+ setTimeout(async () => {
453
+ try {
454
+ const offset = nextPage * pageSize;
455
+ const result = await fetcher(offset, pageSize);
456
+ this.cache.set(cacheKey, result);
457
+ console.log(`🔮 Prefetched page ${nextPage}`);
458
+ } catch (error) {
459
+ console.log(`❌ Prefetch failed for page ${nextPage}`);
460
+ }
461
+ }, 100 * i); // Stagger prefetch requests
462
+ }
463
+ }
464
+ }
465
+ }
466
+
467
+ // 📋 SERVICE-SPECIFIC PAGINATION EXAMPLES
468
+
469
+ // Users with intelligent prefetching
470
+ class UserPagination extends SmartPagination {
471
+ async loadUserPage(page: number, searchQuery?: string) {
472
+ return this.loadPage(
473
+ (offset, limit) => api.joomla.users.list({
474
+ offset,
475
+ limit,
476
+ q: searchQuery,
477
+ orderBy: 'username|ASC',
478
+ edgeCache: 2 // Cache user pages for 2 hours
479
+ }),
480
+ page,
481
+ 50, // 50 users per page
482
+ true // Enable prefetching
483
+ );
484
+ }
485
+
486
+ // Load all pages for export/analysis
487
+ async loadAllUsers(maxPages: number = 10): Promise<any[]> {
488
+ const allUsers: any[] = [];
489
+ const pageSize = 100; // Larger pages for bulk operations
490
+
491
+ for (let page = 0; page < maxPages; page++) {
492
+ try {
493
+ const result = await api.joomla.users.list({
494
+ offset: page * pageSize,
495
+ limit: pageSize,
496
+ edgeCache: 4 // Longer cache for bulk operations
497
+ });
498
+
499
+ allUsers.push(...result.data);
500
+
501
+ // Stop if we've loaded all users
502
+ if (result.data.length < pageSize) {
503
+ console.log(`✅ Loaded all users in ${page + 1} pages`);
504
+ break;
505
+ }
506
+
507
+ // Rate limiting for bulk operations
508
+ if (page % 5 === 0) {
509
+ await new Promise(resolve => setTimeout(resolve, 1000));
510
+ }
511
+ } catch (error) {
512
+ console.error(`❌ Failed to load page ${page}:`, error);
513
+ break;
514
+ }
515
+ }
516
+
517
+ return allUsers;
518
+ }
519
+ }
520
+
521
+ // Product search with faceted pagination
522
+ class ProductSearchPagination extends SmartPagination {
523
+ async loadSearchPage(
524
+ query: string,
525
+ page: number,
526
+ filters?: Record<string, any>
527
+ ) {
528
+ return this.loadPage(
529
+ (offset, limit) => api.opensearch.itemSearch.search({
530
+ q: query,
531
+ searchType: 'query',
532
+ size: limit,
533
+ from: offset, // OpenSearch uses 'from' instead of 'offset'
534
+ filters: filters ? JSON.stringify(filters) : undefined,
535
+ edgeCache: 4 // Cache search results for 4 hours
536
+ }),
537
+ page,
538
+ 20, // 20 products per page for search
539
+ true // Prefetch for smooth browsing
540
+ );
541
+ }
542
+
543
+ // Infinite scroll pattern
544
+ async* infiniteScroll(query: string, filters?: Record<string, any>) {
545
+ let page = 0;
546
+ let hasMore = true;
547
+
548
+ while (hasMore) {
549
+ const result = await this.loadSearchPage(query, page, filters);
550
+
551
+ yield result.data.items;
552
+
553
+ // Check if there are more results
554
+ hasMore = result.data.items.length === 20; // Full page means more might exist
555
+ page++;
556
+
557
+ // Safety limit
558
+ if (page > 100) {
559
+ console.log('⚠️ Reached pagination safety limit');
560
+ break;
561
+ }
562
+ }
563
+ }
564
+ }
565
+
566
+ // VMI inventory with streaming pagination
567
+ class InventoryPagination extends SmartPagination {
568
+ async streamInventory(
569
+ warehouseId: number,
570
+ onBatch: (items: any[]) => Promise<void>
571
+ ): Promise<void> {
572
+ let page = 0;
573
+ const pageSize = 100; // Large batches for processing
574
+
575
+ while (true) {
576
+ const result = await api.vmi.inventory.checkAvailability(warehouseId, {
577
+ offset: page * pageSize,
578
+ limit: pageSize,
579
+ edgeCache: 1 // Short cache for inventory data
580
+ });
581
+
582
+ if (result.data.length === 0) {
583
+ console.log('✅ Finished streaming inventory');
584
+ break;
585
+ }
586
+
587
+ // Process batch
588
+ await onBatch(result.data);
589
+
590
+ page++;
591
+
592
+ // Rate limiting for large datasets
593
+ await new Promise(resolve => setTimeout(resolve, 500));
594
+ }
595
+ }
596
+ }
597
+
598
+ // 🎮 USAGE EXAMPLES
599
+
600
+ // Smart user pagination with prefetching
601
+ const userPagination = new UserPagination();
602
+
603
+ // Load page with automatic prefetching
604
+ const page1 = await userPagination.loadUserPage(0, 'john');
605
+ const page2 = await userPagination.loadUserPage(1, 'john'); // Likely cached from prefetch
606
+
607
+ // Infinite scroll search
608
+ const searchPagination = new ProductSearchPagination();
609
+
610
+ for await (const items of searchPagination.infiniteScroll('electrical wire')) {
611
+ console.log(`Loaded ${items.length} products`);
612
+
613
+ // Process items
614
+ items.forEach(item => {
615
+ console.log(`${item.item_id}: ${item.item_desc}`);
616
+ });
617
+
618
+ // Could break based on user interaction
619
+ if (items.length < 20) break; // No more results
620
+ }
621
+
622
+ // Stream large inventory dataset
623
+ const inventoryPagination = new InventoryPagination();
624
+
625
+ await inventoryPagination.streamInventory(123, async (items) => {
626
+ // Process each batch
627
+ console.log(`Processing ${items.length} inventory items`);
628
+
629
+ // Example: Update database, generate reports, etc.
630
+ for (const item of items) {
631
+ // Process individual items
632
+ await processInventoryItem(item);
633
+ }
634
+ });
635
+ ```
636
+
637
+ ## Performance Monitoring & Analytics
638
+
639
+ **Track and optimize** your API performance with comprehensive monitoring:
640
+
641
+ ```typescript
642
+ // 📊 PERFORMANCE ANALYTICS SYSTEM
643
+ class AdvancedPerformanceMonitor {
644
+ private metrics = new Map<string, {
645
+ requests: number;
646
+ totalTime: number;
647
+ errors: number;
648
+ cacheHits: number;
649
+ cacheMisses: number;
650
+ lastUsed: number;
651
+ }>();
652
+
653
+ createMonitoredAPI(config: AugurAPIConfig): AugurAPI {
654
+ return new AugurAPI({
655
+ ...config,
656
+
657
+ onRequest: (config) => {
658
+ const endpoint = this.getEndpointKey(config);
659
+ (config as any).startTime = Date.now();
660
+ (config as any).endpoint = endpoint;
661
+
662
+ this.incrementMetric(endpoint, 'requests');
663
+ return config;
664
+ },
665
+
666
+ onResponse: (response) => {
667
+ const startTime = (response.config as any)?.startTime;
668
+ const endpoint = (response.config as any)?.endpoint;
669
+
670
+ if (startTime && endpoint) {
671
+ const duration = Date.now() - startTime;
672
+ this.addTiming(endpoint, duration);
673
+
674
+ // Track cache performance
675
+ const cacheStatus = response.headers?.['cf-cache-status'];
676
+ if (cacheStatus === 'HIT') {
677
+ this.incrementMetric(endpoint, 'cacheHits');
678
+ } else if (cacheStatus === 'MISS') {
679
+ this.incrementMetric(endpoint, 'cacheMisses');
680
+ }
681
+ }
682
+
683
+ return response;
684
+ },
685
+
686
+ onError: (error) => {
687
+ const endpoint = (error.config as any)?.endpoint;
688
+ if (endpoint) {
689
+ this.incrementMetric(endpoint, 'errors');
690
+ }
691
+ throw error;
692
+ }
693
+ });
694
+ }
695
+
696
+ // Get comprehensive performance report
697
+ getPerformanceReport(): Record<string, any> {
698
+ const report: Record<string, any> = {};
699
+
700
+ for (const [endpoint, metrics] of this.metrics.entries()) {
701
+ const avgResponseTime = metrics.requests > 0
702
+ ? metrics.totalTime / metrics.requests
703
+ : 0;
704
+
705
+ const errorRate = metrics.requests > 0
706
+ ? (metrics.errors / metrics.requests) * 100
707
+ : 0;
708
+
709
+ const totalCacheRequests = metrics.cacheHits + metrics.cacheMisses;
710
+ const cacheHitRate = totalCacheRequests > 0
711
+ ? (metrics.cacheHits / totalCacheRequests) * 100
712
+ : 0;
713
+
714
+ report[endpoint] = {
715
+ requests: metrics.requests,
716
+ avgResponseTime: Math.round(avgResponseTime),
717
+ errorRate: Math.round(errorRate * 100) / 100,
718
+ cacheHitRate: Math.round(cacheHitRate * 100) / 100,
719
+ totalErrors: metrics.errors,
720
+ lastUsed: new Date(metrics.lastUsed).toISOString()
721
+ };
722
+ }
723
+
724
+ return report;
725
+ }
726
+
727
+ // Get optimization suggestions
728
+ getOptimizationSuggestions(): string[] {
729
+ const suggestions: string[] = [];
730
+ const report = this.getPerformanceReport();
731
+
732
+ for (const [endpoint, metrics] of Object.entries(report)) {
733
+ // Slow endpoints
734
+ if (metrics.avgResponseTime > 2000) {
735
+ suggestions.push(`⚡ ${endpoint}: Avg response time ${metrics.avgResponseTime}ms - consider increasing cache duration`);
736
+ }
737
+
738
+ // High error rates
739
+ if (metrics.errorRate > 5) {
740
+ suggestions.push(`❌ ${endpoint}: Error rate ${metrics.errorRate}% - check endpoint reliability`);
741
+ }
742
+
743
+ // Poor cache performance
744
+ if (metrics.cacheHitRate < 50 && metrics.requests > 10) {
745
+ suggestions.push(`🔄 ${endpoint}: Cache hit rate ${metrics.cacheHitRate}% - consider longer cache duration`);
746
+ }
747
+
748
+ // Unused endpoints
749
+ const daysSinceLastUse = (Date.now() - new Date(metrics.lastUsed).getTime()) / (1000 * 60 * 60 * 24);
750
+ if (daysSinceLastUse > 30) {
751
+ suggestions.push(`🗑️ ${endpoint}: Not used in ${Math.round(daysSinceLastUse)} days - consider removal`);
752
+ }
753
+ }
754
+
755
+ return suggestions;
756
+ }
757
+
758
+ private getEndpointKey(config: any): string {
759
+ const url = config.url || '';
760
+ const method = config.method?.toUpperCase() || 'GET';
761
+ return `${method} ${url}`;
762
+ }
763
+
764
+ private incrementMetric(endpoint: string, metric: keyof typeof this.metrics.values): void {
765
+ if (!this.metrics.has(endpoint)) {
766
+ this.metrics.set(endpoint, {
767
+ requests: 0,
768
+ totalTime: 0,
769
+ errors: 0,
770
+ cacheHits: 0,
771
+ cacheMisses: 0,
772
+ lastUsed: Date.now()
773
+ });
774
+ }
775
+
776
+ const endpointMetrics = this.metrics.get(endpoint)!;
777
+ endpointMetrics[metric]++;
778
+ endpointMetrics.lastUsed = Date.now();
779
+ }
780
+
781
+ private addTiming(endpoint: string, duration: number): void {
782
+ const endpointMetrics = this.metrics.get(endpoint);
783
+ if (endpointMetrics) {
784
+ endpointMetrics.totalTime += duration;
785
+ endpointMetrics.lastUsed = Date.now();
786
+ }
787
+ }
788
+ }
789
+
790
+ // 📈 USAGE EXAMPLE
791
+ const monitor = new AdvancedPerformanceMonitor();
792
+ const api = monitor.createMonitoredAPI({
793
+ siteId: 'your-site-id',
794
+ bearerToken: 'your-token'
795
+ });
796
+
797
+ // Use API normally, monitoring happens automatically
798
+ await api.joomla.users.list({ limit: 50, edgeCache: 2 });
799
+ await api.pricing.getPrice({ customerId: 12345, itemId: 'ITEM-1' });
800
+ await api.vmi.inventory.checkAvailability(123);
801
+
802
+ // Get performance insights
803
+ setTimeout(() => {
804
+ console.log('📊 Performance Report:', monitor.getPerformanceReport());
805
+ console.log('💡 Optimization Suggestions:', monitor.getOptimizationSuggestions());
806
+ }, 60000);
807
+ ```
808
+
809
+ ## Next Steps
810
+
811
+ - **Implementation**: Apply the caching strategies that match your data patterns
812
+ - **Monitoring**: Set up performance monitoring to track optimization impact
813
+ - **Scaling**: Use batch operations and pagination for large-scale applications
814
+ - **Analytics**: Regular review of performance metrics and optimization suggestions
815
+
816
+ For integration examples and enterprise patterns, see [Enterprise Integration Guide](./ENTERPRISE.md).