what-devtools 0.5.5 → 0.6.2
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/README.md +1 -1
- package/dist/index.js +348 -0
- package/dist/index.js.map +7 -0
- package/dist/index.min.js +2 -0
- package/dist/index.min.js.map +7 -0
- package/dist/panel.js +476 -0
- package/dist/panel.js.map +7 -0
- package/dist/panel.min.js +2 -0
- package/dist/panel.min.js.map +7 -0
- package/index.d.ts +22 -0
- package/package.json +21 -9
- package/panel.d.ts +2 -0
- package/src/DevPanel.jsx +138 -124
- package/src/index.js +72 -9
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/DevPanel.jsx", "../src/index.js"],
|
|
4
|
+
"sourcesContent": ["/**\n * What Framework DevPanel\n *\n * A small floating UI panel for browser-based devtools tests and local debugging.\n * It is intentionally implemented without JSX so the devtools package does not\n * depend on compiler fragment behavior to render its own diagnostics UI.\n */\n\nimport { onCleanup } from 'what-core';\nimport { subscribe, getSnapshot, getErrors, installDevTools } from './index.js';\n\nconst MONO = 'ui-monospace,SFMono-Regular,Menlo,monospace';\n\nexport function DevPanel() {\n installDevTools();\n\n if (typeof document === 'undefined') return null;\n\n let activeTab = 'signals';\n let isOpen = false;\n\n const root = document.createDocumentFragment();\n const toggle = document.createElement('button');\n toggle.type = 'button';\n toggle.textContent = 'W';\n toggle.title = 'What Framework DevTools (Ctrl+Shift+D)';\n toggle.setAttribute('style',\n 'position:fixed;bottom:12px;right:12px;z-index:99999;width:36px;height:36px;' +\n 'border-radius:8px;border:1px solid #2a2a4a;background:linear-gradient(135deg,#2563eb,#1d4ed8);' +\n `color:#fff;font-weight:800;font-size:14px;cursor:pointer;font-family:${MONO};` +\n 'box-shadow:0 4px 12px rgba(37,99,235,0.3);'\n );\n\n const panel = document.createElement('div');\n panel.setAttribute('style',\n 'position:fixed;bottom:0;right:0;width:380px;max-height:55vh;z-index:99998;' +\n `font-family:${MONO};font-size:12px;background:#1a1a2e;color:#e0e0e0;` +\n 'border:1px solid #2a2a4a;border-radius:12px 0 0 0;box-shadow:0 -4px 24px rgba(0,0,0,0.3);' +\n 'display:none;flex-direction:column;overflow:hidden;'\n );\n\n root.append(toggle, panel);\n\n function setOpen(next) {\n isOpen = next;\n panel.style.display = isOpen ? 'flex' : 'none';\n if (isOpen) renderPanel();\n }\n\n toggle.addEventListener('click', () => setOpen(!isOpen));\n\n const onKeyDown = (e) => {\n if ((e.ctrlKey || e.metaKey) && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n setOpen(!isOpen);\n }\n };\n document.addEventListener('keydown', onKeyDown);\n\n const unsub = subscribe(() => {\n if (isOpen) renderPanel();\n });\n const interval = setInterval(() => {\n if (isOpen) renderPanel();\n }, 500);\n\n onCleanup(() => {\n unsub();\n clearInterval(interval);\n document.removeEventListener('keydown', onKeyDown);\n });\n\n function renderPanel() {\n panel.replaceChildren(renderHeader(), renderTabs(), renderContent());\n }\n\n function renderHeader() {\n const header = document.createElement('div');\n header.setAttribute('style', 'display:flex;align-items:center;justify-content:space-between;padding:8px 12px;border-bottom:1px solid #2a2a4a;background:#16163a;');\n\n const title = document.createElement('span');\n title.textContent = 'What DevTools';\n title.setAttribute('style', 'font-weight:700;font-size:12px;color:#818cf8;');\n\n const close = document.createElement('button');\n close.type = 'button';\n close.textContent = 'x';\n close.setAttribute('style', 'background:none;border:none;color:#6a6a8a;cursor:pointer;font-size:14px;');\n close.addEventListener('click', () => setOpen(false));\n\n header.append(title, close);\n return header;\n }\n\n function renderTabs() {\n const tabs = document.createElement('div');\n tabs.setAttribute('style', 'display:flex;gap:2px;padding:6px 8px;border-bottom:1px solid #2a2a4a;flex-wrap:wrap;');\n for (const tab of ['signals', 'effects', 'components', 'errors']) {\n const button = document.createElement('button');\n button.type = 'button';\n button.textContent = tabLabel(tab);\n button.setAttribute('style', tabStyle(tab));\n button.addEventListener('click', () => {\n activeTab = tab;\n renderPanel();\n });\n tabs.append(button);\n }\n return tabs;\n }\n\n function tabLabel(tab) {\n const snapshot = getSnapshot();\n if (tab === 'signals') return `Signals (${snapshot.signals.length})`;\n if (tab === 'effects') return `Effects (${snapshot.effects.length})`;\n if (tab === 'components') return `Components (${snapshot.components.length})`;\n return `Errors (${getErrors().length})`;\n }\n\n function tabStyle(tab) {\n const selected = activeTab === tab;\n return 'padding:6px 10px;border:none;background:' + (selected ? '#2a2a4a' : 'transparent') +\n ';color:' + (selected ? '#fff' : '#6a6a8a') +\n `;cursor:pointer;font-family:${MONO};font-size:11px;font-weight:600;border-radius:4px;`;\n }\n\n function renderContent() {\n const content = document.createElement('div');\n content.setAttribute('style', 'overflow-y:auto;flex:1;padding:8px;');\n const snapshot = getSnapshot();\n\n if (activeTab === 'signals') {\n renderRows(content, snapshot.signals, (signal) => [signal.name, formatValue(signal.value)], '#818cf8');\n } else if (activeTab === 'effects') {\n renderRows(content, snapshot.effects, (effect) => [effect.name, `runs: ${effect.runCount || 0}`], '#fbbf24');\n } else if (activeTab === 'components') {\n renderRows(content, snapshot.components, (component) => [`<${component.name} />`, ''], '#34d399');\n } else {\n renderRows(content, getErrors(), (error) => [`[${error.type}]`, error.message], '#f87171');\n }\n\n if (!content.childNodes.length) {\n content.textContent = `No ${activeTab} tracked`;\n content.style.color = '#4a4a6a';\n content.style.padding = '12px';\n }\n return content;\n }\n\n function renderRows(parent, rows, mapRow, color) {\n for (const row of rows) {\n const [leftText, rightText] = mapRow(row);\n const item = document.createElement('div');\n item.setAttribute('style', 'display:flex;justify-content:space-between;align-items:center;padding:4px 8px;border-bottom:1px solid #2a2a4a;gap:12px;');\n const left = document.createElement('span');\n left.textContent = leftText;\n left.setAttribute('style', `color:${color};`);\n const right = document.createElement('span');\n right.textContent = rightText;\n right.setAttribute('style', 'color:#a0a0c0;max-width:180px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;');\n item.append(left, right);\n parent.append(item);\n }\n }\n\n return root;\n}\n\nfunction formatValue(value) {\n if (value === null) return 'null';\n if (value === undefined) return 'undefined';\n if (typeof value === 'string') return `\"${value.length > 30 ? value.slice(0, 30) + '...' : value}\"`;\n if (typeof value === 'object') {\n try {\n const str = JSON.stringify(value);\n return str.length > 40 ? str.slice(0, 40) + '...' : str;\n } catch {\n return '[Object]';\n }\n }\n return String(value);\n}\n\nexport default DevPanel;\n", "/**\n * What Framework DevTools\n *\n * Runtime instrumentation for debugging signals, effects, and components.\n * In dev mode, exposes a `window.__WHAT_DEVTOOLS__` global for inspection.\n *\n * Usage:\n * import { installDevTools } from 'what-devtools';\n * installDevTools(); // Call once at app entry\n *\n * Then inspect in console:\n * __WHAT_DEVTOOLS__.signals // Map of all live signals\n * __WHAT_DEVTOOLS__.components // Map of mounted components\n * __WHAT_DEVTOOLS__.effects // Map of active effects\n */\n\nlet installed = false;\nlet signalId = 0;\nlet effectId = 0;\nlet componentId = 0;\n\n// Registries\nconst signals = new Map(); // id \u2192 { name, ref, createdAt, internal }\nconst effects = new Map(); // id \u2192 { name, createdAt, depSignalIds, runCount, lastRunAt }\nconst components = new Map(); // id \u2192 { name, element, mountedAt, parentId }\n\n// Reverse lookup: subscriber Set \u2192 signal ID (O(1) dep resolution)\nconst subsToSignalId = new WeakMap();\n\n// Error log (capped at 100)\nconst errors = [];\nconst MAX_ERRORS = 100;\n\n// Hydration mismatch log (capped at 50)\nconst hydrationMismatches = [];\nconst MAX_HYDRATION_MISMATCHES = 50;\n\n// Event listeners for the DevPanel\nconst listeners = new Set();\n\nfunction emit(event, data) {\n for (const fn of listeners) {\n try { fn(event, data); } catch {}\n }\n}\n\n/**\n * Safely serialize a value for transport (WS, JSON).\n * Handles DOM nodes, functions, circular refs, Maps, Sets, large collections.\n */\nexport function safeSerialize(value, depth = 0, seen) {\n if (depth > 6) return '[max depth]';\n if (value === null || value === undefined) return value;\n\n const type = typeof value;\n if (type === 'string' || type === 'number' || type === 'boolean') return value;\n if (type === 'function') return `[Function: ${value.name || 'anonymous'}]`;\n if (type === 'symbol') return `[Symbol: ${value.description || ''}]`;\n if (type === 'bigint') return value.toString() + 'n';\n\n // DOM nodes\n if (typeof Node !== 'undefined' && value instanceof Node) {\n const tag = value.nodeName?.toLowerCase() || 'node';\n const id = value.id ? `#${value.id}` : '';\n const cls = value.className ? `.${String(value.className).split(' ')[0]}` : '';\n return `[DOM: <${tag}${id}${cls}>]`;\n }\n\n if (!seen) seen = new Set();\n if (seen.has(value)) return '[Circular]';\n seen.add(value);\n\n // Map\n if (value instanceof Map) {\n if (value.size > 50) return `[Map: ${value.size} entries]`;\n const obj = {};\n for (const [k, v] of value) {\n obj[String(k)] = safeSerialize(v, depth + 1, seen);\n }\n return { __type: 'Map', entries: obj };\n }\n\n // Set\n if (value instanceof Set) {\n if (value.size > 50) return `[Set: ${value.size} items]`;\n return { __type: 'Set', values: [...value].map(v => safeSerialize(v, depth + 1, seen)) };\n }\n\n // Array\n if (Array.isArray(value)) {\n if (value.length > 100) {\n return [...value.slice(0, 100).map(v => safeSerialize(v, depth + 1, seen)), `... (${value.length} total)`];\n }\n return value.map(v => safeSerialize(v, depth + 1, seen));\n }\n\n // Error\n if (value instanceof Error) {\n return { __type: 'Error', name: value.name, message: value.message, stack: value.stack };\n }\n\n // Date\n if (value instanceof Date) return { __type: 'Date', iso: value.toISOString() };\n\n // RegExp\n if (value instanceof RegExp) return value.toString();\n\n // Plain object\n if (type === 'object') {\n const keys = Object.keys(value);\n if (keys.length > 100) {\n const obj = {};\n for (const k of keys.slice(0, 100)) {\n obj[k] = safeSerialize(value[k], depth + 1, seen);\n }\n obj['...'] = `(${keys.length} total keys)`;\n return obj;\n }\n const obj = {};\n for (const k of keys) {\n obj[k] = safeSerialize(value[k], depth + 1, seen);\n }\n return obj;\n }\n\n return String(value);\n}\n\n/**\n * Register a signal with the devtools.\n * Called from reactive.js __DEV__ hooks.\n */\nexport function registerSignal(sig, name) {\n if (!installed) return;\n const id = ++signalId;\n const entry = {\n id,\n name: sig._debugName || name || `signal_${id}`,\n ref: sig,\n createdAt: Date.now(),\n internal: false,\n };\n signals.set(id, entry);\n sig._devId = id;\n // Reverse lookup for O(1) effect dep resolution\n if (sig._subs) subsToSignalId.set(sig._subs, id);\n emit('signal:created', entry);\n return id;\n}\n\n/**\n * Notify devtools that a signal value changed.\n */\nexport function notifySignalUpdate(sig) {\n if (!installed) return;\n const id = sig._devId;\n if (id == null) return;\n const entry = signals.get(id);\n if (entry) {\n emit('signal:updated', { id, name: entry.name, value: sig.peek() });\n }\n}\n\n/**\n * Unregister a signal (when disposed via createRoot cleanup).\n */\nexport function unregisterSignal(sig) {\n if (!installed) return;\n const id = sig._devId;\n if (id == null) return;\n signals.delete(id);\n emit('signal:disposed', { id });\n}\n\n/**\n * Register an effect with the devtools.\n */\nexport function registerEffect(e, name) {\n if (!installed) return;\n const id = ++effectId;\n const entry = {\n id,\n name: name || e.fn?.name || `effect_${id}`,\n createdAt: Date.now(),\n depSignalIds: [],\n runCount: 0,\n lastRunAt: null,\n };\n effects.set(id, entry);\n e._devId = id;\n emit('effect:created', entry);\n return id;\n}\n\n/**\n * Track effect dependencies and run count after an effect runs.\n */\nfunction trackEffectRun(e) {\n const id = e._devId;\n if (id == null) return;\n const entry = effects.get(id);\n if (!entry) return;\n\n // Resolve deps via WeakMap reverse lookup \u2014 O(m) where m = number of deps\n const depSignalIds = [];\n if (e.deps) {\n for (const subSet of e.deps) {\n const sigId = subsToSignalId.get(subSet);\n if (sigId != null) depSignalIds.push(sigId);\n }\n }\n\n entry.depSignalIds = depSignalIds;\n entry.runCount = (entry.runCount || 0) + 1;\n entry.lastRunAt = Date.now();\n emit('effect:run', { id, depSignalIds: entry.depSignalIds, runCount: entry.runCount });\n}\n\n/**\n * Unregister an effect.\n */\nexport function unregisterEffect(e) {\n if (!installed) return;\n const id = e._devId;\n if (id == null) return;\n effects.delete(id);\n emit('effect:disposed', { id });\n}\n\n/**\n * Capture a runtime error.\n */\nexport function captureError(err, typeOrContext, context) {\n const resolvedContext = typeof typeOrContext === 'string'\n ? { ...(context || {}), type: typeOrContext }\n : (typeOrContext || context || {});\n const entry = {\n message: err?.message || String(err),\n stack: err?.stack || null,\n type: resolvedContext?.type || 'unknown',\n effectId: resolvedContext?.effect?._devId || null,\n timestamp: Date.now(),\n };\n errors.push(entry);\n if (errors.length > MAX_ERRORS) errors.shift();\n emit('error:captured', entry);\n}\n\n/**\n * Register a component mount.\n */\nexport function registerComponent(name, element, parentDevId) {\n if (!installed) return;\n const id = ++componentId;\n const entry = {\n id,\n name: name || 'Anonymous',\n element,\n parentId: parentDevId || null,\n mountedAt: Date.now(),\n };\n components.set(id, entry);\n emit('component:mounted', entry);\n return id;\n}\n\n/**\n * Unregister a component (unmount).\n */\nexport function unregisterComponent(id) {\n if (!installed) return;\n components.delete(id);\n emit('component:unmounted', { id });\n}\n\n/**\n * Subscribe to devtools events.\n * Returns an unsubscribe function.\n */\nexport function subscribe(fn) {\n listeners.add(fn);\n return () => listeners.delete(fn);\n}\n\n/**\n * Get a snapshot of all tracked state.\n * @param {object} [opts] - Options\n * @param {boolean} [opts.includeInternal=false] - Include framework-internal signals\n */\nexport function getSnapshot(opts = {}) {\n const { includeInternal = false } = opts;\n\n const signalList = [];\n for (const [id, entry] of signals) {\n if (!includeInternal && entry.internal) continue;\n signalList.push({\n id,\n name: entry.name,\n value: entry.ref.peek(),\n });\n }\n\n const effectList = [];\n for (const [id, entry] of effects) {\n effectList.push({\n id,\n name: entry.name,\n depSignalIds: entry.depSignalIds || [],\n runCount: entry.runCount || 0,\n lastRunAt: entry.lastRunAt || null,\n });\n }\n\n const componentList = [];\n for (const [id, entry] of components) {\n componentList.push({ id, name: entry.name, parentId: entry.parentId });\n }\n\n return {\n signals: signalList,\n effects: effectList,\n components: componentList,\n errors: errors.slice(),\n hydrationMismatches: hydrationMismatches.slice(),\n };\n}\n\n/**\n * Get captured errors.\n * @param {object} [opts]\n * @param {number} [opts.since] - Only errors after this timestamp\n */\nexport function getErrors(opts = {}) {\n const { since } = opts;\n if (since) return errors.filter(e => e.timestamp > since);\n return errors.slice();\n}\n\n/**\n * Get captured hydration mismatches.\n * @param {object} [opts]\n * @param {number} [opts.since] - Only mismatches after this timestamp\n */\nexport function getHydrationMismatches(opts = {}) {\n const { since } = opts;\n if (since) return hydrationMismatches.filter(m => m.timestamp > since);\n return hydrationMismatches.slice();\n}\n\n/**\n * Reset devtools registries and captured logs.\n */\nexport function resetDevTools() {\n signals.clear();\n effects.clear();\n components.clear();\n errors.length = 0;\n hydrationMismatches.length = 0;\n listeners.clear();\n signalId = 0;\n effectId = 0;\n componentId = 0;\n}\n\n/**\n * Install devtools. Call once at app startup.\n * Wires into what-core's __DEV__ hooks and exposes `window.__WHAT_DEVTOOLS__`.\n *\n * @param {object} [core] - Optional what-core module. If not provided, attempts dynamic import.\n */\nexport function installDevTools(core) {\n if (installed) return;\n installed = true;\n\n const hooks = {\n onSignalCreate: (sig) => registerSignal(sig),\n onSignalUpdate: (sig) => notifySignalUpdate(sig),\n onSignalDispose: (sig) => unregisterSignal(sig),\n onEffectCreate: (e) => registerEffect(e),\n onEffectDispose: (e) => unregisterEffect(e),\n onEffectRun: (e) => trackEffectRun(e),\n onError: (err, context) => captureError(err, context),\n onHydrationMismatch: (info) => {\n const entry = {\n type: 'hydration_mismatch',\n component: info.component,\n expected: info.expected,\n actual: info.actual,\n mismatchCount: info.mismatchCount,\n timestamp: Date.now(),\n };\n hydrationMismatches.push(entry);\n if (hydrationMismatches.length > MAX_HYDRATION_MISMATCHES) hydrationMismatches.shift();\n emit('hydration:mismatch', entry);\n },\n onComponentMount: (ctx) => {\n const name = ctx.Component?.displayName || ctx.Component?.name || 'Anonymous';\n const parentDevId = ctx._parentCtx?._devId || null;\n const id = registerComponent(name, ctx._wrapper, parentDevId);\n ctx._devId = id;\n },\n onComponentUnmount: (ctx) => {\n if (ctx._devId != null) unregisterComponent(ctx._devId);\n },\n };\n\n // Wire into what-core's reactive system\n if (core && core.__setDevToolsHooks) {\n core.__setDevToolsHooks(hooks);\n if (typeof window !== 'undefined') window.__WHAT_CORE__ = core;\n } else {\n try {\n import('what-core/devtools').then(mod => {\n if (mod.__setDevToolsHooks) mod.__setDevToolsHooks(hooks);\n if (typeof window !== 'undefined') window.__WHAT_CORE_DEVTOOLS__ = mod;\n }).catch((error) => warnDevToolsImportFailure(error));\n } catch (error) {\n warnDevToolsImportFailure(error);\n }\n }\n\n if (typeof window !== 'undefined') {\n window.__WHAT_DEVTOOLS__ = {\n get signals() { return getSnapshot().signals; },\n get effects() { return getSnapshot().effects; },\n get components() { return getSnapshot().components; },\n get errors() { return getErrors(); },\n get hydrationMismatches() { return getHydrationMismatches(); },\n getSnapshot,\n getErrors,\n getHydrationMismatches,\n subscribe,\n safeSerialize,\n captureError,\n resetDevTools,\n _registries: { signals, effects, components, errors, hydrationMismatches },\n };\n }\n}\n\nexport { signals, effects, components, errors, hydrationMismatches };\n\nfunction warnDevToolsImportFailure(error) {\n const isDev = typeof process === 'undefined' || process.env?.NODE_ENV !== 'production';\n if (!isDev || typeof console === 'undefined') return;\n console.warn(\n '[what-devtools] Could not import what-core/devtools. Pass installDevTools({ __setDevToolsHooks }) or verify package subpath exports.',\n error\n );\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["onCleanup", "installed", "signalId", "effectId", "componentId", "signals", "effects", "components", "subsToSignalId", "errors", "MAX_ERRORS", "hydrationMismatches", "MAX_HYDRATION_MISMATCHES", "listeners", "emit", "event", "data", "fn", "safeSerialize", "value", "depth", "seen", "type", "tag", "id", "cls", "obj", "k", "v", "keys", "registerSignal", "sig", "name", "entry", "notifySignalUpdate", "unregisterSignal", "registerEffect", "e", "trackEffectRun", "depSignalIds", "subSet", "sigId", "unregisterEffect", "captureError", "err", "typeOrContext", "context", "resolvedContext", "registerComponent", "element", "parentDevId", "unregisterComponent", "subscribe", "getSnapshot", "opts", "includeInternal", "signalList", "effectList", "componentList", "getErrors", "since", "getHydrationMismatches", "m", "resetDevTools", "installDevTools", "core", "hooks", "info", "ctx", "mod", "error", "warnDevToolsImportFailure", "warnDevToolsImportFailure", "error", "MONO", "DevPanel", "installDevTools", "activeTab", "isOpen", "root", "toggle", "panel", "setOpen", "next", "renderPanel", "onKeyDown", "e", "unsub", "subscribe", "interval", "onCleanup", "renderHeader", "renderTabs", "renderContent", "header", "title", "close", "tabs", "tab", "button", "tabLabel", "tabStyle", "snapshot", "getSnapshot", "getErrors", "selected", "content", "renderRows", "signal", "formatValue", "effect", "component", "error", "parent", "rows", "mapRow", "color", "row", "leftText", "rightText", "item", "left", "right", "value", "str", "DevPanel_default"]
|
|
7
|
+
}
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export interface DevToolsSnapshot {
|
|
2
|
+
signals: Array<Record<string, unknown>>;
|
|
3
|
+
effects: Array<Record<string, unknown>>;
|
|
4
|
+
components: Array<Record<string, unknown>>;
|
|
5
|
+
errors: Array<Record<string, unknown>>;
|
|
6
|
+
hydrationMismatches: Array<Record<string, unknown>>;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function installDevTools(core?: Record<string, unknown>): void;
|
|
10
|
+
export function safeSerialize(value: unknown, depth?: number, seen?: Set<unknown>): unknown;
|
|
11
|
+
export function registerSignal(sig: unknown, name?: string): number | undefined;
|
|
12
|
+
export function notifySignalUpdate(sig: unknown): void;
|
|
13
|
+
export function unregisterSignal(sig: unknown): void;
|
|
14
|
+
export function registerEffect(effect: unknown, name?: string): number | undefined;
|
|
15
|
+
export function registerComponent(component: unknown, element?: unknown, parentId?: number): number | undefined;
|
|
16
|
+
export function unregisterComponent(idOrComponent: unknown): void;
|
|
17
|
+
export function captureError(error: unknown, type?: string, context?: Record<string, unknown>): void;
|
|
18
|
+
export function getSnapshot(): DevToolsSnapshot;
|
|
19
|
+
export function getErrors(): Array<Record<string, unknown>>;
|
|
20
|
+
export function getHydrationMismatches(): Array<Record<string, unknown>>;
|
|
21
|
+
export function subscribe(listener: (event: string, data: unknown) => void): () => void;
|
|
22
|
+
export function resetDevTools(): void;
|
package/package.json
CHANGED
|
@@ -1,15 +1,26 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "what-devtools",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Dev tools for What Framework
|
|
3
|
+
"version": "0.6.2",
|
|
4
|
+
"description": "Dev tools for What Framework \u2014 signal inspector, component tree, effect graph",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.js",
|
|
7
7
|
"exports": {
|
|
8
|
-
".":
|
|
9
|
-
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./index.d.ts",
|
|
10
|
+
"production": "./dist/index.min.js",
|
|
11
|
+
"import": "./src/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./panel": {
|
|
14
|
+
"types": "./panel.d.ts",
|
|
15
|
+
"production": "./dist/panel.min.js",
|
|
16
|
+
"import": "./dist/panel.js"
|
|
17
|
+
}
|
|
10
18
|
},
|
|
11
19
|
"files": [
|
|
12
|
-
"src"
|
|
20
|
+
"src",
|
|
21
|
+
"dist",
|
|
22
|
+
"index.d.ts",
|
|
23
|
+
"panel.d.ts"
|
|
13
24
|
],
|
|
14
25
|
"keywords": [
|
|
15
26
|
"what",
|
|
@@ -20,16 +31,17 @@
|
|
|
20
31
|
"inspector"
|
|
21
32
|
],
|
|
22
33
|
"peerDependencies": {
|
|
23
|
-
"what-core": "^0.
|
|
34
|
+
"what-core": "^0.6.2"
|
|
24
35
|
},
|
|
25
36
|
"author": "ZVN DEV (https://zvndev.com)",
|
|
26
37
|
"license": "MIT",
|
|
27
38
|
"repository": {
|
|
28
39
|
"type": "git",
|
|
29
|
-
"url": "https://github.com/CelsianJs/
|
|
40
|
+
"url": "https://github.com/CelsianJs/what-framework"
|
|
30
41
|
},
|
|
31
42
|
"bugs": {
|
|
32
|
-
"url": "https://github.com/CelsianJs/
|
|
43
|
+
"url": "https://github.com/CelsianJs/what-framework/issues"
|
|
33
44
|
},
|
|
34
|
-
"homepage": "https://whatfw.com"
|
|
45
|
+
"homepage": "https://whatfw.com",
|
|
46
|
+
"types": "index.d.ts"
|
|
35
47
|
}
|
package/panel.d.ts
ADDED
package/src/DevPanel.jsx
CHANGED
|
@@ -1,155 +1,169 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* What Framework DevPanel
|
|
3
3
|
*
|
|
4
|
-
* A
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* Usage:
|
|
8
|
-
* import { DevPanel } from 'what-devtools/panel';
|
|
9
|
-
* // Add to your app:
|
|
10
|
-
* <DevPanel />
|
|
11
|
-
*
|
|
12
|
-
* The panel is draggable and can be collapsed. It auto-updates
|
|
13
|
-
* when signals change.
|
|
4
|
+
* A small floating UI panel for browser-based devtools tests and local debugging.
|
|
5
|
+
* It is intentionally implemented without JSX so the devtools package does not
|
|
6
|
+
* depend on compiler fragment behavior to render its own diagnostics UI.
|
|
14
7
|
*/
|
|
15
8
|
|
|
16
|
-
import {
|
|
17
|
-
import { subscribe, getSnapshot, installDevTools } from './index.js';
|
|
9
|
+
import { onCleanup } from 'what-core';
|
|
10
|
+
import { subscribe, getSnapshot, getErrors, installDevTools } from './index.js';
|
|
11
|
+
|
|
12
|
+
const MONO = 'ui-monospace,SFMono-Regular,Menlo,monospace';
|
|
18
13
|
|
|
19
14
|
export function DevPanel() {
|
|
20
|
-
// Auto-install devtools if not already done
|
|
21
15
|
installDevTools();
|
|
22
16
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
17
|
+
if (typeof document === 'undefined') return null;
|
|
18
|
+
|
|
19
|
+
let activeTab = 'signals';
|
|
20
|
+
let isOpen = false;
|
|
21
|
+
|
|
22
|
+
const root = document.createDocumentFragment();
|
|
23
|
+
const toggle = document.createElement('button');
|
|
24
|
+
toggle.type = 'button';
|
|
25
|
+
toggle.textContent = 'W';
|
|
26
|
+
toggle.title = 'What Framework DevTools (Ctrl+Shift+D)';
|
|
27
|
+
toggle.setAttribute('style',
|
|
28
|
+
'position:fixed;bottom:12px;right:12px;z-index:99999;width:36px;height:36px;' +
|
|
29
|
+
'border-radius:8px;border:1px solid #2a2a4a;background:linear-gradient(135deg,#2563eb,#1d4ed8);' +
|
|
30
|
+
`color:#fff;font-weight:800;font-size:14px;cursor:pointer;font-family:${MONO};` +
|
|
31
|
+
'box-shadow:0 4px 12px rgba(37,99,235,0.3);'
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
const panel = document.createElement('div');
|
|
35
|
+
panel.setAttribute('style',
|
|
36
|
+
'position:fixed;bottom:0;right:0;width:380px;max-height:55vh;z-index:99998;' +
|
|
37
|
+
`font-family:${MONO};font-size:12px;background:#1a1a2e;color:#e0e0e0;` +
|
|
38
|
+
'border:1px solid #2a2a4a;border-radius:12px 0 0 0;box-shadow:0 -4px 24px rgba(0,0,0,0.3);' +
|
|
39
|
+
'display:none;flex-direction:column;overflow:hidden;'
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
root.append(toggle, panel);
|
|
43
|
+
|
|
44
|
+
function setOpen(next) {
|
|
45
|
+
isOpen = next;
|
|
46
|
+
panel.style.display = isOpen ? 'flex' : 'none';
|
|
47
|
+
if (isOpen) renderPanel();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
toggle.addEventListener('click', () => setOpen(!isOpen));
|
|
51
|
+
|
|
52
|
+
const onKeyDown = (e) => {
|
|
53
|
+
if ((e.ctrlKey || e.metaKey) && e.shiftKey && e.key === 'D') {
|
|
54
|
+
e.preventDefault();
|
|
55
|
+
setOpen(!isOpen);
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
document.addEventListener('keydown', onKeyDown);
|
|
26
59
|
|
|
27
|
-
// Subscribe to devtools events and refresh
|
|
28
60
|
const unsub = subscribe(() => {
|
|
29
|
-
|
|
61
|
+
if (isOpen) renderPanel();
|
|
30
62
|
});
|
|
31
|
-
|
|
32
|
-
// Also poll every 500ms for signal value changes (cheap — just reads .peek())
|
|
33
63
|
const interval = setInterval(() => {
|
|
34
|
-
|
|
64
|
+
if (isOpen) renderPanel();
|
|
35
65
|
}, 500);
|
|
36
66
|
|
|
37
67
|
onCleanup(() => {
|
|
38
68
|
unsub();
|
|
39
69
|
clearInterval(interval);
|
|
70
|
+
document.removeEventListener('keydown', onKeyDown);
|
|
40
71
|
});
|
|
41
72
|
|
|
42
|
-
|
|
73
|
+
function renderPanel() {
|
|
74
|
+
panel.replaceChildren(renderHeader(), renderTabs(), renderContent());
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function renderHeader() {
|
|
78
|
+
const header = document.createElement('div');
|
|
79
|
+
header.setAttribute('style', 'display:flex;align-items:center;justify-content:space-between;padding:8px 12px;border-bottom:1px solid #2a2a4a;background:#16163a;');
|
|
43
80
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
};
|
|
81
|
+
const title = document.createElement('span');
|
|
82
|
+
title.textContent = 'What DevTools';
|
|
83
|
+
title.setAttribute('style', 'font-weight:700;font-size:12px;color:#818cf8;');
|
|
48
84
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
85
|
+
const close = document.createElement('button');
|
|
86
|
+
close.type = 'button';
|
|
87
|
+
close.textContent = 'x';
|
|
88
|
+
close.setAttribute('style', 'background:none;border:none;color:#6a6a8a;cursor:pointer;font-size:14px;');
|
|
89
|
+
close.addEventListener('click', () => setOpen(false));
|
|
90
|
+
|
|
91
|
+
header.append(title, close);
|
|
92
|
+
return header;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function renderTabs() {
|
|
96
|
+
const tabs = document.createElement('div');
|
|
97
|
+
tabs.setAttribute('style', 'display:flex;gap:2px;padding:6px 8px;border-bottom:1px solid #2a2a4a;flex-wrap:wrap;');
|
|
98
|
+
for (const tab of ['signals', 'effects', 'components', 'errors']) {
|
|
99
|
+
const button = document.createElement('button');
|
|
100
|
+
button.type = 'button';
|
|
101
|
+
button.textContent = tabLabel(tab);
|
|
102
|
+
button.setAttribute('style', tabStyle(tab));
|
|
103
|
+
button.addEventListener('click', () => {
|
|
104
|
+
activeTab = tab;
|
|
105
|
+
renderPanel();
|
|
106
|
+
});
|
|
107
|
+
tabs.append(button);
|
|
53
108
|
}
|
|
54
|
-
return
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
109
|
+
return tabs;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function tabLabel(tab) {
|
|
113
|
+
const snapshot = getSnapshot();
|
|
114
|
+
if (tab === 'signals') return `Signals (${snapshot.signals.length})`;
|
|
115
|
+
if (tab === 'effects') return `Effects (${snapshot.effects.length})`;
|
|
116
|
+
if (tab === 'components') return `Components (${snapshot.components.length})`;
|
|
117
|
+
return `Errors (${getErrors().length})`;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function tabStyle(tab) {
|
|
121
|
+
const selected = activeTab === tab;
|
|
122
|
+
return 'padding:6px 10px;border:none;background:' + (selected ? '#2a2a4a' : 'transparent') +
|
|
123
|
+
';color:' + (selected ? '#fff' : '#6a6a8a') +
|
|
124
|
+
`;cursor:pointer;font-family:${MONO};font-size:11px;font-weight:600;border-radius:4px;`;
|
|
125
|
+
}
|
|
67
126
|
|
|
68
|
-
|
|
69
|
-
const
|
|
70
|
-
|
|
71
|
-
|
|
127
|
+
function renderContent() {
|
|
128
|
+
const content = document.createElement('div');
|
|
129
|
+
content.setAttribute('style', 'overflow-y:auto;flex:1;padding:8px;');
|
|
130
|
+
const snapshot = getSnapshot();
|
|
131
|
+
|
|
132
|
+
if (activeTab === 'signals') {
|
|
133
|
+
renderRows(content, snapshot.signals, (signal) => [signal.name, formatValue(signal.value)], '#818cf8');
|
|
134
|
+
} else if (activeTab === 'effects') {
|
|
135
|
+
renderRows(content, snapshot.effects, (effect) => [effect.name, `runs: ${effect.runCount || 0}`], '#fbbf24');
|
|
136
|
+
} else if (activeTab === 'components') {
|
|
137
|
+
renderRows(content, snapshot.components, (component) => [`<${component.name} />`, ''], '#34d399');
|
|
138
|
+
} else {
|
|
139
|
+
renderRows(content, getErrors(), (error) => [`[${error.type}]`, error.message], '#f87171');
|
|
72
140
|
}
|
|
73
|
-
return (
|
|
74
|
-
<div style="padding:8px;">
|
|
75
|
-
{data.effects.map(e => (
|
|
76
|
-
<div key={e.id} style="padding:4px 8px;border-bottom:1px solid #2a2a4a;">
|
|
77
|
-
<span style="color:#fbbf24;">{e.name}</span>
|
|
78
|
-
</div>
|
|
79
|
-
))}
|
|
80
|
-
</div>
|
|
81
|
-
);
|
|
82
|
-
};
|
|
83
141
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
142
|
+
if (!content.childNodes.length) {
|
|
143
|
+
content.textContent = `No ${activeTab} tracked`;
|
|
144
|
+
content.style.color = '#4a4a6a';
|
|
145
|
+
content.style.padding = '12px';
|
|
88
146
|
}
|
|
89
|
-
return
|
|
90
|
-
|
|
91
|
-
{data.components.map(c => (
|
|
92
|
-
<div key={c.id} style="padding:4px 8px;border-bottom:1px solid #2a2a4a;">
|
|
93
|
-
<span style="color:#34d399;"><{c.name} /></span>
|
|
94
|
-
</div>
|
|
95
|
-
))}
|
|
96
|
-
</div>
|
|
97
|
-
);
|
|
98
|
-
};
|
|
147
|
+
return content;
|
|
148
|
+
}
|
|
99
149
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
<span style="font-weight:700;font-size:12px;color:#818cf8;">What DevTools</span>
|
|
118
|
-
</div>
|
|
119
|
-
<button
|
|
120
|
-
onclick={() => isOpen(false)}
|
|
121
|
-
style="background:none;border:none;color:#6a6a8a;cursor:pointer;font-size:14px;"
|
|
122
|
-
>
|
|
123
|
-
x
|
|
124
|
-
</button>
|
|
125
|
-
</div>
|
|
126
|
-
|
|
127
|
-
{/* Tabs */}
|
|
128
|
-
<div style="display:flex;gap:4px;padding:6px 8px;border-bottom:1px solid #2a2a4a;">
|
|
129
|
-
<button style={tabStyle('signals')} onclick={() => activeTab('signals')}>
|
|
130
|
-
Signals ({() => snapshot().signals.length})
|
|
131
|
-
</button>
|
|
132
|
-
<button style={tabStyle('effects')} onclick={() => activeTab('effects')}>
|
|
133
|
-
Effects ({() => snapshot().effects.length})
|
|
134
|
-
</button>
|
|
135
|
-
<button style={tabStyle('components')} onclick={() => activeTab('components')}>
|
|
136
|
-
Components ({() => snapshot().components.length})
|
|
137
|
-
</button>
|
|
138
|
-
</div>
|
|
139
|
-
|
|
140
|
-
{/* Content */}
|
|
141
|
-
<div style="overflow-y:auto;flex:1;">
|
|
142
|
-
{() => {
|
|
143
|
-
const tab = activeTab();
|
|
144
|
-
if (tab === 'signals') return renderSignals();
|
|
145
|
-
if (tab === 'effects') return renderEffects();
|
|
146
|
-
return renderComponents();
|
|
147
|
-
}}
|
|
148
|
-
</div>
|
|
149
|
-
</div>
|
|
150
|
-
) : null}
|
|
151
|
-
</>
|
|
152
|
-
);
|
|
150
|
+
function renderRows(parent, rows, mapRow, color) {
|
|
151
|
+
for (const row of rows) {
|
|
152
|
+
const [leftText, rightText] = mapRow(row);
|
|
153
|
+
const item = document.createElement('div');
|
|
154
|
+
item.setAttribute('style', 'display:flex;justify-content:space-between;align-items:center;padding:4px 8px;border-bottom:1px solid #2a2a4a;gap:12px;');
|
|
155
|
+
const left = document.createElement('span');
|
|
156
|
+
left.textContent = leftText;
|
|
157
|
+
left.setAttribute('style', `color:${color};`);
|
|
158
|
+
const right = document.createElement('span');
|
|
159
|
+
right.textContent = rightText;
|
|
160
|
+
right.setAttribute('style', 'color:#a0a0c0;max-width:180px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;');
|
|
161
|
+
item.append(left, right);
|
|
162
|
+
parent.append(item);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
return root;
|
|
153
167
|
}
|
|
154
168
|
|
|
155
169
|
function formatValue(value) {
|
package/src/index.js
CHANGED
|
@@ -31,6 +31,10 @@ const subsToSignalId = new WeakMap();
|
|
|
31
31
|
const errors = [];
|
|
32
32
|
const MAX_ERRORS = 100;
|
|
33
33
|
|
|
34
|
+
// Hydration mismatch log (capped at 50)
|
|
35
|
+
const hydrationMismatches = [];
|
|
36
|
+
const MAX_HYDRATION_MISMATCHES = 50;
|
|
37
|
+
|
|
34
38
|
// Event listeners for the DevPanel
|
|
35
39
|
const listeners = new Set();
|
|
36
40
|
|
|
@@ -226,12 +230,15 @@ export function unregisterEffect(e) {
|
|
|
226
230
|
/**
|
|
227
231
|
* Capture a runtime error.
|
|
228
232
|
*/
|
|
229
|
-
function captureError(err, context) {
|
|
233
|
+
export function captureError(err, typeOrContext, context) {
|
|
234
|
+
const resolvedContext = typeof typeOrContext === 'string'
|
|
235
|
+
? { ...(context || {}), type: typeOrContext }
|
|
236
|
+
: (typeOrContext || context || {});
|
|
230
237
|
const entry = {
|
|
231
238
|
message: err?.message || String(err),
|
|
232
239
|
stack: err?.stack || null,
|
|
233
|
-
type:
|
|
234
|
-
effectId:
|
|
240
|
+
type: resolvedContext?.type || 'unknown',
|
|
241
|
+
effectId: resolvedContext?.effect?._devId || null,
|
|
235
242
|
timestamp: Date.now(),
|
|
236
243
|
};
|
|
237
244
|
errors.push(entry);
|
|
@@ -314,6 +321,7 @@ export function getSnapshot(opts = {}) {
|
|
|
314
321
|
effects: effectList,
|
|
315
322
|
components: componentList,
|
|
316
323
|
errors: errors.slice(),
|
|
324
|
+
hydrationMismatches: hydrationMismatches.slice(),
|
|
317
325
|
};
|
|
318
326
|
}
|
|
319
327
|
|
|
@@ -328,6 +336,32 @@ export function getErrors(opts = {}) {
|
|
|
328
336
|
return errors.slice();
|
|
329
337
|
}
|
|
330
338
|
|
|
339
|
+
/**
|
|
340
|
+
* Get captured hydration mismatches.
|
|
341
|
+
* @param {object} [opts]
|
|
342
|
+
* @param {number} [opts.since] - Only mismatches after this timestamp
|
|
343
|
+
*/
|
|
344
|
+
export function getHydrationMismatches(opts = {}) {
|
|
345
|
+
const { since } = opts;
|
|
346
|
+
if (since) return hydrationMismatches.filter(m => m.timestamp > since);
|
|
347
|
+
return hydrationMismatches.slice();
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* Reset devtools registries and captured logs.
|
|
352
|
+
*/
|
|
353
|
+
export function resetDevTools() {
|
|
354
|
+
signals.clear();
|
|
355
|
+
effects.clear();
|
|
356
|
+
components.clear();
|
|
357
|
+
errors.length = 0;
|
|
358
|
+
hydrationMismatches.length = 0;
|
|
359
|
+
listeners.clear();
|
|
360
|
+
signalId = 0;
|
|
361
|
+
effectId = 0;
|
|
362
|
+
componentId = 0;
|
|
363
|
+
}
|
|
364
|
+
|
|
331
365
|
/**
|
|
332
366
|
* Install devtools. Call once at app startup.
|
|
333
367
|
* Wires into what-core's __DEV__ hooks and exposes `window.__WHAT_DEVTOOLS__`.
|
|
@@ -341,10 +375,24 @@ export function installDevTools(core) {
|
|
|
341
375
|
const hooks = {
|
|
342
376
|
onSignalCreate: (sig) => registerSignal(sig),
|
|
343
377
|
onSignalUpdate: (sig) => notifySignalUpdate(sig),
|
|
378
|
+
onSignalDispose: (sig) => unregisterSignal(sig),
|
|
344
379
|
onEffectCreate: (e) => registerEffect(e),
|
|
345
380
|
onEffectDispose: (e) => unregisterEffect(e),
|
|
346
381
|
onEffectRun: (e) => trackEffectRun(e),
|
|
347
382
|
onError: (err, context) => captureError(err, context),
|
|
383
|
+
onHydrationMismatch: (info) => {
|
|
384
|
+
const entry = {
|
|
385
|
+
type: 'hydration_mismatch',
|
|
386
|
+
component: info.component,
|
|
387
|
+
expected: info.expected,
|
|
388
|
+
actual: info.actual,
|
|
389
|
+
mismatchCount: info.mismatchCount,
|
|
390
|
+
timestamp: Date.now(),
|
|
391
|
+
};
|
|
392
|
+
hydrationMismatches.push(entry);
|
|
393
|
+
if (hydrationMismatches.length > MAX_HYDRATION_MISMATCHES) hydrationMismatches.shift();
|
|
394
|
+
emit('hydration:mismatch', entry);
|
|
395
|
+
},
|
|
348
396
|
onComponentMount: (ctx) => {
|
|
349
397
|
const name = ctx.Component?.displayName || ctx.Component?.name || 'Anonymous';
|
|
350
398
|
const parentDevId = ctx._parentCtx?._devId || null;
|
|
@@ -362,11 +410,13 @@ export function installDevTools(core) {
|
|
|
362
410
|
if (typeof window !== 'undefined') window.__WHAT_CORE__ = core;
|
|
363
411
|
} else {
|
|
364
412
|
try {
|
|
365
|
-
import('what-core').then(mod => {
|
|
413
|
+
import('what-core/devtools').then(mod => {
|
|
366
414
|
if (mod.__setDevToolsHooks) mod.__setDevToolsHooks(hooks);
|
|
367
|
-
if (typeof window !== 'undefined') window.
|
|
368
|
-
}).catch(() =>
|
|
369
|
-
} catch {
|
|
415
|
+
if (typeof window !== 'undefined') window.__WHAT_CORE_DEVTOOLS__ = mod;
|
|
416
|
+
}).catch((error) => warnDevToolsImportFailure(error));
|
|
417
|
+
} catch (error) {
|
|
418
|
+
warnDevToolsImportFailure(error);
|
|
419
|
+
}
|
|
370
420
|
}
|
|
371
421
|
|
|
372
422
|
if (typeof window !== 'undefined') {
|
|
@@ -375,13 +425,26 @@ export function installDevTools(core) {
|
|
|
375
425
|
get effects() { return getSnapshot().effects; },
|
|
376
426
|
get components() { return getSnapshot().components; },
|
|
377
427
|
get errors() { return getErrors(); },
|
|
428
|
+
get hydrationMismatches() { return getHydrationMismatches(); },
|
|
378
429
|
getSnapshot,
|
|
379
430
|
getErrors,
|
|
431
|
+
getHydrationMismatches,
|
|
380
432
|
subscribe,
|
|
381
433
|
safeSerialize,
|
|
382
|
-
|
|
434
|
+
captureError,
|
|
435
|
+
resetDevTools,
|
|
436
|
+
_registries: { signals, effects, components, errors, hydrationMismatches },
|
|
383
437
|
};
|
|
384
438
|
}
|
|
385
439
|
}
|
|
386
440
|
|
|
387
|
-
export { signals, effects, components, errors };
|
|
441
|
+
export { signals, effects, components, errors, hydrationMismatches };
|
|
442
|
+
|
|
443
|
+
function warnDevToolsImportFailure(error) {
|
|
444
|
+
const isDev = typeof process === 'undefined' || process.env?.NODE_ENV !== 'production';
|
|
445
|
+
if (!isDev || typeof console === 'undefined') return;
|
|
446
|
+
console.warn(
|
|
447
|
+
'[what-devtools] Could not import what-core/devtools. Pass installDevTools({ __setDevToolsHooks }) or verify package subpath exports.',
|
|
448
|
+
error
|
|
449
|
+
);
|
|
450
|
+
}
|