@lensmcp/vite-plugin 1.21.3 → 1.21.5

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,2 +1,2 @@
1
- "use strict";var x=Object.defineProperty;var c=(e,t)=>x(e,"name",{value:t,configurable:!0});var S=Object.defineProperty,l=c((e,t)=>S(e,"name",{value:t,configurable:!0}),"c"),U=Object.defineProperty,d=l((e,t)=>U(e,"name",{value:t,configurable:!0}),"c"),R=Object.defineProperty,v=d((e,t)=>R(e,"name",{value:t,configurable:!0}),"u"),A=Object.defineProperty,m=v((e,t)=>A(e,"name",{value:t,configurable:!0}),"u"),C=Object.defineProperty,f=m((e,t)=>C(e,"name",{value:t,configurable:!0}),"u"),F=Object.defineProperty,p=f((e,t)=>F(e,"name",{value:t,configurable:!0}),"c"),J=Object.defineProperty,g=p((e,t)=>J(e,"name",{value:t,configurable:!0}),"c"),L=Object.defineProperty,y=g((e,t)=>L(e,"name",{value:t,configurable:!0}),"c"),N=Object.defineProperty,b=y((e,t)=>N(e,"name",{value:t,configurable:!0}),"u"),q=Object.defineProperty,j=b((e,t)=>q(e,"name",{value:t,configurable:!0}),"u"),z=Object.defineProperty,T=j((e,t)=>z(e,"name",{value:t,configurable:!0}),"u"),B=Object.defineProperty,E=T((e,t)=>B(e,"name",{value:t,configurable:!0}),"u"),D=Object.defineProperty,O=E((e,t)=>D(e,"name",{value:t,configurable:!0}),"o"),G=Object.defineProperty,P=O((e,t)=>G(e,"name",{value:t,configurable:!0}),"o"),H=Object.defineProperty,I=P((e,t)=>H(e,"name",{value:t,configurable:!0}),"o"),K=Object.defineProperty,w=I((e,t)=>K(e,"name",{value:t,configurable:!0}),"o"),M=Object.defineProperty,k=w((e,t)=>M(e,"name",{value:t,configurable:!0}),"o"),Q=Object.defineProperty,$=k((e,t)=>Q(e,"name",{value:t,configurable:!0}),"o");import{fingerprint as s,ulid as u}from"@lensmcp/core";const V="pending";export function envelopeToEvent(e,t=V){const o=e.tabId?{tabId:e.tabId}:{};switch(e.kind){case"error":return{id:u(),sessionId:t,timestamp:e.at,source:"client-runtime",category:"runtime",severity:"error",context:{sessionId:t,...o},fingerprint:s({kind:"runtime",identity:`error:${n(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:u(),sessionId:t,timestamp:e.at,source:"client-runtime",category:"runtime",severity:"error",context:{sessionId:t,...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",h=e.args.map(i).join(" ");return{id:u(),sessionId:t,timestamp:e.at,source:"client-runtime",category:"runtime",severity:a,context:{sessionId:t,...o},fingerprint:s({kind:"runtime",identity:`console:${e.level}:${h.slice(0,80)}`}),title:`console.${e.level}`,message:h,raw:e}}case"fetch":{const a=e.error!==void 0||e.status!==void 0&&e.status>=400;return{id:u(),sessionId:t,timestamp:e.at,source:"client-runtime",category:"network",severity:a?"error":"info",context:{sessionId:t,...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:u(),sessionId:t,timestamp:e.at,source:"client-runtime",category:"runtime",severity:"info",context:{sessionId:t,url:e.url,...o},fingerprint:s({kind:"runtime",identity:`route:${e.url}`}),title:`Route \u2192 ${e.url}`,raw:e};case"ready":return{id:u(),sessionId:t,timestamp:e.at,source:"client-runtime",category:"runtime",severity:"info",context:{sessionId:t,url:e.url,...o},fingerprint:s({kind:"runtime",identity:"client-ready"}),title:"Client runtime ready",message:e.userAgent,raw:e};case"publish":return{id:u(),sessionId:t,timestamp:e.at,source:e.source,category:e.category,severity:e.severity??"info",context:{sessionId:t,...o,...e.context??{}},fingerprint:e.fingerprint??s({kind:"publish",identity:e.title}),title:e.title,message:e.message,raw:e.raw}}}c(envelopeToEvent,"envelopeToEvent"),l(envelopeToEvent,"envelopeToEvent"),d(envelopeToEvent,"envelopeToEvent"),v(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");function n(e){if(!e)return"unknown";const t=e.split(`
2
- `).slice(0,2);for(const o of t){const a=o.match(/at\s+(\S+)/);if(a&&a[1])return a[1]}return"unknown"}c(n,"t"),l(n,"n"),d(n,"t"),v(n,"r"),m(n,"t"),f(n,"r"),p(n,"t"),g(n,"n"),y(n,"n"),b(n,"r"),j(n,"n"),T(n,"o"),E(n,"a"),O(n,"l"),P(n,"l"),I(n,"c"),w(n,"c"),k(n,"s"),$(n,"normaliseStackTopFrame");function r(e){try{return`${new URL(e,"http://x").pathname}`}catch{return e}}c(r,"r"),l(r,"r"),d(r,"r"),v(r,"n"),m(r,"r"),f(r,"n"),p(r,"r"),g(r,"r"),y(r,"r"),b(r,"i"),j(r,"i"),T(r,"a"),E(r,"c"),O(r,"d"),P(r,"d"),I(r,"l"),w(r,"l"),k(r,"m"),$(r,"normaliseUrl");function i(e){if(typeof e=="string")return e;try{return JSON.stringify(e)}catch{return String(e)}}c(i,"i"),l(i,"i"),d(i,"i"),v(i,"i"),m(i,"i"),f(i,"i"),p(i,"i"),g(i,"i"),y(i,"i"),b(i,"o"),j(i,"o"),T(i,"c"),E(i,"u"),O(i,"m"),P(i,"m"),I(i,"d"),w(i,"d"),k(i,"d"),$(i,"stringify");
1
+ "use strict";var U=Object.defineProperty;var l=(e,t)=>U(e,"name",{value:t,configurable:!0});var R=Object.defineProperty,u=l((e,t)=>R(e,"name",{value:t,configurable:!0}),"l"),A=Object.defineProperty,d=u((e,t)=>A(e,"name",{value:t,configurable:!0}),"c"),C=Object.defineProperty,v=d((e,t)=>C(e,"name",{value:t,configurable:!0}),"c"),F=Object.defineProperty,m=v((e,t)=>F(e,"name",{value:t,configurable:!0}),"c"),J=Object.defineProperty,f=m((e,t)=>J(e,"name",{value:t,configurable:!0}),"u"),L=Object.defineProperty,p=f((e,t)=>L(e,"name",{value:t,configurable:!0}),"u"),N=Object.defineProperty,g=p((e,t)=>N(e,"name",{value:t,configurable:!0}),"u"),q=Object.defineProperty,y=g((e,t)=>q(e,"name",{value:t,configurable:!0}),"c"),z=Object.defineProperty,b=y((e,t)=>z(e,"name",{value:t,configurable:!0}),"c"),B=Object.defineProperty,j=b((e,t)=>B(e,"name",{value:t,configurable:!0}),"c"),D=Object.defineProperty,T=j((e,t)=>D(e,"name",{value:t,configurable:!0}),"u"),G=Object.defineProperty,E=T((e,t)=>G(e,"name",{value:t,configurable:!0}),"u"),H=Object.defineProperty,O=E((e,t)=>H(e,"name",{value:t,configurable:!0}),"u"),K=Object.defineProperty,P=O((e,t)=>K(e,"name",{value:t,configurable:!0}),"u"),M=Object.defineProperty,I=P((e,t)=>M(e,"name",{value:t,configurable:!0}),"o"),Q=Object.defineProperty,w=I((e,t)=>Q(e,"name",{value:t,configurable:!0}),"o"),V=Object.defineProperty,k=w((e,t)=>V(e,"name",{value:t,configurable:!0}),"o"),W=Object.defineProperty,$=k((e,t)=>W(e,"name",{value:t,configurable:!0}),"o"),X=Object.defineProperty,h=$((e,t)=>X(e,"name",{value:t,configurable:!0}),"o"),Y=Object.defineProperty,x=h((e,t)=>Y(e,"name",{value:t,configurable:!0}),"o");import{fingerprint as s,ulid as c}from"@lensmcp/core";const Z="pending";export function envelopeToEvent(e,t=Z){const o=e.tabId?{tabId:e.tabId}:{};switch(e.kind){case"error":return{id:c(),sessionId:t,timestamp:e.at,source:"client-runtime",category:"runtime",severity:"error",context:{sessionId:t,...o},fingerprint:s({kind:"runtime",identity:`error:${n(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:c(),sessionId:t,timestamp:e.at,source:"client-runtime",category:"runtime",severity:"error",context:{sessionId:t,...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",S=e.args.map(i).join(" ");return{id:c(),sessionId:t,timestamp:e.at,source:"client-runtime",category:"runtime",severity:a,context:{sessionId:t,...o},fingerprint:s({kind:"runtime",identity:`console:${e.level}:${S.slice(0,80)}`}),title:`console.${e.level}`,message:S,raw:e}}case"fetch":{const a=e.error!==void 0||e.status!==void 0&&e.status>=400;return{id:c(),sessionId:t,timestamp:e.at,source:"client-runtime",category:"network",severity:a?"error":"info",context:{sessionId:t,...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:c(),sessionId:t,timestamp:e.at,source:"client-runtime",category:"runtime",severity:"info",context:{sessionId:t,url:e.url,...o},fingerprint:s({kind:"runtime",identity:`route:${e.url}`}),title:`Route \u2192 ${e.url}`,raw:e};case"ready":return{id:c(),sessionId:t,timestamp:e.at,source:"client-runtime",category:"runtime",severity:"info",context:{sessionId:t,url:e.url,...o},fingerprint:s({kind:"runtime",identity:"client-ready"}),title:"Client runtime ready",message:e.userAgent,raw:e};case"publish":return{id:c(),sessionId:t,timestamp:e.at,source:e.source,category:e.category,severity:e.severity??"info",context:{sessionId:t,...o,...e.context??{}},fingerprint:e.fingerprint??s({kind:"publish",identity:e.title}),title:e.title,message:e.message,raw:e.raw}}}l(envelopeToEvent,"envelopeToEvent"),u(envelopeToEvent,"envelopeToEvent"),d(envelopeToEvent,"envelopeToEvent"),v(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");function n(e){if(!e)return"unknown";const t=e.split(`
2
+ `).slice(0,2);for(const o of t){const a=o.match(/at\s+(\S+)/);if(a&&a[1])return a[1]}return"unknown"}l(n,"t"),u(n,"n"),d(n,"t"),v(n,"n"),m(n,"t"),f(n,"r"),p(n,"t"),g(n,"r"),y(n,"t"),b(n,"n"),j(n,"n"),T(n,"r"),E(n,"n"),O(n,"o"),P(n,"a"),I(n,"l"),w(n,"l"),k(n,"c"),$(n,"c"),h(n,"s"),x(n,"normaliseStackTopFrame");function r(e){try{return`${new URL(e,"http://x").pathname}`}catch{return e}}l(r,"r"),u(r,"r"),d(r,"r"),v(r,"r"),m(r,"r"),f(r,"n"),p(r,"r"),g(r,"n"),y(r,"r"),b(r,"r"),j(r,"r"),T(r,"i"),E(r,"i"),O(r,"a"),P(r,"c"),I(r,"d"),w(r,"d"),k(r,"l"),$(r,"l"),h(r,"m"),x(r,"normaliseUrl");function i(e){if(typeof e=="string")return e;try{return JSON.stringify(e)}catch{return String(e)}}l(i,"i"),u(i,"i"),d(i,"i"),v(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,"o"),E(i,"o"),O(i,"c"),P(i,"u"),I(i,"m"),w(i,"m"),k(i,"d"),$(i,"d"),h(i,"d"),x(i,"stringify");
package/lib/plugin.d.ts CHANGED
@@ -1,6 +1,23 @@
1
1
  import type { Plugin } from 'vite';
2
2
  import { type EventBus } from '@lensmcp/core';
3
3
  import type { LensmcpViteOptions, LensmcpViteRuntime } from './types.js';
4
+ /**
5
+ * PURE (fs reads only): the extra roots to add to Vite's watcher for a source SCOPE the gateway handed over
6
+ * (`LENSMCP_WATCH_DIRS`, `path.delimiter`-joined absolute dirs — e.g. `<ws>/web:<ws>/shared:<ws>/ai`).
7
+ *
8
+ * WHY. Vite's chokidar watches `config.root` and nothing else; a file outside it is watched one at a time
9
+ * as it is imported. So a NEW file in `shared/` or `web/libs/` never produced an `add` event, the testimony
10
+ * below never stamped it, and the gateway's stale-source-set sweeper read every out-of-root add as "this
11
+ * vite missed it" and rolled the app — 16 of 16 rolling handoffs in one foodguard day were exactly that
12
+ * (issues/dev-gateway/02). Watching the scope makes the add audible, which both spares the roll AND lets
13
+ * Vite's own create-handling (the resolve-failed retry) work for those files.
14
+ *
15
+ * Shape rules: a dir INSIDE the root is already watched → skipped. A dir that CONTAINS the root (the app's own
16
+ * bucket, `web/`) is not added whole — that would double-watch the root — but its SIBLING subtrees along the
17
+ * path to the root are (`web/libs`, `web/apps/authentication`, …). Anything else is added as-is. Missing dirs
18
+ * are dropped; the list is capped.
19
+ */
20
+ export declare function resolveExtraWatchRoots(spec: string | undefined, root: string): string[];
4
21
  interface BoundDeps {
5
22
  /**
6
23
  * EventBus to publish onto (in-process, e.g. tests). If undefined, events are
@@ -31,6 +48,8 @@ interface BoundDeps {
31
48
  * The plugin is *passive*: it never mutates app state or behaviour.
32
49
  */
33
50
  export declare function lensmcpVitePlugin(options?: LensmcpViteOptions, deps?: BoundDeps): Plugin & LensmcpViteRuntime;
51
+ /** Tests only. */
52
+ export declare function resetTransformFailuresForTests(): void;
34
53
  /**
35
54
  * Parse one raw WebSocket message from the injected client runtime and
36
55
  * publish the resulting event. Kept as a public export for backwards
package/lib/plugin.js CHANGED
@@ -1,4 +1,4 @@
1
- "use strict";var N=Object.defineProperty;var d=(e,t)=>N(e,"name",{value:t,configurable:!0});var x=Object.defineProperty,u=d((e,t)=>x(e,"name",{value:t,configurable:!0}),"c");import{resolve as P}from"node:path";import{fingerprint as k,ulid as _}from"@lensmcp/core";import{createBridgeServer as j,makePublisher as E,handleClientEnvelope as M}from"@lensmcp/bridge";const I="/@lensmcp/client-runtime",T="\0lensmcp-client-runtime",H="/__lensmcp/watcher-health",C=256;export function lensmcpVitePlugin(e={},t={}){const s=e.enabled??!0,f=e.wsHost??"127.0.0.1",i=e.injectClient??!0;let v,g;const b=E(t),D=e.aliasValtio??!0,B=e.transformSource??!0;return{name:"@lensmcp/vite-plugin",apply:s?void 0:()=>!1,enforce:"pre",wsPort:u(()=>v,"wsPort"),config(){if(!(!s||!D))return{resolve:{alias:[{find:/^valtio$/,replacement:"@lensmcp/valtio-instrumentation"}]}}},async configureServer(r){if(!s)return;g=await j({host:f,port:e.wsPort??0,bus:t.bus,sessionId:t.sessionId}),v=g.port,r.ws.on("vite:error",n=>{b(O(n,t.sessionId))});let a=0,o=0,l=0;const p=[],m=u((n,h)=>{a=Date.now(),o+=1,l+=1,p.push({sequence:l,kind:n,path:P(h),at:a}),p.length>C&&p.splice(0,p.length-C)},"stampFsSetEvent");r.watcher.on("add",n=>m("add",n)),r.watcher.on("addDir",n=>m("addDir",n)),r.watcher.on("unlink",n=>m("unlink",n)),r.watcher.on("unlinkDir",n=>m("unlinkDir",n)),r.middlewares.use(H,(n,h)=>{h.setHeader("content-type","application/json"),h.setHeader("cache-control","no-store"),h.end(JSON.stringify({schemaVersion:2,ready:!0,sequence:l,lastFsSetEventAt:a,fsSetEvents:o,recentEvents:p,now:Date.now()}))})},resolveId(r){return r===I?T:null},load(r){if(r!==T)return null;const a=v??e.wsPort??0;return A({host:f,port:a})},async transform(r,a){if(!s||!B)return null;const o=a.split("?")[0]??a;if(o.includes("/node_modules/")||!/\.[jt]sx$/.test(o))return null;const l=await L(r,o);return l?{code:l.code,map:l.map}:null},transformIndexHtml(){if(!(!i||!s))return[{tag:"script",attrs:{type:"module",src:I},injectTo:"head-prepend"}]},handleHotUpdate(r){if(!s)return;const a=r.modules.map(o=>o.file??o.id??null).filter(o=>!!o);b({id:_(),sessionId:t.sessionId??"pending",timestamp:Date.now(),source:"vite",category:"build",severity:"info",context:{sessionId:t.sessionId??"pending"},fingerprint:k({kind:"hmr",identity:r.file}),title:`HMR ${r.file}`,location:{file:r.file},relatedFiles:a,raw:{kind:"hmr",file:r.file}})},generateBundle(r,a){if(!s)return;const o=[];let l=0;for(const m of Object.values(a)){const n=m,h=n.fileName;let w;if(n.type==="chunk")w=(n.code??"").length;else{const c=n.source;w=typeof c=="string"?c.length:c instanceof Uint8Array?c.byteLength:0}l+=w;const S=[];if(n.type==="chunk"&&n.modules){for(const[c,y]of Object.entries(n.modules)){const F=y.renderedLength??y.originalLength??0;S.push({id:c,sizeBytes:F})}S.sort((c,y)=>y.sizeBytes-c.sizeBytes)}o.push({name:h,sizeBytes:w,modules:S})}const p={timestamp:Date.now(),totalBytes:l,chunks:o};b({id:_(),sessionId:t.sessionId??"pending",timestamp:Date.now(),source:"rollup",category:"build",severity:"info",context:{sessionId:t.sessionId??"pending"},fingerprint:k({kind:"bundle",identity:"report"}),title:`Bundle report: ${o.length} chunks, ${l} bytes`,raw:{kind:"bundle-report",report:p}})},async closeBundle(){g&&(await g.close(),g=void 0)}}}d(lensmcpVitePlugin,"lensmcpVitePlugin"),u(lensmcpVitePlugin,"lensmcpVitePlugin");async function L(e,t){try{const[{transformSync:s},{lensmcpBabelPlugin:f}]=await Promise.all([import("@babel/core"),import("@lensmcp/react-instrumentation")]),i=s(e,{filename:t,babelrc:!1,configFile:!1,sourceMaps:!0,parserOpts:{plugins:["jsx","typescript"]},plugins:[[f,{rootDir:process.cwd(),production:!1}]],code:!0});return i?.code?{code:i.code,map:i.map}:null}catch{return null}}d(L,"F"),u(L,"runLensmcpBabel");export function handleClientEnvelope(e,t){M(e,E(t),t.sessionId)}d(handleClientEnvelope,"handleClientEnvelope"),u(handleClientEnvelope,"handleClientEnvelope");function R(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}:{}}}d(R,"P"),u(R,"errorLocation");function O(e,t){const s=e.err?.message??"Vite error",f=e.err?.stack,i=R(e.err);return{id:_(),sessionId:t??"pending",timestamp:Date.now(),source:"vite",category:"build",severity:"error",context:{sessionId:t??"pending"},fingerprint:k({kind:"vite",identity:e.type??s,...i?{file:i.file}:{}}),title:s,message:f,...i?{location:i}:{},raw:{kind:"build-diagnostic",...i?{file:i.file}:{},...e.err?.plugin?{plugin:e.err.plugin}:{}}}}d(O,"j"),u(O,"viteErrorToEvent");function A(e){return`// @lensmcp/client-runtime (inlined by @lensmcp/vite-plugin)
1
+ "use strict";var W=Object.defineProperty;var f=(e,t)=>W(e,"name",{value:t,configurable:!0});var $=Object.defineProperty,d=f((e,t)=>$(e,"name",{value:t,configurable:!0}),"u");import{existsSync as V,readdirSync as U,statSync as q}from"node:fs";import{delimiter as J,join as A,relative as E,resolve as I,sep as B}from"node:path";import{fingerprint as T,ulid as C}from"@lensmcp/core";import{createBridgeServer as K,makePublisher as O,handleClientEnvelope as z}from"@lensmcp/bridge";const x="/@lensmcp/client-runtime",D="\0lensmcp-client-runtime",X="/__lensmcp/watcher-health",L=256,G=64,Y=new Set(["node_modules",".git","dist","tmp","coverage","build","out","target",".nx",".lensmcp"]);export function resolveExtraWatchRoots(e,t){if(!e)return[];const s=I(t),g=d((u,y)=>{const c=E(y,u);return c!==""&&!c.startsWith("..")&&!c.startsWith(B)&&!/^[A-Za-z]:/.test(c)},"inside"),a=[],b=d(u=>{a.length<G&&!a.includes(u)&&a.push(u)},"push");for(const u of e.split(J)){const y=u.trim();if(!y)continue;const c=I(y);let S;try{S=V(c)&&q(c).isDirectory()}catch{S=!1}if(S&&!(c===s||g(c,s))){if(g(s,c)){const n=E(c,s).split(B).filter(Boolean);let o=c;for(const i of n){let l;try{l=U(o,{withFileTypes:!0})}catch{l=[]}for(const p of l)!p.isDirectory()||p.name===i||p.name.startsWith(".")||Y.has(p.name)||b(A(o,p.name));o=A(o,i)}continue}b(c)}}return a}f(resolveExtraWatchRoots,"resolveExtraWatchRoots"),d(resolveExtraWatchRoots,"resolveExtraWatchRoots");export function lensmcpVitePlugin(e={},t={}){const s=e.enabled??!0,g=e.wsHost??"127.0.0.1",a=e.injectClient??!0;let b,u;const y=O(t),c=e.aliasValtio??!0,S=e.transformSource??!0;return{name:"@lensmcp/vite-plugin",apply:s?void 0:()=>!1,enforce:"pre",wsPort:d(()=>b,"wsPort"),config(){if(!(!s||!c))return{resolve:{alias:[{find:/^valtio$/,replacement:"@lensmcp/valtio-instrumentation"}]}}},async configureServer(n){if(!s)return;u=await K({host:g,port:e.wsPort??0,bus:t.bus,sessionId:t.sessionId}),b=u.port,n.ws.on("vite:error",r=>{y(j(r,t.sessionId))});const o=resolveExtraWatchRoots(process.env.LENSMCP_WATCH_DIRS,n.config?.root??process.cwd());if(o.length>0&&typeof n.watcher?.add=="function")try{n.watcher.add(o),console.log(`[lensmcp] watching ${o.length} extra source root(s) for set changes: ${o.map(r=>E(n.config?.root??process.cwd(),r)||r).join(", ")}`)}catch(r){console.warn(`[lensmcp] could not widen the watcher: ${r?.message??String(r)}`)}let i=0,l=0,p=0;const v=[],h=d((r,m)=>{i=Date.now(),l+=1,p+=1,v.push({sequence:p,kind:r,path:I(m),at:i}),v.length>L&&v.splice(0,v.length-L)},"stampFsSetEvent");n.watcher.on("add",r=>h("add",r)),n.watcher.on("addDir",r=>h("addDir",r)),n.watcher.on("unlink",r=>h("unlink",r)),n.watcher.on("unlinkDir",r=>h("unlinkDir",r)),n.middlewares.use(X,(r,m)=>{m.setHeader("content-type","application/json"),m.setHeader("cache-control","no-store"),m.end(JSON.stringify({schemaVersion:2,ready:!0,sequence:p,lastFsSetEventAt:i,fsSetEvents:l,recentEvents:v,extraWatchRoots:o,now:Date.now()}))})},resolveId(n){return n===x?D:null},load(n){if(n!==D)return null;const o=b??e.wsPort??0;return M({host:g,port:o})},async transform(n,o){if(!s||!S)return null;const i=o.split("?")[0]??o;if(i.includes("/node_modules/")||!/\.[jt]sx$/.test(i))return null;const l=await F(n,i);return l?{code:l.code,map:l.map}:null},transformIndexHtml(){if(!(!a||!s))return[{tag:"script",attrs:{type:"module",src:x},injectTo:"head-prepend"}]},handleHotUpdate(n){if(!s)return;const o=n.modules.map(i=>i.file??i.id??null).filter(i=>!!i);y({id:C(),sessionId:t.sessionId??"pending",timestamp:Date.now(),source:"vite",category:"build",severity:"info",context:{sessionId:t.sessionId??"pending"},fingerprint:T({kind:"hmr",identity:n.file}),title:`HMR ${n.file}`,location:{file:n.file},relatedFiles:o,raw:{kind:"hmr",file:n.file}})},generateBundle(n,o){if(!s)return;const i=[];let l=0;for(const v of Object.values(o)){const h=v,r=h.fileName;let m;if(h.type==="chunk")m=(h.code??"").length;else{const w=h.source;m=typeof w=="string"?w.length:w instanceof Uint8Array?w.byteLength:0}l+=m;const _=[];if(h.type==="chunk"&&h.modules){for(const[w,k]of Object.entries(h.modules)){const H=k.renderedLength??k.originalLength??0;_.push({id:w,sizeBytes:H})}_.sort((w,k)=>k.sizeBytes-w.sizeBytes)}i.push({name:r,sizeBytes:m,modules:_})}const p={timestamp:Date.now(),totalBytes:l,chunks:i};y({id:C(),sessionId:t.sessionId??"pending",timestamp:Date.now(),source:"rollup",category:"build",severity:"info",context:{sessionId:t.sessionId??"pending"},fingerprint:T({kind:"bundle",identity:"report"}),title:`Bundle report: ${i.length} chunks, ${l} bytes`,raw:{kind:"bundle-report",report:p}})},async closeBundle(){u&&(await u.close(),u=void 0)}}}f(lensmcpVitePlugin,"lensmcpVitePlugin"),d(lensmcpVitePlugin,"lensmcpVitePlugin");async function F(e,t){try{const[{transformSync:s},{lensmcpBabelPlugin:g}]=await Promise.all([import("@babel/core"),import("@lensmcp/react-instrumentation")]),a=s(e,{filename:t,babelrc:!1,configFile:!1,sourceMaps:!0,parserOpts:{plugins:["jsx","typescript"]},plugins:[[g,{rootDir:process.cwd(),production:!1}]],code:!0});return a?.code?{code:a.code,map:a.map}:null}catch(s){return N(t,s),null}}f(F,"q"),d(F,"runLensmcpBabel");const R=new Set;function N(e,t){R.has(e)||(R.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.`))}f(N,"J"),d(N,"warnTransformFailed");export function resetTransformFailuresForTests(){R.clear()}f(resetTransformFailuresForTests,"resetTransformFailuresForTests"),d(resetTransformFailuresForTests,"resetTransformFailuresForTests");export function handleClientEnvelope(e,t){z(e,O(t),t.sessionId)}f(handleClientEnvelope,"handleClientEnvelope"),d(handleClientEnvelope,"handleClientEnvelope");function P(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}:{}}}f(P,"K"),d(P,"errorLocation");function j(e,t){const s=e.err?.message??"Vite error",g=e.err?.stack,a=P(e.err);return{id:C(),sessionId:t??"pending",timestamp:Date.now(),source:"vite",category:"build",severity:"error",context:{sessionId:t??"pending"},fingerprint:T({kind:"vite",identity:e.type??s,...a?{file:a.file}:{}}),title:s,message:g,...a?{location:a}:{},raw:{kind:"build-diagnostic",...a?{file:a.file}:{},...e.err?.plugin?{plugin:e.err.plugin}:{}}}}f(j,"z"),d(j,"viteErrorToEvent");function M(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;
@@ -94,13 +94,42 @@
94
94
  const chunk = queue.splice(0, 200);
95
95
  try { ws.send(JSON.stringify(chunk.length === 1 ? chunk[0] : { kind: 'batch', at: Date.now(), tabId: TAB_ID, events: chunk })); } catch (e) {}
96
96
  }
97
- send({ kind: 'ready', userAgent: navigator.userAgent, url: location.href });
97
+ // If Vite threw the previous document away (a full reload), say so and why \u2014 the runtime that saw
98
+ // the 'vite:beforeFullReload' parked the cause in sessionStorage because its socket died with it.
99
+ let reloadCause;
100
+ try { const c = sessionStorage.getItem('lensmcp:reloadCause'); if (c) { sessionStorage.removeItem('lensmcp:reloadCause'); reloadCause = JSON.parse(c); } } catch (e) {}
101
+ send(Object.assign({ kind: 'ready', userAgent: navigator.userAgent, url: location.href }, reloadCause ? { reloadCause } : {}));
98
102
  });
99
103
  ws.addEventListener('close', () => { if (openOnce) setTimeout(open, 1000); });
100
104
  ws.addEventListener('error', () => { /* ignore \u2014 close handler reconnects */ });
101
105
  }
102
106
  open();
103
107
 
108
+ // HMR TESTIMONY \u2014 Vite's HMR channel as this page sees it. A full reload is the event the developer
109
+ // pays for and nobody could explain ("why did it reload instead of hot-updating?"); Vite names the file
110
+ // it could not hot-update in \`triggeredBy\`. The cause is also parked in sessionStorage so the NEXT
111
+ // document's \`ready\` can carry it \u2014 this socket dies with the page. \`import.meta.hot\` exists only
112
+ // under the dev server; guarded so a build that inlines this file is unaffected.
113
+ try {
114
+ const hot = import.meta.hot;
115
+ if (hot && typeof hot.on === 'function') {
116
+ const bound = (list) => (Array.isArray(list) ? list : []).slice(0, 20);
117
+ hot.on('vite:beforeFullReload', (p) => {
118
+ const cause = { path: p && p.path, triggeredBy: p && p.triggeredBy, at: Date.now() };
119
+ try { sessionStorage.setItem('lensmcp:reloadCause', JSON.stringify(cause)); } catch (e) {}
120
+ send({ kind: 'hmr', event: 'full-reload', path: cause.path, triggeredBy: cause.triggeredBy });
121
+ flushBatch(); // the page is about to unload \u2014 do not leave this in the macrotask queue
122
+ });
123
+ hot.on('vite:beforeUpdate', (p) => {
124
+ const updates = (p && p.updates) || [];
125
+ send({ kind: 'hmr', event: 'update', count: updates.length, updates: bound(updates.map((u) => u && (u.path || u.acceptedPath))) });
126
+ });
127
+ hot.on('vite:invalidate', (p) => send({ kind: 'hmr', event: 'invalidate', path: p && p.path, message: p && p.message }));
128
+ hot.on('vite:ws:disconnect', () => send({ kind: 'hmr', event: 'ws-disconnect' }));
129
+ hot.on('vite:ws:connect', () => send({ kind: 'hmr', event: 'ws-connect' }));
130
+ }
131
+ } catch (e) { /* strictly passive */ }
132
+
104
133
  // Bridge for in-page instrumentation (@lensmcp/react-instrumentation,
105
134
  // @lensmcp/valtio-instrumentation). Their publish() calls land here and
106
135
  // ride the same WS as a 'publish' envelope, so React renders + Valtio
@@ -221,4 +250,4 @@
221
250
  try { return JSON.parse(JSON.stringify(v)); } catch { return String(v); }
222
251
  }
223
252
  })();
224
- `}d(A,"x"),u(A,"buildInlineClientRuntime");
253
+ `}f(M,"X"),d(M,"buildInlineClientRuntime");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lensmcp/vite-plugin",
3
- "version": "1.21.3",
3
+ "version": "1.21.5",
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.21.3",
19
- "@lensmcp/core": "1.21.3",
20
- "@lensmcp/protocol-types": "1.21.3",
21
- "@lensmcp/react-instrumentation": "1.21.3",
22
- "@lensmcp/valtio-instrumentation": "1.21.3",
18
+ "@lensmcp/bridge": "1.21.5",
19
+ "@lensmcp/core": "1.21.5",
20
+ "@lensmcp/protocol-types": "1.21.5",
21
+ "@lensmcp/react-instrumentation": "1.21.5",
22
+ "@lensmcp/valtio-instrumentation": "1.21.5",
23
23
  "tslib": "^2.3.0"
24
24
  },
25
25
  "peerDependencies": {