@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.
- package/dist/chunk-JM5KTMNL.js +240 -0
- package/dist/chunk-JM5KTMNL.js.map +1 -0
- package/dist/{chunk-KLWNDWC4.js → chunk-SJ2YYRCT.js} +10 -3
- package/dist/chunk-SJ2YYRCT.js.map +1 -0
- package/dist/index.d.ts +2 -11
- package/dist/index.js +37 -21
- package/dist/index.js.map +1 -1
- package/dist/rendering/index.d.ts +210 -0
- package/dist/rendering/index.js +25 -0
- package/dist/rendering/index.js.map +1 -0
- package/dist/schemas/schema-utils.js +1 -1
- package/package.json +5 -5
- package/dist/cache/index.d.ts +0 -464
- package/dist/cache/index.js +0 -741
- package/dist/cache/index.js.map +0 -1
- package/dist/chunk-KLWNDWC4.js.map +0 -1
package/dist/cache/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/cache/manager.ts","../../src/cache/memory-cache.ts","../../src/cache/config.ts","../../src/cache/analytics.ts"],"sourcesContent":["/**\n * Cache Manager Base Class\n * Abstract base class for cache implementations\n */\n\nimport { EventEmitter } from 'events';\nimport {\n CachedComponent,\n CacheConfiguration,\n CacheStatistics,\n ComponentStatistics,\n} from './types';\n\n/**\n * Main cache manager abstract class\n */\nexport abstract class ComponentCacheManager extends EventEmitter {\n protected config: CacheConfiguration;\n protected stats: CacheStatistics;\n\n constructor(config: CacheConfiguration) {\n super();\n this.config = config;\n this.stats = this.initializeStats();\n }\n\n /**\n * Get a cached component\n */\n abstract get(key: string): Promise<CachedComponent | undefined>;\n\n /**\n * Set a cached component\n */\n abstract set(key: string, component: CachedComponent): Promise<void>;\n\n /**\n * Check if key exists\n */\n abstract has(key: string): Promise<boolean>;\n\n /**\n * Delete a cached entry\n */\n abstract delete(key: string): Promise<boolean>;\n\n /**\n * Clear all cache entries\n */\n abstract clear(): Promise<void>;\n\n /**\n * Get all keys (for utilities)\n */\n abstract getKeys(): Promise<string[]>;\n\n /**\n * Get cache statistics with deep immutability\n */\n getStats(): CacheStatistics {\n // Create a deep copy of the componentStats Map\n const componentStatsCopy = new Map<string, ComponentStatistics>();\n this.stats.componentStats.forEach((value, key) => {\n // Deep copy each ComponentStatistics object\n componentStatsCopy.set(key, { ...value });\n });\n\n // Return a deep copy of the stats object\n return {\n ...this.stats,\n componentStats: componentStatsCopy,\n };\n }\n\n /**\n * Get configuration with deep immutability\n */\n getConfig(): CacheConfiguration {\n // Deep copy the configuration object\n const configCopy: CacheConfiguration = {\n enabled: this.config.enabled,\n evictionPolicy: this.config.evictionPolicy,\n memory: { ...this.config.memory },\n performance: { ...this.config.performance },\n };\n\n // Deep copy optional disk configuration if present\n if (this.config.disk) {\n configCopy.disk = { ...this.config.disk };\n }\n\n // Deep copy componentConfig if present\n if (this.config.componentConfig) {\n configCopy.componentConfig = {};\n for (const [key, value] of Object.entries(this.config.componentConfig)) {\n configCopy.componentConfig[key] = { ...value };\n }\n }\n\n return configCopy;\n }\n\n /**\n * Get multiple entries (batch operation)\n */\n async getMany(keys: string[]): Promise<Map<string, CachedComponent>> {\n const results = new Map<string, CachedComponent>();\n\n if (this.config.performance.parallelProcessing) {\n const promises = keys.map(async (key) => {\n const value = await this.get(key);\n if (value) results.set(key, value);\n });\n await Promise.all(promises);\n } else {\n for (const key of keys) {\n const value = await this.get(key);\n if (value) results.set(key, value);\n }\n }\n\n return results;\n }\n\n /**\n * Set multiple entries (batch operation)\n */\n async setMany(entries: [string, CachedComponent][]): Promise<void> {\n if (this.config.performance.parallelProcessing) {\n const promises = entries.map(([key, value]) => this.set(key, value));\n await Promise.all(promises);\n } else {\n for (const [key, value] of entries) {\n await this.set(key, value);\n }\n }\n }\n\n /**\n * Delete multiple entries\n */\n async deleteMany(keys: string[]): Promise<number> {\n let deleted = 0;\n\n if (this.config.performance.parallelProcessing) {\n const results = await Promise.all(keys.map((key) => this.delete(key)));\n deleted = results.filter(Boolean).length;\n } else {\n for (const key of keys) {\n if (await this.delete(key)) {\n deleted++;\n }\n }\n }\n\n return deleted;\n }\n\n /**\n * Initialize statistics\n */\n protected initializeStats(): CacheStatistics {\n return {\n entries: 0,\n totalSize: 0,\n hitRate: 0,\n missRate: 0,\n totalHits: 0,\n totalMisses: 0,\n avgResponseTime: 0,\n evictions: 0,\n componentStats: new Map(),\n };\n }\n\n /**\n * Update statistics on cache hit\n */\n protected updateHitStats(key: string, component: CachedComponent): void {\n this.stats.totalHits++;\n this.updateComponentStats(component.componentName, 'hit');\n this.recalculateRates();\n this.emit('hit', key, component);\n }\n\n /**\n * Update statistics on cache miss\n */\n protected updateMissStats(key: string, componentName?: string): void {\n this.stats.totalMisses++;\n if (componentName) {\n this.updateComponentStats(componentName, 'miss');\n }\n this.recalculateRates();\n this.emit('miss', key);\n }\n\n /**\n * Update component-specific statistics\n */\n protected updateComponentStats(componentName: string, event: 'hit' | 'miss'): void {\n if (!this.stats.componentStats.has(componentName)) {\n this.stats.componentStats.set(componentName, {\n name: componentName,\n hits: 0,\n misses: 0,\n avgProcessTime: 0,\n avgSize: 0,\n entries: 0,\n });\n }\n\n const stats = this.stats.componentStats.get(componentName)!;\n if (event === 'hit') {\n stats.hits++;\n } else {\n stats.misses++;\n }\n }\n\n /**\n * Recalculate hit/miss rates\n */\n protected recalculateRates(): void {\n const total = this.stats.totalHits + this.stats.totalMisses;\n if (total > 0) {\n this.stats.hitRate = this.stats.totalHits / total;\n this.stats.missRate = this.stats.totalMisses / total;\n }\n }\n\n /**\n * Emit statistics periodically\n */\n protected emitStats(): void {\n this.emit('stats', this.getStats());\n }\n}\n","/**\n * Memory Cache Implementation\n * In-memory cache with LRU eviction policy\n */\n\nimport { ComponentCacheManager } from './manager';\nimport { CachedComponent, CacheConfiguration } from './types';\n\n/**\n * LRU node for doubly-linked list\n */\nclass LRUNode<T> {\n key: string;\n value: T;\n prev: LRUNode<T> | null = null;\n next: LRUNode<T> | null = null;\n\n constructor(key: string, value: T) {\n this.key = key;\n this.value = value;\n }\n}\n\n/**\n * In-memory cache with LRU eviction\n */\nexport class MemoryCache extends ComponentCacheManager {\n private cache: Map<string, LRUNode<CachedComponent>>;\n private head: LRUNode<CachedComponent> | null = null;\n private tail: LRUNode<CachedComponent> | null = null;\n private currentSize: number = 0;\n private keyToComponentName: Map<string, string> = new Map();\n private cleanupTimer?: NodeJS.Timeout;\n\n constructor(config: CacheConfiguration) {\n super(config);\n this.cache = new Map();\n if (config.memory.cleanupInterval > 0) {\n this.startCleanupTimer();\n }\n }\n\n async get(key: string): Promise<CachedComponent | undefined> {\n const node = this.cache.get(key);\n\n if (!node) {\n // Try to get component name from our mapping first, then from the key itself\n const componentName =\n this.keyToComponentName.get(key) ||\n this.extractComponentNameFromKey(key);\n this.updateMissStats(key, componentName);\n return undefined;\n }\n\n const component = node.value;\n\n // Check if expired\n if (this.isExpired(component)) {\n await this.delete(key);\n this.updateMissStats(key, component.componentName);\n return undefined;\n }\n\n // Update access time and move to head (MRU)\n component.lastAccessed = Date.now();\n component.hits++;\n this.moveToHead(node);\n\n this.updateHitStats(key, component);\n return component;\n }\n\n async set(key: string, component: CachedComponent): Promise<void> {\n // Check if component is cacheable\n if (!this.isCacheable(component.componentName)) {\n return;\n }\n\n // Store the component name mapping\n this.keyToComponentName.set(key, component.componentName);\n\n // Remove existing entry if present\n if (this.cache.has(key)) {\n await this.delete(key);\n }\n\n // Check size constraints\n await this.ensureSpace(component.size);\n\n // Create new node and add to head\n const node = new LRUNode(key, component);\n this.cache.set(key, node);\n this.addToHead(node);\n\n // Update stats\n this.currentSize += component.size;\n this.stats.entries++;\n this.stats.totalSize = this.currentSize;\n\n // Update component stats\n let componentStats = this.stats.componentStats.get(component.componentName);\n if (!componentStats) {\n componentStats = {\n name: component.componentName,\n hits: 0,\n misses: 0,\n entries: 0,\n avgSize: 0,\n avgProcessTime: 0,\n };\n this.stats.componentStats.set(component.componentName, componentStats);\n }\n componentStats.entries++;\n componentStats.avgSize =\n (componentStats.avgSize * (componentStats.entries - 1) + component.size) /\n componentStats.entries;\n\n this.emit('set', key, component);\n }\n\n async has(key: string): Promise<boolean> {\n const node = this.cache.get(key);\n if (!node) return false;\n return !this.isExpired(node.value);\n }\n\n async delete(key: string): Promise<boolean> {\n const node = this.cache.get(key);\n if (!node) return false;\n\n this.removeNode(node);\n this.cache.delete(key);\n this.keyToComponentName.delete(key);\n\n // Update stats\n this.currentSize -= node.value.size;\n this.stats.entries--;\n this.stats.totalSize = this.currentSize;\n\n // Update component stats\n const componentStats = this.stats.componentStats.get(\n node.value.componentName\n );\n if (componentStats && componentStats.entries > 0) {\n componentStats.entries--;\n }\n\n return true;\n }\n\n async clear(): Promise<void> {\n this.cache.clear();\n this.keyToComponentName.clear();\n this.head = null;\n this.tail = null;\n this.currentSize = 0;\n this.stats = this.initializeStats();\n }\n\n async getKeys(): Promise<string[]> {\n return Array.from(this.cache.keys());\n }\n\n /**\n * Extract component name from cache key\n */\n private extractComponentNameFromKey(key: string): string | undefined {\n // Cache key format: version:componentName:propsHash:...\n const parts = key.split(':');\n return parts.length >= 2 ? parts[1] : undefined;\n }\n\n /**\n * Check if component is expired\n */\n private isExpired(component: CachedComponent): boolean {\n if (!component.ttl) return false;\n return Date.now() - component.timestamp > component.ttl * 1000;\n }\n\n /**\n * Check if component is cacheable\n */\n private isCacheable(componentName: string): boolean {\n const componentConfig = this.config.componentConfig?.[componentName];\n return componentConfig?.cacheable !== false;\n }\n\n /**\n * Ensure enough space for new entry\n */\n private async ensureSpace(requiredSize: number): Promise<void> {\n const maxSize = this.config.memory.maxSize * 1024 * 1024; // Convert MB to bytes\n\n // Evict based on size\n while (this.currentSize + requiredSize > maxSize && this.tail) {\n const keyToEvict = this.tail.key;\n await this.delete(keyToEvict);\n this.stats.evictions++;\n this.emit('evict', keyToEvict, 'size');\n }\n\n // Also check max entries\n const maxEntries = this.config.memory.maxEntries;\n while (this.stats.entries >= maxEntries && this.tail) {\n const keyToEvict = this.tail.key;\n await this.delete(keyToEvict);\n this.stats.evictions++;\n this.emit('evict', keyToEvict, 'size');\n }\n }\n\n /**\n * LRU operations - Add node to head\n */\n private addToHead(node: LRUNode<CachedComponent>): void {\n node.prev = null;\n node.next = this.head;\n\n if (this.head) {\n this.head.prev = node;\n }\n\n this.head = node;\n\n if (!this.tail) {\n this.tail = node;\n }\n }\n\n /**\n * Remove node from list\n */\n private removeNode(node: LRUNode<CachedComponent>): void {\n if (node.prev) {\n node.prev.next = node.next;\n } else {\n this.head = node.next;\n }\n\n if (node.next) {\n node.next.prev = node.prev;\n } else {\n this.tail = node.prev;\n }\n }\n\n /**\n * Move node to head\n */\n private moveToHead(node: LRUNode<CachedComponent>): void {\n if (node === this.head) return;\n this.removeNode(node);\n this.addToHead(node);\n }\n\n /**\n * Start cleanup timer for expired entries\n */\n private startCleanupTimer(): void {\n this.cleanupTimer = setInterval(\n async () => {\n const keysToDelete: string[] = [];\n\n for (const [key, node] of this.cache) {\n if (this.isExpired(node.value)) {\n keysToDelete.push(key);\n }\n }\n\n for (const key of keysToDelete) {\n await this.delete(key);\n this.stats.evictions++;\n this.emit('evict', key, 'ttl');\n }\n },\n (this.config.memory?.cleanupInterval || 300) * 1000\n );\n // Opportunistic housekeeping should never keep the event loop alive — a\n // short-lived CLI run shouldn't wait 5 minutes for the next sweep before\n // exiting (#hang-on-exit).\n this.cleanupTimer.unref?.();\n }\n\n /**\n * Stop cleanup timer\n */\n destroy(): void {\n if (this.cleanupTimer) {\n clearInterval(this.cleanupTimer);\n }\n }\n}\n","/**\n * Cache Configuration\n * Default configuration and environment-based configuration\n */\n\nimport { CacheConfiguration } from './types';\n\n/**\n * Default cache configuration\n */\nexport const DEFAULT_CACHE_CONFIG: CacheConfiguration = {\n enabled: true,\n memory: {\n enabled: true,\n maxSize: 100, // 100MB\n maxEntries: 1000,\n defaultTTL: 3600, // 1 hour\n cleanupInterval: 300, // 5 minutes\n },\n evictionPolicy: 'lru',\n componentConfig: {\n // Static content - longer TTL\n text: { cacheable: true, ttl: 7200 }, // 2 hours\n heading: { cacheable: true, ttl: 7200 },\n columns: { cacheable: true, ttl: 3600 }, // 1 hour\n section: { cacheable: true, ttl: 3600 },\n\n // Dynamic content - shorter TTL\n 'custom-data': { cacheable: true, ttl: 300 }, // 5 minutes\n 'api-content': { cacheable: true, ttl: 180 }, // 3 minutes\n\n // Resource-intensive components - medium TTL\n image: { cacheable: true, ttl: 1800 }, // 30 minutes\n table: { cacheable: true, ttl: 1800 },\n },\n performance: {\n trackMetrics: true,\n metricsSampleRate: 1.0,\n enableWarming: false,\n parallelProcessing: true,\n },\n};\n\n/**\n * Get cache configuration from environment variables\n */\nexport function getCacheConfigFromEnv(): Partial<CacheConfiguration> {\n const config: Partial<CacheConfiguration> = {};\n\n // Global enabled flag\n if (process.env.CACHE_ENABLED !== undefined) {\n config.enabled = process.env.CACHE_ENABLED !== 'false';\n }\n\n // Memory cache configuration\n if (\n process.env.CACHE_MAX_SIZE ||\n process.env.CACHE_MAX_ENTRIES ||\n process.env.CACHE_TTL\n ) {\n config.memory = {\n enabled: true,\n maxSize: parseInt(process.env.CACHE_MAX_SIZE || '100'),\n maxEntries: parseInt(process.env.CACHE_MAX_ENTRIES || '1000'),\n defaultTTL: parseInt(process.env.CACHE_TTL || '3600'),\n cleanupInterval: parseInt(process.env.CACHE_CLEANUP_INTERVAL || '300'),\n };\n }\n\n // Performance configuration\n if (\n process.env.CACHE_TRACK_METRICS !== undefined ||\n process.env.CACHE_WARMING !== undefined\n ) {\n config.performance = {\n trackMetrics: process.env.CACHE_TRACK_METRICS !== 'false',\n metricsSampleRate: parseFloat(process.env.CACHE_SAMPLE_RATE || '1.0'),\n enableWarming: process.env.CACHE_WARMING === 'true',\n parallelProcessing: process.env.CACHE_PARALLEL !== 'false',\n };\n }\n\n return config;\n}\n\n/**\n * Merge configurations with priority\n */\nexport function mergeConfigs(\n ...configs: Partial<CacheConfiguration>[]\n): CacheConfiguration {\n const merged = { ...DEFAULT_CACHE_CONFIG };\n\n for (const config of configs) {\n if (config.enabled !== undefined) {\n merged.enabled = config.enabled;\n }\n\n if (config.memory) {\n merged.memory = { ...merged.memory, ...config.memory };\n }\n\n if (config.disk) {\n merged.disk = { ...merged.disk, ...config.disk };\n }\n\n if (config.evictionPolicy) {\n merged.evictionPolicy = config.evictionPolicy;\n }\n\n if (config.componentConfig) {\n merged.componentConfig = { ...merged.componentConfig, ...config.componentConfig };\n }\n\n if (config.performance) {\n merged.performance = { ...merged.performance, ...config.performance };\n }\n }\n\n return merged;\n}\n","/**\n * Component Cache Analytics\n * Advanced analytics and insights for component-level caching\n */\n\nimport { CacheStatistics } from './types';\n\n/**\n * Time-series data point for tracking metrics over time\n */\nexport interface TimeSeriesPoint {\n timestamp: number;\n value: number;\n}\n\n/**\n * Component performance metrics\n */\nexport interface ComponentPerformanceMetrics {\n /** Component name identifier */\n componentName: string;\n /** Cache hit rate (0-1) */\n hitRate: number;\n /** Total requests (hits + misses) */\n totalRequests: number;\n /** Average response time for cache hits (ms) */\n avgHitTime: number;\n /** Average response time for cache misses (ms) */\n avgMissTime: number;\n /** Cache efficiency score (0-100) */\n efficiencyScore: number;\n /** Memory usage in bytes */\n memoryUsage: number;\n /** Time saved by caching (ms) */\n timeSaved: number;\n /** Cost-benefit ratio */\n costBenefitRatio: number;\n}\n\n/**\n * Component cache trends over time\n */\nexport interface ComponentCacheTrends {\n /** Component name */\n componentName: string;\n /** Hit rate trend */\n hitRateTrend: TimeSeriesPoint[];\n /** Request volume trend */\n requestVolumeTrend: TimeSeriesPoint[];\n /** Response time trend */\n responseTimeTrend: TimeSeriesPoint[];\n /** Memory usage trend */\n memoryUsageTrend: TimeSeriesPoint[];\n}\n\n/**\n * Cache optimization recommendations\n */\nexport interface CacheOptimizationRecommendation {\n /** Component name to optimize */\n componentName: string;\n /** Recommendation type */\n type:\n | 'increase_ttl'\n | 'decrease_ttl'\n | 'increase_size'\n | 'disable_cache'\n | 'enable_cache';\n /** Recommendation description */\n description: string;\n /** Expected improvement percentage */\n expectedImprovement: number;\n /** Priority level (1-5, 5 being highest) */\n priority: number;\n /** Detailed reasoning */\n reasoning: string;\n}\n\n/**\n * Comprehensive cache analytics report\n */\nexport interface CacheAnalyticsReport {\n /** Report generation timestamp */\n timestamp: number;\n /** Overall cache health score (0-100) */\n healthScore: number;\n /** Total cache efficiency percentage */\n overallEfficiency: number;\n /** Per-component performance metrics */\n componentMetrics: ComponentPerformanceMetrics[];\n /** Component cache trends */\n trends: ComponentCacheTrends[];\n /** Optimization recommendations */\n recommendations: CacheOptimizationRecommendation[];\n /** Top performing components */\n topPerformers: string[];\n /** Components needing attention */\n needsAttention: string[];\n /** Estimated performance gain from caching */\n performanceGain: {\n timeReduction: number; // milliseconds\n cpuReduction: number; // percentage\n memoryOptimization: number; // percentage\n };\n}\n\n/**\n * Component Cache Analytics Engine\n */\nexport class ComponentCacheAnalytics {\n private historyWindow: number = 3600000; // 1 hour in milliseconds\n private metricsHistory: Map<string, TimeSeriesPoint[]> = new Map();\n private performanceBaseline: Map<string, number> = new Map();\n\n /**\n * Analyze cache statistics and generate comprehensive report\n */\n analyzeCache(stats: CacheStatistics): CacheAnalyticsReport {\n const componentMetrics = this.calculateComponentMetrics(stats);\n const trends = this.calculateTrends(stats);\n const recommendations = this.generateRecommendations(componentMetrics, trends);\n const healthScore = this.calculateHealthScore(componentMetrics);\n const overallEfficiency = this.calculateOverallEfficiency(componentMetrics);\n const performanceGain = this.calculatePerformanceGain(componentMetrics);\n\n // Identify top performers and components needing attention\n const sortedByEfficiency = [...componentMetrics].sort(\n (a, b) => b.efficiencyScore - a.efficiencyScore\n );\n const topPerformers = sortedByEfficiency\n .slice(0, 3)\n .map((m) => m.componentName);\n const needsAttention = sortedByEfficiency\n .filter((m) => m.efficiencyScore < 50)\n .map((m) => m.componentName);\n\n return {\n timestamp: Date.now(),\n healthScore,\n overallEfficiency,\n componentMetrics,\n trends,\n recommendations,\n topPerformers,\n needsAttention,\n performanceGain,\n };\n }\n\n /**\n * Calculate detailed metrics for each component\n */\n private calculateComponentMetrics(\n stats: CacheStatistics\n ): ComponentPerformanceMetrics[] {\n const metrics: ComponentPerformanceMetrics[] = [];\n\n stats.componentStats.forEach((componentStats, componentName) => {\n const totalRequests = componentStats.hits + componentStats.misses;\n const hitRate = totalRequests > 0 ? componentStats.hits / totalRequests : 0;\n\n // Calculate efficiency score based on multiple factors\n const efficiencyScore = this.calculateEfficiencyScore(\n hitRate,\n componentStats.avgProcessTime,\n componentStats.avgSize,\n componentStats.entries\n );\n\n // Estimate time saved by caching\n const timeSaved = componentStats.hits * componentStats.avgProcessTime;\n\n // Calculate cost-benefit ratio\n const memoryCost = componentStats.entries * componentStats.avgSize;\n const timeBenefit = timeSaved;\n const costBenefitRatio = memoryCost > 0 ? timeBenefit / memoryCost : 0;\n\n metrics.push({\n componentName,\n hitRate,\n totalRequests,\n avgHitTime: 1, // Cache hits are typically ~1ms\n avgMissTime: componentStats.avgProcessTime,\n efficiencyScore,\n memoryUsage: componentStats.entries * componentStats.avgSize,\n timeSaved,\n costBenefitRatio,\n });\n });\n\n return metrics;\n }\n\n /**\n * Calculate efficiency score for a component\n */\n private calculateEfficiencyScore(\n hitRate: number,\n avgProcessTime: number,\n avgSize: number,\n entries: number\n ): number {\n // Weighted scoring system\n const hitRateWeight = 0.4;\n const processingTimeWeight = 0.3;\n const memorySizeWeight = 0.2;\n const utilizationWeight = 0.1;\n\n // Normalize metrics to 0-100 scale\n const hitRateScore = hitRate * 100;\n const processingTimeScore = Math.min(100, (avgProcessTime / 10) * 100); // Assumes 10ms is slow\n const memorySizeScore = Math.max(0, 100 - (avgSize / 10000) * 100); // Assumes 10KB is large\n const utilizationScore = Math.min(100, (entries / 100) * 100); // Assumes 100 entries is good utilization\n\n const score =\n hitRateScore * hitRateWeight +\n processingTimeScore * processingTimeWeight +\n memorySizeScore * memorySizeWeight +\n utilizationScore * utilizationWeight;\n\n return Math.round(score);\n }\n\n /**\n * Calculate trends over time\n */\n private calculateTrends(stats: CacheStatistics): ComponentCacheTrends[] {\n const trends: ComponentCacheTrends[] = [];\n const now = Date.now();\n\n stats.componentStats.forEach((componentStats, componentName) => {\n // Get or create history for this component\n const historyKey = `${componentName}_hitRate`;\n if (!this.metricsHistory.has(historyKey)) {\n this.metricsHistory.set(historyKey, []);\n }\n\n const history = this.metricsHistory.get(historyKey)!;\n const totalRequests = componentStats.hits + componentStats.misses;\n const hitRate = totalRequests > 0 ? componentStats.hits / totalRequests : 0;\n\n // Add current data point\n history.push({ timestamp: now, value: hitRate });\n\n // Clean old data points\n const cutoff = now - this.historyWindow;\n const cleanedHistory = history.filter(\n (point) => point.timestamp > cutoff\n );\n this.metricsHistory.set(historyKey, cleanedHistory);\n\n // Create trend data\n trends.push({\n componentName,\n hitRateTrend: [...cleanedHistory],\n requestVolumeTrend: this.getOrCreateHistory(\n `${componentName}_volume`,\n totalRequests\n ),\n responseTimeTrend: this.getOrCreateHistory(\n `${componentName}_response`,\n componentStats.avgProcessTime\n ),\n memoryUsageTrend: this.getOrCreateHistory(\n `${componentName}_memory`,\n componentStats.entries * componentStats.avgSize\n ),\n });\n });\n\n return trends;\n }\n\n /**\n * Get or create history for a metric\n */\n private getOrCreateHistory(\n key: string,\n currentValue: number\n ): TimeSeriesPoint[] {\n const now = Date.now();\n\n if (!this.metricsHistory.has(key)) {\n this.metricsHistory.set(key, []);\n }\n\n const history = this.metricsHistory.get(key)!;\n history.push({ timestamp: now, value: currentValue });\n\n // Clean old data points\n const cutoff = now - this.historyWindow;\n const cleanedHistory = history.filter((point) => point.timestamp > cutoff);\n this.metricsHistory.set(key, cleanedHistory);\n\n return [...cleanedHistory];\n }\n\n /**\n * Generate optimization recommendations\n */\n private generateRecommendations(\n metrics: ComponentPerformanceMetrics[],\n trends: ComponentCacheTrends[]\n ): CacheOptimizationRecommendation[] {\n const recommendations: CacheOptimizationRecommendation[] = [];\n\n metrics.forEach((metric) => {\n const trend = trends.find((t) => t.componentName === metric.componentName);\n\n // Low hit rate recommendation\n if (metric.hitRate < 0.3 && metric.totalRequests > 10) {\n recommendations.push({\n componentName: metric.componentName,\n type: 'increase_ttl',\n description: `Increase TTL for ${metric.componentName} components to improve hit rate`,\n expectedImprovement: 20,\n priority: 4,\n reasoning: `Current hit rate of ${(metric.hitRate * 100).toFixed(1)}% is below optimal threshold. Increasing TTL could improve cache effectiveness.`,\n });\n }\n\n // High memory usage with low hit rate\n if (metric.memoryUsage > 1000000 && metric.hitRate < 0.5) {\n recommendations.push({\n componentName: metric.componentName,\n type: 'decrease_ttl',\n description: `Reduce cache size for ${metric.componentName} components`,\n expectedImprovement: 15,\n priority: 3,\n reasoning: `High memory usage (${(metric.memoryUsage / 1024 / 1024).toFixed(2)}MB) with moderate hit rate suggests over-caching.`,\n });\n }\n\n // Very low efficiency score\n if (metric.efficiencyScore < 30) {\n recommendations.push({\n componentName: metric.componentName,\n type: 'disable_cache',\n description: `Consider disabling cache for ${metric.componentName} components`,\n expectedImprovement: 10,\n priority: 2,\n reasoning: `Efficiency score of ${metric.efficiencyScore} indicates caching may not be beneficial for this component.`,\n });\n }\n\n // Check trends for declining performance\n if (trend && this.isDecliningSlopbankTrend(trend.hitRateTrend)) {\n recommendations.push({\n componentName: metric.componentName,\n type: 'increase_size',\n description: `Increase cache capacity for ${metric.componentName} components`,\n expectedImprovement: 25,\n priority: 5,\n reasoning: 'Hit rate is declining over time, suggesting cache capacity may be insufficient.',\n });\n }\n });\n\n // Sort by priority\n return recommendations.sort((a, b) => b.priority - a.priority);\n }\n\n /**\n * Check if a trend is declining\n */\n private isDecliningSlopbankTrend(trend: TimeSeriesPoint[]): boolean {\n if (trend.length < 3) return false;\n\n // Simple linear regression to detect trend\n const n = trend.length;\n const recent = trend.slice(-Math.min(10, n)); // Look at last 10 points\n\n if (recent.length < 3) return false;\n\n const firstValue = recent[0].value;\n const lastValue = recent[recent.length - 1].value;\n\n // Declining if dropped by more than 10%\n return (firstValue - lastValue) / firstValue > 0.1;\n }\n\n /**\n * Calculate overall cache health score\n */\n private calculateHealthScore(metrics: ComponentPerformanceMetrics[]): number {\n if (metrics.length === 0) return 0;\n\n const avgEfficiency =\n metrics.reduce((sum, m) => sum + m.efficiencyScore, 0) / metrics.length;\n const avgHitRate =\n metrics.reduce((sum, m) => sum + m.hitRate, 0) / metrics.length;\n\n // Weight efficiency and hit rate\n const healthScore = avgEfficiency * 0.6 + avgHitRate * 100 * 0.4;\n\n return Math.round(healthScore);\n }\n\n /**\n * Calculate overall cache efficiency\n */\n private calculateOverallEfficiency(\n metrics: ComponentPerformanceMetrics[]\n ): number {\n if (metrics.length === 0) return 0;\n\n const totalTimeSaved = metrics.reduce((sum, m) => sum + m.timeSaved, 0);\n const totalMemoryUsed = metrics.reduce((sum, m) => sum + m.memoryUsage, 0);\n const totalRequests = metrics.reduce((sum, m) => sum + m.totalRequests, 0);\n const totalHits = metrics.reduce(\n (sum, m) => sum + m.hitRate * m.totalRequests,\n 0\n );\n\n if (totalRequests === 0) return 0;\n\n // Calculate efficiency as a combination of hit rate and resource utilization\n const hitRateEfficiency = (totalHits / totalRequests) * 100;\n const resourceEfficiency =\n totalMemoryUsed > 0\n ? Math.min(100, (totalTimeSaved / totalMemoryUsed) * 1000)\n : 0;\n\n return Math.round(hitRateEfficiency * 0.7 + resourceEfficiency * 0.3);\n }\n\n /**\n * Calculate performance gain from caching\n */\n private calculatePerformanceGain(metrics: ComponentPerformanceMetrics[]): {\n timeReduction: number;\n cpuReduction: number;\n memoryOptimization: number;\n } {\n const totalTimeSaved = metrics.reduce((sum, m) => sum + m.timeSaved, 0);\n const totalProcessingTime = metrics.reduce(\n (sum, m) => sum + m.totalRequests * m.avgMissTime,\n 0\n );\n // Estimate CPU reduction based on cache hits avoiding processing\n const cpuReduction =\n totalProcessingTime > 0\n ? Math.round((totalTimeSaved / totalProcessingTime) * 100)\n : 0;\n\n // Memory optimization is based on deduplication\n const uniqueEntries = metrics.reduce(\n (sum, m) => sum + m.memoryUsage / m.avgHitTime,\n 0\n );\n const totalDataProcessed = metrics.reduce(\n (sum, m) => sum + m.totalRequests * m.memoryUsage,\n 0\n );\n const memoryOptimization =\n totalDataProcessed > 0\n ? Math.round(\n ((totalDataProcessed - uniqueEntries) / totalDataProcessed) * 100\n )\n : 0;\n\n return {\n timeReduction: Math.round(totalTimeSaved),\n cpuReduction: Math.min(100, cpuReduction),\n memoryOptimization: Math.min(100, memoryOptimization),\n };\n }\n\n /**\n * Reset analytics history\n */\n reset(): void {\n this.metricsHistory.clear();\n this.performanceBaseline.clear();\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/schemas/schema-utils.ts","../src/schemas/discriminated-unions.ts"],"sourcesContent":["import { Type, TSchema } from '@sinclair/typebox';\nimport { restructureNameDiscriminatedUnions } from './discriminated-unions';\nimport type { ComponentDefinition } from '../types/components';\n\nexport interface ComponentSchemaConfig {\n schema: TSchema;\n title: string;\n description: string;\n requiresName?: boolean;\n enhanceForRichContent?: boolean;\n}\n\nfunction replaceRefs(\n obj: Record<string, unknown>,\n target: string,\n replacement: string\n): void {\n if (typeof obj !== 'object' || obj === null) return;\n if (Array.isArray(obj)) {\n obj.forEach((item) => {\n if (typeof item === 'object' && item !== null) {\n replaceRefs(item as Record<string, unknown>, target, replacement);\n }\n });\n return;\n }\n if (obj.$ref === target) {\n obj.$ref = replacement;\n }\n for (const value of Object.values(obj)) {\n if (typeof value === 'object' && value !== null) {\n replaceRefs(value as Record<string, unknown>, target, replacement);\n }\n }\n}\n\nexport function fixSchemaReferences(\n schema: Record<string, unknown>,\n rootDefinitionName = 'ComponentDefinition'\n): void {\n function traverse(obj: Record<string, unknown>, path = ''): void {\n if (typeof obj !== 'object' || obj === null) return;\n\n for (const [key, value] of Object.entries(obj)) {\n const currentPath = path ? `${path}.${key}` : key;\n\n if (value && typeof value === 'object') {\n const schemaValue = value as Record<string, unknown>;\n\n if (\n schemaValue.type === 'array' &&\n schemaValue.items &&\n Object.keys(schemaValue.items).length === 0\n ) {\n schemaValue.items = {\n $ref: `#/definitions/${rootDefinitionName}`,\n };\n }\n\n if (\n schemaValue.type === 'array' &&\n schemaValue.items &&\n typeof schemaValue.items === 'object' &&\n '$ref' in schemaValue.items &&\n typeof (schemaValue.items as Record<string, unknown>).$ref ===\n 'string' &&\n /^T\\d+$/.test(\n (schemaValue.items as Record<string, unknown>).$ref as string\n )\n ) {\n schemaValue.items = {\n $ref: `#/definitions/${rootDefinitionName}`,\n };\n }\n\n if (\n typeof schemaValue.$ref === 'string' &&\n (/^T\\d+$/.test(schemaValue.$ref as string) ||\n schemaValue.$ref === rootDefinitionName)\n ) {\n schemaValue.$ref = `#/definitions/${rootDefinitionName}`;\n }\n\n if (\n key === '$id' &&\n typeof value === 'string' &&\n (/^T\\d+$/.test(value) || value === rootDefinitionName) &&\n currentPath !== `definitions.${rootDefinitionName}.$id`\n ) {\n delete obj[key];\n continue;\n }\n\n traverse(value as Record<string, unknown>, currentPath);\n }\n }\n }\n\n traverse(schema);\n}\n\nexport function convertToJsonSchema(\n schema: TSchema,\n options: {\n $schema?: string;\n $id?: string;\n title?: string;\n description?: string;\n definitions?: Record<string, unknown>;\n } = {}\n): Record<string, unknown> {\n const {\n $schema = 'https://json-schema.org/draft-07/schema#',\n $id,\n title,\n description,\n definitions = {},\n } = options;\n\n const schemaJson = JSON.parse(JSON.stringify(schema));\n\n if (\n schemaJson.$id &&\n typeof schemaJson.$id === 'string' &&\n /^T\\d+$/.test(schemaJson.$id)\n ) {\n const recursiveId = schemaJson.$id;\n delete schemaJson.$id;\n replaceRefs(schemaJson, recursiveId, '#');\n }\n\n const extractedDefinitions: Record<string, unknown> = { ...definitions };\n\n function extractRecursiveSchemas(\n obj: Record<string, unknown>,\n path = ''\n ): void {\n if (typeof obj !== 'object' || obj === null) return;\n\n for (const [key, value] of Object.entries(obj)) {\n if (value && typeof value === 'object') {\n const schemaValue = value as Record<string, unknown>;\n\n if (schemaValue.$id && typeof schemaValue.$id === 'string') {\n const definitionName = schemaValue.$id;\n\n if (path !== `definitions.${definitionName}`) {\n const { $id: _id, ...schemaWithoutId } = schemaValue; // eslint-disable-line @typescript-eslint/no-unused-vars\n extractedDefinitions[definitionName] = schemaWithoutId;\n obj[key] = { $ref: `#/definitions/${definitionName}` };\n extractRecursiveSchemas(\n schemaWithoutId,\n `definitions.${definitionName}`\n );\n continue;\n }\n }\n\n extractRecursiveSchemas(\n value as Record<string, unknown>,\n path ? `${path}.${key}` : key\n );\n }\n }\n }\n\n extractRecursiveSchemas(schemaJson);\n\n const jsonSchema: Record<string, unknown> = { $schema };\n\n if ($id) jsonSchema.$id = $id;\n\n Object.assign(jsonSchema, schemaJson);\n\n jsonSchema.$schema = $schema;\n if ($id) jsonSchema.$id = $id;\n if (title !== undefined) jsonSchema.title = title;\n if (description !== undefined) jsonSchema.description = description;\n\n if (Object.keys(extractedDefinitions).length > 0) {\n jsonSchema.definitions = extractedDefinitions;\n }\n\n fixSchemaReferences(jsonSchema);\n restructureNameDiscriminatedUnions(jsonSchema);\n\n return jsonSchema;\n}\n\nexport function createComponentSchema(\n name: string,\n config: ComponentSchemaConfig,\n containerNames: string[],\n componentDefinitionSchema?: TSchema\n): Record<string, unknown> {\n const componentStructure: Record<string, unknown> = {\n $schema: 'https://json-schema.org/draft-07/schema#',\n $id: `${name}.schema.json`,\n title: config.title,\n description: config.description,\n type: 'object',\n required: ['name', 'props'],\n properties: {\n name: {\n type: 'string',\n const: name,\n description: `Component name identifier (must be \"${name}\")`,\n },\n id: {\n type: 'string',\n description: 'Optional unique identifier for the component',\n },\n props: JSON.parse(JSON.stringify(config.schema)),\n },\n };\n\n if (containerNames.includes(name)) {\n (componentStructure.properties as Record<string, unknown>).children = {\n type: 'array',\n description: 'Children within this container',\n items: {\n $ref: '#/definitions/ComponentDefinition',\n },\n };\n\n if (componentDefinitionSchema) {\n componentStructure.definitions = {\n ComponentDefinition: JSON.parse(\n JSON.stringify(componentDefinitionSchema)\n ),\n };\n }\n }\n\n fixSchemaReferences(componentStructure);\n componentStructure.additionalProperties = false;\n\n return componentStructure;\n}\n\nexport async function exportSchemaToFile(\n schema: Record<string, unknown>,\n outputPath: string,\n options: { prettyPrint?: boolean } = {}\n): Promise<void> {\n const { prettyPrint = true } = options;\n const jsonSchema = prettyPrint\n ? JSON.stringify(schema, null, 2)\n : JSON.stringify(schema);\n const fs = await import('fs/promises');\n await fs.writeFile(outputPath, jsonSchema, 'utf-8');\n}\n\n/**\n * Create a TypeBox schema object for any component definition.\n * Works for both docx and pptx components.\n */\nexport function createComponentSchemaObject(\n component: ComponentDefinition,\n recursiveRef?: TSchema\n): TSchema {\n const schema: Record<string, TSchema> = {\n name: Type.Literal(component.name),\n id: Type.Optional(Type.String()),\n enabled: Type.Optional(\n Type.Boolean({\n default: true,\n description:\n 'When false, this component is filtered out and not rendered. Defaults to true.',\n })\n ),\n };\n\n if (component.special?.hasSchemaField) {\n schema.$schema = Type.Optional(Type.String({ format: 'uri' }));\n }\n\n schema.props = component.propsSchema;\n\n if (component.hasChildren && recursiveRef) {\n schema.children = Type.Optional(Type.Array(recursiveRef));\n }\n\n return Type.Object(schema, { additionalProperties: false });\n}\n","/**\n * Canonical `if/then` restructuring for name-discriminated component unions.\n *\n * The generators export component unions as a flat `anyOf`. Schema-driven\n * editors (Monaco, VS Code — vscode-json-languageservice) resolve a partially\n * typed node against an `anyOf` by picking the single best-matching branch:\n * while typing `{ \"name\": | }`, every branch requiring `props` fails\n * validation, so its name const never reached autocomplete, and diagnostics\n * reported one arbitrary branch's complaints (\"Value must be \\\"heading\\\"\",\n * \"Missing property \\\"props\\\"\") instead of the real problem.\n *\n * This transform rewrites each such union — at JSON-Schema export time only,\n * the runtime TypeBox validators are untouched — into the standard\n * discriminated-union dispatch:\n *\n * {\n * type: \"object\",\n * required: [\"name\"],\n * properties: { name: { anyOf: [{ const, description }, …] } },\n * allOf: [\n * { if: { properties: { name: { const } }, required: [\"name\"] },\n * then: <branch> },\n * …\n * ]\n * }\n *\n * The accepted set of documents is exactly the same — `properties.name` is\n * the enum the branches already imply, and each `then` is the original\n * branch — but editors now behave deterministically:\n * - completing `name` offers every component, with its description\n * - an empty object reports only `Missing property \"name\"`\n * - a wrong name reports only `Value is not accepted. Valid values: …`\n * - a valid name activates exactly its branch for keys, props and errors\n *\n * Standard draft-07 keywords only, so ajv and every schema-aware editor\n * agree. Versioned plugin branches share a name; they stay grouped in a\n * small `anyOf` inside their `then`, containing best-match ambiguity to the\n * component's own versions.\n */\n\ninterface SchemaNode {\n [key: string]: unknown;\n}\n\ninterface NameConstEntry {\n const: string;\n type: 'string';\n description?: string;\n}\n\n/** A union branch shaped `{ properties: { name: { const: \"...\" } } }`. */\nfunction branchNameConst(branch: unknown): string | undefined {\n if (typeof branch !== 'object' || branch === null || Array.isArray(branch))\n return undefined;\n const name = ((branch as SchemaNode).properties as SchemaNode | undefined)\n ?.name as SchemaNode | undefined;\n return typeof name?.const === 'string' ? name.const : undefined;\n}\n\n/** True when the branch also discriminates on a `version` const (plugins). */\nfunction isVersionedBranch(branch: SchemaNode): boolean {\n const version = (branch.properties as SchemaNode | undefined)?.version as\n | SchemaNode\n | undefined;\n return typeof version?.const === 'string';\n}\n\nfunction branchRequiresName(branch: SchemaNode): boolean {\n return Array.isArray(branch.required) && branch.required.includes('name');\n}\n\n/** Group branches by their name const, preserving union order. */\nfunction groupByName(branches: SchemaNode[]): Map<string, SchemaNode[]> {\n const groups = new Map<string, SchemaNode[]>();\n for (const branch of branches) {\n const name = branchNameConst(branch)!;\n const group = groups.get(name);\n if (group) group.push(branch);\n else groups.set(name, [branch]);\n }\n return groups;\n}\n\nfunction nameEntry(name: string, group: SchemaNode[]): NameConstEntry {\n // Versioned plugins repeat the same name across version branches; the\n // un-versioned fallback carries the cleanest component description.\n const source =\n group.find(\n (b) => !isVersionedBranch(b) && typeof b.description === 'string'\n ) ?? group.find((b) => typeof b.description === 'string');\n return {\n const: name,\n type: 'string',\n ...(source ? { description: source.description as string } : {}),\n };\n}\n\n/**\n * Walk a JSON Schema and restructure every `anyOf` union whose branches are\n * all name-discriminated objects into the `if/then` dispatch shape above.\n *\n * Mutates in place. Conservative by design — a union is only restructured\n * when the rewrite is provably equivalent:\n * - every branch is an object with a `name` const that lists `name` as\n * required (unions containing `$ref` or free-form branches are left alone;\n * a `$ref`'s target union is restructured where it is defined)\n * - the node declares no `properties`, `allOf`, `if`, `required`,\n * `additionalProperties` or `type` of its own that the rewrite would have\n * to merge with\n * - at least two distinct names; single-name unions (a versioned plugin's\n * variants) validate and complete fine as a plain anyOf\n */\nexport function restructureNameDiscriminatedUnions(schema: unknown): void {\n const visited = new WeakSet<object>();\n\n function walk(node: unknown): void {\n if (typeof node !== 'object' || node === null) return;\n if (visited.has(node)) return;\n visited.add(node);\n\n if (Array.isArray(node)) {\n node.forEach(walk);\n return;\n }\n\n const obj = node as SchemaNode;\n const anyOf = obj.anyOf;\n const isCandidate =\n Array.isArray(anyOf) &&\n anyOf.length >= 2 &&\n anyOf.every(\n (b) => branchNameConst(b) !== undefined && branchRequiresName(b)\n ) &&\n obj.properties === undefined &&\n obj.allOf === undefined &&\n obj.if === undefined &&\n obj.required === undefined &&\n // A sibling `additionalProperties` evaluates against the node's own\n // (absent) `properties`; declaring `name` here would change what it\n // rejects, so such unions are left alone.\n obj.additionalProperties === undefined &&\n (obj.type === undefined || obj.type === 'object');\n // Dispatch needs at least two distinct names. Same-name groups (a\n // versioned plugin's variants) stay a plain anyOf — restructuring them\n // would recurse forever on the group it just created.\n const groups = isCandidate ? groupByName(anyOf as SchemaNode[]) : undefined;\n if (groups && groups.size >= 2) {\n obj.type = 'object';\n obj.required = ['name'];\n obj.properties = {\n name: {\n anyOf: [...groups.entries()].map(([name, group]) =>\n nameEntry(name, group)\n ),\n },\n };\n obj.allOf = [...groups.entries()].map(([name, group]) => ({\n if: {\n properties: { name: { const: name } },\n required: ['name'],\n },\n then: group.length === 1 ? group[0] : { anyOf: group },\n }));\n delete obj.anyOf;\n }\n\n for (const value of Object.values(obj)) walk(value);\n }\n\n walk(schema);\n}\n\n/**\n * Iterate the component branches of an exported union, whichever shape it is\n * in — the flat `anyOf` the generators emit, or the `if/then` dispatch this\n * module rewrites it into. For consumers that post-process branch objects\n * (description enhancement, theme-name injection, …).\n */\nexport function unionBranches(schema: unknown): SchemaNode[] {\n if (typeof schema !== 'object' || schema === null) return [];\n const obj = schema as SchemaNode;\n if (Array.isArray(obj.anyOf)) {\n return obj.anyOf.filter(\n (b): b is SchemaNode => typeof b === 'object' && b !== null\n );\n }\n if (Array.isArray(obj.allOf)) {\n return obj.allOf.flatMap((entry): SchemaNode[] => {\n const then = (entry as SchemaNode | null)?.then;\n if (typeof then !== 'object' || then === null) return [];\n const inner = (then as SchemaNode).anyOf;\n return Array.isArray(inner)\n ? inner.filter(\n (b): b is SchemaNode => typeof b === 'object' && b !== null\n )\n : [then as SchemaNode];\n });\n }\n return [];\n}\n"],"mappings":"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","names":[]}
|