@json-to-office/shared 0.35.0 → 1.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.
@@ -1,741 +0,0 @@
1
- // src/cache/manager.ts
2
- import { EventEmitter } from "events";
3
- var ComponentCacheManager = class extends EventEmitter {
4
- config;
5
- stats;
6
- constructor(config) {
7
- super();
8
- this.config = config;
9
- this.stats = this.initializeStats();
10
- }
11
- /**
12
- * Get cache statistics with deep immutability
13
- */
14
- getStats() {
15
- const componentStatsCopy = /* @__PURE__ */ new Map();
16
- this.stats.componentStats.forEach((value, key) => {
17
- componentStatsCopy.set(key, { ...value });
18
- });
19
- return {
20
- ...this.stats,
21
- componentStats: componentStatsCopy
22
- };
23
- }
24
- /**
25
- * Get configuration with deep immutability
26
- */
27
- getConfig() {
28
- const configCopy = {
29
- enabled: this.config.enabled,
30
- evictionPolicy: this.config.evictionPolicy,
31
- memory: { ...this.config.memory },
32
- performance: { ...this.config.performance }
33
- };
34
- if (this.config.disk) {
35
- configCopy.disk = { ...this.config.disk };
36
- }
37
- if (this.config.componentConfig) {
38
- configCopy.componentConfig = {};
39
- for (const [key, value] of Object.entries(this.config.componentConfig)) {
40
- configCopy.componentConfig[key] = { ...value };
41
- }
42
- }
43
- return configCopy;
44
- }
45
- /**
46
- * Get multiple entries (batch operation)
47
- */
48
- async getMany(keys) {
49
- const results = /* @__PURE__ */ new Map();
50
- if (this.config.performance.parallelProcessing) {
51
- const promises = keys.map(async (key) => {
52
- const value = await this.get(key);
53
- if (value) results.set(key, value);
54
- });
55
- await Promise.all(promises);
56
- } else {
57
- for (const key of keys) {
58
- const value = await this.get(key);
59
- if (value) results.set(key, value);
60
- }
61
- }
62
- return results;
63
- }
64
- /**
65
- * Set multiple entries (batch operation)
66
- */
67
- async setMany(entries) {
68
- if (this.config.performance.parallelProcessing) {
69
- const promises = entries.map(([key, value]) => this.set(key, value));
70
- await Promise.all(promises);
71
- } else {
72
- for (const [key, value] of entries) {
73
- await this.set(key, value);
74
- }
75
- }
76
- }
77
- /**
78
- * Delete multiple entries
79
- */
80
- async deleteMany(keys) {
81
- let deleted = 0;
82
- if (this.config.performance.parallelProcessing) {
83
- const results = await Promise.all(keys.map((key) => this.delete(key)));
84
- deleted = results.filter(Boolean).length;
85
- } else {
86
- for (const key of keys) {
87
- if (await this.delete(key)) {
88
- deleted++;
89
- }
90
- }
91
- }
92
- return deleted;
93
- }
94
- /**
95
- * Initialize statistics
96
- */
97
- initializeStats() {
98
- return {
99
- entries: 0,
100
- totalSize: 0,
101
- hitRate: 0,
102
- missRate: 0,
103
- totalHits: 0,
104
- totalMisses: 0,
105
- avgResponseTime: 0,
106
- evictions: 0,
107
- componentStats: /* @__PURE__ */ new Map()
108
- };
109
- }
110
- /**
111
- * Update statistics on cache hit
112
- */
113
- updateHitStats(key, component) {
114
- this.stats.totalHits++;
115
- this.updateComponentStats(component.componentName, "hit");
116
- this.recalculateRates();
117
- this.emit("hit", key, component);
118
- }
119
- /**
120
- * Update statistics on cache miss
121
- */
122
- updateMissStats(key, componentName) {
123
- this.stats.totalMisses++;
124
- if (componentName) {
125
- this.updateComponentStats(componentName, "miss");
126
- }
127
- this.recalculateRates();
128
- this.emit("miss", key);
129
- }
130
- /**
131
- * Update component-specific statistics
132
- */
133
- updateComponentStats(componentName, event) {
134
- if (!this.stats.componentStats.has(componentName)) {
135
- this.stats.componentStats.set(componentName, {
136
- name: componentName,
137
- hits: 0,
138
- misses: 0,
139
- avgProcessTime: 0,
140
- avgSize: 0,
141
- entries: 0
142
- });
143
- }
144
- const stats = this.stats.componentStats.get(componentName);
145
- if (event === "hit") {
146
- stats.hits++;
147
- } else {
148
- stats.misses++;
149
- }
150
- }
151
- /**
152
- * Recalculate hit/miss rates
153
- */
154
- recalculateRates() {
155
- const total = this.stats.totalHits + this.stats.totalMisses;
156
- if (total > 0) {
157
- this.stats.hitRate = this.stats.totalHits / total;
158
- this.stats.missRate = this.stats.totalMisses / total;
159
- }
160
- }
161
- /**
162
- * Emit statistics periodically
163
- */
164
- emitStats() {
165
- this.emit("stats", this.getStats());
166
- }
167
- };
168
-
169
- // src/cache/memory-cache.ts
170
- var LRUNode = class {
171
- key;
172
- value;
173
- prev = null;
174
- next = null;
175
- constructor(key, value) {
176
- this.key = key;
177
- this.value = value;
178
- }
179
- };
180
- var MemoryCache = class extends ComponentCacheManager {
181
- cache;
182
- head = null;
183
- tail = null;
184
- currentSize = 0;
185
- keyToComponentName = /* @__PURE__ */ new Map();
186
- cleanupTimer;
187
- constructor(config) {
188
- super(config);
189
- this.cache = /* @__PURE__ */ new Map();
190
- if (config.memory.cleanupInterval > 0) {
191
- this.startCleanupTimer();
192
- }
193
- }
194
- async get(key) {
195
- const node = this.cache.get(key);
196
- if (!node) {
197
- const componentName = this.keyToComponentName.get(key) || this.extractComponentNameFromKey(key);
198
- this.updateMissStats(key, componentName);
199
- return void 0;
200
- }
201
- const component = node.value;
202
- if (this.isExpired(component)) {
203
- await this.delete(key);
204
- this.updateMissStats(key, component.componentName);
205
- return void 0;
206
- }
207
- component.lastAccessed = Date.now();
208
- component.hits++;
209
- this.moveToHead(node);
210
- this.updateHitStats(key, component);
211
- return component;
212
- }
213
- async set(key, component) {
214
- if (!this.isCacheable(component.componentName)) {
215
- return;
216
- }
217
- this.keyToComponentName.set(key, component.componentName);
218
- if (this.cache.has(key)) {
219
- await this.delete(key);
220
- }
221
- await this.ensureSpace(component.size);
222
- const node = new LRUNode(key, component);
223
- this.cache.set(key, node);
224
- this.addToHead(node);
225
- this.currentSize += component.size;
226
- this.stats.entries++;
227
- this.stats.totalSize = this.currentSize;
228
- let componentStats = this.stats.componentStats.get(component.componentName);
229
- if (!componentStats) {
230
- componentStats = {
231
- name: component.componentName,
232
- hits: 0,
233
- misses: 0,
234
- entries: 0,
235
- avgSize: 0,
236
- avgProcessTime: 0
237
- };
238
- this.stats.componentStats.set(component.componentName, componentStats);
239
- }
240
- componentStats.entries++;
241
- componentStats.avgSize = (componentStats.avgSize * (componentStats.entries - 1) + component.size) / componentStats.entries;
242
- this.emit("set", key, component);
243
- }
244
- async has(key) {
245
- const node = this.cache.get(key);
246
- if (!node) return false;
247
- return !this.isExpired(node.value);
248
- }
249
- async delete(key) {
250
- const node = this.cache.get(key);
251
- if (!node) return false;
252
- this.removeNode(node);
253
- this.cache.delete(key);
254
- this.keyToComponentName.delete(key);
255
- this.currentSize -= node.value.size;
256
- this.stats.entries--;
257
- this.stats.totalSize = this.currentSize;
258
- const componentStats = this.stats.componentStats.get(
259
- node.value.componentName
260
- );
261
- if (componentStats && componentStats.entries > 0) {
262
- componentStats.entries--;
263
- }
264
- return true;
265
- }
266
- async clear() {
267
- this.cache.clear();
268
- this.keyToComponentName.clear();
269
- this.head = null;
270
- this.tail = null;
271
- this.currentSize = 0;
272
- this.stats = this.initializeStats();
273
- }
274
- async getKeys() {
275
- return Array.from(this.cache.keys());
276
- }
277
- /**
278
- * Extract component name from cache key
279
- */
280
- extractComponentNameFromKey(key) {
281
- const parts = key.split(":");
282
- return parts.length >= 2 ? parts[1] : void 0;
283
- }
284
- /**
285
- * Check if component is expired
286
- */
287
- isExpired(component) {
288
- if (!component.ttl) return false;
289
- return Date.now() - component.timestamp > component.ttl * 1e3;
290
- }
291
- /**
292
- * Check if component is cacheable
293
- */
294
- isCacheable(componentName) {
295
- const componentConfig = this.config.componentConfig?.[componentName];
296
- return componentConfig?.cacheable !== false;
297
- }
298
- /**
299
- * Ensure enough space for new entry
300
- */
301
- async ensureSpace(requiredSize) {
302
- const maxSize = this.config.memory.maxSize * 1024 * 1024;
303
- while (this.currentSize + requiredSize > maxSize && this.tail) {
304
- const keyToEvict = this.tail.key;
305
- await this.delete(keyToEvict);
306
- this.stats.evictions++;
307
- this.emit("evict", keyToEvict, "size");
308
- }
309
- const maxEntries = this.config.memory.maxEntries;
310
- while (this.stats.entries >= maxEntries && this.tail) {
311
- const keyToEvict = this.tail.key;
312
- await this.delete(keyToEvict);
313
- this.stats.evictions++;
314
- this.emit("evict", keyToEvict, "size");
315
- }
316
- }
317
- /**
318
- * LRU operations - Add node to head
319
- */
320
- addToHead(node) {
321
- node.prev = null;
322
- node.next = this.head;
323
- if (this.head) {
324
- this.head.prev = node;
325
- }
326
- this.head = node;
327
- if (!this.tail) {
328
- this.tail = node;
329
- }
330
- }
331
- /**
332
- * Remove node from list
333
- */
334
- removeNode(node) {
335
- if (node.prev) {
336
- node.prev.next = node.next;
337
- } else {
338
- this.head = node.next;
339
- }
340
- if (node.next) {
341
- node.next.prev = node.prev;
342
- } else {
343
- this.tail = node.prev;
344
- }
345
- }
346
- /**
347
- * Move node to head
348
- */
349
- moveToHead(node) {
350
- if (node === this.head) return;
351
- this.removeNode(node);
352
- this.addToHead(node);
353
- }
354
- /**
355
- * Start cleanup timer for expired entries
356
- */
357
- startCleanupTimer() {
358
- this.cleanupTimer = setInterval(
359
- async () => {
360
- const keysToDelete = [];
361
- for (const [key, node] of this.cache) {
362
- if (this.isExpired(node.value)) {
363
- keysToDelete.push(key);
364
- }
365
- }
366
- for (const key of keysToDelete) {
367
- await this.delete(key);
368
- this.stats.evictions++;
369
- this.emit("evict", key, "ttl");
370
- }
371
- },
372
- (this.config.memory?.cleanupInterval || 300) * 1e3
373
- );
374
- this.cleanupTimer.unref?.();
375
- }
376
- /**
377
- * Stop cleanup timer
378
- */
379
- destroy() {
380
- if (this.cleanupTimer) {
381
- clearInterval(this.cleanupTimer);
382
- }
383
- }
384
- };
385
-
386
- // src/cache/config.ts
387
- var DEFAULT_CACHE_CONFIG = {
388
- enabled: true,
389
- memory: {
390
- enabled: true,
391
- maxSize: 100,
392
- // 100MB
393
- maxEntries: 1e3,
394
- defaultTTL: 3600,
395
- // 1 hour
396
- cleanupInterval: 300
397
- // 5 minutes
398
- },
399
- evictionPolicy: "lru",
400
- componentConfig: {
401
- // Static content - longer TTL
402
- text: { cacheable: true, ttl: 7200 },
403
- // 2 hours
404
- heading: { cacheable: true, ttl: 7200 },
405
- columns: { cacheable: true, ttl: 3600 },
406
- // 1 hour
407
- section: { cacheable: true, ttl: 3600 },
408
- // Dynamic content - shorter TTL
409
- "custom-data": { cacheable: true, ttl: 300 },
410
- // 5 minutes
411
- "api-content": { cacheable: true, ttl: 180 },
412
- // 3 minutes
413
- // Resource-intensive components - medium TTL
414
- image: { cacheable: true, ttl: 1800 },
415
- // 30 minutes
416
- table: { cacheable: true, ttl: 1800 }
417
- },
418
- performance: {
419
- trackMetrics: true,
420
- metricsSampleRate: 1,
421
- enableWarming: false,
422
- parallelProcessing: true
423
- }
424
- };
425
- function getCacheConfigFromEnv() {
426
- const config = {};
427
- if (process.env.CACHE_ENABLED !== void 0) {
428
- config.enabled = process.env.CACHE_ENABLED !== "false";
429
- }
430
- if (process.env.CACHE_MAX_SIZE || process.env.CACHE_MAX_ENTRIES || process.env.CACHE_TTL) {
431
- config.memory = {
432
- enabled: true,
433
- maxSize: parseInt(process.env.CACHE_MAX_SIZE || "100"),
434
- maxEntries: parseInt(process.env.CACHE_MAX_ENTRIES || "1000"),
435
- defaultTTL: parseInt(process.env.CACHE_TTL || "3600"),
436
- cleanupInterval: parseInt(process.env.CACHE_CLEANUP_INTERVAL || "300")
437
- };
438
- }
439
- if (process.env.CACHE_TRACK_METRICS !== void 0 || process.env.CACHE_WARMING !== void 0) {
440
- config.performance = {
441
- trackMetrics: process.env.CACHE_TRACK_METRICS !== "false",
442
- metricsSampleRate: parseFloat(process.env.CACHE_SAMPLE_RATE || "1.0"),
443
- enableWarming: process.env.CACHE_WARMING === "true",
444
- parallelProcessing: process.env.CACHE_PARALLEL !== "false"
445
- };
446
- }
447
- return config;
448
- }
449
- function mergeConfigs(...configs) {
450
- const merged = { ...DEFAULT_CACHE_CONFIG };
451
- for (const config of configs) {
452
- if (config.enabled !== void 0) {
453
- merged.enabled = config.enabled;
454
- }
455
- if (config.memory) {
456
- merged.memory = { ...merged.memory, ...config.memory };
457
- }
458
- if (config.disk) {
459
- merged.disk = { ...merged.disk, ...config.disk };
460
- }
461
- if (config.evictionPolicy) {
462
- merged.evictionPolicy = config.evictionPolicy;
463
- }
464
- if (config.componentConfig) {
465
- merged.componentConfig = { ...merged.componentConfig, ...config.componentConfig };
466
- }
467
- if (config.performance) {
468
- merged.performance = { ...merged.performance, ...config.performance };
469
- }
470
- }
471
- return merged;
472
- }
473
-
474
- // src/cache/analytics.ts
475
- var ComponentCacheAnalytics = class {
476
- historyWindow = 36e5;
477
- // 1 hour in milliseconds
478
- metricsHistory = /* @__PURE__ */ new Map();
479
- performanceBaseline = /* @__PURE__ */ new Map();
480
- /**
481
- * Analyze cache statistics and generate comprehensive report
482
- */
483
- analyzeCache(stats) {
484
- const componentMetrics = this.calculateComponentMetrics(stats);
485
- const trends = this.calculateTrends(stats);
486
- const recommendations = this.generateRecommendations(componentMetrics, trends);
487
- const healthScore = this.calculateHealthScore(componentMetrics);
488
- const overallEfficiency = this.calculateOverallEfficiency(componentMetrics);
489
- const performanceGain = this.calculatePerformanceGain(componentMetrics);
490
- const sortedByEfficiency = [...componentMetrics].sort(
491
- (a, b) => b.efficiencyScore - a.efficiencyScore
492
- );
493
- const topPerformers = sortedByEfficiency.slice(0, 3).map((m) => m.componentName);
494
- const needsAttention = sortedByEfficiency.filter((m) => m.efficiencyScore < 50).map((m) => m.componentName);
495
- return {
496
- timestamp: Date.now(),
497
- healthScore,
498
- overallEfficiency,
499
- componentMetrics,
500
- trends,
501
- recommendations,
502
- topPerformers,
503
- needsAttention,
504
- performanceGain
505
- };
506
- }
507
- /**
508
- * Calculate detailed metrics for each component
509
- */
510
- calculateComponentMetrics(stats) {
511
- const metrics = [];
512
- stats.componentStats.forEach((componentStats, componentName) => {
513
- const totalRequests = componentStats.hits + componentStats.misses;
514
- const hitRate = totalRequests > 0 ? componentStats.hits / totalRequests : 0;
515
- const efficiencyScore = this.calculateEfficiencyScore(
516
- hitRate,
517
- componentStats.avgProcessTime,
518
- componentStats.avgSize,
519
- componentStats.entries
520
- );
521
- const timeSaved = componentStats.hits * componentStats.avgProcessTime;
522
- const memoryCost = componentStats.entries * componentStats.avgSize;
523
- const timeBenefit = timeSaved;
524
- const costBenefitRatio = memoryCost > 0 ? timeBenefit / memoryCost : 0;
525
- metrics.push({
526
- componentName,
527
- hitRate,
528
- totalRequests,
529
- avgHitTime: 1,
530
- // Cache hits are typically ~1ms
531
- avgMissTime: componentStats.avgProcessTime,
532
- efficiencyScore,
533
- memoryUsage: componentStats.entries * componentStats.avgSize,
534
- timeSaved,
535
- costBenefitRatio
536
- });
537
- });
538
- return metrics;
539
- }
540
- /**
541
- * Calculate efficiency score for a component
542
- */
543
- calculateEfficiencyScore(hitRate, avgProcessTime, avgSize, entries) {
544
- const hitRateWeight = 0.4;
545
- const processingTimeWeight = 0.3;
546
- const memorySizeWeight = 0.2;
547
- const utilizationWeight = 0.1;
548
- const hitRateScore = hitRate * 100;
549
- const processingTimeScore = Math.min(100, avgProcessTime / 10 * 100);
550
- const memorySizeScore = Math.max(0, 100 - avgSize / 1e4 * 100);
551
- const utilizationScore = Math.min(100, entries / 100 * 100);
552
- const score = hitRateScore * hitRateWeight + processingTimeScore * processingTimeWeight + memorySizeScore * memorySizeWeight + utilizationScore * utilizationWeight;
553
- return Math.round(score);
554
- }
555
- /**
556
- * Calculate trends over time
557
- */
558
- calculateTrends(stats) {
559
- const trends = [];
560
- const now = Date.now();
561
- stats.componentStats.forEach((componentStats, componentName) => {
562
- const historyKey = `${componentName}_hitRate`;
563
- if (!this.metricsHistory.has(historyKey)) {
564
- this.metricsHistory.set(historyKey, []);
565
- }
566
- const history = this.metricsHistory.get(historyKey);
567
- const totalRequests = componentStats.hits + componentStats.misses;
568
- const hitRate = totalRequests > 0 ? componentStats.hits / totalRequests : 0;
569
- history.push({ timestamp: now, value: hitRate });
570
- const cutoff = now - this.historyWindow;
571
- const cleanedHistory = history.filter(
572
- (point) => point.timestamp > cutoff
573
- );
574
- this.metricsHistory.set(historyKey, cleanedHistory);
575
- trends.push({
576
- componentName,
577
- hitRateTrend: [...cleanedHistory],
578
- requestVolumeTrend: this.getOrCreateHistory(
579
- `${componentName}_volume`,
580
- totalRequests
581
- ),
582
- responseTimeTrend: this.getOrCreateHistory(
583
- `${componentName}_response`,
584
- componentStats.avgProcessTime
585
- ),
586
- memoryUsageTrend: this.getOrCreateHistory(
587
- `${componentName}_memory`,
588
- componentStats.entries * componentStats.avgSize
589
- )
590
- });
591
- });
592
- return trends;
593
- }
594
- /**
595
- * Get or create history for a metric
596
- */
597
- getOrCreateHistory(key, currentValue) {
598
- const now = Date.now();
599
- if (!this.metricsHistory.has(key)) {
600
- this.metricsHistory.set(key, []);
601
- }
602
- const history = this.metricsHistory.get(key);
603
- history.push({ timestamp: now, value: currentValue });
604
- const cutoff = now - this.historyWindow;
605
- const cleanedHistory = history.filter((point) => point.timestamp > cutoff);
606
- this.metricsHistory.set(key, cleanedHistory);
607
- return [...cleanedHistory];
608
- }
609
- /**
610
- * Generate optimization recommendations
611
- */
612
- generateRecommendations(metrics, trends) {
613
- const recommendations = [];
614
- metrics.forEach((metric) => {
615
- const trend = trends.find((t) => t.componentName === metric.componentName);
616
- if (metric.hitRate < 0.3 && metric.totalRequests > 10) {
617
- recommendations.push({
618
- componentName: metric.componentName,
619
- type: "increase_ttl",
620
- description: `Increase TTL for ${metric.componentName} components to improve hit rate`,
621
- expectedImprovement: 20,
622
- priority: 4,
623
- reasoning: `Current hit rate of ${(metric.hitRate * 100).toFixed(1)}% is below optimal threshold. Increasing TTL could improve cache effectiveness.`
624
- });
625
- }
626
- if (metric.memoryUsage > 1e6 && metric.hitRate < 0.5) {
627
- recommendations.push({
628
- componentName: metric.componentName,
629
- type: "decrease_ttl",
630
- description: `Reduce cache size for ${metric.componentName} components`,
631
- expectedImprovement: 15,
632
- priority: 3,
633
- reasoning: `High memory usage (${(metric.memoryUsage / 1024 / 1024).toFixed(2)}MB) with moderate hit rate suggests over-caching.`
634
- });
635
- }
636
- if (metric.efficiencyScore < 30) {
637
- recommendations.push({
638
- componentName: metric.componentName,
639
- type: "disable_cache",
640
- description: `Consider disabling cache for ${metric.componentName} components`,
641
- expectedImprovement: 10,
642
- priority: 2,
643
- reasoning: `Efficiency score of ${metric.efficiencyScore} indicates caching may not be beneficial for this component.`
644
- });
645
- }
646
- if (trend && this.isDecliningSlopbankTrend(trend.hitRateTrend)) {
647
- recommendations.push({
648
- componentName: metric.componentName,
649
- type: "increase_size",
650
- description: `Increase cache capacity for ${metric.componentName} components`,
651
- expectedImprovement: 25,
652
- priority: 5,
653
- reasoning: "Hit rate is declining over time, suggesting cache capacity may be insufficient."
654
- });
655
- }
656
- });
657
- return recommendations.sort((a, b) => b.priority - a.priority);
658
- }
659
- /**
660
- * Check if a trend is declining
661
- */
662
- isDecliningSlopbankTrend(trend) {
663
- if (trend.length < 3) return false;
664
- const n = trend.length;
665
- const recent = trend.slice(-Math.min(10, n));
666
- if (recent.length < 3) return false;
667
- const firstValue = recent[0].value;
668
- const lastValue = recent[recent.length - 1].value;
669
- return (firstValue - lastValue) / firstValue > 0.1;
670
- }
671
- /**
672
- * Calculate overall cache health score
673
- */
674
- calculateHealthScore(metrics) {
675
- if (metrics.length === 0) return 0;
676
- const avgEfficiency = metrics.reduce((sum, m) => sum + m.efficiencyScore, 0) / metrics.length;
677
- const avgHitRate = metrics.reduce((sum, m) => sum + m.hitRate, 0) / metrics.length;
678
- const healthScore = avgEfficiency * 0.6 + avgHitRate * 100 * 0.4;
679
- return Math.round(healthScore);
680
- }
681
- /**
682
- * Calculate overall cache efficiency
683
- */
684
- calculateOverallEfficiency(metrics) {
685
- if (metrics.length === 0) return 0;
686
- const totalTimeSaved = metrics.reduce((sum, m) => sum + m.timeSaved, 0);
687
- const totalMemoryUsed = metrics.reduce((sum, m) => sum + m.memoryUsage, 0);
688
- const totalRequests = metrics.reduce((sum, m) => sum + m.totalRequests, 0);
689
- const totalHits = metrics.reduce(
690
- (sum, m) => sum + m.hitRate * m.totalRequests,
691
- 0
692
- );
693
- if (totalRequests === 0) return 0;
694
- const hitRateEfficiency = totalHits / totalRequests * 100;
695
- const resourceEfficiency = totalMemoryUsed > 0 ? Math.min(100, totalTimeSaved / totalMemoryUsed * 1e3) : 0;
696
- return Math.round(hitRateEfficiency * 0.7 + resourceEfficiency * 0.3);
697
- }
698
- /**
699
- * Calculate performance gain from caching
700
- */
701
- calculatePerformanceGain(metrics) {
702
- const totalTimeSaved = metrics.reduce((sum, m) => sum + m.timeSaved, 0);
703
- const totalProcessingTime = metrics.reduce(
704
- (sum, m) => sum + m.totalRequests * m.avgMissTime,
705
- 0
706
- );
707
- const cpuReduction = totalProcessingTime > 0 ? Math.round(totalTimeSaved / totalProcessingTime * 100) : 0;
708
- const uniqueEntries = metrics.reduce(
709
- (sum, m) => sum + m.memoryUsage / m.avgHitTime,
710
- 0
711
- );
712
- const totalDataProcessed = metrics.reduce(
713
- (sum, m) => sum + m.totalRequests * m.memoryUsage,
714
- 0
715
- );
716
- const memoryOptimization = totalDataProcessed > 0 ? Math.round(
717
- (totalDataProcessed - uniqueEntries) / totalDataProcessed * 100
718
- ) : 0;
719
- return {
720
- timeReduction: Math.round(totalTimeSaved),
721
- cpuReduction: Math.min(100, cpuReduction),
722
- memoryOptimization: Math.min(100, memoryOptimization)
723
- };
724
- }
725
- /**
726
- * Reset analytics history
727
- */
728
- reset() {
729
- this.metricsHistory.clear();
730
- this.performanceBaseline.clear();
731
- }
732
- };
733
- export {
734
- ComponentCacheAnalytics,
735
- ComponentCacheManager,
736
- DEFAULT_CACHE_CONFIG,
737
- MemoryCache,
738
- getCacheConfigFromEnv,
739
- mergeConfigs
740
- };
741
- //# sourceMappingURL=index.js.map