@visulima/dev-toolbar 1.0.10 → 1.0.12

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.
@@ -1,7 +1,7 @@
1
1
  import { Plugin } from 'vite';
2
- import { R as ReadFileOptions } from "./packem_shared/server.d-ZkcY0pge.js";
3
- import { D as DevToolbarApp, S as ServerFunctions } from "./packem_shared/app.d-SmKEDxsI.js";
4
- import "./packem_shared/global-api.d-DeaCvII9.js";
2
+ import { R as ReadFileOptions } from "./packem_shared/server.d-CF1fcO17.js";
3
+ import { D as DevToolbarApp, S as ServerFunctions } from "./packem_shared/app.d-BV5WIojP.js";
4
+ import "./packem_shared/global-api.d-PUBE6Od9.js";
5
5
  import '@babel/generator';
6
6
  import 'preact';
7
7
  interface InjectSourceIgnore {
@@ -11,23 +11,23 @@ interface InjectSourceIgnore {
11
11
  files?: (RegExp | string)[];
12
12
  }
13
13
  /**
14
- * Dev toolbar plugin options
15
- */
14
+ * Dev toolbar plugin options
15
+ */
16
16
  interface DevToolbarOptions {
17
17
  /**
18
- * append an import to the module id ending with `appendTo` instead of adding a script into body
19
- * useful for projects that do not use html file as an entry
20
- *
21
- * WARNING: only set this if you know exactly what it does.
22
- * @default Empty string (disabled).
23
- */
18
+ * append an import to the module id ending with `appendTo` instead of adding a script into body
19
+ * useful for projects that do not use html file as an entry
20
+ *
21
+ * WARNING: only set this if you know exactly what it does.
22
+ * @default Empty string (disabled).
23
+ */
24
24
  appendTo?: string | RegExp;
25
25
  /**
26
- * Built-in apps to enable. All apps are disabled by default — only
27
- * `viteConfig`, `settings`, and the "more" drawer are shown out of the box.
28
- * Explicitly set an app to `true` to enable it.
29
- * @example { inspector: true, seo: true }
30
- */
26
+ * Built-in apps to enable. All apps are disabled by default — only
27
+ * `viteConfig`, `settings`, and the "more" drawer are shown out of the box.
28
+ * Explicitly set an app to `true` to enable it.
29
+ * @example { inspector: true, seo: true }
30
+ */
31
31
  apps?: {
32
32
  [key: string]: boolean | undefined;
33
33
  a11y?: boolean;
@@ -43,66 +43,66 @@ interface DevToolbarOptions {
43
43
  viteConfig?: boolean;
44
44
  };
45
45
  /**
46
- * Whether clicking outside the DevTools panel closes it.
47
- * @default true
48
- */
46
+ * Whether clicking outside the DevTools panel closes it.
47
+ * @default true
48
+ */
49
49
  closeOnOutsideClick?: boolean;
50
50
  /**
51
- * Custom apps to register
52
- */
51
+ * Custom apps to register
52
+ */
53
53
  customApps?: DevToolbarApp[];
54
54
  /**
55
- * Whether toolbar is visible by default
56
- */
55
+ * Whether toolbar is visible by default
56
+ */
57
57
  defaultVisible?: boolean;
58
58
  /**
59
- * The editor to open when clicking "Open in editor" in the inspector.
60
- * Accepts any value supported by `launch-editor` — an editor name/alias
61
- * (e.g. `"code"`, `"webstorm"`, `"vim"`, `"atom"`) or the full path to
62
- * the editor executable.
63
- *
64
- * If omitted, `launch-editor` auto-detects the editor from the `EDITOR`
65
- * / `VISUAL` environment variables or from the currently running IDE
66
- * process detected on the OS process list.
67
- * @example "webstorm"
68
- * @example "code"
69
- */
59
+ * The editor to open when clicking "Open in editor" in the inspector.
60
+ * Accepts any value supported by `launch-editor` — an editor name/alias
61
+ * (e.g. `"code"`, `"webstorm"`, `"vim"`, `"atom"`) or the full path to
62
+ * the editor executable.
63
+ *
64
+ * If omitted, `launch-editor` auto-detects the editor from the `EDITOR`
65
+ * / `VISUAL` environment variables or from the currently running IDE
66
+ * process detected on the OS process list.
67
+ * @example "webstorm"
68
+ * @example "code"
69
+ */
70
70
  editor?: string;
71
71
  /**
72
- * Master switch for the whole plugin. When `false`, `devToolbar()` returns an
73
- * empty plugin array, so no virtual modules, RPC server, or client overlay are
74
- * registered — the equivalent of removing the plugin from `vite.config.ts`
75
- * without editing the config.
76
- *
77
- * Handy for CI/preview environments:
78
- * `devToolbar({ enabled: !process.env.CI })`.
79
- * @default true
80
- */
72
+ * Master switch for the whole plugin. When `false`, `devToolbar()` returns an
73
+ * empty plugin array, so no virtual modules, RPC server, or client overlay are
74
+ * registered — the equivalent of removing the plugin from `vite.config.ts`
75
+ * without editing the config.
76
+ *
77
+ * Handy for CI/preview environments:
78
+ * `devToolbar({ enabled: !process.env.CI })`.
79
+ * @default true
80
+ */
81
81
  enabled?: boolean;
82
82
  /**
83
- * Initial panel height as a percentage of the viewport height (20–95).
84
- * @default 60
85
- */
83
+ * Initial panel height as a percentage of the viewport height (20–95).
84
+ * @default 60
85
+ */
86
86
  height?: number;
87
87
  /**
88
- * Inject `data-vdt-source="<file>:<line>:<col>"` attributes into every JSX
89
- * opening element during development. This lets the inspector jump directly
90
- * to the source file when an element is clicked.
91
- *
92
- * Only active when `mode === 'development'`. Set `enabled: false` to opt out.
93
- * Use `ignore.files` / `ignore.components` to exclude specific paths or
94
- * component names (strings are treated as glob patterns).
95
- * @default { enabled: true }
96
- */
88
+ * Inject `data-vdt-source="<file>:<line>:<col>"` attributes into every JSX
89
+ * opening element during development. This lets the inspector jump directly
90
+ * to the source file when an element is clicked.
91
+ *
92
+ * Only active when `mode === 'development'`. Set `enabled: false` to opt out.
93
+ * Use `ignore.files` / `ignore.components` to exclude specific paths or
94
+ * component names (strings are treated as glob patterns).
95
+ * @default { enabled: true }
96
+ */
97
97
  injectSource?: {
98
98
  enabled?: boolean;
99
99
  ignore?: InjectSourceIgnore;
100
100
  };
101
101
  /**
102
- * Keyboard shortcut bindings.
103
- * These are project-level defaults; users can still override them via the
104
- * Settings app (stored in localStorage).
105
- */
102
+ * Keyboard shortcut bindings.
103
+ * These are project-level defaults; users can still override them via the
104
+ * Settings app (stored in localStorage).
105
+ */
106
106
  keybindings?: {
107
107
  /** Close active app / panel. \@default "Escape" */
108
108
  close?: string;
@@ -110,77 +110,77 @@ interface DevToolbarOptions {
110
110
  toggle?: string;
111
111
  };
112
112
  /**
113
- * Auto-hide the toolbar pill after this many milliseconds of inactivity.
114
- * Set to -1 to never auto-hide.
115
- * @default 5000
116
- */
113
+ * Auto-hide the toolbar pill after this many milliseconds of inactivity.
114
+ * Set to -1 to never auto-hide.
115
+ * @default 5000
116
+ */
117
117
  minimizePanelInactive?: number;
118
118
  /**
119
- * Toolbar placement (coarse shorthand — sets the edge and rough horizontal
120
- * alignment of the toolbar pill).
121
- * @default "bottom-center"
122
- */
119
+ * Toolbar placement (coarse shorthand — sets the edge and rough horizontal
120
+ * alignment of the toolbar pill).
121
+ * @default "bottom-center"
122
+ */
123
123
  placement?: "bottom-left" | "bottom-center" | "bottom-right";
124
124
  /**
125
- * Which edge of the viewport the toolbar pill is anchored to.
126
- * Takes precedence over the edge implied by `placement`.
127
- * @default "bottom"
128
- */
125
+ * Which edge of the viewport the toolbar pill is anchored to.
126
+ * Takes precedence over the edge implied by `placement`.
127
+ * @default "bottom"
128
+ */
129
129
  position?: "bottom" | "left" | "right" | "top";
130
130
  /**
131
- * Policy for the built-in `readFile` RPC endpoint, which lets toolbar apps read
132
- * text files under the project root.
133
- *
134
- * Set to `false` to remove the endpoint entirely — recommended when the dev
135
- * server is exposed on the network (`vite --host`), since any device on the LAN
136
- * can then call RPC methods. Pass an object to override the allowed extensions.
137
- *
138
- * By default the endpoint is restricted to a curated allowlist of source/markup/
139
- * text extensions, so `.env`, lockfiles, and key material are never served.
140
- * @default { extensions: curated source/text list }
141
- */
131
+ * Policy for the built-in `readFile` RPC endpoint, which lets toolbar apps read
132
+ * text files under the project root.
133
+ *
134
+ * Set to `false` to remove the endpoint entirely — recommended when the dev
135
+ * server is exposed on the network (`vite --host`), since any device on the LAN
136
+ * can then call RPC methods. Pass an object to override the allowed extensions.
137
+ *
138
+ * By default the endpoint is restricted to a curated allowlist of source/markup/
139
+ * text extensions, so `.env`, lockfiles, and key material are never served.
140
+ * @default { extensions: curated source/text list }
141
+ */
142
142
  readFile?: ReadFileOptions | false;
143
143
  /**
144
- * Reduce motion for accessibility (disables all CSS animations).
145
- * @default false
146
- */
144
+ * Reduce motion for accessibility (disables all CSS animations).
145
+ * @default false
146
+ */
147
147
  reduceMotion?: boolean;
148
148
  /**
149
- * Strip all \@visulima/dev-toolbar imports and virtual modules when building
150
- * for production (i.e. when `command !== 'serve'` or `mode === 'production'`).
151
- * This guarantees the toolbar never ends up in a production bundle even if the
152
- * user accidentally imports our package in application code.
153
- * @default true
154
- */
149
+ * Strip all \@visulima/dev-toolbar imports and virtual modules when building
150
+ * for production (i.e. when `command !== 'serve'` or `mode === 'production'`).
151
+ * This guarantees the toolbar never ends up in a production bundle even if the
152
+ * user accidentally imports our package in application code.
153
+ * @default true
154
+ */
155
155
  removeDevtoolsOnBuild?: boolean;
156
156
  /**
157
- * Only activate the toolbar when the URL contains a specific query parameter.
158
- * Useful for staging/production environments where you want opt-in debugging.
159
- * @example requireUrlFlag: true, urlFlagName: 'debug' → toolbar only shows when URL has ?debug=true
160
- * @default false
161
- */
157
+ * Only activate the toolbar when the URL contains a specific query parameter.
158
+ * Useful for staging/production environments where you want opt-in debugging.
159
+ * @example requireUrlFlag: true, urlFlagName: 'debug' → toolbar only shows when URL has ?debug=true
160
+ * @default false
161
+ */
162
162
  requireUrlFlag?: boolean;
163
163
  /**
164
- * Custom server RPC functions
165
- */
164
+ * Custom server RPC functions
165
+ */
166
166
  serverFunctions?: Partial<ServerFunctions>;
167
167
  /**
168
- * The URL query parameter name used when requireUrlFlag is true.
169
- * @default 'devtools'
170
- */
168
+ * The URL query parameter name used when requireUrlFlag is true.
169
+ * @default 'devtools'
170
+ */
171
171
  urlFlagName?: string;
172
172
  /**
173
- * Initial panel width as a percentage of the viewport width (20–95).
174
- * Applies when position is "left" or "right".
175
- * @default 80
176
- */
173
+ * Initial panel width as a percentage of the viewport width (20–95).
174
+ * Applies when position is "left" or "right".
175
+ * @default 80
176
+ */
177
177
  width?: number;
178
178
  }
179
179
  /**
180
- * Returns the Vite plugin array for the dev toolbar.
181
- *
182
- * Returns an empty array when `options.enabled === false`, so the plugin can be
183
- * gated for CI/preview builds without removing it from `vite.config.ts`.
184
- */
180
+ * Returns the Vite plugin array for the dev toolbar.
181
+ *
182
+ * Returns an empty array when `options.enabled === false`, so the plugin can be
183
+ * gated for CI/preview builds without removing it from `vite.config.ts`.
184
+ */
185
185
  declare const devToolbar: (options?: DevToolbarOptions) => Plugin[];
186
186
  export { DevToolbarOptions, devToolbar };
@@ -1,5 +1,5 @@
1
- import{createRequire as O}from"node:module";import{normalizePath as R}from"vite";import{createServerRPCContext as N}from"./packem_shared/createServerRPCContext-0Fs78uvP.js";const M=O(import.meta.url),u=typeof globalThis<"u"&&typeof globalThis.process<"u"?globalThis.process:process,y=e=>{if(typeof u<"u"&&u.versions&&u.versions.node){const[p,f]=u.versions.node.split(".").map(Number);if(p>22||p===22&&f>=3||p===20&&f>=16)return u.getBuiltinModule(e)}return M(e)},S=y("node:fs"),x=y("node:path"),{fileURLToPath:I}=y("node:url"),P=()=>R(x.dirname(I(import.meta.url))),q=/\?.+$/,D=/\/dist\/|\/build\//,W=/\.[jt]sx$/,B=e=>e.replace(q,""),_="?__visulima-dev-toolbar-resource",b="virtual:visulima-dev-toolbar-options",j=`\0${b}`,m="virtual:visulima-dev-toolbar-path:",$="\0__visulima-dev-toolbar-empty",T=(e,p)=>typeof e!="number"||!Number.isFinite(e)?p:Math.min(95,Math.max(20,e)),U=(e={})=>{if(e.enabled===!1)return[];const p=P(),f=e.removeDevtoolsOnBuild??!0,C=e.injectSource?.enabled??!0;let v;const F={apply:"serve",config(){return{server:{watch:{ignored:["**/.devtoolbar/**"]}}}},configResolved(t){if(v=t,!e.appendTo){const o=new Set(t.plugins.map(i=>i.name));(o.has("tanstack-start-core:config")||o.has("tanstack-react-start:config"))&&(e.appendTo=/router\.tsx$/)}const n=/dev-toolbar[\\/]dist[\\/]|__visulima-dev-toolbar-resource/;for(const o of t.plugins){if(!o.name.includes("babel"))continue;const i=o.transform;if(!i)continue;const a=typeof i=="function"?i:typeof i=="object"&&"handler"in i?i.handler:void 0;if(typeof a!="function")continue;const s=function(c,r,...l){if(!n.test(r))return a.call(this,c,r,...l)};typeof i=="function"?o.transform=s:i.handler=s}},configureServer(t){N(t,e.serverFunctions,{editor:e.editor,readFile:e.readFile}),t.ws.on("connection",()=>{t.ws.send({event:"dev-toolbar:init",type:"custom"})}),t.middlewares.use("/__devtoolbar/events",async(n,o)=>{o.writeHead(200,{"Cache-Control":"no-cache",Connection:"keep-alive","Content-Type":"text/event-stream","X-Accel-Buffering":"no"});const i=(r,l)=>{o.write(`event: ${r}
1
+ import{createRequire as O}from"node:module";import{normalizePath as q}from"vite";import{createServerRPCContext as N}from"./packem_shared/createServerRPCContext-Mi6xw5Iz.js";let M;const R=e=>(M??=O(import.meta.url))(e),u=typeof globalThis<"u"&&typeof globalThis.process<"u"?globalThis.process:process,y=e=>{if(typeof u<"u"&&u.versions&&u.versions.node){const[p,f]=u.versions.node.split(".").map(Number);if(p>22||p===22&&f>=3||p===20&&f>=16)return u.getBuiltinModule(e)}return R(e)},S=y("node:fs"),x=y("node:path"),{fileURLToPath:I}=y("node:url"),P=()=>q(x.dirname(I(import.meta.url))),D=/\?.+$/,W=/\/dist\/|\/build\//,B=/\.[jt]sx$/,z=e=>e.replace(D,""),_="?__visulima-dev-toolbar-resource",b="virtual:visulima-dev-toolbar-options",$=`\0${b}`,m="virtual:visulima-dev-toolbar-path:",j="\0__visulima-dev-toolbar-empty",T=(e,p)=>typeof e!="number"||!Number.isFinite(e)?p:Math.min(95,Math.max(20,e)),E=(e={})=>{if(e.enabled===!1)return[];const p=P(),f=e.removeDevtoolsOnBuild??!0,C=e.injectSource?.enabled??!0;let v;const F={apply:"serve",config(){return{server:{watch:{ignored:["**/.devtoolbar/**"]}}}},configResolved(t){if(v=t,!e.appendTo){const o=new Set(t.plugins.map(i=>i.name));(o.has("tanstack-start-core:config")||o.has("tanstack-react-start:config"))&&(e.appendTo=/router\.tsx$/)}const n=/dev-toolbar[\\/]dist[\\/]|__visulima-dev-toolbar-resource/;for(const o of t.plugins){if(!o.name.includes("babel"))continue;const i=o.transform;if(!i)continue;const a=typeof i=="function"?i:typeof i=="object"&&"handler"in i?i.handler:void 0;if(typeof a!="function")continue;const s=function(c,r,...l){if(!n.test(r))return a.call(this,c,r,...l)};typeof i=="function"?o.transform=s:i.handler=s}},configureServer(t){N(t,e.serverFunctions,{editor:e.editor,readFile:e.readFile}),t.ws.on("connection",()=>{t.ws.send({event:"dev-toolbar:init",type:"custom"})}),t.middlewares.use("/__devtoolbar/events",async(n,o)=>{o.writeHead(200,{"Cache-Control":"no-cache",Connection:"keep-alive","Content-Type":"text/event-stream","X-Accel-Buffering":"no"});const i=(r,l)=>{o.write(`event: ${r}
2
2
  data: ${JSON.stringify(l)}
3
3
 
4
- `)};i("connected",{timestamp:Date.now()});const{watch:a}=await import("node:fs"),s=x.join(t.config.root,".devtoolbar","annotations.json");let c;try{c=a(s,{persistent:!1},r=>{r==="change"&&i("annotations.changed",{timestamp:Date.now()})}),c.on("error",()=>{})}catch{const{stat:r}=await import("node:fs/promises");let l=0;const h=setInterval(async()=>{try{const d=(await r(s)).mtimeMs;d!==l&&(l=d,i("annotations.changed",{timestamp:Date.now()}))}catch{}},2e3);n.on("close",()=>{clearInterval(h)});return}n.on("close",()=>{c?.close()})})},enforce:"pre",async load(t){if(t===j){const n=(e.customApps??[]).filter(o=>!o.component&&!o.init&&o.view?.type==="iframe").map(o=>({defaultOpen:o.defaultOpen,icon:o.icon,id:o.id,name:o.name,view:o.view}));return`export default ${JSON.stringify({apps:{a11y:e.apps?.a11y??!1,annotations:e.apps?.annotations??e.apps?.inspector??!1,assets:e.apps?.assets??!1,inspector:e.apps?.inspector??!1,moduleGraph:e.apps?.moduleGraph??!1,performance:e.apps?.performance??!1,seo:e.apps?.seo??!1,settings:e.apps?.settings??!0,tailwind:e.apps?.tailwind??!1,timeline:e.apps?.timeline??!1,viteConfig:e.apps?.viteConfig??!0},base:v.base,closeOnOutsideClick:e.closeOnOutsideClick??!0,customApps:n,defaultVisible:e.defaultVisible??!0,editor:e.editor??"",height:T(e.height,60),keybindings:e.keybindings??{},minimizePanelInactive:e.minimizePanelInactive??5e3,placement:e.placement??"bottom-center",position:e.position??"bottom",reduceMotion:e.reduceMotion??!1,requireUrlFlag:e.requireUrlFlag??!1,urlFlagName:e.urlFlagName??"devtools",width:T(e.width,80)})};`}if(t.endsWith(_)){const n=B(t);return this.addWatchFile(n),await S.promises.readFile(n,"utf8")}},name:"@visulima/dev-toolbar",resolveId(t){if(t===b)return j;if(t.startsWith(m))return`${t.replace(m,`${p}/`)}${_}`},transform(t,n,o){if(o?.ssr)return;const{appendTo:i}=e,a=n.split("?",2)[0];if(i&&a&&(typeof i=="string"&&a.endsWith(i)||i instanceof RegExp&&i.test(a)))return`import '${m}client/overlay.js';
5
- ${t}`},transformIndexHtml(){return e.appendTo?void 0:{html:"",tags:[{attrs:{src:`${v.base||"/"}@id/${m}client/overlay.js`,type:"module"},injectTo:"head-prepend",tag:"script"}]}}},k={apply(t,{command:n,mode:o}){return f&&(n!=="serve"||o==="production")},load(t){if(t===$)return"export default {};"},name:"@visulima/dev-toolbar:remove-on-build",resolveId(t){if(t===b||t.startsWith(m))return $}},w=new Map;return[F,{enforce:"pre",name:"@visulima/dev-toolbar:inject-source",async transform(t,n){if(!C||v.mode!=="development"||n.includes("node_modules")||n.includes("?raw")||D.test(n)||!W.test(n.split("?")[0]??""))return;const o=n.split("?")[0]??n,{readFile:i,stat:a}=await import("node:fs/promises");let s;try{const{mtimeMs:d}=await a(o);s=`${t.length}:${d}`;const g=w.get(n);if(g&&g.key===s)return g.result}catch{}let c;try{const d=await i(o,"utf8");d!==t&&(c=d)}catch{}const{addSourceToJsx:r}=await import("./packem_chunks/inject-source.js"),l=r(t,n,e.injectSource?.ignore,c),h=l?{code:l.code??t,map:l.map??void 0}:void 0;return s!==void 0&&w.set(n,{key:s,result:h}),h}},k]};export{U as devToolbar};
4
+ `)};i("connected",{timestamp:Date.now()});const{watch:a}=await import("node:fs"),s=x.join(t.config.root,".devtoolbar","annotations.json");let c;try{c=a(s,{persistent:!1},r=>{r==="change"&&i("annotations.changed",{timestamp:Date.now()})}),c.on("error",()=>{})}catch{const{stat:r}=await import("node:fs/promises");let l=0;const h=setInterval(async()=>{try{const d=(await r(s)).mtimeMs;d!==l&&(l=d,i("annotations.changed",{timestamp:Date.now()}))}catch{}},2e3);n.on("close",()=>{clearInterval(h)});return}n.on("close",()=>{c?.close()})})},enforce:"pre",async load(t){if(t===$){const n=(e.customApps??[]).filter(o=>!o.component&&!o.init&&o.view?.type==="iframe").map(o=>({defaultOpen:o.defaultOpen,icon:o.icon,id:o.id,name:o.name,view:o.view}));return`export default ${JSON.stringify({apps:{a11y:e.apps?.a11y??!1,annotations:e.apps?.annotations??e.apps?.inspector??!1,assets:e.apps?.assets??!1,inspector:e.apps?.inspector??!1,moduleGraph:e.apps?.moduleGraph??!1,performance:e.apps?.performance??!1,seo:e.apps?.seo??!1,settings:e.apps?.settings??!0,tailwind:e.apps?.tailwind??!1,timeline:e.apps?.timeline??!1,viteConfig:e.apps?.viteConfig??!0},base:v.base,closeOnOutsideClick:e.closeOnOutsideClick??!0,customApps:n,defaultVisible:e.defaultVisible??!0,editor:e.editor??"",height:T(e.height,60),keybindings:e.keybindings??{},minimizePanelInactive:e.minimizePanelInactive??5e3,placement:e.placement??"bottom-center",position:e.position??"bottom",reduceMotion:e.reduceMotion??!1,requireUrlFlag:e.requireUrlFlag??!1,urlFlagName:e.urlFlagName??"devtools",width:T(e.width,80)})};`}if(t.endsWith(_)){const n=z(t);return this.addWatchFile(n),await S.promises.readFile(n,"utf8")}},name:"@visulima/dev-toolbar",resolveId(t){if(t===b)return $;if(t.startsWith(m))return`${t.replace(m,`${p}/`)}${_}`},transform(t,n,o){if(o?.ssr)return;const{appendTo:i}=e,a=n.split("?",2)[0];if(i&&a&&(typeof i=="string"&&a.endsWith(i)||i instanceof RegExp&&i.test(a)))return`import '${m}client/overlay.js';
5
+ ${t}`},transformIndexHtml(){return e.appendTo?void 0:{html:"",tags:[{attrs:{src:`${v.base||"/"}@id/${m}client/overlay.js`,type:"module"},injectTo:"head-prepend",tag:"script"}]}}},k={apply(t,{command:n,mode:o}){return f&&(n!=="serve"||o==="production")},load(t){if(t===j)return"export default {};"},name:"@visulima/dev-toolbar:remove-on-build",resolveId(t){if(t===b||t.startsWith(m))return j}},w=new Map;return[F,{enforce:"pre",name:"@visulima/dev-toolbar:inject-source",async transform(t,n){if(!C||v.mode!=="development"||n.includes("node_modules")||n.includes("?raw")||W.test(n)||!B.test(n.split("?")[0]??""))return;const o=n.split("?")[0]??n,{readFile:i,stat:a}=await import("node:fs/promises");let s;try{const{mtimeMs:d}=await a(o);s=`${t.length}:${d}`;const g=w.get(n);if(g&&g.key===s)return g.result}catch{}let c;try{const d=await i(o,"utf8");d!==t&&(c=d)}catch{}const{addSourceToJsx:r}=await import("./packem_chunks/inject-source.js"),l=r(t,n,e.injectSource?.ignore,c),h=l?{code:l.code??t,map:l.map??void 0}:void 0;return s!==void 0&&w.set(n,{key:s,result:h}),h}},k]};export{E as devToolbar};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@visulima/dev-toolbar",
3
- "version": "1.0.10",
3
+ "version": "1.0.12",
4
4
  "description": "Devtools is a set of tools for building advanced devtools for your application",
