@lensmcp/react-instrumentation 1.25.17 → 1.25.18
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/lib/babel-plugin.js +1 -1
- package/lib/component-identity.js +1 -1
- package/lib/context.js +1 -1
- package/lib/fiber-renders.js +1 -1
- package/lib/flow-fetch.js +1 -1
- package/lib/hoc.js +1 -1
- package/lib/identity.js +1 -1
- package/lib/lensmcp-root.js +1 -1
- package/lib/page-perf.js +1 -1
- package/lib/page-visit-runtime.d.ts +23 -0
- package/lib/page-visit-runtime.js +1 -1
- package/lib/page-visits.d.ts +7 -0
- package/lib/page-visits.js +1 -1
- package/lib/publish.js +1 -1
- package/lib/replay-anchors.d.ts +18 -0
- package/lib/replay-anchors.js +1 -0
- package/lib/route-flows.d.ts +6 -0
- package/lib/route-flows.js +1 -1
- package/lib/router-pattern.js +1 -1
- package/lib/trace-slot.js +1 -1
- package/lib/traced-hooks.js +1 -1
- package/package.json +2 -2
package/lib/babel-plugin.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var L=Object.defineProperty;var l=(o,e)=>L(o,"name",{value:e,configurable:!0});var P=Object.defineProperty,c=l((o,e)=>P(o,"name",{value:e,configurable:!0}),"l"),R=Object.defineProperty,d=c((o,e)=>R(o,"name",{value:e,configurable:!0}),"a");const F=4;export function displaySourcePath(o,e){const n=d(u=>u.replace(/\\/g,"/").replace(/\/+$/,"").split("/"),"segments"),t=n(o),r=n(e);let i=0;for(;i<t.length&&i<r.length&&t[i]===r[i];)i++;const a=r.length-i;if(i===0||a>4)return`<external>/${t[t.length-1]??"unknown"}`;const s=t.slice(i);return s.length===0?"<external>/unknown":[...new Array(a).fill(".."),...s].join("/")}l(displaySourcePath,"displaySourcePath"),c(displaySourcePath,"displaySourcePath"),d(displaySourcePath,"displaySourcePath");const j="@lensmcp/react-instrumentation",C=new Map([["useEffect","tracedUseEffect"],["useMemo","tracedUseMemo"],["useCallback","tracedUseCallback"]]),J=new Set(C.values());function m(o){return`useLensmcp_${o}`}l(m,"m"),c(m,"S"),d(m,"tracedHookLocalName");function f(o){return J.has(o)?m(o):o}l(f,"f"),c(f,"b"),d(f,"helperLocalName");const X=["onClick","onDoubleClick","onContextMenu","onSubmit","onChange"],$=new Map([["onSubmit","form-submit"],["onChange","input-change"]]);export default function w(o){const e=o.types;return{name:"@lensmcp/react-instrumentation/babel-plugin",visitor:{Program:{enter(n,t){if(t.needHelpers=new Set,t.needRoot=!1,t.hookIndex=0,t.flowEvents=new Set(t.opts.flowEvents??X),t.rootVars=new Set,t.opts.production??process.env.NODE_ENV==="production"){t.fileIgnored=!0;return}(n.node.body[0]?.leadingComments??n.node.directives.flatMap(i=>i.leadingComments??[])??[]).some(i=>i.value.includes("@lensmcp-ignore"))&&(t.fileIgnored=!0);const r=t.file?.opts?.filename;r&&(t.relativePath=displaySourcePath(r,t.opts.rootDir??process.cwd()))},exit(n,t){if(t.fileIgnored)return;const r=[...t.needHelpers??[]];if(t.needRoot&&r.push("LensmcpRoot","installFlowFetch"),r.length===0)return;const i=x(n.node.body,j,e),a=r.filter(s=>i.get(f(s))!==s);if(a.length>0&&n.node.body.unshift(e.importDeclaration(a.map(s=>e.importSpecifier(e.identifier(f(s)),e.identifier(s))),e.stringLiteral(j))),t.needRoot){const s=n.node.body.findIndex(p=>!e.isImportDeclaration(p)),u=e.expressionStatement(e.callExpression(e.identifier("installFlowFetch"),[]));n.node.body.splice(s<0?n.node.body.length:s,0,u)}}},VariableDeclarator(n,t){t.fileIgnored||t.opts.autoWrapRoot!==!1&&e.isIdentifier(n.node.id)&&n.node.init&&h(n.node.init,e)&&t.rootVars.add(n.node.id.name)},CallExpression(n,t){if(t.fileIgnored)return;const r=n.node.callee,i=t.opts.autoWrapHooks!==!1&&e.isIdentifier(r)?C.get(r.name):void 0;if(i){const a=`${t.relativePath??"(anon)"}:${n.node.loc?.start.line??0}:${t.hookIndex++}`;n.node.callee=e.identifier(m(i)),n.node.arguments.unshift(e.stringLiteral(a)),t.needHelpers.add(i);return}if(t.opts.autoWrapRoot!==!1&&e.isMemberExpression(r)&&e.isIdentifier(r.property,{name:"render"})&&(h(r.object,e)||e.isIdentifier(r.object)&&t.rootVars?.has(r.object.name))&&n.node.arguments.length>=1){const a=n.node.arguments[0];a&&!S(a,e)&&(n.node.arguments[0]=e.jsxElement(e.jsxOpeningElement(e.jsxIdentifier("LensmcpRoot"),[],!1),e.jsxClosingElement(e.jsxIdentifier("LensmcpRoot")),[e.jsxExpressionContainer(a)],!1),t.needRoot=!0)}},JSXOpeningElement(n,t){if(t.fileIgnored)return;const r=n.node.attributes;if(g(r,"data-agent-component")||g(r,"data-lensmcp-ignore")||(n.parent.leadingComments??n.node.leadingComments??[]).some(s=>s.value.includes("@lensmcp-ignore")))return;if(t.opts.autoFlowHandlers!==!1){const s=n.node.loc?.start.line??0,u=t.relativePath??"(anon)";for(const p of n.node.attributes){if(p.type!=="JSXAttribute"||p.name.type!=="JSXIdentifier"||!t.flowEvents.has(p.name.name)||!p.value||p.value.type!=="JSXExpressionContainer")continue;const b=p.value.expression;if(b.type==="JSXEmptyExpression"||y(b,e))continue;const v=p.name.name;p.value.expression=e.callExpression(e.identifier("withFlow"),[b,e.objectExpression([e.objectProperty(e.identifier("originType"),e.stringLiteral($.get(v)??"user-click")),e.objectProperty(e.identifier("originNodeId"),e.stringLiteral(`ui:${u}:${s}:${v}`))])]),t.needHelpers.add("withFlow")}}const i=E(n.node.name);if(!i||I(i))return;const a=[e.jsxAttribute(e.jsxIdentifier("data-agent-component"),e.stringLiteral(i))];if(t.opts.includeSource!==!1){const s=n.node.loc?.start.line??0,u=t.relativePath??"(anon)";a.push(e.jsxAttribute(e.jsxIdentifier("data-agent-source"),e.stringLiteral(`${u}:${s}`)))}n.node.attributes.push(...a)}}}}l(w,"j"),c(w,"v"),d(w,"lensmcpBabelPlugin");function g(o,e){return o.some(n=>n.type==="JSXAttribute"&&n.name.type==="JSXIdentifier"&&n.name.name===e)}l(g,"g"),c(g,"x"),d(g,"hasAttr");function x(o,e,n){const t=new Map;for(const r of o)if(n.isImportDeclaration(r)&&r.source.value===e)for(const i of r.specifiers)n.isImportSpecifier(i)&&n.isIdentifier(i.imported)&&t.set(i.local.name,i.imported.name);return t}l(x,"I"),c(x,"L"),d(x,"collectImported");function h(o,e){if(!e.isCallExpression(o))return!1;const n=o.callee,t=new Set(["createRoot","hydrateRoot"]);return e.isIdentifier(n)?t.has(n.name):e.isMemberExpression(n)&&e.isIdentifier(n.property)?t.has(n.property.name):!1}l(h,"h"),c(h,"I"),d(h,"isRootFactoryCall");function y(o,e){return e.isCallExpression(o)&&e.isIdentifier(o.callee,{name:"withFlow"})}l(y,"S"),c(y,"j"),d(y,"isAlreadyWithFlow");function S(o,e){return e.isJSXElement(o)&&e.isJSXIdentifier(o.openingElement.name,{name:"LensmcpRoot"})}l(S,"E"),c(S,"A"),d(S,"isAlreadyLensmcpRoot");const M=new Set(["Fragment","StrictMode","Suspense","SuspenseList","Profiler"]);function I(o){const e=o.split(".").pop()??o;return M.has(e)?!0:e.endsWith("Provider")||e.endsWith("Consumer")}l(I,"w"),c(I,"P"),d(I,"isUnstampableElement");function E(o){switch(o.type){case"JSXIdentifier":return o.name;case"JSXMemberExpression":{const e=[];let n=o;for(;n.type==="JSXMemberExpression";)e.unshift(n.property.name),n=n.object;return n.type==="JSXIdentifier"&&e.unshift(n.name),e.join(".")}case"JSXNamespacedName":return`${o.namespace.name}:${o.name.name}`;default:return}}l(E,"v"),c(E,"R"),d(E,"describeElementName");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var m=Object.defineProperty;var t=(n,e)=>m(n,"name",{value:e,configurable:!0});var p=Object.defineProperty,o=t((n,e)=>p(n,"name",{value:e,configurable:!0}),"t"),_=Object.defineProperty,c=o((n,e)=>_(n,"name",{value:e,configurable:!0}),"r");import{useId as f,useRef as s}from"react";export function readOwnerName(n){try{if(!n)return;const e=n.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE??n.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;if(!e)return;const i=e.A,r=((typeof i?.getOwner=="function"?i.getOwner():null)??e.owner??e.ReactCurrentOwner?.current)?.type;if(!r)return;if(typeof r=="string")return r;const u=r.displayName??r.name;return typeof u=="string"&&u.length>0?u:void 0}catch{return}}t(readOwnerName,"readOwnerName"),o(readOwnerName,"readOwnerName"),c(readOwnerName,"readOwnerName");export function composeComponentIdentity(n,e){return{componentInstanceId:`react:component:${e??"fn"}${n}`,...e?{componentLogicalId:`react:component:${e}`,componentName:e}:{}}}t(composeComponentIdentity,"composeComponentIdentity"),o(composeComponentIdentity,"composeComponentIdentity"),c(composeComponentIdentity,"composeComponentIdentity");function a(){try{return readOwnerName(require("react"))}catch{return}}t(a,"i"),o(a,"f"),c(a,"currentOwnerName");export function useComponentIdentity(){const n=f(),e=s(void 0);return e.current||(e.current=composeComponentIdentity(n,a())),e.current}t(useComponentIdentity,"useComponentIdentity"),o(useComponentIdentity,"useComponentIdentity"),c(useComponentIdentity,"useComponentIdentity");
|
package/lib/context.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var o=Object.defineProperty;var n=(e,t)=>o(e,"name",{value:t,configurable:!0});var s=Object.defineProperty,r=n((e,t)=>s(e,"name",{value:t,configurable:!0}),"n"),c=Object.defineProperty,a=r((e,t)=>c(e,"name",{value:t,configurable:!0}),"t");import{createContext as p,useContext as u}from"react";const m={rendererId:"lensmcp-root"};export const LensmcpContext=p(m);export function useLensmcpContext(){return u(LensmcpContext)}n(useLensmcpContext,"useLensmcpContext"),r(useLensmcpContext,"useLensmcpContext"),a(useLensmcpContext,"useLensmcpContext");
|
package/lib/fiber-renders.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var L=Object.defineProperty;var u=(e,t)=>L(e,"name",{value:t,configurable:!0});var W=Object.defineProperty,f=u((e,t)=>W(e,"name",{value:t,configurable:!0}),"u"),G=Object.defineProperty,m=f((e,t)=>G(e,"name",{value:t,configurable:!0}),"d");import{makeInstanceId as $}from"./identity.js";import{publish as N}from"./publish.js";import{notePageCommit as K}from"./page-visit-runtime.js";import{patternOf as Z,routeMatchesOf as q}from"./router-pattern.js";const B=1,H=0,U=1,Y=11,J=13,_=14,Q=15,k=15e3,z=25,j=15,X=8,M=(typeof process<"u"?process.env?.LENSMCP_RENDER_INCLUDE_INTERNALS:void 0)==="1",V=new Set(["Insertion","EmotionGlobal","EmotionCssPropInternal","GlobalStyles","ThemeProvider","CacheProvider"]);function v(e){return!!(V.has(e)||e.startsWith("Styled(")&&/^Styled\([a-z][a-zA-Z0-9-]*\)$/.test(e)||e==="lensmcp-root"||e.startsWith("Lensmcp"))}u(v,"I"),f(v,"R"),m(v,"isInternalRender");let w=!1,I=!1;const ee={};function P(e){const t=e.type;if(!(t==null||typeof t=="string"))switch(e.tag){case H:case U:return t.displayName||t.name||void 0;case Y:return t.displayName||t.render?.displayName||t.render?.name||void 0;case _:case Q:return t.displayName||t.type?.displayName||t.type?.name||t.name||void 0;default:return}}u(P,"k"),f(P,"O"),m(P,"componentNameOf");function C(e){const t=e.alternate?.memoizedProps,s=e.memoizedProps;if(!t||!s||t===s)return[];const r=[];for(const o of Object.keys(s))if(o!=="children"&&!Object.is(t[o],s[o])&&(r.push(o),r.length>=X))break;return r}u(C,"z"),f(C,"H"),m(C,"changedPropKeys");const R=new WeakMap;function S(e,t){const s=R.get(e);if(s)return s;const r=e.alternate,o=(r?R.get(r):void 0)??$(t).instanceId;return R.set(e,o),r&&R.set(r,o),o}u(S,"F"),f(S,"Y"),m(S,"stableInstanceId");const E=m(e=>e.alternate==null||e.child!==e.alternate.child,"childrenChanged");function F(e){const t=[];let s=0,r=!1,o,l=!1;const a=[],i=m((n,d,p)=>{for(let g=n.child;g;g=g.sibling)a.push({node:g,parentName:d,...p?{wrapperName:p}:{}})},"pushChildren");for(E(e.current)&&i(e.current,void 0);a.length>0;){const{node:n,parentName:d,wrapperName:p}=a.pop();if(s+=1,s>k){r=!0;break}let g=d;const b=n.memoizedProps?q(n.memoizedProps):void 0;if(b&&b.length>=(o?.length??0)&&(o=b),n.tag===J&&n.memoizedState!=null&&(l=!0),n.tag===_){E(n)&&i(n,d,P(n));continue}const c=P(n)??p,A=(n.flags&B)!==0;if(c&&A){const O=n.alternate==null,y=[];if(!O){const T=C(n);T.length>0&&y.push({type:"props",changedKeys:T}),d&&y.push({type:"parent-render",parentRenderId:d}),y.length===0&&y.push({type:"react-state",hookIndex:-1})}t.push({name:c,instanceId:S(n,`react:component:(fiber):${c}`),phase:O?"mount":"update",durationMs:typeof n.actualDuration=="number"?n.actualDuration:0,why:y,parentName:d}),g=c}E(n)&&i(n,g)}const h=o?Z(o):void 0;return{renders:t,cut:r,suspense:l,...h?{pattern:h}:{}}}u(F,"O"),f(F,"Z"),m(F,"collectCommitRenders");let x;export function activeCommitId(){return x}u(activeCommitId,"activeCommitId"),f(activeCommitId,"activeCommitId"),m(activeCommitId,"activeCommitId");export function fiberRendersActive(){return w&&!I}u(fiberRendersActive,"fiberRendersActive"),f(fiberRendersActive,"fiberRendersActive"),m(fiberRendersActive,"fiberRendersActive");function D(e,t,s=!1){const r=M?e:e.filter(a=>!v(a.name));if(r.length===0)return;const o=$("react:commit").instanceId;x=o;const l=r.length>z?[...r].sort((a,i)=>i.durationMs-a.durationMs).slice(0,z):r;for(const a of l){const i=`react:component:(fiber):${a.name}`,{instanceId:h}=$(i),n={id:h,commitId:o,componentInstanceId:a.instanceId,componentLogicalId:i,componentName:a.name,rendererId:"fiber",phase:a.phase,actualDurationMs:a.durationMs,baseDurationMs:a.durationMs,startTime:t,commitTime:t,why:a.why};N({source:"react",category:"render",severity:"info",title:`render ${a.name} (${a.phase})`,fingerprint:`react-render:${i}`,raw:{kind:"render",render:n}})}if(r.length>l.length||s){const a=s?`at least ${r.length}`:String(r.length);N({source:"react",category:"render",severity:"debug",title:s?`render commit truncated: the walk stopped at ${k} fibers \u2014 ${a} renders, ${l.length} recorded`:`render commit truncated: ${r.length-l.length} of ${r.length} renders dropped (per-commit cap)`,fingerprint:"react-render:commit-truncated",raw:{kind:"render-commit-truncated",commitId:o,total:r.length,published:l.length,...s?{walkStoppedAt:k}:{}}})}}u(D,"x"),f(D,"q"),m(D,"publishRecords");export function installFiberRenderPublisher(){if(w||I||typeof window>"u")return;const e=window.__LENSMCP_FIBER__;if(!e||typeof e.subscribe!="function")return;w=!0;let t=j,s=0;const r=new Map;let o=0,l;const a=m(()=>{if(l=void 0,t=j,s===0)return;const i=[...r.entries()].sort((d,p)=>p[1]-d[1]).slice(0,5),h=i.length>0?`top: ${i.map(([d,p])=>`${d}\xD7${p}`).join(", ")}`:"no product component in the commits \u2014 all framework-internal",n=o>0?` (+${o} framework-internal)`:"";N({source:"react",category:"render",severity:"warning",title:`render storm: ${s} commits/s over budget \u2014 ${h}${n}`,fingerprint:"react-render:storm",raw:{kind:"render-storm",commits:s,components:Object.fromEntries(i),internalRenders:o}}),s=0,o=0,r.clear()},"flushStorm");e.subscribe((i,h)=>{if(!I)try{if(!h||!h.current)return;const{renders:n,cut:d,pattern:p,suspense:g}=F(h),b=M?n:n.filter(c=>!v(c.name));if(K(ee,{at:Date.now(),renders:b.map(c=>({name:c.name,ms:c.durationMs,mount:c.phase==="mount"})),storm:t<=0,suspense:g,...p?{pattern:p}:{}}),n.length===0)return;if(t>0)t-=1,D(n,Date.now(),d);else{s+=1;for(const c of n){if(!M&&v(c.name)){o+=1;continue}r.set(c.name,(r.get(c.name)??0)+1)}}l||(l=setTimeout(a,1e3))}catch{I=!0}})}u(installFiberRenderPublisher,"installFiberRenderPublisher"),f(installFiberRenderPublisher,"installFiberRenderPublisher"),m(installFiberRenderPublisher,"installFiberRenderPublisher");export function resetFiberRenderPublisherForTests(){w=!1,I=!1}u(resetFiberRenderPublisherForTests,"resetFiberRenderPublisherForTests"),f(resetFiberRenderPublisherForTests,"resetFiberRenderPublisherForTests"),m(resetFiberRenderPublisherForTests,"resetFiberRenderPublisherForTests");
|
package/lib/flow-fetch.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var B=Object.defineProperty;var f=(e,o)=>B(e,"name",{value:o,configurable:!0});var V=Object.defineProperty,g=f((e,o)=>V(e,"name",{value:o,configurable:!0}),"f"),X=Object.defineProperty,c=g((e,o)=>X(e,"name",{value:o,configurable:!0}),"c");import{beginBackgroundFlow as K,extendFlowWindow as A,flowForNewActivity as j,publish as E}from"./publish.js";import{installRouteFlows as z}from"./route-flows.js";import{notePageFetch as x,pageVisitOpen as C,startHardPageVisit as J}from"./page-visit-runtime.js";import{replayActive as G,replayLeg as L}from"./replay-anchors.js";export function mayPropagateTo(e,o=[]){const d=typeof location<"u"?location.href:void 0;let u;try{u=new URL(e,d)}catch{return!1}if(typeof location<"u"&&u.origin===location.origin||_(u.hostname))return!0;for(const i of o){let l;try{l=new URL(i).origin}catch{continue}if(l===u.origin)return!0}return!1}f(mayPropagateTo,"mayPropagateTo"),g(mayPropagateTo,"mayPropagateTo"),c(mayPropagateTo,"mayPropagateTo");const Q=new Set(["localhost","[::1]","::1"]);function _(e){const o=e.toLowerCase();return Q.has(o)||/^127\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(o)}f(_,"O"),g(_,"B"),c(_,"isLoopbackHost");function $(){const e=globalThis.__LENSMCP_FLOW_PROPAGATE__;return Array.isArray(e)?e.filter(o=>typeof o=="string"):typeof e=="string"?e.split(",").map(o=>o.trim()).filter(Boolean):[]}f($,"$"),g($,"E"),c($,"globalPropagateList");function F(){return Date.now().toString(36)+Math.random().toString(36).slice(2,12)}f(F,"S"),g(F,"k"),c(F,"newRequestId");function I(e){return typeof e=="string"?e:e instanceof URL?e.href:e.url??String(e)}f(I,"y"),g(I,"H"),c(I,"urlOf");const U=Symbol.for("lensmcp.flow-fetch"),D=Symbol.for("lensmcp.flow-fetch.recorded-leg");function b(e){return{...e,[D]:!0}}f(b,"x"),g(b,"R"),c(b,"markRecorded");let W=!1;export function installFlowFetch(e={}){const o=globalThis;if(typeof o.fetch!="function")return()=>{};if(o.fetch[U])return()=>{};if(!W&&typeof location<"u"&&typeof document<"u"){W=!0;const t=K({originType:"page-load",originNodeId:`page:${location.pathname}`});J(t.flowId)}const d=e.flowHeader??"x-lensmcp-flow-id",u=e.originHeader??"x-lensmcp-origin-node-id",i=e.requestHeader??"x-request-id",l=e.propagateTo??[],a=o.fetch.bind(globalThis);globalThis.__LENSMCP_FLOW_FETCH__=!0;const h=c(((t,r)=>{if(r?.[D])return a(t,r);const w=j();if(!w?.flowId){if(!C()&&!G())return a(t,r);const m=I(t);if(!mayPropagateTo(m,[...l,...$()])){const P=a(t,b(r));return x(P,y(t,r),m,void 0,void 0),L(P,y(t,r),m,void 0,void 0),P}const S=new Headers(r?.headers??(typeof t=="object"&&t!==null&&"headers"in t?t.headers:void 0)??void 0),k=S.get(i)??F();S.has(i)||S.set(i,k);const R=a(t,{...b(r),headers:S});return x(R,y(t,r),m,k,void 0),L(R,y(t,r),m,k,void 0),R}if(!mayPropagateTo(I(t),[...l,...$()])){const m=a(t,b(r));return q(w,t,r,m,void 0),x(m,y(t,r),I(t),void 0,w.flowId),L(m,y(t,r),I(t),void 0,w.flowId),m}const v=typeof t=="object"&&t!==null&&"headers"in t?t.headers:void 0,p=new Headers(r?.headers??v??void 0);p.has(d)||p.set(d,w.flowId),w.originNodeId&&!p.has(u)&&p.set(u,w.originNodeId);const H=p.get(i)??F();p.has(i)||p.set(i,H);const T=a(t,{...b(r),headers:p});return q(w,t,r,T,H),x(T,y(t,r),I(t),H,w.flowId),L(T,y(t,r),I(t),H,w.flowId),T}),"patched");h[U]=!0,o.fetch=h;const n=M({flowHeader:d,originHeader:u,requestHeader:i,propagate:c(t=>mayPropagateTo(t,[...l,...$()]),"propagate")}),s=e.routeFlows===!1?()=>{}:z();return()=>{s(),n(),o.fetch=a}}f(installFlowFetch,"installFlowFetch"),g(installFlowFetch,"installFlowFetch"),c(installFlowFetch,"installFlowFetch");const N=Symbol.for("lensmcp.flow-xhr");function M(e){const o=globalThis.XMLHttpRequest;if(typeof o!="function")return()=>{};const d=o.prototype;if(d[N])return()=>{};const u=d.open,i=d.send,l=d.setRequestHeader,a=new WeakMap;d.open=c(function(n,s,...t){return a.set(this,{method:String(n).toUpperCase(),url:String(s),headers:new Map}),u.call(this,n,s,...t)},"patchedOpen"),d.setRequestHeader=c(function(n,s){return a.get(this)?.headers.set(String(n).toLowerCase(),String(s)),l.call(this,n,s)},"patchedSetHeader"),d.send=c(function(n){const s=a.get(this);if(s)try{h(this,s)}catch{}return i.call(this,n)},"patchedSend"),d[N]=!0;function h(n,s){const t=j(),r=C(),w=G();if(!t?.flowId&&!r&&!w)return;let v;e.propagate(s.url)&&(t?.flowId&&(s.headers.has(e.flowHeader)||l.call(n,e.flowHeader,t.flowId),t.originNodeId&&!s.headers.has(e.originHeader)&&l.call(n,e.originHeader,t.originNodeId)),v=s.headers.get(e.requestHeader)??F(),s.headers.has(e.requestHeader)||l.call(n,e.requestHeader,v));const p=new Promise((H,T)=>{n.addEventListener("loadend",()=>n.status===0?T(new Error("XMLHttpRequest failed")):H({status:n.status,statusText:n.statusText,ok:n.status>=200&&n.status<300}),{once:!0})});t?.flowId&&q(t,s.url,{method:s.method},p,v,"xhr"),(t?.flowId||r)&&x(p,s.method,s.url,v,t?.flowId),L(p,s.method,s.url,v,t?.flowId),p.catch(()=>{})}return f(h,"p"),g(h,"g"),c(h,"xhrLeg"),()=>{d.open=u,d.send=i,d.setRequestHeader=l,delete d[N]}}f(M,"U"),g(M,"K"),c(M,"installFlowXhr");function y(e,o){return o?.method??(typeof e=="object"&&e!==null&&"method"in e?e.method??"GET":"GET")}f(y,"m"),g(y,"y"),c(y,"methodOf");function O(e){const o=typeof location<"u"?location.href:void 0;try{return new URL(e,o).href}catch{return}}f(O,"D"),g(O,"V"),c(O,"absoluteHref");function q(e,o,d,u,i,l){const a=I(o),h=O(a),n=d?.method??(typeof o=="object"&&o!==null&&"method"in o?o.method??"GET":"GET"),s=Date.now(),t={flowId:e.flowId,...e.originType?{originType:e.originType}:{},...e.originNodeId?{originNodeId:e.originNodeId}:{},...i?{requestId:i}:{}};E({source:"react",category:"network",severity:"info",title:`fetch ${n} ${a}`,fingerprint:`flow-fetch:${n}:${a}`,context:t,raw:{kind:"fetch-start",url:a,method:n,...h?{href:h}:{},...i?{requestId:i}:{},...l?{transport:l}:{}}}),u.then(r=>{A(e),E({source:"react",category:"network",severity:r.ok||r.status===304?"info":"error",title:`fetch ${n} ${a} \u2192 ${r.status}${r.statusText?` ${r.statusText}`:""}`,fingerprint:`flow-fetch:${n}:${a}:${r.status}`,context:t,raw:{kind:"fetch-done",url:a,...h?{href:h}:{},...i?{requestId:i}:{},method:n,status:r.status,statusText:r.statusText,ok:r.ok,startedAt:s,durationMs:Date.now()-s}})},r=>{A(e),E({source:"react",category:"network",severity:"error",title:`fetch ${n} ${a} failed`,message:r instanceof Error?r.message:String(r),fingerprint:`flow-fetch:${n}:${a}:error`,context:t,raw:{kind:"fetch-error",url:a,...h?{href:h}:{},...i?{requestId:i}:{},method:n,startedAt:s,durationMs:Date.now()-s}})})}f(q,"q"),g(q,"x"),c(q,"publishFetchLeg");
|
package/lib/hoc.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var w=Object.defineProperty;var a=(e,n)=>w(e,"name",{value:n,configurable:!0});var I=Object.defineProperty,i=a((e,n)=>I(e,"name",{value:n,configurable:!0}),"o"),b=Object.defineProperty,m=i((e,n)=>b(e,"name",{value:n,configurable:!0}),"t");import{jsx as s}from"react/jsx-runtime";import{Profiler as $}from"react";import{publish as g}from"./publish.js";import{makeInstanceId as v}from"./identity.js";export function withTraceComponent(e,n={}){const r=n.componentName??e.displayName??e.name??"TracedComponent",t=`react:component:${n.source??"(unknown)"}:${r}`;function o(u){let d;return s($,{id:t,onRender:m((C,p,f,l,T,y)=>{const{instanceId:c}=v(t),h={id:c,parentRenderId:d,componentInstanceId:c,componentLogicalId:t,componentName:r,phase:p==="mount"?"mount":"update",actualDurationMs:f,baseDurationMs:l,startTime:T,commitTime:y,why:[{type:"force",reason:"withTraceComponent"}]};d=c,g({source:"react",category:"render",severity:"info",title:`render ${r} (${p})`,fingerprint:`react-render:${t}`,raw:{kind:"render",render:h}})},"onRender"),children:s(e,{...u})})}return a(o,"a"),i(o,"a"),m(o,"Traced"),o.displayName=`Traced(${r})`,o}a(withTraceComponent,"withTraceComponent"),i(withTraceComponent,"withTraceComponent"),m(withTraceComponent,"withTraceComponent");
|
package/lib/identity.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var f=Object.defineProperty;var
|
|
1
|
+
"use strict";var f=Object.defineProperty;var n=(e,t)=>f(e,"name",{value:t,configurable:!0});var p=Object.defineProperty,o=n((e,t)=>p(e,"name",{value:t,configurable:!0}),"e"),I=Object.defineProperty,r=o((e,t)=>I(e,"name",{value:t,configurable:!0}),"n");const l=new Map;let s=0;export function nextGeneration(e){const t=(l.get(e)??0)+1;return l.set(e,t),t}n(nextGeneration,"nextGeneration"),o(nextGeneration,"nextGeneration"),r(nextGeneration,"nextGeneration");export function shortHash(){return s=(s+1)%4294967295,(Date.now()&4095^s).toString(36).slice(-4)}n(shortHash,"shortHash"),o(shortHash,"shortHash"),r(shortHash,"shortHash");export function componentLogicalId(e,t){return`react:component:${e}:${t}`}n(componentLogicalId,"componentLogicalId"),o(componentLogicalId,"componentLogicalId"),r(componentLogicalId,"componentLogicalId");export function hookLogicalId(e,t,i,c){return`react:hook:${e}:${t}:${i}:${c}`}n(hookLogicalId,"hookLogicalId"),o(hookLogicalId,"hookLogicalId"),r(hookLogicalId,"hookLogicalId");export function slotLogicalId(e,t,i){return`react:slot:${e}:${t}:${i}`}n(slotLogicalId,"slotLogicalId"),o(slotLogicalId,"slotLogicalId"),r(slotLogicalId,"slotLogicalId");export function makeInstanceId(e){const t=nextGeneration(e);return{instanceId:`${e}#${t}#${shortHash()}`,generation:t}}n(makeInstanceId,"makeInstanceId"),o(makeInstanceId,"makeInstanceId"),r(makeInstanceId,"makeInstanceId");export function depsHash(e){if(!e)return"no-deps";let t=5381;const i=r(c=>{for(let a=0;a<c.length;a++)t=t*33^c.charCodeAt(a);t=t*33^59},"mix");for(const c of e){if(c===null){i("null");continue}const a=typeof c;i(a==="object"||a==="function"?`ref:${u(c)}`:`${a}:${String(c)}`)}return(t>>>0).toString(36)}n(depsHash,"depsHash"),o(depsHash,"depsHash"),r(depsHash,"depsHash");const d=new WeakMap;let g=1;function u(e){let t=d.get(e);return t===void 0&&(t=g++,d.set(e,t)),t}n(u,"l"),o(u,"p"),r(u,"refId");export function resetIdentityState(){l.clear(),s=0}n(resetIdentityState,"resetIdentityState"),o(resetIdentityState,"resetIdentityState"),r(resetIdentityState,"resetIdentityState");
|
package/lib/lensmcp-root.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var w=Object.defineProperty;var i=(e,r)=>w(e,"name",{value:r,configurable:!0});var
|
|
1
|
+
"use strict";var w=Object.defineProperty;var i=(e,r)=>w(e,"name",{value:r,configurable:!0});var L=Object.defineProperty,u=i((e,r)=>L(e,"name",{value:r,configurable:!0}),"i"),M=Object.defineProperty,m=u((e,r)=>M(e,"name",{value:r,configurable:!0}),"c");import{jsx as f}from"react/jsx-runtime";import{Profiler as P,useMemo as $,useRef as s}from"react";import{LensmcpContext as j}from"./context.js";import{publish as x}from"./publish.js";import{makeInstanceId as k}from"./identity.js";import{fiberRendersActive as D,installFiberRenderPublisher as O}from"./fiber-renders.js";typeof window<"u"&&O();export function LensmcpRoot(e){const r=e.rendererId??"lensmcp-root",l=$(()=>({rendererId:r,page:e.page,route:e.route}),[r,e.page,e.route]),g=s(new Map),c=s(new Map),d=s(void 0),v=m((n,p,I,b,R,h)=>{const a=`render:${r}:${n}`,{instanceId:o}=k(a);let t=c.current.get(n);t===void 0&&(t=o,c.current.set(n,t));const y={id:o,parentRenderId:d.current,componentInstanceId:t,componentLogicalId:a,componentName:n,page:e.page,route:e.route,rendererId:r,phase:p==="mount"?"mount":"update",actualDurationMs:I,baseDurationMs:b,startTime:R,commitTime:h,why:[{type:"force",reason:"profiler-onrender"}]};d.current=o,g.current.set(n,o),!D()&&x({source:"react",category:"render",severity:"info",title:`render ${n} (${p})`,fingerprint:`react-render:${a}`,raw:{kind:"render",render:y}})},"onRender");return f(j.Provider,{value:l,children:f(P,{id:r,onRender:v,children:e.children})})}i(LensmcpRoot,"LensmcpRoot"),u(LensmcpRoot,"LensmcpRoot"),m(LensmcpRoot,"LensmcpRoot");
|
package/lib/page-perf.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var E=Object.defineProperty;var c=(n,e)=>E(n,"name",{value:e,configurable:!0});var P=Object.defineProperty,d=c((n,e)=>P(n,"name",{value:e,configurable:!0}),"c"),S=Object.defineProperty,a=d((n,e)=>S(n,"name",{value:e,configurable:!0}),"a");const M=600,O=3e3,o=a(n=>typeof n=="number"&&Number.isFinite(n)?n:0,"num"),h=a(n=>Math.round(n*10)/10,"r1");export class PagePerf{static{c(this,"PagePerf")}static{d(this,"PagePerf")}static{a(this,"PagePerf")}constructor(e){this.host=e,this.marks=[],this.scripts=[],this.loaf=!1;const i=a(s=>e.timeOrigin+o(s.startTime),"at");e.observe("largest-contentful-paint",s=>{for(const t of s)this.push({type:"lcp",at:i(t),dur:0,value:o(t.startTime)})}),e.observe("layout-shift",s=>{for(const t of s)t.hadRecentInput!==!0&&this.push({type:"shift",at:i(t),dur:0,value:o(t.value)})}),e.observe("event",s=>{for(const t of s)o(t.interactionId)>0&&this.push({type:"event",at:i(t),dur:o(t.duration),value:0})}),this.loaf=e.observe("long-animation-frame",s=>{for(const t of s)this.push({type:"long",at:i(t),dur:o(t.duration),value:0})}),this.loaf||e.observe("longtask",s=>{for(const t of s)this.push({type:"long",at:i(t),dur:o(t.duration),value:0})}),e.observe("resource",s=>{for(const t of s)t.initiatorType!=="script"&&!/\.(m?js|tsx?|jsx)(\?|$)/.test(String(t.name??""))||/\/@lensmcp\//.test(String(t.name??""))||(this.scripts.push({at:i(t),kb:(o(t.transferSize)||o(t.encodedBodySize))/1024}),this.scripts.length>3e3&&this.scripts.splice(0,this.scripts.length-3e3))})}window(e){const i=a(r=>r.at>=e.startAt&&r.at<=e.toAt,"inside"),s={};if(e.hard){const r=this.host.navigation();r&&(o(r.responseStart)>0&&(s.ttfb=h(o(r.responseStart))),o(r.domContentLoadedEventEnd)>0&&(s.dcl=h(o(r.domContentLoadedEventEnd))),o(r.loadEventEnd)>0&&(s.load=h(o(r.loadEventEnd))));const y=this.host.paint("first-contentful-paint");y!==void 0&&(s.fcp=h(y));const b=this.marks.filter(k=>k.type==="lcp"&&k.at<=e.toAt).at(-1);b&&(s.lcp=h(b.value))}let t=0,p=0,u=0,v=0,f=0;for(const r of this.marks)i(r)&&(r.type==="shift"?t+=r.value:r.type==="event"?p=Math.max(p,r.dur):r.type==="long"&&(u++,v+=r.dur,f=Math.max(f,r.dur)));t>0&&(s.cls=Math.round(t*1e3)/1e3),p>0&&(s.inp=h(p));let l=0,m=0;for(const r of this.scripts)r.at<e.startAt||r.at>e.toAt||(l++,m+=r.kb);const g=this.host.heapBytes();return{...Object.keys(s).length?{vitals:s}:{},...u?{longTasks:{n:u,totalMs:h(v),maxMs:h(f)}}:{},...g!==void 0?{heapMb:h(g/(1<<20))}:{},...l?{chunks:{n:l,kb:Math.round(m)}}:{}}}push(e){this.marks.push(e),this.marks.length>600&&this.marks.splice(0,this.marks.length-600)}}export function browserPerfHost(){const n=globalThis,e=n.performance,i=n.PerformanceObserver;if(!e||!i||typeof e.timeOrigin!="number")return;const s=new Set(i.supportedEntryTypes??[]);return{timeOrigin:e.timeOrigin,observe(t,p){if(!s.has(t))return!1;try{return new i(u=>p(u.getEntries())).observe({type:t,buffered:!0,...t==="event"?{durationThreshold:16}:{}}),!0}catch{return!1}},navigation:a(()=>e.getEntriesByType?.("navigation")?.[0]?.toJSON?.(),"navigation"),paint:a(t=>e.getEntriesByName?.(t,"paint")?.[0]?.startTime,"paint"),heapBytes:a(()=>e.memory?.usedJSHeapSize,"heapBytes")}}c(browserPerfHost,"browserPerfHost"),d(browserPerfHost,"browserPerfHost"),a(browserPerfHost,"browserPerfHost");
|
|
@@ -1,4 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The page-visit tracker in the browser (`page-visits.ts`): one per tab, shared by every copy of this module.
|
|
3
|
+
*
|
|
4
|
+
* An app can load this library twice — FoodGuard's dashboard and its shared UI library each render a React root, and
|
|
5
|
+
* each copy installs its hooks (issues/closed/foodguard-38: every request reached the bus twice). So the tracker
|
|
6
|
+
* lives on `globalThis`, the hard load starts it once, and the commits come from whichever copy's fiber subscriber
|
|
7
|
+
* claimed them first. Navigations reach it from every copy and the tracker drops a repeat of the same path; fetches
|
|
8
|
+
* from the one wrapper the fetch mark allows.
|
|
9
|
+
*/
|
|
10
|
+
import type { PageVisitRaw } from '@lensmcp/protocol-types';
|
|
1
11
|
import { type PageCommit } from './page-visits.js';
|
|
12
|
+
/**
|
|
13
|
+
* A visit's moments on the session replay (planning/replay/00-plan.md §2.4): ready and end, and — once an SPA visit is
|
|
14
|
+
* ready — a fresh snapshot when the page is idle, so the visit plays on its own. A hard load needs none: it has the
|
|
15
|
+
* base snapshot and its first render already.
|
|
16
|
+
*/
|
|
17
|
+
export declare function replayVisit(raw: Pick<PageVisitRaw, 'visitId' | 'phase' | 'nav' | 'pattern' | 'readyBy' | 'readyMs'>): void;
|
|
18
|
+
/** A visit began: the bus hears of it only at ready, the recording marks the moment now. */
|
|
19
|
+
export declare function replayVisitStart(v: {
|
|
20
|
+
visitId: string;
|
|
21
|
+
path: string;
|
|
22
|
+
nav: 'hard' | 'spa';
|
|
23
|
+
startAt: number;
|
|
24
|
+
}): void;
|
|
2
25
|
/** The hard load: from navigation start, once per document. `flowId`: the page-load flow. */
|
|
3
26
|
export declare function startHardPageVisit(flowId?: string): void;
|
|
4
27
|
/** A pathname change through the history API (after it happened). */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var u=Object.defineProperty;var i=(t
|
|
1
|
+
"use strict";var u=Object.defineProperty;var i=(e,t)=>u(e,"name",{value:t,configurable:!0});var l=Object.defineProperty,s=i((e,t)=>l(e,"name",{value:t,configurable:!0}),"i"),v=Object.defineProperty,n=s((e,t)=>v(e,"name",{value:t,configurable:!0}),"a");import{publish as P}from"./publish.js";import{PageVisitTracker as _}from"./page-visits.js";import{browserPerfHost as w,PagePerf as S}from"./page-perf.js";import{replayCheckpoint as b,replayMark as h}from"./replay-anchors.js";const f="__LENSMCP_PAGE_VISITS__";function g(){return typeof window<"u"&&typeof location<"u"&&typeof document<"u"}i(g,"y"),s(g,"_"),n(g,"browser");function d(){if(!g())return;const e=globalThis,t=e[f];if(t===!1)return;if(t)return t;const a=typeof e.__LENSMCP_APP__=="string"&&e.__LENSMCP_APP__?e.__LENSMCP_APP__:location.host||"app";let c;try{const r=w();c=r?new S(r):void 0}catch{c=void 0}const o={tracker:new _({app:a,...c?{perf:n(r=>c.window(r),"perf")}:{},emit:n((r,p)=>{P({source:"react",category:"performance",severity:r.readyBy==="timeout"?"warning":"info",title:p,fingerprint:`page-visit:${r.visitId}:${r.phase}`,detached:!0,raw:r}),replayVisit(r)},"emit"),onStart:replayVisitStart,tabId:n(()=>{try{return sessionStorage.getItem("lensmcp:tabId")??void 0}catch{return}},"tabId"),base:n(()=>location.href,"base")}),hardStarted:!1};e[f]=o;try{window.addEventListener("beforeunload",()=>o.tracker.pagehide()),window.addEventListener("pagehide",()=>o.tracker.pagehide()),window.addEventListener("error",r=>o.tracker.error(r.message||"error")),window.addEventListener("unhandledrejection",r=>{const p=r.reason;o.tracker.error(p instanceof Error?`${p.name}: ${p.message}`:String(p))})}catch{}return o}i(d,"p"),s(d,"p"),n(d,"shared");export function replayVisit(e){h("lens/visit",{visitId:e.visitId,phase:e.phase,...e.pattern?{pattern:e.pattern}:{},...e.readyBy?{readyBy:e.readyBy}:{},...e.readyMs!==void 0?{readyMs:e.readyMs}:{}}),e.phase==="ready"&&e.nav==="spa"&&e.readyBy!=="left"&&b()}i(replayVisit,"replayVisit"),s(replayVisit,"replayVisit"),n(replayVisit,"replayVisit");export function replayVisitStart(e){h("lens/visit",{visitId:e.visitId,phase:"start",path:e.path,nav:e.nav,startAt:e.startAt})}i(replayVisitStart,"replayVisitStart"),s(replayVisitStart,"replayVisitStart"),n(replayVisitStart,"replayVisitStart");export function startHardPageVisit(e){const t=d();if(!(!t||t.hardStarted)){t.hardStarted=!0;try{const a=Date.now(),c=typeof performance<"u"&&typeof performance.timeOrigin=="number"?Math.round(performance.timeOrigin):a,o=(typeof performance<"u"&&typeof performance.getEntriesByType=="function"?performance.getEntriesByType("navigation")[0]:void 0)?.type,r=o==="navigate"||o==="reload"||o==="back_forward"?o:void 0;t.tracker.hard({path:location.pathname,startAt:Math.min(c,a),appStartAt:a,...r?{navType:r}:{},...y()?{cause:"hmr"}:{},...e?{flowId:e}:{}})}catch{}}}i(startHardPageVisit,"startHardPageVisit"),s(startHardPageVisit,"startHardPageVisit"),n(startHardPageVisit,"startHardPageVisit");function y(){if(globalThis.__LENSMCP_RELOAD_CAUSE__)return!0;try{return!!sessionStorage.getItem("lensmcp:reloadCause")}catch{return!1}}i(y,"h"),s(y,"P"),n(y,"hmrReload");export function notePageNavigation(e,t,a){try{d()?.tracker.navigate({path:e,how:t,...a?{flowId:a}:{}})}catch{}}i(notePageNavigation,"notePageNavigation"),s(notePageNavigation,"notePageNavigation"),n(notePageNavigation,"notePageNavigation");export function pageVisitOpen(){const e=globalThis[f];return!!e&&e.tracker.open()}i(pageVisitOpen,"pageVisitOpen"),s(pageVisitOpen,"pageVisitOpen"),n(pageVisitOpen,"pageVisitOpen");export function notePageFetch(e,t,a,c,o){const r=d();if(r)try{const p=r.tracker.fetchStarted({method:t,url:a,...c?{rid:c}:{},...o?{flowId:o}:{}});e.then(m=>p(m.status),()=>p(0))}catch{}}i(notePageFetch,"notePageFetch"),s(notePageFetch,"notePageFetch"),n(notePageFetch,"notePageFetch");export function notePageCommit(e,t){const a=d();if(a&&(a.commitsBy??=e,a.commitsBy===e))try{a.tracker.commit(t)}catch{}}i(notePageCommit,"notePageCommit"),s(notePageCommit,"notePageCommit"),n(notePageCommit,"notePageCommit");export function notePageState(e,t){const a=globalThis[f];if(a)try{a.tracker.storeUpdated(e,t)}catch{}}i(notePageState,"notePageState"),s(notePageState,"notePageState"),n(notePageState,"notePageState");
|
package/lib/page-visits.d.ts
CHANGED
|
@@ -58,6 +58,13 @@ export interface PageVisitTrackerOptions {
|
|
|
58
58
|
base?: () => string | undefined;
|
|
59
59
|
/** The browser's own timings within a window of the visit (page-perf.ts): vitals, long tasks, heap, scripts. */
|
|
60
60
|
perf?: (w: PerfWindow) => Pick<PageVisitRaw, 'vitals' | 'longTasks' | 'heapMb' | 'chunks'>;
|
|
61
|
+
/** A visit began (the bus hears of it only at ready): the session replay marks the moment. */
|
|
62
|
+
onStart?: (v: {
|
|
63
|
+
visitId: string;
|
|
64
|
+
path: string;
|
|
65
|
+
nav: 'hard' | 'spa';
|
|
66
|
+
startAt: number;
|
|
67
|
+
}) => void;
|
|
61
68
|
}
|
|
62
69
|
interface RenderTally {
|
|
63
70
|
commits: number;
|
package/lib/page-visits.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var f=Object.defineProperty;var l=(r,t)=>f(r,"name",{value:t,configurable:!0});var y=Object.defineProperty,u=l((r,t)=>y(r,"name",{value:t,configurable:!0}),"l"),A=Object.defineProperty,d=u((r,t)=>A(r,"name",{value:t,configurable:!0}),"o");export const QUIET_MS=100,READY_CAP_MS=3e4,NO_COMMIT_MS=1e3,END_AFTER_READY_MS=6e4;const C=60,S=200,q=8,k=20,w={now:d(()=>Date.now(),"now"),setTimeout:d((r,t)=>setTimeout(r,t),"setTimeout"),clearTimeout:d(r=>clearTimeout(r),"clearTimeout")},c=d((r,t=200)=>r.length>t?r.slice(0,t):r,"clip");function v(r){let t=2166136261;for(let s=0;s<r.length;s++)t^=r.charCodeAt(s),t=Math.imul(t,16777619);return(t>>>0).toString(36)}l(v,"u"),u(v,"l"),d(v,"shortHash");export function templatePath(r){return r.split("/").map(t=>/^\d+$/.test(t)||/^[0-9a-f]{8}-[0-9a-f]{4}-/i.test(t)||/^[0-9a-zA-Z_-]{20,}$/.test(t)?":id":t).join("/")}l(templatePath,"templatePath"),u(templatePath,"templatePath"),d(templatePath,"templatePath");const T=d(()=>({commits:0,renders:0,renderMs:0,maxCommitMs:0,stormCommits:0,mounts:0,suspenseWaits:0,byName:new Map}),"newTally");let g=0;const M=d(r=>`pv-${r.toString(36)}-${(++g).toString(36)}${Math.random().toString(36).slice(2,6)}`,"newVisitId");export class PageVisitTracker{static{l(this,"PageVisitTracker")}static{u(this,"PageVisitTracker")}static{d(this,"PageVisitTracker")}constructor(t){this.opts=t,this.clock=t.clock??w}current(){return this.visit}open(){return this.visit!==void 0}hard(t){this.begin({nav:"hard",path:t.path,startAt:t.startAt,appStartAt:t.appStartAt,...t.navType?{navType:t.navType}:{},...t.cause?{cause:t.cause}:{},...t.flowId?{flowId:t.flowId}:{}})}navigate(t){const s=this.visit;if(!(s&&c(t.path)===s.path)){if(s&&t.how==="replace"&&s.readyAt===void 0){s.redirectedFrom??=s.path,s.path=c(t.path),s.pattern=void 0,t.flowId&&s.flowIds.add(t.flowId);return}this.begin({nav:"spa",path:t.path,startAt:this.clock.now(),navType:t.how,...t.flowId?{flowId:t.flowId}:{}})}}fetchStarted(t){const s=this.visit;if(!s)return()=>{};const e=this.clock.now();t.flowId&&s.flowIds.add(t.flowId);const o=this.where(t.url),a=s.readyAt!==void 0;let i;if(s.requests.length<60?(i={rid:t.rid??"",m:t.method.toUpperCase(),p:o.p,...o.qh?{qh:o.qh}:{},s:Math.max(0,e-s.startAt),...t.flowId?{flowId:t.flowId}:{},...a?{late:!0}:{}},s.requests.push(i)):s.dropped++,a)return s.after.requests++,s.after.templates.size<20&&s.after.templates.add(`${t.method.toUpperCase()} ${templatePath(o.path)}`),m=>{i&&(i.d=Math.max(0,this.clock.now()-s.startAt-i.s),i.st=m)};s.open++,this.cancelCandidate(s),this.clearTimer(s,"noCommit");let p=!1;return m=>{p||(p=!0,i&&(i.d=Math.max(0,this.clock.now()-s.startAt-i.s),i.st=m),!(this.visit!==s||s.readyAt!==void 0)&&(s.open=Math.max(0,s.open-1),s.open===0&&(s.noCommit=this.clock.setTimeout(()=>{s.noCommit=void 0,this.visit===s&&s.readyAt===void 0&&s.open===0&&this.ready(s,s.lastCommitAt??this.clock.now(),"no-commit")},1e3))))}}commit(t){const s=this.visit;if(s){if(t.pattern&&s.readyBy===void 0&&(s.pattern=t.pattern),s.readyAt!==void 0){s.after.renders+=t.renders.length;return}if(t.renders.length>0){const e=s.r;e.commits++,e.renders+=t.renders.length;let o=0;for(const a of t.renders){a.ms>o&&(o=a.ms),a.mount&&e.mounts++;const i=e.byName.get(a.name);i?(i.n++,i.ms+=a.ms):e.byName.set(a.name,{n:1,ms:a.ms})}e.renderMs+=o,o>e.maxCommitMs&&(e.maxCommitMs=o),t.storm&&e.stormCommits++}if(t.suspense&&s.r.suspenseWaits++,s.lastCommitAt=t.at,this.clearTimer(s,"noCommit"),s.open>0||t.suspense){this.cancelCandidate(s);return}this.cancelCandidate(s),s.candidate=t.at,s.quiet=this.clock.setTimeout(()=>{s.quiet=void 0,!(this.visit!==s||s.readyAt!==void 0||s.candidate===void 0)&&this.ready(s,s.candidate,s.requests.length?"settled":"no-requests")},100)}}storeUpdated(t,s){const e=this.visit;if(!e)return;if(e.readyAt!==void 0){e.after.updates++;return}e.updates++;const o=`${t}\0${s}`,a=e.byStore.get(o);a?a.n++:e.byStore.size<200&&e.byStore.set(o,{store:t,path:c(s,120),n:1})}error(t){const s=this.visit;s&&(s.errors++,s.firstError??=c(t,200))}pagehide(){this.visit&&this.finish(this.visit)}begin(t){this.visit&&this.finish(this.visit);const s={id:M(t.startAt),nav:t.nav,...t.navType?{navType:t.navType}:{},...t.cause?{cause:t.cause}:{},path:c(t.path),startAt:t.startAt,...t.appStartAt!==void 0?{appStartAt:t.appStartAt}:{},flowIds:new Set(t.flowId?[t.flowId]:[]),requests:[],dropped:0,open:0,r:T(),updates:0,byStore:new Map,errors:0,after:{requests:0,templates:new Set,renders:0,updates:0}};this.visit=s;try{this.opts.onStart?.({visitId:s.id,path:s.path,nav:s.nav,startAt:s.startAt})}catch{}s.cap=this.clock.setTimeout(()=>{s.cap=void 0,this.visit===s&&s.readyAt===void 0&&this.ready(s,this.clock.now(),"timeout")},Math.max(0,3e4-(this.clock.now()-s.startAt)))}ready(t,s,e){t.readyAt=e==="left"?void 0:s,t.readyBy=e,this.clearTimer(t,"quiet"),this.clearTimer(t,"noCommit"),this.clearTimer(t,"cap"),t.candidate=void 0,this.send(t,"ready"),e!=="left"&&(t.end=this.clock.setTimeout(()=>{t.end=void 0,this.visit===t&&this.finish(t)},6e4))}finish(t){t.readyBy===void 0&&this.ready(t,this.clock.now(),"left");for(const s of["quiet","noCommit","cap","end"])this.clearTimer(t,s);this.send(t,"end"),this.visit===t&&(this.visit=void 0)}send(t,s){const e=t.r,o=this.opts.tabId?.(),a=t.readyAt!==void 0?Math.max(0,t.readyAt-t.startAt):void 0,i={kind:"page-visit",phase:s,visitId:t.id,...o?{tabId:o}:{},app:this.opts.app,...t.pattern?{pattern:t.pattern}:{},path:t.path,nav:t.nav,...t.navType?{navType:t.navType}:{},...t.cause?{cause:t.cause}:{},...t.redirectedFrom?{redirectedFrom:t.redirectedFrom}:{},startAt:t.startAt,...t.readyAt!==void 0?{readyAt:t.readyAt}:{},...t.readyBy?{readyBy:t.readyBy}:{},...a!==void 0?{readyMs:a}:{},...a!==void 0&&t.appStartAt!==void 0?{appReadyMs:Math.max(0,t.readyAt-t.appStartAt)}:{},...s==="end"?{endAt:this.clock.now()}:{},flowIds:[...t.flowIds].slice(0,20),requests:t.requests.map(n=>({...n})),...t.dropped?{requestsDropped:t.dropped}:{},renders:{commits:e.commits,renders:e.renders,renderMs:Math.round(e.renderMs*10)/10,maxCommitMs:Math.round(e.maxCommitMs*10)/10,stormCommits:e.stormCommits,mounts:e.mounts,suspenseWaits:e.suspenseWaits,top:[...e.byName.entries()].sort((n,h)=>h[1].n-n[1].n||h[1].ms-n[1].ms).slice(0,8).map(([n,h])=>({name:n,n:h.n,ms:Math.round(h.ms*10)/10}))},store:{updates:t.updates,top:[...t.byStore.values()].sort((n,h)=>h.n-n.n).slice(0,8)},errors:{n:t.errors,...t.firstError?{first:t.firstError}:{}},...s==="end"?{afterReady:{requests:t.after.requests,templates:[...t.after.templates],renders:t.after.renders,updates:t.after.updates}}:{}};try{const n=s==="ready"?t.readyAt??this.clock.now():this.clock.now();this.opts.perf&&Object.assign(i,this.opts.perf({startAt:t.startAt,toAt:n,hard:t.nav==="hard"}))}catch{}const p=t.pattern??t.path,m=s==="end"?`page visit ended ${p}`:t.readyBy==="left"?`page left before ready ${p}`:t.readyBy==="timeout"?`page not ready in ${3e4/1e3}s ${p} \u2014 ${t.requests.filter(n=>n.d===void 0).length} requests open`:`page ready ${p} \xB7 ${a} ms`;try{this.opts.emit(i,m)}catch{}}where(t){try{const s=new URL(t,this.opts.base?.()??"http://localhost/"),e=s.search.length>1?v(s.search):void 0;return{p:c(`${s.host}${s.pathname}`),path:s.pathname,...e?{qh:e}:{}}}catch{const[s=""]=t.split("?");return{p:c(s),path:s}}}cancelCandidate(t){t.candidate=void 0,this.clearTimer(t,"quiet")}clearTimer(t,s){t[s]!==void 0&&(this.clock.clearTimeout(t[s]),t[s]=void 0)}}
|
package/lib/publish.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var $=Object.defineProperty;var e=(o,n)=>$(o,"name",{value:n,configurable:!0});var q=Object.defineProperty,i=e((o,n)=>q(o,"name",{value:n,configurable:!0}),"t"),U=Object.defineProperty,t=i((o,n)=>U(o,"name",{value:n,configurable:!0}),"t");import{createEventFloodGuard as j,estimateJsonBytes as z}from"@lensmcp/protocol-types";import{replayMark as P}from"./replay-anchors.js";const l=[],X=200,C=(()=>{const o=typeof process<"u"?process.env?.LENSMCP_PUBLISH_QUEUE_BYTES:void 0,n=Number(o);return Number.isFinite(n)&&n>0?Math.floor(n):1024*1024})(),F=[];let c=0;function v(o){const n=z(o,C);for(l.push(o),F.push(n),c+=n;l.length>X||c>C&&l.length>1;)l.shift(),c-=F.shift()??0;l.length===0&&(c=0)}e(v,"L"),i(v,"P"),t(v,"enqueue");function T(){const o=l.shift();return c-=F.shift()??0,l.length===0&&(c=0),o}e(T,"E"),i(T,"C"),t(T,"dequeue");export function queuedByteCount(){return c}e(queuedByteCount,"queuedByteCount"),i(queuedByteCount,"queuedByteCount"),t(queuedByteCount,"queuedByteCount");const w=[],x=4e3;let d;export const DEFAULT_AMBIENT_FLOW_MAX_MS=3e4;let b;function g(o){if(o==="off"||o==="Infinity")return 1/0;const n=typeof o=="string"&&o.trim()!==""?Number(o):o;if(!(typeof n!="number"||Number.isNaN(n)||n<0))return n===0||n===1/0?1/0:n}e(g,"N"),i(g,"m"),t(g,"parseMaxLifetime");function M(){if(b!==void 0)return b;const o=g(globalThis.__LENSMCP_AMBIENT_FLOW_MAX_MS__);return o!==void 0?o:g(typeof process<"u"?process.env?.LENSMCP_AMBIENT_FLOW_MAX_MS:void 0)??DEFAULT_AMBIENT_FLOW_MAX_MS}e(M,"B"),i(M,"X"),t(M,"ambientMaxMs");export function configureAmbientFlows(o){b=o.maxLifetimeMs===void 0?void 0:g(o.maxLifetimeMs)}e(configureAmbientFlows,"configureAmbientFlows"),i(configureAmbientFlows,"configureAmbientFlows"),t(configureAmbientFlows,"configureAmbientFlows");const f=new Map,Q=16;function S(o){for(f.set(o,{bornAt:Date.now()});f.size>Q;)f.delete(f.keys().next().value)}e(S,"k"),i(S,"Q"),t(S,"trackAmbient");function h(o){const n=f.get(o.flowId);if(!n)return!1;const r=M();return r!==1/0&&Date.now()-n.bornAt>=r}e(h,"b"),i(h,"x"),t(h,"ambientExhausted");export function extendFlowWindow(o){const n=o??currentFlow()??d?.spec;n&&(h(n)||(d={spec:n,until:Date.now()+x}))}e(extendFlowWindow,"extendFlowWindow"),i(extendFlowWindow,"extendFlowWindow"),t(extendFlowWindow,"extendFlowWindow");function p(){return d&&Date.now()<d.until?d.spec:void 0}e(p,"a"),i(p,"y"),t(p,"windowedFlow");export function activeFlow(){return currentFlow()??p()}e(activeFlow,"activeFlow"),i(activeFlow,"activeFlow"),t(activeFlow,"activeFlow");export function beginBackgroundFlow(o){const n={flowId:I(),originType:o.originType,...o.originNodeId?{originNodeId:o.originNodeId}:{}};return d={spec:n,until:Date.now()+x},S(n.flowId),publish({source:"react",category:"runtime",severity:"info",title:o.originType,fingerprint:m(o.originNodeId??o.originType,n.flowId),raw:{kind:"flow-origin",originNodeId:o.originNodeId,...o.continuesFlowId?{continuesFlowId:o.continuesFlowId}:{}}}),P("lens/flow",{flowId:n.flowId,kind:o.originType,...o.originNodeId?{originNodeId:o.originNodeId}:{}}),n}e(beginBackgroundFlow,"beginBackgroundFlow"),i(beginBackgroundFlow,"beginBackgroundFlow"),t(beginBackgroundFlow,"beginBackgroundFlow");export function flowForNewActivity(){const o=currentFlow();if(o)return o;const n=p();if(n)return h(n)?beginBackgroundFlow({originType:"timer",originNodeId:typeof location<"u"?`ambient:${location.pathname}`:"ambient",continuesFlowId:n.flowId}):n}e(flowForNewActivity,"flowForNewActivity"),i(flowForNewActivity,"flowForNewActivity"),t(flowForNewActivity,"flowForNewActivity");export const FLOW_ORIGIN_FINGERPRINT_PREFIX="flow-origin:";function m(o,n){return`${FLOW_ORIGIN_FINGERPRINT_PREFIX}${o}:${n}`}e(m,"_"),i(m,"S"),t(m,"originFingerprint");export function setPublisher(o){if(globalThis.__LENSMCP_PUBLISH__=o,o)for(;l.length;){const n=T();if(n)try{o(n)}catch{}}}e(setPublisher,"setPublisher"),i(setPublisher,"setPublisher"),t(setPublisher,"setPublisher");export function runInFlow(o,n){w.push(o),d={spec:o,until:Date.now()+x};try{return n()}finally{w.pop()}}e(runInFlow,"runInFlow"),i(runInFlow,"runInFlow"),t(runInFlow,"runInFlow");export function currentFlow(){return w[w.length-1]}e(currentFlow,"currentFlow"),i(currentFlow,"currentFlow"),t(currentFlow,"currentFlow");const D=Symbol.for("lensmcp.flowed"),O=2e3,a=new Map;function B(o){if(o==null||typeof o!="object")return;const n=o,r=n.nativeEvent;if(r!=null&&typeof r=="object"){const u=r.isTrusted;if(typeof u=="boolean")return u}if(typeof n.isTrusted=="boolean")return n.isTrusted}e(B,"D"),i(B,"$"),t(B,"eventTrust");function L(o){if(!(a.size<=64))for(const[n,r]of a)o>=r.until&&a.delete(n)}e(L,"C"),i(L,"q"),t(L,"pruneInputBursts");export function withFlow(o,n={}){if(typeof o!="function"||o[D])return o;const r=t(()=>{publish({source:"react",category:"runtime",severity:"info",title:n.originType??"user-click",fingerprint:m(n.originNodeId??"unknown",currentFlow()?.flowId??""),raw:{kind:"flow-origin",originNodeId:n.originNodeId}});const s=currentFlow()?.flowId;s&&P("lens/flow",{flowId:s,kind:n.originType??"user-click",...n.originNodeId?{originNodeId:n.originNodeId}:{}})},"publishOrigin"),u=t(function(...s){if(n.originType==="input-change"){if(B(s[0])===!1)return currentFlow()==null&&p()!=null&&extendFlowWindow(),o(...s);const k=n.originNodeId??"input",y=Date.now(),N=a.get(k);if(N&&y<N.until)return N.until=y+O,runInFlow(N.spec,()=>o(...s));const A={flowId:I(),originType:"input-change",originNodeId:n.originNodeId};return a.set(k,{spec:A,until:y+O}),L(y),runInFlow(A,()=>(r(),o(...s)))}const W=I();return runInFlow({flowId:W,originType:n.originType??"user-click",originNodeId:n.originNodeId},()=>(r(),o(...s)))},"flowed");return u[D]=!0,u}e(withFlow,"withFlow"),i(withFlow,"withFlow"),t(withFlow,"withFlow");let E=0;function I(){return E=(E+1)%65535,`flow:${Date.now().toString(36)}:${E.toString(36)}`}e(I,"h"),i(I,"E"),t(I,"newFlowId");export function publish(o){if(o.detached){const{detached:u,...s}=o;_(s);return}const n=currentFlow()??(o.context?.flowId?void 0:p()),r=n==null?o:{...o,context:{...n.flowId?{flowId:n.flowId}:{},...n.originType?{originType:n.originType}:{},...n.originNodeId?{originNodeId:n.originNodeId}:{},...n.causedByNodeId?{causedByNodeId:n.causedByNodeId}:{},...o.context}};_(r)}e(publish,"publish"),i(publish,"publish"),t(publish,"publish");function _(o){const n=globalThis.__LENSMCP_PUBLISH__;if(n)try{n(o);return}catch{}v(o)}e(_,"T"),i(_,"B"),t(_,"deliver");const R=j({burst:30,perSec:5});export function publishLazy(o,n){const r=o.startsWith(FLOW_ORIGIN_FINGERPRINT_PREFIX)?{ok:!0,suppressed:0}:R.admit(o);if(!r.ok)return;const u=n();if(r.suppressed>0&&u.raw!==null&&typeof u.raw=="object"){publish({...u,raw:{...u.raw,floodSuppressed:r.suppressed}});return}publish(u)}e(publishLazy,"publishLazy"),i(publishLazy,"publishLazy"),t(publishLazy,"publishLazy");export function resetFlowStateForTests(){w.length=0,d=void 0,f.clear(),a.clear(),b=void 0}e(resetFlowStateForTests,"resetFlowStateForTests"),i(resetFlowStateForTests,"resetFlowStateForTests"),t(resetFlowStateForTests,"resetFlowStateForTests");export function drainQueue(){return F.length=0,c=0,l.splice(0,l.length)}e(drainQueue,"drainQueue"),i(drainQueue,"drainQueue"),t(drainQueue,"drainQueue");
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session replay anchors from the app's side (planning/replay/00-plan.md §2.4): a flow began, a request went out and
|
|
3
|
+
* came back, a page visit started / was ready / ended. They are written into the page's own recording, on the page
|
|
4
|
+
* clock, through the handle the recorder hangs on `window.__LENSMCP_REPLAY__` — and are nothing when no recorder runs.
|
|
5
|
+
* The recorder bounds every payload and redacts its URLs; here only ids and names are chosen.
|
|
6
|
+
*/
|
|
7
|
+
/** A recording is running in this page. */
|
|
8
|
+
export declare function replayActive(): boolean;
|
|
9
|
+
export declare function replayMark(tag: string, payload: Record<string, unknown>): void;
|
|
10
|
+
/** A fresh snapshot when the page is idle — a visit is ready, so it plays on its own. */
|
|
11
|
+
export declare function replayCheckpoint(): void;
|
|
12
|
+
/**
|
|
13
|
+
* A request's two anchors: `lens/request` now, `lens/response` when it settles. The request id is what joins the
|
|
14
|
+
* moment on the replay to the backend's whole run of that request (gateway, handler, SQL), with no clock to guess.
|
|
15
|
+
*/
|
|
16
|
+
export declare function replayLeg(result: Promise<{
|
|
17
|
+
status: number;
|
|
18
|
+
}>, method: string, url: string, requestId: string | undefined, flowId: string | undefined): void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";var f=Object.defineProperty;var r=(e,t)=>f(e,"name",{value:t,configurable:!0});var y=Object.defineProperty,n=r((e,t)=>y(e,"name",{value:t,configurable:!0}),"n"),h=Object.defineProperty,a=n((e,t)=>h(e,"name",{value:t,configurable:!0}),"t");function c(){const e=globalThis.__LENSMCP_REPLAY__;return e&&typeof e.mark=="function"?e:void 0}r(c,"a"),n(c,"c"),a(c,"handle");export function replayActive(){return c()!==void 0}r(replayActive,"replayActive"),n(replayActive,"replayActive"),a(replayActive,"replayActive");export function replayMark(e,t){const i=c();if(i)try{i.mark(e,t)}catch{}}r(replayMark,"replayMark"),n(replayMark,"replayMark"),a(replayMark,"replayMark");export function replayCheckpoint(){const e=c();if(!(!e||typeof e.checkpoint!="function"))try{e.checkpoint()}catch{}}r(replayCheckpoint,"replayCheckpoint"),n(replayCheckpoint,"replayCheckpoint"),a(replayCheckpoint,"replayCheckpoint");export function replayLeg(e,t,i,s,l){if(!replayActive())return;const u=Date.now(),p={...s?{requestId:s}:{},...l?{flowId:l}:{}};replayMark("lens/request",{...p,method:t,url:i}),e.then(o=>replayMark("lens/response",{...p,status:o.status,ms:Date.now()-u}),o=>replayMark("lens/response",{...p,error:o instanceof Error?o.message:String(o),ms:Date.now()-u}))}r(replayLeg,"replayLeg"),n(replayLeg,"replayLeg"),a(replayLeg,"replayLeg");
|
package/lib/route-flows.d.ts
CHANGED
|
@@ -15,6 +15,12 @@ export interface RouteFlowEnvironment {
|
|
|
15
15
|
removeEventListener(type: 'popstate', listener: () => void, options?: {
|
|
16
16
|
capture?: boolean;
|
|
17
17
|
}): void;
|
|
18
|
+
/**
|
|
19
|
+
* Where a person's gesture is heard: `click` and `keydown` in the capture phase, before any of the app's own
|
|
20
|
+
* handlers run, so none of them can stop it. Without it, no gesture is heard and a background flow keeps
|
|
21
|
+
* every navigation inside it (the first three cases above).
|
|
22
|
+
*/
|
|
23
|
+
document?: Pick<Document, 'addEventListener' | 'removeEventListener'>;
|
|
18
24
|
}
|
|
19
25
|
/** The node id of a route flow: `route:/companies/42/staff`. Pathname only, clipped. */
|
|
20
26
|
export declare function routeNodeId(pathname: string): string;
|
package/lib/route-flows.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var F=Object.defineProperty;var i=(t,e)=>F(t,"name",{value:e,configurable:!0});var I=Object.defineProperty,c=i((t,e)=>I(t,"name",{value:e,configurable:!0}),"i"),_=Object.defineProperty,n=c((t,e)=>_(t,"name",{value:e,configurable:!0}),"n");import{activeFlow as K,beginBackgroundFlow as P}from"./publish.js";import{notePageNavigation as R}from"./page-visit-runtime.js";const B=200,T=1e3,j=new Set(["page-load","route-load","timer"]),x='a[href], button, [role="link"], [role="button"]';function f(t){if(t.isTrusted!==!0)return!1;const e=t;if(e.metaKey||e.ctrlKey||e.shiftKey||e.altKey)return!1;if(t.type==="click")return e.button===0;if(t.type!=="keydown"||e.key!=="Enter"&&e.key!==" ")return!1;const o=t.target;return typeof o?.closest=="function"&&o.closest(x)!=null}i(f,"S"),c(f,"R"),n(f,"isGesture");function h(){const t=globalThis.window;if(!t?.history||!t.location||typeof t.addEventListener!="function"||typeof t.removeEventListener!="function")return;const e=t.__LENSMCP_NAV__;return e&&typeof e.subscribe=="function"?{history:t.history,location:t.location,navBus:e,addEventListener:t.addEventListener.bind(t),removeEventListener:t.removeEventListener.bind(t),...t.document?{document:t.document}:{}}:t}i(h,"N"),c(h,"B"),n(h,"browserEnvironment");export function routeNodeId(t){return`route:${t.length>B?t.slice(0,B):t}`}i(routeNodeId,"routeNodeId"),c(routeNodeId,"routeNodeId"),n(routeNodeId,"routeNodeId");let m;export function installRouteFlows(t=h()){if(!t)return()=>{};if(m)return()=>{};let e=t.location.pathname,o=!0,u;const w=n(a=>{if(!o)return;const r=t.location.pathname;if(r===e)return;e=r;const y=u!==void 0&&Date.now()-u<T;u=void 0;const s=K(),N=s&&!(y&&j.has(s.originType??""))?s:void 0;R(r,a,N?.flowId),!N&&P({originType:"route-load",originNodeId:routeNodeId(r)})},"navigated"),l=n(a=>{try{o&&f(a)&&(u=Date.now())}catch{}},"heard"),b=n((a,r)=>n(function(...y){const s=a.apply(this,y);try{w(r)}catch{}return s},"wrapped"),"wrap"),E=t.history.pushState,g=t.history.replaceState,L=b(E,"push"),k=b(g,"replace"),d=n(()=>w("pop"),"popped");t.history.pushState=L,t.history.replaceState=k;const v=t.navBus?t.navBus.subscribe(d):void 0;v||t.addEventListener("popstate",d,{capture:!0});const p=t.document;p?.addEventListener("click",l,{capture:!0,passive:!0}),p?.addEventListener("keydown",l,{capture:!0,passive:!0});const S=n(()=>{o=!1,v?v():t.removeEventListener("popstate",d,{capture:!0}),p?.removeEventListener("click",l,{capture:!0}),p?.removeEventListener("keydown",l,{capture:!0}),t.history.pushState===L&&(t.history.pushState=E),t.history.replaceState===k&&(t.history.replaceState=g),m=void 0},"uninstall");return m=S,S}i(installRouteFlows,"installRouteFlows"),c(installRouteFlows,"installRouteFlows"),n(installRouteFlows,"installRouteFlows");
|
package/lib/router-pattern.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var i=Object.defineProperty;var n=(e,t)=>i(e,"name",{value:t,configurable:!0});var u=Object.defineProperty,a=n((e,t)=>u(e,"name",{value:t,configurable:!0}),"n"),s=Object.defineProperty,c=a((e,t)=>s(e,"name",{value:t,configurable:!0}),"r");export function routeMatchesOf(e){if(!e||typeof e!="object")return;const t=e;if(!t.match||typeof t.match!="object"||!t.match.route||typeof t.match.route!="object")return;const r=t.routeContext?.matches;return Array.isArray(r)?r:void 0}n(routeMatchesOf,"routeMatchesOf"),a(routeMatchesOf,"routeMatchesOf"),c(routeMatchesOf,"routeMatchesOf");export function patternOf(e){if(!e.length)return;let t="";for(const f of e){const o=f?.route?.path;typeof o!="string"||o===""||(t=o.startsWith("/")?o:`${t.replace(/\/?\*$/,"")}/${o}`)}const r=`/${t.split("/").filter(Boolean).join("/")}`;return r.length>300?r.slice(0,300):r}n(patternOf,"patternOf"),a(patternOf,"patternOf"),c(patternOf,"patternOf");
|
package/lib/trace-slot.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var p=Object.defineProperty;var o=(t,n)=>p(t,"name",{value:n,configurable:!0});var d=Object.defineProperty,a=o((t,n)=>d(t,"name",{value:n,configurable:!0}),"o"),l=Object.defineProperty,f=a((t,n)=>l(t,"name",{value:n,configurable:!0}),"c");import{jsx as y}from"react/jsx-runtime";import{Children as I,Fragment as g,useEffect as b,useRef as m}from"react";import{publish as h}from"./publish.js";import{makeInstanceId as v}from"./identity.js";import{useLensmcpContext as C}from"./context.js";export function TraceSlot(t){const n=C(),e=m(void 0),c=m(void 0);c.current||(c.current=v(`react:slot:${t.id}`).instanceId);const s=c.current,r=i(t.children);return b(()=>{if(e.current!==r){const u=e.current;e.current=r,h({source:"react",category:"render",severity:"info",title:`slot ${t.id}: ${u??"(none)"} \u2192 ${r}`,fingerprint:`slot-change:${t.id}`,raw:{kind:"slot-content-changed",slot:{slotLogicalId:`react:slot:${t.id}`,slotInstanceId:s,fromComponent:u,toComponent:r,componentInstanceId:n.componentInstanceId}}})}},[r,t.id,s,n.componentInstanceId]),y(g,{children:t.children})}o(TraceSlot,"TraceSlot"),a(TraceSlot,"TraceSlot"),f(TraceSlot,"TraceSlot");function i(t){const n=I.toArray(t)[0];if(!n)return"(empty)";if(typeof n=="string"||typeof n=="number")return"(text)";if(typeof n=="boolean")return"(boolean)";if(Array.isArray(n))return"(array)";if(typeof n=="object"&&n&&"type"in n){const e=n.type;return typeof e=="string"?e:typeof e=="function"?e.displayName??e.name??"AnonymousComponent":"unknown"}return"unknown"}o(i,"f"),a(i,"g"),f(i,"describeChild");
|
package/lib/traced-hooks.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var w=Object.defineProperty;var d=(e,n)=>w(e,"name",{value:n,configurable:!0});var H=Object.defineProperty,f=d((e,n)=>H(e,"name",{value:n,configurable:!0}),"p"),M=Object.defineProperty,m=f((e,n)=>M(e,"name",{value:n,configurable:!0}),"p");import{useCallback as $,useEffect as C,useMemo as U,useRef as I}from"react";import{useComponentIdentity as y}from"./component-identity.js";import{useLensmcpContext as v}from"./context.js";import{depsHash as g}from"./identity.js";import{publish as l}from"./publish.js";import{activeCommitId as h}from"./fiber-renders.js";export function tracedUseEffect(e,n,r){const a=v(),s=y(),u=i(e),t=I(void 0);C(()=>{const o=typeof performance<"u"&&performance.now?performance.now():Date.now(),c=g(r),p=t.current;t.current=c;let k;try{k=n()}finally{const b=typeof performance<"u"&&performance.now?performance.now():Date.now();l({source:"react",category:"render",severity:"info",title:`effect-run ${e}`,fingerprint:`effect-run:${e}`,raw:{kind:"effect-run",effect:{...h()?{commitId:h()}:{},hookInstanceId:u,hookLogicalId:e,componentInstanceId:a.componentInstanceId??s.componentInstanceId,depsHash:c,prevDepsHash:p,durationMs:Math.max(0,b-o)}}})}return()=>{typeof k=="function"&&k(),l({source:"react",category:"render",severity:"info",title:`effect-cleanup ${e}`,fingerprint:`effect-cleanup:${e}`,raw:{kind:"effect-run",effect:{...h()?{commitId:h()}:{},hookInstanceId:u,hookLogicalId:e,componentInstanceId:a.componentInstanceId??s.componentInstanceId,depsHash:t.current??c,durationMs:0,cleanupRan:!0}}})}},r)}d(tracedUseEffect,"tracedUseEffect"),f(tracedUseEffect,"tracedUseEffect"),m(tracedUseEffect,"tracedUseEffect");export function tracedUseMemo(e,n,r){const a=v(),s=y(),u=i(e),t=I(void 0),o=g(r),c=o!==t.current,p=U(n,r??[]);return c&&l({source:"react",category:"render",severity:"debug",title:`useMemo recomputed ${e}`,fingerprint:`hook-run:${e}`,raw:{kind:"hook-run",hook:{hookInstanceId:u,hookLogicalId:e,componentInstanceId:a.componentInstanceId??s.componentInstanceId,hookType:"useMemo",depsHash:o,prevDepsHash:t.current,recomputed:!0}}}),t.current=o,p}d(tracedUseMemo,"tracedUseMemo"),f(tracedUseMemo,"tracedUseMemo"),m(tracedUseMemo,"tracedUseMemo");export function tracedUseCallback(e,n,r){const a=v(),s=y(),u=i(e),t=I(void 0),o=g(r),c=o!==t.current,p=$(n,r??[]);return c&&l({source:"react",category:"render",severity:"debug",title:`useCallback recomputed ${e}`,fingerprint:`hook-run:${e}`,raw:{kind:"hook-run",hook:{hookInstanceId:u,hookLogicalId:e,componentInstanceId:a.componentInstanceId??s.componentInstanceId,hookType:"useCallback",depsHash:o,prevDepsHash:t.current,recomputed:!0}}}),t.current=o,p}d(tracedUseCallback,"tracedUseCallback"),f(tracedUseCallback,"tracedUseCallback"),m(tracedUseCallback,"tracedUseCallback");function i(e){const n=I(void 0);return n.current||(n.current=`${e}#${Math.random()*1e9|0}`),n.current}d(i,"l"),f(i,"H"),m(i,"useStableHookInstance");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lensmcp/react-instrumentation",
|
|
3
|
-
"version": "1.25.
|
|
3
|
+
"version": "1.25.18",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./index.js",
|
|
6
6
|
"module": "./index.js",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
}
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@lensmcp/protocol-types": "1.25.
|
|
22
|
+
"@lensmcp/protocol-types": "1.25.18",
|
|
23
23
|
"tslib": "^2.3.0"
|
|
24
24
|
},
|
|
25
25
|
"peerDependencies": {
|