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
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ and this project adheres to Semantic Versioning.
- **`@bquery/bquery/i18n`** — ICU MessageFormat support ([#141](https://github.com/bQuery/bQuery/issues/141)). Messages using typed arguments (`{count, plural, …}`, `{n, selectordinal, …}`, `{gender, select, …}`) are routed through a locale-aware formatter backed by `Intl.PluralRules`, with `offset:`, exact `=N` selectors, nested arguments, the `#` token, and apostrophe escaping. New authoring helpers `defineMessages()` (identity + extraction anchor) and `formatMessage()` (standalone single-message formatter). Plain `{name}` interpolation and the legacy `singular | plural` pipe form are unchanged.
- **`@bquery/bquery/i18n/extract`** — optional, dependency-free message-extraction tooling ([#141](https://github.com/bQuery/bQuery/issues/141)). `extractFromSource()`, `mergeCatalog()`, `extractFiles()`, `expandGlobs()`, `flatten()` / `unflatten()`, and the CLI (`runExtractCli`, `bquery-i18n extract`) scan source for `defineMessages` catalogs and `t()` / `tc()` calls, then emit/merge nested JSON catalogs without overwriting existing translations (`--prune` opt-in). A separate entry point — importing it is never required at runtime, preserving the zero-build path.
- **`@bquery/bquery/a11y`** — the runtime audit now stamps each `AuditFinding` with its WCAG 2.1 criterion (`wcag`), and the full rule catalog is exported as `auditRules` ([#142](https://github.com/bQuery/bQuery/issues/142)) — each rule documents its WCAG mapping, default severity, and a known limitation (what it cannot detect).
- **`@bquery/bquery/plugin`** — new `definePlugin()` authoring helper ([#145](https://github.com/bQuery/bQuery/issues/145)): an identity helper that infers a plugin's install-options type and gives third-party authors a single, stable entry point.
- **`@bquery/bquery/devtools`** — new stable, versioned bridge protocol for the DevTools browser extension ([#146](https://github.com/bQuery/bQuery/issues/146)): `connectDevtoolsBridge()` (over `window.postMessage`), the transport-agnostic `createBridgeServer()`, `serializeComponentTree()`, and `BRIDGE_PROTOCOL_VERSION` / `BRIDGE_SOURCE` / `BRIDGE_CAPABILITIES`. A reference Manifest V3 extension (component tree, signal/store inspection, live timeline) ships in `extension/`.

### Changed (Unreleased)

Expand All @@ -106,6 +108,10 @@ and this project adheres to Semantic Versioning.
- **`@bquery/bquery/a11y`** — `a11y` is now **targeting Stable in 1.15.0** ([#142](https://github.com/bQuery/bQuery/issues/142)). The surface (focus management, live regions, `inert`/`scrollLock`, preference signals) is frozen for one minor cycle, and the audit's WCAG coverage is documented with its known limitations. See the [A11y guide](https://bquery.js.org/guide/a11y).
- **`@bquery/bquery/dnd`** — `dnd` is now **targeting Stable in 1.15.0** ([#143](https://github.com/bQuery/bQuery/issues/143)). The surface is frozen for one minor cycle; the keyboard model (pick up / move / drop / cancel, `aria-grabbed`) is hardened and tested across `grid` / `delay` / `viewport`; and an accessibility statement is published. Drag announcements route through the shared `a11y` live-region announcer. See the [DnD guide](https://bquery.js.org/guide/dnd).
- **`@bquery/bquery/media`** — `media` is now **targeting Stable in 1.15.0** ([#144](https://github.com/bQuery/bQuery/issues/144)). The 1.14 composable surface is frozen for one minor cycle; each composable's SSR-safe default and cleanup is documented; and reactivity, idempotent `destroy()`, listener detachment, and `AbortSignal` teardown are verified. Bake-and-verify — no new features. See the [Media guide](https://bquery.js.org/guide/media).
- **`@bquery/bquery/plugin`** — `plugin` is now **targeting Stable in 1.15.0** ([#145](https://github.com/bQuery/bQuery/issues/145)). The hook-bus / DI / install-lifecycle / directive-registration surface is frozen for one minor cycle; install/uninstall symmetry (no leaked directives/filters/actions/DI bindings) is proven with tests; and a plugin-author guide (lifecycle, hook timing, DI resolution, directive namespacing) is published. See the [Plugin guide](https://bquery.js.org/guide/plugin).
- **`@bquery/bquery/devtools`** — `devtools` is now **targeting Stable in 1.15.0** ([#146](https://github.com/bQuery/bQuery/issues/146)). The surface is frozen for one minor cycle; the bridge protocol is stabilized as the app↔extension contract; and a reference browser extension ships. See the [DevTools guide](https://bquery.js.org/guide/devtools).
- **`@bquery/bquery/testing`** — `testing` is now **targeting Stable in 1.15.0** ([#147](https://github.com/bQuery/bQuery/issues/147)). The Testing-Library-parity surface is frozen for one minor cycle; runner integration beyond `bun:test` (Vitest / Jest) is documented; and the shadow-DOM-aware queries, `userEvent` / `fireEvent`, and mocks are tested across light + shadow DOM. See the [Testing guide](https://bquery.js.org/guide/testing).
- **`@bquery/bquery/storybook`** — `storybook` is now **targeting Stable in 1.15.0** ([#148](https://github.com/bQuery/bQuery/issues/148)). The helper surface is frozen for one minor cycle, and the `unsafeHtml` security contract is pinned (sanitize-by-default; only brand-checked, author-controlled fragments inserted verbatim) and covered by tests. See the [Storybook guide](https://bquery.js.org/guide/storybook).

### Fixed (Unreleased)

Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ import { storyHtml, when } from '@bquery/bquery/storybook';
| **Reactive** | Stable | `signal`, `computed`, `effect`, `watchDebounce`, `watchThrottle`, async data, HTTP clients, polling, pagination, WebSocket / SSE, and REST helpers |
| **Concurrency** | Experimental | Zero-build worker tasks, explicit RPC helpers, optional reactive state wrappers, bounded worker pools, high-level collection helpers, an optional fluent pipeline layer, CSP-safe module workers, and client UI-scheduling primitives (targeting Stable in 1.15.0) |
| **Component** | Stable | Typed Web Components with scoped reactivity and configurable Shadow DOM |
| **Storybook** | Beta | Safe story template helpers with boolean-attribute shorthand |
| **Storybook** | Beta | Secure-by-default story template helpers with a pinned `unsafeHtml` contract (targeting Stable in 1.15.0) |
| **Motion** | Stable | View transitions, FLIP, morphing, parallax, typewriter, springs, and timelines |
| **Security** | Stable | HTML sanitization, Trusted Types, CSP helpers, and trusted fragment composition |
| **Platform** | Stable | Storage, cache, cookies, page metadata, announcers, and shared runtime config |
Expand All @@ -220,9 +220,9 @@ import { storyHtml, when } from '@bquery/bquery/storybook';
| **A11y** | Beta | Focus traps, live-region announcements, roving tabindex, skip links, and audits with documented WCAG scope (targeting Stable in 1.15.0) |
| **DnD** | Beta | Draggable elements, droppable zones, and keyboard-accessible sortable lists (targeting Stable in 1.15.0) |
| **Media** | Beta | Reactive, SSR-safe browser/device signals for viewport, network, battery, geolocation, clipboard, and DOM observers (targeting Stable in 1.15.0) |
| **Plugin** | Beta | Global plugin registration for custom directives and Web Components |
| **Devtools** | Beta | Runtime inspection helpers for signals, stores, components, and timelines |
| **Testing** | Beta | Component mounting, mock signals/router helpers, and async test utilities |
| **Plugin** | Beta | Global plugin registration (hook bus, DI, namespaced directives) with symmetric install/uninstall, plus `definePlugin` (targeting Stable in 1.15.0) |
| **Devtools** | Beta | Runtime inspection helpers plus a stable bridge protocol and reference browser extension (component tree, signals/stores, timeline) (targeting Stable in 1.15.0) |
| **Testing** | Beta | Testing-Library-parity, shadow-DOM-aware queries, `userEvent`/`fireEvent`, mocks, runner-agnostic (Vitest/Jest/bun:test) (targeting Stable in 1.15.0) |
| **SSR** | Experimental | Runtime-agnostic server-side rendering (Node ≥ 24, Deno, Bun), streaming, async loaders, hydration islands, head/asset/CSP-nonce management, runtime adapters |
| **Server** | Experimental | Express-inspired backend routing, middleware, safe responses, SSR-aware requests, sessions, CSRF, guards, auth, and WebSocket sessions (targeting Stable in 1.15.0) |

Expand Down
53 changes: 53 additions & 0 deletions docs/guide/devtools.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,58 @@ getPerformanceSummary(); // counts + averages per event type

---

## Stability: targeting Stable in 1.15.0

`devtools` has been **Beta**, and its biggest gap versus React/Vue/Svelte DevTools was the absence of a real **browser extension** — `installBrowserBridge()` only mirrored events to an in-page global. The work to graduate it is tracked in [#146](https://github.com/bQuery/bQuery/issues/146): stabilize the **bridge protocol** as the public contract between app and extension, ship a reference extension (component tree + signal/store inspection + timeline), and freeze the `devtools` API. Promotion to **Stable** then follows one full minor cycle with the surface frozen.

### Exit criteria

- [x] **Stabilized, versioned bridge protocol** ([#146](https://github.com/bQuery/bQuery/issues/146)) — `connectDevtoolsBridge()`, `createBridgeServer()`, `BRIDGE_PROTOCOL_VERSION`, and the message contract are the frozen app↔extension surface. See [Bridge protocol](#bridge-protocol-v1).
- [x] **Reference browser extension shipped** — a Manifest V3 extension (component tree, signal/store inspection, live timeline) lives in [`extension/`](https://github.com/bQuery/bQuery/tree/main/extension) and connects over the protocol.
- [x] **Public surface frozen for one minor** — see [Frozen surface reference](#frozen-surface-reference-1150). The bridge additions are additive; existing runtime helpers are unchanged.
- [ ] **Surface frozen for one full minor** (no breaking changes) — demonstrated across the 1.15 cycle.

### Frozen surface reference (1.15.0)

The frozen public surface of `@bquery/bquery/devtools`:

- **Lifecycle:** `enableDevtools`, `isDevtoolsEnabled`, `getDevtoolsState`.
- **Inspection:** `inspectSignals`, `inspectStores`, `inspectComponents`, `inspectEffects`, `trackSignal`, `untrackSignal`, `traceSignal`, `untraceSignal`.
- **Timeline:** `recordEvent`, `getTimeline`, `clearTimeline`, `filterTimeline`, `subscribeTimeline`.
- **Snapshots / diffs / perf:** `exportDevtoolsSnapshot`, `importDevtoolsSnapshot`, `diffSignals`, `diffStores`, `time`, `measureRender`, `getPerformanceSummary`.
- **Bridge (new in 1.15.0, additive):** `installBrowserBridge`, `connectDevtoolsBridge`, `createBridgeServer`, `serializeComponentTree`, `BRIDGE_PROTOCOL_VERSION`, `BRIDGE_SOURCE`, `BRIDGE_CAPABILITIES`.

### Bridge protocol (v1)

`connectDevtoolsBridge()` exposes a small, **versioned** message protocol over `window.postMessage` that the DevTools extension connects to. It is the stable contract between your app and the extension.

```ts
import { enableDevtools, connectDevtoolsBridge } from '@bquery/bquery/devtools';

enableDevtools(true);
const bridge = connectDevtoolsBridge(); // protocol v1 over window.postMessage
// ...later
bridge.disconnect();
```

Every message carries `source: 'bquery-devtools'` and a protocol version `v`:

| Direction | `kind` | Purpose |
| ------------ | ---------- | -------------------------------------------- |
| panel → page | `hello` | Announce the panel; page replies with `init` |
| panel → page | `request` | `{ id, method, params }` |
| page → panel | `init` | `{ capabilities }` handshake |
| page → panel | `response` | `{ id, result \| error }` |
| page → panel | `event` | A streamed timeline `entry` |

**Built-in methods:** `ping`, `getSnapshot` (signals + stores + components + state), `getTimeline` (`{ limit }`), `getComponentTree` (serialized custom-element tree + flat counts). Supply extra/override methods via `connectDevtoolsBridge({ methods })`. The transport-agnostic `createBridgeServer({ post, methods })` powers it and can be embedded in any transport (and unit-tested without a DOM).

Time-travel is built on these primitives plus the existing `exportDevtoolsSnapshot` / `diffSignals` / `diffStores` helpers — the panel diffs successive snapshots rather than the protocol carrying mutation commands.

### The reference extension

A Manifest V3 reference extension lives in [`extension/`](https://github.com/bQuery/bQuery/tree/main/extension): load it unpacked (`chrome://extensions` → Developer mode → Load unpacked), enable the bridge in your app, and open the **bQuery** DevTools panel. See [`extension/README.md`](https://github.com/bQuery/bQuery/tree/main/extension/README.md) for details. The panel renders the component tree, live signal/store values, and the reactive timeline. It is intentionally minimal — the **protocol** is the stable contract; the panel is a starting point to extend.

---

## Getting Started
Expand Down Expand Up @@ -526,4 +578,5 @@ clearTimeline();

## Version history

- **1.15.0** — **targeting Stable**: surface frozen for one minor cycle ([#146](https://github.com/bQuery/bQuery/issues/146)). New stable, versioned bridge protocol (`connectDevtoolsBridge`, `createBridgeServer`, `serializeComponentTree`, `BRIDGE_PROTOCOL_VERSION`) and a reference Manifest V3 browser extension (component tree + signal/store inspection + timeline) in `extension/`.
- **1.14.0** — ring-buffered timeline, expanded `TimelineEntry`, new event types, `filterTimeline`, `subscribeTimeline`, privacy-aware `inspectSignals`, `diffSignals` / `diffStores`, `traceSignal` / `untraceSignal`, `inspectEffects`, snapshot import/export, `installBrowserBridge`, perf helpers.
Loading