5
5
  "keywords": [
6
6
  "dev-toolbar",
@@ -1 +0,0 @@
1
- import{createRequire as f}from"node:module";const p=f(import.meta.url),i=typeof globalThis<"u"&&typeof globalThis.process<"u"?globalThis.process:process,h=e=>{if(typeof i<"u"&&i.versions&&i.versions.node){const[s,t]=i.versions.node.split(".").map(Number);if(s>22||s===22&&t>=3||s===20&&t>=16)return i.getBuiltinModule(e)}return p(e)},o=h("node:fs/promises"),n=h("node:path"),y=".devtoolbar",A="annotations.json",_="screenshots",m=1e3,l=500,u=1e5;function g(e){return typeof e=="string"&&e.length>u?e.slice(0,u):e}const c=e=>{const s=n.join(e,y);return{annotationsFile:n.join(s,A),base:s,screenshotsDir:n.join(s,_)}},S=(e,s)=>{const t=n.resolve(e),r=n.resolve(s);return t.startsWith(r+n.sep)||t===r},N=e=>e.replaceAll(/[^a-z0-9-]/gi,""),T=async e=>{const{screenshotsDir:s}=c(e);await o.mkdir(s,{recursive:!0})};let d=Promise.resolve();const j=async e=>{const s=d;let t;d=new Promise(r=>{t=r}),await s;try{return await e()}finally{t()}},v=async e=>{const{annotationsFile:s}=c(e);try{const t=await o.readFile(s,"utf8"),r=JSON.parse(t);return Array.isArray(r)?r.slice(0,m).map(a=>Array.isArray(a?.thread)&&a.thread.length>l?{...a,thread:a.thread.slice(0,l)}:a):[]}catch{return[]}},E=async(e,s)=>{await T(e);const{annotationsFile:t}=c(e);await o.writeFile(t,JSON.stringify(s,void 0,2),"utf8")},F=async(e,s)=>{if(!s.startsWith(`${_}/`))return;const{base:t}=c(e),r=n.join(t,s);if(S(r,t))try{await o.unlink(r)}catch{}};export{l as M,_ as S,c as a,E as b,g as c,F as d,T as e,m as f,S as i,v as r,N as s,j as w};
@@ -1,229 +0,0 @@
1
- import { ComponentType } from 'preact';
2
- /**
3
- * Toolbar placement options (for backward compatibility)
4
- */
5
- type ToolbarPlacement = "top-left" | "top-center" | "top-right" | "bottom-left" | "bottom-center" | "bottom-right";
6
- /**
7
- * Notification levels
8
- */
9
- type NotificationLevel = "info" | "warning" | "error";
10
- /**
11
- * Position anchor (which edge the toolbar is attached to)
12
- * Matches Vue DevTools positioning
13
- */
14
- type PositionAnchor = "top" | "bottom" | "left" | "right";
15
- /**
16
- * Frame state - matches Vue DevTools DevToolsFrameState
17
- * @see https://github.com/vuejs/devtools/blob/main/packages/overlay/src/composables/state.ts
18
- */
19
- interface FrameState {
20
- /**
21
- * Horizontal position as percentage (0-100)
22
- */
23
- left: number;
24
- /**
25
- * Whether panel is open
26
- */
27
- open: boolean;
28
- /**
29
- * Which edge the toolbar is anchored to
30
- */
31
- position: PositionAnchor;
32
- /**
33
- * Vertical position as percentage (0-100)
34
- */
35
- top: number;
36
- }
37
- /**
38
- * Configuration options controlling the toolbar's initial appearance.
39
- */
40
- interface ToolbarSettings {
41
- /**
42
- * Whether toolbar is visible by default
43
- */
44
- defaultVisible: boolean;
45
- /**
46
- * Toolbar placement on screen
47
- */
48
- placement: ToolbarPlacement;
49
- /**
50
- * Whether to show notifications
51
- */
52
- showNotifications: boolean;
53
- }
54
- /**
55
- * Default toolbar settings
56
- */
57
- declare const DEFAULT_TOOLBAR_SETTINGS: ToolbarSettings;
58
- /**
59
- * Server helpers available to apps
60
- */
61
- interface ServerHelpers {
62
- /**
63
- * RPC client for calling server functions
64
- */
65
- rpc: { [K in keyof ServerFunctions]: ServerFunctions[K] };
66
- }
67
- /**
68
- * Props passed to app tooltip (hover mini-canvas) components.
69
- * Keep compact — tooltip components should be lightweight.
70
- */
71
- interface AppTooltipProps {
72
- /**
73
- * Server helpers (RPC, etc.)
74
- */
75
- helpers: ServerHelpers;
76
- }
77
- /**
78
- * Event target for app communication
79
- */
80
- interface ToolbarAppEventTarget extends EventTarget {
81
- /**
82
- * Dispatch a custom event
83
- */
84
- dispatchEvent: (event: Event) => boolean;
85
- }
86
- /**
87
- * App view configuration
88
- */
89
- type AppView = {
90
- /**
91
- * Render app inline in shadow DOM (default)
92
- */
93
- type: "inline";
94
- } | {
95
- /**
96
- * URL to load in iframe
97
- */
98
- src: string;
99
- /**
100
- * Render app in iframe for isolation
101
- */
102
- type: "iframe";
103
- };
104
- /**
105
- * Props passed to Preact component apps
106
- */
107
- interface AppComponentProps {
108
- /**
109
- * Event target for app communication
110
- */
111
- eventTarget: ToolbarAppEventTarget;
112
- /**
113
- * Server helpers (RPC, etc.)
114
- */
115
- helpers: ServerHelpers;
116
- }
117
- /**
118
- * Dev toolbar app definition
119
- */
120
- interface DevToolbarApp {
121
- /**
122
- * Called before app is toggled off
123
- * Return false to prevent closing
124
- * @param canvas Shadow root of the app
125
- * @returns Whether to allow closing
126
- */
127
- beforeTogglingOff?: (canvas: ShadowRoot) => boolean | Promise<boolean>;
128
- /**
129
- * Preact component for rendering (alternative to init)
130
- * If provided, this will be used instead of init
131
- */
132
- component?: ComponentType<AppComponentProps>;
133
- /**
134
- * When true, this app is automatically activated when the toolbar opens for
135
- * the first time (or when no other app has been activated yet).
136
- * Only the first registered app with defaultOpen: true is used.
137
- * @default false
138
- */
139
- defaultOpen?: boolean;
140
- /**
141
- * Called when the app is unregistered / removed from the toolbar.
142
- * Use this for final cleanup (event listeners, timers, subscriptions).
143
- * @param canvas Shadow root of the app
144
- */
145
- destroy?: (canvas: ShadowRoot) => Promise<void> | void;
146
- /**
147
- * Icon HTML string (SVG)
148
- */
149
- icon: string;
150
- /**
151
- * Unique identifier for the app
152
- */
153
- id: string;
154
- /**
155
- * Initialize the app when opened (vanilla JS/CSS/HTML)
156
- * @param canvas Shadow root to render into
157
- * @param eventTarget Event target for app communication
158
- * @param helpers Server helpers (RPC, etc.)
159
- */
160
- init?: (canvas: ShadowRoot, eventTarget: ToolbarAppEventTarget, helpers: ServerHelpers) => void | Promise<void>;
161
- /**
162
- * Display name of the app
163
- */
164
- name: string;
165
- /**
166
- * Action button callback — called when the button is activated (active: false → true).
167
- * When present, clicking the toolbar button will NOT open a panel.
168
- * Instead the button toggles its active state and calls onClick (activate)
169
- * or onDeactivate (deactivate).
170
- */
171
- onClick?: () => Promise<void> | void;
172
- /**
173
- * Called when the action button is deactivated (active: true → false).
174
- * Only meaningful when onClick is also provided.
175
- */
176
- onDeactivate?: () => Promise<void> | void;
177
- /**
178
- * Optional hover tooltip component — renders a compact live preview when the
179
- * user hovers over this app's button in the toolbar pill.
180
- * The component should be small (≤280px wide) and self-contained.
181
- * If omitted, hovering shows the native title tooltip only.
182
- */
183
- tooltip?: ComponentType<AppTooltipProps>;
184
- /**
185
- * App rendering mode
186
- */
187
- view?: AppView;
188
- }
189
- /**
190
- * Internal app state (extends DevToolbarApp)
191
- */
192
- interface DevToolbarAppState extends DevToolbarApp {
193
- /**
194
- * Whether the app is currently active/open
195
- */
196
- active: boolean;
197
- /**
198
- * Whether this is a built-in app
199
- */
200
- builtIn: boolean;
201
- /**
202
- * Event target for this app
203
- */
204
- eventTarget: ToolbarAppEventTarget;
205
- /**
206
- * Notification state
207
- */
208
- notification: {
209
- /**
210
- * Notification level
211
- */
212
- level?: NotificationLevel;
213
- /**
214
- * Whether notification is active
215
- */
216
- state: boolean;
217
- };
218
- /**
219
- * App initialization status
220
- */
221
- status: "ready" | "loading" | "pending" | "error";
222
- }
223
- /**
224
- * Placeholder for ServerFunctions (defined in rpc.ts)
225
- */
226
- interface ServerFunctions {
227
- [key: string]: (...args: any[]) => Promise<any>;
228
- }
229
- export { AppView as A, DevToolbarApp as D, FrameState as F, NotificationLevel as N, PositionAnchor as P, ServerFunctions as S, ToolbarSettings as T, DevToolbarAppState as a, DEFAULT_TOOLBAR_SETTINGS as b, ServerHelpers as c, ToolbarAppEventTarget as d, ToolbarPlacement as e };
@@ -1 +0,0 @@
1
- import{createRequire as k}from"node:module";import{w as b,r as h,c as p,d as E,M as S,b as x,e as R,a as P,s as _,i as v,S as F,f as j}from"./annotation-store-WIJhHG5y.js";import{normalizePath as $}from"vite";const O=k(import.meta.url),f=typeof globalThis<"u"&&typeof globalThis.process<"u"?globalThis.process:process,w=r=>{if(typeof f<"u"&&f.versions&&f.versions.node){const[e,t]=f.versions.node.split(".").map(Number);if(e>22||e===22&&t>=3||e===20&&t>=16)return f.getBuiltinModule(r)}return O(r)},m=w("node:fs/promises"),u=w("node:path"),{createRequire:z}=w("node:module"),B=async r=>h(r.config.root),L=async(r,e)=>b(async()=>{const{root:t}=r.config,s=new Date().toISOString(),o=await h(t);if(o.length>=j)throw new Error(`Annotation limit reached (${j}). Resolve or delete existing annotations before creating new ones.`);const n={accessibility:e.accessibility,boundingBox:e.boundingBox,comment:p(e.comment),computedStyles:p(e.computedStyles),createdAt:s,cssClasses:p(e.cssClasses),elementBoundingBoxes:e.elementBoundingBoxes,elementLabel:p(e.elementLabel),elementPath:p(e.elementPath),elementTag:e.elementTag,frameworkContext:e.frameworkContext,fullPath:p(e.fullPath),id:crypto.randomUUID(),intent:e.intent,isFixed:e.isFixed,isMultiSelect:e.isMultiSelect,nearbyElements:p(e.nearbyElements),nearbyText:p(e.nearbyText),screenshot:e.screenshot,selectedText:p(e.selectedText),severity:e.severity,source:e.source,status:"pending",updatedAt:s,url:e.url,x:e.x,y:e.y};return o.push(n),await x(t,o),n}),W=async(r,e,t)=>b(async()=>{const{root:s}=r.config,o=await h(s),n=o.findIndex(c=>c.id===e);if(n===-1)return null;const i=o[n],a=new Date().toISOString();if(t.comment!==void 0&&(i.comment=p(t.comment)),t.intent!==void 0&&(i.intent=t.intent),t.severity!==void 0&&(i.severity=t.severity),t.status!==void 0&&(i.status=t.status,(t.status==="resolved"||t.status==="dismissed")&&(i.resolvedBy=t.resolvedBy??"human",i.resolvedAt=a,i.screenshot&&(await E(s,i.screenshot),i.screenshot=void 0))),t.threadMessage){if(i.thread||(i.thread=[]),i.thread.length>=S)throw new Error(`Thread message limit reached (${S}) for this annotation.`);i.thread.push({...t.threadMessage,content:p(t.threadMessage.content),id:crypto.randomUUID(),timestamp:a})}return i.updatedAt=a,o[n]=i,await x(s,o),i}),U=async(r,e)=>b(async()=>{const{root:t}=r.config,s=await h(t),o=s.findIndex(i=>i.id===e);if(o===-1)return!1;const n=s[o];return n.screenshot&&await E(t,n.screenshot),s.splice(o,1),await x(t,s),!0}),q=async(r,e,t)=>{const{root:s}=r.config;await R(s);const{base:o,screenshotsDir:n}=P(s),i=_(e);if(!i)throw new Error("Invalid annotation ID");let a,c;if(t.startsWith("data:image/png;base64,"))a="png",c=Buffer.from(t.slice(22),"base64");else if(t.startsWith("data:image/jpeg;base64,"))a="jpg",c=Buffer.from(t.slice(23),"base64");else if(t.startsWith("data:image/webp;base64,"))a="webp",c=Buffer.from(t.slice(23),"base64");else throw new Error("Unsupported screenshot format. Expected PNG, JPEG, or WebP data URL.");const l=`${i}.${a}`,d=u.join(n,l);if(!v(d,o))throw new Error("Invalid screenshot path");return await m.writeFile(d,c),`${F}/${l}`},G=async(r,e)=>{const{root:t}=r.config,s=(await h(t)).find(i=>i.id===e);if(!s?.screenshot||!s.screenshot.startsWith(`${F}/`))return null;const{base:o}=P(t),n=u.join(o,s.screenshot);if(!v(n,o))return null;try{const i=await m.readFile(n),a=u.extname(n).slice(1);return a==="svg"?`data:image/svg+xml,${encodeURIComponent(i.toString("utf8"))}`:`data:${a==="jpg"?"image/jpeg":`image/${a}`};base64,${i.toString("base64")}`}catch{return null}},N=new Set(["apng","avif","bmp","gif","ico","jpeg","jpg","png","svg","tiff","webp"]),H=new Set(["avi","mkv","mov","mp4","ogv","webm"]),X=new Set(["aac","flac","m4a","mp3","ogg","opus","wav"]),J=new Set(["eot","otf","ttf","woff","woff2"]),V=new Set(["css","csv","html","js","json","md","txt","xml"]),g=5e3,A=r=>{const e=r.toLowerCase();return N.has(e)?"image":H.has(e)?"video":X.has(e)?"audio":J.has(e)?"font":V.has(e)?"text":"other"},K=r=>{let e=0;const t=[];return{acquire:()=>new Promise(s=>{e<r?(e+=1,s()):t.push(()=>{e+=1,s()})}),release:()=>{e-=1,t.shift()?.()}}},T=async(r,e,t,s)=>{if(s.length>=g)return;let o;await t.acquire();try{o=await m.readdir(r,{withFileTypes:!0})}catch{return}finally{t.release()}await Promise.all(o.map(async n=>{if(s.length>=g)return;const i=u.join(r,n.name);if(n.isDirectory())await T(i,e,t,s);else if(n.isFile()||n.isSymbolicLink()){await t.acquire();try{const a=await m.lstat(i);if(a.isSymbolicLink()){let c;try{c=await m.realpath(i)}catch{return}if(!c.startsWith(e+u.sep)&&c!==e)return;const l=await m.stat(i),d=u.relative(e,i),C=`/${$(d)}`,M=u.extname(n.name).slice(1);s.length<g&&s.push({mtime:l.mtimeMs,publicPath:C,size:l.size,type:A(M)})}else if(a.isFile()){const c=u.relative(e,i),l=`/${$(c)}`,d=u.extname(n.name).slice(1);s.length<g&&s.push({mtime:a.mtimeMs,publicPath:l,size:a.size,type:A(d)})}}catch{}finally{t.release()}}}))},Q=async r=>{const{publicDir:e}=r.config;if(!e)return[];let t;try{t=await m.realpath(e)}catch{return[]}const s=[],o=K(20);return await T(t,t,o,s),s.sort((n,i)=>n.publicPath.localeCompare(i.publicPath)),s},Y=async r=>{const{moduleGraph:e}=r,t=[];for(const s of e.idToModuleMap.values()){if(t.length>=5e3)break;const o=s.id??s.url,n=s.url??s.id;if(!o||!n||o.startsWith("/@"))continue;const i=[];s.importers.forEach(a=>{const c=a.url??a.id;c&&i.push(c)}),t.push({id:o,importerCount:s.importers.size,importerUrls:i,url:n})}return t},Z=async(r,e,t,s,o)=>{const n=u.resolve(r.config.root,e);if(!v(n,r.config.root))throw new Error(`Refusing to open file outside project root: ${e}`);const i=s===void 0?"":`:${s}`,a=t===void 0?"":`:${t}${i}`,c=`${n}${a}`,{default:l}=await import("launch-editor");l(c,o)},ee=/\/\*[\s\S]*?\*\//g,te=/\s+/g,D=/@theme\s+default[^{]*\{[\s\S]*?\}/g,y=/(--[\w-]+)\s*:\s*([\s\S]*?);/g,I=r=>{const e={},t=r.replaceAll(ee,"");let s=0;for(;s<t.length;){const o=t.indexOf("@theme",s);if(o===-1)break;const n=t.indexOf("{",o);if(n===-1)break;let i=1,a=n+1;for(;a<t.length&&i>0;)t[a]==="{"?i+=1:t[a]==="}"&&(i-=1),a+=1;const c=t.slice(n+1,a-1);y.lastIndex=0;let l=y.exec(c);for(;l!==null;){const d=l[2].replaceAll(te," ").trim();d&&!e[l[1]]&&(e[l[1]]=d),l=y.exec(c)}s=a}return e},se=async r=>{const e=[],t=async(s,o)=>{if(o>4)return;let n;try{n=await m.readdir(s,{encoding:"utf8",withFileTypes:!0})}catch{return}for(const i of n){const a=u.join(s,i.name);if(i.isDirectory()){if(i.name==="node_modules"||i.name===".git"||i.name==="dist")continue;await t(a,o+1)}else if(i.name.endsWith(".css"))try{const c=await m.readFile(a,"utf8");c.includes("@import")&&(c.includes('"tailwindcss"')||c.includes("'tailwindcss'"))&&e.push(a)}catch{}}};return await t(r,0),e},re=async r=>{const e={};for(const t of r)try{const s=await m.readFile(t,"utf8");D.lastIndex=0;const o=s.replaceAll(D,""),n=I(o);Object.assign(e,n)}catch{}return e},ne=async r=>{const{root:e}=r.config;let t="unknown",s={};const o=["tailwind.config.js","tailwind.config.ts","tailwind.config.mjs","tailwind.config.cjs"];for(const a of o)try{await m.access(u.join(e,a)),t="v3";break}catch{}try{const a=z(import.meta.url).resolve("tailwindcss/theme.css"),c=await m.readFile(a,"utf8");s=I(c),Object.keys(s).length>0&&t!=="v3"&&(t="v4")}catch{}const n=await se(e),i=await re(n);return{cssFiles:n.map(a=>u.relative(e,a)),customTheme:i,defaultTheme:s,version:t}},ie=r=>{if(Array.isArray(r))return r.filter(e=>e!=null&&(e.find!==void 0||e.replacement!==void 0)).map(e=>({find:e.find instanceof RegExp?e.find.toString():String(e.find??""),replacement:String(e.replacement??"")}));if(r!=null&&typeof r=="object")return Object.fromEntries(Object.entries(r).map(([e,t])=>[e,String(t)]))},oe=r=>{if(typeof r=="boolean"||Array.isArray(r))return r},ae=async r=>{const{config:e}=r,t=[];for(const l of e.plugins.filter(d=>!!d?.name))t.push({enforce:l?.enforce,name:l.name});const s=ie(e.resolve?.alias),o=e.server?.proxy?Object.keys(e.server.proxy):void 0,n=e.server?.hmr,i=n!==!1,a=typeof n=="object"&&n!==null?n.port:void 0,c=oe(e.ssr?.noExternal);return{base:e.base,build:{assetsDir:e.build?.assetsDir,assetsInlineLimit:typeof e.build?.assetsInlineLimit=="number"?e.build.assetsInlineLimit:void 0,chunkSizeWarningLimit:e.build?.chunkSizeWarningLimit,cssCodeSplit:e.build?.cssCodeSplit,emptyOutDir:e.build?.emptyOutDir,minify:e.build?.minify,outDir:e.build?.outDir,reportCompressedSize:e.build?.reportCompressedSize,sourcemap:e.build?.sourcemap,target:e.build?.target},cacheDir:e.cacheDir,css:{devSourcemap:e.css?.devSourcemap,preprocessors:e.css?.preprocessorOptions?Object.keys(e.css.preprocessorOptions):[]},define:e.define,env:e.env,envDir:typeof e.envDir=="string"?e.envDir:void 0,envPrefix:e.envPrefix,esbuild:e.esbuild?{jsx:e.esbuild.jsx,jsxFactory:e.esbuild.jsxFactory,jsxFragment:e.esbuild.jsxFragment,jsxImportSource:e.esbuild.jsxImportSource,target:e.esbuild.target}:void 0,mode:e.mode,optimizeDeps:{exclude:e.optimizeDeps?.exclude,include:e.optimizeDeps?.include},plugins:t,publicDir:e.publicDir,resolve:{alias:s,conditions:e.resolve?.conditions,dedupe:e.resolve?.dedupe,extensions:e.resolve?.extensions,mainFields:e.resolve?.mainFields,preserveSymlinks:e.resolve?.preserveSymlinks},root:e.root,server:{cors:e.server?.cors===void 0?void 0:!!e.server.cors,hmrEnabled:i,hmrPort:a,host:e.server?.host,https:e.server?.https!==void 0,middlewareMode:(()=>{if(e.server?.middlewareMode!==void 0)return typeof e.server.middlewareMode=="object"?!0:!!e.server.middlewareMode})(),open:e.server?.open,origin:e.server?.origin,port:e.server?.port,proxy:o,strictPort:e.server?.strictPort},ssr:e.ssr===void 0?void 0:{external:Array.isArray(e.ssr?.external)?e.ssr.external:void 0,noExternal:c,target:e.ssr?.target}}},ce=["astro","cjs","css","cts","html","js","json","jsx","less","md","mdx","mjs","mts","sass","scss","svelte","ts","tsx","txt","vue"],le=(r,e={})=>{const t={createAnnotation:async s=>L(r,s),deleteAnnotation:async s=>U(r,s),getAnnotations:async()=>B(r),getModuleGraph:async()=>Y(r),getScreenshot:async s=>G(r,s),getStaticAssets:async()=>Q(r),getTailwindConfig:async()=>ne(r),getViteConfig:async()=>ae(r),openInEditor:async(s,o,n)=>Z(r,s,o,n,e.editor),saveScreenshot:async(s,o)=>q(r,s,o),updateAnnotation:async(s,o)=>W(r,s,o)};if(e.readFile!==!1){const s=new Set((e.readFile?.extensions??ce).map(o=>o.toLowerCase().replace(/^\./,"")));t.readFile=async o=>{const{readFile:n}=await import("node:fs/promises"),{extname:i,resolve:a}=await import("node:path"),{root:c}=r.config,l=a(c,o);if(!v(l,c))throw new Error(`Refusing to read file outside project root: ${o}`);const d=i(l).slice(1).toLowerCase();if(!s.has(d))throw new Error(`Refusing to read file with disallowed extension ".${d}": ${o}`);return n(l,"utf8")}}return t},pe=(r,e,t={})=>{const s={...le(r,t),...e};return r.ws.on("dev-toolbar:rpc",async(o,n)=>{const{args:i,id:a,method:c}=o,l=s[c];if(!l){n.send("dev-toolbar:rpc:error",{error:`Unknown RPC method: ${c}`,id:a});return}try{const d=await l(...i);n.send("dev-toolbar:rpc:response",{id:a,result:d})}catch(d){n.send("dev-toolbar:rpc:error",{error:d instanceof Error?d.message:String(d),id:a})}}),{callClient(o,...n){r.ws.send({data:{args:n,method:o},event:"dev-toolbar:client",type:"custom"})},registerFunction(o,n){s[o]=n},server:r}};export{pe as createServerRPCContext};
@@ -1,39 +0,0 @@
1
- import { ViteDevServer } from 'vite';
2
- import { S as ServerFunctions, a as ServerRPCContext } from "./global-api.d-DeaCvII9.js";
3
- /**
4
- * Configuration for the `readFile` RPC endpoint.
5
- */
6
- interface ReadFileOptions {
7
- /**
8
- * Lower-cased file extensions (without the dot) the `readFile` RPC may return.
9
- * Defaults to a curated list of source/markup/text formats — set this to widen
10
- * or narrow the surface. Sensitive formats (`.env`, `.pem`, lockfiles) are not
11
- * in the default list.
12
- */
13
- extensions?: string[];
14
- }
15
- /**
16
- * Options accepted by {@link createServerRPCContext}.
17
- */
18
- interface ServerRPCOptions {
19
- /** Editor to use for "open in editor" functionality. */
20
- editor?: string;
21
- /**
22
- * `readFile` RPC behaviour. Set to `false` to remove the endpoint entirely,
23
- * or pass an object to customise the allowed extensions.
24
- * @default { extensions: curated source/text list }
25
- */
26
- readFile?: ReadFileOptions | false;
27
- }
28
- /**
29
- * Creates server-side RPC context.
30
- * @param server Vite dev server instance.
31
- * @param customFunctions Custom server functions to register.
32
- * @param options Additional options (e.g. which editor to launch, readFile policy).
33
- * @param options.editor Editor to use for "open in editor" functionality.
34
- * @param options.readFile `readFile` RPC policy — `false` disables it, or pass an
35
- * object to override the allowed extension list.
36
- * @returns Server RPC context.
37
- */
38
- declare const createServerRPCContext: (server: ViteDevServer, customFunctions?: Partial<ServerFunctions>, options?: ServerRPCOptions) => ServerRPCContext;
39
- export { ReadFileOptions as R, ServerRPCOptions as S, createServerRPCContext as c };