@lensmcp/vite-plugin 1.21.5 → 1.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -8
- package/lib/event-mappers.js +2 -2
- package/lib/plugin.js +2 -2
- package/lib/types.d.ts +10 -0
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -34,15 +34,15 @@ export default defineConfig({
|
|
|
34
34
|
|
|
35
35
|
The plugin runs at `enforce: 'pre'`, so its source transform sees raw JSX/TSX before `@vitejs/plugin-react` (Babel), `@vitejs/plugin-react@6` (oxc), or `@vitejs/plugin-react-swc` (SWC) turn JSX into calls — it coexists with whichever React compiler you use.
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
It is dev-only on its own: the plugin attaches to `vite serve` and detaches from `vite build`, so a
|
|
38
|
+
production bundle carries none of it — no WebSocket bridge, no injected client runtime, no
|
|
39
|
+
`data-agent-source` attributes, no source paths. You do not need to gate it yourself.
|
|
40
|
+
|
|
41
|
+
If you deliberately want an instrumented build — a staging deploy you intend to point the lens at —
|
|
42
|
+
say so:
|
|
38
43
|
|
|
39
44
|
```ts
|
|
40
|
-
|
|
41
|
-
plugins: [
|
|
42
|
-
react(),
|
|
43
|
-
lensmcpVitePlugin({ enabled: command === 'serve' }),
|
|
44
|
-
],
|
|
45
|
-
}));
|
|
45
|
+
lensmcpVitePlugin({ applyOnBuild: true }); // or LENSMCP_VITE_APPLY_ON_BUILD=1
|
|
46
46
|
```
|
|
47
47
|
|
|
48
48
|
## What it does
|
|
@@ -60,7 +60,8 @@ Incoming browser envelopes and Vite/Rollup events are normalised into LensMCP's
|
|
|
60
60
|
|
|
61
61
|
| Option | Type | Default | Description |
|
|
62
62
|
| --- | --- | --- | --- |
|
|
63
|
-
| `enabled` | `boolean` | `true` | Whether the plugin attaches anything
|
|
63
|
+
| `enabled` | `boolean` | `true` | Whether the plugin attaches anything at all. |
|
|
64
|
+
| `applyOnBuild` | `boolean` | `false` | Also attach during `vite build`. Off by default — everything here is a development tool. `LENSMCP_VITE_APPLY_ON_BUILD=1` sets it too. |
|
|
64
65
|
| `wsPort` | `number` | ephemeral | WebSocket port the client runtime posts events to. An unused port is chosen automatically when omitted. |
|
|
65
66
|
| `wsHost` | `string` | `'127.0.0.1'` | Bind address for the WebSocket. |
|
|
66
67
|
| `injectClient` | `boolean` | `true` | Inject the client runtime via a `<script>` tag. |
|
package/lib/event-mappers.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var
|
|
2
|
-
`).slice(0,2);for(const o of
|
|
1
|
+
"use strict";var C=Object.defineProperty;var c=(e,n)=>C(e,"name",{value:n,configurable:!0});var F=Object.defineProperty,u=c((e,n)=>F(e,"name",{value:n,configurable:!0}),"c"),J=Object.defineProperty,v=u((e,n)=>J(e,"name",{value:n,configurable:!0}),"c"),L=Object.defineProperty,d=v((e,n)=>L(e,"name",{value:n,configurable:!0}),"l"),N=Object.defineProperty,m=d((e,n)=>N(e,"name",{value:n,configurable:!0}),"l"),q=Object.defineProperty,f=m((e,n)=>q(e,"name",{value:n,configurable:!0}),"c"),z=Object.defineProperty,p=f((e,n)=>z(e,"name",{value:n,configurable:!0}),"c"),B=Object.defineProperty,g=p((e,n)=>B(e,"name",{value:n,configurable:!0}),"c"),D=Object.defineProperty,y=g((e,n)=>D(e,"name",{value:n,configurable:!0}),"u"),G=Object.defineProperty,b=y((e,n)=>G(e,"name",{value:n,configurable:!0}),"u"),H=Object.defineProperty,j=b((e,n)=>H(e,"name",{value:n,configurable:!0}),"u"),K=Object.defineProperty,T=j((e,n)=>K(e,"name",{value:n,configurable:!0}),"c"),M=Object.defineProperty,E=T((e,n)=>M(e,"name",{value:n,configurable:!0}),"c"),Q=Object.defineProperty,O=E((e,n)=>Q(e,"name",{value:n,configurable:!0}),"c"),V=Object.defineProperty,P=O((e,n)=>V(e,"name",{value:n,configurable:!0}),"u"),W=Object.defineProperty,I=P((e,n)=>W(e,"name",{value:n,configurable:!0}),"u"),X=Object.defineProperty,w=I((e,n)=>X(e,"name",{value:n,configurable:!0}),"u"),Y=Object.defineProperty,k=w((e,n)=>Y(e,"name",{value:n,configurable:!0}),"u"),Z=Object.defineProperty,$=k((e,n)=>Z(e,"name",{value:n,configurable:!0}),"o"),_=Object.defineProperty,h=$((e,n)=>_(e,"name",{value:n,configurable:!0}),"o"),ee=Object.defineProperty,x=h((e,n)=>ee(e,"name",{value:n,configurable:!0}),"o"),ne=Object.defineProperty,S=x((e,n)=>ne(e,"name",{value:n,configurable:!0}),"o"),te=Object.defineProperty,U=S((e,n)=>te(e,"name",{value:n,configurable:!0}),"o"),re=Object.defineProperty,R=U((e,n)=>re(e,"name",{value:n,configurable:!0}),"o");import{fingerprint as s,ulid as l}from"@lensmcp/core";const ie="pending";export function envelopeToEvent(e,n=ie){const o=e.tabId?{tabId:e.tabId}:{};switch(e.kind){case"error":return{id:l(),sessionId:n,timestamp:e.at,source:"client-runtime",category:"runtime",severity:"error",context:{sessionId:n,...o},fingerprint:s({kind:"runtime",identity:`error:${t(e.stack)}`,file:e.source,detail:e.message}),title:e.message,message:e.stack??e.message,location:e.source?{file:e.source,line:e.lineno,column:e.colno}:void 0,raw:e};case"unhandledrejection":return{id:l(),sessionId:n,timestamp:e.at,source:"client-runtime",category:"runtime",severity:"error",context:{sessionId:n,...o},fingerprint:s({kind:"runtime",identity:`unhandledrejection:${e.reason.slice(0,80)}`}),title:"Unhandled promise rejection",message:e.reason,raw:e};case"console":{const a=e.level==="error"?"error":e.level==="warn"?"warning":"info",A=e.args.map(i).join(" ");return{id:l(),sessionId:n,timestamp:e.at,source:"client-runtime",category:"runtime",severity:a,context:{sessionId:n,...o},fingerprint:s({kind:"runtime",identity:`console:${e.level}:${A.slice(0,80)}`}),title:`console.${e.level}`,message:A,raw:e}}case"fetch":{const a=e.error!==void 0||e.status!==void 0&&e.status>=400;return{id:l(),sessionId:n,timestamp:e.at,source:"client-runtime",category:"network",severity:a?"error":"info",context:{sessionId:n,...o},fingerprint:s({kind:"network",identity:`${e.method}:${r(e.url)}:${e.status??"err"}`}),title:`${e.method} ${e.url}${e.status!==void 0?` \u2192 ${e.status}`:""}`,message:e.error,relatedUrls:[e.url],raw:e}}case"route":return{id:l(),sessionId:n,timestamp:e.at,source:"client-runtime",category:"runtime",severity:"info",context:{sessionId:n,url:e.url,...o},fingerprint:s({kind:"runtime",identity:`route:${e.url}`}),title:`Route \u2192 ${e.url}`,raw:e};case"ready":return{id:l(),sessionId:n,timestamp:e.at,source:"client-runtime",category:"runtime",severity:"info",context:{sessionId:n,url:e.url,...o},fingerprint:s({kind:"runtime",identity:"client-ready"}),title:"Client runtime ready",message:e.userAgent,raw:e};case"publish":return{id:l(),sessionId:n,timestamp:e.at,source:e.source,category:e.category,severity:e.severity??"info",context:{sessionId:n,...o,...e.context??{}},fingerprint:e.fingerprint??s({kind:"publish",identity:e.title}),title:e.title,message:e.message,raw:e.raw}}}c(envelopeToEvent,"envelopeToEvent"),u(envelopeToEvent,"envelopeToEvent"),v(envelopeToEvent,"envelopeToEvent"),d(envelopeToEvent,"envelopeToEvent"),m(envelopeToEvent,"envelopeToEvent"),f(envelopeToEvent,"envelopeToEvent"),p(envelopeToEvent,"envelopeToEvent"),g(envelopeToEvent,"envelopeToEvent"),y(envelopeToEvent,"envelopeToEvent"),b(envelopeToEvent,"envelopeToEvent"),j(envelopeToEvent,"envelopeToEvent"),T(envelopeToEvent,"envelopeToEvent"),E(envelopeToEvent,"envelopeToEvent"),O(envelopeToEvent,"envelopeToEvent"),P(envelopeToEvent,"envelopeToEvent"),I(envelopeToEvent,"envelopeToEvent"),w(envelopeToEvent,"envelopeToEvent"),k(envelopeToEvent,"envelopeToEvent"),$(envelopeToEvent,"envelopeToEvent"),h(envelopeToEvent,"envelopeToEvent"),x(envelopeToEvent,"envelopeToEvent"),S(envelopeToEvent,"envelopeToEvent"),U(envelopeToEvent,"envelopeToEvent"),R(envelopeToEvent,"envelopeToEvent");function t(e){if(!e)return"unknown";const n=e.split(`
|
|
2
|
+
`).slice(0,2);for(const o of n){const a=o.match(/at\s+(\S+)/);if(a&&a[1])return a[1]}return"unknown"}c(t,"n"),u(t,"t"),v(t,"n"),d(t,"t"),m(t,"n"),f(t,"t"),p(t,"n"),g(t,"t"),y(t,"r"),b(t,"t"),j(t,"r"),T(t,"t"),E(t,"n"),O(t,"n"),P(t,"r"),I(t,"n"),w(t,"o"),k(t,"a"),$(t,"l"),h(t,"l"),x(t,"c"),S(t,"c"),U(t,"s"),R(t,"normaliseStackTopFrame");function r(e){try{return`${new URL(e,"http://x").pathname}`}catch{return e}}c(r,"r"),u(r,"r"),v(r,"r"),d(r,"r"),m(r,"r"),f(r,"r"),p(r,"r"),g(r,"r"),y(r,"n"),b(r,"r"),j(r,"n"),T(r,"r"),E(r,"r"),O(r,"r"),P(r,"i"),I(r,"i"),w(r,"a"),k(r,"c"),$(r,"d"),h(r,"d"),x(r,"l"),S(r,"l"),U(r,"m"),R(r,"normaliseUrl");function i(e){if(typeof e=="string")return e;try{return JSON.stringify(e)}catch{return String(e)}}c(i,"i"),u(i,"i"),v(i,"i"),d(i,"i"),m(i,"i"),f(i,"i"),p(i,"i"),g(i,"i"),y(i,"i"),b(i,"i"),j(i,"i"),T(i,"i"),E(i,"i"),O(i,"i"),P(i,"o"),I(i,"o"),w(i,"c"),k(i,"u"),$(i,"m"),h(i,"m"),x(i,"d"),S(i,"d"),U(i,"d"),R(i,"stringify");
|
package/lib/plugin.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var V=Object.defineProperty;var p=(e,t)=>V(e,"name",{value:t,configurable:!0});var $=Object.defineProperty,d=p((e,t)=>$(e,"name",{value:t,configurable:!0}),"u");import{existsSync as U,readdirSync as q,statSync as J}from"node:fs";import{delimiter as K,join as O,relative as I,resolve as T,sep as A}from"node:path";import{fingerprint as C,ulid as R}from"@lensmcp/core";import{createBridgeServer as z,makePublisher as L,handleClientEnvelope as X}from"@lensmcp/bridge";const D="/@lensmcp/client-runtime",x="\0lensmcp-client-runtime",G="/__lensmcp/watcher-health",F=256,Y=64,Z=new Set(["node_modules",".git","dist","tmp","coverage","build","out","target",".nx",".lensmcp"]);export function resolveExtraWatchRoots(e,t){if(!e)return[];const o=T(t),m=d((u,g)=>{const l=I(g,u);return l!==""&&!l.startsWith("..")&&!l.startsWith(A)&&!/^[A-Za-z]:/.test(l)},"inside"),a=[],v=d(u=>{a.length<Y&&!a.includes(u)&&a.push(u)},"push");for(const u of e.split(K)){const g=u.trim();if(!g)continue;const l=T(g);let b;try{b=U(l)&&J(l).isDirectory()}catch{b=!1}if(b&&!(l===o||m(l,o))){if(m(o,l)){const _=I(l,o).split(A).filter(Boolean);let n=l;for(const i of _){let r;try{r=q(n,{withFileTypes:!0})}catch{r=[]}for(const c of r)!c.isDirectory()||c.name===i||c.name.startsWith(".")||Z.has(c.name)||v(O(n,c.name));n=O(n,i)}continue}v(l)}}return a}p(resolveExtraWatchRoots,"resolveExtraWatchRoots"),d(resolveExtraWatchRoots,"resolveExtraWatchRoots");export function lensmcpVitePlugin(e={},t={}){const o=e.enabled??!0,m=e.wsHost??"127.0.0.1",a=e.injectClient??!0;let v,u;const g=L(t),l=e.aliasValtio??!0,b=e.transformSource??!0,_=e.applyOnBuild??process.env.LENSMCP_VITE_APPLY_ON_BUILD==="1";return{name:"@lensmcp/vite-plugin",apply:d((n,i)=>o&&(i.command==="serve"||_),"apply"),enforce:"pre",wsPort:d(()=>v,"wsPort"),config(){if(!(!o||!l))return{resolve:{alias:[{find:/^valtio$/,replacement:"@lensmcp/valtio-instrumentation"}]}}},async configureServer(n){if(!o)return;u=await z({host:m,port:e.wsPort??0,bus:t.bus,sessionId:t.sessionId}),v=u.port,n.ws.on("vite:error",s=>{g(j(s,t.sessionId))});const i=resolveExtraWatchRoots(process.env.LENSMCP_WATCH_DIRS,n.config?.root??process.cwd());if(i.length>0&&typeof n.watcher?.add=="function")try{n.watcher.add(i),console.log(`[lensmcp] watching ${i.length} extra source root(s) for set changes: ${i.map(s=>I(n.config?.root??process.cwd(),s)||s).join(", ")}`)}catch(s){console.warn(`[lensmcp] could not widen the watcher: ${s?.message??String(s)}`)}let r=0,c=0,S=0;const w=[],h=d((s,f)=>{r=Date.now(),c+=1,S+=1,w.push({sequence:S,kind:s,path:T(f),at:r}),w.length>F&&w.splice(0,w.length-F)},"stampFsSetEvent");n.watcher.on("add",s=>h("add",s)),n.watcher.on("addDir",s=>h("addDir",s)),n.watcher.on("unlink",s=>h("unlink",s)),n.watcher.on("unlinkDir",s=>h("unlinkDir",s)),n.middlewares.use(G,(s,f)=>{f.setHeader("content-type","application/json"),f.setHeader("cache-control","no-store"),f.end(JSON.stringify({schemaVersion:2,ready:!0,sequence:S,lastFsSetEventAt:r,fsSetEvents:c,recentEvents:w,extraWatchRoots:i,now:Date.now()}))})},resolveId(n){return n===D?x:null},load(n){if(n!==x)return null;const i=v??e.wsPort??0;return H({host:m,port:i})},async transform(n,i){if(!o||!b)return null;const r=i.split("?")[0]??i;if(r.includes("/node_modules/")||!/\.[jt]sx$/.test(r))return null;const c=await N(n,r);return c?{code:c.code,map:c.map}:null},transformIndexHtml(){if(!(!a||!o))return[{tag:"script",attrs:{type:"module",src:D},injectTo:"head-prepend"}]},handleHotUpdate(n){if(!o)return;const i=n.modules.map(r=>r.file??r.id??null).filter(r=>!!r);g({id:R(),sessionId:t.sessionId??"pending",timestamp:Date.now(),source:"vite",category:"build",severity:"info",context:{sessionId:t.sessionId??"pending"},fingerprint:C({kind:"hmr",identity:n.file}),title:`HMR ${n.file}`,location:{file:n.file},relatedFiles:i,raw:{kind:"hmr",file:n.file}})},generateBundle(n,i){if(!o)return;const r=[];let c=0;for(const w of Object.values(i)){const h=w,s=h.fileName;let f;if(h.type==="chunk")f=(h.code??"").length;else{const y=h.source;f=typeof y=="string"?y.length:y instanceof Uint8Array?y.byteLength:0}c+=f;const E=[];if(h.type==="chunk"&&h.modules){for(const[y,k]of Object.entries(h.modules)){const W=k.renderedLength??k.originalLength??0;E.push({id:y,sizeBytes:W})}E.sort((y,k)=>k.sizeBytes-y.sizeBytes)}r.push({name:s,sizeBytes:f,modules:E})}const S={timestamp:Date.now(),totalBytes:c,chunks:r};g({id:R(),sessionId:t.sessionId??"pending",timestamp:Date.now(),source:"rollup",category:"build",severity:"info",context:{sessionId:t.sessionId??"pending"},fingerprint:C({kind:"bundle",identity:"report"}),title:`Bundle report: ${r.length} chunks, ${c} bytes`,raw:{kind:"bundle-report",report:S}})},async closeBundle(){u&&(await u.close(),u=void 0)}}}p(lensmcpVitePlugin,"lensmcpVitePlugin"),d(lensmcpVitePlugin,"lensmcpVitePlugin");async function N(e,t){try{const[{transformSync:o},{lensmcpBabelPlugin:m}]=await Promise.all([import("@babel/core"),import("@lensmcp/react-instrumentation")]),a=o(e,{filename:t,babelrc:!1,configFile:!1,sourceMaps:!0,parserOpts:{plugins:["jsx","typescript"]},plugins:[[m,{rootDir:process.cwd()}]],code:!0});return a?.code?{code:a.code,map:a.map}:null}catch(o){return P(t,o),null}}p(N,"J"),d(N,"runLensmcpBabel");const B=new Set;function P(e,t){B.has(e)||(B.add(e),console.warn(`[lensmcp] could not instrument ${e}: ${t?.message??t}. The file still builds, but its renders, effects and hooks will be MISSING from react://renders/*, react://effects/recent and react://hooks/recent.`))}p(P,"K"),d(P,"warnTransformFailed");export function resetTransformFailuresForTests(){B.clear()}p(resetTransformFailuresForTests,"resetTransformFailuresForTests"),d(resetTransformFailuresForTests,"resetTransformFailuresForTests");export function handleClientEnvelope(e,t){X(e,L(t),t.sessionId)}p(handleClientEnvelope,"handleClientEnvelope"),d(handleClientEnvelope,"handleClientEnvelope");function M(e){const t=e?.loc?.file??e?.id;return typeof t!="string"||t.length===0?void 0:{file:t.split("?")[0]||t,...typeof e?.loc?.line=="number"?{line:e.loc.line}:{},...typeof e?.loc?.column=="number"?{column:e.loc.column}:{}}}p(M,"z"),d(M,"errorLocation");function j(e,t){const o=e.err?.message??"Vite error",m=e.err?.stack,a=M(e.err);return{id:R(),sessionId:t??"pending",timestamp:Date.now(),source:"vite",category:"build",severity:"error",context:{sessionId:t??"pending"},fingerprint:C({kind:"vite",identity:e.type??o,...a?{file:a.file}:{}}),title:o,message:m,...a?{location:a}:{},raw:{kind:"build-diagnostic",...a?{file:a.file}:{},...e.err?.plugin?{plugin:e.err.plugin}:{}}}}p(j,"X"),d(j,"viteErrorToEvent");function H(e){return`// @lensmcp/client-runtime (inlined by @lensmcp/vite-plugin)
|
|
2
2
|
(() => {
|
|
3
3
|
if (typeof window === 'undefined') return;
|
|
4
4
|
if (window.__LENSMCP_CLIENT__) return;
|
|
@@ -250,4 +250,4 @@
|
|
|
250
250
|
try { return JSON.parse(JSON.stringify(v)); } catch { return String(v); }
|
|
251
251
|
}
|
|
252
252
|
})();
|
|
253
|
-
`}
|
|
253
|
+
`}p(H,"G"),d(H,"buildInlineClientRuntime");
|
package/lib/types.d.ts
CHANGED
|
@@ -18,6 +18,16 @@ export interface LensmcpViteOptions {
|
|
|
18
18
|
aliasValtio?: boolean;
|
|
19
19
|
/** Run the LensMCP source transform (root-wrap + hooks + JSX ids). Default true. */
|
|
20
20
|
transformSource?: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Also attach during `vite build`. Default **false** — everything this plugin does (the WS
|
|
23
|
+
* bridge, the injected client runtime, `data-agent-source` on every element, source paths in
|
|
24
|
+
* `originNodeId`) is a development tool, and `enabled` defaulting to `true` meant a plain
|
|
25
|
+
* `lensmcpVitePlugin()` shipped all of it in a production bundle (issues/codex-security/39).
|
|
26
|
+
*
|
|
27
|
+
* Set it, or `LENSMCP_VITE_APPLY_ON_BUILD=1`, when you deliberately want an instrumented build —
|
|
28
|
+
* a staging deploy you intend to point the lens at.
|
|
29
|
+
*/
|
|
30
|
+
applyOnBuild?: boolean;
|
|
21
31
|
}
|
|
22
32
|
export interface LensmcpViteRuntime {
|
|
23
33
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lensmcp/vite-plugin",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.22.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./index.js",
|
|
6
6
|
"module": "./index.js",
|
|
@@ -15,11 +15,11 @@
|
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
17
|
"@babel/core": "^7.0.0",
|
|
18
|
-
"@lensmcp/bridge": "1.
|
|
19
|
-
"@lensmcp/core": "1.
|
|
20
|
-
"@lensmcp/protocol-types": "1.
|
|
21
|
-
"@lensmcp/react-instrumentation": "1.
|
|
22
|
-
"@lensmcp/valtio-instrumentation": "1.
|
|
18
|
+
"@lensmcp/bridge": "1.22.0",
|
|
19
|
+
"@lensmcp/core": "1.22.0",
|
|
20
|
+
"@lensmcp/protocol-types": "1.22.0",
|
|
21
|
+
"@lensmcp/react-instrumentation": "1.22.0",
|
|
22
|
+
"@lensmcp/valtio-instrumentation": "1.22.0",
|
|
23
23
|
"tslib": "^2.3.0"
|
|
24
24
|
},
|
|
25
25
|
"peerDependencies": {
|