vite-devtools-svelte 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -258,8 +258,8 @@ function N(e) {
258
258
  }
259
259
  //#endregion
260
260
  //#region src/runtime.ts
261
- var P = "virtual:svelte-devtools-runtime", F = "\0virtual:svelte-devtools-runtime", I = "\0svelte-devtools:wrapped-client", L = "\nimport * as __svelte_original from 'svelte/internal/client';\nexport * from 'svelte/internal/client';\n\nfunction __dt() {\n return typeof window !== 'undefined' ? window.__SVELTE_DEVTOOLS__ : null;\n}\n\n// Component ID stack (parallel to runtime._stack but local to wrapper)\nconst __idStack = [];\nfunction __currentId() {\n return __idStack.length > 0 ? __idStack[__idStack.length - 1] : null;\n}\n\n// Tracks the most recently created signal for type determination in tag()\nconst __pendingSignal = { ref: null, type: null };\n\n// --- Component Lifecycle ---\n//\n// Observer must not break the observed: every devtools side-effect below is\n// wrapped in try/catch so a bug or an out-of-shape runtime cannot tear down\n// the user's app. The original Svelte function is always called, and its\n// return value always returned, regardless of devtools failures.\n\nexport function push() {\n const result = __svelte_original.push.apply(null, arguments);\n try {\n const dt = __dt();\n if (dt) {\n const file = dt._pendingFile || 'Unknown';\n dt._pendingFile = null;\n const id = dt.register(file);\n __idStack.push(id);\n dt.startInit(id);\n try {\n __svelte_original.user_effect(() => {\n return () => { try { dt.unmount(id); } catch {} };\n });\n } catch {}\n }\n } catch {}\n return result;\n}\n\nexport function pop() {\n // Capture devtools errors but ALWAYS forward to the original pop so the\n // Svelte component stack stays balanced.\n try {\n const dt = __dt();\n if (dt && __idStack.length > 0) {\n const id = __idStack.pop();\n try { dt.endInit(id); } catch {}\n try { dt.registered(id); } catch {}\n }\n } catch {}\n return __svelte_original.pop.apply(null, arguments);\n}\n\n// --- Signal Creation (type markers) ---\n\nexport function state() {\n const signal = __svelte_original.state.apply(null, arguments);\n try {\n __pendingSignal.ref = signal;\n __pendingSignal.type = 'state';\n } catch {}\n return signal;\n}\n\nexport function derived() {\n const signal = __svelte_original.derived.apply(null, arguments);\n try {\n __pendingSignal.ref = signal;\n __pendingSignal.type = 'derived';\n } catch {}\n return signal;\n}\n\nexport function proxy() {\n const p = __svelte_original.proxy.apply(null, arguments);\n try {\n __pendingSignal.ref = p;\n __pendingSignal.type = 'proxy';\n } catch {}\n return p;\n}\n\n// --- Signal Tagging (Svelte dev mode) ---\n\nexport function tag(signal, name) {\n const result = __svelte_original.tag.apply(null, arguments);\n try {\n const dt = __dt();\n const cid = __currentId();\n if (dt && cid !== null) {\n const type = (__pendingSignal.ref === signal) ? __pendingSignal.type : 'state';\n if (type === 'derived') {\n dt.trackDerived(signal, name, cid);\n } else {\n dt.trackState(signal, name, cid);\n }\n }\n __pendingSignal.ref = null;\n __pendingSignal.type = null;\n } catch {}\n return result;\n}\n\nexport function tag_proxy(proxy, name) {\n const result = __svelte_original.tag_proxy.apply(null, arguments);\n try {\n const dt = __dt();\n const cid = __currentId();\n if (dt && cid !== null) {\n dt.trackProxy(proxy, name, cid);\n }\n __pendingSignal.ref = null;\n __pendingSignal.type = null;\n } catch {}\n return result;\n}\n\n// --- Effect Tracking ---\n\nexport function user_effect() {\n const result = __svelte_original.user_effect.apply(null, arguments);\n try {\n const dt = __dt();\n const cid = __currentId();\n if (dt && cid !== null) {\n dt._effectCounter = (dt._effectCounter || 0) + 1;\n // Track the effect OBJECT (not the callback). The Svelte runtime\n // populates result.deps with the signals this effect depends on,\n // which is what getReactiveGraph() reads to build edges.\n dt.trackEffect(result, 'effect_' + dt._effectCounter, cid);\n }\n } catch {}\n return result;\n}\n\nexport function user_pre_effect() {\n const result = __svelte_original.user_pre_effect.apply(null, arguments);\n try {\n const dt = __dt();\n const cid = __currentId();\n if (dt && cid !== null) {\n dt._effectCounter = (dt._effectCounter || 0) + 1;\n dt.trackEffect(result, 'effect_pre_' + dt._effectCounter, cid);\n }\n } catch {}\n return result;\n}\n", R = "\nif (typeof window !== 'undefined' && !window.__SVELTE_DEVTOOLS__) {\n const __SVELTE_DT = {\n _nextId: 0,\n _instances: new Map(),\n _stack: [],\n _pendingFile: null,\n _effectCounter: 0,\n _debounceTimer: null,\n _listeners: new Set(),\n\n // Phase 2: Profiling data\n _profiles: new Map(),\n _initStartTimes: new Map(),\n _profileDebounceTimer: null,\n\n // Phase 2: Reactive graph data\n _reactiveNodes: new Map(),\n _reactiveProxies: new Map(),\n\n // Phase 3: State timeline\n _stateTimeline: [],\n _stateSnapshots: new Map(),\n _timelineDebounceTimer: null,\n\n register(file) {\n const id = this._nextId++;\n const parentId = this._stack.length > 0 ? this._stack[this._stack.length - 1] : null;\n const name = file.split('/').pop()?.replace('.svelte', '') || 'Unknown';\n this._instances.set(id, { id, file, name, parentId, mounted: true, children: [] });\n if (parentId !== null) {\n const parent = this._instances.get(parentId);\n if (parent) parent.children.push(id);\n }\n this._stack.push(id);\n this._scheduleUpdate();\n return id;\n },\n\n registered(id) {\n const idx = this._stack.indexOf(id);\n if (idx !== -1) this._stack.splice(idx, 1);\n },\n\n mount(id) {\n const instance = this._instances.get(id);\n if (instance && !instance.mounted) {\n instance.mounted = true;\n this._scheduleUpdate();\n }\n },\n\n unmount(id) {\n const instance = this._instances.get(id);\n if (instance) {\n if (instance.parentId !== null) {\n const parent = this._instances.get(instance.parentId);\n if (parent) {\n parent.children = parent.children.filter(cid => cid !== id);\n }\n }\n this._removeChildren(id);\n this._cleanupReactiveNodes(id);\n this._instances.delete(id);\n }\n this._scheduleUpdate();\n },\n\n _cleanupReactiveNodes(componentId) {\n for (const [nodeId, entry] of this._reactiveNodes) {\n if (entry.meta.componentId === componentId) {\n this._reactiveNodes.delete(nodeId);\n }\n }\n },\n\n _removeChildren(parentId) {\n const parent = this._instances.get(parentId);\n if (!parent) return;\n for (const childId of [...parent.children]) {\n this._removeChildren(childId);\n this._cleanupReactiveNodes(childId);\n this._instances.delete(childId);\n }\n },\n\n _scheduleUpdate() {\n if (this._debounceTimer) clearTimeout(this._debounceTimer);\n this._debounceTimer = setTimeout(() => {\n this._sendUpdate();\n }, 100);\n },\n\n _sendUpdate() {\n const components = [];\n for (const [, instance] of this._instances) {\n if (instance.mounted) {\n components.push({\n id: instance.id,\n file: instance.file,\n name: instance.name,\n parentId: instance.parentId,\n mounted: instance.mounted,\n });\n }\n }\n if (import.meta.hot) {\n import.meta.hot.send('svelte-devtools:components', { components });\n }\n },\n\n getTree() {\n const components = [];\n for (const [, instance] of this._instances) {\n if (instance.mounted) {\n components.push({\n id: instance.id,\n file: instance.file,\n name: instance.name,\n parentId: instance.parentId,\n mounted: instance.mounted,\n });\n }\n }\n return components;\n },\n\n // --- Phase 2: Render Profiling ---\n\n startInit(id) {\n this._initStartTimes.set(id, performance.now());\n },\n\n endInit(id) {\n const start = this._initStartTimes.get(id);\n if (start === undefined) return;\n const initTime = performance.now() - start;\n this._initStartTimes.delete(id);\n const instance = this._instances.get(id);\n if (!instance) return;\n this._profiles.set(id, {\n componentId: id,\n file: instance.file,\n name: instance.name,\n initTime,\n renderCount: 0,\n totalRenderTime: 0,\n lastRenderTime: 0,\n lastRenderAt: Date.now(),\n });\n this._scheduleProfileUpdate();\n },\n\n recordRender(id) {\n const profile = this._profiles.get(id);\n if (!profile) {\n const instance = this._instances.get(id);\n if (!instance) return;\n this._profiles.set(id, {\n componentId: id,\n file: instance.file,\n name: instance.name,\n initTime: 0,\n renderCount: 1,\n totalRenderTime: 0,\n lastRenderTime: 0,\n lastRenderAt: Date.now(),\n });\n } else {\n profile.renderCount++;\n profile.lastRenderAt = Date.now();\n }\n this._scheduleProfileUpdate();\n },\n\n recordRenderTime(id, duration) {\n const profile = this._profiles.get(id);\n if (profile) {\n profile.totalRenderTime += duration;\n profile.lastRenderTime = duration;\n }\n },\n\n _scheduleProfileUpdate() {\n if (this._profileDebounceTimer) clearTimeout(this._profileDebounceTimer);\n this._profileDebounceTimer = setTimeout(() => {\n this._sendProfileUpdate();\n }, 500);\n },\n\n _sendProfileUpdate() {\n const profiles = Array.from(this._profiles.values());\n if (import.meta.hot) {\n import.meta.hot.send('svelte-devtools:profiles', { profiles });\n }\n },\n\n getProfiles() {\n return Array.from(this._profiles.values());\n },\n\n resetProfiles() {\n this._profiles.clear();\n this._scheduleProfileUpdate();\n },\n\n // --- Phase 2: Reactive Graph Tracking ---\n\n trackState(signal, name, componentId) {\n const instance = this._instances.get(componentId);\n const nodeId = componentId + ':' + name;\n this._reactiveNodes.set(nodeId, {\n signal: new WeakRef(signal),\n meta: { id: nodeId, type: 'state', name, componentId, componentFile: instance ? instance.file : '' }\n });\n },\n\n trackProxy(proxy, name, componentId) {\n const instance = this._instances.get(componentId);\n const nodeId = componentId + ':' + name;\n this._reactiveProxies.set(nodeId, new WeakRef(proxy));\n this._reactiveNodes.set(nodeId, {\n signal: new WeakRef({ v: '(proxy)', _isProxy: true }),\n meta: { id: nodeId, type: 'state', name, componentId, componentFile: instance ? instance.file : '' }\n });\n },\n\n trackDerived(signal, name, componentId) {\n const instance = this._instances.get(componentId);\n const nodeId = componentId + ':' + name;\n this._reactiveNodes.set(nodeId, {\n signal: new WeakRef(signal),\n meta: { id: nodeId, type: 'derived', name, componentId, componentFile: instance ? instance.file : '' }\n });\n },\n\n trackEffect(effect, name, componentId) {\n const instance = this._instances.get(componentId);\n const nodeId = componentId + ':' + name;\n this._reactiveNodes.set(nodeId, {\n signal: new WeakRef(effect || { v: undefined, _isEffect: true }),\n meta: { id: nodeId, type: 'effect', name, componentId, componentFile: instance ? instance.file : '' }\n });\n return effect;\n },\n\n getReactiveGraph() {\n const nodes = [];\n const edges = [];\n const signalToId = new Map();\n\n for (const [nodeId, entry] of this._reactiveNodes) {\n const signal = entry.signal.deref();\n if (!signal || !this._instances.has(entry.meta.componentId)) {\n this._reactiveNodes.delete(nodeId);\n continue;\n }\n signalToId.set(signal, nodeId);\n const node = { ...entry.meta };\n if (signal._isProxy) {\n const proxyRef = this._reactiveProxies.get(nodeId);\n const proxy = proxyRef?.deref();\n if (proxy) {\n try {\n node.value = Array.isArray(proxy) ? '[' + proxy.length + ']' : '{' + Object.keys(proxy).length + '}';\n } catch { node.value = '(proxy)'; }\n }\n } else if (node.type !== 'effect' && signal.v !== undefined && typeof signal.v !== 'symbol') {\n try {\n const v = signal.v;\n if (typeof v === 'number' || typeof v === 'string' || typeof v === 'boolean' || v === null) {\n node.value = v;\n } else {\n node.value = '(object)';\n }\n } catch { /* ignore */ }\n }\n nodes.push(node);\n }\n\n // Map proxy internal signals to their proxy node ID\n for (const [nodeId, ref] of this._reactiveProxies) {\n const proxy = ref.deref();\n if (!proxy) { this._reactiveProxies.delete(nodeId); continue; }\n const meta = this._reactiveNodes.get(nodeId)?.meta;\n if (!meta || !this._instances.has(meta.componentId)) { this._reactiveProxies.delete(nodeId); continue; }\n }\n\n // Build edges from deps\n const edgeSet = new Set();\n for (const [nodeId, entry] of this._reactiveNodes) {\n const signal = entry.signal.deref();\n if (!signal) continue;\n if (!signal.deps) continue;\n\n const visited = new Set();\n const queue = [...signal.deps];\n while (queue.length > 0) {\n const dep = queue.shift();\n if (!dep || visited.has(dep)) continue;\n visited.add(dep);\n const depId = signalToId.get(dep);\n if (depId) {\n const key = depId + '>' + nodeId;\n if (depId !== nodeId && !edgeSet.has(key)) {\n edgeSet.add(key);\n edges.push({ from: depId, to: nodeId });\n }\n } else if (dep.deps) {\n for (const d of dep.deps) queue.push(d);\n }\n }\n }\n\n return { nodes, edges };\n },\n\n sendReactiveGraph() {\n const graph = this.getReactiveGraph();\n if (import.meta.hot) {\n import.meta.hot.send('svelte-devtools:reactive-graph', graph);\n }\n },\n\n // --- Phase 3: State Timeline ---\n\n _pollStateValues() {\n for (const [nodeId, entry] of this._reactiveNodes) {\n if (entry.meta.type !== 'state') continue;\n if (!this._instances.has(entry.meta.componentId)) {\n this._reactiveNodes.delete(nodeId);\n continue;\n }\n const signal = entry.signal.deref();\n if (!signal || signal.v === undefined) continue;\n try {\n const currentVal = signal.v;\n const prev = this._stateSnapshots.get(nodeId);\n if (prev !== undefined && currentVal === prev) continue;\n const isPrimitive = currentVal === null || typeof currentVal !== 'object';\n let newSnapshot;\n if (isPrimitive) {\n if (prev !== undefined && prev === currentVal) continue;\n newSnapshot = currentVal;\n } else {\n const currStr = JSON.stringify(currentVal);\n const prevStr = this._stateSnapshotStrs?.get(nodeId);\n if (prevStr === currStr) continue;\n newSnapshot = JSON.parse(currStr);\n if (!this._stateSnapshotStrs) this._stateSnapshotStrs = new Map();\n this._stateSnapshotStrs.set(nodeId, currStr);\n }\n if (this._stateTimeline.length >= 500) this._stateTimeline.splice(0, this._stateTimeline.length - 499);\n this._stateTimeline.push({\n id: nodeId,\n name: entry.meta.name,\n componentFile: entry.meta.componentFile,\n oldValue: prev !== undefined ? prev : null,\n newValue: newSnapshot,\n timestamp: Date.now(),\n });\n this._stateSnapshots.set(nodeId, newSnapshot);\n this._scheduleTimelineUpdate();\n } catch { /* ignore non-serializable */ }\n }\n },\n\n _scheduleTimelineUpdate() {\n if (this._timelineDebounceTimer) clearTimeout(this._timelineDebounceTimer);\n this._timelineDebounceTimer = setTimeout(() => {\n if (import.meta.hot) {\n import.meta.hot.send('svelte-devtools:state-timeline', { changes: this._stateTimeline });\n }\n }, 300);\n },\n\n getStateTimeline() {\n return this._stateTimeline;\n },\n\n clearStateTimeline() {\n this._stateTimeline = [];\n this._scheduleTimelineUpdate();\n },\n\n // --- FPS Monitoring ---\n // Uses requestAnimationFrame to measure frame rate with minimal overhead.\n // Only stores timestamps - no allocations per frame beyond a single array push.\n _fpsFrameTimes: [],\n\n _fpsLoop() {\n this._fpsFrameTimes.push(performance.now());\n requestAnimationFrame(() => this._fpsLoop());\n },\n\n _sampleFps() {\n const now = performance.now();\n // Remove frame timestamps older than 1 second\n const cutoff = now - 1000;\n let i = 0;\n while (i < this._fpsFrameTimes.length && this._fpsFrameTimes[i] < cutoff) i++;\n if (i > 0) this._fpsFrameTimes.splice(0, i);\n const fps = this._fpsFrameTimes.length;\n if (import.meta.hot) {\n import.meta.hot.send('svelte-devtools:fps', { timestamp: Date.now(), fps });\n }\n }\n };\n\n window.__SVELTE_DEVTOOLS__ = __SVELTE_DT;\n\n // Poll state values for timeline\n setInterval(() => { __SVELTE_DT._pollStateValues(); }, 200);\n\n // FPS monitoring\n requestAnimationFrame(() => __SVELTE_DT._fpsLoop());\n setInterval(() => __SVELTE_DT._sampleFps(), 500);\n\n // Phase 3: Capture runtime errors\n window.addEventListener('error', (event) => {\n if (import.meta.hot) {\n import.meta.hot.send('svelte-devtools:runtime-error', {\n message: event.message,\n file: event.filename,\n line: event.lineno,\n column: event.colno,\n stack: event.error?.stack || '',\n timestamp: Date.now(),\n });\n }\n });\n window.addEventListener('unhandledrejection', (event) => {\n if (import.meta.hot) {\n const reason = event.reason;\n import.meta.hot.send('svelte-devtools:runtime-error', {\n message: reason?.message || String(reason),\n stack: reason?.stack || '',\n timestamp: Date.now(),\n });\n }\n });\n\n // Listen for reactive graph requests from server\n if (import.meta.hot) {\n import.meta.hot.on('svelte-devtools:request-reactive-graph', () => {\n __SVELTE_DT.sendReactiveGraph();\n });\n import.meta.hot.on('svelte-devtools:request-state-timeline', () => {\n import.meta.hot.send('svelte-devtools:state-timeline', { changes: __SVELTE_DT._stateTimeline });\n });\n import.meta.hot.on('svelte-devtools:clear-state-timeline', () => {\n __SVELTE_DT.clearStateTimeline();\n });\n }\n}\n", z = 1, B = 5, V = 1, H = 30;
262
- function U(e) {
261
+ var P = "virtual:svelte-devtools-runtime", ee = "\0virtual:svelte-devtools-runtime", F = "\0svelte-devtools:wrapped-client", I = "\nimport * as __svelte_original from 'svelte/internal/client';\nexport * from 'svelte/internal/client';\n\nfunction __dt() {\n return typeof window !== 'undefined' ? window.__SVELTE_DEVTOOLS__ : null;\n}\n\n// Component ID stack (parallel to runtime._stack but local to wrapper)\nconst __idStack = [];\nfunction __currentId() {\n return __idStack.length > 0 ? __idStack[__idStack.length - 1] : null;\n}\n\n// Tracks the most recently created signal for type determination in tag()\nconst __pendingSignal = { ref: null, type: null };\n\n// --- Component Lifecycle ---\n//\n// Observer must not break the observed: every devtools side-effect below is\n// wrapped in try/catch so a bug or an out-of-shape runtime cannot tear down\n// the user's app. The original Svelte function is always called, and its\n// return value always returned, regardless of devtools failures.\n\nexport function push() {\n const result = __svelte_original.push.apply(null, arguments);\n try {\n const dt = __dt();\n if (dt) {\n const file = dt._pendingFile || 'Unknown';\n dt._pendingFile = null;\n const id = dt.register(file);\n __idStack.push(id);\n dt.startInit(id);\n try {\n __svelte_original.user_effect(() => {\n return () => { try { dt.unmount(id); } catch {} };\n });\n } catch {}\n }\n } catch {}\n return result;\n}\n\nexport function pop() {\n // Capture devtools errors but ALWAYS forward to the original pop so the\n // Svelte component stack stays balanced.\n try {\n const dt = __dt();\n if (dt && __idStack.length > 0) {\n const id = __idStack.pop();\n try { dt.endInit(id); } catch {}\n try { dt.registered(id); } catch {}\n }\n } catch {}\n return __svelte_original.pop.apply(null, arguments);\n}\n\n// --- Signal Creation (type markers) ---\n\nexport function state() {\n const signal = __svelte_original.state.apply(null, arguments);\n try {\n __pendingSignal.ref = signal;\n __pendingSignal.type = 'state';\n } catch {}\n return signal;\n}\n\nexport function derived() {\n const signal = __svelte_original.derived.apply(null, arguments);\n try {\n __pendingSignal.ref = signal;\n __pendingSignal.type = 'derived';\n } catch {}\n return signal;\n}\n\nexport function proxy() {\n const p = __svelte_original.proxy.apply(null, arguments);\n try {\n __pendingSignal.ref = p;\n __pendingSignal.type = 'proxy';\n } catch {}\n return p;\n}\n\n// --- Signal Tagging (Svelte dev mode) ---\n\nexport function tag(signal, name) {\n const result = __svelte_original.tag.apply(null, arguments);\n try {\n const dt = __dt();\n const cid = __currentId();\n if (dt && cid !== null) {\n const type = (__pendingSignal.ref === signal) ? __pendingSignal.type : 'state';\n if (type === 'derived') {\n dt.trackDerived(signal, name, cid);\n } else {\n dt.trackState(signal, name, cid);\n }\n }\n __pendingSignal.ref = null;\n __pendingSignal.type = null;\n } catch {}\n return result;\n}\n\nexport function tag_proxy(proxy, name) {\n const result = __svelte_original.tag_proxy.apply(null, arguments);\n try {\n const dt = __dt();\n const cid = __currentId();\n if (dt && cid !== null) {\n dt.trackProxy(proxy, name, cid);\n }\n __pendingSignal.ref = null;\n __pendingSignal.type = null;\n } catch {}\n return result;\n}\n\n// --- Effect Tracking ---\n\nexport function user_effect() {\n const result = __svelte_original.user_effect.apply(null, arguments);\n try {\n const dt = __dt();\n const cid = __currentId();\n if (dt && cid !== null) {\n dt._effectCounter = (dt._effectCounter || 0) + 1;\n // Track the effect OBJECT (not the callback). The Svelte runtime\n // populates result.deps with the signals this effect depends on,\n // which is what getReactiveGraph() reads to build edges.\n dt.trackEffect(result, 'effect_' + dt._effectCounter, cid);\n }\n } catch {}\n return result;\n}\n\nexport function user_pre_effect() {\n const result = __svelte_original.user_pre_effect.apply(null, arguments);\n try {\n const dt = __dt();\n const cid = __currentId();\n if (dt && cid !== null) {\n dt._effectCounter = (dt._effectCounter || 0) + 1;\n dt.trackEffect(result, 'effect_pre_' + dt._effectCounter, cid);\n }\n } catch {}\n return result;\n}\n\n// --- Render Profiling ---\n//\n// Svelte 5 has no virtual DOM: the compiler wraps every dynamic part of a\n// template in a template_effect (deferred_template_effect for <svelte:head>\n// <title>). A re-run of such an effect IS the component updating the DOM, so\n// these two functions are the measurement points for renders / render time.\n//\n// The first run of an effect is the mount-time paint, already covered by\n// initTime, so it is skipped (initialRun). One state change re-runs several\n// effects of the same component, so durations are pooled per microtask and\n// recorded once per flush: recordRender() +1, recordRenderTime() the sum.\n\nconst __pendingRenderDurations = new Map();\nlet __renderFlushScheduled = false;\n\nfunction __flushRenderDurations() {\n __renderFlushScheduled = false;\n const dt = __dt();\n for (const [cid, duration] of __pendingRenderDurations) {\n if (dt) {\n try { dt.recordRender(cid); } catch {}\n try { dt.recordRenderTime(cid, duration); } catch {}\n }\n }\n __pendingRenderDurations.clear();\n}\n\nfunction __recordRenderDuration(cid, duration) {\n __pendingRenderDurations.set(cid, (__pendingRenderDurations.get(cid) || 0) + duration);\n if (!__renderFlushScheduled) {\n __renderFlushScheduled = true;\n queueMicrotask(__flushRenderDurations);\n }\n}\n\n// Returns a (possibly new) args array whose first element times each re-run\n// of the effect closure. The owning component is whatever id is on top of\n// __idStack at effect-creation time. User exceptions propagate untouched;\n// only the args are built inside try so the original is called exactly once.\nfunction __wrapTemplateEffect(args) {\n const cid = __currentId();\n const fn = args[0];\n if (cid === null || typeof fn !== 'function') return args;\n const wrapped = Array.prototype.slice.call(args);\n let initialRun = true;\n wrapped[0] = function () {\n if (initialRun) {\n initialRun = false;\n return fn.apply(this, arguments);\n }\n const start = performance.now();\n try {\n return fn.apply(this, arguments);\n } finally {\n try { __recordRenderDuration(cid, performance.now() - start); } catch {}\n }\n };\n return wrapped;\n}\n\nexport function template_effect() {\n let args = arguments;\n try { args = __wrapTemplateEffect(arguments); } catch {}\n return __svelte_original.template_effect.apply(null, args);\n}\n\nexport function deferred_template_effect() {\n let args = arguments;\n try { args = __wrapTemplateEffect(arguments); } catch {}\n return __svelte_original.deferred_template_effect.apply(null, args);\n}\n\n// --- Block Attribution ---\n//\n// Svelte creates render effects synchronously at creation time. At mount this\n// happens during the component function (between push/pop), so __idStack has\n// the owner. But effects for {#each} items added later or re-created {#if}\n// branches are created during a batch flush, when the stack is empty — they\n// would never be attributed. Block helpers themselves ARE always called\n// during their owner's init (or inside an outer block's callback), so the\n// owner id is on the stack at block-creation time. __wrapBlock captures it\n// and re-pushes it around every function argument the block invokes later,\n// so effects created inside land on the innermost owner. Child components\n// push their own id on top, keeping nested attribution correct.\n\nfunction __wrapBlockFn(fn, cid) {\n return function () {\n let pushed = false;\n try { __idStack.push(cid); pushed = true; } catch {}\n try {\n return fn.apply(this, arguments);\n } finally {\n if (pushed) { try { __idStack.pop(); } catch {} }\n }\n };\n}\n\nfunction __wrapBlock(args) {\n const cid = __currentId();\n if (cid === null) return args;\n const wrapped = Array.prototype.slice.call(args);\n for (let i = 0; i < wrapped.length; i++) {\n if (typeof wrapped[i] === 'function') wrapped[i] = __wrapBlockFn(wrapped[i], cid);\n }\n return wrapped;\n}\n\nexport function each() {\n let args = arguments;\n try { args = __wrapBlock(arguments); } catch {}\n return __svelte_original.each.apply(null, args);\n}\n\nexport function key() {\n let args = arguments;\n try { args = __wrapBlock(arguments); } catch {}\n return __svelte_original.key.apply(null, args);\n}\n\nexport function component() {\n let args = arguments;\n try { args = __wrapBlock(arguments); } catch {}\n return __svelte_original.component.apply(null, args);\n}\n\nexport function boundary() {\n let args = arguments;\n try { args = __wrapBlock(arguments); } catch {}\n return __svelte_original.boundary.apply(null, args);\n}\n\n// 'if' and 'await' are reserved words, so they cannot be declared as\n// function names and are exported via aliases instead.\nfunction __if_block() {\n let args = arguments;\n try { args = __wrapBlock(arguments); } catch {}\n return __svelte_original['if'].apply(null, args);\n}\n\nfunction __await_block() {\n let args = arguments;\n try { args = __wrapBlock(arguments); } catch {}\n return __svelte_original['await'].apply(null, args);\n}\n\nexport { __if_block as if, __await_block as await };\n", L = "\nif (typeof window !== 'undefined' && !window.__SVELTE_DEVTOOLS__) {\n const __SVELTE_DT = {\n _nextId: 0,\n _instances: new Map(),\n _stack: [],\n _pendingFile: null,\n _effectCounter: 0,\n _debounceTimer: null,\n _listeners: new Set(),\n\n // Phase 2: Profiling data\n _profiles: new Map(),\n _initStartTimes: new Map(),\n _profileDebounceTimer: null,\n\n // Phase 2: Reactive graph data\n _reactiveNodes: new Map(),\n _reactiveProxies: new Map(),\n\n // Phase 3: State timeline\n _stateTimeline: [],\n _stateSnapshots: new Map(),\n _timelineDebounceTimer: null,\n\n register(file) {\n const id = this._nextId++;\n const parentId = this._stack.length > 0 ? this._stack[this._stack.length - 1] : null;\n const name = file.split('/').pop()?.replace('.svelte', '') || 'Unknown';\n this._instances.set(id, { id, file, name, parentId, mounted: true, children: [] });\n if (parentId !== null) {\n const parent = this._instances.get(parentId);\n if (parent) parent.children.push(id);\n }\n this._stack.push(id);\n this._scheduleUpdate();\n return id;\n },\n\n registered(id) {\n const idx = this._stack.indexOf(id);\n if (idx !== -1) this._stack.splice(idx, 1);\n },\n\n mount(id) {\n const instance = this._instances.get(id);\n if (instance && !instance.mounted) {\n instance.mounted = true;\n this._scheduleUpdate();\n }\n },\n\n unmount(id) {\n const instance = this._instances.get(id);\n if (instance) {\n if (instance.parentId !== null) {\n const parent = this._instances.get(instance.parentId);\n if (parent) {\n parent.children = parent.children.filter(cid => cid !== id);\n }\n }\n this._removeChildren(id);\n this._cleanupComponent(id);\n }\n this._scheduleUpdate();\n this._scheduleProfileUpdate();\n },\n\n // Remounts get a fresh id, so entries keyed by a dead id would otherwise\n // survive forever — every per-component map must be purged here.\n _cleanupComponent(id) {\n this._cleanupReactiveNodes(id);\n this._instances.delete(id);\n this._profiles.delete(id);\n this._initStartTimes.delete(id);\n },\n\n _cleanupReactiveNodes(componentId) {\n for (const [nodeId, entry] of this._reactiveNodes) {\n if (entry.meta.componentId === componentId) {\n this._reactiveNodes.delete(nodeId);\n this._reactiveProxies.delete(nodeId);\n this._stateSnapshots.delete(nodeId);\n if (this._stateSnapshotStrs) this._stateSnapshotStrs.delete(nodeId);\n }\n }\n },\n\n _removeChildren(parentId) {\n const parent = this._instances.get(parentId);\n if (!parent) return;\n for (const childId of [...parent.children]) {\n this._removeChildren(childId);\n this._cleanupComponent(childId);\n }\n },\n\n _scheduleUpdate() {\n if (this._debounceTimer) clearTimeout(this._debounceTimer);\n this._debounceTimer = setTimeout(() => {\n this._sendUpdate();\n }, 100);\n },\n\n _sendUpdate() {\n const components = [];\n for (const [, instance] of this._instances) {\n if (instance.mounted) {\n components.push({\n id: instance.id,\n file: instance.file,\n name: instance.name,\n parentId: instance.parentId,\n mounted: instance.mounted,\n });\n }\n }\n if (import.meta.hot) {\n import.meta.hot.send('svelte-devtools:components', { components });\n }\n },\n\n getTree() {\n const components = [];\n for (const [, instance] of this._instances) {\n if (instance.mounted) {\n components.push({\n id: instance.id,\n file: instance.file,\n name: instance.name,\n parentId: instance.parentId,\n mounted: instance.mounted,\n });\n }\n }\n return components;\n },\n\n // --- Phase 2: Render Profiling ---\n\n startInit(id) {\n this._initStartTimes.set(id, performance.now());\n },\n\n endInit(id) {\n const start = this._initStartTimes.get(id);\n if (start === undefined) return;\n const initTime = performance.now() - start;\n this._initStartTimes.delete(id);\n const instance = this._instances.get(id);\n if (!instance) return;\n this._profiles.set(id, {\n componentId: id,\n file: instance.file,\n name: instance.name,\n initTime,\n renderCount: 0,\n totalRenderTime: 0,\n lastRenderTime: 0,\n lastRenderAt: Date.now(),\n });\n this._scheduleProfileUpdate();\n },\n\n recordRender(id) {\n const profile = this._profiles.get(id);\n if (!profile) {\n const instance = this._instances.get(id);\n if (!instance) return;\n this._profiles.set(id, {\n componentId: id,\n file: instance.file,\n name: instance.name,\n initTime: 0,\n renderCount: 1,\n totalRenderTime: 0,\n lastRenderTime: 0,\n lastRenderAt: Date.now(),\n });\n } else {\n profile.renderCount++;\n profile.lastRenderAt = Date.now();\n }\n this._scheduleProfileUpdate();\n },\n\n recordRenderTime(id, duration) {\n const profile = this._profiles.get(id);\n if (profile) {\n profile.totalRenderTime += duration;\n profile.lastRenderTime = duration;\n }\n },\n\n _scheduleProfileUpdate() {\n if (this._profileDebounceTimer) clearTimeout(this._profileDebounceTimer);\n this._profileDebounceTimer = setTimeout(() => {\n this._sendProfileUpdate();\n }, 500);\n },\n\n _sendProfileUpdate() {\n const profiles = Array.from(this._profiles.values());\n if (import.meta.hot) {\n import.meta.hot.send('svelte-devtools:profiles', { profiles });\n }\n },\n\n getProfiles() {\n return Array.from(this._profiles.values());\n },\n\n resetProfiles() {\n this._profiles.clear();\n this._scheduleProfileUpdate();\n },\n\n // --- Phase 2: Reactive Graph Tracking ---\n\n trackState(signal, name, componentId) {\n const instance = this._instances.get(componentId);\n const nodeId = componentId + ':' + name;\n this._reactiveNodes.set(nodeId, {\n signal: new WeakRef(signal),\n meta: { id: nodeId, type: 'state', name, componentId, componentFile: instance ? instance.file : '' }\n });\n },\n\n trackProxy(proxy, name, componentId) {\n const instance = this._instances.get(componentId);\n const nodeId = componentId + ':' + name;\n this._reactiveProxies.set(nodeId, new WeakRef(proxy));\n this._reactiveNodes.set(nodeId, {\n signal: new WeakRef({ v: '(proxy)', _isProxy: true }),\n meta: { id: nodeId, type: 'state', name, componentId, componentFile: instance ? instance.file : '' }\n });\n },\n\n trackDerived(signal, name, componentId) {\n const instance = this._instances.get(componentId);\n const nodeId = componentId + ':' + name;\n this._reactiveNodes.set(nodeId, {\n signal: new WeakRef(signal),\n meta: { id: nodeId, type: 'derived', name, componentId, componentFile: instance ? instance.file : '' }\n });\n },\n\n trackEffect(effect, name, componentId) {\n const instance = this._instances.get(componentId);\n const nodeId = componentId + ':' + name;\n this._reactiveNodes.set(nodeId, {\n signal: new WeakRef(effect || { v: undefined, _isEffect: true }),\n meta: { id: nodeId, type: 'effect', name, componentId, componentFile: instance ? instance.file : '' }\n });\n return effect;\n },\n\n getReactiveGraph() {\n const nodes = [];\n const edges = [];\n const signalToId = new Map();\n\n for (const [nodeId, entry] of this._reactiveNodes) {\n const signal = entry.signal.deref();\n if (!signal || !this._instances.has(entry.meta.componentId)) {\n this._reactiveNodes.delete(nodeId);\n continue;\n }\n signalToId.set(signal, nodeId);\n const node = { ...entry.meta };\n if (signal._isProxy) {\n const proxyRef = this._reactiveProxies.get(nodeId);\n const proxy = proxyRef?.deref();\n if (proxy) {\n try {\n node.value = Array.isArray(proxy) ? '[' + proxy.length + ']' : '{' + Object.keys(proxy).length + '}';\n } catch { node.value = '(proxy)'; }\n }\n } else if (node.type !== 'effect' && signal.v !== undefined && typeof signal.v !== 'symbol') {\n try {\n const v = signal.v;\n if (typeof v === 'number' || typeof v === 'string' || typeof v === 'boolean' || v === null) {\n node.value = v;\n } else {\n node.value = '(object)';\n }\n } catch { /* ignore */ }\n }\n nodes.push(node);\n }\n\n // Map proxy internal signals to their proxy node ID\n for (const [nodeId, ref] of this._reactiveProxies) {\n const proxy = ref.deref();\n if (!proxy) { this._reactiveProxies.delete(nodeId); continue; }\n const meta = this._reactiveNodes.get(nodeId)?.meta;\n if (!meta || !this._instances.has(meta.componentId)) { this._reactiveProxies.delete(nodeId); continue; }\n }\n\n // Build edges from deps\n const edgeSet = new Set();\n for (const [nodeId, entry] of this._reactiveNodes) {\n const signal = entry.signal.deref();\n if (!signal) continue;\n if (!signal.deps) continue;\n\n const visited = new Set();\n const queue = [...signal.deps];\n while (queue.length > 0) {\n const dep = queue.shift();\n if (!dep || visited.has(dep)) continue;\n visited.add(dep);\n const depId = signalToId.get(dep);\n if (depId) {\n const key = depId + '>' + nodeId;\n if (depId !== nodeId && !edgeSet.has(key)) {\n edgeSet.add(key);\n edges.push({ from: depId, to: nodeId });\n }\n } else if (dep.deps) {\n for (const d of dep.deps) queue.push(d);\n }\n }\n }\n\n return { nodes, edges };\n },\n\n sendReactiveGraph() {\n const graph = this.getReactiveGraph();\n if (import.meta.hot) {\n import.meta.hot.send('svelte-devtools:reactive-graph', graph);\n }\n },\n\n // --- Phase 3: State Timeline ---\n\n _pollStateValues() {\n for (const [nodeId, entry] of this._reactiveNodes) {\n if (entry.meta.type !== 'state') continue;\n if (!this._instances.has(entry.meta.componentId)) {\n this._reactiveNodes.delete(nodeId);\n continue;\n }\n const signal = entry.signal.deref();\n if (!signal || signal.v === undefined) continue;\n try {\n const currentVal = signal.v;\n const prev = this._stateSnapshots.get(nodeId);\n if (prev !== undefined && currentVal === prev) continue;\n const isPrimitive = currentVal === null || typeof currentVal !== 'object';\n let newSnapshot;\n if (isPrimitive) {\n if (prev !== undefined && prev === currentVal) continue;\n newSnapshot = currentVal;\n } else {\n const currStr = JSON.stringify(currentVal);\n const prevStr = this._stateSnapshotStrs?.get(nodeId);\n if (prevStr === currStr) continue;\n newSnapshot = JSON.parse(currStr);\n if (!this._stateSnapshotStrs) this._stateSnapshotStrs = new Map();\n this._stateSnapshotStrs.set(nodeId, currStr);\n }\n if (this._stateTimeline.length >= 500) this._stateTimeline.splice(0, this._stateTimeline.length - 499);\n this._stateTimeline.push({\n id: nodeId,\n name: entry.meta.name,\n componentFile: entry.meta.componentFile,\n oldValue: prev !== undefined ? prev : null,\n newValue: newSnapshot,\n timestamp: Date.now(),\n });\n this._stateSnapshots.set(nodeId, newSnapshot);\n this._scheduleTimelineUpdate();\n } catch { /* ignore non-serializable */ }\n }\n },\n\n _scheduleTimelineUpdate() {\n if (this._timelineDebounceTimer) clearTimeout(this._timelineDebounceTimer);\n this._timelineDebounceTimer = setTimeout(() => {\n if (import.meta.hot) {\n import.meta.hot.send('svelte-devtools:state-timeline', { changes: this._stateTimeline });\n }\n }, 300);\n },\n\n getStateTimeline() {\n return this._stateTimeline;\n },\n\n clearStateTimeline() {\n this._stateTimeline = [];\n this._scheduleTimelineUpdate();\n },\n\n // --- FPS Monitoring ---\n // Uses requestAnimationFrame to measure frame rate with minimal overhead.\n // Only stores timestamps - no allocations per frame beyond a single array push.\n _fpsFrameTimes: [],\n\n _fpsLoop() {\n this._fpsFrameTimes.push(performance.now());\n requestAnimationFrame(() => this._fpsLoop());\n },\n\n _sampleFps() {\n const now = performance.now();\n // Remove frame timestamps older than 1 second\n const cutoff = now - 1000;\n let i = 0;\n while (i < this._fpsFrameTimes.length && this._fpsFrameTimes[i] < cutoff) i++;\n if (i > 0) this._fpsFrameTimes.splice(0, i);\n const fps = this._fpsFrameTimes.length;\n if (import.meta.hot) {\n import.meta.hot.send('svelte-devtools:fps', { timestamp: Date.now(), fps });\n }\n }\n };\n\n window.__SVELTE_DEVTOOLS__ = __SVELTE_DT;\n\n // Poll state values for timeline\n setInterval(() => { __SVELTE_DT._pollStateValues(); }, 200);\n\n // FPS monitoring\n requestAnimationFrame(() => __SVELTE_DT._fpsLoop());\n setInterval(() => __SVELTE_DT._sampleFps(), 500);\n\n // Phase 3: Capture runtime errors\n window.addEventListener('error', (event) => {\n if (import.meta.hot) {\n import.meta.hot.send('svelte-devtools:runtime-error', {\n message: event.message,\n file: event.filename,\n line: event.lineno,\n column: event.colno,\n stack: event.error?.stack || '',\n timestamp: Date.now(),\n });\n }\n });\n window.addEventListener('unhandledrejection', (event) => {\n if (import.meta.hot) {\n const reason = event.reason;\n import.meta.hot.send('svelte-devtools:runtime-error', {\n message: reason?.message || String(reason),\n stack: reason?.stack || '',\n timestamp: Date.now(),\n });\n }\n });\n\n // Listen for reactive graph requests from server\n if (import.meta.hot) {\n import.meta.hot.on('svelte-devtools:request-reactive-graph', () => {\n __SVELTE_DT.sendReactiveGraph();\n });\n import.meta.hot.on('svelte-devtools:request-state-timeline', () => {\n import.meta.hot.send('svelte-devtools:state-timeline', { changes: __SVELTE_DT._stateTimeline });\n });\n import.meta.hot.on('svelte-devtools:clear-state-timeline', () => {\n __SVELTE_DT.clearStateTimeline();\n });\n }\n}\n", R = 1, z = 5, B = 1, V = 30;
262
+ function H(e) {
263
263
  return {
264
264
  renderProfiles: e.getRenderProfiles().map((e) => ({
265
265
  componentId: e.componentId,
@@ -273,10 +273,10 @@ function U(e) {
273
273
  takenAt: Date.now()
274
274
  };
275
275
  }
276
- function W(e, t, n) {
276
+ function U(e, t, n) {
277
277
  return Math.abs(e) < t ? "unchanged" : n ? e < 0 ? "improved" : "regressed" : e > 0 ? "improved" : "regressed";
278
278
  }
279
- var G = class {
279
+ var te = class {
280
280
  sessions = /* @__PURE__ */ new Map();
281
281
  active = null;
282
282
  persistDir;
@@ -291,7 +291,7 @@ var G = class {
291
291
  label: e,
292
292
  startedAt: Date.now(),
293
293
  persist: t,
294
- startSnapshot: U(this.getters),
294
+ startSnapshot: H(this.getters),
295
295
  loadProfiles: [],
296
296
  fpsSamples: []
297
297
  };
@@ -311,7 +311,7 @@ var G = class {
311
311
  if (!this.active) throw Error("No active session");
312
312
  let t = this.sessions.get(this.active);
313
313
  if (!t) throw Error("Active session missing from store");
314
- return t.endedAt = Date.now(), t.endSnapshot = U(this.getters), this.active = null, e === "discard" ? this.sessions.delete(t.id) : (e === "disk" || t.persist) && this.persistToDisk(t), t;
314
+ return t.endedAt = Date.now(), t.endSnapshot = H(this.getters), this.active = null, e === "discard" ? this.sessions.delete(t.id) : (e === "disk" || t.persist) && this.persistToDisk(t), t;
315
315
  }
316
316
  get(e) {
317
317
  return this.sessions.get(e) || this.loadFromDisk(e);
@@ -367,7 +367,7 @@ var G = class {
367
367
  totalRenderTimeDelta: o,
368
368
  avgRenderTimeDelta: a > 0 ? o / a : 0
369
369
  };
370
- }).filter((e) => e.renderCountDelta > 0).sort((e, t) => t.totalRenderTimeDelta - e.totalRenderTimeDelta), i = t.loadProfiles.map((e) => e.duration), a = K(i), o = ee(i, 95), s = t.fpsSamples.map((e) => e.fps), c = K(s), l = s.length ? Math.min(...s) : 0, u = s.filter((e) => e < H).length;
370
+ }).filter((e) => e.renderCountDelta > 0).sort((e, t) => t.totalRenderTimeDelta - e.totalRenderTimeDelta), i = t.loadProfiles.map((e) => e.duration), a = W(i), o = ne(i, 95), s = t.fpsSamples.map((e) => e.fps), c = W(s), l = s.length ? Math.min(...s) : 0, u = s.filter((e) => e < V).length;
371
371
  return {
372
372
  durationMs: t.endedAt - t.startedAt,
373
373
  components: r,
@@ -399,19 +399,19 @@ var G = class {
399
399
  totalRenderTimeDeltaA: o,
400
400
  totalRenderTimeDeltaB: s,
401
401
  diff: c,
402
- verdict: W(c, z, !0)
402
+ verdict: U(c, R, !0)
403
403
  },
404
404
  load: {
405
405
  avgA: n.loadProfiles.avgDuration,
406
406
  avgB: r.loadProfiles.avgDuration,
407
407
  diff: l,
408
- verdict: W(l, B, !0)
408
+ verdict: U(l, z, !0)
409
409
  },
410
410
  fps: {
411
411
  avgA: n.fps.avg,
412
412
  avgB: r.fps.avg,
413
413
  diff: u,
414
- verdict: W(u, V, !1)
414
+ verdict: U(u, B, !1)
415
415
  }
416
416
  };
417
417
  }
@@ -432,26 +432,26 @@ var G = class {
432
432
  }
433
433
  }
434
434
  };
435
- function K(e) {
435
+ function W(e) {
436
436
  return e.length ? e.reduce((e, t) => e + t, 0) / e.length : 0;
437
437
  }
438
- function ee(e, t) {
438
+ function ne(e, t) {
439
439
  if (!e.length) return 0;
440
440
  let n = [...e].sort((e, t) => e - t);
441
441
  return n[Math.min(n.length - 1, Math.floor(t / 100 * n.length))];
442
442
  }
443
443
  //#endregion
444
444
  //#region src/mcp/issues.ts
445
- var q = {
445
+ var G = {
446
446
  avgRenderTimeMs: 4,
447
447
  renderCount: 30,
448
448
  loadDurationMs: 200,
449
449
  fpsDropThreshold: 40,
450
450
  effectMaxDeps: 8
451
451
  };
452
- function te(e, t = {}) {
452
+ function re(e, t = {}) {
453
453
  let n = {
454
- ...q,
454
+ ...G,
455
455
  ...t
456
456
  }, r = [];
457
457
  for (let t of e.renderProfiles) {
@@ -463,9 +463,9 @@ function te(e, t = {}) {
463
463
  summary: `${t.name} averages ${e.toFixed(2)}ms per render (${t.renderCount} renders)`,
464
464
  file: t.file,
465
465
  metric: {
466
- avgRenderTimeMs: Y(e),
466
+ avgRenderTimeMs: q(e),
467
467
  renderCount: t.renderCount,
468
- totalRenderTimeMs: Y(t.totalRenderTime)
468
+ totalRenderTimeMs: q(t.totalRenderTime)
469
469
  },
470
470
  suggestedTool: "get_render_profile"
471
471
  }), t.renderCount >= n.renderCount && r.push({
@@ -476,7 +476,7 @@ function te(e, t = {}) {
476
476
  file: t.file,
477
477
  metric: {
478
478
  renderCount: t.renderCount,
479
- avgRenderTimeMs: Y(e)
479
+ avgRenderTimeMs: q(e)
480
480
  },
481
481
  suggestedTool: "get_component_hotspots"
482
482
  });
@@ -488,7 +488,7 @@ function te(e, t = {}) {
488
488
  summary: `${t.type} load for ${t.route} took ${t.duration.toFixed(0)}ms`,
489
489
  file: t.file,
490
490
  metric: {
491
- durationMs: Y(t.duration),
491
+ durationMs: q(t.duration),
492
492
  dataSizeBytes: t.dataSize
493
493
  },
494
494
  suggestedTool: "get_load_waterfall"
@@ -539,22 +539,22 @@ function te(e, t = {}) {
539
539
  });
540
540
  }
541
541
  }
542
- return r.sort(ne);
542
+ return r.sort(ie);
543
543
  }
544
- var J = {
544
+ var K = {
545
545
  high: 0,
546
546
  medium: 1,
547
547
  low: 2
548
548
  };
549
- function ne(e, t) {
550
- return J[e.severity] - J[t.severity];
549
+ function ie(e, t) {
550
+ return K[e.severity] - K[t.severity];
551
551
  }
552
- function Y(e) {
552
+ function q(e) {
553
553
  return Math.round(e * 100) / 100;
554
554
  }
555
- function re(e, t = {}) {
555
+ function ae(e, t = {}) {
556
556
  let n = {
557
- ...q,
557
+ ...G,
558
558
  ...t
559
559
  }, r = /* @__PURE__ */ new Map(), i = /* @__PURE__ */ new Map();
560
560
  for (let t of e.edges) r.set(t.to, (r.get(t.to) ?? 0) + 1), i.set(t.from, (i.get(t.from) ?? 0) + 1);
@@ -585,11 +585,11 @@ function re(e, t = {}) {
585
585
  }
586
586
  //#endregion
587
587
  //#region src/mcp/server.ts
588
- var X = (e) => ({ content: [{
588
+ var J = (e) => ({ content: [{
589
589
  type: "text",
590
590
  text: typeof e == "string" ? e : JSON.stringify(e, null, 2)
591
591
  }] });
592
- function ie(e) {
592
+ function oe(e) {
593
593
  let t = new c({
594
594
  name: "vite-devtools-svelte",
595
595
  version: "0.1.0"
@@ -605,13 +605,13 @@ function ie(e) {
605
605
  effectMaxDeps: u.number().optional()
606
606
  }
607
607
  }, async (t) => {
608
- let n = t, r = await e.getReactiveGraph(), i = te({
608
+ let n = t, r = await e.getReactiveGraph(), i = re({
609
609
  renderProfiles: e.getRenderProfiles(),
610
610
  reactiveGraph: r,
611
611
  loadProfiles: e.getLoadProfiles(),
612
612
  fpsSamples: e.getFpsSamples()
613
613
  }, n);
614
- return X({
614
+ return J({
615
615
  count: i.length,
616
616
  issues: i
617
617
  });
@@ -619,20 +619,20 @@ function ie(e) {
619
619
  title: "Component render hotspots",
620
620
  description: "Top components by total render time, with render count and per-render average.",
621
621
  inputSchema: { topN: u.number().int().min(1).max(200).optional() }
622
- }, async ({ topN: t = 20 }) => X([...e.getRenderProfiles()].map((e) => ({
622
+ }, async ({ topN: t = 20 }) => J([...e.getRenderProfiles()].map((e) => ({
623
623
  file: e.file,
624
624
  name: e.name,
625
625
  componentId: e.componentId,
626
626
  renderCount: e.renderCount,
627
- totalRenderTimeMs: Z(e.totalRenderTime),
628
- avgRenderTimeMs: Z(e.renderCount > 0 ? e.totalRenderTime / e.renderCount : 0),
629
- lastRenderTimeMs: Z(e.lastRenderTime),
627
+ totalRenderTimeMs: Y(e.totalRenderTime),
628
+ avgRenderTimeMs: Y(e.renderCount > 0 ? e.totalRenderTime / e.renderCount : 0),
629
+ lastRenderTimeMs: Y(e.lastRenderTime),
630
630
  lastRenderAt: e.lastRenderAt
631
631
  })).sort((e, t) => t.totalRenderTimeMs - e.totalRenderTimeMs).slice(0, t))), t.registerTool("get_reactive_graph_problems", {
632
632
  title: "Reactive graph problems",
633
633
  description: "Classified reactive graph issues: over-connected effects, orphan deriveds, isolated nodes. Returns categories instead of the full graph.",
634
634
  inputSchema: { effectMaxDeps: u.number().int().min(1).optional() }
635
- }, async ({ effectMaxDeps: t }) => X(re(await e.getReactiveGraph(), { effectMaxDeps: t }))), t.registerTool("get_load_waterfall", {
635
+ }, async ({ effectMaxDeps: t }) => J(ae(await e.getReactiveGraph(), { effectMaxDeps: t }))), t.registerTool("get_load_waterfall", {
636
636
  title: "SvelteKit load waterfall",
637
637
  description: "Load profiles grouped by route, with timing and data size. Optionally filtered by route.",
638
638
  inputSchema: { route: u.string().optional() }
@@ -644,14 +644,14 @@ function ie(e) {
644
644
  let t = r.get(e.route) ?? [];
645
645
  t.push(e), r.set(e.route, t);
646
646
  }
647
- return X([...r.entries()].map(([e, t]) => {
647
+ return J([...r.entries()].map(([e, t]) => {
648
648
  let n = t.map((e) => e.duration);
649
649
  return {
650
650
  route: e,
651
651
  file: t[0]?.file,
652
652
  count: t.length,
653
- avgDuration: Z(ae(n)),
654
- maxDuration: Z(Math.max(...n)),
653
+ avgDuration: Y(se(n)),
654
+ maxDuration: Y(Math.max(...n)),
655
655
  totalDataBytes: t.reduce((e, t) => e + t.dataSize, 0),
656
656
  samples: t
657
657
  };
@@ -670,7 +670,7 @@ function ie(e) {
670
670
  r = r.filter((t) => t.timestamp >= e);
671
671
  }
672
672
  let i = r.filter((e) => e.fps < t);
673
- return X({
673
+ return J({
674
674
  threshold: t,
675
675
  sampleCount: r.length,
676
676
  dropCount: i.length,
@@ -681,27 +681,27 @@ function ie(e) {
681
681
  title: "Render profile for a specific file",
682
682
  description: "Returns render profile entries matching the given component file (substring match).",
683
683
  inputSchema: { file: u.string() }
684
- }, async ({ file: t }) => X(e.getRenderProfiles().filter((e) => e.file.includes(t)).map((e) => ({
684
+ }, async ({ file: t }) => J(e.getRenderProfiles().filter((e) => e.file.includes(t)).map((e) => ({
685
685
  ...e,
686
- totalRenderTimeMs: Z(e.totalRenderTime),
687
- avgRenderTimeMs: Z(e.renderCount > 0 ? e.totalRenderTime / e.renderCount : 0)
686
+ totalRenderTimeMs: Y(e.totalRenderTime),
687
+ avgRenderTimeMs: Y(e.renderCount > 0 ? e.totalRenderTime / e.renderCount : 0)
688
688
  })))), t.registerTool("get_project_info", {
689
689
  title: "Project info",
690
690
  description: "Package name/version, Svelte / SvelteKit / Vite versions, dependency lists.",
691
691
  inputSchema: {}
692
- }, async () => X(e.getProject())), t.registerTool("get_routes", {
692
+ }, async () => J(e.getProject())), t.registerTool("get_routes", {
693
693
  title: "SvelteKit routes",
694
694
  description: "Static analysis of the SvelteKit routes tree.",
695
695
  inputSchema: {}
696
- }, async () => X(e.getRoutes())), t.registerTool("get_live_components", {
696
+ }, async () => J(e.getRoutes())), t.registerTool("get_live_components", {
697
697
  title: "Currently mounted components",
698
698
  description: "Component instances with file, parent, mounted status as currently mounted in the browser.",
699
699
  inputSchema: {}
700
- }, async () => X(e.getLiveComponents())), t.registerTool("get_component_relations", {
700
+ }, async () => J(e.getLiveComponents())), t.registerTool("get_component_relations", {
701
701
  title: "Component import graph",
702
702
  description: "Static import relations between .svelte components.",
703
703
  inputSchema: {}
704
- }, async () => X(e.getComponentRelations())), t.registerTool("start_session", {
704
+ }, async () => J(e.getComponentRelations())), t.registerTool("start_session", {
705
705
  title: "Start measurement session",
706
706
  description: "Begin capturing metrics under a labelled session. Required before compare_sessions. Set `persist:true` to write to disk on end; otherwise the session lives in memory only.",
707
707
  inputSchema: {
@@ -710,7 +710,7 @@ function ie(e) {
710
710
  }
711
711
  }, async ({ label: t, persist: n = !1 }) => {
712
712
  let r = e.sessions.start(t, n);
713
- return X({
713
+ return J({
714
714
  id: r.id,
715
715
  label: r.label,
716
716
  startedAt: r.startedAt,
@@ -726,7 +726,7 @@ function ie(e) {
726
726
  ]).optional() }
727
727
  }, async ({ keep: t = "memory" }) => {
728
728
  let n = e.sessions.end(t), r = n.endedAt ? e.sessions.delta(n.id) : null;
729
- return X({
729
+ return J({
730
730
  id: n.id,
731
731
  label: n.label,
732
732
  startedAt: n.startedAt,
@@ -741,19 +741,19 @@ function ie(e) {
741
741
  a: u.string(),
742
742
  b: u.string()
743
743
  }
744
- }, async ({ a: t, b: n }) => X(e.sessions.compare(t, n))), t.registerTool("list_sessions", {
744
+ }, async ({ a: t, b: n }) => J(e.sessions.compare(t, n))), t.registerTool("list_sessions", {
745
745
  title: "List sessions",
746
746
  description: "In-memory + on-disk sessions, most recent first.",
747
747
  inputSchema: {}
748
- }, async () => X(e.sessions.list())), t.registerTool("load_session", {
748
+ }, async () => J(e.sessions.list())), t.registerTool("load_session", {
749
749
  title: "Load a session by id",
750
750
  description: "Returns the full session record (including delta if ended) by id.",
751
751
  inputSchema: { id: u.string() }
752
752
  }, async ({ id: t }) => {
753
753
  let n = e.sessions.get(t);
754
- if (!n) return X({ error: `Session not found: ${t}` });
754
+ if (!n) return J({ error: `Session not found: ${t}` });
755
755
  let r = n.endedAt ? e.sessions.delta(t) : null;
756
- return X({
756
+ return J({
757
757
  ...n,
758
758
  delta: r
759
759
  });
@@ -761,14 +761,35 @@ function ie(e) {
761
761
  title: "Delete a session",
762
762
  description: "Removes a session from memory and disk.",
763
763
  inputSchema: { id: u.string() }
764
- }, async ({ id: t }) => X({ deleted: e.sessions.delete(t) })), t;
764
+ }, async ({ id: t }) => J({ deleted: e.sessions.delete(t) })), t;
765
765
  }
766
- function ae(e) {
766
+ function se(e) {
767
767
  return e.length ? e.reduce((e, t) => e + t, 0) / e.length : 0;
768
768
  }
769
- function Z(e) {
769
+ function Y(e) {
770
770
  return Math.round(e * 100) / 100;
771
771
  }
772
+ var ce = "templates: {", X = "/@id/@vitejs/devtools/client/inject", le = `<script type=\\"module\\" src=\\"${X}\\"><\/script>`, Z = "</body>";
773
+ function ue(e) {
774
+ if (!e.includes("templates: {") || !e.includes(Z) || e.includes(X)) return null;
775
+ let t = e.indexOf(ce), n = e.indexOf(Z, t);
776
+ return n === -1 ? null : e.slice(0, n) + le + e.slice(n);
777
+ }
778
+ function de() {
779
+ return {
780
+ name: "vite-devtools-svelte:sveltekit-template-injector",
781
+ enforce: "post",
782
+ apply: (e, t) => t.command === "serve" && !t.isSsrBuild,
783
+ transform(e, t) {
784
+ if (!t.endsWith(".svelte-kit/generated/server/internal.js")) return;
785
+ let n = ue(e);
786
+ if (n !== null) return {
787
+ code: n,
788
+ map: null
789
+ };
790
+ }
791
+ };
792
+ }
772
793
  //#endregion
773
794
  //#region src/plugin.ts
774
795
  var Q = e.dirname(i(import.meta.url));
@@ -783,17 +804,17 @@ function $(e) {
783
804
  let r = t.hostname;
784
805
  if (r === "::1" || r === "[::1]") throw Error("Blocked: loopback address");
785
806
  if (n.isIP(r)) {
786
- if (oe(r)) throw Error(`Blocked: private IP address ${r}`);
807
+ if (fe(r)) throw Error(`Blocked: private IP address ${r}`);
787
808
  } else {
788
809
  let e = r.toLowerCase();
789
810
  if (e === "localhost" || e.endsWith(".local") || e.endsWith(".internal")) throw Error(`Blocked: internal hostname ${r}`);
790
811
  }
791
812
  }
792
- function oe(e) {
813
+ function fe(e) {
793
814
  let t = e.split(".").map(Number);
794
815
  return !!(t.length === 4 && (t[0] === 127 || t[0] === 10 || t[0] === 172 && t[1] >= 16 && t[1] <= 31 || t[0] === 192 && t[1] === 168 || t[0] === 169 && t[1] === 254 || t.every((e) => e === 0)));
795
816
  }
796
- function se(n = {}) {
817
+ function pe(n = {}) {
797
818
  let { componentTracking: i = !0 } = n, o, s, c, u = r.randomUUID();
798
819
  function f(n) {
799
820
  if (typeof n != "string" || n.length === 0) throw Error("Invalid file path");
@@ -811,7 +832,7 @@ function se(n = {}) {
811
832
  edges: []
812
833
  }, y = [], b = [], x = [], S = [], w = [], T = [], E = null;
813
834
  function D() {
814
- return E ||= new G({
835
+ return E ||= new te({
815
836
  persistDir: e.join(c, "node_modules", ".vite-devtools-svelte", "sessions"),
816
837
  getters: {
817
838
  getRenderProfiles: () => m,
@@ -985,7 +1006,7 @@ function se(n = {}) {
985
1006
  },
986
1007
  "svelte-devtools:get-module-graph": async () => M(),
987
1008
  "svelte-devtools:get-og-preview": async (e) => N(String(e)),
988
- "svelte-devtools:get-build-analysis": async () => z(),
1009
+ "svelte-devtools:get-build-analysis": async () => R(),
989
1010
  "svelte-devtools:get-fps": async () => T,
990
1011
  "svelte-devtools:clear-fps": async () => {
991
1012
  T = [];
@@ -1119,7 +1140,7 @@ function se(n = {}) {
1119
1140
  r.statusCode = 404, r.end("Not found");
1120
1141
  }
1121
1142
  });
1122
- let S = () => ie({
1143
+ let S = () => oe({
1123
1144
  getProject: () => C(c),
1124
1145
  getRoutes: () => d(C(c).routesDir),
1125
1146
  getLiveComponents: () => p,
@@ -1161,14 +1182,14 @@ function se(n = {}) {
1161
1182
  },
1162
1183
  resolveId(e, t) {
1163
1184
  if (o?.command === "serve") {
1164
- if (e === "virtual:svelte-devtools-runtime") return F;
1165
- if (i && e === "svelte/internal/client" && t && !t.includes("node_modules") && !t.startsWith("\0")) return I;
1185
+ if (e === "virtual:svelte-devtools-runtime") return ee;
1186
+ if (i && e === "svelte/internal/client" && t && !t.includes("node_modules") && !t.startsWith("\0")) return F;
1166
1187
  }
1167
1188
  },
1168
1189
  load(e) {
1169
1190
  if (o?.command === "serve") {
1170
- if (e === "\0virtual:svelte-devtools-runtime") return R;
1171
- if (e === "\0svelte-devtools:wrapped-client") return L;
1191
+ if (e === "\0virtual:svelte-devtools-runtime") return L;
1192
+ if (e === "\0svelte-devtools:wrapped-client") return I;
1172
1193
  }
1173
1194
  },
1174
1195
  transformIndexHtml() {
@@ -1298,7 +1319,7 @@ function se(n = {}) {
1298
1319
  }
1299
1320
  return t;
1300
1321
  }
1301
- function z() {
1322
+ function R() {
1302
1323
  let n = e.resolve(c, ".svelte-kit/output"), r = e.resolve(c, "build/client"), i = [];
1303
1324
  for (let a of [
1304
1325
  n,
@@ -1413,10 +1434,11 @@ export const load = async (event) => {
1413
1434
  t(e, n);
1414
1435
  };
1415
1436
  }
1416
- }
1437
+ },
1438
+ de()
1417
1439
  ];
1418
1440
  }
1419
1441
  //#endregion
1420
- export { se as svelteDevtools };
1442
+ export { pe as svelteDevtools };
1421
1443
 
1422
1444
  //# sourceMappingURL=index.mjs.map