@lensmcp/cluster 1.25.34 → 1.25.35

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.
Files changed (137) hide show
  1. package/basic-ssl.js +1 -1
  2. package/build-host.js +1 -1
  3. package/build-scope-patterns.js +1 -1
  4. package/bundle-parent.js +1 -1
  5. package/checkout-cache.js +1 -1
  6. package/child-process-env.js +1 -1
  7. package/compile-retry.js +1 -1
  8. package/create-webpack-dev.js +1 -1
  9. package/create-webpack-prod.js +1 -1
  10. package/dev-devtool.js +1 -1
  11. package/devserver-host.js +1 -1
  12. package/devserver-notifier.js +1 -1
  13. package/devserver-transport.js +1 -1
  14. package/error-stack-release.js +1 -1
  15. package/executors/build/build.impl.js +1 -1
  16. package/executors/gateway/body-stall.js +1 -1
  17. package/executors/gateway/canonical-path.js +1 -1
  18. package/executors/gateway/client-ip.js +1 -1
  19. package/executors/gateway/gateway-errors.js +1 -1
  20. package/executors/gateway/gateway.impl.js +1 -1
  21. package/executors/gateway/gateway.lib.js +1 -1
  22. package/executors/gateway/health-check.js +1 -1
  23. package/executors/gateway/jwks-verify.js +1 -1
  24. package/executors/gateway/jwt-claims.js +1 -1
  25. package/executors/gateway/main.prod-gateway.js +2 -2
  26. package/executors/gateway/main.rollout.js +4 -4
  27. package/executors/gateway/manifest.js +1 -1
  28. package/executors/gateway/metrics.js +1 -1
  29. package/executors/gateway/otel-tracing.js +1 -1
  30. package/executors/gateway/prod-config.js +1 -1
  31. package/executors/gateway/prod-gateway.lib.js +1 -1
  32. package/executors/gateway/prod-runtime/access-log.js +1 -1
  33. package/executors/gateway/prod-runtime/app.js +1 -1
  34. package/executors/gateway/prod-runtime/auth.js +1 -1
  35. package/executors/gateway/prod-runtime/body-stall.js +1 -1
  36. package/executors/gateway/prod-runtime/cors.js +1 -1
  37. package/executors/gateway/prod-runtime/edge.js +1 -1
  38. package/executors/gateway/prod-runtime/handler.js +1 -1
  39. package/executors/gateway/prod-runtime/hooks.js +1 -1
  40. package/executors/gateway/prod-runtime/observability.js +1 -1
  41. package/executors/gateway/prod-runtime/rollout.js +1 -1
  42. package/executors/gateway/prod-runtime/routing.js +1 -1
  43. package/executors/gateway/prod-runtime/server.js +1 -1
  44. package/executors/gateway/prod-runtime/trust.js +1 -1
  45. package/executors/gateway/prod-runtime/upgrade.js +7 -7
  46. package/executors/gateway/prod-runtime/upstream.js +1 -1
  47. package/executors/gateway/providers-prod.js +1 -1
  48. package/executors/gateway/rate-limit.js +2 -2
  49. package/executors/gateway/registry-source.js +1 -1
  50. package/executors/gateway/rollout-ops.js +2 -2
  51. package/executors/gateway/runtime/act.js +1 -1
  52. package/executors/gateway/runtime/auth.js +1 -1
  53. package/executors/gateway/runtime/chooser.js +12 -12
  54. package/executors/gateway/runtime/control.js +2 -2
  55. package/executors/gateway/runtime/dev-auth.js +1 -1
  56. package/executors/gateway/runtime/discovery.js +1 -1
  57. package/executors/gateway/runtime/edge.js +1 -1
  58. package/executors/gateway/runtime/guest-graph.js +2 -2
  59. package/executors/gateway/runtime/guest-replay.js +2 -2
  60. package/executors/gateway/runtime/handler.js +1 -1
  61. package/executors/gateway/runtime/hmr-reload.js +1 -1
  62. package/executors/gateway/runtime/hooks.js +1 -1
  63. package/executors/gateway/runtime/hosted-dashboard.js +1 -1
  64. package/executors/gateway/runtime/instance.js +2 -2
  65. package/executors/gateway/runtime/lens-children.js +1 -1
  66. package/executors/gateway/runtime/lifecycle.js +3 -3
  67. package/executors/gateway/runtime/observability.js +3 -3
  68. package/executors/gateway/runtime/orphan-reaper.js +2 -2
  69. package/executors/gateway/runtime/own-log.js +6 -6
  70. package/executors/gateway/runtime/pod-env.js +2 -2
  71. package/executors/gateway/runtime/pod-output.js +1 -1
  72. package/executors/gateway/runtime/pod-probe.js +1 -1
  73. package/executors/gateway/runtime/process-names.js +1 -1
  74. package/executors/gateway/runtime/project-graph-store.js +1 -1
  75. package/executors/gateway/runtime/proxy.js +1 -1
  76. package/executors/gateway/runtime/registration-guards.js +1 -1
  77. package/executors/gateway/runtime/route-registry.js +1 -1
  78. package/executors/gateway/runtime/scope.js +1 -1
  79. package/executors/gateway/runtime/serve-launch.js +3 -3
  80. package/executors/gateway/runtime/server.js +2 -2
  81. package/executors/gateway/runtime/service-keys.js +1 -1
  82. package/executors/gateway/runtime/shared-build.js +3 -3
  83. package/executors/gateway/runtime/source-poller.js +1 -1
  84. package/executors/gateway/runtime/types.js +1 -1
  85. package/executors/gateway/runtime/upgrade.js +1 -1
  86. package/executors/gateway/runtime/warm-start.js +1 -1
  87. package/executors/gateway/runtime/workspace-log.js +1 -1
  88. package/executors/gateway/runtime/workspace-middleware.js +1 -1
  89. package/executors/gateway/runtime/workspace-registry.js +1 -1
  90. package/executors/gateway/ssrf-guard.js +1 -1
  91. package/executors/serve/serve.impl.js +1 -1
  92. package/executors/serve/stop-on-signal.js +1 -1
  93. package/executors/trust/hostname.js +1 -1
  94. package/executors/trust/trust.impl.js +3 -3
  95. package/exit-reason.js +2 -2
  96. package/fork-ts-check-reporter.js +1 -1
  97. package/gateway.js +1 -1
  98. package/gc-notice.js +1 -1
  99. package/graph-snapshot.js +1 -1
  100. package/handoff-retire.js +1 -1
  101. package/heap-snapshot.js +1 -1
  102. package/hot-swap-registries.js +1 -1
  103. package/index.js +1 -1
  104. package/inspector-secret.js +1 -1
  105. package/main.devserver.js +11 -11
  106. package/notice-generation.js +1 -1
  107. package/package.json +4 -4
  108. package/perf/heavy-barrel-import.js +1 -1
  109. package/perf/perf-config.js +1 -1
  110. package/perf/perf-rule-events.js +2 -2
  111. package/perf/perf-rules-analysis.js +1 -1
  112. package/perf/perf-rules-plugin.js +1 -1
  113. package/perf/source-scan.js +5 -5
  114. package/perf/workspace-libraries.js +2 -2
  115. package/pod-memory-events.js +2 -2
  116. package/pod-memory.js +1 -1
  117. package/pod-sock.js +1 -1
  118. package/process-name.js +1 -1
  119. package/redis-disconnect-fix.js +1 -1
  120. package/schema-first-instance.js +1 -1
  121. package/serve-runner.js +1 -1
  122. package/service-build-events.js +2 -2
  123. package/shared-build/attach.js +2 -2
  124. package/shared-build/host.js +3 -3
  125. package/shared-build/protocol.js +1 -1
  126. package/shared-build/shared-compilation.js +3 -3
  127. package/shared-build/signature.js +1 -1
  128. package/stdio-guard.js +1 -1
  129. package/swap-mode.js +1 -1
  130. package/swap-recycle.js +1 -1
  131. package/tsgo-check-plugin.js +4 -4
  132. package/typecheck-bus.js +3 -3
  133. package/typecheck-queue.js +1 -1
  134. package/worker-guard.js +1 -1
  135. package/worker-retire.js +1 -1
  136. package/worker-supervisor.js +2 -2
  137. package/workspace-paths.js +1 -1
