@scayle/storefront-devtools 0.2.0-alpha.1 → 0.2.0-alpha.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/CHANGELOG.md +10 -0
- package/README.md +113 -83
- package/dist/_chunks/coalesce-cmmfn4qq.mjs +1585 -0
- package/dist/group.d.ts +29 -21
- package/dist/group.d.ts.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +40 -65
- package/dist/inertia/channel.d.ts +54 -0
- package/dist/inertia/channel.d.ts.map +1 -0
- package/dist/inertia/client/index.d.ts +1 -6
- package/dist/inertia/client/index.d.ts.map +1 -1
- package/dist/inertia/client/index.mjs +246 -109
- package/dist/inertia/client/publish.d.ts +24 -0
- package/dist/inertia/client/publish.d.ts.map +1 -0
- package/dist/inertia/core/network.d.ts +1 -1
- package/dist/inertia/core/network.d.ts.map +1 -1
- package/dist/inertia/core/response.d.ts +3 -3
- package/dist/inertia/core/response.d.ts.map +1 -1
- package/dist/inertia/plugin.d.ts +8 -6
- package/dist/inertia/plugin.d.ts.map +1 -1
- package/dist/orpc/channel.d.ts +29 -0
- package/dist/orpc/channel.d.ts.map +1 -0
- package/dist/orpc/client/index.d.ts +1 -6
- package/dist/orpc/client/index.d.ts.map +1 -1
- package/dist/orpc/client/index.mjs +152 -137
- package/dist/orpc/client/publish.d.ts +15 -0
- package/dist/orpc/client/publish.d.ts.map +1 -0
- package/dist/orpc/core/serialize.d.ts +1 -1
- package/dist/orpc/core/stats.d.ts +10 -0
- package/dist/orpc/core/stats.d.ts.map +1 -0
- package/dist/orpc/core/store.d.ts +1 -2
- package/dist/orpc/core/store.d.ts.map +1 -1
- package/dist/orpc/plugin.d.ts +8 -5
- package/dist/orpc/plugin.d.ts.map +1 -1
- package/dist/shared/clipboard.d.ts +2 -3
- package/dist/shared/clipboard.d.ts.map +1 -1
- package/dist/shared/coalesce.d.ts +14 -0
- package/dist/shared/coalesce.d.ts.map +1 -0
- package/dist/shared/panel-channel.d.ts +49 -0
- package/dist/shared/panel-channel.d.ts.map +1 -0
- package/dist/shared/publish-options.d.ts +13 -0
- package/dist/shared/publish-options.d.ts.map +1 -0
- package/dist/shared/safe-clone.d.ts +2 -1
- package/dist/shared/safe-clone.d.ts.map +1 -1
- package/dist/storefront/plugin.d.ts +6 -4
- package/dist/storefront/plugin.d.ts.map +1 -1
- package/dist/ui/assets/App-BlEKD1MK.js +4 -0
- package/dist/ui/assets/App-C1rr07m5.js +1 -0
- package/dist/ui/assets/App-C5-JscO0.css +1 -0
- package/dist/ui/assets/App-M0iU7c4p.css +1 -0
- package/dist/ui/assets/App-VElUrn9P.js +5 -0
- package/dist/ui/assets/App-jiQKInbo.css +1 -0
- package/dist/ui/assets/_plugin-vue_export-helper-BDNMzG2s.js +1 -0
- package/dist/ui/assets/channel-D7V7aU79.js +1 -0
- package/dist/ui/assets/clipboard-BnEeWyfh.css +1 -0
- package/dist/ui/assets/clipboard-n-T06WI3.js +1 -0
- package/dist/ui/assets/panel-channel-DjMENemf.js +2 -0
- package/dist/ui/assets/panels-B4LTsmli.css +1 -0
- package/dist/ui/assets/panels-BLV_p6Kz.js +2 -0
- package/dist/ui/assets/preload-helper-J6bGWMBq.js +2 -0
- package/dist/{vue-devtools/ui/assets/index-Dby9TIQH.js → ui/assets/vue-BAMMushd.js} +19 -20
- package/dist/{vue-devtools/ui/assets/index-sSkqWPzY.css → ui/assets/vue-Kq4tvBbL.css} +1 -1
- package/dist/ui/panels/index.html +15 -0
- package/dist/{vue-devtools/ui → ui/vue}/index.html +4 -2
- package/dist/vue-devtools/client/index.mjs +0 -1
- package/dist/vue-devtools/plugin.d.ts +10 -9
- package/dist/vue-devtools/plugin.d.ts.map +1 -1
- package/package.json +11 -29
- package/dist/_chunks/clipboard-DrVHc2QA.mjs +0 -61
- package/dist/_chunks/diff-DzJ5arJj.mjs +0 -169
- package/dist/_chunks/panel-uV5ITqhY.mjs +0 -51
- package/dist/_chunks/redact-DmIF-iyk.mjs +0 -96
- package/dist/_chunks/useStore-Db8RZW8T.mjs +0 -10
- package/dist/inertia/client/index.d.mts +0 -13
- package/dist/inertia/renderer/index.d.mts +0 -16
- package/dist/inertia/renderer/index.mjs +0 -771
- package/dist/orpc/client/index.d.mts +0 -13
- package/dist/orpc/renderer/index.d.mts +0 -16
- package/dist/orpc/renderer/index.mjs +0 -457
- package/dist/resource-center/client/index.mjs +0 -21
- package/dist/resource-center/client.d.ts +0 -3
- package/dist/resource-center/client.d.ts.map +0 -1
- package/dist/resource-center/plugin.d.ts +0 -12
- package/dist/resource-center/plugin.d.ts.map +0 -1
- package/dist/shared/use-window-store.d.ts +0 -18
- package/dist/shared/use-window-store.d.ts.map +0 -1
- package/dist/storefront/renderer/index.d.mts +0 -16
- package/dist/storefront/renderer/index.mjs +0 -124
- /package/dist/{vue-devtools/ui → ui}/assets/css-8QJvnqUH.js +0 -0
- /package/dist/{vue-devtools/ui → ui}/assets/css-CaJ9TzKE.js +0 -0
- /package/dist/{vue-devtools/ui → ui}/assets/diff-woXpYk--.js +0 -0
- /package/dist/{vue-devtools/ui → ui}/assets/html-BHDw6EPc.js +0 -0
- /package/dist/{vue-devtools/ui → ui}/assets/html-GueGcY0x.js +0 -0
- /package/dist/{vue-devtools/ui → ui}/assets/javascript-BzbQS41l.js +0 -0
- /package/dist/{vue-devtools/ui → ui}/assets/javascript-Yelw-5ZN.js +0 -0
- /package/dist/{vue-devtools/ui → ui}/assets/json-B88Oqtu5.js +0 -0
- /package/dist/{vue-devtools/ui → ui}/assets/json-CaljABEy.js +0 -0
- /package/dist/{vue-devtools/ui → ui}/assets/shellscript-CLZ0U2zV.js +0 -0
- /package/dist/{vue-devtools/ui → ui}/assets/typescript-Utq2Cl8c.js +0 -0
- /package/dist/{vue-devtools/ui → ui}/assets/typescript-j_1H8WHN.js +0 -0
- /package/dist/{vue-devtools/ui → ui}/assets/vitesse-dark-BZCL-v6S.js +0 -0
- /package/dist/{vue-devtools/ui → ui}/assets/vitesse-light-VbXTXTou.js +0 -0
- /package/dist/{vue-devtools/ui → ui}/assets/vue-B1Tf5CHw.js +0 -0
- /package/dist/{vue-devtools/ui → ui}/assets/vue-html-CGMs_6qn.js +0 -0
- /package/dist/{vue-devtools/ui → ui}/assets/yaml-rwi0_p6S.js +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# @scayle/storefront-devtools
|
|
2
2
|
|
|
3
|
+
## 0.2.0-alpha.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Added dependency `@vitejs/devtools-kit@catalog:`
|
|
8
|
+
- Removed dependency `sirv@catalog:`
|
|
9
|
+
- The Inertia.js, oRPC, and Storefront context panels now run as iframe apps in the dock. Page scripts in your app send them their data over `devframe/in-page-channel`. The panels keep rendering when you switch the dock between Float, Edge, and Popup, and they no longer show up as extra apps in Vue DevTools.
|
|
10
|
+
|
|
11
|
+
The Resource Center entry is gone, and so are the `./inertia/renderer`, `./orpc/renderer`, `./storefront/renderer`, and `./resource-center/client` subpath exports. The dock loads the panels itself, so nothing outside this package imported them.
|
|
12
|
+
|
|
3
13
|
## 0.2.0-alpha.1
|
|
4
14
|
|
|
5
15
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
</h4>
|
|
11
11
|
|
|
12
12
|
<p align="center">
|
|
13
|
-
The SCAYLE <strong>Storefront DevTools</strong> package
|
|
13
|
+
The SCAYLE <strong>Storefront DevTools</strong> package adds the Vite DevTools dock to the Storefront Application V3 with one Vite plugin call. The dock holds an Inertia.js inspector, an oRPC call inspector, a Storefront context viewer, and Vue DevTools.
|
|
14
14
|
</p>
|
|
15
15
|
<p align="center">
|
|
16
16
|
<a href="#"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="SCAYLE's Storefront DevTools is released under the MIT license." /></a>
|
|
@@ -18,30 +18,29 @@
|
|
|
18
18
|
|
|
19
19
|
## Overview
|
|
20
20
|
|
|
21
|
-
`@scayle/storefront-devtools` is a dev-only Vite plugin. It hosts the Vite DevTools dock and registers
|
|
21
|
+
`@scayle/storefront-devtools` is a dev-only Vite plugin. It hosts the Vite DevTools dock and registers two dock groups, **SCAYLE Storefront** and **Vue**:
|
|
22
22
|
|
|
23
|
-
-
|
|
24
|
-
-
|
|
25
|
-
-
|
|
26
|
-
-
|
|
27
|
-
- **Vue panel**: the component tree and timeline you'd otherwise get from a separate `vite-plugin-vue-devtools` install, mounted in the same dock.
|
|
23
|
+
- The Inertia.js panel lists every visit your app makes, one request per navigation. It shows the response body and headers, the Inertia protocol details (partial reload keys, asset version, redirects), and a lifecycle timeline, and it flags common mistakes such as a missing partial-reload prop. The [Inertia.js panel](#inertiajs-panel) section covers it in depth.
|
|
24
|
+
- The oRPC panel lists every call to your `/api` endpoint and decodes each call's `{ json, meta }` envelope back to typed input and output. It groups calls by procedure, classifies failures, and tracks timing per procedure. The [oRPC panel](#orpc-panel) section covers it in depth.
|
|
25
|
+
- The Storefront context panel is a read-only view of the resolved shop, country, locale, and session for the page you're looking at, taken from the Inertia page the SDK ships. The [Storefront context panel](#storefront-context-panel) section covers it.
|
|
26
|
+
- The Vue panel gives you the component tree and timeline in the same dock, so you don't need a separate `vite-plugin-vue-devtools` install.
|
|
28
27
|
|
|
29
|
-
The plugin runs
|
|
28
|
+
The plugin only runs on the dev server and drops out of production builds without an environment flag. [Production safety](#production-safety) explains why.
|
|
30
29
|
|
|
31
|
-
##
|
|
30
|
+
## Beyond the browser Network tab
|
|
32
31
|
|
|
33
|
-
|
|
32
|
+
Use the browser's Network tab for raw HTTP. These panels cover what it can't show.
|
|
34
33
|
|
|
35
|
-
-
|
|
36
|
-
-
|
|
37
|
-
-
|
|
38
|
-
-
|
|
34
|
+
- Many Inertia visits never hit the network. The initial page load embeds the page object in the HTML, so no XHR fires. Client-side history navigations, prefetch cache hits, and `preserveState` updates send no request at all, and the Network tab has no row for them. The Inertia.js panel picks them up from Inertia's DOM events and from history.
|
|
35
|
+
- The Inertia.js panel compares visits. It diffs the props of consecutive visits, links a deferred-prop reload to the visit that triggered it, and draws the lifecycle event timeline. The Network tab shows one request at a time and forgets the one before.
|
|
36
|
+
- An oRPC request body isn't the argument your code passed. Every oRPC call is a `POST` under `/api` with a `{ json, meta }` envelope. The Network tab shows that envelope as raw JSON and can't rebuild the `Date`, `Map`, `Set`, or `BigInt` values it encodes, because JSON has no way to represent them. The oRPC panel decodes the envelope back to the typed value your handler received.
|
|
37
|
+
- oRPC calls get lost in the Network tab, between the images, scripts, and page visits a storefront loads. The oRPC panel lists only oRPC calls, groups them by procedure, adds up the timing per procedure, and classifies each failure as validation, server, or network.
|
|
39
38
|
|
|
40
|
-
Where
|
|
39
|
+
Where the two overlap, in the HTTP view of a single oRPC request, the panels don't try to replace the Network tab. Use the Network tab for the raw transaction and the panels for what it means to Inertia and oRPC.
|
|
41
40
|
|
|
42
41
|
## Installation
|
|
43
42
|
|
|
44
|
-
The package ships with Storefront Application V3 by default. To add it
|
|
43
|
+
The package ships with Storefront Application V3 by default. To add it yourself:
|
|
45
44
|
|
|
46
45
|
```bash
|
|
47
46
|
pnpm add -D @scayle/storefront-devtools
|
|
@@ -49,7 +48,7 @@ pnpm add -D @scayle/storefront-devtools
|
|
|
49
48
|
|
|
50
49
|
## Integration
|
|
51
50
|
|
|
52
|
-
The
|
|
51
|
+
The only file you change is the Storefront Application V3 `vite.config.ts`. The plugin injects the dock client and the Inertia and oRPC page scripts into the app's client entry, so the rest of your app code stays as it is.
|
|
53
52
|
|
|
54
53
|
Import the default export and spread it into the `plugins` array, after `@vitejs/plugin-vue`:
|
|
55
54
|
|
|
@@ -75,147 +74,178 @@ export default defineConfig({
|
|
|
75
74
|
})
|
|
76
75
|
```
|
|
77
76
|
|
|
78
|
-
`storefrontDevtools()` returns an array of Vite plugins, so
|
|
77
|
+
`storefrontDevtools()` returns an array of Vite plugins, so you have to spread it. It includes the Vue DevTools panel, so you don't need `vite-plugin-vue-devtools` on top.
|
|
79
78
|
|
|
80
79
|
### Dev server path exclusion
|
|
81
80
|
|
|
82
|
-
|
|
81
|
+
Vite serves the dock and its assets under `/__devtools/` and `/__storefront-devtools/`. The Storefront Application V3 serves pages through a Hono dev server with a country-prefix redirect, which would catch those paths and rewrite them. `@scayle/storefront-build` already excludes the DevTools paths from the Hono dev server, so with both packages installed you need no extra configuration.
|
|
83
82
|
|
|
84
|
-
`storefrontDevtools()` takes no options. It always registers the Inertia.js, oRPC, Storefront context,
|
|
83
|
+
`storefrontDevtools()` takes no options. It always registers the Inertia.js, oRPC, Storefront context, and Vue panels, and it always injects into the Storefront Application V3's own client entry (`src/client/main.ts`).
|
|
85
84
|
|
|
86
85
|
## Opening the dock
|
|
87
86
|
|
|
88
|
-
Run the Storefront Application V3 dev server (`pnpm dev`) and open the app. A floating launcher appears on the page. Open it, then open the **SCAYLE Storefront** group
|
|
87
|
+
Run the Storefront Application V3 dev server (`pnpm dev`) and open the app. A floating launcher appears on the page. Open it, then open the **SCAYLE Storefront** group for the **Inertia.js**, **oRPC**, and **Storefront** entries, or the **Vue** group for the component tree and timeline.
|
|
89
88
|
|
|
90
|
-
The
|
|
89
|
+
The plugin injects the launcher into the client entry instead of the HTML. The Storefront Application V3 builds its HTML in the SSR renderer, so Vite's `transformIndexHtml` hook never fires. Every panel's page script arrives through the same injection.
|
|
91
90
|
|
|
92
|
-
## Security
|
|
91
|
+
## Security and browser authorization
|
|
93
92
|
|
|
94
|
-
The dock
|
|
93
|
+
The dock in the browser talks to the Vite dev server over a WebSocket RPC channel (`@devframes/hub`, with `crossws` as its transport layer). Our panels aren't the only thing on that channel. `@vitejs/devtools` ships its own RPC functions with real reach into your machine, for example `vite:core:open-in-editor`, which opens any file path in your editor, and a terminals feed. This package sets `builtinDevTools: false`, which drops the upstream Terminals, Messages, and Inspector docks and their UI. The RPC declarations behind them stay, because they belong to `@vitejs/devtools` itself and a consumer can't remove them. Two independent checks protect the channel.
|
|
95
94
|
|
|
96
|
-
|
|
97
|
-
- **One-time client authorization.** On top of the origin check, `@vitejs/devtools` gates the RPC connection behind a one-time code by default (`clientAuth: true`). On first connection from a new browser, the `pnpm dev` terminal prints `devframe auth code <code>` and a magic-link URL (`...#devframe_otp=<code>`); enter the code in the dock's prompt, or open the printed URL, to authorize that browser. Until then, the dock stays unauthorized — this is expected, not a connection failure.
|
|
95
|
+
### Origin allowlist
|
|
98
96
|
|
|
99
|
-
|
|
97
|
+
`@vitejs/devtools` accepts a WebSocket connection only when its `Origin` header matches a built-in loopback allowlist (`localhost`, `127.0.0.1`, and similar). The check compares strings. It doesn't resolve DNS or read your hosts file, so a custom dev hostname that points at loopback through `/etc/hosts` or a local DNS override (for example `dev-my-app.example.com`) gets rejected by default. If your setup needs another hostname, such as a reverse proxy, a tunnel, or a custom `/etc/hosts` entry, add it with `devtools: { allowedOrigins: ['https://dev-my-app.example.com'] }` in the app's Vite config.
|
|
100
98
|
|
|
101
|
-
|
|
99
|
+
### One-time client authorization
|
|
102
100
|
|
|
103
|
-
|
|
101
|
+
On top of the origin check, `@vitejs/devtools` puts the RPC connection behind a one-time code by default (`clientAuth: true`). The first time a new browser connects, the `pnpm dev` terminal prints `devframe auth code <code>` and a magic-link URL (`...#devframe_otp=<code>`). Enter the code in the dock's prompt, or open the printed URL, to authorize that browser. The dock stays unauthorized until you do, and that's expected.
|
|
104
102
|
|
|
105
|
-
|
|
103
|
+
### Turning off the authorization check
|
|
104
|
+
|
|
105
|
+
Setting `devtools: { clientAuth: false }` (or the `VITE_DEVTOOLS_DISABLE_CLIENT_AUTH=true` environment variable) skips the one-time code. The `@vitejs/devtools` documentation warns about this: _"if you disable client authentication, any browsers can connect to the devtools and access to your server and filesystem (including other devices, if you open server `host` option to LAN or WAN)."_ Only turn it off where every request comes from a trusted developer. Never do it with `server.host` bound to a LAN or WAN interface, or in a shared environment or anything close to production.
|
|
106
|
+
|
|
107
|
+
### Production safety
|
|
108
|
+
|
|
109
|
+
`storefrontDevtools()` registers its plugins in every build, with no `import.meta.env.PROD` check of its own. The safety comes from `@vitejs/devtools`. Its plugin opens the WebSocket RPC server from Vite's `configureServer` hook, and Vite calls that hook during `vite dev` and `vite serve`, never during `vite build`. A production build and its runtime output carry no RPC server, no WebSocket endpoint, and none of the injected page scripts or launcher code.
|
|
110
|
+
|
|
111
|
+
## Page scripts and panel apps
|
|
112
|
+
|
|
113
|
+
The package has two halves. Page scripts run in the app's own page and capture what happens there. Panel apps run in iframes inside the dock and render what the page scripts publish. The two talk over `devframe/in-page-channel`, a `postMessage` channel between the page and the iframes the dock hosts for it.
|
|
106
114
|
|
|
107
115
|
```
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
DOM-event capture (inertia:*)
|
|
111
|
-
-> Correlator -> RequestRecords
|
|
112
|
-
history-capture (pushState/replaceState)
|
|
116
|
+
app page (browser) dock iframe
|
|
117
|
+
page script (injected into the client entry) panel app (/__storefront-devtools/panels/)
|
|
118
|
+
DOM-event capture (inertia:*) ?view=inertia | orpc | storefront
|
|
119
|
+
-> Correlator -> RequestRecords
|
|
120
|
+
history-capture (pushState/replaceState)
|
|
113
121
|
network timing (PerformanceObserver)
|
|
114
|
-
-> DevToolsStore
|
|
115
|
-
|
|
122
|
+
-> DevToolsStore
|
|
123
|
+
createPageScriptChannel() ── state snapshots ──▶ connectPanelChannel()
|
|
124
|
+
◀── getState, clear, mirrors the latest
|
|
125
|
+
setPaused ─────── snapshot into a Vue ref
|
|
116
126
|
```
|
|
117
127
|
|
|
118
|
-
### Capture
|
|
128
|
+
### Capture in the app page
|
|
119
129
|
|
|
120
|
-
On load, the
|
|
130
|
+
On load, the Inertia page script builds a `DevToolsStore` and feeds it from three sources, none of which change how Inertia behaves:
|
|
121
131
|
|
|
122
|
-
-
|
|
123
|
-
-
|
|
124
|
-
-
|
|
132
|
+
- Inertia 3.x's `inertia:*` DOM events, through `document.addEventListener`. The script copies each event's detail with a depth limit, drops functions and abort signals, and hands it to the store. It doesn't patch `router.on()`.
|
|
133
|
+
- A `PerformanceObserver` over resource-timing entries, matched to in-flight requests by URL.
|
|
134
|
+
- A `history.pushState` / `replaceState` patch that catches client visits (`router.push` / `router.replace`) that skip the normal Inertia event lifecycle.
|
|
125
135
|
|
|
126
|
-
Every handler
|
|
136
|
+
Every handler runs inside a guard, so a devtools error can't crash the app.
|
|
127
137
|
|
|
128
138
|
### Correlation
|
|
129
139
|
|
|
130
|
-
A correlator groups the raw events into one `RequestRecord` per
|
|
140
|
+
A correlator groups the raw events into one `RequestRecord` per visit. It matches events by a visit fingerprint plus a pointer to the active visit, and it handles deferred prop reloads, prefetch cache hits, POST→redirect flows, 409 asset-version mismatches, and the initial page load. The store keeps the latest 200 records and saves a compact summary to `sessionStorage`, so the requests from before a reload stay visible.
|
|
131
141
|
|
|
132
142
|
### oRPC capture
|
|
133
143
|
|
|
134
|
-
The oRPC panel follows the same shape with its own store
|
|
144
|
+
The oRPC panel follows the same shape with its own store and page script. The page script patches `window.fetch` once on load. For each request whose path starts with `/api`, it records one `OrpcCall`: the procedure name (the path after `/api`), the input from the request body, and, once the response arrives, the output, status, duration, and any error. Every other fetch passes through untouched, and the app always gets the original response or rejection, so the patch can't break a real request. The store keeps the latest 200 calls, classifies each failure as validation, server, or network, and saves a previous-session summary the way the Inertia store does. It keeps each input, output, and error in two forms: decoded to typed values, and as the raw `{ json, meta }` envelope, which the Data tab can show too.
|
|
145
|
+
|
|
146
|
+
### Publishing to the panels
|
|
147
|
+
|
|
148
|
+
Each page script opens its own channel (`storefront-devtools:inertia`, `storefront-devtools:orpc`) and pushes a snapshot of its store to the connected panels whenever the store changes. It sends at most one snapshot per 16 ms, so a burst of Inertia events costs one message instead of twenty. A timer paces this rather than `requestAnimationFrame`, because the browser pauses animation frames in a hidden tab, and the dock can sit in a Picture-in-Picture window while the app's tab is in the background. A panel that opens later asks for the current snapshot with `getState`. **Pause** and **Clear** reach the store the same way, as channel calls.
|
|
149
|
+
|
|
150
|
+
Snapshots cross the channel through structured clone, which rejects functions, so the page scripts run captured values through `safeClone` before they store them. The channel stays inside one browser tab, so two open tabs never see each other's requests.
|
|
135
151
|
|
|
136
152
|
### Storefront context
|
|
137
153
|
|
|
138
|
-
Unlike the Inertia and oRPC panels, the Storefront context panel has no
|
|
154
|
+
Unlike the Inertia and oRPC panels, the Storefront context panel has no page script of its own. The Inertia page script serves it on a second channel, `storefront-devtools:storefront`, which carries only the current Inertia page and sends a new snapshot only when that page changes. The panel shows what the Inertia store has already captured, nothing more.
|
|
139
155
|
|
|
140
|
-
###
|
|
156
|
+
### Panel apps
|
|
141
157
|
|
|
142
|
-
|
|
158
|
+
The dock loads every panel as an `iframe` entry. The package builds one small Vue app for the three storefront panels and serves it, together with the Vue DevTools UI, from `/__storefront-devtools/` on the dev server. The `?view=` query picks the panel the app mounts. Each iframe is its own document, so the panel styles never touch the app, and the panel's own Vue instance stays out of the app's Vue DevTools. The dock keeps a hidden panel's iframe alive while you use another entry, and that panel keeps receiving snapshots.
|
|
143
159
|
|
|
144
160
|
## Panels
|
|
145
161
|
|
|
146
162
|
### Inertia.js panel
|
|
147
163
|
|
|
148
|
-
|
|
164
|
+
Inertia drives navigation over XHR and swaps page props without a full reload, so the browser Network tab shows you raw JSON and nothing about the visit itself. This panel reads the Inertia lifecycle and shows you the visit. It's the main reason the package exists.
|
|
165
|
+
|
|
166
|
+
It opens on the **Requests** tab and has a second **Page** tab. A top bar holds **Pause** and **Clear**.
|
|
149
167
|
|
|
150
|
-
|
|
168
|
+
#### Requests tab
|
|
151
169
|
|
|
152
|
-
|
|
170
|
+
The left side lists each visit as it happens: method, URL, visit type, timing, and a badge for any diagnostics. Filter by type (full, partial, deferred, prefetch, redirect, client), or type into the URL box to narrow the list. Deferred reloads nest under the visit that triggered them, so you can see which page started which background load. Once the list passes 200 visits, a footer tells you how many older ones dropped off. After a reload, a collapsible **Previous session** block keeps the visits from before it, because a full reload would otherwise empty the list. This tab answers "did that click fire a visit, and what kind?"
|
|
153
171
|
|
|
154
|
-
Select a visit and the right side
|
|
172
|
+
Select a visit and the right side shows its detail in four tabs:
|
|
155
173
|
|
|
156
|
-
- **Response**
|
|
157
|
-
- **Headers**
|
|
158
|
-
- **Network**
|
|
159
|
-
- **Events**
|
|
174
|
+
- **Response** shows the props captured for that visit, each tagged with how it arrived (full, partial, deferred, merged, prepended, or deep-merged). It notes any prop you asked for with `only` that the response left out, and counts the props carried over unchanged from the previous page. The **Show changes since last page** toggle switches to a before/after diff that marks added keys, removed keys, and changed values. Use it to confirm a partial or deferred reload returned the prop you asked for, or to spot a prop that changed when it shouldn't have.
|
|
175
|
+
- **Headers** shows the request and response headers of that visit as a table. The store redacts credential headers (`authorization`, `cookie`, and similar) before it saves anything.
|
|
176
|
+
- **Network** shows the Inertia protocol side of the request: asset version, the `only` / `except` partial-reload keys, the `errorBag` name, reset keys, and resource timing and transfer size when the browser recorded them. Use it to check that a partial reload sent the right `only` set, or to see how long a visit spent on the network.
|
|
177
|
+
- **Events** shows a lifecycle timeline (`before`, `start`, `success`, `finish`, and the rest) with each step's offset in milliseconds from the first event, colored by outcome. Below the timeline sits every captured event with its full payload as a collapsible tree. Come here to debug a visit that hung, got canceled, or fired events in an order you didn't expect.
|
|
160
178
|
|
|
161
|
-
The detail header also
|
|
179
|
+
The detail header also has **Copy as Markdown**, which copies the visit (header, features, error, and the raw page JSON) for pasting into an issue or an AI chat.
|
|
162
180
|
|
|
163
|
-
Above the tabs, the detail shows an overview (method, URL, type, status, component, duration, and the redirect URL on a 409), the active
|
|
181
|
+
Above the tabs, the detail shows an overview (method, URL, type, status, component, duration, and the redirect URL on a 409), the active feature badges, and any diagnostics.
|
|
164
182
|
|
|
165
|
-
|
|
183
|
+
#### Feature badges
|
|
166
184
|
|
|
167
|
-
|
|
185
|
+
Feature badges mark the Inertia features active on a visit: partial reload, deferred props, the merge, deep-merge, and prepend strategies, scroll regions, once props, prefetch, cached (a prefetch hit that skipped the network), flash data, remembered state, encrypted history, and clear-history. Click a badge to see its description and a link to the matching Inertia docs, so you don't have to remember what each one means.
|
|
168
186
|
|
|
169
|
-
|
|
187
|
+
#### Diagnostics
|
|
170
188
|
|
|
171
|
-
|
|
189
|
+
Diagnostics flag common mistakes on a visit: an asset-version mismatch that forced a 409 reload, a canceled or interrupted visit, a partial-reload prop you requested that the response left out, validation errors lost because an `only` option didn't include `errors`, deferred props that failed to load, and a history replace to the same URL. Each one links to the relevant docs.
|
|
190
|
+
|
|
191
|
+
#### Page tab
|
|
192
|
+
|
|
193
|
+
The Page tab shows the current page props as a collapsible tree, with the page-level feature badges. Use it to inspect the props your component renders right now, apart from any single visit.
|
|
194
|
+
|
|
195
|
+
#### Pausing and clearing
|
|
196
|
+
|
|
197
|
+
Pause stops capture, so a busy page doesn't flood the list while you read a visit. Resume picks up new visits from that point. Clear empties the list. The panel keeps your active tab and list filter when you reopen it, but not the URL search.
|
|
172
198
|
|
|
173
199
|
### oRPC panel
|
|
174
200
|
|
|
175
|
-
The Storefront Application V3
|
|
201
|
+
The Storefront Application V3 changes state through oRPC calls to `/api`: add to basket, toggle wishlist, apply a promotion code, run a search. In the browser Network tab they show up as POST requests with a JSON envelope for a body, mixed in with everything else the page loads. This panel shows them as oRPC calls, labeled by procedure.
|
|
176
202
|
|
|
177
|
-
It opens on the **Calls** tab and has a second **Stats** tab. A top bar
|
|
203
|
+
It opens on the **Calls** tab and has a second **Stats** tab. A top bar holds **Pause** and **Clear**.
|
|
178
204
|
|
|
179
|
-
|
|
205
|
+
#### Calls tab
|
|
180
206
|
|
|
181
|
-
|
|
207
|
+
The left side lists each oRPC call as it fires: method, procedure (`basket/add`, `wishlist/remove`, and so on), a status badge, and the duration. The badge is green for success, amber for a validation error, and red for a server or network error. Filter by domain (the first path segment, such as `basket`, `wishlist`, or `search`), or type into the box to match a procedure. A collapsible **Previous session** block keeps the calls from before a reload.
|
|
182
208
|
|
|
183
|
-
|
|
184
|
-
- **Headers** — the request and response headers actually sent and received for that call, as a table. Credential-bearing headers and sensitive input fields (passwords, tokens, and similar) are redacted before they are ever stored.
|
|
209
|
+
Select a call and the right side shows its detail in two tabs:
|
|
185
210
|
|
|
186
|
-
|
|
211
|
+
- **Data** shows the request input and the success output as collapsible trees. For a failed call it shows the **Error** instead, with its oRPC code, status, message, and data. A streaming response shows a note in place of a buffered body.
|
|
212
|
+
- **Headers** shows the request and response headers of that call as a table. The store redacts credential headers and sensitive input fields (passwords, tokens, and similar) before it saves anything.
|
|
187
213
|
|
|
188
|
-
The
|
|
214
|
+
The overview above the tabs shows the procedure, method, URL, status, duration, and the error kind for a failed call.
|
|
189
215
|
|
|
190
|
-
|
|
216
|
+
The detail header has **Copy as curl**, which copies the call as a runnable `curl` command with its JSON body, for replaying it in a terminal or pasting it into an issue.
|
|
191
217
|
|
|
192
|
-
|
|
218
|
+
#### Stats tab
|
|
193
219
|
|
|
194
|
-
|
|
220
|
+
The Stats tab lists every procedure with its call count, average duration, and last duration. Sort by count to find the chatty procedure a page fires ten times, or by average to find the slow one.
|
|
221
|
+
|
|
222
|
+
#### Pausing and clearing
|
|
195
223
|
|
|
196
|
-
|
|
224
|
+
Pause stops capture while you read a call. Clear empties the list.
|
|
197
225
|
|
|
198
|
-
###
|
|
226
|
+
### Storefront context panel
|
|
199
227
|
|
|
200
|
-
A
|
|
228
|
+
A read-only view of the resolved shop, country, locale, and session for the current page, plus the config public fields the SDK sends to the client. It shows only what the Inertia page props already contain, so it never renders secrets or the full session token. Use it to check which shop, country, and locale the app resolved for a request without digging through page props.
|
|
201
229
|
|
|
202
230
|
### Vue
|
|
203
231
|
|
|
204
|
-
The Vue DevTools component tree and timeline, in a **Vue** dock group
|
|
232
|
+
The Vue DevTools component tree and timeline, in a **Vue** dock group next to the SCAYLE Storefront group. It replaces a separate `vite-plugin-vue-devtools` install. Every panel in this package runs as an iframe app. The Vue panels load the `@vue/devtools-applet` UI, which reaches the app page over a `BroadcastChannel` RPC bridge. The storefront panels use the package's own panel app.
|
|
205
233
|
|
|
206
|
-
Click-to-inspect
|
|
234
|
+
Click-to-inspect, where you click a rendered element to jump to its component in the tree, isn't included. It needs `vite-plugin-vue-inspector` in the app's own Vite config, and this package doesn't add it.
|
|
207
235
|
|
|
208
236
|
## Architecture notes
|
|
209
237
|
|
|
210
|
-
Each panel that captures live app state (Inertia, oRPC)
|
|
238
|
+
Each panel that captures live app state (Inertia, oRPC) splits into three parts. `src/<feature>/core/` is plain TypeScript with no Vue import, and handles capture, classification, diffing, diagnostics, and persistence. `src/<feature>/client/` is the page script: it runs the core in the app page and publishes the store over `devframe/in-page-channel`. `src/<feature>/panel/` holds the Vue components that render it. Both features share panel UI (`TreeView`, the clipboard helper, panel styles) and generic building blocks (snapshot pacing, snapshot mirroring, `sessionStorage` persistence) from `src/shared/`.
|
|
239
|
+
|
|
240
|
+
The storefront panels load from `/__storefront-devtools/panels/`, one iframe per view, and the Vue DevTools UI loads from `/__storefront-devtools/vue/`. The panel styles are dark-mode only. Each panel runs in its own iframe document, so its styles never leak into the host application.
|
|
211
241
|
|
|
212
242
|
## Upstream stability
|
|
213
243
|
|
|
214
|
-
`@vitejs/devtools
|
|
244
|
+
`@vitejs/devtools` and `@vitejs/devtools-kit` are still `0.x` releases, so any minor version can ship a breaking change without a deprecation period. `@devframes/hub` and `@devframes/hub-ui` reached 1.0.0 in September 2026. If you upgrade any of them:
|
|
215
245
|
|
|
216
|
-
- Check `@vitejs/devtools`
|
|
217
|
-
- `@devframes/hub
|
|
218
|
-
-
|
|
246
|
+
- Check the peer range `@vitejs/devtools` declares against the Vite version this repository pins. `@vitejs/devtools` 0.6.x and 0.7.x have at times shipped outside the range `vite` itself declares for it, so a newer devtools version doesn't always work with the pinned Vite.
|
|
247
|
+
- `@devframes/hub` and `@devframes/hub-ui` are transitive dependencies of `@vitejs/devtools`. A routine `pnpm update`, or a fresh install after a range widens, can move them without any `@vitejs/devtools` bump.
|
|
248
|
+
- After any bump, run `pnpm exec vitest run`, `pnpm run build`, and `pnpm run verify-packaging` again, then open every panel in the dock. The unit tests cover this package's capture and classification logic, not the dock's runtime.
|
|
219
249
|
|
|
220
250
|
## License
|
|
221
251
|
|