specnav-core 0.2.1 → 0.2.3
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/CHANGELOG.md +12 -0
- package/dist/cache.js +5 -1
- package/dist/cache.js.map +1 -1
- package/dist/cache.mjs +5 -1
- package/dist/cache.mjs.map +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +5 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @specnav/core
|
|
2
2
|
|
|
3
|
+
## 0.2.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Allow Next.js hydration scripts (self.**next_f, self.**next_r) in cache validation
|
|
8
|
+
|
|
9
|
+
## 0.2.2
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- Allow Next.js inline module scripts and data-nscript attributes in cache validation
|
|
14
|
+
|
|
3
15
|
## 0.2.1
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
package/dist/cache.js
CHANGED
|
@@ -86,9 +86,13 @@ var CacheManager = class {
|
|
|
86
86
|
let match;
|
|
87
87
|
while ((match = scriptRegex.exec(html)) !== null) {
|
|
88
88
|
const attrs = match[1] || "";
|
|
89
|
+
const content = match[2] || "";
|
|
89
90
|
if (/src\s*=/.test(attrs)) continue;
|
|
90
91
|
if (/type\s*=\s*["']?(application\/json|application\/ld\+json|text\/template)["']?/i.test(attrs)) continue;
|
|
91
|
-
if (/id\s*=\s*["']__NEXT_DATA__["']/i.test(attrs)) continue;
|
|
92
|
+
if (/id\s*=\s*["'](__NEXT_DATA__|_R_)["']/i.test(attrs)) continue;
|
|
93
|
+
if (/data-nscript\s*=/i.test(attrs)) continue;
|
|
94
|
+
if (/type\s*=\s*["']?module["']?/i.test(attrs)) continue;
|
|
95
|
+
if (/self\.__next_[fr]/.test(content)) continue;
|
|
92
96
|
return true;
|
|
93
97
|
}
|
|
94
98
|
return dangerousPatterns.some((pattern) => pattern.test(html));
|
package/dist/cache.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cache.ts"],"names":[],"mappings":"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","file":"cache.js","sourcesContent":["import type { CacheConfig, CachedPage, CacheLayer } from \"./types\";\n\nconst DEFAULT_CONFIG: CacheConfig = {\n memory: {\n enabled: true,\n maxPages: 10,\n },\n serviceWorker: {\n enabled: true,\n ttl: 300,\n cacheName: \"specnav-v1\",\n crossTabSync: true,\n broadcastChannel: \"specnav-sync\",\n },\n edge: {\n enabled: true,\n maxAge: 60,\n staleWhileRevalidate: 300,\n },\n exclude: [],\n};\n\nexport class CacheManager {\n private config: CacheConfig;\n private memoryCache: Map<string, CachedPage> = new Map();\n private accessOrder: string[] = [];\n private broadcastChannel?: BroadcastChannel;\n private onCacheHit?: (href: string, layer: CacheLayer) => void;\n\n constructor(\n config: Partial<CacheConfig> = {},\n callbacks?: { onCacheHit?: (href: string, layer: CacheLayer) => void }\n ) {\n this.config = { ...DEFAULT_CONFIG, ...config };\n this.onCacheHit = callbacks?.onCacheHit;\n\n if (\n this.config.serviceWorker.enabled &&\n this.config.serviceWorker.crossTabSync &&\n typeof BroadcastChannel !== \"undefined\"\n ) {\n this.broadcastChannel = new BroadcastChannel(\n this.config.serviceWorker.broadcastChannel\n );\n this.broadcastChannel.onmessage = this.handleBroadcast;\n }\n }\n\n async get(href: string): Promise<string | null> {\n if (this.isExcluded(href)) return null;\n\n // L1: Memory cache\n const memoryHit = this.getFromMemory(href);\n if (memoryHit) {\n this.onCacheHit?.(href, 1);\n return memoryHit;\n }\n\n // L2: Service Worker cache\n if (this.config.serviceWorker.enabled) {\n const swHit = await this.getFromServiceWorker(href);\n if (swHit) {\n this.onCacheHit?.(href, 2);\n this.setInMemory(href, swHit);\n return swHit;\n }\n }\n\n return null;\n }\n\n async set(href: string, html: string): Promise<void> {\n if (this.isExcluded(href)) return;\n\n // Sanitize href to prevent cache poisoning\n const sanitizedHref = this.sanitizeHref(href);\n if (!sanitizedHref) return;\n\n // Validate HTML doesn't contain dangerous inline scripts\n if (this.containsDangerousContent(html)) {\n console.warn(`Refusing to cache potentially dangerous content from ${sanitizedHref}`);\n return;\n }\n\n const page: CachedPage = {\n href: sanitizedHref,\n html,\n timestamp: Date.now(),\n ttl: this.config.serviceWorker.ttl,\n };\n\n // L1: Memory\n if (this.config.memory.enabled) {\n this.setInMemory(sanitizedHref, html);\n }\n\n // L2: Service Worker\n if (this.config.serviceWorker.enabled) {\n await this.setInServiceWorker(page);\n this.broadcastSet(sanitizedHref);\n }\n }\n\n private containsDangerousContent(html: string): boolean {\n // Check for inline event handlers and javascript: URLs\n const dangerousPatterns = [\n /on\\w+\\s*=\\s*[\"'][^\"']*[\"']/i, // Inline event handlers\n /javascript:/i, // javascript: URLs\n ];\n\n // Check for inline scripts, but exclude safe types\n const scriptRegex = /<script([^>]*)>([\\s\\S]*?)<\\/script>/gi;\n let match;\n while ((match = scriptRegex.exec(html)) !== null) {\n const attrs = match[1] || \"\";\n \n // Allow scripts with src attribute\n if (/src\\s*=/.test(attrs)) continue;\n \n // Allow safe script types (JSON data, templates)\n if (/type\\s*=\\s*[\"']?(application\\/json|application\\/ld\\+json|text\\/template)[\"']?/i.test(attrs)) continue;\n \n // Allow Next.js data script\n if (/id\\s*=\\s*[\"']__NEXT_DATA__[\"']/i.test(attrs)) continue;\n \n // If we get here, it's an inline script without safe type\n return true;\n }\n\n return dangerousPatterns.some(pattern => pattern.test(html));\n }\n\n private sanitizeHref(href: string): string | null {\n try {\n const url = new URL(href, window.location.origin);\n // Only allow same-origin URLs\n if (url.origin !== window.location.origin) return null;\n return url.pathname + url.search + url.hash;\n } catch {\n return null;\n }\n }\n\n clear(href?: string): void {\n if (href) {\n this.memoryCache.delete(href);\n this.accessOrder = this.accessOrder.filter((h) => h !== href);\n this.clearFromServiceWorker(href);\n } else {\n this.memoryCache.clear();\n this.accessOrder = [];\n this.clearAllServiceWorker();\n }\n }\n\n getSize(): number {\n return this.memoryCache.size;\n }\n\n destroy(): void {\n this.memoryCache.clear();\n this.accessOrder = [];\n this.broadcastChannel?.close();\n }\n\n private getFromMemory(href: string): string | null {\n const page = this.memoryCache.get(href);\n if (!page) return null;\n\n // Update LRU order\n this.accessOrder = this.accessOrder.filter((h) => h !== href);\n this.accessOrder.push(href);\n\n return page.html;\n }\n\n private setInMemory(href: string, html: string): void {\n // Prevent memory exhaustion - limit individual page size\n const maxPageSize = 5 * 1024 * 1024; // 5MB per page\n if (html.length > maxPageSize) {\n console.warn(`Page ${href} exceeds max size, not caching`);\n return;\n }\n\n this.memoryCache.set(href, {\n href,\n html,\n timestamp: Date.now(),\n ttl: this.config.serviceWorker.ttl,\n });\n\n // Deduplicate before adding to accessOrder\n const existingIndex = this.accessOrder.indexOf(href);\n if (existingIndex !== -1) {\n this.accessOrder.splice(existingIndex, 1);\n }\n this.accessOrder.push(href);\n\n // LRU eviction\n if (this.memoryCache.size > this.config.memory.maxPages) {\n const oldest = this.accessOrder.shift();\n if (oldest) this.memoryCache.delete(oldest);\n }\n }\n\n private async getFromServiceWorker(href: string): Promise<string | null> {\n if (typeof caches === \"undefined\") return null;\n\n try {\n const cache = await caches.open(this.config.serviceWorker.cacheName);\n const response = await cache.match(href);\n\n if (!response) return null;\n\n const data = await response.json();\n const page = data as CachedPage;\n\n // Check TTL\n const age = Date.now() - page.timestamp;\n if (age > page.ttl * 1000) {\n await cache.delete(href);\n return null;\n }\n\n return page.html;\n } catch {\n return null;\n }\n }\n\n private async setInServiceWorker(page: CachedPage): Promise<void> {\n if (typeof caches === \"undefined\") return;\n\n try {\n const cache = await caches.open(this.config.serviceWorker.cacheName);\n const response = new Response(JSON.stringify(page), {\n headers: {\n \"Content-Type\": \"application/json\",\n \"Cache-Control\": `max-age=${this.config.edge.maxAge}, stale-while-revalidate=${this.config.edge.staleWhileRevalidate}`,\n },\n });\n await cache.put(page.href, response);\n } catch {\n // Silently fail\n }\n }\n\n private async clearFromServiceWorker(href: string): Promise<void> {\n if (typeof caches === \"undefined\") return;\n\n try {\n const cache = await caches.open(this.config.serviceWorker.cacheName);\n await cache.delete(href);\n } catch {\n // Silently fail\n }\n }\n\n private async clearAllServiceWorker(): Promise<void> {\n if (typeof caches === \"undefined\") return;\n\n try {\n await caches.delete(this.config.serviceWorker.cacheName);\n } catch {\n // Silently fail\n }\n }\n\n private isExcluded(href: string): boolean {\n return this.config.exclude.some((pattern) => {\n if (typeof pattern === \"string\") {\n return pattern.includes(\"*\")\n ? new RegExp(pattern.replace(/\\*/g, \".*\")).test(href)\n : href === pattern;\n }\n return pattern.test(href);\n });\n }\n\n private broadcastSet(href: string): void {\n this.broadcastChannel?.postMessage({ type: \"set\", href });\n }\n\n private handleBroadcast = (event: MessageEvent): void => {\n if (event.data.type === \"set\") {\n // Invalidate memory cache to force fetch from SW\n this.memoryCache.delete(event.data.href);\n }\n };\n}\n\nexport function createCacheManager(\n config?: Partial<CacheConfig>,\n callbacks?: { onCacheHit?: (href: string, layer: CacheLayer) => void }\n): CacheManager {\n return new CacheManager(config, callbacks);\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/cache.ts"],"names":[],"mappings":"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","file":"cache.js","sourcesContent":["import type { CacheConfig, CachedPage, CacheLayer } from \"./types\";\n\nconst DEFAULT_CONFIG: CacheConfig = {\n memory: {\n enabled: true,\n maxPages: 10,\n },\n serviceWorker: {\n enabled: true,\n ttl: 300,\n cacheName: \"specnav-v1\",\n crossTabSync: true,\n broadcastChannel: \"specnav-sync\",\n },\n edge: {\n enabled: true,\n maxAge: 60,\n staleWhileRevalidate: 300,\n },\n exclude: [],\n};\n\nexport class CacheManager {\n private config: CacheConfig;\n private memoryCache: Map<string, CachedPage> = new Map();\n private accessOrder: string[] = [];\n private broadcastChannel?: BroadcastChannel;\n private onCacheHit?: (href: string, layer: CacheLayer) => void;\n\n constructor(\n config: Partial<CacheConfig> = {},\n callbacks?: { onCacheHit?: (href: string, layer: CacheLayer) => void }\n ) {\n this.config = { ...DEFAULT_CONFIG, ...config };\n this.onCacheHit = callbacks?.onCacheHit;\n\n if (\n this.config.serviceWorker.enabled &&\n this.config.serviceWorker.crossTabSync &&\n typeof BroadcastChannel !== \"undefined\"\n ) {\n this.broadcastChannel = new BroadcastChannel(\n this.config.serviceWorker.broadcastChannel\n );\n this.broadcastChannel.onmessage = this.handleBroadcast;\n }\n }\n\n async get(href: string): Promise<string | null> {\n if (this.isExcluded(href)) return null;\n\n // L1: Memory cache\n const memoryHit = this.getFromMemory(href);\n if (memoryHit) {\n this.onCacheHit?.(href, 1);\n return memoryHit;\n }\n\n // L2: Service Worker cache\n if (this.config.serviceWorker.enabled) {\n const swHit = await this.getFromServiceWorker(href);\n if (swHit) {\n this.onCacheHit?.(href, 2);\n this.setInMemory(href, swHit);\n return swHit;\n }\n }\n\n return null;\n }\n\n async set(href: string, html: string): Promise<void> {\n if (this.isExcluded(href)) return;\n\n // Sanitize href to prevent cache poisoning\n const sanitizedHref = this.sanitizeHref(href);\n if (!sanitizedHref) return;\n\n // Validate HTML doesn't contain dangerous inline scripts\n if (this.containsDangerousContent(html)) {\n console.warn(`Refusing to cache potentially dangerous content from ${sanitizedHref}`);\n return;\n }\n\n const page: CachedPage = {\n href: sanitizedHref,\n html,\n timestamp: Date.now(),\n ttl: this.config.serviceWorker.ttl,\n };\n\n // L1: Memory\n if (this.config.memory.enabled) {\n this.setInMemory(sanitizedHref, html);\n }\n\n // L2: Service Worker\n if (this.config.serviceWorker.enabled) {\n await this.setInServiceWorker(page);\n this.broadcastSet(sanitizedHref);\n }\n }\n\n private containsDangerousContent(html: string): boolean {\n // Check for inline event handlers and javascript: URLs\n const dangerousPatterns = [\n /on\\w+\\s*=\\s*[\"'][^\"']*[\"']/i, // Inline event handlers\n /javascript:/i, // javascript: URLs\n ];\n\n // Check for inline scripts, but exclude safe types\n const scriptRegex = /<script([^>]*)>([\\s\\S]*?)<\\/script>/gi;\n let match;\n while ((match = scriptRegex.exec(html)) !== null) {\n const attrs = match[1] || \"\";\n const content = match[2] || \"\";\n \n // Allow scripts with src attribute\n if (/src\\s*=/.test(attrs)) continue;\n \n // Allow safe script types (JSON data, templates)\n if (/type\\s*=\\s*[\"']?(application\\/json|application\\/ld\\+json|text\\/template)[\"']?/i.test(attrs)) continue;\n \n // Allow Next.js scripts\n if (/id\\s*=\\s*[\"'](__NEXT_DATA__|_R_)[\"']/i.test(attrs)) continue;\n if (/data-nscript\\s*=/i.test(attrs)) continue;\n \n // Allow module scripts (Next.js uses these for hydration)\n if (/type\\s*=\\s*[\"']?module[\"']?/i.test(attrs)) continue;\n \n // Allow Next.js hydration scripts (self.__next_f, self.__next_r)\n if (/self\\.__next_[fr]/.test(content)) continue;\n \n // If we get here, it's an inline script without safe type\n return true;\n }\n\n return dangerousPatterns.some(pattern => pattern.test(html));\n }\n\n private sanitizeHref(href: string): string | null {\n try {\n const url = new URL(href, window.location.origin);\n // Only allow same-origin URLs\n if (url.origin !== window.location.origin) return null;\n return url.pathname + url.search + url.hash;\n } catch {\n return null;\n }\n }\n\n clear(href?: string): void {\n if (href) {\n this.memoryCache.delete(href);\n this.accessOrder = this.accessOrder.filter((h) => h !== href);\n this.clearFromServiceWorker(href);\n } else {\n this.memoryCache.clear();\n this.accessOrder = [];\n this.clearAllServiceWorker();\n }\n }\n\n getSize(): number {\n return this.memoryCache.size;\n }\n\n destroy(): void {\n this.memoryCache.clear();\n this.accessOrder = [];\n this.broadcastChannel?.close();\n }\n\n private getFromMemory(href: string): string | null {\n const page = this.memoryCache.get(href);\n if (!page) return null;\n\n // Update LRU order\n this.accessOrder = this.accessOrder.filter((h) => h !== href);\n this.accessOrder.push(href);\n\n return page.html;\n }\n\n private setInMemory(href: string, html: string): void {\n // Prevent memory exhaustion - limit individual page size\n const maxPageSize = 5 * 1024 * 1024; // 5MB per page\n if (html.length > maxPageSize) {\n console.warn(`Page ${href} exceeds max size, not caching`);\n return;\n }\n\n this.memoryCache.set(href, {\n href,\n html,\n timestamp: Date.now(),\n ttl: this.config.serviceWorker.ttl,\n });\n\n // Deduplicate before adding to accessOrder\n const existingIndex = this.accessOrder.indexOf(href);\n if (existingIndex !== -1) {\n this.accessOrder.splice(existingIndex, 1);\n }\n this.accessOrder.push(href);\n\n // LRU eviction\n if (this.memoryCache.size > this.config.memory.maxPages) {\n const oldest = this.accessOrder.shift();\n if (oldest) this.memoryCache.delete(oldest);\n }\n }\n\n private async getFromServiceWorker(href: string): Promise<string | null> {\n if (typeof caches === \"undefined\") return null;\n\n try {\n const cache = await caches.open(this.config.serviceWorker.cacheName);\n const response = await cache.match(href);\n\n if (!response) return null;\n\n const data = await response.json();\n const page = data as CachedPage;\n\n // Check TTL\n const age = Date.now() - page.timestamp;\n if (age > page.ttl * 1000) {\n await cache.delete(href);\n return null;\n }\n\n return page.html;\n } catch {\n return null;\n }\n }\n\n private async setInServiceWorker(page: CachedPage): Promise<void> {\n if (typeof caches === \"undefined\") return;\n\n try {\n const cache = await caches.open(this.config.serviceWorker.cacheName);\n const response = new Response(JSON.stringify(page), {\n headers: {\n \"Content-Type\": \"application/json\",\n \"Cache-Control\": `max-age=${this.config.edge.maxAge}, stale-while-revalidate=${this.config.edge.staleWhileRevalidate}`,\n },\n });\n await cache.put(page.href, response);\n } catch {\n // Silently fail\n }\n }\n\n private async clearFromServiceWorker(href: string): Promise<void> {\n if (typeof caches === \"undefined\") return;\n\n try {\n const cache = await caches.open(this.config.serviceWorker.cacheName);\n await cache.delete(href);\n } catch {\n // Silently fail\n }\n }\n\n private async clearAllServiceWorker(): Promise<void> {\n if (typeof caches === \"undefined\") return;\n\n try {\n await caches.delete(this.config.serviceWorker.cacheName);\n } catch {\n // Silently fail\n }\n }\n\n private isExcluded(href: string): boolean {\n return this.config.exclude.some((pattern) => {\n if (typeof pattern === \"string\") {\n return pattern.includes(\"*\")\n ? new RegExp(pattern.replace(/\\*/g, \".*\")).test(href)\n : href === pattern;\n }\n return pattern.test(href);\n });\n }\n\n private broadcastSet(href: string): void {\n this.broadcastChannel?.postMessage({ type: \"set\", href });\n }\n\n private handleBroadcast = (event: MessageEvent): void => {\n if (event.data.type === \"set\") {\n // Invalidate memory cache to force fetch from SW\n this.memoryCache.delete(event.data.href);\n }\n };\n}\n\nexport function createCacheManager(\n config?: Partial<CacheConfig>,\n callbacks?: { onCacheHit?: (href: string, layer: CacheLayer) => void }\n): CacheManager {\n return new CacheManager(config, callbacks);\n}\n"]}
|
package/dist/cache.mjs
CHANGED
|
@@ -84,9 +84,13 @@ var CacheManager = class {
|
|
|
84
84
|
let match;
|
|
85
85
|
while ((match = scriptRegex.exec(html)) !== null) {
|
|
86
86
|
const attrs = match[1] || "";
|
|
87
|
+
const content = match[2] || "";
|
|
87
88
|
if (/src\s*=/.test(attrs)) continue;
|
|
88
89
|
if (/type\s*=\s*["']?(application\/json|application\/ld\+json|text\/template)["']?/i.test(attrs)) continue;
|
|
89
|
-
if (/id\s*=\s*["']__NEXT_DATA__["']/i.test(attrs)) continue;
|
|
90
|
+
if (/id\s*=\s*["'](__NEXT_DATA__|_R_)["']/i.test(attrs)) continue;
|
|
91
|
+
if (/data-nscript\s*=/i.test(attrs)) continue;
|
|
92
|
+
if (/type\s*=\s*["']?module["']?/i.test(attrs)) continue;
|
|
93
|
+
if (/self\.__next_[fr]/.test(content)) continue;
|
|
90
94
|
return true;
|
|
91
95
|
}
|
|
92
96
|
return dangerousPatterns.some((pattern) => pattern.test(html));
|
package/dist/cache.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cache.ts"],"names":[],"mappings":"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","file":"cache.mjs","sourcesContent":["import type { CacheConfig, CachedPage, CacheLayer } from \"./types\";\n\nconst DEFAULT_CONFIG: CacheConfig = {\n memory: {\n enabled: true,\n maxPages: 10,\n },\n serviceWorker: {\n enabled: true,\n ttl: 300,\n cacheName: \"specnav-v1\",\n crossTabSync: true,\n broadcastChannel: \"specnav-sync\",\n },\n edge: {\n enabled: true,\n maxAge: 60,\n staleWhileRevalidate: 300,\n },\n exclude: [],\n};\n\nexport class CacheManager {\n private config: CacheConfig;\n private memoryCache: Map<string, CachedPage> = new Map();\n private accessOrder: string[] = [];\n private broadcastChannel?: BroadcastChannel;\n private onCacheHit?: (href: string, layer: CacheLayer) => void;\n\n constructor(\n config: Partial<CacheConfig> = {},\n callbacks?: { onCacheHit?: (href: string, layer: CacheLayer) => void }\n ) {\n this.config = { ...DEFAULT_CONFIG, ...config };\n this.onCacheHit = callbacks?.onCacheHit;\n\n if (\n this.config.serviceWorker.enabled &&\n this.config.serviceWorker.crossTabSync &&\n typeof BroadcastChannel !== \"undefined\"\n ) {\n this.broadcastChannel = new BroadcastChannel(\n this.config.serviceWorker.broadcastChannel\n );\n this.broadcastChannel.onmessage = this.handleBroadcast;\n }\n }\n\n async get(href: string): Promise<string | null> {\n if (this.isExcluded(href)) return null;\n\n // L1: Memory cache\n const memoryHit = this.getFromMemory(href);\n if (memoryHit) {\n this.onCacheHit?.(href, 1);\n return memoryHit;\n }\n\n // L2: Service Worker cache\n if (this.config.serviceWorker.enabled) {\n const swHit = await this.getFromServiceWorker(href);\n if (swHit) {\n this.onCacheHit?.(href, 2);\n this.setInMemory(href, swHit);\n return swHit;\n }\n }\n\n return null;\n }\n\n async set(href: string, html: string): Promise<void> {\n if (this.isExcluded(href)) return;\n\n // Sanitize href to prevent cache poisoning\n const sanitizedHref = this.sanitizeHref(href);\n if (!sanitizedHref) return;\n\n // Validate HTML doesn't contain dangerous inline scripts\n if (this.containsDangerousContent(html)) {\n console.warn(`Refusing to cache potentially dangerous content from ${sanitizedHref}`);\n return;\n }\n\n const page: CachedPage = {\n href: sanitizedHref,\n html,\n timestamp: Date.now(),\n ttl: this.config.serviceWorker.ttl,\n };\n\n // L1: Memory\n if (this.config.memory.enabled) {\n this.setInMemory(sanitizedHref, html);\n }\n\n // L2: Service Worker\n if (this.config.serviceWorker.enabled) {\n await this.setInServiceWorker(page);\n this.broadcastSet(sanitizedHref);\n }\n }\n\n private containsDangerousContent(html: string): boolean {\n // Check for inline event handlers and javascript: URLs\n const dangerousPatterns = [\n /on\\w+\\s*=\\s*[\"'][^\"']*[\"']/i, // Inline event handlers\n /javascript:/i, // javascript: URLs\n ];\n\n // Check for inline scripts, but exclude safe types\n const scriptRegex = /<script([^>]*)>([\\s\\S]*?)<\\/script>/gi;\n let match;\n while ((match = scriptRegex.exec(html)) !== null) {\n const attrs = match[1] || \"\";\n \n // Allow scripts with src attribute\n if (/src\\s*=/.test(attrs)) continue;\n \n // Allow safe script types (JSON data, templates)\n if (/type\\s*=\\s*[\"']?(application\\/json|application\\/ld\\+json|text\\/template)[\"']?/i.test(attrs)) continue;\n \n // Allow Next.js data script\n if (/id\\s*=\\s*[\"']__NEXT_DATA__[\"']/i.test(attrs)) continue;\n \n // If we get here, it's an inline script without safe type\n return true;\n }\n\n return dangerousPatterns.some(pattern => pattern.test(html));\n }\n\n private sanitizeHref(href: string): string | null {\n try {\n const url = new URL(href, window.location.origin);\n // Only allow same-origin URLs\n if (url.origin !== window.location.origin) return null;\n return url.pathname + url.search + url.hash;\n } catch {\n return null;\n }\n }\n\n clear(href?: string): void {\n if (href) {\n this.memoryCache.delete(href);\n this.accessOrder = this.accessOrder.filter((h) => h !== href);\n this.clearFromServiceWorker(href);\n } else {\n this.memoryCache.clear();\n this.accessOrder = [];\n this.clearAllServiceWorker();\n }\n }\n\n getSize(): number {\n return this.memoryCache.size;\n }\n\n destroy(): void {\n this.memoryCache.clear();\n this.accessOrder = [];\n this.broadcastChannel?.close();\n }\n\n private getFromMemory(href: string): string | null {\n const page = this.memoryCache.get(href);\n if (!page) return null;\n\n // Update LRU order\n this.accessOrder = this.accessOrder.filter((h) => h !== href);\n this.accessOrder.push(href);\n\n return page.html;\n }\n\n private setInMemory(href: string, html: string): void {\n // Prevent memory exhaustion - limit individual page size\n const maxPageSize = 5 * 1024 * 1024; // 5MB per page\n if (html.length > maxPageSize) {\n console.warn(`Page ${href} exceeds max size, not caching`);\n return;\n }\n\n this.memoryCache.set(href, {\n href,\n html,\n timestamp: Date.now(),\n ttl: this.config.serviceWorker.ttl,\n });\n\n // Deduplicate before adding to accessOrder\n const existingIndex = this.accessOrder.indexOf(href);\n if (existingIndex !== -1) {\n this.accessOrder.splice(existingIndex, 1);\n }\n this.accessOrder.push(href);\n\n // LRU eviction\n if (this.memoryCache.size > this.config.memory.maxPages) {\n const oldest = this.accessOrder.shift();\n if (oldest) this.memoryCache.delete(oldest);\n }\n }\n\n private async getFromServiceWorker(href: string): Promise<string | null> {\n if (typeof caches === \"undefined\") return null;\n\n try {\n const cache = await caches.open(this.config.serviceWorker.cacheName);\n const response = await cache.match(href);\n\n if (!response) return null;\n\n const data = await response.json();\n const page = data as CachedPage;\n\n // Check TTL\n const age = Date.now() - page.timestamp;\n if (age > page.ttl * 1000) {\n await cache.delete(href);\n return null;\n }\n\n return page.html;\n } catch {\n return null;\n }\n }\n\n private async setInServiceWorker(page: CachedPage): Promise<void> {\n if (typeof caches === \"undefined\") return;\n\n try {\n const cache = await caches.open(this.config.serviceWorker.cacheName);\n const response = new Response(JSON.stringify(page), {\n headers: {\n \"Content-Type\": \"application/json\",\n \"Cache-Control\": `max-age=${this.config.edge.maxAge}, stale-while-revalidate=${this.config.edge.staleWhileRevalidate}`,\n },\n });\n await cache.put(page.href, response);\n } catch {\n // Silently fail\n }\n }\n\n private async clearFromServiceWorker(href: string): Promise<void> {\n if (typeof caches === \"undefined\") return;\n\n try {\n const cache = await caches.open(this.config.serviceWorker.cacheName);\n await cache.delete(href);\n } catch {\n // Silently fail\n }\n }\n\n private async clearAllServiceWorker(): Promise<void> {\n if (typeof caches === \"undefined\") return;\n\n try {\n await caches.delete(this.config.serviceWorker.cacheName);\n } catch {\n // Silently fail\n }\n }\n\n private isExcluded(href: string): boolean {\n return this.config.exclude.some((pattern) => {\n if (typeof pattern === \"string\") {\n return pattern.includes(\"*\")\n ? new RegExp(pattern.replace(/\\*/g, \".*\")).test(href)\n : href === pattern;\n }\n return pattern.test(href);\n });\n }\n\n private broadcastSet(href: string): void {\n this.broadcastChannel?.postMessage({ type: \"set\", href });\n }\n\n private handleBroadcast = (event: MessageEvent): void => {\n if (event.data.type === \"set\") {\n // Invalidate memory cache to force fetch from SW\n this.memoryCache.delete(event.data.href);\n }\n };\n}\n\nexport function createCacheManager(\n config?: Partial<CacheConfig>,\n callbacks?: { onCacheHit?: (href: string, layer: CacheLayer) => void }\n): CacheManager {\n return new CacheManager(config, callbacks);\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/cache.ts"],"names":[],"mappings":"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","file":"cache.mjs","sourcesContent":["import type { CacheConfig, CachedPage, CacheLayer } from \"./types\";\n\nconst DEFAULT_CONFIG: CacheConfig = {\n memory: {\n enabled: true,\n maxPages: 10,\n },\n serviceWorker: {\n enabled: true,\n ttl: 300,\n cacheName: \"specnav-v1\",\n crossTabSync: true,\n broadcastChannel: \"specnav-sync\",\n },\n edge: {\n enabled: true,\n maxAge: 60,\n staleWhileRevalidate: 300,\n },\n exclude: [],\n};\n\nexport class CacheManager {\n private config: CacheConfig;\n private memoryCache: Map<string, CachedPage> = new Map();\n private accessOrder: string[] = [];\n private broadcastChannel?: BroadcastChannel;\n private onCacheHit?: (href: string, layer: CacheLayer) => void;\n\n constructor(\n config: Partial<CacheConfig> = {},\n callbacks?: { onCacheHit?: (href: string, layer: CacheLayer) => void }\n ) {\n this.config = { ...DEFAULT_CONFIG, ...config };\n this.onCacheHit = callbacks?.onCacheHit;\n\n if (\n this.config.serviceWorker.enabled &&\n this.config.serviceWorker.crossTabSync &&\n typeof BroadcastChannel !== \"undefined\"\n ) {\n this.broadcastChannel = new BroadcastChannel(\n this.config.serviceWorker.broadcastChannel\n );\n this.broadcastChannel.onmessage = this.handleBroadcast;\n }\n }\n\n async get(href: string): Promise<string | null> {\n if (this.isExcluded(href)) return null;\n\n // L1: Memory cache\n const memoryHit = this.getFromMemory(href);\n if (memoryHit) {\n this.onCacheHit?.(href, 1);\n return memoryHit;\n }\n\n // L2: Service Worker cache\n if (this.config.serviceWorker.enabled) {\n const swHit = await this.getFromServiceWorker(href);\n if (swHit) {\n this.onCacheHit?.(href, 2);\n this.setInMemory(href, swHit);\n return swHit;\n }\n }\n\n return null;\n }\n\n async set(href: string, html: string): Promise<void> {\n if (this.isExcluded(href)) return;\n\n // Sanitize href to prevent cache poisoning\n const sanitizedHref = this.sanitizeHref(href);\n if (!sanitizedHref) return;\n\n // Validate HTML doesn't contain dangerous inline scripts\n if (this.containsDangerousContent(html)) {\n console.warn(`Refusing to cache potentially dangerous content from ${sanitizedHref}`);\n return;\n }\n\n const page: CachedPage = {\n href: sanitizedHref,\n html,\n timestamp: Date.now(),\n ttl: this.config.serviceWorker.ttl,\n };\n\n // L1: Memory\n if (this.config.memory.enabled) {\n this.setInMemory(sanitizedHref, html);\n }\n\n // L2: Service Worker\n if (this.config.serviceWorker.enabled) {\n await this.setInServiceWorker(page);\n this.broadcastSet(sanitizedHref);\n }\n }\n\n private containsDangerousContent(html: string): boolean {\n // Check for inline event handlers and javascript: URLs\n const dangerousPatterns = [\n /on\\w+\\s*=\\s*[\"'][^\"']*[\"']/i, // Inline event handlers\n /javascript:/i, // javascript: URLs\n ];\n\n // Check for inline scripts, but exclude safe types\n const scriptRegex = /<script([^>]*)>([\\s\\S]*?)<\\/script>/gi;\n let match;\n while ((match = scriptRegex.exec(html)) !== null) {\n const attrs = match[1] || \"\";\n const content = match[2] || \"\";\n \n // Allow scripts with src attribute\n if (/src\\s*=/.test(attrs)) continue;\n \n // Allow safe script types (JSON data, templates)\n if (/type\\s*=\\s*[\"']?(application\\/json|application\\/ld\\+json|text\\/template)[\"']?/i.test(attrs)) continue;\n \n // Allow Next.js scripts\n if (/id\\s*=\\s*[\"'](__NEXT_DATA__|_R_)[\"']/i.test(attrs)) continue;\n if (/data-nscript\\s*=/i.test(attrs)) continue;\n \n // Allow module scripts (Next.js uses these for hydration)\n if (/type\\s*=\\s*[\"']?module[\"']?/i.test(attrs)) continue;\n \n // Allow Next.js hydration scripts (self.__next_f, self.__next_r)\n if (/self\\.__next_[fr]/.test(content)) continue;\n \n // If we get here, it's an inline script without safe type\n return true;\n }\n\n return dangerousPatterns.some(pattern => pattern.test(html));\n }\n\n private sanitizeHref(href: string): string | null {\n try {\n const url = new URL(href, window.location.origin);\n // Only allow same-origin URLs\n if (url.origin !== window.location.origin) return null;\n return url.pathname + url.search + url.hash;\n } catch {\n return null;\n }\n }\n\n clear(href?: string): void {\n if (href) {\n this.memoryCache.delete(href);\n this.accessOrder = this.accessOrder.filter((h) => h !== href);\n this.clearFromServiceWorker(href);\n } else {\n this.memoryCache.clear();\n this.accessOrder = [];\n this.clearAllServiceWorker();\n }\n }\n\n getSize(): number {\n return this.memoryCache.size;\n }\n\n destroy(): void {\n this.memoryCache.clear();\n this.accessOrder = [];\n this.broadcastChannel?.close();\n }\n\n private getFromMemory(href: string): string | null {\n const page = this.memoryCache.get(href);\n if (!page) return null;\n\n // Update LRU order\n this.accessOrder = this.accessOrder.filter((h) => h !== href);\n this.accessOrder.push(href);\n\n return page.html;\n }\n\n private setInMemory(href: string, html: string): void {\n // Prevent memory exhaustion - limit individual page size\n const maxPageSize = 5 * 1024 * 1024; // 5MB per page\n if (html.length > maxPageSize) {\n console.warn(`Page ${href} exceeds max size, not caching`);\n return;\n }\n\n this.memoryCache.set(href, {\n href,\n html,\n timestamp: Date.now(),\n ttl: this.config.serviceWorker.ttl,\n });\n\n // Deduplicate before adding to accessOrder\n const existingIndex = this.accessOrder.indexOf(href);\n if (existingIndex !== -1) {\n this.accessOrder.splice(existingIndex, 1);\n }\n this.accessOrder.push(href);\n\n // LRU eviction\n if (this.memoryCache.size > this.config.memory.maxPages) {\n const oldest = this.accessOrder.shift();\n if (oldest) this.memoryCache.delete(oldest);\n }\n }\n\n private async getFromServiceWorker(href: string): Promise<string | null> {\n if (typeof caches === \"undefined\") return null;\n\n try {\n const cache = await caches.open(this.config.serviceWorker.cacheName);\n const response = await cache.match(href);\n\n if (!response) return null;\n\n const data = await response.json();\n const page = data as CachedPage;\n\n // Check TTL\n const age = Date.now() - page.timestamp;\n if (age > page.ttl * 1000) {\n await cache.delete(href);\n return null;\n }\n\n return page.html;\n } catch {\n return null;\n }\n }\n\n private async setInServiceWorker(page: CachedPage): Promise<void> {\n if (typeof caches === \"undefined\") return;\n\n try {\n const cache = await caches.open(this.config.serviceWorker.cacheName);\n const response = new Response(JSON.stringify(page), {\n headers: {\n \"Content-Type\": \"application/json\",\n \"Cache-Control\": `max-age=${this.config.edge.maxAge}, stale-while-revalidate=${this.config.edge.staleWhileRevalidate}`,\n },\n });\n await cache.put(page.href, response);\n } catch {\n // Silently fail\n }\n }\n\n private async clearFromServiceWorker(href: string): Promise<void> {\n if (typeof caches === \"undefined\") return;\n\n try {\n const cache = await caches.open(this.config.serviceWorker.cacheName);\n await cache.delete(href);\n } catch {\n // Silently fail\n }\n }\n\n private async clearAllServiceWorker(): Promise<void> {\n if (typeof caches === \"undefined\") return;\n\n try {\n await caches.delete(this.config.serviceWorker.cacheName);\n } catch {\n // Silently fail\n }\n }\n\n private isExcluded(href: string): boolean {\n return this.config.exclude.some((pattern) => {\n if (typeof pattern === \"string\") {\n return pattern.includes(\"*\")\n ? new RegExp(pattern.replace(/\\*/g, \".*\")).test(href)\n : href === pattern;\n }\n return pattern.test(href);\n });\n }\n\n private broadcastSet(href: string): void {\n this.broadcastChannel?.postMessage({ type: \"set\", href });\n }\n\n private handleBroadcast = (event: MessageEvent): void => {\n if (event.data.type === \"set\") {\n // Invalidate memory cache to force fetch from SW\n this.memoryCache.delete(event.data.href);\n }\n };\n}\n\nexport function createCacheManager(\n config?: Partial<CacheConfig>,\n callbacks?: { onCacheHit?: (href: string, layer: CacheLayer) => void }\n): CacheManager {\n return new CacheManager(config, callbacks);\n}\n"]}
|
package/dist/index.js
CHANGED
|
@@ -226,9 +226,13 @@ var CacheManager = class {
|
|
|
226
226
|
let match;
|
|
227
227
|
while ((match = scriptRegex.exec(html)) !== null) {
|
|
228
228
|
const attrs = match[1] || "";
|
|
229
|
+
const content = match[2] || "";
|
|
229
230
|
if (/src\s*=/.test(attrs)) continue;
|
|
230
231
|
if (/type\s*=\s*["']?(application\/json|application\/ld\+json|text\/template)["']?/i.test(attrs)) continue;
|
|
231
|
-
if (/id\s*=\s*["']__NEXT_DATA__["']/i.test(attrs)) continue;
|
|
232
|
+
if (/id\s*=\s*["'](__NEXT_DATA__|_R_)["']/i.test(attrs)) continue;
|
|
233
|
+
if (/data-nscript\s*=/i.test(attrs)) continue;
|
|
234
|
+
if (/type\s*=\s*["']?module["']?/i.test(attrs)) continue;
|
|
235
|
+
if (/self\.__next_[fr]/.test(content)) continue;
|
|
232
236
|
return true;
|
|
233
237
|
}
|
|
234
238
|
return dangerousPatterns.some((pattern) => pattern.test(html));
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/trajectory.ts","../src/cache.ts","../src/morpher.ts","../src/speculator.ts","../src/graph.ts","../src/adaptive.ts","../src/performance.ts"],"names":["DEFAULT_CONFIG"],"mappings":"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","file":"index.js","sourcesContent":["import type {\n PointerSample,\n Velocity,\n LinkRect,\n TrajectoryConfig,\n} from \"./types\";\n\nconst DEFAULT_CONFIG: TrajectoryConfig = {\n lookaheadMs: 120,\n minVelocity: 0.2,\n sampleRate: 50,\n cancelOnDeviation: true,\n};\n\nexport class TrajectoryEngine {\n private samples: PointerSample[] = [];\n private links: Map<HTMLAnchorElement, LinkRect> = new Map();\n private config: TrajectoryConfig;\n private lastPrediction: string | null = null;\n private sampleInterval: number | null = null;\n private onPrediction?: (href: string) => void;\n private onCancel?: (href: string) => void;\n private cooldownMap = new Map<string, number>();\n private updateDebounceTimer: number | null = null;\n\n constructor(\n config: Partial<TrajectoryConfig> = {},\n callbacks?: {\n onPrediction?: (href: string) => void;\n onCancel?: (href: string) => void;\n }\n ) {\n this.config = { ...DEFAULT_CONFIG, ...config };\n this.onPrediction = callbacks?.onPrediction;\n this.onCancel = callbacks?.onCancel;\n }\n\n start(): void {\n if (typeof window === \"undefined\") return;\n\n window.addEventListener(\"pointermove\", this.handlePointerMove);\n this.sampleInterval = window.setInterval(\n () => this.processSamples(),\n this.config.sampleRate\n );\n }\n\n stop(): void {\n if (typeof window === \"undefined\") return;\n\n window.removeEventListener(\"pointermove\", this.handlePointerMove);\n if (this.sampleInterval) {\n clearInterval(this.sampleInterval);\n this.sampleInterval = null;\n }\n if (this.updateDebounceTimer) {\n clearTimeout(this.updateDebounceTimer);\n this.updateDebounceTimer = null;\n }\n \n // Clean up memory\n this.samples = [];\n this.links.clear();\n this.cooldownMap.clear();\n this.lastPrediction = null;\n }\n\n registerLink(href: string, element: HTMLAnchorElement): void {\n const rect = element.getBoundingClientRect();\n this.links.set(element, { href, rect, element });\n }\n\n unregisterLink(element: HTMLAnchorElement): void {\n this.links.delete(element);\n }\n\n updateLinkPositions(): void {\n // Debounce to prevent excessive reflows\n if (this.updateDebounceTimer) {\n clearTimeout(this.updateDebounceTimer);\n }\n\n this.updateDebounceTimer = window.setTimeout(() => {\n this.links.forEach((link, element) => {\n const rect = element.getBoundingClientRect();\n this.links.set(element, { ...link, rect });\n });\n this.updateDebounceTimer = null;\n }, 100);\n }\n\n private handlePointerMove = (e: PointerEvent): void => {\n this.samples.push({\n x: e.clientX,\n y: e.clientY,\n t: e.timeStamp,\n });\n\n // Keep only last 10 samples for smoothing\n if (this.samples.length > 10) {\n this.samples.shift();\n }\n };\n\n private processSamples(): void {\n if (this.samples.length < 4) return;\n\n const velocity = this.computeVelocity();\n const speed = Math.sqrt(velocity.vx ** 2 + velocity.vy ** 2);\n\n if (speed < this.config.minVelocity) {\n if (this.lastPrediction && this.config.cancelOnDeviation) {\n this.onCancel?.(this.lastPrediction);\n this.lastPrediction = null;\n }\n return;\n }\n\n const target = this.predictTarget(velocity);\n\n if (target && target.href !== this.lastPrediction) {\n // Check cooldown\n const now = Date.now();\n const lastTime = this.cooldownMap.get(target.href) ?? 0;\n const cooldown = 500; // 500ms cooldown per href\n \n if (now - lastTime < cooldown) {\n return; // Still in cooldown\n }\n\n if (this.lastPrediction && this.config.cancelOnDeviation) {\n this.onCancel?.(this.lastPrediction);\n }\n \n this.lastPrediction = target.href;\n this.cooldownMap.set(target.href, now);\n this.onPrediction?.(target.href);\n } else if (!target && this.lastPrediction && this.config.cancelOnDeviation) {\n this.onCancel?.(this.lastPrediction);\n this.lastPrediction = null;\n }\n }\n\n private computeVelocity(): Velocity {\n const recent = this.samples.slice(-4);\n const dt = recent[recent.length - 1]!.t - recent[0]!.t;\n\n if (dt === 0) return { vx: 0, vy: 0 };\n\n const dx = recent[recent.length - 1]!.x - recent[0]!.x;\n const dy = recent[recent.length - 1]!.y - recent[0]!.y;\n\n return {\n vx: dx / dt,\n vy: dy / dt,\n };\n }\n\n private projectRay(velocity: Velocity): { x: number; y: number } {\n const origin = this.samples[this.samples.length - 1]!;\n return {\n x: origin.x + velocity.vx * this.config.lookaheadMs,\n y: origin.y + velocity.vy * this.config.lookaheadMs,\n };\n }\n\n private predictTarget(velocity: Velocity): LinkRect | null {\n const tip = this.projectRay(velocity);\n\n for (const link of this.links.values()) {\n if (this.rectContains(link.rect, tip)) {\n return link;\n }\n }\n\n return null;\n }\n\n private rectContains(rect: DOMRect, point: { x: number; y: number }): boolean {\n return (\n point.x >= rect.left &&\n point.x <= rect.right &&\n point.y >= rect.top &&\n point.y <= rect.bottom\n );\n }\n}\n\nexport function createTrajectoryEngine(\n config?: Partial<TrajectoryConfig>,\n callbacks?: {\n onPrediction?: (href: string) => void;\n onCancel?: (href: string) => void;\n }\n): TrajectoryEngine {\n return new TrajectoryEngine(config, callbacks);\n}\n","import type { CacheConfig, CachedPage, CacheLayer } from \"./types\";\n\nconst DEFAULT_CONFIG: CacheConfig = {\n memory: {\n enabled: true,\n maxPages: 10,\n },\n serviceWorker: {\n enabled: true,\n ttl: 300,\n cacheName: \"specnav-v1\",\n crossTabSync: true,\n broadcastChannel: \"specnav-sync\",\n },\n edge: {\n enabled: true,\n maxAge: 60,\n staleWhileRevalidate: 300,\n },\n exclude: [],\n};\n\nexport class CacheManager {\n private config: CacheConfig;\n private memoryCache: Map<string, CachedPage> = new Map();\n private accessOrder: string[] = [];\n private broadcastChannel?: BroadcastChannel;\n private onCacheHit?: (href: string, layer: CacheLayer) => void;\n\n constructor(\n config: Partial<CacheConfig> = {},\n callbacks?: { onCacheHit?: (href: string, layer: CacheLayer) => void }\n ) {\n this.config = { ...DEFAULT_CONFIG, ...config };\n this.onCacheHit = callbacks?.onCacheHit;\n\n if (\n this.config.serviceWorker.enabled &&\n this.config.serviceWorker.crossTabSync &&\n typeof BroadcastChannel !== \"undefined\"\n ) {\n this.broadcastChannel = new BroadcastChannel(\n this.config.serviceWorker.broadcastChannel\n );\n this.broadcastChannel.onmessage = this.handleBroadcast;\n }\n }\n\n async get(href: string): Promise<string | null> {\n if (this.isExcluded(href)) return null;\n\n // L1: Memory cache\n const memoryHit = this.getFromMemory(href);\n if (memoryHit) {\n this.onCacheHit?.(href, 1);\n return memoryHit;\n }\n\n // L2: Service Worker cache\n if (this.config.serviceWorker.enabled) {\n const swHit = await this.getFromServiceWorker(href);\n if (swHit) {\n this.onCacheHit?.(href, 2);\n this.setInMemory(href, swHit);\n return swHit;\n }\n }\n\n return null;\n }\n\n async set(href: string, html: string): Promise<void> {\n if (this.isExcluded(href)) return;\n\n // Sanitize href to prevent cache poisoning\n const sanitizedHref = this.sanitizeHref(href);\n if (!sanitizedHref) return;\n\n // Validate HTML doesn't contain dangerous inline scripts\n if (this.containsDangerousContent(html)) {\n console.warn(`Refusing to cache potentially dangerous content from ${sanitizedHref}`);\n return;\n }\n\n const page: CachedPage = {\n href: sanitizedHref,\n html,\n timestamp: Date.now(),\n ttl: this.config.serviceWorker.ttl,\n };\n\n // L1: Memory\n if (this.config.memory.enabled) {\n this.setInMemory(sanitizedHref, html);\n }\n\n // L2: Service Worker\n if (this.config.serviceWorker.enabled) {\n await this.setInServiceWorker(page);\n this.broadcastSet(sanitizedHref);\n }\n }\n\n private containsDangerousContent(html: string): boolean {\n // Check for inline event handlers and javascript: URLs\n const dangerousPatterns = [\n /on\\w+\\s*=\\s*[\"'][^\"']*[\"']/i, // Inline event handlers\n /javascript:/i, // javascript: URLs\n ];\n\n // Check for inline scripts, but exclude safe types\n const scriptRegex = /<script([^>]*)>([\\s\\S]*?)<\\/script>/gi;\n let match;\n while ((match = scriptRegex.exec(html)) !== null) {\n const attrs = match[1] || \"\";\n \n // Allow scripts with src attribute\n if (/src\\s*=/.test(attrs)) continue;\n \n // Allow safe script types (JSON data, templates)\n if (/type\\s*=\\s*[\"']?(application\\/json|application\\/ld\\+json|text\\/template)[\"']?/i.test(attrs)) continue;\n \n // Allow Next.js data script\n if (/id\\s*=\\s*[\"']__NEXT_DATA__[\"']/i.test(attrs)) continue;\n \n // If we get here, it's an inline script without safe type\n return true;\n }\n\n return dangerousPatterns.some(pattern => pattern.test(html));\n }\n\n private sanitizeHref(href: string): string | null {\n try {\n const url = new URL(href, window.location.origin);\n // Only allow same-origin URLs\n if (url.origin !== window.location.origin) return null;\n return url.pathname + url.search + url.hash;\n } catch {\n return null;\n }\n }\n\n clear(href?: string): void {\n if (href) {\n this.memoryCache.delete(href);\n this.accessOrder = this.accessOrder.filter((h) => h !== href);\n this.clearFromServiceWorker(href);\n } else {\n this.memoryCache.clear();\n this.accessOrder = [];\n this.clearAllServiceWorker();\n }\n }\n\n getSize(): number {\n return this.memoryCache.size;\n }\n\n destroy(): void {\n this.memoryCache.clear();\n this.accessOrder = [];\n this.broadcastChannel?.close();\n }\n\n private getFromMemory(href: string): string | null {\n const page = this.memoryCache.get(href);\n if (!page) return null;\n\n // Update LRU order\n this.accessOrder = this.accessOrder.filter((h) => h !== href);\n this.accessOrder.push(href);\n\n return page.html;\n }\n\n private setInMemory(href: string, html: string): void {\n // Prevent memory exhaustion - limit individual page size\n const maxPageSize = 5 * 1024 * 1024; // 5MB per page\n if (html.length > maxPageSize) {\n console.warn(`Page ${href} exceeds max size, not caching`);\n return;\n }\n\n this.memoryCache.set(href, {\n href,\n html,\n timestamp: Date.now(),\n ttl: this.config.serviceWorker.ttl,\n });\n\n // Deduplicate before adding to accessOrder\n const existingIndex = this.accessOrder.indexOf(href);\n if (existingIndex !== -1) {\n this.accessOrder.splice(existingIndex, 1);\n }\n this.accessOrder.push(href);\n\n // LRU eviction\n if (this.memoryCache.size > this.config.memory.maxPages) {\n const oldest = this.accessOrder.shift();\n if (oldest) this.memoryCache.delete(oldest);\n }\n }\n\n private async getFromServiceWorker(href: string): Promise<string | null> {\n if (typeof caches === \"undefined\") return null;\n\n try {\n const cache = await caches.open(this.config.serviceWorker.cacheName);\n const response = await cache.match(href);\n\n if (!response) return null;\n\n const data = await response.json();\n const page = data as CachedPage;\n\n // Check TTL\n const age = Date.now() - page.timestamp;\n if (age > page.ttl * 1000) {\n await cache.delete(href);\n return null;\n }\n\n return page.html;\n } catch {\n return null;\n }\n }\n\n private async setInServiceWorker(page: CachedPage): Promise<void> {\n if (typeof caches === \"undefined\") return;\n\n try {\n const cache = await caches.open(this.config.serviceWorker.cacheName);\n const response = new Response(JSON.stringify(page), {\n headers: {\n \"Content-Type\": \"application/json\",\n \"Cache-Control\": `max-age=${this.config.edge.maxAge}, stale-while-revalidate=${this.config.edge.staleWhileRevalidate}`,\n },\n });\n await cache.put(page.href, response);\n } catch {\n // Silently fail\n }\n }\n\n private async clearFromServiceWorker(href: string): Promise<void> {\n if (typeof caches === \"undefined\") return;\n\n try {\n const cache = await caches.open(this.config.serviceWorker.cacheName);\n await cache.delete(href);\n } catch {\n // Silently fail\n }\n }\n\n private async clearAllServiceWorker(): Promise<void> {\n if (typeof caches === \"undefined\") return;\n\n try {\n await caches.delete(this.config.serviceWorker.cacheName);\n } catch {\n // Silently fail\n }\n }\n\n private isExcluded(href: string): boolean {\n return this.config.exclude.some((pattern) => {\n if (typeof pattern === \"string\") {\n return pattern.includes(\"*\")\n ? new RegExp(pattern.replace(/\\*/g, \".*\")).test(href)\n : href === pattern;\n }\n return pattern.test(href);\n });\n }\n\n private broadcastSet(href: string): void {\n this.broadcastChannel?.postMessage({ type: \"set\", href });\n }\n\n private handleBroadcast = (event: MessageEvent): void => {\n if (event.data.type === \"set\") {\n // Invalidate memory cache to force fetch from SW\n this.memoryCache.delete(event.data.href);\n }\n };\n}\n\nexport function createCacheManager(\n config?: Partial<CacheConfig>,\n callbacks?: { onCacheHit?: (href: string, layer: CacheLayer) => void }\n): CacheManager {\n return new CacheManager(config, callbacks);\n}\n","import type { MorphConfig } from \"./types\";\n\nconst DEFAULT_CONFIG: MorphConfig = {\n preserveScroll: true,\n preserveFocus: true,\n};\n\ninterface MorphContext {\n config: MorphConfig;\n focusedElement: Element | null;\n scrollPositions: Map<Element, { top: number; left: number }>;\n}\n\nexport class DOMmorpher {\n private config: MorphConfig;\n\n constructor(config: Partial<MorphConfig> = {}) {\n this.config = { ...DEFAULT_CONFIG, ...config };\n }\n\n morph(from: Element, to: Element): void {\n const ctx = this.createContext();\n requestAnimationFrame(() => {\n this.morphElement(from, to, ctx);\n this.restoreContext(ctx);\n });\n }\n\n private createContext(): MorphContext {\n const ctx: MorphContext = {\n config: this.config,\n focusedElement: null,\n scrollPositions: new Map(),\n };\n\n if (this.config.preserveFocus) {\n ctx.focusedElement = document.activeElement;\n }\n\n if (this.config.preserveScroll) {\n this.captureScrollPositions(document.body, ctx.scrollPositions);\n }\n\n return ctx;\n }\n\n private restoreContext(ctx: MorphContext): void {\n if (ctx.config.preserveFocus && ctx.focusedElement) {\n const element = ctx.focusedElement as HTMLElement;\n if (element.focus && document.body.contains(element)) {\n element.focus();\n }\n }\n\n if (ctx.config.preserveScroll) {\n ctx.scrollPositions.forEach((pos, element) => {\n element.scrollTop = pos.top;\n element.scrollLeft = pos.left;\n });\n }\n }\n\n private captureScrollPositions(\n element: Element,\n positions: Map<Element, { top: number; left: number }>\n ): void {\n if (element.scrollTop > 0 || element.scrollLeft > 0) {\n positions.set(element, {\n top: element.scrollTop,\n left: element.scrollLeft,\n });\n }\n\n Array.from(element.children).forEach((child) => {\n this.captureScrollPositions(child, positions);\n });\n }\n\n private morphElement(from: Element, to: Element, ctx: MorphContext): void {\n // Sync attributes\n this.syncAttributes(from, to);\n\n // Morph children\n this.morphChildren(from, to, ctx);\n }\n\n private syncAttributes(from: Element, to: Element): void {\n const fromAttrs = from.attributes;\n const toAttrs = to.attributes;\n\n // Remove attributes not in target\n for (let i = fromAttrs.length - 1; i >= 0; i--) {\n const attr = fromAttrs[i]!;\n if (!to.hasAttribute(attr.name)) {\n from.removeAttribute(attr.name);\n }\n }\n\n // Add/update attributes from target\n for (let i = 0; i < toAttrs.length; i++) {\n const attr = toAttrs[i]!;\n if (from.getAttribute(attr.name) !== attr.value) {\n from.setAttribute(attr.name, attr.value);\n }\n }\n }\n\n private morphChildren(from: Element, to: Element, ctx: MorphContext): void {\n const fromChildren = Array.from(from.childNodes);\n const toChildren = Array.from(to.childNodes);\n\n let fromIndex = 0;\n let toIndex = 0;\n\n while (toIndex < toChildren.length) {\n const toNode = toChildren[toIndex]!;\n const fromNode = fromChildren[fromIndex];\n\n if (!fromNode) {\n // Append new node\n from.appendChild(toNode.cloneNode(true));\n toIndex++;\n continue;\n }\n\n if (this.nodesMatch(fromNode, toNode)) {\n // Nodes match - recurse or update text\n if (fromNode.nodeType === Node.TEXT_NODE) {\n if (fromNode.nodeValue !== toNode.nodeValue) {\n fromNode.nodeValue = toNode.nodeValue;\n }\n } else if (fromNode.nodeType === Node.ELEMENT_NODE) {\n this.morphElement(fromNode as Element, toNode as Element, ctx);\n }\n fromIndex++;\n toIndex++;\n } else {\n // Try to find matching node ahead\n const matchIndex = this.findMatchingNode(\n fromChildren,\n fromIndex + 1,\n toNode\n );\n\n if (matchIndex !== -1) {\n // Remove nodes before match\n for (let i = fromIndex; i < matchIndex; i++) {\n from.removeChild(fromChildren[i]!);\n }\n fromIndex = matchIndex;\n } else {\n // Insert new node\n from.insertBefore(toNode.cloneNode(true), fromNode);\n toIndex++;\n }\n }\n }\n\n // Remove remaining old nodes\n while (fromIndex < fromChildren.length) {\n from.removeChild(fromChildren[fromIndex]!);\n fromIndex++;\n }\n }\n\n private nodesMatch(a: Node, b: Node): boolean {\n if (a.nodeType !== b.nodeType) return false;\n\n if (a.nodeType === Node.ELEMENT_NODE) {\n const aEl = a as Element;\n const bEl = b as Element;\n\n if (aEl.tagName !== bEl.tagName) return false;\n\n const aId = aEl.getAttribute(\"id\");\n const bId = bEl.getAttribute(\"id\");\n\n if (aId && bId) return aId === bId;\n\n return true;\n }\n\n return true;\n }\n\n private findMatchingNode(\n nodes: Node[],\n startIndex: number,\n target: Node\n ): number {\n for (let i = startIndex; i < nodes.length; i++) {\n if (this.nodesMatch(nodes[i]!, target)) {\n return i;\n }\n }\n return -1;\n }\n}\n\nexport function createMorpher(config?: Partial<MorphConfig>): DOMmorpher {\n return new DOMmorpher(config);\n}\n\nexport function morph(\n from: Element,\n to: Element,\n config?: Partial<MorphConfig>\n): void {\n const morpher = createMorpher(config);\n morpher.morph(from, to);\n}\n","interface SpeculatedPage {\n href: string;\n html: string;\n container: HTMLElement;\n timestamp: number;\n}\n\n/**\n * SpeculativeRenderer pre-renders pages in detached DOM containers.\n * \n * LIMITATIONS:\n * - This implementation uses innerHTML, NOT React rendering. The speculated content\n * is raw HTML set on a disconnected DOM node, not a fully rendered React component tree.\n * - For true React speculative rendering, the container must be appended to the document\n * (hidden via CSS) and ReactDOM.createRoot(container).render(...) must be called.\n * - Current implementation is suitable for static HTML morphing but may produce different\n * results than a real React render for dynamic components.\n */\nexport class SpeculativeRenderer {\n private speculations: Map<string, SpeculatedPage> = new Map();\n private maxSpeculations: number;\n\n constructor(maxSpeculations = 3) {\n this.maxSpeculations = maxSpeculations;\n }\n\n async speculate(href: string, html: string): Promise<void> {\n if (this.speculations.has(href)) return;\n\n // Evict oldest if at capacity\n if (this.speculations.size >= this.maxSpeculations) {\n const oldest = Array.from(this.speculations.values()).sort(\n (a, b) => a.timestamp - b.timestamp\n )[0];\n if (oldest) this.cancel(oldest.href);\n }\n\n const container = this.createDetachedContainer();\n container.innerHTML = html;\n\n this.speculations.set(href, {\n href,\n html,\n container,\n timestamp: Date.now(),\n });\n }\n\n get(href: string): HTMLElement | null {\n const speculation = this.speculations.get(href);\n return speculation?.container ?? null;\n }\n\n cancel(href: string): void {\n const speculation = this.speculations.get(href);\n if (speculation) {\n speculation.container.remove();\n this.speculations.delete(href);\n }\n }\n\n cancelAll(): void {\n this.speculations.forEach((spec) => spec.container.remove());\n this.speculations.clear();\n }\n\n has(href: string): boolean {\n return this.speculations.has(href);\n }\n\n private createDetachedContainer(): HTMLElement {\n const container = document.createElement(\"div\");\n container.style.display = \"none\";\n container.setAttribute(\"data-specnav-speculation\", \"true\");\n return container;\n }\n}\n\nexport function createSpeculativeRenderer(\n maxSpeculations?: number\n): SpeculativeRenderer {\n return new SpeculativeRenderer(maxSpeculations);\n}\n","import type { GraphConfig, NavigationGraph } from \"./types\";\n\nconst DEFAULT_CONFIG: GraphConfig = {\n enabled: true,\n minConfidence: 0.6,\n sessionWeight: 0.7,\n storageKey: \"specnav-graph\",\n maxNodes: 50,\n};\n\nexport class NavigationGraphLearner {\n private config: GraphConfig;\n private graph: NavigationGraph = {};\n private sessionGraph: NavigationGraph = {};\n\n constructor(config: Partial<GraphConfig> = {}) {\n this.config = { ...DEFAULT_CONFIG, ...config };\n if (this.config.enabled) {\n this.loadGraph();\n }\n }\n\n recordNavigation(fromHref: string, toHref: string): void {\n if (!this.config.enabled) return;\n\n // Update session graph\n if (!this.sessionGraph[fromHref]) {\n this.sessionGraph[fromHref] = {};\n }\n const current = this.sessionGraph[fromHref]![toHref] ?? 0;\n this.sessionGraph[fromHref]![toHref] = current + 1;\n\n // Update persistent graph\n if (!this.graph[fromHref]) {\n this.graph[fromHref] = {};\n }\n const persistentCurrent = this.graph[fromHref]![toHref] ?? 0;\n this.graph[fromHref]![toHref] = persistentCurrent + 1;\n\n this.saveGraph();\n }\n\n getPredictions(fromHref: string): string[] {\n if (!this.config.enabled) return [];\n\n const sessionEdges = this.sessionGraph[fromHref] ?? {};\n const persistentEdges = this.graph[fromHref] ?? {};\n\n // Merge session and persistent with weighting\n const merged: Record<string, number> = {};\n\n Object.entries(persistentEdges).forEach(([href, count]) => {\n merged[href] = count * (1 - this.config.sessionWeight);\n });\n\n Object.entries(sessionEdges).forEach(([href, count]) => {\n merged[href] = (merged[href] ?? 0) + count * this.config.sessionWeight;\n });\n\n // Calculate total for normalization\n const total = Object.values(merged).reduce((sum, val) => sum + val, 0);\n if (total === 0) return [];\n\n // Convert to confidence scores and filter\n const predictions = Object.entries(merged)\n .map(([href, count]) => ({\n href,\n confidence: count / total,\n }))\n .filter((p) => p.confidence >= this.config.minConfidence)\n .sort((a, b) => b.confidence - a.confidence)\n .map((p) => p.href);\n\n return predictions;\n }\n\n getGraph(): NavigationGraph {\n return { ...this.graph };\n }\n\n clearGraph(): void {\n this.graph = {};\n this.sessionGraph = {};\n this.saveGraph();\n }\n\n private loadGraph(): void {\n if (typeof localStorage === \"undefined\") return;\n\n try {\n const stored = localStorage.getItem(this.config.storageKey);\n if (stored) {\n this.graph = JSON.parse(stored);\n this.pruneGraph();\n }\n } catch {\n // Silently fail\n }\n }\n\n private saveGraph(): void {\n if (typeof localStorage === \"undefined\") return;\n\n try {\n this.pruneGraph();\n const serialized = JSON.stringify(this.graph);\n \n // Check size before saving (localStorage typically has 5-10MB limit)\n if (serialized.length > 4 * 1024 * 1024) { // 4MB safety limit\n console.warn(\"Navigation graph too large, pruning more aggressively\");\n // Prune to half the max nodes (use local variable)\n const reducedMaxNodes = Math.floor(this.config.maxNodes / 2);\n const originalMaxNodes = this.config.maxNodes;\n this.config.maxNodes = reducedMaxNodes;\n this.pruneGraph();\n this.config.maxNodes = originalMaxNodes; // Restore original\n }\n \n localStorage.setItem(this.config.storageKey, JSON.stringify(this.graph));\n } catch (error) {\n // Handle quota exceeded error\n if (error instanceof Error && error.name === \"QuotaExceededError\") {\n console.warn(\"localStorage quota exceeded, clearing navigation graph\");\n this.clearGraph();\n }\n }\n }\n\n private pruneGraph(): void {\n const nodes = Object.keys(this.graph);\n if (nodes.length <= this.config.maxNodes) return;\n\n // Calculate total transitions per node\n const nodeCounts = nodes.map((node) => ({\n node,\n count: Object.values(this.graph[node]!).reduce(\n (sum, val) => sum + val,\n 0\n ),\n }));\n\n // Sort by count and keep top maxNodes\n nodeCounts.sort((a, b) => b.count - a.count);\n const toKeep = new Set(\n nodeCounts.slice(0, this.config.maxNodes).map((n) => n.node)\n );\n\n // Remove nodes not in top set\n Object.keys(this.graph).forEach((node) => {\n if (!toKeep.has(node)) {\n delete this.graph[node];\n }\n });\n }\n}\n\nexport function createNavigationGraphLearner(\n config?: Partial<GraphConfig>\n): NavigationGraphLearner {\n return new NavigationGraphLearner(config);\n}\n\nexport function getNavigationGraph(\n storageKey = \"specnav-graph\"\n): NavigationGraph {\n if (typeof localStorage === \"undefined\") return {};\n\n try {\n const stored = localStorage.getItem(storageKey);\n return stored ? JSON.parse(stored) : {};\n } catch {\n return {};\n }\n}\n","import type { AdaptiveConfig, Strategy } from \"./types\";\n\nconst DEFAULT_CONFIG: AdaptiveConfig = {\n batteryThreshold: 0.2,\n connectionTypes: {\n slow: [\"2g\", \"3g\", \"slow-2g\"],\n fast: [\"4g\"],\n },\n respectSaveData: true,\n respectReducedMotion: true,\n};\n\nexport class AdaptiveMode {\n private config: AdaptiveConfig;\n private battery: any = null;\n private connection: any = null;\n private initPromise: Promise<void>;\n\n constructor(config: Partial<AdaptiveConfig> = {}) {\n this.config = { ...DEFAULT_CONFIG, ...config };\n this.initPromise = this.initialize();\n }\n\n async waitForInit(): Promise<void> {\n await this.initPromise;\n }\n\n private async initialize(): Promise<void> {\n if (typeof navigator === \"undefined\") return;\n\n // Battery API\n if (\"getBattery\" in navigator) {\n try {\n this.battery = await (navigator as any).getBattery();\n } catch {\n // Not available\n }\n }\n\n // Network Information API\n if (\"connection\" in navigator || \"mozConnection\" in navigator || \"webkitConnection\" in navigator) {\n this.connection =\n (navigator as any).connection ||\n (navigator as any).mozConnection ||\n (navigator as any).webkitConnection;\n }\n }\n\n getStrategy(baseStrategy: Strategy): Strategy {\n if (baseStrategy === \"off\") return \"off\";\n if (baseStrategy !== \"auto\") return baseStrategy;\n\n // Check Save-Data\n if (this.config.respectSaveData && this.hasSaveData()) {\n return \"off\";\n }\n\n // Check battery\n if (this.isLowBattery()) {\n return \"conservative\";\n }\n\n // Check connection\n if (this.isSlowConnection()) {\n return \"conservative\";\n }\n\n return \"aggressive\";\n }\n\n shouldPrefetch(): boolean {\n if (this.config.respectSaveData && this.hasSaveData()) {\n return false;\n }\n\n if (this.isLowBattery()) {\n return false;\n }\n\n return true;\n }\n\n shouldSpeculate(): boolean {\n if (!this.shouldPrefetch()) {\n return false;\n }\n\n if (this.isSlowConnection()) {\n return false;\n }\n\n return true;\n }\n\n shouldUseTransitions(): boolean {\n if (!this.config.respectReducedMotion) return true;\n\n if (typeof window === \"undefined\") return true;\n\n return !window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n }\n\n private hasSaveData(): boolean {\n if (typeof navigator === \"undefined\") return false;\n\n return (\n (navigator as any).connection?.saveData === true ||\n (navigator as any).mozConnection?.saveData === true ||\n (navigator as any).webkitConnection?.saveData === true\n );\n }\n\n private isLowBattery(): boolean {\n if (!this.battery) return false;\n\n return (\n !this.battery.charging &&\n this.battery.level < this.config.batteryThreshold\n );\n }\n\n private isSlowConnection(): boolean {\n if (!this.connection) return false;\n\n const effectiveType = this.connection.effectiveType;\n if (!effectiveType) return false;\n\n return this.config.connectionTypes.slow.includes(effectiveType);\n }\n\n isFastConnection(): boolean {\n if (!this.connection) return true; // Assume fast if unknown\n\n const effectiveType = this.connection.effectiveType;\n if (!effectiveType) return true;\n\n return this.config.connectionTypes.fast.includes(effectiveType);\n }\n\n getBatteryLevel(): number | null {\n return this.battery?.level ?? null;\n }\n\n getConnectionType(): string | null {\n return this.connection?.effectiveType ?? null;\n }\n}\n\nexport function createAdaptiveMode(\n config?: Partial<AdaptiveConfig>\n): AdaptiveMode {\n return new AdaptiveMode(config);\n}\n","// Performance monitoring utilities\n\nexport interface PerformanceMetrics {\n navigationTime: number;\n cacheHit: boolean;\n cacheLayer?: 1 | 2 | 3;\n speculativeHit: boolean;\n fetchTime?: number;\n morphTime?: number;\n}\n\nexport class PerformanceMonitor {\n private metrics: PerformanceMetrics[] = [];\n private maxMetrics = 100;\n\n recordNavigation(metrics: PerformanceMetrics): void {\n this.metrics.push(metrics);\n \n // Keep only last N metrics\n if (this.metrics.length > this.maxMetrics) {\n this.metrics.shift();\n }\n }\n\n getAverageNavigationTime(): number {\n if (this.metrics.length === 0) return 0;\n const sum = this.metrics.reduce((acc, m) => acc + m.navigationTime, 0);\n return sum / this.metrics.length;\n }\n\n getCacheHitRate(): number {\n if (this.metrics.length === 0) return 0;\n const hits = this.metrics.filter(m => m.cacheHit).length;\n return hits / this.metrics.length;\n }\n\n getSpeculativeHitRate(): number {\n if (this.metrics.length === 0) return 0;\n const hits = this.metrics.filter(m => m.speculativeHit).length;\n return hits / this.metrics.length;\n }\n\n getMetrics(): PerformanceMetrics[] {\n return [...this.metrics];\n }\n\n clear(): void {\n this.metrics = [];\n }\n}\n\nexport const performanceMonitor = new PerformanceMonitor();\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/trajectory.ts","../src/cache.ts","../src/morpher.ts","../src/speculator.ts","../src/graph.ts","../src/adaptive.ts","../src/performance.ts"],"names":["DEFAULT_CONFIG"],"mappings":"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","file":"index.js","sourcesContent":["import type {\n PointerSample,\n Velocity,\n LinkRect,\n TrajectoryConfig,\n} from \"./types\";\n\nconst DEFAULT_CONFIG: TrajectoryConfig = {\n lookaheadMs: 120,\n minVelocity: 0.2,\n sampleRate: 50,\n cancelOnDeviation: true,\n};\n\nexport class TrajectoryEngine {\n private samples: PointerSample[] = [];\n private links: Map<HTMLAnchorElement, LinkRect> = new Map();\n private config: TrajectoryConfig;\n private lastPrediction: string | null = null;\n private sampleInterval: number | null = null;\n private onPrediction?: (href: string) => void;\n private onCancel?: (href: string) => void;\n private cooldownMap = new Map<string, number>();\n private updateDebounceTimer: number | null = null;\n\n constructor(\n config: Partial<TrajectoryConfig> = {},\n callbacks?: {\n onPrediction?: (href: string) => void;\n onCancel?: (href: string) => void;\n }\n ) {\n this.config = { ...DEFAULT_CONFIG, ...config };\n this.onPrediction = callbacks?.onPrediction;\n this.onCancel = callbacks?.onCancel;\n }\n\n start(): void {\n if (typeof window === \"undefined\") return;\n\n window.addEventListener(\"pointermove\", this.handlePointerMove);\n this.sampleInterval = window.setInterval(\n () => this.processSamples(),\n this.config.sampleRate\n );\n }\n\n stop(): void {\n if (typeof window === \"undefined\") return;\n\n window.removeEventListener(\"pointermove\", this.handlePointerMove);\n if (this.sampleInterval) {\n clearInterval(this.sampleInterval);\n this.sampleInterval = null;\n }\n if (this.updateDebounceTimer) {\n clearTimeout(this.updateDebounceTimer);\n this.updateDebounceTimer = null;\n }\n \n // Clean up memory\n this.samples = [];\n this.links.clear();\n this.cooldownMap.clear();\n this.lastPrediction = null;\n }\n\n registerLink(href: string, element: HTMLAnchorElement): void {\n const rect = element.getBoundingClientRect();\n this.links.set(element, { href, rect, element });\n }\n\n unregisterLink(element: HTMLAnchorElement): void {\n this.links.delete(element);\n }\n\n updateLinkPositions(): void {\n // Debounce to prevent excessive reflows\n if (this.updateDebounceTimer) {\n clearTimeout(this.updateDebounceTimer);\n }\n\n this.updateDebounceTimer = window.setTimeout(() => {\n this.links.forEach((link, element) => {\n const rect = element.getBoundingClientRect();\n this.links.set(element, { ...link, rect });\n });\n this.updateDebounceTimer = null;\n }, 100);\n }\n\n private handlePointerMove = (e: PointerEvent): void => {\n this.samples.push({\n x: e.clientX,\n y: e.clientY,\n t: e.timeStamp,\n });\n\n // Keep only last 10 samples for smoothing\n if (this.samples.length > 10) {\n this.samples.shift();\n }\n };\n\n private processSamples(): void {\n if (this.samples.length < 4) return;\n\n const velocity = this.computeVelocity();\n const speed = Math.sqrt(velocity.vx ** 2 + velocity.vy ** 2);\n\n if (speed < this.config.minVelocity) {\n if (this.lastPrediction && this.config.cancelOnDeviation) {\n this.onCancel?.(this.lastPrediction);\n this.lastPrediction = null;\n }\n return;\n }\n\n const target = this.predictTarget(velocity);\n\n if (target && target.href !== this.lastPrediction) {\n // Check cooldown\n const now = Date.now();\n const lastTime = this.cooldownMap.get(target.href) ?? 0;\n const cooldown = 500; // 500ms cooldown per href\n \n if (now - lastTime < cooldown) {\n return; // Still in cooldown\n }\n\n if (this.lastPrediction && this.config.cancelOnDeviation) {\n this.onCancel?.(this.lastPrediction);\n }\n \n this.lastPrediction = target.href;\n this.cooldownMap.set(target.href, now);\n this.onPrediction?.(target.href);\n } else if (!target && this.lastPrediction && this.config.cancelOnDeviation) {\n this.onCancel?.(this.lastPrediction);\n this.lastPrediction = null;\n }\n }\n\n private computeVelocity(): Velocity {\n const recent = this.samples.slice(-4);\n const dt = recent[recent.length - 1]!.t - recent[0]!.t;\n\n if (dt === 0) return { vx: 0, vy: 0 };\n\n const dx = recent[recent.length - 1]!.x - recent[0]!.x;\n const dy = recent[recent.length - 1]!.y - recent[0]!.y;\n\n return {\n vx: dx / dt,\n vy: dy / dt,\n };\n }\n\n private projectRay(velocity: Velocity): { x: number; y: number } {\n const origin = this.samples[this.samples.length - 1]!;\n return {\n x: origin.x + velocity.vx * this.config.lookaheadMs,\n y: origin.y + velocity.vy * this.config.lookaheadMs,\n };\n }\n\n private predictTarget(velocity: Velocity): LinkRect | null {\n const tip = this.projectRay(velocity);\n\n for (const link of this.links.values()) {\n if (this.rectContains(link.rect, tip)) {\n return link;\n }\n }\n\n return null;\n }\n\n private rectContains(rect: DOMRect, point: { x: number; y: number }): boolean {\n return (\n point.x >= rect.left &&\n point.x <= rect.right &&\n point.y >= rect.top &&\n point.y <= rect.bottom\n );\n }\n}\n\nexport function createTrajectoryEngine(\n config?: Partial<TrajectoryConfig>,\n callbacks?: {\n onPrediction?: (href: string) => void;\n onCancel?: (href: string) => void;\n }\n): TrajectoryEngine {\n return new TrajectoryEngine(config, callbacks);\n}\n","import type { CacheConfig, CachedPage, CacheLayer } from \"./types\";\n\nconst DEFAULT_CONFIG: CacheConfig = {\n memory: {\n enabled: true,\n maxPages: 10,\n },\n serviceWorker: {\n enabled: true,\n ttl: 300,\n cacheName: \"specnav-v1\",\n crossTabSync: true,\n broadcastChannel: \"specnav-sync\",\n },\n edge: {\n enabled: true,\n maxAge: 60,\n staleWhileRevalidate: 300,\n },\n exclude: [],\n};\n\nexport class CacheManager {\n private config: CacheConfig;\n private memoryCache: Map<string, CachedPage> = new Map();\n private accessOrder: string[] = [];\n private broadcastChannel?: BroadcastChannel;\n private onCacheHit?: (href: string, layer: CacheLayer) => void;\n\n constructor(\n config: Partial<CacheConfig> = {},\n callbacks?: { onCacheHit?: (href: string, layer: CacheLayer) => void }\n ) {\n this.config = { ...DEFAULT_CONFIG, ...config };\n this.onCacheHit = callbacks?.onCacheHit;\n\n if (\n this.config.serviceWorker.enabled &&\n this.config.serviceWorker.crossTabSync &&\n typeof BroadcastChannel !== \"undefined\"\n ) {\n this.broadcastChannel = new BroadcastChannel(\n this.config.serviceWorker.broadcastChannel\n );\n this.broadcastChannel.onmessage = this.handleBroadcast;\n }\n }\n\n async get(href: string): Promise<string | null> {\n if (this.isExcluded(href)) return null;\n\n // L1: Memory cache\n const memoryHit = this.getFromMemory(href);\n if (memoryHit) {\n this.onCacheHit?.(href, 1);\n return memoryHit;\n }\n\n // L2: Service Worker cache\n if (this.config.serviceWorker.enabled) {\n const swHit = await this.getFromServiceWorker(href);\n if (swHit) {\n this.onCacheHit?.(href, 2);\n this.setInMemory(href, swHit);\n return swHit;\n }\n }\n\n return null;\n }\n\n async set(href: string, html: string): Promise<void> {\n if (this.isExcluded(href)) return;\n\n // Sanitize href to prevent cache poisoning\n const sanitizedHref = this.sanitizeHref(href);\n if (!sanitizedHref) return;\n\n // Validate HTML doesn't contain dangerous inline scripts\n if (this.containsDangerousContent(html)) {\n console.warn(`Refusing to cache potentially dangerous content from ${sanitizedHref}`);\n return;\n }\n\n const page: CachedPage = {\n href: sanitizedHref,\n html,\n timestamp: Date.now(),\n ttl: this.config.serviceWorker.ttl,\n };\n\n // L1: Memory\n if (this.config.memory.enabled) {\n this.setInMemory(sanitizedHref, html);\n }\n\n // L2: Service Worker\n if (this.config.serviceWorker.enabled) {\n await this.setInServiceWorker(page);\n this.broadcastSet(sanitizedHref);\n }\n }\n\n private containsDangerousContent(html: string): boolean {\n // Check for inline event handlers and javascript: URLs\n const dangerousPatterns = [\n /on\\w+\\s*=\\s*[\"'][^\"']*[\"']/i, // Inline event handlers\n /javascript:/i, // javascript: URLs\n ];\n\n // Check for inline scripts, but exclude safe types\n const scriptRegex = /<script([^>]*)>([\\s\\S]*?)<\\/script>/gi;\n let match;\n while ((match = scriptRegex.exec(html)) !== null) {\n const attrs = match[1] || \"\";\n const content = match[2] || \"\";\n \n // Allow scripts with src attribute\n if (/src\\s*=/.test(attrs)) continue;\n \n // Allow safe script types (JSON data, templates)\n if (/type\\s*=\\s*[\"']?(application\\/json|application\\/ld\\+json|text\\/template)[\"']?/i.test(attrs)) continue;\n \n // Allow Next.js scripts\n if (/id\\s*=\\s*[\"'](__NEXT_DATA__|_R_)[\"']/i.test(attrs)) continue;\n if (/data-nscript\\s*=/i.test(attrs)) continue;\n \n // Allow module scripts (Next.js uses these for hydration)\n if (/type\\s*=\\s*[\"']?module[\"']?/i.test(attrs)) continue;\n \n // Allow Next.js hydration scripts (self.__next_f, self.__next_r)\n if (/self\\.__next_[fr]/.test(content)) continue;\n \n // If we get here, it's an inline script without safe type\n return true;\n }\n\n return dangerousPatterns.some(pattern => pattern.test(html));\n }\n\n private sanitizeHref(href: string): string | null {\n try {\n const url = new URL(href, window.location.origin);\n // Only allow same-origin URLs\n if (url.origin !== window.location.origin) return null;\n return url.pathname + url.search + url.hash;\n } catch {\n return null;\n }\n }\n\n clear(href?: string): void {\n if (href) {\n this.memoryCache.delete(href);\n this.accessOrder = this.accessOrder.filter((h) => h !== href);\n this.clearFromServiceWorker(href);\n } else {\n this.memoryCache.clear();\n this.accessOrder = [];\n this.clearAllServiceWorker();\n }\n }\n\n getSize(): number {\n return this.memoryCache.size;\n }\n\n destroy(): void {\n this.memoryCache.clear();\n this.accessOrder = [];\n this.broadcastChannel?.close();\n }\n\n private getFromMemory(href: string): string | null {\n const page = this.memoryCache.get(href);\n if (!page) return null;\n\n // Update LRU order\n this.accessOrder = this.accessOrder.filter((h) => h !== href);\n this.accessOrder.push(href);\n\n return page.html;\n }\n\n private setInMemory(href: string, html: string): void {\n // Prevent memory exhaustion - limit individual page size\n const maxPageSize = 5 * 1024 * 1024; // 5MB per page\n if (html.length > maxPageSize) {\n console.warn(`Page ${href} exceeds max size, not caching`);\n return;\n }\n\n this.memoryCache.set(href, {\n href,\n html,\n timestamp: Date.now(),\n ttl: this.config.serviceWorker.ttl,\n });\n\n // Deduplicate before adding to accessOrder\n const existingIndex = this.accessOrder.indexOf(href);\n if (existingIndex !== -1) {\n this.accessOrder.splice(existingIndex, 1);\n }\n this.accessOrder.push(href);\n\n // LRU eviction\n if (this.memoryCache.size > this.config.memory.maxPages) {\n const oldest = this.accessOrder.shift();\n if (oldest) this.memoryCache.delete(oldest);\n }\n }\n\n private async getFromServiceWorker(href: string): Promise<string | null> {\n if (typeof caches === \"undefined\") return null;\n\n try {\n const cache = await caches.open(this.config.serviceWorker.cacheName);\n const response = await cache.match(href);\n\n if (!response) return null;\n\n const data = await response.json();\n const page = data as CachedPage;\n\n // Check TTL\n const age = Date.now() - page.timestamp;\n if (age > page.ttl * 1000) {\n await cache.delete(href);\n return null;\n }\n\n return page.html;\n } catch {\n return null;\n }\n }\n\n private async setInServiceWorker(page: CachedPage): Promise<void> {\n if (typeof caches === \"undefined\") return;\n\n try {\n const cache = await caches.open(this.config.serviceWorker.cacheName);\n const response = new Response(JSON.stringify(page), {\n headers: {\n \"Content-Type\": \"application/json\",\n \"Cache-Control\": `max-age=${this.config.edge.maxAge}, stale-while-revalidate=${this.config.edge.staleWhileRevalidate}`,\n },\n });\n await cache.put(page.href, response);\n } catch {\n // Silently fail\n }\n }\n\n private async clearFromServiceWorker(href: string): Promise<void> {\n if (typeof caches === \"undefined\") return;\n\n try {\n const cache = await caches.open(this.config.serviceWorker.cacheName);\n await cache.delete(href);\n } catch {\n // Silently fail\n }\n }\n\n private async clearAllServiceWorker(): Promise<void> {\n if (typeof caches === \"undefined\") return;\n\n try {\n await caches.delete(this.config.serviceWorker.cacheName);\n } catch {\n // Silently fail\n }\n }\n\n private isExcluded(href: string): boolean {\n return this.config.exclude.some((pattern) => {\n if (typeof pattern === \"string\") {\n return pattern.includes(\"*\")\n ? new RegExp(pattern.replace(/\\*/g, \".*\")).test(href)\n : href === pattern;\n }\n return pattern.test(href);\n });\n }\n\n private broadcastSet(href: string): void {\n this.broadcastChannel?.postMessage({ type: \"set\", href });\n }\n\n private handleBroadcast = (event: MessageEvent): void => {\n if (event.data.type === \"set\") {\n // Invalidate memory cache to force fetch from SW\n this.memoryCache.delete(event.data.href);\n }\n };\n}\n\nexport function createCacheManager(\n config?: Partial<CacheConfig>,\n callbacks?: { onCacheHit?: (href: string, layer: CacheLayer) => void }\n): CacheManager {\n return new CacheManager(config, callbacks);\n}\n","import type { MorphConfig } from \"./types\";\n\nconst DEFAULT_CONFIG: MorphConfig = {\n preserveScroll: true,\n preserveFocus: true,\n};\n\ninterface MorphContext {\n config: MorphConfig;\n focusedElement: Element | null;\n scrollPositions: Map<Element, { top: number; left: number }>;\n}\n\nexport class DOMmorpher {\n private config: MorphConfig;\n\n constructor(config: Partial<MorphConfig> = {}) {\n this.config = { ...DEFAULT_CONFIG, ...config };\n }\n\n morph(from: Element, to: Element): void {\n const ctx = this.createContext();\n requestAnimationFrame(() => {\n this.morphElement(from, to, ctx);\n this.restoreContext(ctx);\n });\n }\n\n private createContext(): MorphContext {\n const ctx: MorphContext = {\n config: this.config,\n focusedElement: null,\n scrollPositions: new Map(),\n };\n\n if (this.config.preserveFocus) {\n ctx.focusedElement = document.activeElement;\n }\n\n if (this.config.preserveScroll) {\n this.captureScrollPositions(document.body, ctx.scrollPositions);\n }\n\n return ctx;\n }\n\n private restoreContext(ctx: MorphContext): void {\n if (ctx.config.preserveFocus && ctx.focusedElement) {\n const element = ctx.focusedElement as HTMLElement;\n if (element.focus && document.body.contains(element)) {\n element.focus();\n }\n }\n\n if (ctx.config.preserveScroll) {\n ctx.scrollPositions.forEach((pos, element) => {\n element.scrollTop = pos.top;\n element.scrollLeft = pos.left;\n });\n }\n }\n\n private captureScrollPositions(\n element: Element,\n positions: Map<Element, { top: number; left: number }>\n ): void {\n if (element.scrollTop > 0 || element.scrollLeft > 0) {\n positions.set(element, {\n top: element.scrollTop,\n left: element.scrollLeft,\n });\n }\n\n Array.from(element.children).forEach((child) => {\n this.captureScrollPositions(child, positions);\n });\n }\n\n private morphElement(from: Element, to: Element, ctx: MorphContext): void {\n // Sync attributes\n this.syncAttributes(from, to);\n\n // Morph children\n this.morphChildren(from, to, ctx);\n }\n\n private syncAttributes(from: Element, to: Element): void {\n const fromAttrs = from.attributes;\n const toAttrs = to.attributes;\n\n // Remove attributes not in target\n for (let i = fromAttrs.length - 1; i >= 0; i--) {\n const attr = fromAttrs[i]!;\n if (!to.hasAttribute(attr.name)) {\n from.removeAttribute(attr.name);\n }\n }\n\n // Add/update attributes from target\n for (let i = 0; i < toAttrs.length; i++) {\n const attr = toAttrs[i]!;\n if (from.getAttribute(attr.name) !== attr.value) {\n from.setAttribute(attr.name, attr.value);\n }\n }\n }\n\n private morphChildren(from: Element, to: Element, ctx: MorphContext): void {\n const fromChildren = Array.from(from.childNodes);\n const toChildren = Array.from(to.childNodes);\n\n let fromIndex = 0;\n let toIndex = 0;\n\n while (toIndex < toChildren.length) {\n const toNode = toChildren[toIndex]!;\n const fromNode = fromChildren[fromIndex];\n\n if (!fromNode) {\n // Append new node\n from.appendChild(toNode.cloneNode(true));\n toIndex++;\n continue;\n }\n\n if (this.nodesMatch(fromNode, toNode)) {\n // Nodes match - recurse or update text\n if (fromNode.nodeType === Node.TEXT_NODE) {\n if (fromNode.nodeValue !== toNode.nodeValue) {\n fromNode.nodeValue = toNode.nodeValue;\n }\n } else if (fromNode.nodeType === Node.ELEMENT_NODE) {\n this.morphElement(fromNode as Element, toNode as Element, ctx);\n }\n fromIndex++;\n toIndex++;\n } else {\n // Try to find matching node ahead\n const matchIndex = this.findMatchingNode(\n fromChildren,\n fromIndex + 1,\n toNode\n );\n\n if (matchIndex !== -1) {\n // Remove nodes before match\n for (let i = fromIndex; i < matchIndex; i++) {\n from.removeChild(fromChildren[i]!);\n }\n fromIndex = matchIndex;\n } else {\n // Insert new node\n from.insertBefore(toNode.cloneNode(true), fromNode);\n toIndex++;\n }\n }\n }\n\n // Remove remaining old nodes\n while (fromIndex < fromChildren.length) {\n from.removeChild(fromChildren[fromIndex]!);\n fromIndex++;\n }\n }\n\n private nodesMatch(a: Node, b: Node): boolean {\n if (a.nodeType !== b.nodeType) return false;\n\n if (a.nodeType === Node.ELEMENT_NODE) {\n const aEl = a as Element;\n const bEl = b as Element;\n\n if (aEl.tagName !== bEl.tagName) return false;\n\n const aId = aEl.getAttribute(\"id\");\n const bId = bEl.getAttribute(\"id\");\n\n if (aId && bId) return aId === bId;\n\n return true;\n }\n\n return true;\n }\n\n private findMatchingNode(\n nodes: Node[],\n startIndex: number,\n target: Node\n ): number {\n for (let i = startIndex; i < nodes.length; i++) {\n if (this.nodesMatch(nodes[i]!, target)) {\n return i;\n }\n }\n return -1;\n }\n}\n\nexport function createMorpher(config?: Partial<MorphConfig>): DOMmorpher {\n return new DOMmorpher(config);\n}\n\nexport function morph(\n from: Element,\n to: Element,\n config?: Partial<MorphConfig>\n): void {\n const morpher = createMorpher(config);\n morpher.morph(from, to);\n}\n","interface SpeculatedPage {\n href: string;\n html: string;\n container: HTMLElement;\n timestamp: number;\n}\n\n/**\n * SpeculativeRenderer pre-renders pages in detached DOM containers.\n * \n * LIMITATIONS:\n * - This implementation uses innerHTML, NOT React rendering. The speculated content\n * is raw HTML set on a disconnected DOM node, not a fully rendered React component tree.\n * - For true React speculative rendering, the container must be appended to the document\n * (hidden via CSS) and ReactDOM.createRoot(container).render(...) must be called.\n * - Current implementation is suitable for static HTML morphing but may produce different\n * results than a real React render for dynamic components.\n */\nexport class SpeculativeRenderer {\n private speculations: Map<string, SpeculatedPage> = new Map();\n private maxSpeculations: number;\n\n constructor(maxSpeculations = 3) {\n this.maxSpeculations = maxSpeculations;\n }\n\n async speculate(href: string, html: string): Promise<void> {\n if (this.speculations.has(href)) return;\n\n // Evict oldest if at capacity\n if (this.speculations.size >= this.maxSpeculations) {\n const oldest = Array.from(this.speculations.values()).sort(\n (a, b) => a.timestamp - b.timestamp\n )[0];\n if (oldest) this.cancel(oldest.href);\n }\n\n const container = this.createDetachedContainer();\n container.innerHTML = html;\n\n this.speculations.set(href, {\n href,\n html,\n container,\n timestamp: Date.now(),\n });\n }\n\n get(href: string): HTMLElement | null {\n const speculation = this.speculations.get(href);\n return speculation?.container ?? null;\n }\n\n cancel(href: string): void {\n const speculation = this.speculations.get(href);\n if (speculation) {\n speculation.container.remove();\n this.speculations.delete(href);\n }\n }\n\n cancelAll(): void {\n this.speculations.forEach((spec) => spec.container.remove());\n this.speculations.clear();\n }\n\n has(href: string): boolean {\n return this.speculations.has(href);\n }\n\n private createDetachedContainer(): HTMLElement {\n const container = document.createElement(\"div\");\n container.style.display = \"none\";\n container.setAttribute(\"data-specnav-speculation\", \"true\");\n return container;\n }\n}\n\nexport function createSpeculativeRenderer(\n maxSpeculations?: number\n): SpeculativeRenderer {\n return new SpeculativeRenderer(maxSpeculations);\n}\n","import type { GraphConfig, NavigationGraph } from \"./types\";\n\nconst DEFAULT_CONFIG: GraphConfig = {\n enabled: true,\n minConfidence: 0.6,\n sessionWeight: 0.7,\n storageKey: \"specnav-graph\",\n maxNodes: 50,\n};\n\nexport class NavigationGraphLearner {\n private config: GraphConfig;\n private graph: NavigationGraph = {};\n private sessionGraph: NavigationGraph = {};\n\n constructor(config: Partial<GraphConfig> = {}) {\n this.config = { ...DEFAULT_CONFIG, ...config };\n if (this.config.enabled) {\n this.loadGraph();\n }\n }\n\n recordNavigation(fromHref: string, toHref: string): void {\n if (!this.config.enabled) return;\n\n // Update session graph\n if (!this.sessionGraph[fromHref]) {\n this.sessionGraph[fromHref] = {};\n }\n const current = this.sessionGraph[fromHref]![toHref] ?? 0;\n this.sessionGraph[fromHref]![toHref] = current + 1;\n\n // Update persistent graph\n if (!this.graph[fromHref]) {\n this.graph[fromHref] = {};\n }\n const persistentCurrent = this.graph[fromHref]![toHref] ?? 0;\n this.graph[fromHref]![toHref] = persistentCurrent + 1;\n\n this.saveGraph();\n }\n\n getPredictions(fromHref: string): string[] {\n if (!this.config.enabled) return [];\n\n const sessionEdges = this.sessionGraph[fromHref] ?? {};\n const persistentEdges = this.graph[fromHref] ?? {};\n\n // Merge session and persistent with weighting\n const merged: Record<string, number> = {};\n\n Object.entries(persistentEdges).forEach(([href, count]) => {\n merged[href] = count * (1 - this.config.sessionWeight);\n });\n\n Object.entries(sessionEdges).forEach(([href, count]) => {\n merged[href] = (merged[href] ?? 0) + count * this.config.sessionWeight;\n });\n\n // Calculate total for normalization\n const total = Object.values(merged).reduce((sum, val) => sum + val, 0);\n if (total === 0) return [];\n\n // Convert to confidence scores and filter\n const predictions = Object.entries(merged)\n .map(([href, count]) => ({\n href,\n confidence: count / total,\n }))\n .filter((p) => p.confidence >= this.config.minConfidence)\n .sort((a, b) => b.confidence - a.confidence)\n .map((p) => p.href);\n\n return predictions;\n }\n\n getGraph(): NavigationGraph {\n return { ...this.graph };\n }\n\n clearGraph(): void {\n this.graph = {};\n this.sessionGraph = {};\n this.saveGraph();\n }\n\n private loadGraph(): void {\n if (typeof localStorage === \"undefined\") return;\n\n try {\n const stored = localStorage.getItem(this.config.storageKey);\n if (stored) {\n this.graph = JSON.parse(stored);\n this.pruneGraph();\n }\n } catch {\n // Silently fail\n }\n }\n\n private saveGraph(): void {\n if (typeof localStorage === \"undefined\") return;\n\n try {\n this.pruneGraph();\n const serialized = JSON.stringify(this.graph);\n \n // Check size before saving (localStorage typically has 5-10MB limit)\n if (serialized.length > 4 * 1024 * 1024) { // 4MB safety limit\n console.warn(\"Navigation graph too large, pruning more aggressively\");\n // Prune to half the max nodes (use local variable)\n const reducedMaxNodes = Math.floor(this.config.maxNodes / 2);\n const originalMaxNodes = this.config.maxNodes;\n this.config.maxNodes = reducedMaxNodes;\n this.pruneGraph();\n this.config.maxNodes = originalMaxNodes; // Restore original\n }\n \n localStorage.setItem(this.config.storageKey, JSON.stringify(this.graph));\n } catch (error) {\n // Handle quota exceeded error\n if (error instanceof Error && error.name === \"QuotaExceededError\") {\n console.warn(\"localStorage quota exceeded, clearing navigation graph\");\n this.clearGraph();\n }\n }\n }\n\n private pruneGraph(): void {\n const nodes = Object.keys(this.graph);\n if (nodes.length <= this.config.maxNodes) return;\n\n // Calculate total transitions per node\n const nodeCounts = nodes.map((node) => ({\n node,\n count: Object.values(this.graph[node]!).reduce(\n (sum, val) => sum + val,\n 0\n ),\n }));\n\n // Sort by count and keep top maxNodes\n nodeCounts.sort((a, b) => b.count - a.count);\n const toKeep = new Set(\n nodeCounts.slice(0, this.config.maxNodes).map((n) => n.node)\n );\n\n // Remove nodes not in top set\n Object.keys(this.graph).forEach((node) => {\n if (!toKeep.has(node)) {\n delete this.graph[node];\n }\n });\n }\n}\n\nexport function createNavigationGraphLearner(\n config?: Partial<GraphConfig>\n): NavigationGraphLearner {\n return new NavigationGraphLearner(config);\n}\n\nexport function getNavigationGraph(\n storageKey = \"specnav-graph\"\n): NavigationGraph {\n if (typeof localStorage === \"undefined\") return {};\n\n try {\n const stored = localStorage.getItem(storageKey);\n return stored ? JSON.parse(stored) : {};\n } catch {\n return {};\n }\n}\n","import type { AdaptiveConfig, Strategy } from \"./types\";\n\nconst DEFAULT_CONFIG: AdaptiveConfig = {\n batteryThreshold: 0.2,\n connectionTypes: {\n slow: [\"2g\", \"3g\", \"slow-2g\"],\n fast: [\"4g\"],\n },\n respectSaveData: true,\n respectReducedMotion: true,\n};\n\nexport class AdaptiveMode {\n private config: AdaptiveConfig;\n private battery: any = null;\n private connection: any = null;\n private initPromise: Promise<void>;\n\n constructor(config: Partial<AdaptiveConfig> = {}) {\n this.config = { ...DEFAULT_CONFIG, ...config };\n this.initPromise = this.initialize();\n }\n\n async waitForInit(): Promise<void> {\n await this.initPromise;\n }\n\n private async initialize(): Promise<void> {\n if (typeof navigator === \"undefined\") return;\n\n // Battery API\n if (\"getBattery\" in navigator) {\n try {\n this.battery = await (navigator as any).getBattery();\n } catch {\n // Not available\n }\n }\n\n // Network Information API\n if (\"connection\" in navigator || \"mozConnection\" in navigator || \"webkitConnection\" in navigator) {\n this.connection =\n (navigator as any).connection ||\n (navigator as any).mozConnection ||\n (navigator as any).webkitConnection;\n }\n }\n\n getStrategy(baseStrategy: Strategy): Strategy {\n if (baseStrategy === \"off\") return \"off\";\n if (baseStrategy !== \"auto\") return baseStrategy;\n\n // Check Save-Data\n if (this.config.respectSaveData && this.hasSaveData()) {\n return \"off\";\n }\n\n // Check battery\n if (this.isLowBattery()) {\n return \"conservative\";\n }\n\n // Check connection\n if (this.isSlowConnection()) {\n return \"conservative\";\n }\n\n return \"aggressive\";\n }\n\n shouldPrefetch(): boolean {\n if (this.config.respectSaveData && this.hasSaveData()) {\n return false;\n }\n\n if (this.isLowBattery()) {\n return false;\n }\n\n return true;\n }\n\n shouldSpeculate(): boolean {\n if (!this.shouldPrefetch()) {\n return false;\n }\n\n if (this.isSlowConnection()) {\n return false;\n }\n\n return true;\n }\n\n shouldUseTransitions(): boolean {\n if (!this.config.respectReducedMotion) return true;\n\n if (typeof window === \"undefined\") return true;\n\n return !window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n }\n\n private hasSaveData(): boolean {\n if (typeof navigator === \"undefined\") return false;\n\n return (\n (navigator as any).connection?.saveData === true ||\n (navigator as any).mozConnection?.saveData === true ||\n (navigator as any).webkitConnection?.saveData === true\n );\n }\n\n private isLowBattery(): boolean {\n if (!this.battery) return false;\n\n return (\n !this.battery.charging &&\n this.battery.level < this.config.batteryThreshold\n );\n }\n\n private isSlowConnection(): boolean {\n if (!this.connection) return false;\n\n const effectiveType = this.connection.effectiveType;\n if (!effectiveType) return false;\n\n return this.config.connectionTypes.slow.includes(effectiveType);\n }\n\n isFastConnection(): boolean {\n if (!this.connection) return true; // Assume fast if unknown\n\n const effectiveType = this.connection.effectiveType;\n if (!effectiveType) return true;\n\n return this.config.connectionTypes.fast.includes(effectiveType);\n }\n\n getBatteryLevel(): number | null {\n return this.battery?.level ?? null;\n }\n\n getConnectionType(): string | null {\n return this.connection?.effectiveType ?? null;\n }\n}\n\nexport function createAdaptiveMode(\n config?: Partial<AdaptiveConfig>\n): AdaptiveMode {\n return new AdaptiveMode(config);\n}\n","// Performance monitoring utilities\n\nexport interface PerformanceMetrics {\n navigationTime: number;\n cacheHit: boolean;\n cacheLayer?: 1 | 2 | 3;\n speculativeHit: boolean;\n fetchTime?: number;\n morphTime?: number;\n}\n\nexport class PerformanceMonitor {\n private metrics: PerformanceMetrics[] = [];\n private maxMetrics = 100;\n\n recordNavigation(metrics: PerformanceMetrics): void {\n this.metrics.push(metrics);\n \n // Keep only last N metrics\n if (this.metrics.length > this.maxMetrics) {\n this.metrics.shift();\n }\n }\n\n getAverageNavigationTime(): number {\n if (this.metrics.length === 0) return 0;\n const sum = this.metrics.reduce((acc, m) => acc + m.navigationTime, 0);\n return sum / this.metrics.length;\n }\n\n getCacheHitRate(): number {\n if (this.metrics.length === 0) return 0;\n const hits = this.metrics.filter(m => m.cacheHit).length;\n return hits / this.metrics.length;\n }\n\n getSpeculativeHitRate(): number {\n if (this.metrics.length === 0) return 0;\n const hits = this.metrics.filter(m => m.speculativeHit).length;\n return hits / this.metrics.length;\n }\n\n getMetrics(): PerformanceMetrics[] {\n return [...this.metrics];\n }\n\n clear(): void {\n this.metrics = [];\n }\n}\n\nexport const performanceMonitor = new PerformanceMonitor();\n"]}
|
package/dist/index.mjs
CHANGED
|
@@ -224,9 +224,13 @@ var CacheManager = class {
|
|
|
224
224
|
let match;
|
|
225
225
|
while ((match = scriptRegex.exec(html)) !== null) {
|
|
226
226
|
const attrs = match[1] || "";
|
|
227
|
+
const content = match[2] || "";
|
|
227
228
|
if (/src\s*=/.test(attrs)) continue;
|
|
228
229
|
if (/type\s*=\s*["']?(application\/json|application\/ld\+json|text\/template)["']?/i.test(attrs)) continue;
|
|
229
|
-
if (/id\s*=\s*["']__NEXT_DATA__["']/i.test(attrs)) continue;
|
|
230
|
+
if (/id\s*=\s*["'](__NEXT_DATA__|_R_)["']/i.test(attrs)) continue;
|
|
231
|
+
if (/data-nscript\s*=/i.test(attrs)) continue;
|
|
232
|
+
if (/type\s*=\s*["']?module["']?/i.test(attrs)) continue;
|
|
233
|
+
if (/self\.__next_[fr]/.test(content)) continue;
|
|
230
234
|
return true;
|
|
231
235
|
}
|
|
232
236
|
return dangerousPatterns.some((pattern) => pattern.test(html));
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/trajectory.ts","../src/cache.ts","../src/morpher.ts","../src/speculator.ts","../src/graph.ts","../src/adaptive.ts","../src/performance.ts"],"names":["DEFAULT_CONFIG"],"mappings":"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","file":"index.mjs","sourcesContent":["import type {\n PointerSample,\n Velocity,\n LinkRect,\n TrajectoryConfig,\n} from \"./types\";\n\nconst DEFAULT_CONFIG: TrajectoryConfig = {\n lookaheadMs: 120,\n minVelocity: 0.2,\n sampleRate: 50,\n cancelOnDeviation: true,\n};\n\nexport class TrajectoryEngine {\n private samples: PointerSample[] = [];\n private links: Map<HTMLAnchorElement, LinkRect> = new Map();\n private config: TrajectoryConfig;\n private lastPrediction: string | null = null;\n private sampleInterval: number | null = null;\n private onPrediction?: (href: string) => void;\n private onCancel?: (href: string) => void;\n private cooldownMap = new Map<string, number>();\n private updateDebounceTimer: number | null = null;\n\n constructor(\n config: Partial<TrajectoryConfig> = {},\n callbacks?: {\n onPrediction?: (href: string) => void;\n onCancel?: (href: string) => void;\n }\n ) {\n this.config = { ...DEFAULT_CONFIG, ...config };\n this.onPrediction = callbacks?.onPrediction;\n this.onCancel = callbacks?.onCancel;\n }\n\n start(): void {\n if (typeof window === \"undefined\") return;\n\n window.addEventListener(\"pointermove\", this.handlePointerMove);\n this.sampleInterval = window.setInterval(\n () => this.processSamples(),\n this.config.sampleRate\n );\n }\n\n stop(): void {\n if (typeof window === \"undefined\") return;\n\n window.removeEventListener(\"pointermove\", this.handlePointerMove);\n if (this.sampleInterval) {\n clearInterval(this.sampleInterval);\n this.sampleInterval = null;\n }\n if (this.updateDebounceTimer) {\n clearTimeout(this.updateDebounceTimer);\n this.updateDebounceTimer = null;\n }\n \n // Clean up memory\n this.samples = [];\n this.links.clear();\n this.cooldownMap.clear();\n this.lastPrediction = null;\n }\n\n registerLink(href: string, element: HTMLAnchorElement): void {\n const rect = element.getBoundingClientRect();\n this.links.set(element, { href, rect, element });\n }\n\n unregisterLink(element: HTMLAnchorElement): void {\n this.links.delete(element);\n }\n\n updateLinkPositions(): void {\n // Debounce to prevent excessive reflows\n if (this.updateDebounceTimer) {\n clearTimeout(this.updateDebounceTimer);\n }\n\n this.updateDebounceTimer = window.setTimeout(() => {\n this.links.forEach((link, element) => {\n const rect = element.getBoundingClientRect();\n this.links.set(element, { ...link, rect });\n });\n this.updateDebounceTimer = null;\n }, 100);\n }\n\n private handlePointerMove = (e: PointerEvent): void => {\n this.samples.push({\n x: e.clientX,\n y: e.clientY,\n t: e.timeStamp,\n });\n\n // Keep only last 10 samples for smoothing\n if (this.samples.length > 10) {\n this.samples.shift();\n }\n };\n\n private processSamples(): void {\n if (this.samples.length < 4) return;\n\n const velocity = this.computeVelocity();\n const speed = Math.sqrt(velocity.vx ** 2 + velocity.vy ** 2);\n\n if (speed < this.config.minVelocity) {\n if (this.lastPrediction && this.config.cancelOnDeviation) {\n this.onCancel?.(this.lastPrediction);\n this.lastPrediction = null;\n }\n return;\n }\n\n const target = this.predictTarget(velocity);\n\n if (target && target.href !== this.lastPrediction) {\n // Check cooldown\n const now = Date.now();\n const lastTime = this.cooldownMap.get(target.href) ?? 0;\n const cooldown = 500; // 500ms cooldown per href\n \n if (now - lastTime < cooldown) {\n return; // Still in cooldown\n }\n\n if (this.lastPrediction && this.config.cancelOnDeviation) {\n this.onCancel?.(this.lastPrediction);\n }\n \n this.lastPrediction = target.href;\n this.cooldownMap.set(target.href, now);\n this.onPrediction?.(target.href);\n } else if (!target && this.lastPrediction && this.config.cancelOnDeviation) {\n this.onCancel?.(this.lastPrediction);\n this.lastPrediction = null;\n }\n }\n\n private computeVelocity(): Velocity {\n const recent = this.samples.slice(-4);\n const dt = recent[recent.length - 1]!.t - recent[0]!.t;\n\n if (dt === 0) return { vx: 0, vy: 0 };\n\n const dx = recent[recent.length - 1]!.x - recent[0]!.x;\n const dy = recent[recent.length - 1]!.y - recent[0]!.y;\n\n return {\n vx: dx / dt,\n vy: dy / dt,\n };\n }\n\n private projectRay(velocity: Velocity): { x: number; y: number } {\n const origin = this.samples[this.samples.length - 1]!;\n return {\n x: origin.x + velocity.vx * this.config.lookaheadMs,\n y: origin.y + velocity.vy * this.config.lookaheadMs,\n };\n }\n\n private predictTarget(velocity: Velocity): LinkRect | null {\n const tip = this.projectRay(velocity);\n\n for (const link of this.links.values()) {\n if (this.rectContains(link.rect, tip)) {\n return link;\n }\n }\n\n return null;\n }\n\n private rectContains(rect: DOMRect, point: { x: number; y: number }): boolean {\n return (\n point.x >= rect.left &&\n point.x <= rect.right &&\n point.y >= rect.top &&\n point.y <= rect.bottom\n );\n }\n}\n\nexport function createTrajectoryEngine(\n config?: Partial<TrajectoryConfig>,\n callbacks?: {\n onPrediction?: (href: string) => void;\n onCancel?: (href: string) => void;\n }\n): TrajectoryEngine {\n return new TrajectoryEngine(config, callbacks);\n}\n","import type { CacheConfig, CachedPage, CacheLayer } from \"./types\";\n\nconst DEFAULT_CONFIG: CacheConfig = {\n memory: {\n enabled: true,\n maxPages: 10,\n },\n serviceWorker: {\n enabled: true,\n ttl: 300,\n cacheName: \"specnav-v1\",\n crossTabSync: true,\n broadcastChannel: \"specnav-sync\",\n },\n edge: {\n enabled: true,\n maxAge: 60,\n staleWhileRevalidate: 300,\n },\n exclude: [],\n};\n\nexport class CacheManager {\n private config: CacheConfig;\n private memoryCache: Map<string, CachedPage> = new Map();\n private accessOrder: string[] = [];\n private broadcastChannel?: BroadcastChannel;\n private onCacheHit?: (href: string, layer: CacheLayer) => void;\n\n constructor(\n config: Partial<CacheConfig> = {},\n callbacks?: { onCacheHit?: (href: string, layer: CacheLayer) => void }\n ) {\n this.config = { ...DEFAULT_CONFIG, ...config };\n this.onCacheHit = callbacks?.onCacheHit;\n\n if (\n this.config.serviceWorker.enabled &&\n this.config.serviceWorker.crossTabSync &&\n typeof BroadcastChannel !== \"undefined\"\n ) {\n this.broadcastChannel = new BroadcastChannel(\n this.config.serviceWorker.broadcastChannel\n );\n this.broadcastChannel.onmessage = this.handleBroadcast;\n }\n }\n\n async get(href: string): Promise<string | null> {\n if (this.isExcluded(href)) return null;\n\n // L1: Memory cache\n const memoryHit = this.getFromMemory(href);\n if (memoryHit) {\n this.onCacheHit?.(href, 1);\n return memoryHit;\n }\n\n // L2: Service Worker cache\n if (this.config.serviceWorker.enabled) {\n const swHit = await this.getFromServiceWorker(href);\n if (swHit) {\n this.onCacheHit?.(href, 2);\n this.setInMemory(href, swHit);\n return swHit;\n }\n }\n\n return null;\n }\n\n async set(href: string, html: string): Promise<void> {\n if (this.isExcluded(href)) return;\n\n // Sanitize href to prevent cache poisoning\n const sanitizedHref = this.sanitizeHref(href);\n if (!sanitizedHref) return;\n\n // Validate HTML doesn't contain dangerous inline scripts\n if (this.containsDangerousContent(html)) {\n console.warn(`Refusing to cache potentially dangerous content from ${sanitizedHref}`);\n return;\n }\n\n const page: CachedPage = {\n href: sanitizedHref,\n html,\n timestamp: Date.now(),\n ttl: this.config.serviceWorker.ttl,\n };\n\n // L1: Memory\n if (this.config.memory.enabled) {\n this.setInMemory(sanitizedHref, html);\n }\n\n // L2: Service Worker\n if (this.config.serviceWorker.enabled) {\n await this.setInServiceWorker(page);\n this.broadcastSet(sanitizedHref);\n }\n }\n\n private containsDangerousContent(html: string): boolean {\n // Check for inline event handlers and javascript: URLs\n const dangerousPatterns = [\n /on\\w+\\s*=\\s*[\"'][^\"']*[\"']/i, // Inline event handlers\n /javascript:/i, // javascript: URLs\n ];\n\n // Check for inline scripts, but exclude safe types\n const scriptRegex = /<script([^>]*)>([\\s\\S]*?)<\\/script>/gi;\n let match;\n while ((match = scriptRegex.exec(html)) !== null) {\n const attrs = match[1] || \"\";\n \n // Allow scripts with src attribute\n if (/src\\s*=/.test(attrs)) continue;\n \n // Allow safe script types (JSON data, templates)\n if (/type\\s*=\\s*[\"']?(application\\/json|application\\/ld\\+json|text\\/template)[\"']?/i.test(attrs)) continue;\n \n // Allow Next.js data script\n if (/id\\s*=\\s*[\"']__NEXT_DATA__[\"']/i.test(attrs)) continue;\n \n // If we get here, it's an inline script without safe type\n return true;\n }\n\n return dangerousPatterns.some(pattern => pattern.test(html));\n }\n\n private sanitizeHref(href: string): string | null {\n try {\n const url = new URL(href, window.location.origin);\n // Only allow same-origin URLs\n if (url.origin !== window.location.origin) return null;\n return url.pathname + url.search + url.hash;\n } catch {\n return null;\n }\n }\n\n clear(href?: string): void {\n if (href) {\n this.memoryCache.delete(href);\n this.accessOrder = this.accessOrder.filter((h) => h !== href);\n this.clearFromServiceWorker(href);\n } else {\n this.memoryCache.clear();\n this.accessOrder = [];\n this.clearAllServiceWorker();\n }\n }\n\n getSize(): number {\n return this.memoryCache.size;\n }\n\n destroy(): void {\n this.memoryCache.clear();\n this.accessOrder = [];\n this.broadcastChannel?.close();\n }\n\n private getFromMemory(href: string): string | null {\n const page = this.memoryCache.get(href);\n if (!page) return null;\n\n // Update LRU order\n this.accessOrder = this.accessOrder.filter((h) => h !== href);\n this.accessOrder.push(href);\n\n return page.html;\n }\n\n private setInMemory(href: string, html: string): void {\n // Prevent memory exhaustion - limit individual page size\n const maxPageSize = 5 * 1024 * 1024; // 5MB per page\n if (html.length > maxPageSize) {\n console.warn(`Page ${href} exceeds max size, not caching`);\n return;\n }\n\n this.memoryCache.set(href, {\n href,\n html,\n timestamp: Date.now(),\n ttl: this.config.serviceWorker.ttl,\n });\n\n // Deduplicate before adding to accessOrder\n const existingIndex = this.accessOrder.indexOf(href);\n if (existingIndex !== -1) {\n this.accessOrder.splice(existingIndex, 1);\n }\n this.accessOrder.push(href);\n\n // LRU eviction\n if (this.memoryCache.size > this.config.memory.maxPages) {\n const oldest = this.accessOrder.shift();\n if (oldest) this.memoryCache.delete(oldest);\n }\n }\n\n private async getFromServiceWorker(href: string): Promise<string | null> {\n if (typeof caches === \"undefined\") return null;\n\n try {\n const cache = await caches.open(this.config.serviceWorker.cacheName);\n const response = await cache.match(href);\n\n if (!response) return null;\n\n const data = await response.json();\n const page = data as CachedPage;\n\n // Check TTL\n const age = Date.now() - page.timestamp;\n if (age > page.ttl * 1000) {\n await cache.delete(href);\n return null;\n }\n\n return page.html;\n } catch {\n return null;\n }\n }\n\n private async setInServiceWorker(page: CachedPage): Promise<void> {\n if (typeof caches === \"undefined\") return;\n\n try {\n const cache = await caches.open(this.config.serviceWorker.cacheName);\n const response = new Response(JSON.stringify(page), {\n headers: {\n \"Content-Type\": \"application/json\",\n \"Cache-Control\": `max-age=${this.config.edge.maxAge}, stale-while-revalidate=${this.config.edge.staleWhileRevalidate}`,\n },\n });\n await cache.put(page.href, response);\n } catch {\n // Silently fail\n }\n }\n\n private async clearFromServiceWorker(href: string): Promise<void> {\n if (typeof caches === \"undefined\") return;\n\n try {\n const cache = await caches.open(this.config.serviceWorker.cacheName);\n await cache.delete(href);\n } catch {\n // Silently fail\n }\n }\n\n private async clearAllServiceWorker(): Promise<void> {\n if (typeof caches === \"undefined\") return;\n\n try {\n await caches.delete(this.config.serviceWorker.cacheName);\n } catch {\n // Silently fail\n }\n }\n\n private isExcluded(href: string): boolean {\n return this.config.exclude.some((pattern) => {\n if (typeof pattern === \"string\") {\n return pattern.includes(\"*\")\n ? new RegExp(pattern.replace(/\\*/g, \".*\")).test(href)\n : href === pattern;\n }\n return pattern.test(href);\n });\n }\n\n private broadcastSet(href: string): void {\n this.broadcastChannel?.postMessage({ type: \"set\", href });\n }\n\n private handleBroadcast = (event: MessageEvent): void => {\n if (event.data.type === \"set\") {\n // Invalidate memory cache to force fetch from SW\n this.memoryCache.delete(event.data.href);\n }\n };\n}\n\nexport function createCacheManager(\n config?: Partial<CacheConfig>,\n callbacks?: { onCacheHit?: (href: string, layer: CacheLayer) => void }\n): CacheManager {\n return new CacheManager(config, callbacks);\n}\n","import type { MorphConfig } from \"./types\";\n\nconst DEFAULT_CONFIG: MorphConfig = {\n preserveScroll: true,\n preserveFocus: true,\n};\n\ninterface MorphContext {\n config: MorphConfig;\n focusedElement: Element | null;\n scrollPositions: Map<Element, { top: number; left: number }>;\n}\n\nexport class DOMmorpher {\n private config: MorphConfig;\n\n constructor(config: Partial<MorphConfig> = {}) {\n this.config = { ...DEFAULT_CONFIG, ...config };\n }\n\n morph(from: Element, to: Element): void {\n const ctx = this.createContext();\n requestAnimationFrame(() => {\n this.morphElement(from, to, ctx);\n this.restoreContext(ctx);\n });\n }\n\n private createContext(): MorphContext {\n const ctx: MorphContext = {\n config: this.config,\n focusedElement: null,\n scrollPositions: new Map(),\n };\n\n if (this.config.preserveFocus) {\n ctx.focusedElement = document.activeElement;\n }\n\n if (this.config.preserveScroll) {\n this.captureScrollPositions(document.body, ctx.scrollPositions);\n }\n\n return ctx;\n }\n\n private restoreContext(ctx: MorphContext): void {\n if (ctx.config.preserveFocus && ctx.focusedElement) {\n const element = ctx.focusedElement as HTMLElement;\n if (element.focus && document.body.contains(element)) {\n element.focus();\n }\n }\n\n if (ctx.config.preserveScroll) {\n ctx.scrollPositions.forEach((pos, element) => {\n element.scrollTop = pos.top;\n element.scrollLeft = pos.left;\n });\n }\n }\n\n private captureScrollPositions(\n element: Element,\n positions: Map<Element, { top: number; left: number }>\n ): void {\n if (element.scrollTop > 0 || element.scrollLeft > 0) {\n positions.set(element, {\n top: element.scrollTop,\n left: element.scrollLeft,\n });\n }\n\n Array.from(element.children).forEach((child) => {\n this.captureScrollPositions(child, positions);\n });\n }\n\n private morphElement(from: Element, to: Element, ctx: MorphContext): void {\n // Sync attributes\n this.syncAttributes(from, to);\n\n // Morph children\n this.morphChildren(from, to, ctx);\n }\n\n private syncAttributes(from: Element, to: Element): void {\n const fromAttrs = from.attributes;\n const toAttrs = to.attributes;\n\n // Remove attributes not in target\n for (let i = fromAttrs.length - 1; i >= 0; i--) {\n const attr = fromAttrs[i]!;\n if (!to.hasAttribute(attr.name)) {\n from.removeAttribute(attr.name);\n }\n }\n\n // Add/update attributes from target\n for (let i = 0; i < toAttrs.length; i++) {\n const attr = toAttrs[i]!;\n if (from.getAttribute(attr.name) !== attr.value) {\n from.setAttribute(attr.name, attr.value);\n }\n }\n }\n\n private morphChildren(from: Element, to: Element, ctx: MorphContext): void {\n const fromChildren = Array.from(from.childNodes);\n const toChildren = Array.from(to.childNodes);\n\n let fromIndex = 0;\n let toIndex = 0;\n\n while (toIndex < toChildren.length) {\n const toNode = toChildren[toIndex]!;\n const fromNode = fromChildren[fromIndex];\n\n if (!fromNode) {\n // Append new node\n from.appendChild(toNode.cloneNode(true));\n toIndex++;\n continue;\n }\n\n if (this.nodesMatch(fromNode, toNode)) {\n // Nodes match - recurse or update text\n if (fromNode.nodeType === Node.TEXT_NODE) {\n if (fromNode.nodeValue !== toNode.nodeValue) {\n fromNode.nodeValue = toNode.nodeValue;\n }\n } else if (fromNode.nodeType === Node.ELEMENT_NODE) {\n this.morphElement(fromNode as Element, toNode as Element, ctx);\n }\n fromIndex++;\n toIndex++;\n } else {\n // Try to find matching node ahead\n const matchIndex = this.findMatchingNode(\n fromChildren,\n fromIndex + 1,\n toNode\n );\n\n if (matchIndex !== -1) {\n // Remove nodes before match\n for (let i = fromIndex; i < matchIndex; i++) {\n from.removeChild(fromChildren[i]!);\n }\n fromIndex = matchIndex;\n } else {\n // Insert new node\n from.insertBefore(toNode.cloneNode(true), fromNode);\n toIndex++;\n }\n }\n }\n\n // Remove remaining old nodes\n while (fromIndex < fromChildren.length) {\n from.removeChild(fromChildren[fromIndex]!);\n fromIndex++;\n }\n }\n\n private nodesMatch(a: Node, b: Node): boolean {\n if (a.nodeType !== b.nodeType) return false;\n\n if (a.nodeType === Node.ELEMENT_NODE) {\n const aEl = a as Element;\n const bEl = b as Element;\n\n if (aEl.tagName !== bEl.tagName) return false;\n\n const aId = aEl.getAttribute(\"id\");\n const bId = bEl.getAttribute(\"id\");\n\n if (aId && bId) return aId === bId;\n\n return true;\n }\n\n return true;\n }\n\n private findMatchingNode(\n nodes: Node[],\n startIndex: number,\n target: Node\n ): number {\n for (let i = startIndex; i < nodes.length; i++) {\n if (this.nodesMatch(nodes[i]!, target)) {\n return i;\n }\n }\n return -1;\n }\n}\n\nexport function createMorpher(config?: Partial<MorphConfig>): DOMmorpher {\n return new DOMmorpher(config);\n}\n\nexport function morph(\n from: Element,\n to: Element,\n config?: Partial<MorphConfig>\n): void {\n const morpher = createMorpher(config);\n morpher.morph(from, to);\n}\n","interface SpeculatedPage {\n href: string;\n html: string;\n container: HTMLElement;\n timestamp: number;\n}\n\n/**\n * SpeculativeRenderer pre-renders pages in detached DOM containers.\n * \n * LIMITATIONS:\n * - This implementation uses innerHTML, NOT React rendering. The speculated content\n * is raw HTML set on a disconnected DOM node, not a fully rendered React component tree.\n * - For true React speculative rendering, the container must be appended to the document\n * (hidden via CSS) and ReactDOM.createRoot(container).render(...) must be called.\n * - Current implementation is suitable for static HTML morphing but may produce different\n * results than a real React render for dynamic components.\n */\nexport class SpeculativeRenderer {\n private speculations: Map<string, SpeculatedPage> = new Map();\n private maxSpeculations: number;\n\n constructor(maxSpeculations = 3) {\n this.maxSpeculations = maxSpeculations;\n }\n\n async speculate(href: string, html: string): Promise<void> {\n if (this.speculations.has(href)) return;\n\n // Evict oldest if at capacity\n if (this.speculations.size >= this.maxSpeculations) {\n const oldest = Array.from(this.speculations.values()).sort(\n (a, b) => a.timestamp - b.timestamp\n )[0];\n if (oldest) this.cancel(oldest.href);\n }\n\n const container = this.createDetachedContainer();\n container.innerHTML = html;\n\n this.speculations.set(href, {\n href,\n html,\n container,\n timestamp: Date.now(),\n });\n }\n\n get(href: string): HTMLElement | null {\n const speculation = this.speculations.get(href);\n return speculation?.container ?? null;\n }\n\n cancel(href: string): void {\n const speculation = this.speculations.get(href);\n if (speculation) {\n speculation.container.remove();\n this.speculations.delete(href);\n }\n }\n\n cancelAll(): void {\n this.speculations.forEach((spec) => spec.container.remove());\n this.speculations.clear();\n }\n\n has(href: string): boolean {\n return this.speculations.has(href);\n }\n\n private createDetachedContainer(): HTMLElement {\n const container = document.createElement(\"div\");\n container.style.display = \"none\";\n container.setAttribute(\"data-specnav-speculation\", \"true\");\n return container;\n }\n}\n\nexport function createSpeculativeRenderer(\n maxSpeculations?: number\n): SpeculativeRenderer {\n return new SpeculativeRenderer(maxSpeculations);\n}\n","import type { GraphConfig, NavigationGraph } from \"./types\";\n\nconst DEFAULT_CONFIG: GraphConfig = {\n enabled: true,\n minConfidence: 0.6,\n sessionWeight: 0.7,\n storageKey: \"specnav-graph\",\n maxNodes: 50,\n};\n\nexport class NavigationGraphLearner {\n private config: GraphConfig;\n private graph: NavigationGraph = {};\n private sessionGraph: NavigationGraph = {};\n\n constructor(config: Partial<GraphConfig> = {}) {\n this.config = { ...DEFAULT_CONFIG, ...config };\n if (this.config.enabled) {\n this.loadGraph();\n }\n }\n\n recordNavigation(fromHref: string, toHref: string): void {\n if (!this.config.enabled) return;\n\n // Update session graph\n if (!this.sessionGraph[fromHref]) {\n this.sessionGraph[fromHref] = {};\n }\n const current = this.sessionGraph[fromHref]![toHref] ?? 0;\n this.sessionGraph[fromHref]![toHref] = current + 1;\n\n // Update persistent graph\n if (!this.graph[fromHref]) {\n this.graph[fromHref] = {};\n }\n const persistentCurrent = this.graph[fromHref]![toHref] ?? 0;\n this.graph[fromHref]![toHref] = persistentCurrent + 1;\n\n this.saveGraph();\n }\n\n getPredictions(fromHref: string): string[] {\n if (!this.config.enabled) return [];\n\n const sessionEdges = this.sessionGraph[fromHref] ?? {};\n const persistentEdges = this.graph[fromHref] ?? {};\n\n // Merge session and persistent with weighting\n const merged: Record<string, number> = {};\n\n Object.entries(persistentEdges).forEach(([href, count]) => {\n merged[href] = count * (1 - this.config.sessionWeight);\n });\n\n Object.entries(sessionEdges).forEach(([href, count]) => {\n merged[href] = (merged[href] ?? 0) + count * this.config.sessionWeight;\n });\n\n // Calculate total for normalization\n const total = Object.values(merged).reduce((sum, val) => sum + val, 0);\n if (total === 0) return [];\n\n // Convert to confidence scores and filter\n const predictions = Object.entries(merged)\n .map(([href, count]) => ({\n href,\n confidence: count / total,\n }))\n .filter((p) => p.confidence >= this.config.minConfidence)\n .sort((a, b) => b.confidence - a.confidence)\n .map((p) => p.href);\n\n return predictions;\n }\n\n getGraph(): NavigationGraph {\n return { ...this.graph };\n }\n\n clearGraph(): void {\n this.graph = {};\n this.sessionGraph = {};\n this.saveGraph();\n }\n\n private loadGraph(): void {\n if (typeof localStorage === \"undefined\") return;\n\n try {\n const stored = localStorage.getItem(this.config.storageKey);\n if (stored) {\n this.graph = JSON.parse(stored);\n this.pruneGraph();\n }\n } catch {\n // Silently fail\n }\n }\n\n private saveGraph(): void {\n if (typeof localStorage === \"undefined\") return;\n\n try {\n this.pruneGraph();\n const serialized = JSON.stringify(this.graph);\n \n // Check size before saving (localStorage typically has 5-10MB limit)\n if (serialized.length > 4 * 1024 * 1024) { // 4MB safety limit\n console.warn(\"Navigation graph too large, pruning more aggressively\");\n // Prune to half the max nodes (use local variable)\n const reducedMaxNodes = Math.floor(this.config.maxNodes / 2);\n const originalMaxNodes = this.config.maxNodes;\n this.config.maxNodes = reducedMaxNodes;\n this.pruneGraph();\n this.config.maxNodes = originalMaxNodes; // Restore original\n }\n \n localStorage.setItem(this.config.storageKey, JSON.stringify(this.graph));\n } catch (error) {\n // Handle quota exceeded error\n if (error instanceof Error && error.name === \"QuotaExceededError\") {\n console.warn(\"localStorage quota exceeded, clearing navigation graph\");\n this.clearGraph();\n }\n }\n }\n\n private pruneGraph(): void {\n const nodes = Object.keys(this.graph);\n if (nodes.length <= this.config.maxNodes) return;\n\n // Calculate total transitions per node\n const nodeCounts = nodes.map((node) => ({\n node,\n count: Object.values(this.graph[node]!).reduce(\n (sum, val) => sum + val,\n 0\n ),\n }));\n\n // Sort by count and keep top maxNodes\n nodeCounts.sort((a, b) => b.count - a.count);\n const toKeep = new Set(\n nodeCounts.slice(0, this.config.maxNodes).map((n) => n.node)\n );\n\n // Remove nodes not in top set\n Object.keys(this.graph).forEach((node) => {\n if (!toKeep.has(node)) {\n delete this.graph[node];\n }\n });\n }\n}\n\nexport function createNavigationGraphLearner(\n config?: Partial<GraphConfig>\n): NavigationGraphLearner {\n return new NavigationGraphLearner(config);\n}\n\nexport function getNavigationGraph(\n storageKey = \"specnav-graph\"\n): NavigationGraph {\n if (typeof localStorage === \"undefined\") return {};\n\n try {\n const stored = localStorage.getItem(storageKey);\n return stored ? JSON.parse(stored) : {};\n } catch {\n return {};\n }\n}\n","import type { AdaptiveConfig, Strategy } from \"./types\";\n\nconst DEFAULT_CONFIG: AdaptiveConfig = {\n batteryThreshold: 0.2,\n connectionTypes: {\n slow: [\"2g\", \"3g\", \"slow-2g\"],\n fast: [\"4g\"],\n },\n respectSaveData: true,\n respectReducedMotion: true,\n};\n\nexport class AdaptiveMode {\n private config: AdaptiveConfig;\n private battery: any = null;\n private connection: any = null;\n private initPromise: Promise<void>;\n\n constructor(config: Partial<AdaptiveConfig> = {}) {\n this.config = { ...DEFAULT_CONFIG, ...config };\n this.initPromise = this.initialize();\n }\n\n async waitForInit(): Promise<void> {\n await this.initPromise;\n }\n\n private async initialize(): Promise<void> {\n if (typeof navigator === \"undefined\") return;\n\n // Battery API\n if (\"getBattery\" in navigator) {\n try {\n this.battery = await (navigator as any).getBattery();\n } catch {\n // Not available\n }\n }\n\n // Network Information API\n if (\"connection\" in navigator || \"mozConnection\" in navigator || \"webkitConnection\" in navigator) {\n this.connection =\n (navigator as any).connection ||\n (navigator as any).mozConnection ||\n (navigator as any).webkitConnection;\n }\n }\n\n getStrategy(baseStrategy: Strategy): Strategy {\n if (baseStrategy === \"off\") return \"off\";\n if (baseStrategy !== \"auto\") return baseStrategy;\n\n // Check Save-Data\n if (this.config.respectSaveData && this.hasSaveData()) {\n return \"off\";\n }\n\n // Check battery\n if (this.isLowBattery()) {\n return \"conservative\";\n }\n\n // Check connection\n if (this.isSlowConnection()) {\n return \"conservative\";\n }\n\n return \"aggressive\";\n }\n\n shouldPrefetch(): boolean {\n if (this.config.respectSaveData && this.hasSaveData()) {\n return false;\n }\n\n if (this.isLowBattery()) {\n return false;\n }\n\n return true;\n }\n\n shouldSpeculate(): boolean {\n if (!this.shouldPrefetch()) {\n return false;\n }\n\n if (this.isSlowConnection()) {\n return false;\n }\n\n return true;\n }\n\n shouldUseTransitions(): boolean {\n if (!this.config.respectReducedMotion) return true;\n\n if (typeof window === \"undefined\") return true;\n\n return !window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n }\n\n private hasSaveData(): boolean {\n if (typeof navigator === \"undefined\") return false;\n\n return (\n (navigator as any).connection?.saveData === true ||\n (navigator as any).mozConnection?.saveData === true ||\n (navigator as any).webkitConnection?.saveData === true\n );\n }\n\n private isLowBattery(): boolean {\n if (!this.battery) return false;\n\n return (\n !this.battery.charging &&\n this.battery.level < this.config.batteryThreshold\n );\n }\n\n private isSlowConnection(): boolean {\n if (!this.connection) return false;\n\n const effectiveType = this.connection.effectiveType;\n if (!effectiveType) return false;\n\n return this.config.connectionTypes.slow.includes(effectiveType);\n }\n\n isFastConnection(): boolean {\n if (!this.connection) return true; // Assume fast if unknown\n\n const effectiveType = this.connection.effectiveType;\n if (!effectiveType) return true;\n\n return this.config.connectionTypes.fast.includes(effectiveType);\n }\n\n getBatteryLevel(): number | null {\n return this.battery?.level ?? null;\n }\n\n getConnectionType(): string | null {\n return this.connection?.effectiveType ?? null;\n }\n}\n\nexport function createAdaptiveMode(\n config?: Partial<AdaptiveConfig>\n): AdaptiveMode {\n return new AdaptiveMode(config);\n}\n","// Performance monitoring utilities\n\nexport interface PerformanceMetrics {\n navigationTime: number;\n cacheHit: boolean;\n cacheLayer?: 1 | 2 | 3;\n speculativeHit: boolean;\n fetchTime?: number;\n morphTime?: number;\n}\n\nexport class PerformanceMonitor {\n private metrics: PerformanceMetrics[] = [];\n private maxMetrics = 100;\n\n recordNavigation(metrics: PerformanceMetrics): void {\n this.metrics.push(metrics);\n \n // Keep only last N metrics\n if (this.metrics.length > this.maxMetrics) {\n this.metrics.shift();\n }\n }\n\n getAverageNavigationTime(): number {\n if (this.metrics.length === 0) return 0;\n const sum = this.metrics.reduce((acc, m) => acc + m.navigationTime, 0);\n return sum / this.metrics.length;\n }\n\n getCacheHitRate(): number {\n if (this.metrics.length === 0) return 0;\n const hits = this.metrics.filter(m => m.cacheHit).length;\n return hits / this.metrics.length;\n }\n\n getSpeculativeHitRate(): number {\n if (this.metrics.length === 0) return 0;\n const hits = this.metrics.filter(m => m.speculativeHit).length;\n return hits / this.metrics.length;\n }\n\n getMetrics(): PerformanceMetrics[] {\n return [...this.metrics];\n }\n\n clear(): void {\n this.metrics = [];\n }\n}\n\nexport const performanceMonitor = new PerformanceMonitor();\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/trajectory.ts","../src/cache.ts","../src/morpher.ts","../src/speculator.ts","../src/graph.ts","../src/adaptive.ts","../src/performance.ts"],"names":["DEFAULT_CONFIG"],"mappings":"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","file":"index.mjs","sourcesContent":["import type {\n PointerSample,\n Velocity,\n LinkRect,\n TrajectoryConfig,\n} from \"./types\";\n\nconst DEFAULT_CONFIG: TrajectoryConfig = {\n lookaheadMs: 120,\n minVelocity: 0.2,\n sampleRate: 50,\n cancelOnDeviation: true,\n};\n\nexport class TrajectoryEngine {\n private samples: PointerSample[] = [];\n private links: Map<HTMLAnchorElement, LinkRect> = new Map();\n private config: TrajectoryConfig;\n private lastPrediction: string | null = null;\n private sampleInterval: number | null = null;\n private onPrediction?: (href: string) => void;\n private onCancel?: (href: string) => void;\n private cooldownMap = new Map<string, number>();\n private updateDebounceTimer: number | null = null;\n\n constructor(\n config: Partial<TrajectoryConfig> = {},\n callbacks?: {\n onPrediction?: (href: string) => void;\n onCancel?: (href: string) => void;\n }\n ) {\n this.config = { ...DEFAULT_CONFIG, ...config };\n this.onPrediction = callbacks?.onPrediction;\n this.onCancel = callbacks?.onCancel;\n }\n\n start(): void {\n if (typeof window === \"undefined\") return;\n\n window.addEventListener(\"pointermove\", this.handlePointerMove);\n this.sampleInterval = window.setInterval(\n () => this.processSamples(),\n this.config.sampleRate\n );\n }\n\n stop(): void {\n if (typeof window === \"undefined\") return;\n\n window.removeEventListener(\"pointermove\", this.handlePointerMove);\n if (this.sampleInterval) {\n clearInterval(this.sampleInterval);\n this.sampleInterval = null;\n }\n if (this.updateDebounceTimer) {\n clearTimeout(this.updateDebounceTimer);\n this.updateDebounceTimer = null;\n }\n \n // Clean up memory\n this.samples = [];\n this.links.clear();\n this.cooldownMap.clear();\n this.lastPrediction = null;\n }\n\n registerLink(href: string, element: HTMLAnchorElement): void {\n const rect = element.getBoundingClientRect();\n this.links.set(element, { href, rect, element });\n }\n\n unregisterLink(element: HTMLAnchorElement): void {\n this.links.delete(element);\n }\n\n updateLinkPositions(): void {\n // Debounce to prevent excessive reflows\n if (this.updateDebounceTimer) {\n clearTimeout(this.updateDebounceTimer);\n }\n\n this.updateDebounceTimer = window.setTimeout(() => {\n this.links.forEach((link, element) => {\n const rect = element.getBoundingClientRect();\n this.links.set(element, { ...link, rect });\n });\n this.updateDebounceTimer = null;\n }, 100);\n }\n\n private handlePointerMove = (e: PointerEvent): void => {\n this.samples.push({\n x: e.clientX,\n y: e.clientY,\n t: e.timeStamp,\n });\n\n // Keep only last 10 samples for smoothing\n if (this.samples.length > 10) {\n this.samples.shift();\n }\n };\n\n private processSamples(): void {\n if (this.samples.length < 4) return;\n\n const velocity = this.computeVelocity();\n const speed = Math.sqrt(velocity.vx ** 2 + velocity.vy ** 2);\n\n if (speed < this.config.minVelocity) {\n if (this.lastPrediction && this.config.cancelOnDeviation) {\n this.onCancel?.(this.lastPrediction);\n this.lastPrediction = null;\n }\n return;\n }\n\n const target = this.predictTarget(velocity);\n\n if (target && target.href !== this.lastPrediction) {\n // Check cooldown\n const now = Date.now();\n const lastTime = this.cooldownMap.get(target.href) ?? 0;\n const cooldown = 500; // 500ms cooldown per href\n \n if (now - lastTime < cooldown) {\n return; // Still in cooldown\n }\n\n if (this.lastPrediction && this.config.cancelOnDeviation) {\n this.onCancel?.(this.lastPrediction);\n }\n \n this.lastPrediction = target.href;\n this.cooldownMap.set(target.href, now);\n this.onPrediction?.(target.href);\n } else if (!target && this.lastPrediction && this.config.cancelOnDeviation) {\n this.onCancel?.(this.lastPrediction);\n this.lastPrediction = null;\n }\n }\n\n private computeVelocity(): Velocity {\n const recent = this.samples.slice(-4);\n const dt = recent[recent.length - 1]!.t - recent[0]!.t;\n\n if (dt === 0) return { vx: 0, vy: 0 };\n\n const dx = recent[recent.length - 1]!.x - recent[0]!.x;\n const dy = recent[recent.length - 1]!.y - recent[0]!.y;\n\n return {\n vx: dx / dt,\n vy: dy / dt,\n };\n }\n\n private projectRay(velocity: Velocity): { x: number; y: number } {\n const origin = this.samples[this.samples.length - 1]!;\n return {\n x: origin.x + velocity.vx * this.config.lookaheadMs,\n y: origin.y + velocity.vy * this.config.lookaheadMs,\n };\n }\n\n private predictTarget(velocity: Velocity): LinkRect | null {\n const tip = this.projectRay(velocity);\n\n for (const link of this.links.values()) {\n if (this.rectContains(link.rect, tip)) {\n return link;\n }\n }\n\n return null;\n }\n\n private rectContains(rect: DOMRect, point: { x: number; y: number }): boolean {\n return (\n point.x >= rect.left &&\n point.x <= rect.right &&\n point.y >= rect.top &&\n point.y <= rect.bottom\n );\n }\n}\n\nexport function createTrajectoryEngine(\n config?: Partial<TrajectoryConfig>,\n callbacks?: {\n onPrediction?: (href: string) => void;\n onCancel?: (href: string) => void;\n }\n): TrajectoryEngine {\n return new TrajectoryEngine(config, callbacks);\n}\n","import type { CacheConfig, CachedPage, CacheLayer } from \"./types\";\n\nconst DEFAULT_CONFIG: CacheConfig = {\n memory: {\n enabled: true,\n maxPages: 10,\n },\n serviceWorker: {\n enabled: true,\n ttl: 300,\n cacheName: \"specnav-v1\",\n crossTabSync: true,\n broadcastChannel: \"specnav-sync\",\n },\n edge: {\n enabled: true,\n maxAge: 60,\n staleWhileRevalidate: 300,\n },\n exclude: [],\n};\n\nexport class CacheManager {\n private config: CacheConfig;\n private memoryCache: Map<string, CachedPage> = new Map();\n private accessOrder: string[] = [];\n private broadcastChannel?: BroadcastChannel;\n private onCacheHit?: (href: string, layer: CacheLayer) => void;\n\n constructor(\n config: Partial<CacheConfig> = {},\n callbacks?: { onCacheHit?: (href: string, layer: CacheLayer) => void }\n ) {\n this.config = { ...DEFAULT_CONFIG, ...config };\n this.onCacheHit = callbacks?.onCacheHit;\n\n if (\n this.config.serviceWorker.enabled &&\n this.config.serviceWorker.crossTabSync &&\n typeof BroadcastChannel !== \"undefined\"\n ) {\n this.broadcastChannel = new BroadcastChannel(\n this.config.serviceWorker.broadcastChannel\n );\n this.broadcastChannel.onmessage = this.handleBroadcast;\n }\n }\n\n async get(href: string): Promise<string | null> {\n if (this.isExcluded(href)) return null;\n\n // L1: Memory cache\n const memoryHit = this.getFromMemory(href);\n if (memoryHit) {\n this.onCacheHit?.(href, 1);\n return memoryHit;\n }\n\n // L2: Service Worker cache\n if (this.config.serviceWorker.enabled) {\n const swHit = await this.getFromServiceWorker(href);\n if (swHit) {\n this.onCacheHit?.(href, 2);\n this.setInMemory(href, swHit);\n return swHit;\n }\n }\n\n return null;\n }\n\n async set(href: string, html: string): Promise<void> {\n if (this.isExcluded(href)) return;\n\n // Sanitize href to prevent cache poisoning\n const sanitizedHref = this.sanitizeHref(href);\n if (!sanitizedHref) return;\n\n // Validate HTML doesn't contain dangerous inline scripts\n if (this.containsDangerousContent(html)) {\n console.warn(`Refusing to cache potentially dangerous content from ${sanitizedHref}`);\n return;\n }\n\n const page: CachedPage = {\n href: sanitizedHref,\n html,\n timestamp: Date.now(),\n ttl: this.config.serviceWorker.ttl,\n };\n\n // L1: Memory\n if (this.config.memory.enabled) {\n this.setInMemory(sanitizedHref, html);\n }\n\n // L2: Service Worker\n if (this.config.serviceWorker.enabled) {\n await this.setInServiceWorker(page);\n this.broadcastSet(sanitizedHref);\n }\n }\n\n private containsDangerousContent(html: string): boolean {\n // Check for inline event handlers and javascript: URLs\n const dangerousPatterns = [\n /on\\w+\\s*=\\s*[\"'][^\"']*[\"']/i, // Inline event handlers\n /javascript:/i, // javascript: URLs\n ];\n\n // Check for inline scripts, but exclude safe types\n const scriptRegex = /<script([^>]*)>([\\s\\S]*?)<\\/script>/gi;\n let match;\n while ((match = scriptRegex.exec(html)) !== null) {\n const attrs = match[1] || \"\";\n const content = match[2] || \"\";\n \n // Allow scripts with src attribute\n if (/src\\s*=/.test(attrs)) continue;\n \n // Allow safe script types (JSON data, templates)\n if (/type\\s*=\\s*[\"']?(application\\/json|application\\/ld\\+json|text\\/template)[\"']?/i.test(attrs)) continue;\n \n // Allow Next.js scripts\n if (/id\\s*=\\s*[\"'](__NEXT_DATA__|_R_)[\"']/i.test(attrs)) continue;\n if (/data-nscript\\s*=/i.test(attrs)) continue;\n \n // Allow module scripts (Next.js uses these for hydration)\n if (/type\\s*=\\s*[\"']?module[\"']?/i.test(attrs)) continue;\n \n // Allow Next.js hydration scripts (self.__next_f, self.__next_r)\n if (/self\\.__next_[fr]/.test(content)) continue;\n \n // If we get here, it's an inline script without safe type\n return true;\n }\n\n return dangerousPatterns.some(pattern => pattern.test(html));\n }\n\n private sanitizeHref(href: string): string | null {\n try {\n const url = new URL(href, window.location.origin);\n // Only allow same-origin URLs\n if (url.origin !== window.location.origin) return null;\n return url.pathname + url.search + url.hash;\n } catch {\n return null;\n }\n }\n\n clear(href?: string): void {\n if (href) {\n this.memoryCache.delete(href);\n this.accessOrder = this.accessOrder.filter((h) => h !== href);\n this.clearFromServiceWorker(href);\n } else {\n this.memoryCache.clear();\n this.accessOrder = [];\n this.clearAllServiceWorker();\n }\n }\n\n getSize(): number {\n return this.memoryCache.size;\n }\n\n destroy(): void {\n this.memoryCache.clear();\n this.accessOrder = [];\n this.broadcastChannel?.close();\n }\n\n private getFromMemory(href: string): string | null {\n const page = this.memoryCache.get(href);\n if (!page) return null;\n\n // Update LRU order\n this.accessOrder = this.accessOrder.filter((h) => h !== href);\n this.accessOrder.push(href);\n\n return page.html;\n }\n\n private setInMemory(href: string, html: string): void {\n // Prevent memory exhaustion - limit individual page size\n const maxPageSize = 5 * 1024 * 1024; // 5MB per page\n if (html.length > maxPageSize) {\n console.warn(`Page ${href} exceeds max size, not caching`);\n return;\n }\n\n this.memoryCache.set(href, {\n href,\n html,\n timestamp: Date.now(),\n ttl: this.config.serviceWorker.ttl,\n });\n\n // Deduplicate before adding to accessOrder\n const existingIndex = this.accessOrder.indexOf(href);\n if (existingIndex !== -1) {\n this.accessOrder.splice(existingIndex, 1);\n }\n this.accessOrder.push(href);\n\n // LRU eviction\n if (this.memoryCache.size > this.config.memory.maxPages) {\n const oldest = this.accessOrder.shift();\n if (oldest) this.memoryCache.delete(oldest);\n }\n }\n\n private async getFromServiceWorker(href: string): Promise<string | null> {\n if (typeof caches === \"undefined\") return null;\n\n try {\n const cache = await caches.open(this.config.serviceWorker.cacheName);\n const response = await cache.match(href);\n\n if (!response) return null;\n\n const data = await response.json();\n const page = data as CachedPage;\n\n // Check TTL\n const age = Date.now() - page.timestamp;\n if (age > page.ttl * 1000) {\n await cache.delete(href);\n return null;\n }\n\n return page.html;\n } catch {\n return null;\n }\n }\n\n private async setInServiceWorker(page: CachedPage): Promise<void> {\n if (typeof caches === \"undefined\") return;\n\n try {\n const cache = await caches.open(this.config.serviceWorker.cacheName);\n const response = new Response(JSON.stringify(page), {\n headers: {\n \"Content-Type\": \"application/json\",\n \"Cache-Control\": `max-age=${this.config.edge.maxAge}, stale-while-revalidate=${this.config.edge.staleWhileRevalidate}`,\n },\n });\n await cache.put(page.href, response);\n } catch {\n // Silently fail\n }\n }\n\n private async clearFromServiceWorker(href: string): Promise<void> {\n if (typeof caches === \"undefined\") return;\n\n try {\n const cache = await caches.open(this.config.serviceWorker.cacheName);\n await cache.delete(href);\n } catch {\n // Silently fail\n }\n }\n\n private async clearAllServiceWorker(): Promise<void> {\n if (typeof caches === \"undefined\") return;\n\n try {\n await caches.delete(this.config.serviceWorker.cacheName);\n } catch {\n // Silently fail\n }\n }\n\n private isExcluded(href: string): boolean {\n return this.config.exclude.some((pattern) => {\n if (typeof pattern === \"string\") {\n return pattern.includes(\"*\")\n ? new RegExp(pattern.replace(/\\*/g, \".*\")).test(href)\n : href === pattern;\n }\n return pattern.test(href);\n });\n }\n\n private broadcastSet(href: string): void {\n this.broadcastChannel?.postMessage({ type: \"set\", href });\n }\n\n private handleBroadcast = (event: MessageEvent): void => {\n if (event.data.type === \"set\") {\n // Invalidate memory cache to force fetch from SW\n this.memoryCache.delete(event.data.href);\n }\n };\n}\n\nexport function createCacheManager(\n config?: Partial<CacheConfig>,\n callbacks?: { onCacheHit?: (href: string, layer: CacheLayer) => void }\n): CacheManager {\n return new CacheManager(config, callbacks);\n}\n","import type { MorphConfig } from \"./types\";\n\nconst DEFAULT_CONFIG: MorphConfig = {\n preserveScroll: true,\n preserveFocus: true,\n};\n\ninterface MorphContext {\n config: MorphConfig;\n focusedElement: Element | null;\n scrollPositions: Map<Element, { top: number; left: number }>;\n}\n\nexport class DOMmorpher {\n private config: MorphConfig;\n\n constructor(config: Partial<MorphConfig> = {}) {\n this.config = { ...DEFAULT_CONFIG, ...config };\n }\n\n morph(from: Element, to: Element): void {\n const ctx = this.createContext();\n requestAnimationFrame(() => {\n this.morphElement(from, to, ctx);\n this.restoreContext(ctx);\n });\n }\n\n private createContext(): MorphContext {\n const ctx: MorphContext = {\n config: this.config,\n focusedElement: null,\n scrollPositions: new Map(),\n };\n\n if (this.config.preserveFocus) {\n ctx.focusedElement = document.activeElement;\n }\n\n if (this.config.preserveScroll) {\n this.captureScrollPositions(document.body, ctx.scrollPositions);\n }\n\n return ctx;\n }\n\n private restoreContext(ctx: MorphContext): void {\n if (ctx.config.preserveFocus && ctx.focusedElement) {\n const element = ctx.focusedElement as HTMLElement;\n if (element.focus && document.body.contains(element)) {\n element.focus();\n }\n }\n\n if (ctx.config.preserveScroll) {\n ctx.scrollPositions.forEach((pos, element) => {\n element.scrollTop = pos.top;\n element.scrollLeft = pos.left;\n });\n }\n }\n\n private captureScrollPositions(\n element: Element,\n positions: Map<Element, { top: number; left: number }>\n ): void {\n if (element.scrollTop > 0 || element.scrollLeft > 0) {\n positions.set(element, {\n top: element.scrollTop,\n left: element.scrollLeft,\n });\n }\n\n Array.from(element.children).forEach((child) => {\n this.captureScrollPositions(child, positions);\n });\n }\n\n private morphElement(from: Element, to: Element, ctx: MorphContext): void {\n // Sync attributes\n this.syncAttributes(from, to);\n\n // Morph children\n this.morphChildren(from, to, ctx);\n }\n\n private syncAttributes(from: Element, to: Element): void {\n const fromAttrs = from.attributes;\n const toAttrs = to.attributes;\n\n // Remove attributes not in target\n for (let i = fromAttrs.length - 1; i >= 0; i--) {\n const attr = fromAttrs[i]!;\n if (!to.hasAttribute(attr.name)) {\n from.removeAttribute(attr.name);\n }\n }\n\n // Add/update attributes from target\n for (let i = 0; i < toAttrs.length; i++) {\n const attr = toAttrs[i]!;\n if (from.getAttribute(attr.name) !== attr.value) {\n from.setAttribute(attr.name, attr.value);\n }\n }\n }\n\n private morphChildren(from: Element, to: Element, ctx: MorphContext): void {\n const fromChildren = Array.from(from.childNodes);\n const toChildren = Array.from(to.childNodes);\n\n let fromIndex = 0;\n let toIndex = 0;\n\n while (toIndex < toChildren.length) {\n const toNode = toChildren[toIndex]!;\n const fromNode = fromChildren[fromIndex];\n\n if (!fromNode) {\n // Append new node\n from.appendChild(toNode.cloneNode(true));\n toIndex++;\n continue;\n }\n\n if (this.nodesMatch(fromNode, toNode)) {\n // Nodes match - recurse or update text\n if (fromNode.nodeType === Node.TEXT_NODE) {\n if (fromNode.nodeValue !== toNode.nodeValue) {\n fromNode.nodeValue = toNode.nodeValue;\n }\n } else if (fromNode.nodeType === Node.ELEMENT_NODE) {\n this.morphElement(fromNode as Element, toNode as Element, ctx);\n }\n fromIndex++;\n toIndex++;\n } else {\n // Try to find matching node ahead\n const matchIndex = this.findMatchingNode(\n fromChildren,\n fromIndex + 1,\n toNode\n );\n\n if (matchIndex !== -1) {\n // Remove nodes before match\n for (let i = fromIndex; i < matchIndex; i++) {\n from.removeChild(fromChildren[i]!);\n }\n fromIndex = matchIndex;\n } else {\n // Insert new node\n from.insertBefore(toNode.cloneNode(true), fromNode);\n toIndex++;\n }\n }\n }\n\n // Remove remaining old nodes\n while (fromIndex < fromChildren.length) {\n from.removeChild(fromChildren[fromIndex]!);\n fromIndex++;\n }\n }\n\n private nodesMatch(a: Node, b: Node): boolean {\n if (a.nodeType !== b.nodeType) return false;\n\n if (a.nodeType === Node.ELEMENT_NODE) {\n const aEl = a as Element;\n const bEl = b as Element;\n\n if (aEl.tagName !== bEl.tagName) return false;\n\n const aId = aEl.getAttribute(\"id\");\n const bId = bEl.getAttribute(\"id\");\n\n if (aId && bId) return aId === bId;\n\n return true;\n }\n\n return true;\n }\n\n private findMatchingNode(\n nodes: Node[],\n startIndex: number,\n target: Node\n ): number {\n for (let i = startIndex; i < nodes.length; i++) {\n if (this.nodesMatch(nodes[i]!, target)) {\n return i;\n }\n }\n return -1;\n }\n}\n\nexport function createMorpher(config?: Partial<MorphConfig>): DOMmorpher {\n return new DOMmorpher(config);\n}\n\nexport function morph(\n from: Element,\n to: Element,\n config?: Partial<MorphConfig>\n): void {\n const morpher = createMorpher(config);\n morpher.morph(from, to);\n}\n","interface SpeculatedPage {\n href: string;\n html: string;\n container: HTMLElement;\n timestamp: number;\n}\n\n/**\n * SpeculativeRenderer pre-renders pages in detached DOM containers.\n * \n * LIMITATIONS:\n * - This implementation uses innerHTML, NOT React rendering. The speculated content\n * is raw HTML set on a disconnected DOM node, not a fully rendered React component tree.\n * - For true React speculative rendering, the container must be appended to the document\n * (hidden via CSS) and ReactDOM.createRoot(container).render(...) must be called.\n * - Current implementation is suitable for static HTML morphing but may produce different\n * results than a real React render for dynamic components.\n */\nexport class SpeculativeRenderer {\n private speculations: Map<string, SpeculatedPage> = new Map();\n private maxSpeculations: number;\n\n constructor(maxSpeculations = 3) {\n this.maxSpeculations = maxSpeculations;\n }\n\n async speculate(href: string, html: string): Promise<void> {\n if (this.speculations.has(href)) return;\n\n // Evict oldest if at capacity\n if (this.speculations.size >= this.maxSpeculations) {\n const oldest = Array.from(this.speculations.values()).sort(\n (a, b) => a.timestamp - b.timestamp\n )[0];\n if (oldest) this.cancel(oldest.href);\n }\n\n const container = this.createDetachedContainer();\n container.innerHTML = html;\n\n this.speculations.set(href, {\n href,\n html,\n container,\n timestamp: Date.now(),\n });\n }\n\n get(href: string): HTMLElement | null {\n const speculation = this.speculations.get(href);\n return speculation?.container ?? null;\n }\n\n cancel(href: string): void {\n const speculation = this.speculations.get(href);\n if (speculation) {\n speculation.container.remove();\n this.speculations.delete(href);\n }\n }\n\n cancelAll(): void {\n this.speculations.forEach((spec) => spec.container.remove());\n this.speculations.clear();\n }\n\n has(href: string): boolean {\n return this.speculations.has(href);\n }\n\n private createDetachedContainer(): HTMLElement {\n const container = document.createElement(\"div\");\n container.style.display = \"none\";\n container.setAttribute(\"data-specnav-speculation\", \"true\");\n return container;\n }\n}\n\nexport function createSpeculativeRenderer(\n maxSpeculations?: number\n): SpeculativeRenderer {\n return new SpeculativeRenderer(maxSpeculations);\n}\n","import type { GraphConfig, NavigationGraph } from \"./types\";\n\nconst DEFAULT_CONFIG: GraphConfig = {\n enabled: true,\n minConfidence: 0.6,\n sessionWeight: 0.7,\n storageKey: \"specnav-graph\",\n maxNodes: 50,\n};\n\nexport class NavigationGraphLearner {\n private config: GraphConfig;\n private graph: NavigationGraph = {};\n private sessionGraph: NavigationGraph = {};\n\n constructor(config: Partial<GraphConfig> = {}) {\n this.config = { ...DEFAULT_CONFIG, ...config };\n if (this.config.enabled) {\n this.loadGraph();\n }\n }\n\n recordNavigation(fromHref: string, toHref: string): void {\n if (!this.config.enabled) return;\n\n // Update session graph\n if (!this.sessionGraph[fromHref]) {\n this.sessionGraph[fromHref] = {};\n }\n const current = this.sessionGraph[fromHref]![toHref] ?? 0;\n this.sessionGraph[fromHref]![toHref] = current + 1;\n\n // Update persistent graph\n if (!this.graph[fromHref]) {\n this.graph[fromHref] = {};\n }\n const persistentCurrent = this.graph[fromHref]![toHref] ?? 0;\n this.graph[fromHref]![toHref] = persistentCurrent + 1;\n\n this.saveGraph();\n }\n\n getPredictions(fromHref: string): string[] {\n if (!this.config.enabled) return [];\n\n const sessionEdges = this.sessionGraph[fromHref] ?? {};\n const persistentEdges = this.graph[fromHref] ?? {};\n\n // Merge session and persistent with weighting\n const merged: Record<string, number> = {};\n\n Object.entries(persistentEdges).forEach(([href, count]) => {\n merged[href] = count * (1 - this.config.sessionWeight);\n });\n\n Object.entries(sessionEdges).forEach(([href, count]) => {\n merged[href] = (merged[href] ?? 0) + count * this.config.sessionWeight;\n });\n\n // Calculate total for normalization\n const total = Object.values(merged).reduce((sum, val) => sum + val, 0);\n if (total === 0) return [];\n\n // Convert to confidence scores and filter\n const predictions = Object.entries(merged)\n .map(([href, count]) => ({\n href,\n confidence: count / total,\n }))\n .filter((p) => p.confidence >= this.config.minConfidence)\n .sort((a, b) => b.confidence - a.confidence)\n .map((p) => p.href);\n\n return predictions;\n }\n\n getGraph(): NavigationGraph {\n return { ...this.graph };\n }\n\n clearGraph(): void {\n this.graph = {};\n this.sessionGraph = {};\n this.saveGraph();\n }\n\n private loadGraph(): void {\n if (typeof localStorage === \"undefined\") return;\n\n try {\n const stored = localStorage.getItem(this.config.storageKey);\n if (stored) {\n this.graph = JSON.parse(stored);\n this.pruneGraph();\n }\n } catch {\n // Silently fail\n }\n }\n\n private saveGraph(): void {\n if (typeof localStorage === \"undefined\") return;\n\n try {\n this.pruneGraph();\n const serialized = JSON.stringify(this.graph);\n \n // Check size before saving (localStorage typically has 5-10MB limit)\n if (serialized.length > 4 * 1024 * 1024) { // 4MB safety limit\n console.warn(\"Navigation graph too large, pruning more aggressively\");\n // Prune to half the max nodes (use local variable)\n const reducedMaxNodes = Math.floor(this.config.maxNodes / 2);\n const originalMaxNodes = this.config.maxNodes;\n this.config.maxNodes = reducedMaxNodes;\n this.pruneGraph();\n this.config.maxNodes = originalMaxNodes; // Restore original\n }\n \n localStorage.setItem(this.config.storageKey, JSON.stringify(this.graph));\n } catch (error) {\n // Handle quota exceeded error\n if (error instanceof Error && error.name === \"QuotaExceededError\") {\n console.warn(\"localStorage quota exceeded, clearing navigation graph\");\n this.clearGraph();\n }\n }\n }\n\n private pruneGraph(): void {\n const nodes = Object.keys(this.graph);\n if (nodes.length <= this.config.maxNodes) return;\n\n // Calculate total transitions per node\n const nodeCounts = nodes.map((node) => ({\n node,\n count: Object.values(this.graph[node]!).reduce(\n (sum, val) => sum + val,\n 0\n ),\n }));\n\n // Sort by count and keep top maxNodes\n nodeCounts.sort((a, b) => b.count - a.count);\n const toKeep = new Set(\n nodeCounts.slice(0, this.config.maxNodes).map((n) => n.node)\n );\n\n // Remove nodes not in top set\n Object.keys(this.graph).forEach((node) => {\n if (!toKeep.has(node)) {\n delete this.graph[node];\n }\n });\n }\n}\n\nexport function createNavigationGraphLearner(\n config?: Partial<GraphConfig>\n): NavigationGraphLearner {\n return new NavigationGraphLearner(config);\n}\n\nexport function getNavigationGraph(\n storageKey = \"specnav-graph\"\n): NavigationGraph {\n if (typeof localStorage === \"undefined\") return {};\n\n try {\n const stored = localStorage.getItem(storageKey);\n return stored ? JSON.parse(stored) : {};\n } catch {\n return {};\n }\n}\n","import type { AdaptiveConfig, Strategy } from \"./types\";\n\nconst DEFAULT_CONFIG: AdaptiveConfig = {\n batteryThreshold: 0.2,\n connectionTypes: {\n slow: [\"2g\", \"3g\", \"slow-2g\"],\n fast: [\"4g\"],\n },\n respectSaveData: true,\n respectReducedMotion: true,\n};\n\nexport class AdaptiveMode {\n private config: AdaptiveConfig;\n private battery: any = null;\n private connection: any = null;\n private initPromise: Promise<void>;\n\n constructor(config: Partial<AdaptiveConfig> = {}) {\n this.config = { ...DEFAULT_CONFIG, ...config };\n this.initPromise = this.initialize();\n }\n\n async waitForInit(): Promise<void> {\n await this.initPromise;\n }\n\n private async initialize(): Promise<void> {\n if (typeof navigator === \"undefined\") return;\n\n // Battery API\n if (\"getBattery\" in navigator) {\n try {\n this.battery = await (navigator as any).getBattery();\n } catch {\n // Not available\n }\n }\n\n // Network Information API\n if (\"connection\" in navigator || \"mozConnection\" in navigator || \"webkitConnection\" in navigator) {\n this.connection =\n (navigator as any).connection ||\n (navigator as any).mozConnection ||\n (navigator as any).webkitConnection;\n }\n }\n\n getStrategy(baseStrategy: Strategy): Strategy {\n if (baseStrategy === \"off\") return \"off\";\n if (baseStrategy !== \"auto\") return baseStrategy;\n\n // Check Save-Data\n if (this.config.respectSaveData && this.hasSaveData()) {\n return \"off\";\n }\n\n // Check battery\n if (this.isLowBattery()) {\n return \"conservative\";\n }\n\n // Check connection\n if (this.isSlowConnection()) {\n return \"conservative\";\n }\n\n return \"aggressive\";\n }\n\n shouldPrefetch(): boolean {\n if (this.config.respectSaveData && this.hasSaveData()) {\n return false;\n }\n\n if (this.isLowBattery()) {\n return false;\n }\n\n return true;\n }\n\n shouldSpeculate(): boolean {\n if (!this.shouldPrefetch()) {\n return false;\n }\n\n if (this.isSlowConnection()) {\n return false;\n }\n\n return true;\n }\n\n shouldUseTransitions(): boolean {\n if (!this.config.respectReducedMotion) return true;\n\n if (typeof window === \"undefined\") return true;\n\n return !window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n }\n\n private hasSaveData(): boolean {\n if (typeof navigator === \"undefined\") return false;\n\n return (\n (navigator as any).connection?.saveData === true ||\n (navigator as any).mozConnection?.saveData === true ||\n (navigator as any).webkitConnection?.saveData === true\n );\n }\n\n private isLowBattery(): boolean {\n if (!this.battery) return false;\n\n return (\n !this.battery.charging &&\n this.battery.level < this.config.batteryThreshold\n );\n }\n\n private isSlowConnection(): boolean {\n if (!this.connection) return false;\n\n const effectiveType = this.connection.effectiveType;\n if (!effectiveType) return false;\n\n return this.config.connectionTypes.slow.includes(effectiveType);\n }\n\n isFastConnection(): boolean {\n if (!this.connection) return true; // Assume fast if unknown\n\n const effectiveType = this.connection.effectiveType;\n if (!effectiveType) return true;\n\n return this.config.connectionTypes.fast.includes(effectiveType);\n }\n\n getBatteryLevel(): number | null {\n return this.battery?.level ?? null;\n }\n\n getConnectionType(): string | null {\n return this.connection?.effectiveType ?? null;\n }\n}\n\nexport function createAdaptiveMode(\n config?: Partial<AdaptiveConfig>\n): AdaptiveMode {\n return new AdaptiveMode(config);\n}\n","// Performance monitoring utilities\n\nexport interface PerformanceMetrics {\n navigationTime: number;\n cacheHit: boolean;\n cacheLayer?: 1 | 2 | 3;\n speculativeHit: boolean;\n fetchTime?: number;\n morphTime?: number;\n}\n\nexport class PerformanceMonitor {\n private metrics: PerformanceMetrics[] = [];\n private maxMetrics = 100;\n\n recordNavigation(metrics: PerformanceMetrics): void {\n this.metrics.push(metrics);\n \n // Keep only last N metrics\n if (this.metrics.length > this.maxMetrics) {\n this.metrics.shift();\n }\n }\n\n getAverageNavigationTime(): number {\n if (this.metrics.length === 0) return 0;\n const sum = this.metrics.reduce((acc, m) => acc + m.navigationTime, 0);\n return sum / this.metrics.length;\n }\n\n getCacheHitRate(): number {\n if (this.metrics.length === 0) return 0;\n const hits = this.metrics.filter(m => m.cacheHit).length;\n return hits / this.metrics.length;\n }\n\n getSpeculativeHitRate(): number {\n if (this.metrics.length === 0) return 0;\n const hits = this.metrics.filter(m => m.speculativeHit).length;\n return hits / this.metrics.length;\n }\n\n getMetrics(): PerformanceMetrics[] {\n return [...this.metrics];\n }\n\n clear(): void {\n this.metrics = [];\n }\n}\n\nexport const performanceMonitor = new PerformanceMonitor();\n"]}
|
package/package.json
CHANGED