@@ -1 +1 @@
1
- "use strict";var b=Object.defineProperty;var S=(e,a)=>b(e,"name",{value:a,configurable:!0});var h=Object.defineProperty,c=S((e,a)=>h(e,"name",{value:a,configurable:!0}),"c");Object.defineProperty(exports,"__esModule",{value:!0}),exports.ACT_MAX_IDENTITIES=exports.ACT_RETAIN_MS=exports.ACT_TICKET_MS=exports.ACT_TICKET=exports.ACT_HEADER=void 0,exports.fromBrowser=fromBrowser,exports.actTicketOf=actTicketOf,exports.setActTicketAside=setActTicketAside,exports.createActStore=createActStore;const tslib_1=require("tslib"),node_crypto_1=require("node:crypto"),fs=tslib_1.__importStar(require("node:fs")),path=tslib_1.__importStar(require("node:path"));exports.ACT_HEADER="x-lensmcp-act",exports.ACT_TICKET=Symbol.for("lensmcp.gateway.actTicket"),exports.ACT_TICKET_MS=6e4,exports.ACT_RETAIN_MS=720*60*6e4,exports.ACT_MAX_IDENTITIES=20;const TOKEN_MARGIN_S=30,MAX_OPEN_TICKETS=200,WRITE_EVERY_MS=3e4,TIME_CLAIMS=new Set(["exp","iat","nbf","jti"]),TICKET_VALUE=/^[A-Za-z0-9_-]{43}$/;function fromBrowser(e){return typeof e.headers["sec-fetch-mode"]=="string"||typeof e.headers["sec-fetch-site"]=="string"}S(fromBrowser,"fromBrowser"),c(fromBrowser,"fromBrowser");function actTicketOf(e){return e[exports.ACT_TICKET]}S(actTicketOf,"actTicketOf"),c(actTicketOf,"actTicketOf");function setActTicketAside(e){const a=e.headers[exports.ACT_HEADER];typeof a=="string"&&TICKET_VALUE.test(a)&&(e[exports.ACT_TICKET]=a)}S(setActTicketAside,"setActTicketAside"),c(setActTicketAside,"setActTicketAside");const str=c(e=>typeof e=="string"&&e.length>0&&e.length<=256?e:void 0,"str"),keyOf=c(e=>{const a=str(e.sub);return a?`${a}\0${str(e.tid)??""}`:void 0},"keyOf"),safeName=c(e=>e.replace(/[^A-Za-z0-9._-]/g,"_").slice(0,120)||"_","safeName");function viewOf(e,a){const A=e.claims,d=Array.isArray(A.roles)?A.roles.filter(T=>typeof T=="string").slice(0,20):void 0,y=str(A.tid),u=str(A.email),E=str(A.name)??str(A.preferred_username);return{user:str(A.sub),...y?{tenant:y}:{},...u?{email:u}:{},...E?{name:E}:{},...d?.length?{roles:d}:{},host:e.host,firstSeenAt:e.firstSeenAt,lastSeenAt:e.lastSeenAt,mode:e.token&&e.tokenExp!==void 0&&e.tokenExp-TOKEN_MARGIN_S>a/1e3?"token":"identity"}}S(viewOf,"viewOf"),c(viewOf,"viewOf");function createActStore(e={}){const a=e.now??Date.now,A=new Map,d=new Map,y=new Map,u=new Set,E=c(t=>e.dir?path.join(e.dir,`${safeName(t)}.json`):void 0,"file"),T=c(t=>{let s=A.get(t);if(s)return s;s=new Map,A.set(t,s);const n=E(t);if(!n)return s;try{const o=JSON.parse(fs.readFileSync(n,"utf8"));for(const i of Array.isArray(o.identities)?o.identities:[]){const r=i;if(!r||typeof r!="object"||!r.claims||typeof r.claims!="object"||typeof r.host!="string"||typeof r.firstSeenAt!="number"||typeof r.lastSeenAt!="number")continue;const f=keyOf(r.claims);f&&s.set(f,{claims:r.claims,host:r.host,firstSeenAt:r.firstSeenAt,lastSeenAt:r.lastSeenAt})}}catch{}return s},"load"),g=c((t,s)=>{for(const[n,o]of t)s-o.lastSeenAt>exports.ACT_RETAIN_MS&&t.delete(n);if(t.size>exports.ACT_MAX_IDENTITIES){const n=[...t.entries()].sort((o,i)=>o[1].lastSeenAt-i[1].lastSeenAt).slice(0,t.size-exports.ACT_MAX_IDENTITIES);for(const[o]of n)t.delete(o)}},"prune"),k=c((t,s)=>{const n=E(t),o=A.get(t);if(u.delete(t),!(!n||!o)){y.set(t,s);try{fs.mkdirSync(path.dirname(n),{recursive:!0,mode:448});const i=[...o.values()].map(f=>({claims:f.claims,host:f.host,firstSeenAt:f.firstSeenAt,lastSeenAt:f.lastSeenAt})),r=`${n}.${process.pid}.tmp`;fs.writeFileSync(r,JSON.stringify({identities:i},null,1),{mode:384}),fs.renameSync(r,n)}catch{}}},"write"),I=c((t,s,n,o,i=a())=>{const r=keyOf(s);if(!r)return;const f=T(t),_={};for(const[x,w]of Object.entries(s))TIME_CLAIMS.has(x)||(_[x]=w);const m=f.get(r),l=typeof s.exp=="number"?s.exp:void 0,p=!m||m.host!==o||JSON.stringify(m.claims)!==JSON.stringify(_);f.set(r,{claims:_,host:o,firstSeenAt:m?.firstSeenAt??i,lastSeenAt:i,...n&&l!==void 0?{token:n,tokenExp:l}:m?.token?{token:m.token,tokenExp:m.tokenExp}:{}}),g(f,i),p&&u.add(t),(p||i-(y.get(t)??0)>=WRITE_EVERY_MS)&&k(t,i)},"remember"),C=c((t,s=a())=>{const n=T(t);return g(n,s),[...n.values()].sort((o,i)=>i.lastSeenAt-o.lastSeenAt).map(o=>viewOf(o,s))},"list");return{remember:I,list:C,mint:c((t,s,n=a())=>{const o=T(t);g(o,n);const i=s.user?.trim().toLowerCase(),r=s.tenant?.trim(),f=[...o.entries()].filter(([,l])=>{const p=l.claims;return r&&str(p.tid)!==r?!1:i?[p.sub,p.email,p.name,p.preferred_username].some(x=>typeof x=="string"&&x.toLowerCase()===i):!0}).sort((l,p)=>p[1].lastSeenAt-l[1].lastSeenAt)[0];if(!f){const l=C(t,n);return{error:l.length?`No signed-in identity matches${i?` user '${s.user}'`:""}${r?` in tenant '${r}'`:""} \u2014 ${l.length} known (see identities).`:"No one has signed in to this workspace's app since the gateway started remembering identities. Sign in once in the browser \u2014 the gateway keeps the identity it verified for 30 days.",identities:l}}for(const[l,p]of d)p.expiresAt<=n&&d.delete(l);d.size>=MAX_OPEN_TICKETS&&d.delete(d.keys().next().value);const _=(0,node_crypto_1.randomBytes)(32).toString("base64url"),m=n+exports.ACT_TICKET_MS;return d.set(_,{wsKey:t,key:f[0],expiresAt:m}),{ticket:_,expiresAt:m,identity:viewOf(f[1],n)}},"mint"),redeem:c((t,s,n=a())=>{const o=d.get(t);if(!o||(d.delete(t),o.expiresAt<=n||o.wsKey!==s))return;const i=T(s).get(o.key);if(!i)return;const r=viewOf(i,n);return r.mode==="token"?{token:i.token,claims:i.claims,view:r}:{claims:i.claims,view:r}},"redeem"),flush:c(()=>{const t=a();for(const s of[...u])k(s,t)},"flush")}}S(createActStore,"createActStore"),c(createActStore,"createActStore");
1
+ "use strict";var M=Object.defineProperty;var u=(e,a)=>M(e,"name",{value:a,configurable:!0});var b=Object.defineProperty,S=u((e,a)=>b(e,"name",{value:a,configurable:!0}),"S"),h=Object.defineProperty,c=S((e,a)=>h(e,"name",{value:a,configurable:!0}),"c");Object.defineProperty(exports,"__esModule",{value:!0}),exports.ACT_MAX_IDENTITIES=exports.ACT_RETAIN_MS=exports.ACT_TICKET_MS=exports.ACT_TICKET=exports.ACT_HEADER=void 0,exports.fromBrowser=fromBrowser,exports.actTicketOf=actTicketOf,exports.setActTicketAside=setActTicketAside,exports.createActStore=createActStore;const tslib_1=require("tslib"),node_crypto_1=require("node:crypto"),fs=tslib_1.__importStar(require("node:fs")),path=tslib_1.__importStar(require("node:path"));exports.ACT_HEADER="x-lensmcp-act",exports.ACT_TICKET=Symbol.for("lensmcp.gateway.actTicket"),exports.ACT_TICKET_MS=6e4,exports.ACT_RETAIN_MS=720*60*6e4,exports.ACT_MAX_IDENTITIES=20;const TOKEN_MARGIN_S=30,MAX_OPEN_TICKETS=200,WRITE_EVERY_MS=3e4,TIME_CLAIMS=new Set(["exp","iat","nbf","jti"]),TICKET_VALUE=/^[A-Za-z0-9_-]{43}$/;function fromBrowser(e){return typeof e.headers["sec-fetch-mode"]=="string"||typeof e.headers["sec-fetch-site"]=="string"}u(fromBrowser,"fromBrowser"),S(fromBrowser,"fromBrowser"),c(fromBrowser,"fromBrowser");function actTicketOf(e){return e[exports.ACT_TICKET]}u(actTicketOf,"actTicketOf"),S(actTicketOf,"actTicketOf"),c(actTicketOf,"actTicketOf");function setActTicketAside(e){const a=e.headers[exports.ACT_HEADER];typeof a=="string"&&TICKET_VALUE.test(a)&&(e[exports.ACT_TICKET]=a)}u(setActTicketAside,"setActTicketAside"),S(setActTicketAside,"setActTicketAside"),c(setActTicketAside,"setActTicketAside");const str=c(e=>typeof e=="string"&&e.length>0&&e.length<=256?e:void 0,"str"),keyOf=c(e=>{const a=str(e.sub);return a?`${a}\0${str(e.tid)??""}`:void 0},"keyOf"),safeName=c(e=>e.replace(/[^A-Za-z0-9._-]/g,"_").slice(0,120)||"_","safeName");function viewOf(e,a){const p=e.claims,d=Array.isArray(p.roles)?p.roles.filter(_=>typeof _=="string").slice(0,20):void 0,E=str(p.tid),T=str(p.email),x=str(p.name)??str(p.preferred_username);return{user:str(p.sub),...E?{tenant:E}:{},...T?{email:T}:{},...x?{name:x}:{},...d?.length?{roles:d}:{},host:e.host,firstSeenAt:e.firstSeenAt,lastSeenAt:e.lastSeenAt,mode:e.token&&e.tokenExp!==void 0&&e.tokenExp-TOKEN_MARGIN_S>a/1e3?"token":"identity"}}u(viewOf,"viewOf"),S(viewOf,"viewOf"),c(viewOf,"viewOf");function createActStore(e={}){const a=e.now??Date.now,p=new Map,d=new Map,E=new Map,T=new Set,x=c(t=>e.dir?path.join(e.dir,`${safeName(t)}.json`):void 0,"file"),_=c(t=>{let r=p.get(t);if(r)return r;r=new Map,p.set(t,r);const n=x(t);if(!n)return r;try{const o=JSON.parse(fs.readFileSync(n,"utf8"));for(const i of Array.isArray(o.identities)?o.identities:[]){const s=i;if(!s||typeof s!="object"||!s.claims||typeof s.claims!="object"||typeof s.host!="string"||typeof s.firstSeenAt!="number"||typeof s.lastSeenAt!="number")continue;const f=keyOf(s.claims);f&&r.set(f,{claims:s.claims,host:s.host,firstSeenAt:s.firstSeenAt,lastSeenAt:s.lastSeenAt})}}catch{}return r},"load"),g=c((t,r)=>{for(const[n,o]of t)r-o.lastSeenAt>exports.ACT_RETAIN_MS&&t.delete(n);if(t.size>exports.ACT_MAX_IDENTITIES){const n=[...t.entries()].sort((o,i)=>o[1].lastSeenAt-i[1].lastSeenAt).slice(0,t.size-exports.ACT_MAX_IDENTITIES);for(const[o]of n)t.delete(o)}},"prune"),w=c((t,r)=>{const n=x(t),o=p.get(t);if(T.delete(t),!(!n||!o)){E.set(t,r);try{fs.mkdirSync(path.dirname(n),{recursive:!0,mode:448});const i=[...o.values()].map(f=>({claims:f.claims,host:f.host,firstSeenAt:f.firstSeenAt,lastSeenAt:f.lastSeenAt})),s=`${n}.${process.pid}.tmp`;fs.writeFileSync(s,JSON.stringify({identities:i},null,1),{mode:384}),fs.renameSync(s,n)}catch{}}},"write"),I=c((t,r,n,o,i=a())=>{const s=keyOf(r);if(!s)return;const f=_(t),y={};for(const[k,v]of Object.entries(r))TIME_CLAIMS.has(k)||(y[k]=v);const m=f.get(s),l=typeof r.exp=="number"?r.exp:void 0,A=!m||m.host!==o||JSON.stringify(m.claims)!==JSON.stringify(y);f.set(s,{claims:y,host:o,firstSeenAt:m?.firstSeenAt??i,lastSeenAt:i,...n&&l!==void 0?{token:n,tokenExp:l}:m?.token?{token:m.token,tokenExp:m.tokenExp}:{}}),g(f,i),A&&T.add(t),(A||i-(E.get(t)??0)>=WRITE_EVERY_MS)&&w(t,i)},"remember"),C=c((t,r=a())=>{const n=_(t);return g(n,r),[...n.values()].sort((o,i)=>i.lastSeenAt-o.lastSeenAt).map(o=>viewOf(o,r))},"list");return{remember:I,list:C,mint:c((t,r,n=a())=>{const o=_(t);g(o,n);const i=r.user?.trim().toLowerCase(),s=r.tenant?.trim(),f=[...o.entries()].filter(([,l])=>{const A=l.claims;return s&&str(A.tid)!==s?!1:i?[A.sub,A.email,A.name,A.preferred_username].some(k=>typeof k=="string"&&k.toLowerCase()===i):!0}).sort((l,A)=>A[1].lastSeenAt-l[1].lastSeenAt)[0];if(!f){const l=C(t,n);return{error:l.length?`No signed-in identity matches${i?` user '${r.user}'`:""}${s?` in tenant '${s}'`:""} \u2014 ${l.length} known (see identities).`:"No one has signed in to this workspace's app since the gateway started remembering identities. Sign in once in the browser \u2014 the gateway keeps the identity it verified for 30 days.",identities:l}}for(const[l,A]of d)A.expiresAt<=n&&d.delete(l);d.size>=MAX_OPEN_TICKETS&&d.delete(d.keys().next().value);const y=(0,node_crypto_1.randomBytes)(32).toString("base64url"),m=n+exports.ACT_TICKET_MS;return d.set(y,{wsKey:t,key:f[0],expiresAt:m}),{ticket:y,expiresAt:m,identity:viewOf(f[1],n)}},"mint"),redeem:c((t,r,n=a())=>{const o=d.get(t);if(!o||(d.delete(t),o.expiresAt<=n||o.wsKey!==r))return;const i=_(r).get(o.key);if(!i)return;const s=viewOf(i,n);return s.mode==="token"?{token:i.token,claims:i.claims,view:s}:{claims:i.claims,view:s}},"redeem"),flush:c(()=>{const t=a();for(const r of[...T])w(r,t)},"flush")}}u(createActStore,"createActStore"),S(createActStore,"createActStore"),c(createActStore,"createActStore");
@@ -1 +1 @@
1
- "use strict";var _=Object.defineProperty;var w=(a,s)=>_(a,"name",{value:s,configurable:!0});var b=Object.defineProperty,p=w((a,s)=>b(a,"name",{value:s,configurable:!0}),"p");Object.defineProperty(exports,"__esModule",{value:!0}),exports.declaredCallerIds=declaredCallerIds,exports.createEdgeAuth=createEdgeAuth;const manifest_1=require("../manifest"),act_1=require("./act"),chooser_1=require("./chooser"),dev_auth_1=require("./dev-auth"),edge_1=require("./edge"),NO_CALLER_IDS=new Set;function declaredCallerIds(a,s,c){const k=(a.registry?a.registry.allServices():a.services).filter(r=>c===void 0||r.wsKey===c),i=k.find(r=>r.project===s)?.decl.callerIds;if(!Array.isArray(i)||i.length===0)return NO_CALLER_IDS;const e=new Set(k.map(r=>r.project));for(const[r,n]of a.keyToProject)(c===void 0||a.keyToWorkspace?.get(r)===c)&&e.add(n);return new Set(i.filter(r=>typeof r=="string"&&r!==s&&!e.has(r)))}w(declaredCallerIds,"declaredCallerIds"),p(declaredCallerIds,"declaredCallerIds");const bearerOf=p(a=>{const s=a.headers.authorization,c=Array.isArray(s)?s[0]:s;return typeof c=="string"&&c.startsWith("Bearer ")?c.slice(7):void 0},"bearerOf");function createEdgeAuth(a,s,c,k){const{traceStep:i}=s;return{internal:p((e,r,n)=>{const v=String(e.headers["x-api-key"]??""),o=a.keyToProject.get(v);if(!o)return i(n,"auth",{mode:"x-api-key",ok:!1}),{ok:!1,status:401,reason:"unauthorized",detail:"Invalid or missing x-api-key for internal route."};const l=a.keyToWorkspace?.get(v),t=r.svc?.wsKey;if(l&&t&&l!==t)return i(n,"auth",{mode:"x-api-key",ok:!1,reason:"cross-workspace",caller:o,callerWorkspace:l,routeWorkspace:t}),{ok:!1,status:401,reason:"unauthorized",detail:"Invalid or missing x-api-key for internal route."};const d=(0,edge_1.claimedCallerIdOf)(e),h=d!==void 0&&d!==o&&declaredCallerIds(a,o,l).has(d)?d:o;e.headers["x-api-key-id"]=h,l?e.headers["x-api-key-workspace"]=l:delete e.headers["x-api-key-workspace"],e.__lensmcpCaller=o,delete e.headers["x-api-key"];const u=(0,edge_1.callerContextOf)(e);for(const[g,y]of Object.entries(u))e.headers[g]=y;return i(n,"auth",{mode:"x-api-key",ok:!0,caller:o,...h!==o?{as:h}:{},...d!==void 0&&d!==o&&h===o?{claimRefused:d}:{},...l?{callerWorkspace:l}:{},...u["x-tenant-id"]!==void 0?{callerTenant:!0}:{},...u["x-user-id"]!==void 0?{callerUser:!0}:{}}),{ok:!0,caller:o}},"internal"),public:p((e,r,n,v)=>{const o=r.wsKey??r.svc?.wsKey??a.wsKey,l=(0,act_1.actTicketOf)(e);let t;if(l!==void 0){if(t=k&&(0,chooser_1.isLoopbackRequest)(e)?k.redeem(l,o):void 0,!t)return i(n,"auth",{mode:"act",ok:!1}),{ok:!1,status:401,reason:"unauthorized",detail:"Unauthorized: the act ticket is unknown, spent, expired or for another workspace \u2014 ask for a new one (lensmcp call)."};t.token?e.headers.authorization=`Bearer ${t.token}`:delete e.headers.authorization}const d=p(u=>t?{act:u,as:t.view.user,...t.view.tenant?{tenant:t.view.tenant}:{}}:{},"actStep"),h=r.auth;if(h){const u=v??(0,edge_1.canonicalPath)(e.url??"/")??(e.url??"/").split("?")[0],g=(e.method??"GET").toUpperCase(),y=(0,manifest_1.authRuleFor)(h,u,g);if(y.mode==="jwt"){const x=String(e.headers.host??"").split(":")[0].toLowerCase();let m=t&&!t.token?"identity":"token",f=m==="identity"?t.claims:(0,dev_auth_1.verifyDevJwt)(e,c?.for(x));return!f&&t&&(m="identity",f=t.claims,delete e.headers.authorization),f?y.rule&&!(0,manifest_1.evalRule)(y.rule,(0,dev_auth_1.devAttrs)(e,f,u))?(i(n,"authz",{ok:!1,...d(m)}),{ok:!1,status:403,reason:"forbidden",detail:"Forbidden: insufficient permission"}):((0,dev_auth_1.stampIdentity)(e,f),k&&!t&&(0,act_1.fromBrowser)(e)&&k.remember(o,f,bearerOf(e),x),i(n,"auth",{mode:"jwt",ok:!0,...d(m)}),{ok:!0,claims:f}):(i(n,"auth",{mode:"jwt",ok:!1}),{ok:!1,status:401,reason:"unauthorized",detail:"Unauthorized: invalid or missing token"})}return i(n,"auth",{mode:y.mode,...d(t?.token?"token":"identity")}),{ok:!0}}return i(n,"auth",{mode:"public",unconfigured:!0,...d(t?.token?"token":"identity")}),{ok:!0}},"publicAuth")}}w(createEdgeAuth,"createEdgeAuth"),p(createEdgeAuth,"createEdgeAuth");
1
+ "use strict";var z=Object.defineProperty;var g=(r,o)=>z(r,"name",{value:o,configurable:!0});var _=Object.defineProperty,w=g((r,o)=>_(r,"name",{value:o,configurable:!0}),"w"),b=Object.defineProperty,p=w((r,o)=>b(r,"name",{value:o,configurable:!0}),"p");Object.defineProperty(exports,"__esModule",{value:!0}),exports.declaredCallerIds=declaredCallerIds,exports.createEdgeAuth=createEdgeAuth;const manifest_1=require("../manifest"),act_1=require("./act"),chooser_1=require("./chooser"),dev_auth_1=require("./dev-auth"),edge_1=require("./edge"),NO_CALLER_IDS=new Set;function declaredCallerIds(r,o,c){const h=(r.registry?r.registry.allServices():r.services).filter(a=>c===void 0||a.wsKey===c),s=h.find(a=>a.project===o)?.decl.callerIds;if(!Array.isArray(s)||s.length===0)return NO_CALLER_IDS;const e=new Set(h.map(a=>a.project));for(const[a,n]of r.keyToProject)(c===void 0||r.keyToWorkspace?.get(a)===c)&&e.add(n);return new Set(s.filter(a=>typeof a=="string"&&a!==o&&!e.has(a)))}g(declaredCallerIds,"declaredCallerIds"),w(declaredCallerIds,"declaredCallerIds"),p(declaredCallerIds,"declaredCallerIds");const bearerOf=p(r=>{const o=r.headers.authorization,c=Array.isArray(o)?o[0]:o;return typeof c=="string"&&c.startsWith("Bearer ")?c.slice(7):void 0},"bearerOf");function createEdgeAuth(r,o,c,h){const{traceStep:s}=o;return{internal:p((e,a,n)=>{const m=String(e.headers["x-api-key"]??""),i=r.keyToProject.get(m);if(!i)return s(n,"auth",{mode:"x-api-key",ok:!1}),{ok:!1,status:401,reason:"unauthorized",detail:"Invalid or missing x-api-key for internal route."};const l=r.keyToWorkspace?.get(m),t=a.svc?.wsKey;if(l&&t&&l!==t)return s(n,"auth",{mode:"x-api-key",ok:!1,reason:"cross-workspace",caller:i,callerWorkspace:l,routeWorkspace:t}),{ok:!1,status:401,reason:"unauthorized",detail:"Invalid or missing x-api-key for internal route."};const d=(0,edge_1.claimedCallerIdOf)(e),k=d!==void 0&&d!==i&&declaredCallerIds(r,i,l).has(d)?d:i;e.headers["x-api-key-id"]=k,l?e.headers["x-api-key-workspace"]=l:delete e.headers["x-api-key-workspace"],e.__lensmcpCaller=i,delete e.headers["x-api-key"];const u=(0,edge_1.callerContextOf)(e);for(const[x,y]of Object.entries(u))e.headers[x]=y;return s(n,"auth",{mode:"x-api-key",ok:!0,caller:i,...k!==i?{as:k}:{},...d!==void 0&&d!==i&&k===i?{claimRefused:d}:{},...l?{callerWorkspace:l}:{},...u["x-tenant-id"]!==void 0?{callerTenant:!0}:{},...u["x-user-id"]!==void 0?{callerUser:!0}:{}}),{ok:!0,caller:i}},"internal"),public:p((e,a,n,m)=>{const i=a.wsKey??a.svc?.wsKey??r.wsKey,l=(0,act_1.actTicketOf)(e);let t;if(l!==void 0){if(t=h&&(0,chooser_1.isLoopbackRequest)(e)?h.redeem(l,i):void 0,!t)return s(n,"auth",{mode:"act",ok:!1}),{ok:!1,status:401,reason:"unauthorized",detail:"Unauthorized: the act ticket is unknown, spent, expired or for another workspace \u2014 ask for a new one (lensmcp call)."};t.token?e.headers.authorization=`Bearer ${t.token}`:delete e.headers.authorization}const d=p(u=>t?{act:u,as:t.view.user,...t.view.tenant?{tenant:t.view.tenant}:{}}:{},"actStep"),k=a.auth;if(k){const u=m??(0,edge_1.canonicalPath)(e.url??"/")??(e.url??"/").split("?")[0],x=(e.method??"GET").toUpperCase(),y=(0,manifest_1.authRuleFor)(k,u,x);if(y.mode==="jwt"){const j=String(e.headers.host??"").split(":")[0].toLowerCase();let v=t&&!t.token?"identity":"token",f=v==="identity"?t.claims:(0,dev_auth_1.verifyDevJwt)(e,c?.for(j));return!f&&t&&(v="identity",f=t.claims,delete e.headers.authorization),f?y.rule&&!(0,manifest_1.evalRule)(y.rule,(0,dev_auth_1.devAttrs)(e,f,u))?(s(n,"authz",{ok:!1,...d(v)}),{ok:!1,status:403,reason:"forbidden",detail:"Forbidden: insufficient permission"}):((0,dev_auth_1.stampIdentity)(e,f),h&&!t&&(0,act_1.fromBrowser)(e)&&h.remember(i,f,bearerOf(e),j),s(n,"auth",{mode:"jwt",ok:!0,...d(v)}),{ok:!0,claims:f}):(s(n,"auth",{mode:"jwt",ok:!1}),{ok:!1,status:401,reason:"unauthorized",detail:"Unauthorized: invalid or missing token"})}return s(n,"auth",{mode:y.mode,...d(t?.token?"token":"identity")}),{ok:!0}}return s(n,"auth",{mode:"public",unconfigured:!0,...d(t?.token?"token":"identity")}),{ok:!0}},"publicAuth")}}g(createEdgeAuth,"createEdgeAuth"),w(createEdgeAuth,"createEdgeAuth"),p(createEdgeAuth,"createEdgeAuth");
@@ -1,16 +1,16 @@
1
- "use strict";var m=Object.defineProperty;var l=(a,t)=>m(a,"name",{value:t,configurable:!0});var b=Object.defineProperty,i=l((a,t)=>b(a,"name",{value:t,configurable:!0}),"i");Object.defineProperty(exports,"__esModule",{value:!0}),exports.isLoopbackRequest=isLoopbackRequest,exports.displayRoot=displayRoot,exports.renderChooserPage=renderChooserPage,exports.serveChooser=serveChooser;const node_os_1=require("node:os"),workspace_registry_1=require("./workspace-registry"),esc=i(a=>a.replace(/[&<>"']/g,t=>({"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"})[t]),"esc");function isLoopbackRequest(a){const t=a.socket?.remoteAddress;if(!t)return!1;const o=t.startsWith("::ffff:")?t.slice(7):t;return o==="::1"||o==="127.0.0.1"||/^127\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(o)}l(isLoopbackRequest,"isLoopbackRequest"),i(isLoopbackRequest,"isLoopbackRequest");function displayRoot(a,t=(0,node_os_1.homedir)()){const o=a.replace(/\/+$/,"").split("/").filter(Boolean),c=o.slice(-2).join("/");if(!c)return"/";const p=t!==""&&(a===t||a.startsWith(`${t}/`)),s=o.length>2;return p?s?`~/\u2026/${c}`:`~/${c}`:s?`\u2026/${c}`:`/${c}`}l(displayRoot,"displayRoot"),i(displayRoot,"displayRoot");function renderChooserPage(a,t){const o=a.map(e=>({...e,live:e.key===t||(0,workspace_registry_1.isWorkspaceLive)(e)})).sort((e,n)=>Number(n.live)-Number(e.live)||e.key.localeCompare(n.key)),c=new Set(o.map(e=>e.key)),p=i(e=>!!e.instance&&c.has(e.instance.baseKey),"nested"),s=o.filter(e=>!p(e)),x=i(e=>o.filter(n=>n.instance?.baseKey===e),"worktreesOf"),f=i(e=>e.key===t?'<span class="badge here">running here</span>':e.live?'<span class="badge live">live</span>':'<span class="badge off">offline</span>',"badgeOf"),h=i(e=>{const n=x(e);if(n.length===0)return"";const d=n.map(r=>{const g=`<span class="wt-name">${esc(r.instance?.name??r.key)}</span> ${f(r)}<span class="wt-apex">${esc(r.instance?.apex??"")}</span>`;return r.live?`<a class="wt is-live" href="${esc(r.base)}/">${g}<span class="open">Open \u2192</span></a>`:`<div class="wt is-off">${g}</div>`}).join(`
1
+ "use strict";var y=Object.defineProperty;var p=(o,t)=>y(o,"name",{value:t,configurable:!0});var m=Object.defineProperty,l=p((o,t)=>m(o,"name",{value:t,configurable:!0}),"l"),b=Object.defineProperty,i=l((o,t)=>b(o,"name",{value:t,configurable:!0}),"i");Object.defineProperty(exports,"__esModule",{value:!0}),exports.isLoopbackRequest=isLoopbackRequest,exports.displayRoot=displayRoot,exports.renderChooserPage=renderChooserPage,exports.serveChooser=serveChooser;const node_os_1=require("node:os"),workspace_registry_1=require("./workspace-registry"),esc=i(o=>o.replace(/[&<>"']/g,t=>({"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"})[t]),"esc");function isLoopbackRequest(o){const t=o.socket?.remoteAddress;if(!t)return!1;const a=t.startsWith("::ffff:")?t.slice(7):t;return a==="::1"||a==="127.0.0.1"||/^127\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(a)}p(isLoopbackRequest,"isLoopbackRequest"),l(isLoopbackRequest,"isLoopbackRequest"),i(isLoopbackRequest,"isLoopbackRequest");function displayRoot(o,t=(0,node_os_1.homedir)()){const a=o.replace(/\/+$/,"").split("/").filter(Boolean),c=a.slice(-2).join("/");if(!c)return"/";const d=t!==""&&(o===t||o.startsWith(`${t}/`)),r=a.length>2;return d?r?`~/\u2026/${c}`:`~/${c}`:r?`\u2026/${c}`:`/${c}`}p(displayRoot,"displayRoot"),l(displayRoot,"displayRoot"),i(displayRoot,"displayRoot");function renderChooserPage(o,t){const a=o.map(e=>({...e,live:e.key===t||(0,workspace_registry_1.isWorkspaceLive)(e)})).sort((e,n)=>Number(n.live)-Number(e.live)||e.key.localeCompare(n.key)),c=new Set(a.map(e=>e.key)),d=i(e=>!!e.instance&&c.has(e.instance.baseKey),"nested"),r=a.filter(e=>!d(e)),h=i(e=>a.filter(n=>n.instance?.baseKey===e),"worktreesOf"),g=i(e=>e.key===t?'<span class="badge here">running here</span>':e.live?'<span class="badge live">live</span>':'<span class="badge off">offline</span>',"badgeOf"),u=i(e=>{const n=h(e);if(n.length===0)return"";const f=n.map(s=>{const x=`<span class="wt-name">${esc(s.instance?.name??s.key)}</span> ${g(s)}<span class="wt-apex">${esc(s.instance?.apex??"")}</span>`;return s.live?`<a class="wt is-live" href="${esc(s.base)}/">${x}<span class="open">Open \u2192</span></a>`:`<div class="wt is-off">${x}</div>`}).join(`
2
2
  `);return`
3
- <div class="worktrees"><div class="wt-head">Worktrees \xB7 ${n.filter(r=>r.live).length} running</div>
4
- ${d}
5
- </div>`},"worktreeList"),u=s.length===0?'<p class="empty">No workspaces registered yet. Start a gateway in a workspace (<code>lensmcp gateway start</code>) and it will appear here.</p>':s.map(e=>{const n=e.live?'<span class="open">Open dashboard \u2192</span>':'<span class="hint">start its gateway to open</span>',d=e.instance?`<div class="root">worktree <b>${esc(e.instance.name)}</b> of ${esc(e.instance.baseKey)} \xB7 ${esc(e.instance.apex)}</div>`:"",r=`<div class="card-main">
6
- <div class="key">${esc(e.key)} ${f(e)}</div>
7
- <div class="root">${esc(displayRoot(e.root))}</div>${d}
3
+ <div class="worktrees"><div class="wt-head">Worktrees \xB7 ${n.filter(s=>s.live).length} running</div>
4
+ ${f}
5
+ </div>`},"worktreeList"),v=r.length===0?'<p class="empty">No workspaces registered yet. Start a gateway in a workspace (<code>lensmcp gateway start</code>) and it will appear here.</p>':r.map(e=>{const n=e.live?'<span class="open">Open dashboard \u2192</span>':'<span class="hint">start its gateway to open</span>',f=e.instance?`<div class="root">worktree <b>${esc(e.instance.name)}</b> of ${esc(e.instance.baseKey)} \xB7 ${esc(e.instance.apex)}</div>`:"",s=`<div class="card-main">
6
+ <div class="key">${esc(e.key)} ${g(e)}</div>
7
+ <div class="root">${esc(displayRoot(e.root))}</div>${f}
8
8
  </div>
9
9
  <div class="card-action">${n}</div>`;return`<div class="group">${e.live?`<a class="card is-live" href="${esc(e.base)}/">
10
- ${r}
10
+ ${s}
11
11
  </a>`:`<div class="card is-off">
12
- ${r}
13
- </div>`}${h(e.key)}</div>`}).join(`
12
+ ${s}
13
+ </div>`}${u(e.key)}</div>`}).join(`
14
14
  `);return`<!doctype html>
15
15
  <html lang="en"><head>
16
16
  <meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1">
@@ -55,10 +55,10 @@
55
55
  <body><div class="wrap">
56
56
  <header>
57
57
  <h1>LensMCP workspaces</h1>
58
- <p class="sub">Pick a workspace to open its dashboard. ${s.filter(e=>e.live).length} live \xB7 ${s.length} known${o.length>s.length?` \xB7 ${o.length-s.length} worktree${o.length-s.length===1?"":"s"}`:""}.</p>
58
+ <p class="sub">Pick a workspace to open its dashboard. ${r.filter(e=>e.live).length} live \xB7 ${r.length} known${a.length>r.length?` \xB7 ${a.length-r.length} worktree${a.length-r.length===1?"":"s"}`:""}.</p>
59
59
  </header>
60
60
  <div class="list">
61
- ${u}
61
+ ${v}
62
62
  </div>
63
63
  <footer>Served by the gateway on <code>lensmcp.local</code>. This list updates as gateways start and stop.</footer>
64
- </div></body></html>`}l(renderChooserPage,"renderChooserPage"),i(renderChooserPage,"renderChooserPage");function serveChooser(a,t,o){if(o&&!isLoopbackRequest(o)){a.writeHead(404,{"content-type":"text/plain; charset=utf-8","cache-control":"no-store"}),a.end("not found");return}const c=renderChooserPage((0,workspace_registry_1.readWorkspaces)(),t);a.writeHead(200,{"content-type":"text/html; charset=utf-8","cache-control":"no-store"}),a.end(c)}l(serveChooser,"serveChooser"),i(serveChooser,"serveChooser");
64
+ </div></body></html>`}p(renderChooserPage,"renderChooserPage"),l(renderChooserPage,"renderChooserPage"),i(renderChooserPage,"renderChooserPage");function serveChooser(o,t,a){if(a&&!isLoopbackRequest(a)){o.writeHead(404,{"content-type":"text/plain; charset=utf-8","cache-control":"no-store"}),o.end("not found");return}const c=renderChooserPage((0,workspace_registry_1.readWorkspaces)(),t);o.writeHead(200,{"content-type":"text/html; charset=utf-8","cache-control":"no-store"}),o.end(c)}p(serveChooser,"serveChooser"),l(serveChooser,"serveChooser"),i(serveChooser,"serveChooser");
@@ -1,2 +1,2 @@
1
- "use strict";var O=Object.defineProperty;var w=(i,t)=>O(i,"name",{value:t,configurable:!0});var G=Object.defineProperty,f=w((i,t)=>G(i,"name",{value:t,configurable:!0}),"f");Object.defineProperty(exports,"__esModule",{value:!0}),exports.clusterVersion=void 0,exports.instanceSummary=instanceSummary,exports.controlSocketPath=controlSocketPath,exports.versionAtLoad=versionAtLoad,exports.readClusterVersion=readClusterVersion,exports.ensureOwnerOnlyDir=ensureOwnerOnlyDir,exports.startControlServer=startControlServer;const tslib_1=require("tslib"),fs=tslib_1.__importStar(require("node:fs")),http=tslib_1.__importStar(require("node:http")),os=tslib_1.__importStar(require("node:os")),path=tslib_1.__importStar(require("node:path")),discovery_1=require("./discovery"),guest_graph_1=require("./guest-graph"),guest_replay_1=require("./guest-replay"),registration_guards_1=require("./registration-guards"),scope_1=require("./scope"),service_keys_1=require("./service-keys"),workspace_log_1=require("./workspace-log"),workspace_middleware_1=require("./workspace-middleware");function instanceSummary(i){const t=i?.instance;return t?{instance:t.name,baseKey:t.baseKey,apex:t.apex,baseApex:t.baseApex,...t.frozen?{frozen:!0}:{}}:{}}w(instanceSummary,"instanceSummary"),f(instanceSummary,"instanceSummary");function controlSocketPath(){const i=process.env.LENSMCP_HOME||os.homedir();return path.join(i,".lensmcp","control.sock")}w(controlSocketPath,"controlSocketPath"),f(controlSocketPath,"controlSocketPath");const CONTROL_BODY_BYTES=1e6;class BodyTooLarge extends Error{static{w(this,"BodyTooLarge")}static{f(this,"BodyTooLarge")}constructor(t){super(`body too large (over ${t} bytes)`),this.limit=t}}exports.clusterVersion=versionAtLoad(()=>readClusterVersion(__dirname));function versionAtLoad(i){const t=i();return()=>t}w(versionAtLoad,"versionAtLoad"),f(versionAtLoad,"versionAtLoad");function readClusterVersion(i){let t=i;for(let l=0;l<6;l++){const h=path.join(t,"package.json");if(fs.existsSync(h))try{const g=JSON.parse(fs.readFileSync(h,"utf8"));if(g.name==="@lensmcp/cluster"&&typeof g.version=="string")return g.version}catch{}const a=path.dirname(t);if(a===t)break;t=a}}w(readClusterVersion,"readClusterVersion"),f(readClusterVersion,"readClusterVersion");function readJsonBody(i,t=CONTROL_BODY_BYTES){return new Promise((l,h)=>{const a=[];let g=0,S=!1;i.on("data",v=>{if(!S){if(g+=v.length,g>t){S=!0,a.length=0,h(new BodyTooLarge(t));return}a.push(v)}}),i.on("end",()=>{if(S)return;const v=Buffer.concat(a).toString("utf8");try{l({value:v?JSON.parse(v):{},bytes:g})}catch(k){h(k)}}),i.on("error",h)})}w(readJsonBody,"readJsonBody"),f(readJsonBody,"readJsonBody");function graphShare(i,t){return t-Buffer.byteLength(JSON.stringify({...i,projectGraph:null}))}w(graphShare,"graphShare"),f(graphShare,"graphShare");function graphVerdict(i){return i?i.refused===void 0?{forwarded:!0,accepted:!0}:{forwarded:!0,accepted:!1,reason:i.refused}:{forwarded:!1,accepted:!1}}w(graphVerdict,"graphVerdict"),f(graphVerdict,"graphVerdict");function ensureOwnerOnlyDir(i){try{fs.mkdirSync(i,{recursive:!0,mode:448})}catch{}try{const t=fs.lstatSync(i);return t.isDirectory()?((t.mode&63)!==0&&fs.chmodSync(i,448),!0):!1}catch{return!1}}w(ensureOwnerOnlyDir,"ensureOwnerOnlyDir"),f(ensureOwnerOnlyDir,"ensureOwnerOnlyDir");function startControlServer(i){const{rt:t}=i,l=controlSocketPath(),h=path.dirname(l);ensureOwnerOnlyDir(h)||console.warn(`[gateway] control home ${h} is not a usable owner-only directory \u2014 refusing to expose the control plane there.`);try{fs.unlinkSync(l)}catch{}const a=f((e,n,c)=>{e.writeHead(n,{"content-type":"application/json"}),e.end(JSON.stringify(c))},"send"),g=f(async(e,n,c=!1)=>{if(!e.wsKey||!e.root)return{status:400,json:{error:"wsKey and root are required"}};const r=e.projects??{},s=(0,discovery_1.projectSourceRoots)(e.root,r,e.projectDependencies),o=(0,scope_1.readLensScope)(e.root),u=o.key===e.wsKey,p=u&&o.sockNs!==e.wsKey?o.sockNs:void 0,{routes:y,services:d,instance:j}=(0,discovery_1.discoverRoutes)(e.root,r,void 0,e.wsKey,s,p,u?o.instance:void 0),b=(0,workspace_middleware_1.findGatewayMiddleware)(e.root,r),$={wsKey:e.wsKey,...p?{sockNs:p}:{},root:e.root,routes:y,services:d,...j?{instance:j}:{},...b?{middleware:b}:{}},_=(0,registration_guards_1.refuseRegistration)(t.registry,$);if(_)return console.warn(`[gateway] refused to register '${e.wsKey}' from ${e.root}: ${_.error}`),{status:409,json:_};if(c)return j?{status:200,json:{wsKey:e.wsKey,root:e.root,...instanceSummary($),env:j.env}}:{status:400,json:{error:`'${e.wsKey}' has no resolvable instance configuration`}};try{const m=(0,service_keys_1.adoptServiceKeys)(t,e.root,d,e.wsKey);m.added.length>0&&console.log(`[gateway] adopted east-west keys for ${e.wsKey}: ${m.added.join(", ")}`),m.regenerated.length>0&&console.warn(`[gateway] ${e.root} carried another workspace's east-west keys (a copied key file) \u2014 new keys for ${e.wsKey}: ${m.regenerated.join(", ")}`)}catch(m){console.error(`[gateway] could not adopt east-west keys for ${e.wsKey}: ${m.message}`)}try{(0,workspace_log_1.workspaceLogWriter)(e.root)?.(`[gateway] ${new Date().toISOString()} this workspace ('${e.wsKey}') is served by the daemon at ${t.root} (pid ${process.pid}); its gateway-level log is ${path.join(t.root,".lensmcp","gateway.log")}. Pod output for this workspace follows here. Attach live with \`lensmcp logs <service>\`.
2
- `)}catch{}let K;if(t.graphStores){const m={root:e.root,daemonRoot:t.root,otherRoots:t.registry.keys().filter(T=>T!==e.wsKey).flatMap(T=>t.registry.get(T)?.root??[])};K=e.projectGraph===void 0?void 0:(0,guest_graph_1.admitForwardedGraph)(e.projectGraph,{...m,bytes:graphShare(e,n)}),K?.refused!==void 0&&console.warn(`[gateway] refused the project graph '${e.wsKey}' forwarded from ${e.root}: ${K.refused} \u2014 its services start through \`nx run\` until the gateway computes it`),(0,registration_guards_1.sameRoot)(e.root,t.root)||t.graphStores.set((0,guest_graph_1.createGuestGraphStore)({wsKey:e.wsKey,root:e.root,...K?{admission:K}:{},context:m}))}return t.registry.register($),await i.onRegister?.($),t.rebuildRoutes(),t.root&&!(0,registration_guards_1.sameRoot)(e.root,t.root)&&(0,guest_replay_1.recordGuest)({wsKey:e.wsKey,root:e.root,projects:r,...e.projectDependencies?{projectDependencies:e.projectDependencies}:{},daemonRoot:t.root,registeredAt:new Date().toISOString()}),{status:200,json:{ok:!0,wsKey:e.wsKey,routes:y.length,services:d.length,workspaces:t.registry.keys(),...t.graphStores?{projectGraph:graphVerdict(K)}:{}}}},"register"),S=f((e,n)=>{const c=t.registry.get(e);if(!c)return{error:`no workspace '${e}' is registered`,workspaces:t.registry.keys()};const r=c.services.find(s=>s.project===n);return r?{svc:r}:{error:`'${e}' has no service '${n}'`,services:c.services.map(s=>s.project)}},"findService"),v=f(e=>({wsKey:e.wsKey,service:e.project,state:e.state,...e.generation!==void 0?{generation:e.generation}:{},...e.restart?{restart:e.restart}:{}}),"restartView"),k=http.createServer((e,n)=>{(async()=>{try{const c=(e.url??"").split("?")[0];if(e.method==="GET"&&c==="/list")return a(n,200,{workspaces:t.registry.keys().map(r=>{const s=t.registry.get(r);return{key:r,root:s?.root,routes:s?.routes.length??0,services:s?.services.length??0,...instanceSummary(s)}})});if(e.method==="GET"&&c==="/status"){const r=(0,exports.clusterVersion)();return a(n,200,{daemon:{pid:process.pid,wsKey:t.wsKey,...r?{version:r}:{}},workspaces:t.registry.keys().map(s=>{const o=t.registry.get(s);return{key:s,root:o?.root,routes:o?.routes.length??0,services:o?.services.length??0,isDaemon:s===t.wsKey,...instanceSummary(o)}}),services:t.registry.allServices().map(s=>({project:s.project,wsKey:s.wsKey,host:s.decl.host,state:s.state,...s.generation!==void 0?{generation:s.generation}:{},...s.restart?{restart:s.restart}:{}}))})}if(e.method==="GET"&&c==="/instance-env"){const r=new URL(e.url??"/","http://control").searchParams.get("wsKey")??"",s=t.registry.get(r);return s?s.instance?a(n,200,{wsKey:r,root:s.root,...instanceSummary(s),env:s.instance.env}):a(n,404,{error:`'${r}' is not an instance`}):a(n,404,{error:`no workspace '${r}' is registered`})}if(e.method==="POST"&&c==="/instance-env"){const{value:r,bytes:s}=await readJsonBody(e,CONTROL_BODY_BYTES+guest_graph_1.MAX_FORWARDED_GRAPH_BYTES),o=await g(r,s,!0);return a(n,o.status,o.json)}if(c==="/service"&&(e.method==="GET"||e.method==="POST")){const r=e.method==="GET"?Object.fromEntries(new URL(e.url??"/","http://control").searchParams):(await readJsonBody(e)).value??{};if(typeof r.wsKey!="string"||typeof r.service!="string")return a(n,400,{error:"wsKey and service are required"});const s=S(r.wsKey,r.service);if("error"in s)return a(n,404,s);const o=s.svc,u=f(()=>{let d=(o.stoppingUntil??0)>Date.now();if(o.stoppingPid)try{process.kill(o.stoppingPid,0),d=!0}catch{o.stoppingPid=void 0}return{service:o.project,state:o.state,stopped:o.manualStopped===!0&&!d,ready:!o.manualStopped&&o.state==="up"&&o.pool.socks.length>0,busy:d||o.actionStarting===!0||!!o.rolling||!!(o.restart&&!o.restart.done),failure:o.actionFailure??(!o.manualStopped&&o.restart?.done?.ok===!1?o.restart.done.error:void 0)}},"view");if(e.method==="GET")return a(n,200,u());const p=r.action;if(!["start","stop","restart"].includes(String(p)))return a(n,400,{error:"action must be start, stop or restart"});if(u().busy&&!(p==="stop"&&o.actionStarting&&!o.rolling))return a(n,409,{error:"A service lifecycle operation is already in progress"});if(p==="stop")return!o.proc&&o.pool.socks.length&&!o.manualStopped?a(n,409,{error:"This gateway does not own the adopted service process; stop it with its owner"}):(o.manualStopped=!0,o.stoppingPid=o.proc?.pid,o.stoppingUntil=Date.now()+(o.proc?1600:0),i.killService(o,"workspace action stop"),o.state="down",a(n,202,u()));if(p==="restart"){if(!i.restartService)return a(n,501,{error:"This gateway cannot restart services"});const d=i.restartService(o,{hard:r.hard===!0,reason:"workspace action restart"});return"refused"in d?a(n,409,{error:d.refused}):a(n,202,u())}if(!i.ensureService)return a(n,501,{error:"This gateway cannot start services"});const y=o.state!=="up"&&!o.proc;return o.manualStopped=!1,o.actionFailure=void 0,o.restart=void 0,o.actionStarting=!0,i.ensureService(o).then(d=>{!d&&!o.manualStopped&&(o.actionFailure="Service did not become ready")},d=>{o.actionFailure=String(d).slice(0,500)}).finally(()=>{o.actionStarting=!1}),a(n,202,{...u(),started:y})}if(c==="/restart"&&(e.method==="POST"||e.method==="GET")){const r=e.method==="GET"?Object.fromEntries(new URL(e.url??"/","http://control").searchParams):(await readJsonBody(e)).value??{},s=typeof r.wsKey=="string"?r.wsKey:"",o=typeof r.service=="string"?r.service:"";if(!s||!o)return a(n,400,{error:"wsKey and service are required"});const u=S(s,o);if("error"in u)return a(n,404,u);const p=u.svc;if(e.method==="GET")return a(n,200,v(p));if(!i.restartService)return a(n,501,{error:"this gateway cannot restart a service"});const y=typeof r.reason=="string"&&r.reason.trim()?r.reason.trim().slice(0,200):"asked for",d=i.restartService(p,{hard:r.hard===!0,reason:y});return"refused"in d?a(n,409,{error:d.refused,...v(p)}):a(n,202,{ok:!0,already:d.already,...v(p)})}if(e.method==="GET"&&c==="/identities"||e.method==="POST"&&c==="/act"){const r=e.method==="GET"?Object.fromEntries(new URL(e.url??"/","http://control").searchParams):(await readJsonBody(e)).value??{},s=typeof r.wsKey=="string"?r.wsKey:"";if(!s)return a(n,400,{error:"wsKey is required"});if(!t.registry.get(s)&&s!==t.wsKey)return a(n,404,{error:`no workspace '${s}' is registered`,workspaces:t.registry.keys()});if(!i.act)return a(n,501,{error:"acting as a signed-in user is turned off on this gateway (LENSMCP_GW_ACT=0)"});if(e.method==="GET")return a(n,200,{wsKey:s,identities:i.act.list(s)});const o=f(d=>typeof r[d]=="string"&&r[d].trim()?r[d].trim().slice(0,256):void 0,"pick"),u=o("user"),p=o("tenant"),y=i.act.mint(s,{...u?{user:u}:{},...p?{tenant:p}:{}});return"error"in y?a(n,404,{wsKey:s,...y}):a(n,200,{wsKey:s,...y})}if(e.method==="POST"&&c==="/register"){const{value:r,bytes:s}=await readJsonBody(e,CONTROL_BODY_BYTES+guest_graph_1.MAX_FORWARDED_GRAPH_BYTES),o=await g(r,s);return a(n,o.status,o.json)}if(e.method==="POST"&&c==="/unregister"){const r=(await readJsonBody(e)).value;if(!r.wsKey)return a(n,400,{error:"wsKey is required"});const s=(0,registration_guards_1.refuseUnregistration)(t.registry,{wsKey:r.wsKey,...r.root?{root:r.root}:{}},t.wsKey);if(s)return console.warn(`[gateway] refused to unregister '${r.wsKey}'${r.root?` for ${r.root}`:""}: ${s.error}`),a(n,409,s);const o=t.registry.unregister(r.wsKey);if(o){for(const u of o.services){const p=(0,service_keys_1.serviceKeyId)(u.wsKey??r.wsKey,u.project),y=t.serviceKeys[p];y&&(delete t.serviceKeys[p],t.keyToProject.delete(y),t.keyToWorkspace?.delete(y))}for(const u of o.services)i.killService(u,"workspace unregistered");t.graphStores?.delete(o.root),(0,guest_replay_1.forgetGuest)(r.wsKey),i.onUnregister?.(o)}return t.rebuildRoutes(),a(n,200,{ok:!0,removed:!!o,workspaces:t.registry.keys()})}a(n,404,{error:"not found"})}catch(c){if(c instanceof BodyTooLarge)return e.resume(),a(n,413,{error:c.message});a(n,500,{error:c.message})}})()});return k.listen(l,()=>{try{fs.chmodSync(l,384)}catch(e){console.warn(`[gateway] could not restrict ${l} to 0600:`,e.message)}}),{socketPath:l,async replay(){const{replay:e,gone:n}=(0,guest_replay_1.guestsToReplay)(t.root,(0,guest_replay_1.readGuests)()),c={replayed:[],refused:[],gone:n.map(r=>r.wsKey)};for(const r of n)(0,guest_replay_1.forgetGuest)(r.wsKey),console.log(`[gateway] not re-hosting '${r.wsKey}': ${r.root} is no longer a workspace \u2014 forgotten`);for(const r of e)if(!t.registry.has(r.wsKey))try{const s=await g({wsKey:r.wsKey,root:r.root,projects:r.projects,...r.projectDependencies?{projectDependencies:r.projectDependencies}:{}},0);s.status===200?(c.replayed.push(r.wsKey),console.log(`[gateway] re-hosted '${r.wsKey}' (${r.root}) \u2014 registered before this daemon restarted`)):(c.refused.push(r.wsKey),console.warn(`[gateway] could not re-host '${r.wsKey}' (${r.root}): ${JSON.stringify(s.json)} \u2014 \`lensmcp gateway start\` there`))}catch(s){c.refused.push(r.wsKey),console.warn(`[gateway] could not re-host '${r.wsKey}' (${r.root}): ${s.message}`)}return c},close:f(()=>{k.close();try{fs.unlinkSync(l)}catch{}},"close")}}w(startControlServer,"startControlServer"),f(startControlServer,"startControlServer");
1
+ "use strict";var E=Object.defineProperty;var g=(i,t)=>E(i,"name",{value:t,configurable:!0});var O=Object.defineProperty,w=g((i,t)=>O(i,"name",{value:t,configurable:!0}),"w"),G=Object.defineProperty,f=w((i,t)=>G(i,"name",{value:t,configurable:!0}),"f");Object.defineProperty(exports,"__esModule",{value:!0}),exports.clusterVersion=void 0,exports.instanceSummary=instanceSummary,exports.controlSocketPath=controlSocketPath,exports.versionAtLoad=versionAtLoad,exports.readClusterVersion=readClusterVersion,exports.ensureOwnerOnlyDir=ensureOwnerOnlyDir,exports.startControlServer=startControlServer;const tslib_1=require("tslib"),fs=tslib_1.__importStar(require("node:fs")),http=tslib_1.__importStar(require("node:http")),os=tslib_1.__importStar(require("node:os")),path=tslib_1.__importStar(require("node:path")),discovery_1=require("./discovery"),guest_graph_1=require("./guest-graph"),guest_replay_1=require("./guest-replay"),registration_guards_1=require("./registration-guards"),scope_1=require("./scope"),service_keys_1=require("./service-keys"),workspace_log_1=require("./workspace-log"),workspace_middleware_1=require("./workspace-middleware");function instanceSummary(i){const t=i?.instance;return t?{instance:t.name,baseKey:t.baseKey,apex:t.apex,baseApex:t.baseApex,...t.frozen?{frozen:!0}:{}}:{}}g(instanceSummary,"instanceSummary"),w(instanceSummary,"instanceSummary"),f(instanceSummary,"instanceSummary");function controlSocketPath(){const i=process.env.LENSMCP_HOME||os.homedir();return path.join(i,".lensmcp","control.sock")}g(controlSocketPath,"controlSocketPath"),w(controlSocketPath,"controlSocketPath"),f(controlSocketPath,"controlSocketPath");const CONTROL_BODY_BYTES=1e6;class BodyTooLarge extends Error{static{g(this,"BodyTooLarge")}static{w(this,"BodyTooLarge")}static{f(this,"BodyTooLarge")}constructor(t){super(`body too large (over ${t} bytes)`),this.limit=t}}exports.clusterVersion=versionAtLoad(()=>readClusterVersion(__dirname));function versionAtLoad(i){const t=i();return()=>t}g(versionAtLoad,"versionAtLoad"),w(versionAtLoad,"versionAtLoad"),f(versionAtLoad,"versionAtLoad");function readClusterVersion(i){let t=i;for(let l=0;l<6;l++){const v=path.join(t,"package.json");if(fs.existsSync(v))try{const h=JSON.parse(fs.readFileSync(v,"utf8"));if(h.name==="@lensmcp/cluster"&&typeof h.version=="string")return h.version}catch{}const a=path.dirname(t);if(a===t)break;t=a}}g(readClusterVersion,"readClusterVersion"),w(readClusterVersion,"readClusterVersion"),f(readClusterVersion,"readClusterVersion");function readJsonBody(i,t=CONTROL_BODY_BYTES){return new Promise((l,v)=>{const a=[];let h=0,K=!1;i.on("data",m=>{if(!K){if(h+=m.length,h>t){K=!0,a.length=0,v(new BodyTooLarge(t));return}a.push(m)}}),i.on("end",()=>{if(K)return;const m=Buffer.concat(a).toString("utf8");try{l({value:m?JSON.parse(m):{},bytes:h})}catch(j){v(j)}}),i.on("error",v)})}g(readJsonBody,"readJsonBody"),w(readJsonBody,"readJsonBody"),f(readJsonBody,"readJsonBody");function graphShare(i,t){return t-Buffer.byteLength(JSON.stringify({...i,projectGraph:null}))}g(graphShare,"graphShare"),w(graphShare,"graphShare"),f(graphShare,"graphShare");function graphVerdict(i){return i?i.refused===void 0?{forwarded:!0,accepted:!0}:{forwarded:!0,accepted:!1,reason:i.refused}:{forwarded:!1,accepted:!1}}g(graphVerdict,"graphVerdict"),w(graphVerdict,"graphVerdict"),f(graphVerdict,"graphVerdict");function ensureOwnerOnlyDir(i){try{fs.mkdirSync(i,{recursive:!0,mode:448})}catch{}try{const t=fs.lstatSync(i);return t.isDirectory()?((t.mode&63)!==0&&fs.chmodSync(i,448),!0):!1}catch{return!1}}g(ensureOwnerOnlyDir,"ensureOwnerOnlyDir"),w(ensureOwnerOnlyDir,"ensureOwnerOnlyDir"),f(ensureOwnerOnlyDir,"ensureOwnerOnlyDir");function startControlServer(i){const{rt:t}=i,l=controlSocketPath(),v=path.dirname(l);ensureOwnerOnlyDir(v)||console.warn(`[gateway] control home ${v} is not a usable owner-only directory \u2014 refusing to expose the control plane there.`);try{fs.unlinkSync(l)}catch{}const a=f((e,n,c)=>{e.writeHead(n,{"content-type":"application/json"}),e.end(JSON.stringify(c))},"send"),h=f(async(e,n,c=!1)=>{if(!e.wsKey||!e.root)return{status:400,json:{error:"wsKey and root are required"}};const r=e.projects??{},s=(0,discovery_1.projectSourceRoots)(e.root,r,e.projectDependencies),o=(0,scope_1.readLensScope)(e.root),d=o.key===e.wsKey,y=d&&o.sockNs!==e.wsKey?o.sockNs:void 0,{routes:p,services:u,instance:$}=(0,discovery_1.discoverRoutes)(e.root,r,void 0,e.wsKey,s,y,d?o.instance:void 0),P=(0,workspace_middleware_1.findGatewayMiddleware)(e.root,r),_={wsKey:e.wsKey,...y?{sockNs:y}:{},root:e.root,routes:p,services:u,...$?{instance:$}:{},...P?{middleware:P}:{}},b=(0,registration_guards_1.refuseRegistration)(t.registry,_);if(b)return console.warn(`[gateway] refused to register '${e.wsKey}' from ${e.root}: ${b.error}`),{status:409,json:b};if(c)return $?{status:200,json:{wsKey:e.wsKey,root:e.root,...instanceSummary(_),env:$.env}}:{status:400,json:{error:`'${e.wsKey}' has no resolvable instance configuration`}};try{const S=(0,service_keys_1.adoptServiceKeys)(t,e.root,u,e.wsKey);S.added.length>0&&console.log(`[gateway] adopted east-west keys for ${e.wsKey}: ${S.added.join(", ")}`),S.regenerated.length>0&&console.warn(`[gateway] ${e.root} carried another workspace's east-west keys (a copied key file) \u2014 new keys for ${e.wsKey}: ${S.regenerated.join(", ")}`)}catch(S){console.error(`[gateway] could not adopt east-west keys for ${e.wsKey}: ${S.message}`)}try{(0,workspace_log_1.workspaceLogWriter)(e.root)?.(`[gateway] ${new Date().toISOString()} this workspace ('${e.wsKey}') is served by the daemon at ${t.root} (pid ${process.pid}); its gateway-level log is ${path.join(t.root,".lensmcp","gateway.log")}. Pod output for this workspace follows here. Attach live with \`lensmcp logs <service>\`.
2
+ `)}catch{}let k;if(t.graphStores){const S={root:e.root,daemonRoot:t.root,otherRoots:t.registry.keys().filter(T=>T!==e.wsKey).flatMap(T=>t.registry.get(T)?.root??[])};k=e.projectGraph===void 0?void 0:(0,guest_graph_1.admitForwardedGraph)(e.projectGraph,{...S,bytes:graphShare(e,n)}),k?.refused!==void 0&&console.warn(`[gateway] refused the project graph '${e.wsKey}' forwarded from ${e.root}: ${k.refused} \u2014 its services start through \`nx run\` until the gateway computes it`),(0,registration_guards_1.sameRoot)(e.root,t.root)||t.graphStores.set((0,guest_graph_1.createGuestGraphStore)({wsKey:e.wsKey,root:e.root,...k?{admission:k}:{},context:S}))}return t.registry.register(_),await i.onRegister?.(_),t.rebuildRoutes(),t.root&&!(0,registration_guards_1.sameRoot)(e.root,t.root)&&(0,guest_replay_1.recordGuest)({wsKey:e.wsKey,root:e.root,projects:r,...e.projectDependencies?{projectDependencies:e.projectDependencies}:{},daemonRoot:t.root,registeredAt:new Date().toISOString()}),{status:200,json:{ok:!0,wsKey:e.wsKey,routes:p.length,services:u.length,workspaces:t.registry.keys(),...t.graphStores?{projectGraph:graphVerdict(k)}:{}}}},"register"),K=f((e,n)=>{const c=t.registry.get(e);if(!c)return{error:`no workspace '${e}' is registered`,workspaces:t.registry.keys()};const r=c.services.find(s=>s.project===n);return r?{svc:r}:{error:`'${e}' has no service '${n}'`,services:c.services.map(s=>s.project)}},"findService"),m=f(e=>({wsKey:e.wsKey,service:e.project,state:e.state,...e.generation!==void 0?{generation:e.generation}:{},...e.restart?{restart:e.restart}:{}}),"restartView"),j=http.createServer((e,n)=>{(async()=>{try{const c=(e.url??"").split("?")[0];if(e.method==="GET"&&c==="/list")return a(n,200,{workspaces:t.registry.keys().map(r=>{const s=t.registry.get(r);return{key:r,root:s?.root,routes:s?.routes.length??0,services:s?.services.length??0,...instanceSummary(s)}})});if(e.method==="GET"&&c==="/status"){const r=(0,exports.clusterVersion)();return a(n,200,{daemon:{pid:process.pid,wsKey:t.wsKey,...r?{version:r}:{}},workspaces:t.registry.keys().map(s=>{const o=t.registry.get(s);return{key:s,root:o?.root,routes:o?.routes.length??0,services:o?.services.length??0,isDaemon:s===t.wsKey,...instanceSummary(o)}}),services:t.registry.allServices().map(s=>({project:s.project,wsKey:s.wsKey,host:s.decl.host,state:s.state,...s.generation!==void 0?{generation:s.generation}:{},...s.restart?{restart:s.restart}:{}}))})}if(e.method==="GET"&&c==="/instance-env"){const r=new URL(e.url??"/","http://control").searchParams.get("wsKey")??"",s=t.registry.get(r);return s?s.instance?a(n,200,{wsKey:r,root:s.root,...instanceSummary(s),env:s.instance.env}):a(n,404,{error:`'${r}' is not an instance`}):a(n,404,{error:`no workspace '${r}' is registered`})}if(e.method==="POST"&&c==="/instance-env"){const{value:r,bytes:s}=await readJsonBody(e,CONTROL_BODY_BYTES+guest_graph_1.MAX_FORWARDED_GRAPH_BYTES),o=await h(r,s,!0);return a(n,o.status,o.json)}if(c==="/service"&&(e.method==="GET"||e.method==="POST")){const r=e.method==="GET"?Object.fromEntries(new URL(e.url??"/","http://control").searchParams):(await readJsonBody(e)).value??{};if(typeof r.wsKey!="string"||typeof r.service!="string")return a(n,400,{error:"wsKey and service are required"});const s=K(r.wsKey,r.service);if("error"in s)return a(n,404,s);const o=s.svc,d=f(()=>{let u=(o.stoppingUntil??0)>Date.now();if(o.stoppingPid)try{process.kill(o.stoppingPid,0),u=!0}catch{o.stoppingPid=void 0}return{service:o.project,state:o.state,stopped:o.manualStopped===!0&&!u,ready:!o.manualStopped&&o.state==="up"&&o.pool.socks.length>0,busy:u||o.actionStarting===!0||!!o.rolling||!!(o.restart&&!o.restart.done),failure:o.actionFailure??(!o.manualStopped&&o.restart?.done?.ok===!1?o.restart.done.error:void 0)}},"view");if(e.method==="GET")return a(n,200,d());const y=r.action;if(!["start","stop","restart"].includes(String(y)))return a(n,400,{error:"action must be start, stop or restart"});if(d().busy&&!(y==="stop"&&o.actionStarting&&!o.rolling))return a(n,409,{error:"A service lifecycle operation is already in progress"});if(y==="stop")return!o.proc&&o.pool.socks.length&&!o.manualStopped?a(n,409,{error:"This gateway does not own the adopted service process; stop it with its owner"}):(o.manualStopped=!0,o.stoppingPid=o.proc?.pid,o.stoppingUntil=Date.now()+(o.proc?1600:0),i.killService(o,"workspace action stop"),o.state="down",a(n,202,d()));if(y==="restart"){if(!i.restartService)return a(n,501,{error:"This gateway cannot restart services"});const u=i.restartService(o,{hard:r.hard===!0,reason:"workspace action restart"});return"refused"in u?a(n,409,{error:u.refused}):a(n,202,d())}if(!i.ensureService)return a(n,501,{error:"This gateway cannot start services"});const p=o.state!=="up"&&!o.proc;return o.manualStopped=!1,o.actionFailure=void 0,o.restart=void 0,o.actionStarting=!0,i.ensureService(o).then(u=>{!u&&!o.manualStopped&&(o.actionFailure="Service did not become ready")},u=>{o.actionFailure=String(u).slice(0,500)}).finally(()=>{o.actionStarting=!1}),a(n,202,{...d(),started:p})}if(c==="/restart"&&(e.method==="POST"||e.method==="GET")){const r=e.method==="GET"?Object.fromEntries(new URL(e.url??"/","http://control").searchParams):(await readJsonBody(e)).value??{},s=typeof r.wsKey=="string"?r.wsKey:"",o=typeof r.service=="string"?r.service:"";if(!s||!o)return a(n,400,{error:"wsKey and service are required"});const d=K(s,o);if("error"in d)return a(n,404,d);const y=d.svc;if(e.method==="GET")return a(n,200,m(y));if(!i.restartService)return a(n,501,{error:"this gateway cannot restart a service"});const p=typeof r.reason=="string"&&r.reason.trim()?r.reason.trim().slice(0,200):"asked for",u=i.restartService(y,{hard:r.hard===!0,reason:p});return"refused"in u?a(n,409,{error:u.refused,...m(y)}):a(n,202,{ok:!0,already:u.already,...m(y)})}if(e.method==="GET"&&c==="/identities"||e.method==="POST"&&c==="/act"){const r=e.method==="GET"?Object.fromEntries(new URL(e.url??"/","http://control").searchParams):(await readJsonBody(e)).value??{},s=typeof r.wsKey=="string"?r.wsKey:"";if(!s)return a(n,400,{error:"wsKey is required"});if(!t.registry.get(s)&&s!==t.wsKey)return a(n,404,{error:`no workspace '${s}' is registered`,workspaces:t.registry.keys()});if(!i.act)return a(n,501,{error:"acting as a signed-in user is turned off on this gateway (LENSMCP_GW_ACT=0)"});if(e.method==="GET")return a(n,200,{wsKey:s,identities:i.act.list(s)});const o=f(u=>typeof r[u]=="string"&&r[u].trim()?r[u].trim().slice(0,256):void 0,"pick"),d=o("user"),y=o("tenant"),p=i.act.mint(s,{...d?{user:d}:{},...y?{tenant:y}:{}});return"error"in p?a(n,404,{wsKey:s,...p}):a(n,200,{wsKey:s,...p})}if(e.method==="POST"&&c==="/register"){const{value:r,bytes:s}=await readJsonBody(e,CONTROL_BODY_BYTES+guest_graph_1.MAX_FORWARDED_GRAPH_BYTES),o=await h(r,s);return a(n,o.status,o.json)}if(e.method==="POST"&&c==="/unregister"){const r=(await readJsonBody(e)).value;if(!r.wsKey)return a(n,400,{error:"wsKey is required"});const s=(0,registration_guards_1.refuseUnregistration)(t.registry,{wsKey:r.wsKey,...r.root?{root:r.root}:{}},t.wsKey);if(s)return console.warn(`[gateway] refused to unregister '${r.wsKey}'${r.root?` for ${r.root}`:""}: ${s.error}`),a(n,409,s);const o=t.registry.unregister(r.wsKey);if(o){for(const d of o.services){const y=(0,service_keys_1.serviceKeyId)(d.wsKey??r.wsKey,d.project),p=t.serviceKeys[y];p&&(delete t.serviceKeys[y],t.keyToProject.delete(p),t.keyToWorkspace?.delete(p))}for(const d of o.services)i.killService(d,"workspace unregistered");t.graphStores?.delete(o.root),(0,guest_replay_1.forgetGuest)(r.wsKey),i.onUnregister?.(o)}return t.rebuildRoutes(),a(n,200,{ok:!0,removed:!!o,workspaces:t.registry.keys()})}a(n,404,{error:"not found"})}catch(c){if(c instanceof BodyTooLarge)return e.resume(),a(n,413,{error:c.message});a(n,500,{error:c.message})}})()});return j.listen(l,()=>{try{fs.chmodSync(l,384)}catch(e){console.warn(`[gateway] could not restrict ${l} to 0600:`,e.message)}}),{socketPath:l,async replay(){const{replay:e,gone:n}=(0,guest_replay_1.guestsToReplay)(t.root,(0,guest_replay_1.readGuests)()),c={replayed:[],refused:[],gone:n.map(r=>r.wsKey)};for(const r of n)(0,guest_replay_1.forgetGuest)(r.wsKey),console.log(`[gateway] not re-hosting '${r.wsKey}': ${r.root} is no longer a workspace \u2014 forgotten`);for(const r of e)if(!t.registry.has(r.wsKey))try{const s=await h({wsKey:r.wsKey,root:r.root,projects:r.projects,...r.projectDependencies?{projectDependencies:r.projectDependencies}:{}},0);s.status===200?(c.replayed.push(r.wsKey),console.log(`[gateway] re-hosted '${r.wsKey}' (${r.root}) \u2014 registered before this daemon restarted`)):(c.refused.push(r.wsKey),console.warn(`[gateway] could not re-host '${r.wsKey}' (${r.root}): ${JSON.stringify(s.json)} \u2014 \`lensmcp gateway start\` there`))}catch(s){c.refused.push(r.wsKey),console.warn(`[gateway] could not re-host '${r.wsKey}' (${r.root}): ${s.message}`)}return c},close:f(()=>{j.close();try{fs.unlinkSync(l)}catch{}},"close")}}g(startControlServer,"startControlServer"),w(startControlServer,"startControlServer"),f(startControlServer,"startControlServer");
@@ -1 +1 @@
1
- "use strict";var h=Object.defineProperty;var a=(e,r)=>h(e,"name",{value:r,configurable:!0});var l=Object.defineProperty,u=a((e,r)=>l(e,"name",{value:r,configurable:!0}),"u");Object.defineProperty(exports,"__esModule",{value:!0}),exports.devAttrs=void 0,exports.verifyDevJwt=verifyDevJwt,exports.stampIdentity=stampIdentity;const node_crypto_1=require("node:crypto"),edge_1=require("./edge");function bearerToken(e){const r=Array.isArray(e.headers.authorization)?e.headers.authorization[0]:e.headers.authorization,t=String(r??"");return t.startsWith("Bearer ")?t.slice(7):void 0}a(bearerToken,"bearerToken"),u(bearerToken,"bearerToken");function verifyDevJwt(e,r){const t=bearerToken(e);if(!t)return;const[s,n,f]=t.split(".");if(!s||!n||!f)return;if(r)return r.verify(t);let o;try{o=JSON.parse(Buffer.from(s,"base64url").toString()).alg}catch{return}if(typeof o=="string"&&o!=="HS256"){if(process.env.LENSMCP_GW_DEV_JWT_INSECURE_DECODE!=="1")return;try{const i=JSON.parse(Buffer.from(n,"base64url").toString());return typeof i.exp=="number"&&Date.now()/1e3>i.exp?void 0:i}catch{return}}const d=process.env.AUTH_JWT_SECRET??"tetros-dev-secret",y=(0,node_crypto_1.createHmac)("sha256",d).update(`${s}.${n}`).digest("base64url"),p=Buffer.from(f),c=Buffer.from(y);if(!(p.length!==c.length||!(0,node_crypto_1.timingSafeEqual)(p,c)))try{const i=JSON.parse(Buffer.from(n,"base64url").toString());return typeof i.exp=="number"&&Date.now()/1e3>i.exp?void 0:i}catch{return}}a(verifyDevJwt,"verifyDevJwt"),u(verifyDevJwt,"verifyDevJwt");function stampIdentity(e,r){const t=u((f,o)=>{o!=null&&o!==""&&(e.headers[f]=String(o))},"set");t("x-user-id",r.sub),t("x-tenant-id",r.tid);const s=r.roles;Array.isArray(s)&&s.length&&(e.headers["x-user-roles"]=s.map(String).join(","));const n=r.perms;Array.isArray(n)&&n.length&&(e.headers["x-user-permissions"]=n.map(String).join(","))}a(stampIdentity,"stampIdentity"),u(stampIdentity,"stampIdentity");const devAttrs=u((e,r,t)=>({...r,ip:(0,edge_1.clientIpOf)(e),method:(e.method??"GET").toUpperCase(),path:t??(0,edge_1.canonicalPath)(e.url??"/")??(e.url??"/").split("?")[0]}),"devAttrs");exports.devAttrs=devAttrs;
1
+ "use strict";var m=Object.defineProperty;var f=(e,r)=>m(e,"name",{value:r,configurable:!0});var h=Object.defineProperty,a=f((e,r)=>h(e,"name",{value:r,configurable:!0}),"a"),l=Object.defineProperty,u=a((e,r)=>l(e,"name",{value:r,configurable:!0}),"u");Object.defineProperty(exports,"__esModule",{value:!0}),exports.devAttrs=void 0,exports.verifyDevJwt=verifyDevJwt,exports.stampIdentity=stampIdentity;const node_crypto_1=require("node:crypto"),edge_1=require("./edge");function bearerToken(e){const r=Array.isArray(e.headers.authorization)?e.headers.authorization[0]:e.headers.authorization,t=String(r??"");return t.startsWith("Bearer ")?t.slice(7):void 0}f(bearerToken,"bearerToken"),a(bearerToken,"bearerToken"),u(bearerToken,"bearerToken");function verifyDevJwt(e,r){const t=bearerToken(e);if(!t)return;const[s,n,p]=t.split(".");if(!s||!n||!p)return;if(r)return r.verify(t);let i;try{i=JSON.parse(Buffer.from(s,"base64url").toString()).alg}catch{return}if(typeof i=="string"&&i!=="HS256"){if(process.env.LENSMCP_GW_DEV_JWT_INSECURE_DECODE!=="1")return;try{const o=JSON.parse(Buffer.from(n,"base64url").toString());return typeof o.exp=="number"&&Date.now()/1e3>o.exp?void 0:o}catch{return}}const y=process.env.AUTH_JWT_SECRET??"tetros-dev-secret",v=(0,node_crypto_1.createHmac)("sha256",y).update(`${s}.${n}`).digest("base64url"),c=Buffer.from(p),d=Buffer.from(v);if(!(c.length!==d.length||!(0,node_crypto_1.timingSafeEqual)(c,d)))try{const o=JSON.parse(Buffer.from(n,"base64url").toString());return typeof o.exp=="number"&&Date.now()/1e3>o.exp?void 0:o}catch{return}}f(verifyDevJwt,"verifyDevJwt"),a(verifyDevJwt,"verifyDevJwt"),u(verifyDevJwt,"verifyDevJwt");function stampIdentity(e,r){const t=u((p,i)=>{i!=null&&i!==""&&(e.headers[p]=String(i))},"set");t("x-user-id",r.sub),t("x-tenant-id",r.tid);const s=r.roles;Array.isArray(s)&&s.length&&(e.headers["x-user-roles"]=s.map(String).join(","));const n=r.perms;Array.isArray(n)&&n.length&&(e.headers["x-user-permissions"]=n.map(String).join(","))}f(stampIdentity,"stampIdentity"),a(stampIdentity,"stampIdentity"),u(stampIdentity,"stampIdentity");const devAttrs=u((e,r,t)=>({...r,ip:(0,edge_1.clientIpOf)(e),method:(e.method??"GET").toUpperCase(),path:t??(0,edge_1.canonicalPath)(e.url??"/")??(e.url??"/").split("?")[0]}),"devAttrs");exports.devAttrs=devAttrs;
@@ -1 +1 @@
1
- "use strict";var A=Object.defineProperty;var h=(e,s)=>A(e,"name",{value:s,configurable:!0});var I=Object.defineProperty,p=h((e,s)=>I(e,"name",{value:s,configurable:!0}),"p");Object.defineProperty(exports,"__esModule",{value:!0}),exports.RETIRING_SUFFIX=void 0,exports.stopRoutingTo=stopRoutingTo,exports.pickSock=pickSock,exports.lensPortFromUpstream=lensPortFromUpstream,exports.rewriteInstanceDecls=rewriteInstanceDecls,exports.discoverRoutes=discoverRoutes,exports.projectSourceRoots=projectSourceRoots;const tslib_1=require("tslib"),fs=tslib_1.__importStar(require("node:fs")),os=tslib_1.__importStar(require("node:os")),path=tslib_1.__importStar(require("node:path")),manifest_1=require("../manifest"),pod_sock_1=require("../../../pod-sock"),instance_1=require("./instance"),scope_1=require("./scope");exports.RETIRING_SUFFIX=".retiring";function sockIdentity(e){try{const s=fs.statSync(e);return`${s.dev}:${s.ino}:${s.ctimeMs}`}catch{return}}h(sockIdentity,"sockIdentity"),p(sockIdentity,"sockIdentity");function stopRoutingTo(e,s=()=>!0){let a;try{a=fs.readdirSync(e.dir)}catch{a=[]}const r=a.filter(t=>(0,pod_sock_1.isPodSockName)(t)&&s(t)).map(t=>path.join(e.dir,t));if(r.length===0)return r;const l=e.retired??=new Map;for(const t of r){const d=sockIdentity(t);d!==void 0&&l.set(t,d)}const n=new Set(r);return e.socks=e.socks.filter(t=>!n.has(t)),e.idx=-1,r}h(stopRoutingTo,"stopRoutingTo"),p(stopRoutingTo,"stopRoutingTo");function stillRetired(e,s){const a=e.retired?.get(s);return a===void 0?!1:sockIdentity(s)===a?!0:(e.retired?.delete(s),!1)}h(stillRetired,"stillRetired"),p(stillRetired,"stillRetired");function pickSock(e,s=1500){const a=Date.now();if(a-e.scannedAt>s){try{const r=fs.readdirSync(e.dir),l=r.filter(t=>(0,pod_sock_1.isPodSockName)(t)&&!stillRetired(e,path.join(e.dir,t)));if(e.retired)for(const t of[...e.retired.keys()])r.includes(path.basename(t))||e.retired.delete(t);const n=l.filter(t=>!r.includes(t+exports.RETIRING_SUFFIX));e.socks=(n.length>0?n:l).map(t=>path.join(e.dir,t))}catch{e.socks=[]}e.scannedAt=a}if(e.socks.length!==0)return e.idx=(e.idx+1)%e.socks.length,e.socks[e.idx]}h(pickSock,"pickSock"),p(pickSock,"pickSock");function lensPortFromUpstream(e){if(!e)return;const s=/:(\d+)/.exec(e);return s?Number(s[1]):void 0}h(lensPortFromUpstream,"lensPortFromUpstream"),p(lensPortFromUpstream,"lensPortFromUpstream");function rewriteInstanceDecls(e,s){const a=e.flatMap(([,n])=>[...n.host?[n.host]:[],...typeof n.internalHost=="string"?[n.internalHost]:[]]),r=s.apex??(0,instance_1.commonApex)(a);if(!r)return console.warn(`[gateway] instance '${s.name}': the declared hosts share no apex \u2014 set \`instance.apex\` in .lensmcp/config.json; no host is served for it.`),{decls:e.map(([n,t])=>[n,{...t,host:void 0,internalHost:!1,default:!1}])};const l=[];for(const[n,t]of e){const d={...t};if(t.host){const c=(0,instance_1.rewriteHost)(t.host,r,s.name);c||console.warn(`[gateway] instance '${s.name}': ${n}'s host ${t.host} is outside ${r} \u2014 not served for the instance.`),d.host=c}if(typeof t.internalHost=="string"){const c=(0,instance_1.rewriteHost)(t.internalHost,r,s.name);c||console.warn(`[gateway] instance '${s.name}': ${n}'s internal host ${t.internalHost} is outside ${r} \u2014 not served for the instance.`),d.internalHost=c??!1}l.push([n,d])}return{decls:l,baseApex:r,apex:`${s.name}.${r}`}}h(rewriteInstanceDecls,"rewriteInstanceDecls"),p(rewriteInstanceDecls,"rewriteInstanceDecls");function discoverRoutes(e,s,a=os.tmpdir(),r="",l={},n=r,t){const d=n||r,c=p(i=>d?path.join(a,d,`${i}-devserver`):path.join(a,`${i}-devserver`),"sockDirFor"),u=[],g=[],_=[],H=[],S={};let y,w=[];const F=new Map;for(const[i,o]of Object.entries(s))try{const f=JSON.parse(fs.readFileSync(path.join(e,o.root,"project.json"),"utf8")),m=f.cluster??f.davnx;m&&(w.push([i,m]),F.set(i,o.root))}catch{continue}let v={};t&&({decls:w,...v}=rewriteInstanceDecls(w,t));for(const[i,o]of w){const f={root:F.get(i)};let m,j,k,R;if(!o.service&&o.sources!==void 0&&console.warn(`[gateway] ${i}: cluster.sources is read from pod (service) decls only \u2014 ignored.`),o.service)o.lens&&console.warn(`[gateway] ${i}: cluster.lens is ignored for pod (service) decls \u2014 backends are instrumented by serve-hmr.`),m={dir:c(o.service),socks:[],idx:-1,scannedAt:0},j={project:i,decl:o,root:e,wsKey:r,...d!==r?{sockNs:d}:{},pool:m,state:"down",lastUsed:Date.now(),inflight:0,lastScaleAt:0},g.push(j);else if(o.lens){const x=o.port??lensPortFromUpstream(o.upstream)??5173;k=`http://localhost:${x}`,R={project:i,...r?{workspaceKey:r}:{},workspaceRoot:e,projectRoot:path.join(e,f.root),port:x,...l[i]?.length?{sourceRoots:l[i]}:{}},_.push(R)}else if(k=o.upstream??(o.port?`http://localhost:${o.port}`:void 0),!k){console.warn(`[gateway] ${i}: no service/upstream/port \u2014 skipped.`);continue}const b={...r?{wsKey:r}:{},project:i,prependPrefix:o.prependPrefix,target:k,pool:m,svc:j,prefix:o.path,auth:o.auth,lens:R};if(o.host&&(u.push({...b,host:o.host}),H.push(o.host),S[i]={host:o.host},m&&o.internalHost!==!1)){const x=typeof o.internalHost=="string"?o.internalHost:`internal.${o.host}`;u.push({...b,host:x,internal:!0}),S[i]={host:o.host,internalHost:x}}o.default&&(y={...b,prefix:void 0})}y&&(y.apex=v.apex??(0,scope_1.baseDomainOf)(H),u.push(y));let $;if(t&&v.apex&&v.baseApex){const i={name:t.name,apex:v.apex,baseApex:v.baseApex},o=(0,instance_1.instanceEnv)(e,(0,instance_1.instanceBuiltinEnv)(i,S));$={...i,baseKey:t.baseKey,env:o,...t.frozen?{frozen:!0}:{}};for(const f of g)f.instanceEnv=o,t.frozen&&(f.frozen=!0);for(const f of _)f.env=o,t.frozen&&(f.frozen=!0)}return(0,manifest_1.sortBySpecificity)(u),{routes:u,services:g,...$?{instance:$}:{}}}h(discoverRoutes,"discoverRoutes"),p(discoverRoutes,"discoverRoutes");function projectSourceRoots(e,s,a={}){const r={};for(const l of Object.keys(s)){const n=new Set,t=p(c=>{if(!n.has(c)){n.add(c);for(const u of a[c]??[])t(u)}},"visit");t(l);const d=[...n].map(c=>s[c]?.root).filter(c=>typeof c=="string").map(c=>path.resolve(e,c)).filter(c=>{const u=path.relative(e,c);return u===""||u!==".."&&!u.startsWith(`..${path.sep}`)&&!path.isAbsolute(u)});r[l]=[...new Set(d)]}return r}h(projectSourceRoots,"projectSourceRoots"),p(projectSourceRoots,"projectSourceRoots");
1
+ "use strict";var q=Object.defineProperty;var m=(e,o)=>q(e,"name",{value:o,configurable:!0});var A=Object.defineProperty,h=m((e,o)=>A(e,"name",{value:o,configurable:!0}),"h"),I=Object.defineProperty,p=h((e,o)=>I(e,"name",{value:o,configurable:!0}),"p");Object.defineProperty(exports,"__esModule",{value:!0}),exports.RETIRING_SUFFIX=void 0,exports.stopRoutingTo=stopRoutingTo,exports.pickSock=pickSock,exports.lensPortFromUpstream=lensPortFromUpstream,exports.rewriteInstanceDecls=rewriteInstanceDecls,exports.discoverRoutes=discoverRoutes,exports.projectSourceRoots=projectSourceRoots;const tslib_1=require("tslib"),fs=tslib_1.__importStar(require("node:fs")),os=tslib_1.__importStar(require("node:os")),path=tslib_1.__importStar(require("node:path")),manifest_1=require("../manifest"),pod_sock_1=require("../../../pod-sock"),instance_1=require("./instance"),scope_1=require("./scope");exports.RETIRING_SUFFIX=".retiring";function sockIdentity(e){try{const o=fs.statSync(e);return`${o.dev}:${o.ino}:${o.ctimeMs}`}catch{return}}m(sockIdentity,"sockIdentity"),h(sockIdentity,"sockIdentity"),p(sockIdentity,"sockIdentity");function stopRoutingTo(e,o=()=>!0){let a;try{a=fs.readdirSync(e.dir)}catch{a=[]}const r=a.filter(t=>(0,pod_sock_1.isPodSockName)(t)&&o(t)).map(t=>path.join(e.dir,t));if(r.length===0)return r;const l=e.retired??=new Map;for(const t of r){const d=sockIdentity(t);d!==void 0&&l.set(t,d)}const n=new Set(r);return e.socks=e.socks.filter(t=>!n.has(t)),e.idx=-1,r}m(stopRoutingTo,"stopRoutingTo"),h(stopRoutingTo,"stopRoutingTo"),p(stopRoutingTo,"stopRoutingTo");function stillRetired(e,o){const a=e.retired?.get(o);return a===void 0?!1:sockIdentity(o)===a?!0:(e.retired?.delete(o),!1)}m(stillRetired,"stillRetired"),h(stillRetired,"stillRetired"),p(stillRetired,"stillRetired");function pickSock(e,o=1500){const a=Date.now();if(a-e.scannedAt>o){try{const r=fs.readdirSync(e.dir),l=r.filter(t=>(0,pod_sock_1.isPodSockName)(t)&&!stillRetired(e,path.join(e.dir,t)));if(e.retired)for(const t of[...e.retired.keys()])r.includes(path.basename(t))||e.retired.delete(t);const n=l.filter(t=>!r.includes(t+exports.RETIRING_SUFFIX));e.socks=(n.length>0?n:l).map(t=>path.join(e.dir,t))}catch{e.socks=[]}e.scannedAt=a}if(e.socks.length!==0)return e.idx=(e.idx+1)%e.socks.length,e.socks[e.idx]}m(pickSock,"pickSock"),h(pickSock,"pickSock"),p(pickSock,"pickSock");function lensPortFromUpstream(e){if(!e)return;const o=/:(\d+)/.exec(e);return o?Number(o[1]):void 0}m(lensPortFromUpstream,"lensPortFromUpstream"),h(lensPortFromUpstream,"lensPortFromUpstream"),p(lensPortFromUpstream,"lensPortFromUpstream");function rewriteInstanceDecls(e,o){const a=e.flatMap(([,n])=>[...n.host?[n.host]:[],...typeof n.internalHost=="string"?[n.internalHost]:[]]),r=o.apex??(0,instance_1.commonApex)(a);if(!r)return console.warn(`[gateway] instance '${o.name}': the declared hosts share no apex \u2014 set \`instance.apex\` in .lensmcp/config.json; no host is served for it.`),{decls:e.map(([n,t])=>[n,{...t,host:void 0,internalHost:!1,default:!1}])};const l=[];for(const[n,t]of e){const d={...t};if(t.host){const c=(0,instance_1.rewriteHost)(t.host,r,o.name);c||console.warn(`[gateway] instance '${o.name}': ${n}'s host ${t.host} is outside ${r} \u2014 not served for the instance.`),d.host=c}if(typeof t.internalHost=="string"){const c=(0,instance_1.rewriteHost)(t.internalHost,r,o.name);c||console.warn(`[gateway] instance '${o.name}': ${n}'s internal host ${t.internalHost} is outside ${r} \u2014 not served for the instance.`),d.internalHost=c??!1}l.push([n,d])}return{decls:l,baseApex:r,apex:`${o.name}.${r}`}}m(rewriteInstanceDecls,"rewriteInstanceDecls"),h(rewriteInstanceDecls,"rewriteInstanceDecls"),p(rewriteInstanceDecls,"rewriteInstanceDecls");function discoverRoutes(e,o,a=os.tmpdir(),r="",l={},n=r,t){const d=n||r,c=p(i=>d?path.join(a,d,`${i}-devserver`):path.join(a,`${i}-devserver`),"sockDirFor"),u=[],S=[],H=[],F=[],R={};let k,w=[];const P=new Map;for(const[i,s]of Object.entries(o))try{const f=JSON.parse(fs.readFileSync(path.join(e,s.root,"project.json"),"utf8")),v=f.cluster??f.davnx;v&&(w.push([i,v]),P.set(i,s.root))}catch{continue}let x={};t&&({decls:w,...x}=rewriteInstanceDecls(w,t));for(const[i,s]of w){const f={root:P.get(i)};let v,$,g,b;if(!s.service&&s.sources!==void 0&&console.warn(`[gateway] ${i}: cluster.sources is read from pod (service) decls only \u2014 ignored.`),s.service)s.lens&&console.warn(`[gateway] ${i}: cluster.lens is ignored for pod (service) decls \u2014 backends are instrumented by serve-hmr.`),v={dir:c(s.service),socks:[],idx:-1,scannedAt:0},$={project:i,decl:s,root:e,wsKey:r,...d!==r?{sockNs:d}:{},pool:v,state:"down",lastUsed:Date.now(),inflight:0,lastScaleAt:0},S.push($);else if(s.lens){const y=s.port??lensPortFromUpstream(s.upstream)??5173;g=`http://localhost:${y}`,b={project:i,...r?{workspaceKey:r}:{},workspaceRoot:e,projectRoot:path.join(e,f.root),port:y,...l[i]?.length?{sourceRoots:l[i]}:{}},H.push(b)}else if(g=s.upstream??(s.port?`http://localhost:${s.port}`:void 0),!g){console.warn(`[gateway] ${i}: no service/upstream/port \u2014 skipped.`);continue}const _={...r?{wsKey:r}:{},project:i,prependPrefix:s.prependPrefix,target:g,pool:v,svc:$,prefix:s.path,auth:s.auth,lens:b};if(s.host&&(u.push({..._,host:s.host}),F.push(s.host),R[i]={host:s.host},v&&s.internalHost!==!1)){const y=typeof s.internalHost=="string"?s.internalHost:`internal.${s.host}`;u.push({..._,host:y,internal:!0}),R[i]={host:s.host,internalHost:y}}s.default&&(k={..._,prefix:void 0})}k&&(k.apex=x.apex??(0,scope_1.baseDomainOf)(F),u.push(k));let j;if(t&&x.apex&&x.baseApex){const i={name:t.name,apex:x.apex,baseApex:x.baseApex},s=(0,instance_1.instanceEnv)(e,(0,instance_1.instanceBuiltinEnv)(i,R));j={...i,baseKey:t.baseKey,env:s,...t.frozen?{frozen:!0}:{}};for(const f of S)f.instanceEnv=s,t.frozen&&(f.frozen=!0);for(const f of H)f.env=s,t.frozen&&(f.frozen=!0)}return(0,manifest_1.sortBySpecificity)(u),{routes:u,services:S,...j?{instance:j}:{}}}m(discoverRoutes,"discoverRoutes"),h(discoverRoutes,"discoverRoutes"),p(discoverRoutes,"discoverRoutes");function projectSourceRoots(e,o,a={}){const r={};for(const l of Object.keys(o)){const n=new Set,t=p(c=>{if(!n.has(c)){n.add(c);for(const u of a[c]??[])t(u)}},"visit");t(l);const d=[...n].map(c=>o[c]?.root).filter(c=>typeof c=="string").map(c=>path.resolve(e,c)).filter(c=>{const u=path.relative(e,c);return u===""||u!==".."&&!u.startsWith(`..${path.sep}`)&&!path.isAbsolute(u)});r[l]=[...new Set(d)]}return r}m(projectSourceRoots,"projectSourceRoots"),h(projectSourceRoots,"projectSourceRoots"),p(projectSourceRoots,"projectSourceRoots");
@@ -1 +1 @@
1
- "use strict";var E=Object.defineProperty;var c=(e,r)=>E(e,"name",{value:r,configurable:!0});var p=Object.defineProperty,o=c((e,r)=>p(e,"name",{value:r,configurable:!0}),"o");Object.defineProperty(exports,"__esModule",{value:!0}),exports.PREFLIGHT_METHODS_ROUTED=exports.PREFLIGHT_METHODS_NOROUTE=exports.corsPreflight=exports.PREFLIGHT_MAX_AGE=exports.cors=exports.isRoutedOrigin=exports.callerContextOf=exports.claimedCallerIdOf=exports.CLAIMED_CALLER_ID=exports.CALLER_CONTEXT=exports.CALLER_CONTEXT_HEADERS=exports.GATEWAY_OWNED_HEADERS=exports.sendError=exports.stampForwardingHeaders=exports.clientIpOf=exports.resolveClientIp=exports.CLIENT_IP=exports.rememberRawTarget=exports.rawTargetOf=exports.RAW_TARGET=exports.canonicalPath=exports.canonicalize=exports.ENCODED_STRUCTURE=void 0,exports.stripOwnedHeaders=stripOwnedHeaders;const gateway_errors_1=require("../gateway-errors"),client_ip_1=require("../client-ip"),manifest_1=require("../manifest"),act_1=require("./act");var canonical_path_1=require("../canonical-path");Object.defineProperty(exports,"ENCODED_STRUCTURE",{enumerable:!0,get:o(function(){return canonical_path_1.ENCODED_STRUCTURE},"get")}),Object.defineProperty(exports,"canonicalize",{enumerable:!0,get:o(function(){return canonical_path_1.canonicalize},"get")}),Object.defineProperty(exports,"canonicalPath",{enumerable:!0,get:o(function(){return canonical_path_1.canonicalPath},"get")}),Object.defineProperty(exports,"RAW_TARGET",{enumerable:!0,get:o(function(){return canonical_path_1.RAW_TARGET},"get")}),Object.defineProperty(exports,"rawTargetOf",{enumerable:!0,get:o(function(){return canonical_path_1.rawTargetOf},"get")}),Object.defineProperty(exports,"rememberRawTarget",{enumerable:!0,get:o(function(){return canonical_path_1.rememberRawTarget},"get")}),exports.CLIENT_IP=Symbol.for("lensmcp.gateway.clientIp");const FORWARDED=Symbol.for("lensmcp.gateway.forwarded"),peerOnly=(0,client_ip_1.createClientIpResolver)({}),resolverOf=o(e=>e.clientIp??peerOnly,"resolverOf"),peerOf=o(e=>e.socket?.remoteAddress??"","peerOf"),resolveClientIp=o((e,r)=>{const t=resolverOf(e).clientIpOf(r,peerOf(r));return r[exports.CLIENT_IP]=t,t},"resolveClientIp");exports.resolveClientIp=resolveClientIp;const clientIpOf=o(e=>e[exports.CLIENT_IP]??peerOf(e),"clientIpOf");exports.clientIpOf=clientIpOf;const stampForwardingHeaders=o((e,r)=>{const t=r;if(t[FORWARDED])return;t[FORWARDED]=!0;const s=peerOf(r);r.headers["x-forwarded-for"]=resolverOf(e).forwardedFor(r,s),r.headers["x-forwarded-proto"]=e.https?"https":"http";const n=r.headers.host;(resolverOf(e).trustProxyHops===0||!r.headers["x-forwarded-host"])&&(n?r.headers["x-forwarded-host"]=n:delete r.headers["x-forwarded-host"])},"stampForwardingHeaders");exports.stampForwardingHeaders=stampForwardingHeaders;const sendError=o((e,r,t,s,n,i,l)=>{const a=(0,gateway_errors_1.ensureRequestId)(r);return e.headersSent||e.writeHead(t,{"content-type":gateway_errors_1.GATEWAY_ERROR_CONTENT_TYPE,"x-request-id":a,...l??{}}),e.end((0,gateway_errors_1.gatewayErrorBody)(t,s,a,n,i)),a},"sendError");exports.sendError=sendError,exports.GATEWAY_OWNED_HEADERS=["x-internal-token","x-api-key-id","x-api-key-workspace","x-user-id","x-tenant-id","x-user-roles","x-user-permissions",act_1.ACT_HEADER],exports.CALLER_CONTEXT_HEADERS=["x-tenant-id","x-user-id"],exports.CALLER_CONTEXT=Symbol.for("lensmcp.gateway.callerContext"),exports.CLAIMED_CALLER_ID=Symbol.for("lensmcp.gateway.claimedCallerId");const CALLER_ID_VALUE=/^[a-z0-9][a-z0-9._-]{0,63}$/i,CALLER_CONTEXT_VALUE=/^[\x21-\x2b\x2d-\x7e]{1,128}$/;function stripOwnedHeaders(e){const r={};for(const s of exports.CALLER_CONTEXT_HEADERS){const n=e.headers[s];typeof n=="string"&&CALLER_CONTEXT_VALUE.test(n)&&(r[s]=n)}e[exports.CALLER_CONTEXT]=r;const t=e.headers["x-api-key-id"];typeof t=="string"&&CALLER_ID_VALUE.test(t)&&(e[exports.CLAIMED_CALLER_ID]=t),(0,act_1.setActTicketAside)(e);for(const s of exports.GATEWAY_OWNED_HEADERS)delete e.headers[s]}c(stripOwnedHeaders,"stripOwnedHeaders"),o(stripOwnedHeaders,"stripOwnedHeaders");const claimedCallerIdOf=o(e=>e[exports.CLAIMED_CALLER_ID],"claimedCallerIdOf");exports.claimedCallerIdOf=claimedCallerIdOf;const callerContextOf=o(e=>e[exports.CALLER_CONTEXT]??{},"callerContextOf");exports.callerContextOf=callerContextOf;const isRoutedOrigin=o((e,r)=>{if(!e||e==="null")return!1;let t;try{t=new URL(e).hostname.toLowerCase()}catch{return!1}return t?t==="localhost"||t==="127.0.0.1"||t==="::1"?!0:r.some(s=>!!s.host&&(0,manifest_1.hostMatches)(s.host,t)):!1},"isRoutedOrigin");exports.isRoutedOrigin=isRoutedOrigin;const cors=o((e,r,t)=>{const s=e.headers.origin;typeof s!="string"||s===""||(r.setHeader("vary","Origin"),(0,exports.isRoutedOrigin)(s,t)&&(r.setHeader("access-control-allow-origin",s),r.setHeader("access-control-allow-credentials","true")))},"cors");exports.cors=cors,exports.PREFLIGHT_MAX_AGE="7200";const corsPreflight=o((e,r,t,s)=>{(0,exports.cors)(e,r,s),r.writeHead(204,{"access-control-allow-methods":t,"access-control-allow-headers":String(e.headers["access-control-request-headers"]??"*"),"access-control-max-age":exports.PREFLIGHT_MAX_AGE}),r.end()},"corsPreflight");exports.corsPreflight=corsPreflight,exports.PREFLIGHT_METHODS_NOROUTE="GET,HEAD,OPTIONS",exports.PREFLIGHT_METHODS_ROUTED="GET,HEAD,POST,PUT,PATCH,DELETE,OPTIONS";
1
+ "use strict";var x=Object.defineProperty;var i=(e,r)=>x(e,"name",{value:r,configurable:!0});var E=Object.defineProperty,c=i((e,r)=>E(e,"name",{value:r,configurable:!0}),"c"),p=Object.defineProperty,o=c((e,r)=>p(e,"name",{value:r,configurable:!0}),"o");Object.defineProperty(exports,"__esModule",{value:!0}),exports.PREFLIGHT_METHODS_ROUTED=exports.PREFLIGHT_METHODS_NOROUTE=exports.corsPreflight=exports.PREFLIGHT_MAX_AGE=exports.cors=exports.isRoutedOrigin=exports.callerContextOf=exports.claimedCallerIdOf=exports.CLAIMED_CALLER_ID=exports.CALLER_CONTEXT=exports.CALLER_CONTEXT_HEADERS=exports.GATEWAY_OWNED_HEADERS=exports.sendError=exports.stampForwardingHeaders=exports.clientIpOf=exports.resolveClientIp=exports.CLIENT_IP=exports.rememberRawTarget=exports.rawTargetOf=exports.RAW_TARGET=exports.canonicalPath=exports.canonicalize=exports.ENCODED_STRUCTURE=void 0,exports.stripOwnedHeaders=stripOwnedHeaders;const gateway_errors_1=require("../gateway-errors"),client_ip_1=require("../client-ip"),manifest_1=require("../manifest"),act_1=require("./act");var canonical_path_1=require("../canonical-path");Object.defineProperty(exports,"ENCODED_STRUCTURE",{enumerable:!0,get:o(function(){return canonical_path_1.ENCODED_STRUCTURE},"get")}),Object.defineProperty(exports,"canonicalize",{enumerable:!0,get:o(function(){return canonical_path_1.canonicalize},"get")}),Object.defineProperty(exports,"canonicalPath",{enumerable:!0,get:o(function(){return canonical_path_1.canonicalPath},"get")}),Object.defineProperty(exports,"RAW_TARGET",{enumerable:!0,get:o(function(){return canonical_path_1.RAW_TARGET},"get")}),Object.defineProperty(exports,"rawTargetOf",{enumerable:!0,get:o(function(){return canonical_path_1.rawTargetOf},"get")}),Object.defineProperty(exports,"rememberRawTarget",{enumerable:!0,get:o(function(){return canonical_path_1.rememberRawTarget},"get")}),exports.CLIENT_IP=Symbol.for("lensmcp.gateway.clientIp");const FORWARDED=Symbol.for("lensmcp.gateway.forwarded"),peerOnly=(0,client_ip_1.createClientIpResolver)({}),resolverOf=o(e=>e.clientIp??peerOnly,"resolverOf"),peerOf=o(e=>e.socket?.remoteAddress??"","peerOf"),resolveClientIp=o((e,r)=>{const t=resolverOf(e).clientIpOf(r,peerOf(r));return r[exports.CLIENT_IP]=t,t},"resolveClientIp");exports.resolveClientIp=resolveClientIp;const clientIpOf=o(e=>e[exports.CLIENT_IP]??peerOf(e),"clientIpOf");exports.clientIpOf=clientIpOf;const stampForwardingHeaders=o((e,r)=>{const t=r;if(t[FORWARDED])return;t[FORWARDED]=!0;const s=peerOf(r);r.headers["x-forwarded-for"]=resolverOf(e).forwardedFor(r,s),r.headers["x-forwarded-proto"]=e.https?"https":"http";const n=r.headers.host;(resolverOf(e).trustProxyHops===0||!r.headers["x-forwarded-host"])&&(n?r.headers["x-forwarded-host"]=n:delete r.headers["x-forwarded-host"])},"stampForwardingHeaders");exports.stampForwardingHeaders=stampForwardingHeaders;const sendError=o((e,r,t,s,n,l,d)=>{const a=(0,gateway_errors_1.ensureRequestId)(r);return e.headersSent||e.writeHead(t,{"content-type":gateway_errors_1.GATEWAY_ERROR_CONTENT_TYPE,"x-request-id":a,...d??{}}),e.end((0,gateway_errors_1.gatewayErrorBody)(t,s,a,n,l)),a},"sendError");exports.sendError=sendError,exports.GATEWAY_OWNED_HEADERS=["x-internal-token","x-api-key-id","x-api-key-workspace","x-user-id","x-tenant-id","x-user-roles","x-user-permissions",act_1.ACT_HEADER],exports.CALLER_CONTEXT_HEADERS=["x-tenant-id","x-user-id"],exports.CALLER_CONTEXT=Symbol.for("lensmcp.gateway.callerContext"),exports.CLAIMED_CALLER_ID=Symbol.for("lensmcp.gateway.claimedCallerId");const CALLER_ID_VALUE=/^[a-z0-9][a-z0-9._-]{0,63}$/i,CALLER_CONTEXT_VALUE=/^[\x21-\x2b\x2d-\x7e]{1,128}$/;function stripOwnedHeaders(e){const r={};for(const s of exports.CALLER_CONTEXT_HEADERS){const n=e.headers[s];typeof n=="string"&&CALLER_CONTEXT_VALUE.test(n)&&(r[s]=n)}e[exports.CALLER_CONTEXT]=r;const t=e.headers["x-api-key-id"];typeof t=="string"&&CALLER_ID_VALUE.test(t)&&(e[exports.CLAIMED_CALLER_ID]=t),(0,act_1.setActTicketAside)(e);for(const s of exports.GATEWAY_OWNED_HEADERS)delete e.headers[s]}i(stripOwnedHeaders,"stripOwnedHeaders"),c(stripOwnedHeaders,"stripOwnedHeaders"),o(stripOwnedHeaders,"stripOwnedHeaders");const claimedCallerIdOf=o(e=>e[exports.CLAIMED_CALLER_ID],"claimedCallerIdOf");exports.claimedCallerIdOf=claimedCallerIdOf;const callerContextOf=o(e=>e[exports.CALLER_CONTEXT]??{},"callerContextOf");exports.callerContextOf=callerContextOf;const isRoutedOrigin=o((e,r)=>{if(!e||e==="null")return!1;let t;try{t=new URL(e).hostname.toLowerCase()}catch{return!1}return t?t==="localhost"||t==="127.0.0.1"||t==="::1"?!0:r.some(s=>!!s.host&&(0,manifest_1.hostMatches)(s.host,t)):!1},"isRoutedOrigin");exports.isRoutedOrigin=isRoutedOrigin;const cors=o((e,r,t)=>{const s=e.headers.origin;typeof s!="string"||s===""||(r.setHeader("vary","Origin"),(0,exports.isRoutedOrigin)(s,t)&&(r.setHeader("access-control-allow-origin",s),r.setHeader("access-control-allow-credentials","true")))},"cors");exports.cors=cors,exports.PREFLIGHT_MAX_AGE="7200";const corsPreflight=o((e,r,t,s)=>{(0,exports.cors)(e,r,s),r.writeHead(204,{"access-control-allow-methods":t,"access-control-allow-headers":String(e.headers["access-control-request-headers"]??"*"),"access-control-max-age":exports.PREFLIGHT_MAX_AGE}),r.end()},"corsPreflight");exports.corsPreflight=corsPreflight,exports.PREFLIGHT_METHODS_NOROUTE="GET,HEAD,OPTIONS",exports.PREFLIGHT_METHODS_ROUTED="GET,HEAD,POST,PUT,PATCH,DELETE,OPTIONS";
@@ -1,2 +1,2 @@
1
- "use strict";var _=Object.defineProperty;var u=(e,r)=>_(e,"name",{value:r,configurable:!0});var l=Object.defineProperty,f=u((e,r)=>l(e,"name",{value:r,configurable:!0}),"f");Object.defineProperty(exports,"__esModule",{value:!0}),exports.GUEST_GRAPH_RETRY_MS=exports.MAX_FORWARDED_PROJECTS=exports.MAX_FORWARDED_GRAPH_BYTES=exports.FORWARDED_GRAPH_FORMAT=void 0,exports.ownedByThisUser=ownedByThisUser,exports.admitForwardedGraph=admitForwardedGraph,exports.compactSourceMaps=compactSourceMaps,exports.projectsOnly=projectsOnly,exports.snapshotWorkspaceGraph=snapshotWorkspaceGraph,exports.graphSnapshotScript=graphSnapshotScript,exports.guestGraphEnv=guestGraphEnv,exports.forwardedGraphInChild=forwardedGraphInChild,exports.createGuestGraphStore=createGuestGraphStore;const tslib_1=require("tslib"),node_child_process_1=require("node:child_process"),fs=tslib_1.__importStar(require("node:fs")),os=tslib_1.__importStar(require("node:os")),path=tslib_1.__importStar(require("node:path")),pod_env_1=require("./pod-env"),project_graph_store_1=require("./project-graph-store"),registration_guards_1=require("./registration-guards");exports.FORWARDED_GRAPH_FORMAT=1,exports.MAX_FORWARDED_GRAPH_BYTES=8*1024*1024,exports.MAX_FORWARDED_PROJECTS=2e4,exports.GUEST_GRAPH_RETRY_MS=6e4;const GUEST_GRAPH_TIMEOUT_MS=12e4,SIGNATURE=/^(?:-|\?|\d+(?:\.\d+)?:\d+:\d+)$/;function megabytes(e){return`${(e/(1024*1024)).toFixed(1)} MB`}u(megabytes,"megabytes"),f(megabytes,"megabytes");const isRecord=f(e=>!!e&&typeof e=="object"&&!Array.isArray(e),"isRecord");function insideWorkspace(e){return e===""||path.isAbsolute(e)||/^[a-zA-Z]:/.test(e)?!1:!path.posix.normalize(e.replace(/\\/g,"/")).split("/").includes("..")}u(insideWorkspace,"insideWorkspace"),f(insideWorkspace,"insideWorkspace");function ownedByThisUser(e){const r=fs.statSync(e,{throwIfNoEntry:!1});if(!r?.isDirectory())return!1;if(typeof process.getuid!="function")return!0;const t=process.getuid();return r.uid===t||t===0&&r.uid===Number(process.env.SUDO_UID)}u(ownedByThisUser,"ownedByThisUser"),f(ownedByThisUser,"ownedByThisUser");function relativeDeclaringFiles(e,r){return(0,project_graph_store_1.declaringFiles)(e,r).map(t=>path.relative(e,t).split(path.sep).join("/"))}u(relativeDeclaringFiles,"relativeDeclaringFiles"),f(relativeDeclaringFiles,"relativeDeclaringFiles");function shapeProblem(e){if(!isRecord(e)||!isRecord(e.nodes)||!isRecord(e.dependencies))return"it has no `nodes` and `dependencies`";const r=e.nodes,t=Object.keys(r);if(t.length>exports.MAX_FORWARDED_PROJECTS)return`it names ${t.length} projects (at most ${exports.MAX_FORWARDED_PROJECTS})`;for(const o of t){const s=r[o];if(!isRecord(s)||s.name!==o||typeof s.type!="string"||!isRecord(s.data))return`project '${o}' is not a project node`;const n=s.data.root;if(typeof n!="string"||!insideWorkspace(n))return`project '${o}' has a root outside the workspace (${String(n)})`;const p=s.data.targets;if(p!==void 0&&(!isRecord(p)||!Object.values(p).every(isRecord)))return`project '${o}' has malformed targets`}for(const[o,s]of Object.entries(e.dependencies)){if(!(o in r)||!Array.isArray(s))return`the dependencies of '${o}' are not a known project's`;for(const n of s)if(!isRecord(n)||n.source!==o||typeof n.target!="string"||!(n.target in r)||typeof n.type!="string")return`a dependency of '${o}' is malformed`}}u(shapeProblem,"shapeProblem"),f(shapeProblem,"shapeProblem");function sourceMapsProblem(e){if(e!==void 0){if(!isRecord(e))return"its source maps are not a map";for(const[r,t]of Object.entries(e)){if(!isRecord(t))return`the source map of ${r} is malformed`;for(const o of Object.values(t))if(!Array.isArray(o)||o.length!==2||o[0]!==null&&typeof o[0]!="string"||typeof o[1]!="string")return`the source map of ${r} is malformed`}}}u(sourceMapsProblem,"sourceMapsProblem"),f(sourceMapsProblem,"sourceMapsProblem");function admitForwardedGraph(e,r){const t=f(a=>({refused:a}),"refuse");if(r.bytes>exports.MAX_FORWARDED_GRAPH_BYTES)return t(`${megabytes(r.bytes)} is over the ${megabytes(exports.MAX_FORWARDED_GRAPH_BYTES)} limit`);if(!isRecord(e))return t("it is not a project graph");if(e.format!==exports.FORWARDED_GRAPH_FORMAT)return t(`its format is ${String(e.format)}, and this gateway reads ${exports.FORWARDED_GRAPH_FORMAT}`);const o=e.root;if(typeof o!="string"||!path.isAbsolute(o))return t("it does not say which workspace it describes");if(!(0,registration_guards_1.sameRoot)(o,r.root))return t(`it describes ${o}, not the registering workspace ${r.root}`);if((0,registration_guards_1.sameRoot)(r.root,r.daemonRoot))return t(`${r.root} is the gateway's own workspace \u2014 the gateway reads that graph itself`);if(r.otherRoots.some(a=>(0,registration_guards_1.sameRoot)(a,r.root)))return t(`${r.root} is registered under another key`);if(!ownedByThisUser(r.root))return t(`${r.root} is not a directory this user owns`);const s=e.startedAt;if(typeof s!="number"||!Number.isFinite(s))return t("it does not say when it was computed");const n=shapeProblem(e.projectGraph)??sourceMapsProblem(e.sourceMaps);if(n)return t(n);const p=e.projectGraph,i=e.files;if(!isRecord(i))return t("it carries no fingerprint of its declaring files");const c=(0,registration_guards_1.canonicalRoot)(r.root),h=relativeDeclaringFiles(c,p),d=Object.keys(i),g=h.filter(a=>!(a in i));return g.length>0||d.length!==h.length?t(`its fingerprint does not cover exactly the files that declare it${g.length>0?` (no ${g[0]})`:""}`):Object.values(i).every(a=>typeof a=="string"&&SIGNATURE.test(a))?{snapshot:{root:c,startedAt:s,files:new Map(h.map(a=>[path.join(c,a),i[a]])),projectGraph:{nodes:p.nodes,dependencies:p.dependencies,externalNodes:{}},...e.sourceMaps!==void 0?{sourceMaps:e.sourceMaps}:{}}}:t("its fingerprint is malformed")}u(admitForwardedGraph,"admitForwardedGraph"),f(admitForwardedGraph,"admitForwardedGraph");function compactSourceMaps(e,r){const t={};for(const o of Object.values(e.nodes)){const s=r[o.data.root];if(!s)continue;const n=new Set;for(const i of Object.keys(o.data.targets??{})){const c=`targets.${i}`,h=new Set;for(const[d,g]of Object.entries(s)){if(d!==c&&!d.startsWith(`${c}.`))continue;const a=JSON.stringify(g);h.has(a)||(h.add(a),n.add(d))}}const p={};for(const[i,c]of Object.entries(s))n.has(i)&&(p[i]=c);t[o.data.root]=p}return t}u(compactSourceMaps,"compactSourceMaps"),f(compactSourceMaps,"compactSourceMaps");function projectsOnly(e){const r={};for(const[t,o]of Object.entries(e.dependencies))t in e.nodes&&(r[t]=o.filter(s=>s.target in e.nodes));return{nodes:e.nodes,dependencies:r}}u(projectsOnly,"projectsOnly"),f(projectsOnly,"projectsOnly");async function snapshotWorkspaceGraph(e,r=()=>(0,project_graph_store_1.computeProjectGraphInProcess)(e)){const t=Date.now(),o=(0,project_graph_store_1.filesystemNow)(),s=await r(),n=projectsOnly(s.projectGraph),p={};for(const i of(0,project_graph_store_1.declaringFiles)(e,s.projectGraph)){const c=fs.statSync(i,{throwIfNoEntry:!1});p[path.relative(e,i).split(path.sep).join("/")]=c&&c.mtimeMs>o?"?":(0,project_graph_store_1.statSignature)(i)}return{format:exports.FORWARDED_GRAPH_FORMAT,root:e,startedAt:t,projectGraph:n,...s.sourceMaps?{sourceMaps:compactSourceMaps(n,s.sourceMaps)}:{},files:p}}u(snapshotWorkspaceGraph,"snapshotWorkspaceGraph"),f(snapshotWorkspaceGraph,"snapshotWorkspaceGraph");function graphSnapshotScript(e=path.join(__dirname,"../../..")){const r=path.join(e,"graph-snapshot.js");if(fs.existsSync(r))return{path:r,execArgv:[]};const t=path.join(e,"graph-snapshot.ts");if(fs.existsSync(t))try{return{path:t,execArgv:["--require",require.resolve("@swc-node/register")]}}catch{return}}u(graphSnapshotScript,"graphSnapshotScript"),f(graphSnapshotScript,"graphSnapshotScript");function guestGraphEnv(e,r,t){const o={...(0,pod_env_1.podBaseEnv)(e,r,t)};for(const s of Object.keys(o))(s.startsWith("NX_TASK_")||["NX_WORKSPACE_ROOT","NX_WORKSPACE_ROOT_PATH","NX_WORKSPACE_DATA_DIRECTORY","NX_PROJECT_GRAPH_CACHE_DIRECTORY"].includes(s))&&delete o[s];return o.NX_DAEMON="false",o.NX_ISOLATE_PLUGINS="false",o}u(guestGraphEnv,"guestGraphEnv"),f(guestGraphEnv,"guestGraphEnv");function forwardedGraphInChild(e,r,t=graphSnapshotScript()){if(!t)return Promise.reject(new Error("graph-snapshot.js is missing from @lensmcp/cluster"));const o=fs.mkdtempSync(path.join(os.tmpdir(),"lensmcp-graph-")),s=path.join(o,"graph.json");return new Promise((n,p)=>{let i="";const c=(0,node_child_process_1.spawn)(process.execPath,[...t.execArgv,t.path,s],{cwd:e,env:r,stdio:["ignore","ignore","pipe"]});c.stderr?.on("data",d=>{i.length<4096&&(i+=d.toString())});const h=setTimeout(()=>c.kill("SIGKILL"),GUEST_GRAPH_TIMEOUT_MS);h.unref(),c.on("error",d=>{clearTimeout(h),p(d)}),c.on("exit",(d,g)=>{if(clearTimeout(h),d!==0){const a=i.trim().split(`
2
- `).pop();p(new Error(`the graph computation in ${e} exited ${g??d}${a?` \u2014 ${a}`:""}`));return}try{const a=fs.statSync(s).size;n({bytes:a,graph:a>exports.MAX_FORWARDED_GRAPH_BYTES?void 0:JSON.parse(fs.readFileSync(s,"utf8"))})}catch(a){p(a)}})}).finally(()=>fs.rmSync(o,{recursive:!0,force:!0}))}u(forwardedGraphInChild,"forwardedGraphInChild"),f(forwardedGraphInChild,"forwardedGraphInChild");function createGuestGraphStore(e,r=process.env){const{wsKey:t,admission:o,context:s}=e,n=(0,registration_guards_1.canonicalRoot)(e.root),p=e.compute??(()=>forwardedGraphInChild(n,guestGraphEnv(r,s.daemonRoot,n))),i=o===void 0?"its registration forwarded none":o.refused!==void 0?`the project graph its registration forwarded was refused: ${o.refused}`:void 0;return(0,project_graph_store_1.createProjectGraphStore)(n,async()=>{const{graph:c,bytes:h}=await p(),d=admitForwardedGraph(c,{...s,bytes:h});if(d.refused!==void 0)throw new Error(`the computed project graph was refused: ${d.refused}`);return{projectGraph:d.snapshot.projectGraph,...d.snapshot.sourceMaps?{sourceMaps:d.snapshot.sourceMaps}:{}}},{...o?.snapshot?{seed:o.snapshot}:{},...i?{error:i}:{},retryAfterFailureMs:exports.GUEST_GRAPH_RETRY_MS,onRefreshed:f(c=>console.log(`[gateway] project graph of '${t}' (${n}) refreshed \u2014 ${Object.keys(c.projectGraph.nodes).length} projects; its services start through the serve runner again`),"onRefreshed")})}u(createGuestGraphStore,"createGuestGraphStore"),f(createGuestGraphStore,"createGuestGraphStore");
1
+ "use strict";var m=Object.defineProperty;var h=(e,t)=>m(e,"name",{value:t,configurable:!0});var _=Object.defineProperty,u=h((e,t)=>_(e,"name",{value:t,configurable:!0}),"u"),l=Object.defineProperty,f=u((e,t)=>l(e,"name",{value:t,configurable:!0}),"f");Object.defineProperty(exports,"__esModule",{value:!0}),exports.GUEST_GRAPH_RETRY_MS=exports.MAX_FORWARDED_PROJECTS=exports.MAX_FORWARDED_GRAPH_BYTES=exports.FORWARDED_GRAPH_FORMAT=void 0,exports.ownedByThisUser=ownedByThisUser,exports.admitForwardedGraph=admitForwardedGraph,exports.compactSourceMaps=compactSourceMaps,exports.projectsOnly=projectsOnly,exports.snapshotWorkspaceGraph=snapshotWorkspaceGraph,exports.graphSnapshotScript=graphSnapshotScript,exports.guestGraphEnv=guestGraphEnv,exports.forwardedGraphInChild=forwardedGraphInChild,exports.createGuestGraphStore=createGuestGraphStore;const tslib_1=require("tslib"),node_child_process_1=require("node:child_process"),fs=tslib_1.__importStar(require("node:fs")),os=tslib_1.__importStar(require("node:os")),path=tslib_1.__importStar(require("node:path")),pod_env_1=require("./pod-env"),project_graph_store_1=require("./project-graph-store"),registration_guards_1=require("./registration-guards");exports.FORWARDED_GRAPH_FORMAT=1,exports.MAX_FORWARDED_GRAPH_BYTES=8*1024*1024,exports.MAX_FORWARDED_PROJECTS=2e4,exports.GUEST_GRAPH_RETRY_MS=6e4;const GUEST_GRAPH_TIMEOUT_MS=12e4,SIGNATURE=/^(?:-|\?|\d+(?:\.\d+)?:\d+:\d+)$/;function megabytes(e){return`${(e/(1024*1024)).toFixed(1)} MB`}h(megabytes,"megabytes"),u(megabytes,"megabytes"),f(megabytes,"megabytes");const isRecord=f(e=>!!e&&typeof e=="object"&&!Array.isArray(e),"isRecord");function insideWorkspace(e){return e===""||path.isAbsolute(e)||/^[a-zA-Z]:/.test(e)?!1:!path.posix.normalize(e.replace(/\\/g,"/")).split("/").includes("..")}h(insideWorkspace,"insideWorkspace"),u(insideWorkspace,"insideWorkspace"),f(insideWorkspace,"insideWorkspace");function ownedByThisUser(e){const t=fs.statSync(e,{throwIfNoEntry:!1});if(!t?.isDirectory())return!1;if(typeof process.getuid!="function")return!0;const r=process.getuid();return t.uid===r||r===0&&t.uid===Number(process.env.SUDO_UID)}h(ownedByThisUser,"ownedByThisUser"),u(ownedByThisUser,"ownedByThisUser"),f(ownedByThisUser,"ownedByThisUser");function relativeDeclaringFiles(e,t){return(0,project_graph_store_1.declaringFiles)(e,t).map(r=>path.relative(e,r).split(path.sep).join("/"))}h(relativeDeclaringFiles,"relativeDeclaringFiles"),u(relativeDeclaringFiles,"relativeDeclaringFiles"),f(relativeDeclaringFiles,"relativeDeclaringFiles");function shapeProblem(e){if(!isRecord(e)||!isRecord(e.nodes)||!isRecord(e.dependencies))return"it has no `nodes` and `dependencies`";const t=e.nodes,r=Object.keys(t);if(r.length>exports.MAX_FORWARDED_PROJECTS)return`it names ${r.length} projects (at most ${exports.MAX_FORWARDED_PROJECTS})`;for(const o of r){const s=t[o];if(!isRecord(s)||s.name!==o||typeof s.type!="string"||!isRecord(s.data))return`project '${o}' is not a project node`;const n=s.data.root;if(typeof n!="string"||!insideWorkspace(n))return`project '${o}' has a root outside the workspace (${String(n)})`;const p=s.data.targets;if(p!==void 0&&(!isRecord(p)||!Object.values(p).every(isRecord)))return`project '${o}' has malformed targets`}for(const[o,s]of Object.entries(e.dependencies)){if(!(o in t)||!Array.isArray(s))return`the dependencies of '${o}' are not a known project's`;for(const n of s)if(!isRecord(n)||n.source!==o||typeof n.target!="string"||!(n.target in t)||typeof n.type!="string")return`a dependency of '${o}' is malformed`}}h(shapeProblem,"shapeProblem"),u(shapeProblem,"shapeProblem"),f(shapeProblem,"shapeProblem");function sourceMapsProblem(e){if(e!==void 0){if(!isRecord(e))return"its source maps are not a map";for(const[t,r]of Object.entries(e)){if(!isRecord(r))return`the source map of ${t} is malformed`;for(const o of Object.values(r))if(!Array.isArray(o)||o.length!==2||o[0]!==null&&typeof o[0]!="string"||typeof o[1]!="string")return`the source map of ${t} is malformed`}}}h(sourceMapsProblem,"sourceMapsProblem"),u(sourceMapsProblem,"sourceMapsProblem"),f(sourceMapsProblem,"sourceMapsProblem");function admitForwardedGraph(e,t){const r=f(a=>({refused:a}),"refuse");if(t.bytes>exports.MAX_FORWARDED_GRAPH_BYTES)return r(`${megabytes(t.bytes)} is over the ${megabytes(exports.MAX_FORWARDED_GRAPH_BYTES)} limit`);if(!isRecord(e))return r("it is not a project graph");if(e.format!==exports.FORWARDED_GRAPH_FORMAT)return r(`its format is ${String(e.format)}, and this gateway reads ${exports.FORWARDED_GRAPH_FORMAT}`);const o=e.root;if(typeof o!="string"||!path.isAbsolute(o))return r("it does not say which workspace it describes");if(!(0,registration_guards_1.sameRoot)(o,t.root))return r(`it describes ${o}, not the registering workspace ${t.root}`);if((0,registration_guards_1.sameRoot)(t.root,t.daemonRoot))return r(`${t.root} is the gateway's own workspace \u2014 the gateway reads that graph itself`);if(t.otherRoots.some(a=>(0,registration_guards_1.sameRoot)(a,t.root)))return r(`${t.root} is registered under another key`);if(!ownedByThisUser(t.root))return r(`${t.root} is not a directory this user owns`);const s=e.startedAt;if(typeof s!="number"||!Number.isFinite(s))return r("it does not say when it was computed");const n=shapeProblem(e.projectGraph)??sourceMapsProblem(e.sourceMaps);if(n)return r(n);const p=e.projectGraph,i=e.files;if(!isRecord(i))return r("it carries no fingerprint of its declaring files");const c=(0,registration_guards_1.canonicalRoot)(t.root),g=relativeDeclaringFiles(c,p),d=Object.keys(i),R=g.filter(a=>!(a in i));return R.length>0||d.length!==g.length?r(`its fingerprint does not cover exactly the files that declare it${R.length>0?` (no ${R[0]})`:""}`):Object.values(i).every(a=>typeof a=="string"&&SIGNATURE.test(a))?{snapshot:{root:c,startedAt:s,files:new Map(g.map(a=>[path.join(c,a),i[a]])),projectGraph:{nodes:p.nodes,dependencies:p.dependencies,externalNodes:{}},...e.sourceMaps!==void 0?{sourceMaps:e.sourceMaps}:{}}}:r("its fingerprint is malformed")}h(admitForwardedGraph,"admitForwardedGraph"),u(admitForwardedGraph,"admitForwardedGraph"),f(admitForwardedGraph,"admitForwardedGraph");function compactSourceMaps(e,t){const r={};for(const o of Object.values(e.nodes)){const s=t[o.data.root];if(!s)continue;const n=new Set;for(const i of Object.keys(o.data.targets??{})){const c=`targets.${i}`,g=new Set;for(const[d,R]of Object.entries(s)){if(d!==c&&!d.startsWith(`${c}.`))continue;const a=JSON.stringify(R);g.has(a)||(g.add(a),n.add(d))}}const p={};for(const[i,c]of Object.entries(s))n.has(i)&&(p[i]=c);r[o.data.root]=p}return r}h(compactSourceMaps,"compactSourceMaps"),u(compactSourceMaps,"compactSourceMaps"),f(compactSourceMaps,"compactSourceMaps");function projectsOnly(e){const t={};for(const[r,o]of Object.entries(e.dependencies))r in e.nodes&&(t[r]=o.filter(s=>s.target in e.nodes));return{nodes:e.nodes,dependencies:t}}h(projectsOnly,"projectsOnly"),u(projectsOnly,"projectsOnly"),f(projectsOnly,"projectsOnly");async function snapshotWorkspaceGraph(e,t=()=>(0,project_graph_store_1.computeProjectGraphInProcess)(e)){const r=Date.now(),o=(0,project_graph_store_1.filesystemNow)(),s=await t(),n=projectsOnly(s.projectGraph),p={};for(const i of(0,project_graph_store_1.declaringFiles)(e,s.projectGraph)){const c=fs.statSync(i,{throwIfNoEntry:!1});p[path.relative(e,i).split(path.sep).join("/")]=c&&c.mtimeMs>o?"?":(0,project_graph_store_1.statSignature)(i)}return{format:exports.FORWARDED_GRAPH_FORMAT,root:e,startedAt:r,projectGraph:n,...s.sourceMaps?{sourceMaps:compactSourceMaps(n,s.sourceMaps)}:{},files:p}}h(snapshotWorkspaceGraph,"snapshotWorkspaceGraph"),u(snapshotWorkspaceGraph,"snapshotWorkspaceGraph"),f(snapshotWorkspaceGraph,"snapshotWorkspaceGraph");function graphSnapshotScript(e=path.join(__dirname,"../../..")){const t=path.join(e,"graph-snapshot.js");if(fs.existsSync(t))return{path:t,execArgv:[]};const r=path.join(e,"graph-snapshot.ts");if(fs.existsSync(r))try{return{path:r,execArgv:["--require",require.resolve("@swc-node/register")]}}catch{return}}h(graphSnapshotScript,"graphSnapshotScript"),u(graphSnapshotScript,"graphSnapshotScript"),f(graphSnapshotScript,"graphSnapshotScript");function guestGraphEnv(e,t,r){const o={...(0,pod_env_1.podBaseEnv)(e,t,r)};for(const s of Object.keys(o))(s.startsWith("NX_TASK_")||["NX_WORKSPACE_ROOT","NX_WORKSPACE_ROOT_PATH","NX_WORKSPACE_DATA_DIRECTORY","NX_PROJECT_GRAPH_CACHE_DIRECTORY"].includes(s))&&delete o[s];return o.NX_DAEMON="false",o.NX_ISOLATE_PLUGINS="false",o}h(guestGraphEnv,"guestGraphEnv"),u(guestGraphEnv,"guestGraphEnv"),f(guestGraphEnv,"guestGraphEnv");function forwardedGraphInChild(e,t,r=graphSnapshotScript()){if(!r)return Promise.reject(new Error("graph-snapshot.js is missing from @lensmcp/cluster"));const o=fs.mkdtempSync(path.join(os.tmpdir(),"lensmcp-graph-")),s=path.join(o,"graph.json");return new Promise((n,p)=>{let i="";const c=(0,node_child_process_1.spawn)(process.execPath,[...r.execArgv,r.path,s],{cwd:e,env:t,stdio:["ignore","ignore","pipe"]});c.stderr?.on("data",d=>{i.length<4096&&(i+=d.toString())});const g=setTimeout(()=>c.kill("SIGKILL"),GUEST_GRAPH_TIMEOUT_MS);g.unref(),c.on("error",d=>{clearTimeout(g),p(d)}),c.on("exit",(d,R)=>{if(clearTimeout(g),d!==0){const a=i.trim().split(`
2
+ `).pop();p(new Error(`the graph computation in ${e} exited ${R??d}${a?` \u2014 ${a}`:""}`));return}try{const a=fs.statSync(s).size;n({bytes:a,graph:a>exports.MAX_FORWARDED_GRAPH_BYTES?void 0:JSON.parse(fs.readFileSync(s,"utf8"))})}catch(a){p(a)}})}).finally(()=>fs.rmSync(o,{recursive:!0,force:!0}))}h(forwardedGraphInChild,"forwardedGraphInChild"),u(forwardedGraphInChild,"forwardedGraphInChild"),f(forwardedGraphInChild,"forwardedGraphInChild");function createGuestGraphStore(e,t=process.env){const{wsKey:r,admission:o,context:s}=e,n=(0,registration_guards_1.canonicalRoot)(e.root),p=e.compute??(()=>forwardedGraphInChild(n,guestGraphEnv(t,s.daemonRoot,n))),i=o===void 0?"its registration forwarded none":o.refused!==void 0?`the project graph its registration forwarded was refused: ${o.refused}`:void 0;return(0,project_graph_store_1.createProjectGraphStore)(n,async()=>{const{graph:c,bytes:g}=await p(),d=admitForwardedGraph(c,{...s,bytes:g});if(d.refused!==void 0)throw new Error(`the computed project graph was refused: ${d.refused}`);return{projectGraph:d.snapshot.projectGraph,...d.snapshot.sourceMaps?{sourceMaps:d.snapshot.sourceMaps}:{}}},{...o?.snapshot?{seed:o.snapshot}:{},...i?{error:i}:{},retryAfterFailureMs:exports.GUEST_GRAPH_RETRY_MS,onRefreshed:f(c=>console.log(`[gateway] project graph of '${r}' (${n}) refreshed \u2014 ${Object.keys(c.projectGraph.nodes).length} projects; its services start through the serve runner again`),"onRefreshed")})}h(createGuestGraphStore,"createGuestGraphStore"),u(createGuestGraphStore,"createGuestGraphStore"),f(createGuestGraphStore,"createGuestGraphStore");
@@ -1,2 +1,2 @@
1
- "use strict";var a=Object.defineProperty;var n=(r,t)=>a(r,"name",{value:t,configurable:!0});var c=Object.defineProperty,o=n((r,t)=>c(r,"name",{value:t,configurable:!0}),"o");Object.defineProperty(exports,"__esModule",{value:!0}),exports.guestsFile=guestsFile,exports.readGuests=readGuests,exports.recordGuest=recordGuest,exports.forgetGuest=forgetGuest,exports.guestsToReplay=guestsToReplay;const tslib_1=require("tslib"),fs=tslib_1.__importStar(require("node:fs")),os=tslib_1.__importStar(require("node:os")),path=tslib_1.__importStar(require("node:path"));function guestsFile(){return path.join(process.env.LENSMCP_HOME||os.homedir(),".lensmcp","guests.json")}n(guestsFile,"guestsFile"),o(guestsFile,"guestsFile");function readGuests(r=guestsFile()){try{const t=JSON.parse(fs.readFileSync(r,"utf8"));return Array.isArray(t)?t.filter(e=>!!e&&typeof e=="object"&&typeof e.wsKey=="string"&&typeof e.root=="string"&&typeof e.daemonRoot=="string"&&!!e.projects&&typeof e.projects=="object"):[]}catch{return[]}}n(readGuests,"readGuests"),o(readGuests,"readGuests");function writeGuests(r,t){fs.mkdirSync(path.dirname(t),{recursive:!0,mode:448});const e=`${t}.${process.pid}.tmp`;fs.writeFileSync(e,JSON.stringify(r,null,2)+`
2
- `,{mode:384}),fs.renameSync(e,t)}n(writeGuests,"writeGuests"),o(writeGuests,"writeGuests");function recordGuest(r,t=guestsFile()){try{writeGuests([...readGuests(t).filter(e=>e.wsKey!==r.wsKey),r],t)}catch(e){console.warn(`[gateway] could not record '${r.wsKey}' for replay (${e.message}) \u2014 a daemon restart will not bring it back`)}}n(recordGuest,"recordGuest"),o(recordGuest,"recordGuest");function forgetGuest(r,t=guestsFile()){try{const e=readGuests(t),s=e.filter(i=>i.wsKey!==r);s.length!==e.length&&writeGuests(s,t)}catch{}}n(forgetGuest,"forgetGuest"),o(forgetGuest,"forgetGuest");const same=o((r,t)=>{const e=o(s=>{try{return fs.realpathSync(s)}catch{return path.resolve(s)}},"real");return e(r)===e(t)},"same");function guestsToReplay(r,t){const e=[],s=[];for(const i of t)!same(i.daemonRoot,r)||same(i.root,r)||(fs.existsSync(path.join(i.root,"package.json"))?e:s).push(i);return{replay:e,gone:s}}n(guestsToReplay,"guestsToReplay"),o(guestsToReplay,"guestsToReplay");
1
+ "use strict";var p=Object.defineProperty;var u=(r,t)=>p(r,"name",{value:t,configurable:!0});var a=Object.defineProperty,n=u((r,t)=>a(r,"name",{value:t,configurable:!0}),"n"),c=Object.defineProperty,o=n((r,t)=>c(r,"name",{value:t,configurable:!0}),"o");Object.defineProperty(exports,"__esModule",{value:!0}),exports.guestsFile=guestsFile,exports.readGuests=readGuests,exports.recordGuest=recordGuest,exports.forgetGuest=forgetGuest,exports.guestsToReplay=guestsToReplay;const tslib_1=require("tslib"),fs=tslib_1.__importStar(require("node:fs")),os=tslib_1.__importStar(require("node:os")),path=tslib_1.__importStar(require("node:path"));function guestsFile(){return path.join(process.env.LENSMCP_HOME||os.homedir(),".lensmcp","guests.json")}u(guestsFile,"guestsFile"),n(guestsFile,"guestsFile"),o(guestsFile,"guestsFile");function readGuests(r=guestsFile()){try{const t=JSON.parse(fs.readFileSync(r,"utf8"));return Array.isArray(t)?t.filter(e=>!!e&&typeof e=="object"&&typeof e.wsKey=="string"&&typeof e.root=="string"&&typeof e.daemonRoot=="string"&&!!e.projects&&typeof e.projects=="object"):[]}catch{return[]}}u(readGuests,"readGuests"),n(readGuests,"readGuests"),o(readGuests,"readGuests");function writeGuests(r,t){fs.mkdirSync(path.dirname(t),{recursive:!0,mode:448});const e=`${t}.${process.pid}.tmp`;fs.writeFileSync(e,JSON.stringify(r,null,2)+`
2
+ `,{mode:384}),fs.renameSync(e,t)}u(writeGuests,"writeGuests"),n(writeGuests,"writeGuests"),o(writeGuests,"writeGuests");function recordGuest(r,t=guestsFile()){try{writeGuests([...readGuests(t).filter(e=>e.wsKey!==r.wsKey),r],t)}catch(e){console.warn(`[gateway] could not record '${r.wsKey}' for replay (${e.message}) \u2014 a daemon restart will not bring it back`)}}u(recordGuest,"recordGuest"),n(recordGuest,"recordGuest"),o(recordGuest,"recordGuest");function forgetGuest(r,t=guestsFile()){try{const e=readGuests(t),s=e.filter(i=>i.wsKey!==r);s.length!==e.length&&writeGuests(s,t)}catch{}}u(forgetGuest,"forgetGuest"),n(forgetGuest,"forgetGuest"),o(forgetGuest,"forgetGuest");const same=o((r,t)=>{const e=o(s=>{try{return fs.realpathSync(s)}catch{return path.resolve(s)}},"real");return e(r)===e(t)},"same");function guestsToReplay(r,t){const e=[],s=[];for(const i of t)!same(i.daemonRoot,r)||same(i.root,r)||(fs.existsSync(path.join(i.root,"package.json"))?e:s).push(i);return{replay:e,gone:s}}u(guestsToReplay,"guestsToReplay"),n(guestsToReplay,"guestsToReplay"),o(guestsToReplay,"guestsToReplay");
@@ -1 +1 @@
1
- "use strict";var T=Object.defineProperty;var y=(f,n)=>T(f,"name",{value:n,configurable:!0});var O=Object.defineProperty,p=y((f,n)=>O(f,"name",{value:n,configurable:!0}),"p");Object.defineProperty(exports,"__esModule",{value:!0}),exports.createHandler=createHandler;const manifest_1=require("../manifest"),service_keys_1=require("./service-keys"),gateway_errors_1=require("../gateway-errors"),discovery_1=require("./discovery"),edge_1=require("./edge"),observability_1=require("./observability"),chooser_1=require("./chooser");function createHandler(f){const{rt:n,obs:u,auth:v,proxy:E,hooks:i}=f,R=p(e=>(e.headers.host||"").split(":")[0],"hostOf"),S=p((e,t)=>{if((0,edge_1.cors)(e,t,n.routes),e.method==="OPTIONS"){t.writeHead(204,{"access-control-allow-methods":edge_1.PREFLIGHT_METHODS_NOROUTE,"access-control-allow-headers":String(e.headers["access-control-request-headers"]??"*"),"access-control-max-age":edge_1.PREFLIGHT_MAX_AGE}),t.end();return}const o=(e.headers.host||"").split(":")[0],h=n.routes.filter(r=>r.host&&(0,manifest_1.hostMatches)(r.host,o)&&r.prefix),s=(e.url??"/").split("?")[0];if((s==="/"||s==="/index.html"||s==="")&&n.routes.some(r=>r.host&&(0,manifest_1.hostMatches)(r.host,o)&&r.project===observability_1.LENS_DASHBOARD_PROJECT)){(0,chooser_1.serveChooser)(t,n.wsKey,e);return}if(h.length>0&&(s==="/health"||s==="/healthz")){const r=h.map(l=>({project:l.project,prefix:l.prefix,pods:l.pool?((0,discovery_1.pickSock)(l.pool,0),l.pool.socks.length):void 0,state:l.svc?.state??(l.target?"up":"unknown")})),d=r.every(l=>l.state!=="down"||!0);t.writeHead(d?200:503,{"content-type":"application/json"}),t.end(JSON.stringify({status:"ok",host:o,services:r},null,2));return}if(h.length>0&&s==="/.well-known/services"){t.writeHead(200,{"content-type":"application/json"}),t.end(JSON.stringify({host:o,services:h.map(r=>({prefix:r.prefix,project:r.project,internal:!!r.internal}))},null,2));return}(0,edge_1.sendError)(t,e,404,"not_found",h.length>0?`No service mounted at ${s}. Mounted on ${o}: ${[...new Set(h.map(r=>r.prefix))].join(", ")} (+ /health, /.well-known/services)`:"No gateway route for this hostname.")},"handleNoRoute"),H=p(async(e,t)=>{if(!e.headers.host){const r=e.authority??e.headers[":authority"];r&&(e.headers.host=r)}(0,edge_1.stripOwnedHeaders)(e);let o=u.beginTrace(e);const h=Date.now();(0,gateway_errors_1.ensureRequestId)(e),o&&(u.traceStep(o,"received",{host:o.host,method:o.method,url:o.url}),e.__lensmcpTrace=o);const s=i.httpContext(e,t,o);try{const r=e.url??"/",d=(0,edge_1.canonicalize)(r);if(d===void 0){u.traceStep(o,"bad-path",{}),u.finishTrace(o,"gateway",400),(0,edge_1.sendError)(t,e,400,"bad_request","Bad Request");return}const l=d.policy,_=d.path+d.query;if(_!==r&&(0,edge_1.rememberRawTarget)(e,r),e.url=_,(0,edge_1.resolveClientIp)(n,e),i.has("onRequest")&&(await i.run("onRequest",s),s.responded()))return;const a=(0,manifest_1.matchRoute)(n.routes,R(e),l+d.query);if(!a){S(e,t);return}s.route=a;const w=u.startHeadlessFlow(e,a,o,h);if(w!==o&&(o=w,s.trace=w,e.__lensmcpTrace=w),u.traceStep(o,"route-match",{project:a.project,...a.prefix?{prefix:a.prefix}:{},...a.host?{routeHost:a.host}:{},...a.internal?{internal:!0}:{}}),e.method==="OPTIONS"){(0,edge_1.cors)(e,t,n.routes),t.writeHead(204,{"access-control-allow-methods":edge_1.PREFLIGHT_METHODS_ROUTED,"access-control-allow-headers":String(e.headers["access-control-request-headers"]??"*"),"access-control-max-age":edge_1.PREFLIGHT_MAX_AGE}),t.end();return}if((0,edge_1.cors)(e,t,n.routes),i.has("beforeAuth")&&(await i.run("beforeAuth",s),s.responded()))return;if(a.internal){const c=v.internal(e,a,o);if(!c.ok){u.finishTrace(o,a.project,c.status,void 0,a),(0,edge_1.sendError)(t,e,c.status,c.reason,c.detail);return}s.caller=c.caller}else{const c=v.public(e,a,o,l);if(!c.ok){u.finishTrace(o,a.project,c.status,void 0,a),(0,edge_1.sendError)(t,e,c.status,c.reason,c.detail);return}if(s.claims=c.claims,i.has("afterAuth")&&(await i.run("afterAuth",s),s.responded()))return}const g=a.pool?n.serviceKeys[(0,service_keys_1.serviceKeyId)(a.svc?.wsKey,a.project)]:void 0;if(g&&(e.headers["x-internal-token"]=g),(0,edge_1.stampForwardingHeaders)(n,e),i.has("beforeForward")&&(await i.run("beforeForward",s),s.responded()))return;i.has("onResponse")&&t.on("close",()=>{s.status=t.statusCode??0,i.run("onResponse",s)});const m=a.project===observability_1.LENS_DASHBOARD_PROJECT&&a.target?n.hostedDashboards?.get(a.target):void 0;m&&await m.serve(t),E.forward(a,e,t)}catch(r){s.error=r,console.error(`[gateway] ${new Date().toISOString()} pipeline error traceId=${(0,gateway_errors_1.ensureRequestId)(e)}: ${r?.stack??String(r)}`),i.has("onError")&&await i.run("onError",s),s.responded()||(0,edge_1.sendError)(t,e,500,"internal","Internal gateway error.")}},"runPipeline");return(e,t)=>{H(e,t)}}y(createHandler,"createHandler"),p(createHandler,"createHandler");
1
+ "use strict";var j=Object.defineProperty;var v=(h,n)=>j(h,"name",{value:n,configurable:!0});var T=Object.defineProperty,y=v((h,n)=>T(h,"name",{value:n,configurable:!0}),"y"),O=Object.defineProperty,p=y((h,n)=>O(h,"name",{value:n,configurable:!0}),"p");Object.defineProperty(exports,"__esModule",{value:!0}),exports.createHandler=createHandler;const manifest_1=require("../manifest"),service_keys_1=require("./service-keys"),gateway_errors_1=require("../gateway-errors"),discovery_1=require("./discovery"),edge_1=require("./edge"),observability_1=require("./observability"),chooser_1=require("./chooser");function createHandler(h){const{rt:n,obs:u,auth:g,proxy:H,hooks:i}=h,R=p(e=>(e.headers.host||"").split(":")[0],"hostOf"),S=p((e,t)=>{if((0,edge_1.cors)(e,t,n.routes),e.method==="OPTIONS"){t.writeHead(204,{"access-control-allow-methods":edge_1.PREFLIGHT_METHODS_NOROUTE,"access-control-allow-headers":String(e.headers["access-control-request-headers"]??"*"),"access-control-max-age":edge_1.PREFLIGHT_MAX_AGE}),t.end();return}const s=(e.headers.host||"").split(":")[0],l=n.routes.filter(r=>r.host&&(0,manifest_1.hostMatches)(r.host,s)&&r.prefix),o=(e.url??"/").split("?")[0];if((o==="/"||o==="/index.html"||o==="")&&n.routes.some(r=>r.host&&(0,manifest_1.hostMatches)(r.host,s)&&r.project===observability_1.LENS_DASHBOARD_PROJECT)){(0,chooser_1.serveChooser)(t,n.wsKey,e);return}if(l.length>0&&(o==="/health"||o==="/healthz")){const r=l.map(d=>({project:d.project,prefix:d.prefix,pods:d.pool?((0,discovery_1.pickSock)(d.pool,0),d.pool.socks.length):void 0,state:d.svc?.state??(d.target?"up":"unknown")})),f=r.every(d=>d.state!=="down"||!0);t.writeHead(f?200:503,{"content-type":"application/json"}),t.end(JSON.stringify({status:"ok",host:s,services:r},null,2));return}if(l.length>0&&o==="/.well-known/services"){t.writeHead(200,{"content-type":"application/json"}),t.end(JSON.stringify({host:s,services:l.map(r=>({prefix:r.prefix,project:r.project,internal:!!r.internal}))},null,2));return}(0,edge_1.sendError)(t,e,404,"not_found",l.length>0?`No service mounted at ${o}. Mounted on ${s}: ${[...new Set(l.map(r=>r.prefix))].join(", ")} (+ /health, /.well-known/services)`:"No gateway route for this hostname.")},"handleNoRoute"),b=p(async(e,t)=>{if(!e.headers.host){const r=e.authority??e.headers[":authority"];r&&(e.headers.host=r)}(0,edge_1.stripOwnedHeaders)(e);let s=u.beginTrace(e);const l=Date.now();(0,gateway_errors_1.ensureRequestId)(e),s&&(u.traceStep(s,"received",{host:s.host,method:s.method,url:s.url}),e.__lensmcpTrace=s);const o=i.httpContext(e,t,s);try{const r=e.url??"/",f=(0,edge_1.canonicalize)(r);if(f===void 0){u.traceStep(s,"bad-path",{}),u.finishTrace(s,"gateway",400),(0,edge_1.sendError)(t,e,400,"bad_request","Bad Request");return}const d=f.policy,_=f.path+f.query;if(_!==r&&(0,edge_1.rememberRawTarget)(e,r),e.url=_,(0,edge_1.resolveClientIp)(n,e),i.has("onRequest")&&(await i.run("onRequest",o),o.responded()))return;const a=(0,manifest_1.matchRoute)(n.routes,R(e),d+f.query);if(!a){S(e,t);return}o.route=a;const w=u.startHeadlessFlow(e,a,s,l);if(w!==s&&(s=w,o.trace=w,e.__lensmcpTrace=w),u.traceStep(s,"route-match",{project:a.project,...a.prefix?{prefix:a.prefix}:{},...a.host?{routeHost:a.host}:{},...a.internal?{internal:!0}:{}}),e.method==="OPTIONS"){(0,edge_1.cors)(e,t,n.routes),t.writeHead(204,{"access-control-allow-methods":edge_1.PREFLIGHT_METHODS_ROUTED,"access-control-allow-headers":String(e.headers["access-control-request-headers"]??"*"),"access-control-max-age":edge_1.PREFLIGHT_MAX_AGE}),t.end();return}if((0,edge_1.cors)(e,t,n.routes),i.has("beforeAuth")&&(await i.run("beforeAuth",o),o.responded()))return;if(a.internal){const c=g.internal(e,a,s);if(!c.ok){u.finishTrace(s,a.project,c.status,void 0,a),(0,edge_1.sendError)(t,e,c.status,c.reason,c.detail);return}o.caller=c.caller}else{const c=g.public(e,a,s,d);if(!c.ok){u.finishTrace(s,a.project,c.status,void 0,a),(0,edge_1.sendError)(t,e,c.status,c.reason,c.detail);return}if(o.claims=c.claims,i.has("afterAuth")&&(await i.run("afterAuth",o),o.responded()))return}const m=a.pool?n.serviceKeys[(0,service_keys_1.serviceKeyId)(a.svc?.wsKey,a.project)]:void 0;if(m&&(e.headers["x-internal-token"]=m),(0,edge_1.stampForwardingHeaders)(n,e),i.has("beforeForward")&&(await i.run("beforeForward",o),o.responded()))return;i.has("onResponse")&&t.on("close",()=>{o.status=t.statusCode??0,i.run("onResponse",o)});const E=a.project===observability_1.LENS_DASHBOARD_PROJECT&&a.target?n.hostedDashboards?.get(a.target):void 0;E&&await E.serve(t),H.forward(a,e,t)}catch(r){o.error=r,console.error(`[gateway] ${new Date().toISOString()} pipeline error traceId=${(0,gateway_errors_1.ensureRequestId)(e)}: ${r?.stack??String(r)}`),i.has("onError")&&await i.run("onError",o),o.responded()||(0,edge_1.sendError)(t,e,500,"internal","Internal gateway error.")}},"runPipeline");return(e,t)=>{b(e,t)}}v(createHandler,"createHandler"),y(createHandler,"createHandler"),p(createHandler,"createHandler");
@@ -1 +1 @@
1
- "use strict";var a=Object.defineProperty;var l=(n,e)=>a(n,"name",{value:e,configurable:!0});var c=Object.defineProperty,f=l((n,e)=>c(n,"name",{value:e,configurable:!0}),"f");Object.defineProperty(exports,"__esModule",{value:!0}),exports.VITE_FULL_RELOAD_PAYLOAD=void 0,exports.encodeWsTextFrame=encodeWsTextFrame,exports.registerHmrClient=registerHmrClient,exports.broadcastFullReload=broadcastFullReload,exports.VITE_FULL_RELOAD_PAYLOAD='{"type":"full-reload"}';function encodeWsTextFrame(n){const e=Buffer.from(n,"utf8"),t=e.length;if(t<126)return Buffer.concat([Buffer.from([129,t]),e]);if(t<=65535){const r=Buffer.alloc(4);return r[0]=129,r[1]=126,r.writeUInt16BE(t,2),Buffer.concat([r,e])}const o=Buffer.alloc(10);return o[0]=129,o[1]=127,o.writeBigUInt64BE(BigInt(t),2),Buffer.concat([o,e])}l(encodeWsTextFrame,"encodeWsTextFrame"),f(encodeWsTextFrame,"encodeWsTextFrame");function registerHmrClient(n,e,t){const o=n.hmrClients??=new Map;let r=o.get(e);r||o.set(e,r=new Set),r.add(t);const s=f(()=>{r.delete(t),r.size===0&&o.delete(e)},"drop");t.once("close",s),t.once("error",s)}l(registerHmrClient,"registerHmrClient"),f(registerHmrClient,"registerHmrClient");function broadcastFullReload(n,e){const t=n.hmrClients?.get(e);if(!t||t.size===0)return 0;const o=encodeWsTextFrame(exports.VITE_FULL_RELOAD_PAYLOAD);let r=0;for(const s of t)if(!s.destroyed)try{s.write(o),r+=1}catch{}return r}l(broadcastFullReload,"broadcastFullReload"),f(broadcastFullReload,"broadcastFullReload");
1
+ "use strict";var u=Object.defineProperty;var i=(o,e)=>u(o,"name",{value:e,configurable:!0});var a=Object.defineProperty,l=i((o,e)=>a(o,"name",{value:e,configurable:!0}),"l"),c=Object.defineProperty,f=l((o,e)=>c(o,"name",{value:e,configurable:!0}),"f");Object.defineProperty(exports,"__esModule",{value:!0}),exports.VITE_FULL_RELOAD_PAYLOAD=void 0,exports.encodeWsTextFrame=encodeWsTextFrame,exports.registerHmrClient=registerHmrClient,exports.broadcastFullReload=broadcastFullReload,exports.VITE_FULL_RELOAD_PAYLOAD='{"type":"full-reload"}';function encodeWsTextFrame(o){const e=Buffer.from(o,"utf8"),r=e.length;if(r<126)return Buffer.concat([Buffer.from([129,r]),e]);if(r<=65535){const t=Buffer.alloc(4);return t[0]=129,t[1]=126,t.writeUInt16BE(r,2),Buffer.concat([t,e])}const n=Buffer.alloc(10);return n[0]=129,n[1]=127,n.writeBigUInt64BE(BigInt(r),2),Buffer.concat([n,e])}i(encodeWsTextFrame,"encodeWsTextFrame"),l(encodeWsTextFrame,"encodeWsTextFrame"),f(encodeWsTextFrame,"encodeWsTextFrame");function registerHmrClient(o,e,r){const n=o.hmrClients??=new Map;let t=n.get(e);t||n.set(e,t=new Set),t.add(r);const s=f(()=>{t.delete(r),t.size===0&&n.delete(e)},"drop");r.once("close",s),r.once("error",s)}i(registerHmrClient,"registerHmrClient"),l(registerHmrClient,"registerHmrClient"),f(registerHmrClient,"registerHmrClient");function broadcastFullReload(o,e){const r=o.hmrClients?.get(e);if(!r||r.size===0)return 0;const n=encodeWsTextFrame(exports.VITE_FULL_RELOAD_PAYLOAD);let t=0;for(const s of r)if(!s.destroyed)try{s.write(n),t+=1}catch{}return t}i(broadcastFullReload,"broadcastFullReload"),l(broadcastFullReload,"broadcastFullReload"),f(broadcastFullReload,"broadcastFullReload");
@@ -1 +1 @@
1
- "use strict";var u=Object.defineProperty;var i=(t,e)=>u(t,"name",{value:e,configurable:!0});var a=Object.defineProperty,n=i((t,e)=>a(t,"name",{value:e,configurable:!0}),"n");Object.defineProperty(exports,"__esModule",{value:!0}),exports.createHooks=createHooks;const edge_1=require("./edge"),TERMINAL_PHASES=new Set(["onResponse","onError"]);function createHooks(t){return{run:n(async(e,r)=>{const o=t[e];if(!o||o.length===0)return;const d=TERMINAL_PHASES.has(e);for(const s of o){if(!d&&r.responded())return;await s(r)}},"run"),has:n(e=>(t[e]?.length??0)>0,"has"),httpContext:n((e,r,o)=>({req:e,res:r,socket:void 0,trace:o,route:void 0,claims:void 0,caller:void 0,pod:void 0,error:void 0,status:void 0,sendError:n((d,s,c)=>(0,edge_1.sendError)(r,e,d,s,c),"sendError"),responded:n(()=>r.writableEnded||r.headersSent,"responded")}),"httpContext"),upgradeContext:n((e,r,o)=>({req:e,res:void 0,socket:r,trace:o,route:void 0,claims:void 0,caller:void 0,pod:void 0,error:void 0,status:void 0,sendError:n(()=>{try{r.destroy()}catch{}},"sendError"),responded:n(()=>r.destroyed,"responded")}),"upgradeContext")}}i(createHooks,"createHooks"),n(createHooks,"createHooks");
1
+ "use strict";var p=Object.defineProperty;var c=(o,e)=>p(o,"name",{value:e,configurable:!0});var u=Object.defineProperty,i=c((o,e)=>u(o,"name",{value:e,configurable:!0}),"i"),a=Object.defineProperty,n=i((o,e)=>a(o,"name",{value:e,configurable:!0}),"n");Object.defineProperty(exports,"__esModule",{value:!0}),exports.createHooks=createHooks;const edge_1=require("./edge"),TERMINAL_PHASES=new Set(["onResponse","onError"]);function createHooks(o){return{run:n(async(e,r)=>{const t=o[e];if(!t||t.length===0)return;const d=TERMINAL_PHASES.has(e);for(const s of t){if(!d&&r.responded())return;await s(r)}},"run"),has:n(e=>(o[e]?.length??0)>0,"has"),httpContext:n((e,r,t)=>({req:e,res:r,socket:void 0,trace:t,route:void 0,claims:void 0,caller:void 0,pod:void 0,error:void 0,status:void 0,sendError:n((d,s,v)=>(0,edge_1.sendError)(r,e,d,s,v),"sendError"),responded:n(()=>r.writableEnded||r.headersSent,"responded")}),"httpContext"),upgradeContext:n((e,r,t)=>({req:e,res:void 0,socket:r,trace:t,route:void 0,claims:void 0,caller:void 0,pod:void 0,error:void 0,status:void 0,sendError:n(()=>{try{r.destroy()}catch{}},"sendError"),responded:n(()=>r.destroyed,"responded")}),"upgradeContext")}}c(createHooks,"createHooks"),i(createHooks,"createHooks"),n(createHooks,"createHooks");
@@ -1 +1 @@
1
- "use strict";var f=Object.defineProperty;var c=(s,e)=>f(s,"name",{value:e,configurable:!0});var p=Object.defineProperty,a=c((s,e)=>p(s,"name",{value:e,configurable:!0}),"a");Object.defineProperty(exports,"__esModule",{value:!0}),exports.DEFAULT_DASHBOARD_IDLE_SEC=exports.DASHBOARD_IDLE_ENV=exports.DASHBOARD_READY_MS=void 0,exports.dashboardIdleMs=dashboardIdleMs,exports.createHostedDashboard=createHostedDashboard,exports.DASHBOARD_READY_MS=2e4;const READY_POLL_MS=150;exports.DASHBOARD_IDLE_ENV="LENSMCP_DASHBOARD_IDLE_SEC",exports.DEFAULT_DASHBOARD_IDLE_SEC=600;function dashboardIdleMs(s=process.env){const e=s[exports.DASHBOARD_IDLE_ENV]?.trim(),t=e?Number(e):NaN;return!Number.isFinite(t)||t<0?exports.DEFAULT_DASHBOARD_IDLE_SEC*1e3:t>0?t*1e3:void 0}c(dashboardIdleMs,"dashboardIdleMs"),a(dashboardIdleMs,"dashboardIdleMs");const defaultSleep=a(s=>new Promise(e=>{setTimeout(e,s).unref?.()}),"defaultSleep");function createHostedDashboard(s,e){const t=e.now??Date.now,l=e.sleep??defaultSleep,_=e.log??(o=>console.log(o)),E=e.readyMs??exports.DASHBOARD_READY_MS;let r="parked",i,n=0,d=t(),D=!1;const A=a(o=>r!=="parked"||D?i??Promise.resolve():(r="starting",d=t(),o&&_(`[gateway] dashboard of '${s}' starting (${o})`),i=(async()=>{try{await e.start();const u=t()+E;for(;!D&&t()<u&&!await e.listening();)await l(READY_POLL_MS)}catch(u){_(`[gateway] dashboard of '${s}' did not start: ${u.message}`)}r==="starting"&&(r="up"),d=t()})(),i),"start"),S=a(()=>{r="parked",i=void 0,e.stop(),_(`[gateway] dashboard of '${s}' stopped \u2014 nobody has it open and no service of it runs (it starts on the next request)`)},"park");return e.idleMs===void 0&&A(),{async serve(o){n+=1,d=t(),o.once("close",()=>{n=Math.max(0,n-1),d=t()}),r!=="up"&&await A("a request for it")},tick(){if(D)return;const o=e.servicesUp();if(o&&(d=t()),r==="parked"){o&&A("a service of it is up");return}e.idleMs===void 0||r!=="up"||n>0||o||t()-d>=e.idleMs&&S()},state:a(()=>r,"state"),dispose(){D=!0}}}c(createHostedDashboard,"createHostedDashboard"),a(createHostedDashboard,"createHostedDashboard");
1
+ "use strict";var v=Object.defineProperty;var u=(s,e)=>v(s,"name",{value:e,configurable:!0});var f=Object.defineProperty,c=u((s,e)=>f(s,"name",{value:e,configurable:!0}),"c"),p=Object.defineProperty,a=c((s,e)=>p(s,"name",{value:e,configurable:!0}),"a");Object.defineProperty(exports,"__esModule",{value:!0}),exports.DEFAULT_DASHBOARD_IDLE_SEC=exports.DASHBOARD_IDLE_ENV=exports.DASHBOARD_READY_MS=void 0,exports.dashboardIdleMs=dashboardIdleMs,exports.createHostedDashboard=createHostedDashboard,exports.DASHBOARD_READY_MS=2e4;const READY_POLL_MS=150;exports.DASHBOARD_IDLE_ENV="LENSMCP_DASHBOARD_IDLE_SEC",exports.DEFAULT_DASHBOARD_IDLE_SEC=600;function dashboardIdleMs(s=process.env){const e=s[exports.DASHBOARD_IDLE_ENV]?.trim(),t=e?Number(e):NaN;return!Number.isFinite(t)||t<0?exports.DEFAULT_DASHBOARD_IDLE_SEC*1e3:t>0?t*1e3:void 0}u(dashboardIdleMs,"dashboardIdleMs"),c(dashboardIdleMs,"dashboardIdleMs"),a(dashboardIdleMs,"dashboardIdleMs");const defaultSleep=a(s=>new Promise(e=>{setTimeout(e,s).unref?.()}),"defaultSleep");function createHostedDashboard(s,e){const t=e.now??Date.now,E=e.sleep??defaultSleep,_=e.log??(r=>console.log(r)),S=e.readyMs??exports.DASHBOARD_READY_MS;let o="parked",i,n=0,d=t(),D=!1;const A=a(r=>o!=="parked"||D?i??Promise.resolve():(o="starting",d=t(),r&&_(`[gateway] dashboard of '${s}' starting (${r})`),i=(async()=>{try{await e.start();const l=t()+S;for(;!D&&t()<l&&!await e.listening();)await E(READY_POLL_MS)}catch(l){_(`[gateway] dashboard of '${s}' did not start: ${l.message}`)}o==="starting"&&(o="up"),d=t()})(),i),"start"),b=a(()=>{o="parked",i=void 0,e.stop(),_(`[gateway] dashboard of '${s}' stopped \u2014 nobody has it open and no service of it runs (it starts on the next request)`)},"park");return e.idleMs===void 0&&A(),{async serve(r){n+=1,d=t(),r.once("close",()=>{n=Math.max(0,n-1),d=t()}),o!=="up"&&await A("a request for it")},tick(){if(D)return;const r=e.servicesUp();if(r&&(d=t()),o==="parked"){r&&A("a service of it is up");return}e.idleMs===void 0||o!=="up"||n>0||r||t()-d>=e.idleMs&&b()},state:a(()=>o,"state"),dispose(){D=!0}}}u(createHostedDashboard,"createHostedDashboard"),c(createHostedDashboard,"createHostedDashboard"),a(createHostedDashboard,"createHostedDashboard");
@@ -1,2 +1,2 @@
1
- "use strict";var x=Object.defineProperty;var a=(t,e)=>x(t,"name",{value:e,configurable:!0});var h=Object.defineProperty,c=a((t,e)=>h(t,"name",{value:e,configurable:!0}),"c");Object.defineProperty(exports,"__esModule",{value:!0}),exports.INSTANCE_NAME_PATTERN=void 0,exports.parseInstanceDecl=parseInstanceDecl,exports.instanceKey=instanceKey,exports.instanceSockNs=instanceSockNs,exports.commonApex=commonApex,exports.rewriteHost=rewriteHost,exports.envSuffix=envSuffix,exports.instanceBuiltinEnv=instanceBuiltinEnv,exports.instanceEnvFile=instanceEnvFile,exports.instanceResourcesEnvFile=instanceResourcesEnvFile,exports.parseInstanceEnv=parseInstanceEnv,exports.instanceEnv=instanceEnv;const tslib_1=require("tslib"),fs=tslib_1.__importStar(require("node:fs")),path=tslib_1.__importStar(require("node:path"));exports.INSTANCE_NAME_PATTERN=/^[a-z0-9](?:[a-z0-9-]{0,18}[a-z0-9])?$/;const HOST_PATTERN=/^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)+$/;function parseInstanceDecl(t){if(!t||typeof t!="object")return;const e=t;if(typeof e.name!="string"||!exports.INSTANCE_NAME_PATTERN.test(e.name)||typeof e.baseKey!="string"||e.baseKey.length===0)return;const n=typeof e.apex=="string"&&HOST_PATTERN.test(e.apex.toLowerCase())?e.apex.toLowerCase():void 0;return{name:e.name,baseKey:e.baseKey,...n?{apex:n}:{},...typeof e.mainRoot=="string"&&e.mainRoot.length>0?{mainRoot:e.mainRoot}:{},...e.frozen===!0?{frozen:!0}:{}}}a(parseInstanceDecl,"parseInstanceDecl"),c(parseInstanceDecl,"parseInstanceDecl");function instanceKey(t,e){return`${t}-${e}`}a(instanceKey,"instanceKey"),c(instanceKey,"instanceKey");function instanceSockNs(t){let e=2166136261;for(let n=0;n<t.length;n++)e^=t.charCodeAt(n),e=Math.imul(e,16777619);return`i-${(e>>>0&16777215).toString(16).padStart(6,"0")}`}a(instanceSockNs,"instanceSockNs"),c(instanceSockNs,"instanceSockNs");function commonApex(t){const e=t.map(s=>s.toLowerCase().replace(/^\*\./,"")).filter(s=>s.length>0).map(s=>s.split(".").reverse());if(e.length===0)return;const n=[];for(let s=0;;s++){const i=e[0]?.[s];if(i===void 0||!e.every(r=>r[s]===i))break;n.push(i)}return n.length>=2?n.reverse().join("."):void 0}a(commonApex,"commonApex"),c(commonApex,"commonApex");function rewriteHost(t,e,n){const s=t.toLowerCase();if(s.startsWith("*.")){const i=rewriteHost(s.slice(2),e,n);return i===void 0?void 0:`*.${i}`}if(s===e)return`${n}.${e}`;if(s.endsWith(`.${e}`))return`${s.slice(0,-e.length)}${n}.${e}`}a(rewriteHost,"rewriteHost"),c(rewriteHost,"rewriteHost");function envSuffix(t){return t.toUpperCase().replace(/[^A-Z0-9]+/g,"_").replace(/^_+|_+$/g,"")}a(envSuffix,"envSuffix"),c(envSuffix,"envSuffix");function instanceBuiltinEnv(t,e){const n={LENSMCP_INSTANCE:t.name,LENSMCP_APEX:t.apex,LENSMCP_BASE_APEX:t.baseApex},s={};for(const[i,r]of Object.entries(e).sort(([o],[l])=>o.localeCompare(l))){const o=envSuffix(i);o&&(r.host&&(n[`LENSMCP_HOST_${o}`]=r.host),r.internalHost&&(n[`LENSMCP_INTERNAL_HOST_${o}`]=r.internalHost),(r.host||r.internalHost)&&(s[i]={...r.host?{host:r.host}:{},...r.internalHost?{internalHost:r.internalHost}:{}}))}return n.LENSMCP_HOSTS_JSON=JSON.stringify(s),n}a(instanceBuiltinEnv,"instanceBuiltinEnv"),c(instanceBuiltinEnv,"instanceBuiltinEnv");function instanceEnvFile(t){return path.join(t,".lensmcp","instance.env")}a(instanceEnvFile,"instanceEnvFile"),c(instanceEnvFile,"instanceEnvFile");function instanceResourcesEnvFile(t){return path.join(t,".lensmcp","instance.resources.env")}a(instanceResourcesEnvFile,"instanceResourcesEnvFile"),c(instanceResourcesEnvFile,"instanceResourcesEnvFile");function parseInstanceEnv(t,e){const n={},s=[],i=c(o=>n[o]??e[o]??"","lookup"),r=c(o=>o.replace(/\$\{([A-Za-z_][A-Za-z0-9_]*)\}/g,(l,u)=>i(u)),"expand");return t.split(/\r?\n/).forEach((o,l)=>{const u=o.trim();if(u===""||u.startsWith("#"))return;const v=/^(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)$/.exec(u);if(!v){s.push(l+1);return}const[,_,p]=v;let E;if(p.startsWith("'")){const f=p.indexOf("'",1);if(f<0){s.push(l+1);return}E=p.slice(1,f)}else if(p.startsWith('"')){const f=p.indexOf('"',1);if(f<0){s.push(l+1);return}E=r(p.slice(1,f).replace(/\\n/g,`
2
- `))}else E=r(p.replace(/\s+#.*$/,"").trim());n[_]=E}),{env:n,skipped:s}}a(parseInstanceEnv,"parseInstanceEnv"),c(parseInstanceEnv,"parseInstanceEnv");function instanceEnv(t,e){let n={...e};for(const s of[instanceResourcesEnvFile(t),instanceEnvFile(t)]){let i;try{i=fs.readFileSync(s,"utf8")}catch{continue}const{env:r,skipped:o}=parseInstanceEnv(i,n);o.length>0&&console.warn(`[gateway] ${s}: skipped malformed line(s) ${o.join(", ")}`),n={...n,...r}}return{...n,...e}}a(instanceEnv,"instanceEnv"),c(instanceEnv,"instanceEnv");
1
+ "use strict";var S=Object.defineProperty;var p=(n,e)=>S(n,"name",{value:e,configurable:!0});var x=Object.defineProperty,a=p((n,e)=>x(n,"name",{value:e,configurable:!0}),"a"),h=Object.defineProperty,c=a((n,e)=>h(n,"name",{value:e,configurable:!0}),"c");Object.defineProperty(exports,"__esModule",{value:!0}),exports.INSTANCE_NAME_PATTERN=void 0,exports.parseInstanceDecl=parseInstanceDecl,exports.instanceKey=instanceKey,exports.instanceSockNs=instanceSockNs,exports.commonApex=commonApex,exports.rewriteHost=rewriteHost,exports.envSuffix=envSuffix,exports.instanceBuiltinEnv=instanceBuiltinEnv,exports.instanceEnvFile=instanceEnvFile,exports.instanceResourcesEnvFile=instanceResourcesEnvFile,exports.parseInstanceEnv=parseInstanceEnv,exports.instanceEnv=instanceEnv;const tslib_1=require("tslib"),fs=tslib_1.__importStar(require("node:fs")),path=tslib_1.__importStar(require("node:path"));exports.INSTANCE_NAME_PATTERN=/^[a-z0-9](?:[a-z0-9-]{0,18}[a-z0-9])?$/;const HOST_PATTERN=/^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)+$/;function parseInstanceDecl(n){if(!n||typeof n!="object")return;const e=n;if(typeof e.name!="string"||!exports.INSTANCE_NAME_PATTERN.test(e.name)||typeof e.baseKey!="string"||e.baseKey.length===0)return;const t=typeof e.apex=="string"&&HOST_PATTERN.test(e.apex.toLowerCase())?e.apex.toLowerCase():void 0;return{name:e.name,baseKey:e.baseKey,...t?{apex:t}:{},...typeof e.mainRoot=="string"&&e.mainRoot.length>0?{mainRoot:e.mainRoot}:{},...e.frozen===!0?{frozen:!0}:{}}}p(parseInstanceDecl,"parseInstanceDecl"),a(parseInstanceDecl,"parseInstanceDecl"),c(parseInstanceDecl,"parseInstanceDecl");function instanceKey(n,e){return`${n}-${e}`}p(instanceKey,"instanceKey"),a(instanceKey,"instanceKey"),c(instanceKey,"instanceKey");function instanceSockNs(n){let e=2166136261;for(let t=0;t<n.length;t++)e^=n.charCodeAt(t),e=Math.imul(e,16777619);return`i-${(e>>>0&16777215).toString(16).padStart(6,"0")}`}p(instanceSockNs,"instanceSockNs"),a(instanceSockNs,"instanceSockNs"),c(instanceSockNs,"instanceSockNs");function commonApex(n){const e=n.map(s=>s.toLowerCase().replace(/^\*\./,"")).filter(s=>s.length>0).map(s=>s.split(".").reverse());if(e.length===0)return;const t=[];for(let s=0;;s++){const o=e[0]?.[s];if(o===void 0||!e.every(r=>r[s]===o))break;t.push(o)}return t.length>=2?t.reverse().join("."):void 0}p(commonApex,"commonApex"),a(commonApex,"commonApex"),c(commonApex,"commonApex");function rewriteHost(n,e,t){const s=n.toLowerCase();if(s.startsWith("*.")){const o=rewriteHost(s.slice(2),e,t);return o===void 0?void 0:`*.${o}`}if(s===e)return`${t}.${e}`;if(s.endsWith(`.${e}`))return`${s.slice(0,-e.length)}${t}.${e}`}p(rewriteHost,"rewriteHost"),a(rewriteHost,"rewriteHost"),c(rewriteHost,"rewriteHost");function envSuffix(n){return n.toUpperCase().replace(/[^A-Z0-9]+/g,"_").replace(/^_+|_+$/g,"")}p(envSuffix,"envSuffix"),a(envSuffix,"envSuffix"),c(envSuffix,"envSuffix");function instanceBuiltinEnv(n,e){const t={LENSMCP_INSTANCE:n.name,LENSMCP_APEX:n.apex,LENSMCP_BASE_APEX:n.baseApex},s={};for(const[o,r]of Object.entries(e).sort(([i],[u])=>i.localeCompare(u))){const i=envSuffix(o);i&&(r.host&&(t[`LENSMCP_HOST_${i}`]=r.host),r.internalHost&&(t[`LENSMCP_INTERNAL_HOST_${i}`]=r.internalHost),(r.host||r.internalHost)&&(s[o]={...r.host?{host:r.host}:{},...r.internalHost?{internalHost:r.internalHost}:{}}))}return t.LENSMCP_HOSTS_JSON=JSON.stringify(s),t}p(instanceBuiltinEnv,"instanceBuiltinEnv"),a(instanceBuiltinEnv,"instanceBuiltinEnv"),c(instanceBuiltinEnv,"instanceBuiltinEnv");function instanceEnvFile(n){return path.join(n,".lensmcp","instance.env")}p(instanceEnvFile,"instanceEnvFile"),a(instanceEnvFile,"instanceEnvFile"),c(instanceEnvFile,"instanceEnvFile");function instanceResourcesEnvFile(n){return path.join(n,".lensmcp","instance.resources.env")}p(instanceResourcesEnvFile,"instanceResourcesEnvFile"),a(instanceResourcesEnvFile,"instanceResourcesEnvFile"),c(instanceResourcesEnvFile,"instanceResourcesEnvFile");function parseInstanceEnv(n,e){const t={},s=[],o=c(i=>t[i]??e[i]??"","lookup"),r=c(i=>i.replace(/\$\{([A-Za-z_][A-Za-z0-9_]*)\}/g,(u,f)=>o(f)),"expand");return n.split(/\r?\n/).forEach((i,u)=>{const f=i.trim();if(f===""||f.startsWith("#"))return;const _=/^(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)$/.exec(f);if(!_){s.push(u+1);return}const[,m,l]=_;let E;if(l.startsWith("'")){const v=l.indexOf("'",1);if(v<0){s.push(u+1);return}E=l.slice(1,v)}else if(l.startsWith('"')){const v=l.indexOf('"',1);if(v<0){s.push(u+1);return}E=r(l.slice(1,v).replace(/\\n/g,`
2
+ `))}else E=r(l.replace(/\s+#.*$/,"").trim());t[m]=E}),{env:t,skipped:s}}p(parseInstanceEnv,"parseInstanceEnv"),a(parseInstanceEnv,"parseInstanceEnv"),c(parseInstanceEnv,"parseInstanceEnv");function instanceEnv(n,e){let t={...e};for(const s of[instanceResourcesEnvFile(n),instanceEnvFile(n)]){let o;try{o=fs.readFileSync(s,"utf8")}catch{continue}const{env:r,skipped:i}=parseInstanceEnv(o,t);i.length>0&&console.warn(`[gateway] ${s}: skipped malformed line(s) ${i.join(", ")}`),t={...t,...r}}return{...t,...e}}p(instanceEnv,"instanceEnv"),a(instanceEnv,"instanceEnv"),c(instanceEnv,"instanceEnv");