Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .changeset/shared-protocol-types.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
'@qwik.dev/devtools': patch
---

refactor(devtools): single source of truth for shared protocol types

The VNode tree node, component detail entry, and render event shapes were declared
three times: in the browser extension, in the devtools UI, and in the kit client
bridge. They now live once in @qwik.dev/devtools/kit (protocol module) as
DevtoolsVNodeTreeNode, DevtoolsComponentDetailEntry, and DevtoolsRenderEvent, and
every consumer imports them from there.
28 changes: 7 additions & 21 deletions packages/browser-extension/src/shared/types.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
import type {
DevtoolsVNodeTreeNode as VNodeTreeNode,
DevtoolsComponentDetailEntry as ComponentDetailEntry,
DevtoolsRenderEvent as RenderEvent,
QwikDevtoolsComponentSnapshot,
QwikDevtoolsSignalsSnapshot,
QwikPerfStoreRemembered,
QwikPreloadStoreRemembered,
} from '@qwik.dev/devtools/kit';

// The VNode/detail/render shapes are the shared data contract, owned by @qwik.dev/devtools/kit.
// Re-export under the local names so consumers keep one import source and cannot drift.
export type { VNodeTreeNode, ComponentDetailEntry, RenderEvent };

export interface QwikContainerInfo {
detected: boolean;
version: string | null;
Expand All @@ -16,27 +23,6 @@ export interface QwikContainerInfo {
runtime: string | null;
}

export interface VNodeTreeNode {
name?: string;
id: string;
label?: string;
props?: Record<string, unknown>;
children?: VNodeTreeNode[];
}

export interface ComponentDetailEntry {
hookType: string;
variableName: string;
data: unknown;
}

export interface RenderEvent {
component: string;
phase: string;
duration: number;
timestamp: number;
}

export type ExtensionMessage =
| { type: 'DETECT_QWIK' }
| { type: 'QWIK_DETECTION_RESULT'; payload: QwikContainerInfo }
Expand Down
24 changes: 3 additions & 21 deletions packages/devtools/kit/src/client-bridge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,32 +7,14 @@ import type { QwikPerfStoreRemembered, QwikPreloadStoreRemembered } from './glob
import { getQwikDevtoolsGlobal } from './global-store';
import { QWIK_DEVTOOLS_GLOBAL } from './protocol/globals';
import { DEVTOOLS_MESSAGES, type QwikDevtoolsPageMessage } from './protocol/messages';
import type { DevtoolsVNodeTreeNode } from './protocol/vnode';
import type { DevtoolsRenderEvent } from './protocol/perf';
import type { DevtoolsComponentDetailEntry } from './protocol/hooks';

export interface InPageBridgeOptions {
isBrowser: boolean;
}

export interface DevtoolsRenderEvent {
component: string;
phase: string;
duration: number;
timestamp: number;
}

export interface DevtoolsComponentDetailEntry {
hookType: string;
variableName: string;
data: unknown;
}

export interface DevtoolsVNodeTreeNode {
name?: string;
id: string;
label?: string;
props?: Record<string, unknown>;
children?: DevtoolsVNodeTreeNode[];
}

export interface InPageBridge {
readPerfData(): Promise<QwikPerfStoreRemembered | null>;
readPreloadStore(): Promise<QwikPreloadStoreRemembered | null>;
Expand Down
11 changes: 11 additions & 0 deletions packages/devtools/kit/src/protocol/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,17 @@ export const SIGNAL_HOOK_TYPES = [
'useContext',
] as const;

/**
* A single component hook entry with deeply serialized data, returned by the devtools hook's
* component detail lookup. Shared data contract: do not redeclare in consumers, import it from
* here.
*/
export interface DevtoolsComponentDetailEntry {
hookType: string;
variableName: string;
data: unknown;
}

export const INNER_USE_HOOK = 'useCollectHooks';
export const VIRTUAL_QWIK_DEVTOOLS_KEY = 'virtual-qwik-devtools.ts';
export const QWIK_DEVTOOLS_HOOK_VERSION = 1;
11 changes: 11 additions & 0 deletions packages/devtools/kit/src/protocol/perf.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,14 @@ export const PERF_PHASE_CSR = 'csr';
export const DEFAULT_PERF_STORE_EXPRESSION = '{ ssr: [], csr: [] }';

export type QwikDevtoolsPerfPhase = typeof PERF_PHASE_SSR | typeof PERF_PHASE_CSR;

/**
* A single render event emitted by the performance runtime (CSR render with timing). Shared data
* contract: do not redeclare in consumers, import it from here.
*/
export interface DevtoolsRenderEvent {
component: string;
phase: string;
duration: number;
timestamp: number;
}
12 changes: 12 additions & 0 deletions packages/devtools/kit/src/protocol/vnode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,15 @@ export const QWIK_VNODE_PROTOCOL = {
},
bridgeVirtualModuleId: 'virtual:qwik-devtools-bridge',
} as const;

/**
* Serializable VNode tree node exchanged between the page hook and the devtools UI/extension.
* Shared data contract: do not redeclare in consumers, import it from here.
*/
export interface DevtoolsVNodeTreeNode {
name?: string;
id: string;
label?: string;
props?: Record<string, unknown>;
children?: DevtoolsVNodeTreeNode[];
}
31 changes: 7 additions & 24 deletions packages/devtools/ui/src/devtools/page-data-source.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,16 @@ import {
type QwikPreloadStoreRemembered,
type QwikDevtoolsComponentSnapshot,
type QwikDevtoolsSignalsSnapshot,
type DevtoolsVNodeTreeNode as VNodeTreeNode,
type DevtoolsComponentDetailEntry as ComponentDetailEntry,
type DevtoolsRenderEvent as RenderEvent,
} from '@qwik.dev/devtools/kit';
import { isBrowser } from '@qwik.dev/core';

// The VNode/detail/render shapes are the shared data contract, owned by @qwik.dev/devtools/kit.
// Re-export under the local names so feature components keep one import source and cannot drift.
export type { VNodeTreeNode, ComponentDetailEntry, RenderEvent };

/**
* Abstraction for accessing page-level data from different contexts.
*
Expand Down Expand Up @@ -78,30 +85,6 @@ export interface PageDataSource {
subscribeRenderEvents(cb: (event: RenderEvent) => void): (() => void) | null;
}

/** A single render event emitted by the performance runtime. */
export interface RenderEvent {
component: string;
phase: string;
duration: number;
timestamp: number;
}

/** A single hook entry with deeply serialized data. */
export interface ComponentDetailEntry {
hookType: string;
variableName: string;
data: unknown;
}

/** Serializable VNode tree node (matches overlay's TreeNode shape). */
export interface VNodeTreeNode {
name?: string;
id: string;
label?: string;
props?: Record<string, unknown>;
children?: VNodeTreeNode[];
}

/**
* Default implementation that reads directly from `window` globals. Used when the devtools UI runs
* as an in-app overlay (same document).
Expand Down
Loading