@lensmcp/cluster 1.23.8 → 1.23.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/basic-ssl.js +1 -1
- package/build-scope-patterns.js +1 -1
- package/create-webpack-dev.js +1 -1
- package/create-webpack-prod.js +1 -1
- package/error-stack-release.js +1 -1
- package/executors/build/build.impl.js +1 -1
- package/executors/gateway/body-stall.js +1 -1
- package/executors/gateway/canonical-path.js +1 -1
- package/executors/gateway/client-ip.js +1 -1
- package/executors/gateway/gateway-errors.js +1 -1
- package/executors/gateway/gateway.impl.js +1 -1
- package/executors/gateway/gateway.lib.js +1 -1
- package/executors/gateway/health-check.js +1 -1
- package/executors/gateway/jwks-verify.js +1 -1
- package/executors/gateway/jwt-claims.js +1 -1
- package/executors/gateway/main.prod-gateway.js +2 -2
- package/executors/gateway/main.rollout.js +4 -4
- package/executors/gateway/manifest.js +1 -1
- package/executors/gateway/metrics.js +1 -1
- package/executors/gateway/otel-tracing.js +1 -1
- package/executors/gateway/prod-config.js +1 -1
- package/executors/gateway/prod-gateway.lib.js +1 -1
- package/executors/gateway/prod-runtime/access-log.js +1 -1
- package/executors/gateway/prod-runtime/app.js +1 -1
- package/executors/gateway/prod-runtime/auth.js +1 -1
- package/executors/gateway/prod-runtime/body-stall.js +1 -1
- package/executors/gateway/prod-runtime/cors.js +1 -1
- package/executors/gateway/prod-runtime/edge.js +1 -1
- package/executors/gateway/prod-runtime/handler.js +1 -1
- package/executors/gateway/prod-runtime/hooks.js +1 -1
- package/executors/gateway/prod-runtime/observability.js +1 -1
- package/executors/gateway/prod-runtime/rollout.js +1 -1
- package/executors/gateway/prod-runtime/routing.js +1 -1
- package/executors/gateway/prod-runtime/server.js +1 -1
- package/executors/gateway/prod-runtime/trust.js +1 -1
- package/executors/gateway/prod-runtime/upgrade.js +7 -7
- package/executors/gateway/prod-runtime/upstream.js +1 -1
- package/executors/gateway/providers-prod.js +1 -1
- package/executors/gateway/rate-limit.js +2 -2
- package/executors/gateway/registry-source.js +1 -1
- package/executors/gateway/rollout-ops.js +2 -2
- package/executors/gateway/runtime/auth.js +1 -1
- package/executors/gateway/runtime/chooser.js +9 -9
- package/executors/gateway/runtime/control.js +2 -2
- package/executors/gateway/runtime/dev-auth.js +1 -1
- package/executors/gateway/runtime/discovery.js +1 -1
- package/executors/gateway/runtime/edge.js +1 -1
- package/executors/gateway/runtime/handler.js +1 -1
- package/executors/gateway/runtime/hmr-reload.js +1 -1
- package/executors/gateway/runtime/hooks.js +1 -1
- package/executors/gateway/runtime/lens-children.js +1 -1
- package/executors/gateway/runtime/lifecycle.js +3 -3
- package/executors/gateway/runtime/observability.js +2 -2
- package/executors/gateway/runtime/pod-env.js +2 -2
- package/executors/gateway/runtime/pod-output.d.ts +41 -1
- package/executors/gateway/runtime/pod-output.js +1 -1
- package/executors/gateway/runtime/pod-probe.js +1 -1
- package/executors/gateway/runtime/proxy.js +1 -1
- package/executors/gateway/runtime/route-registry.js +1 -1
- package/executors/gateway/runtime/scope.js +1 -1
- package/executors/gateway/runtime/server.js +2 -2
- package/executors/gateway/runtime/service-keys.js +1 -1
- package/executors/gateway/runtime/types.d.ts +4 -0
- package/executors/gateway/runtime/types.js +1 -1
- package/executors/gateway/runtime/upgrade.js +1 -1
- package/executors/gateway/runtime/workspace-log.js +1 -1
- package/executors/gateway/runtime/workspace-registry.js +1 -1
- package/executors/gateway/ssrf-guard.js +1 -1
- package/executors/serve/serve.impl.js +1 -1
- package/executors/trust/hostname.js +1 -1
- package/executors/trust/trust.impl.js +3 -3
- package/exit-reason.js +2 -2
- package/fork-ts-check-reporter.js +1 -1
- package/gateway.js +1 -1
- package/hot-swap-registries.js +1 -1
- package/index.js +1 -1
- package/main.devserver.js +8 -8
- package/package.json +4 -4
- package/process-name.js +1 -1
- package/redis-disconnect-fix.js +1 -1
- package/schema-first-instance.js +1 -1
- package/stdio-guard.js +1 -1
- package/swap-recycle.js +1 -1
- package/tsgo-check-plugin.d.ts +3 -0
- package/tsgo-check-plugin.js +4 -4
- package/typecheck-bus.js +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var u=Object.defineProperty;var d=(r,t)=>u(r,"name",{value:t,configurable:!0});var o=Object.defineProperty,l=d((r,t)=>o(r,"name",{value:t,configurable:!0}),"l"),a=Object.defineProperty,e=l((r,t)=>a(r,"name",{value:t,configurable:!0}),"e");Object.defineProperty(exports,"__esModule",{value:!0}),exports.createBodyStallGuard=void 0;var body_stall_1=require("../body-stall");Object.defineProperty(exports,"createBodyStallGuard",{enumerable:!0,get:e(function(){return body_stall_1.createBodyStallGuard},"get")});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var d=Object.defineProperty;var l=(o,e)=>d(o,"name",{value:e,configurable:!0});var i=Object.defineProperty,n=l((o,e)=>i(o,"name",{value:e,configurable:!0}),"n"),c=Object.defineProperty,t=n((o,e)=>c(o,"name",{value:e,configurable:!0}),"t");Object.defineProperty(exports,"__esModule",{value:!0}),exports.createCors=createCors;const addVaryOrigin=t(o=>{const e=o.getHeader("vary"),a=Array.isArray(e)?e.join(", "):typeof e=="string"?e:"";if(a.trim()==="*")return;const s=a.split(",").map(r=>r.trim()).filter(Boolean);s.some(r=>r.toLowerCase()==="origin")||o.header("vary",[...s,"Origin"].join(", "))},"addVaryOrigin");function createCors(o,e){return{setCors:t((a,s)=>{const r=s.headers.origin;if(r&&o.corsCredentialOrigins.has(r.toLowerCase())){a.header("access-control-allow-origin",r),a.header("access-control-allow-credentials","true"),addVaryOrigin(a);return}a.header("access-control-allow-origin",String(r??"*")),addVaryOrigin(a)},"setCors"),applyResponseCors:t((a,s)=>{const r=a.headers.origin;r&&!s.getHeader("access-control-allow-origin")&&(o.corsCredentialOrigins.has(r.toLowerCase())?(s.header("access-control-allow-origin",r),s.header("access-control-allow-credentials","true"),addVaryOrigin(s)):e.get(a)?.proxied||(s.header("access-control-allow-origin",String(r)),addVaryOrigin(s)))},"applyResponseCors")}}l(createCors,"createCors"),n(createCors,"createCors"),t(createCors,"createCors");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var u=Object.defineProperty;var d=(e,r)=>u(e,"name",{value:r,configurable:!0});var p=Object.defineProperty,i=d((e,r)=>p(e,"name",{value:r,configurable:!0}),"i"),c=Object.defineProperty,t=i((e,r)=>c(e,"name",{value:r,configurable:!0}),"t");Object.defineProperty(exports,"__esModule",{value:!0}),exports.safeUrl=exports.rememberRawTarget=exports.rawTargetOf=exports.RAW_TARGET=exports.canonicalPath=exports.canonicalize=exports.ENCODED_STRUCTURE=exports.addVary=exports.tokenMatches=exports.NO_STORE=exports.sendError=exports.hdr=exports.eid=void 0;const node_crypto_1=require("node:crypto"),gateway_errors_1=require("../gateway-errors"),eid=t(()=>Date.now().toString(36)+(0,node_crypto_1.randomBytes)(6).toString("hex"),"eid");exports.eid=eid;const hdr=t(e=>typeof e=="string"&&e!==""?e:Array.isArray(e)?e[0]:void 0,"hdr");exports.hdr=hdr;const sendError=t((e,r,o,n,s)=>{const a=(0,gateway_errors_1.ensureRequestId)(r);return e.code(o).header("x-request-id",a).header("cache-control",exports.NO_STORE).type(gateway_errors_1.GATEWAY_ERROR_CONTENT_TYPE).send((0,gateway_errors_1.gatewayErrorBody)(o,n,a,s))},"sendError");exports.sendError=sendError,exports.NO_STORE="no-store";const tokenMatches=t((e,r)=>{if(!r)return!1;const o=Buffer.from(e??""),n=Buffer.from(r);return o.length===n.length&&(0,node_crypto_1.timingSafeEqual)(o,n)},"tokenMatches");exports.tokenMatches=tokenMatches;const addVary=t((e,r)=>{const o=e.vary,n=Array.isArray(o)?o.join(", "):typeof o=="string"?o:"";if(n.trim()==="*")return;const s=n.split(",").map(a=>a.trim()).filter(Boolean);s.some(a=>a.toLowerCase()===r.toLowerCase())||(e.vary=[...s,r].join(", "))},"addVary");exports.addVary=addVary;var canonical_path_1=require("../canonical-path");Object.defineProperty(exports,"ENCODED_STRUCTURE",{enumerable:!0,get:t(function(){return canonical_path_1.ENCODED_STRUCTURE},"get")}),Object.defineProperty(exports,"canonicalize",{enumerable:!0,get:t(function(){return canonical_path_1.canonicalize},"get")}),Object.defineProperty(exports,"canonicalPath",{enumerable:!0,get:t(function(){return canonical_path_1.canonicalPath},"get")}),Object.defineProperty(exports,"RAW_TARGET",{enumerable:!0,get:t(function(){return canonical_path_1.RAW_TARGET},"get")}),Object.defineProperty(exports,"rawTargetOf",{enumerable:!0,get:t(function(){return canonical_path_1.rawTargetOf},"get")}),Object.defineProperty(exports,"rememberRawTarget",{enumerable:!0,get:t(function(){return canonical_path_1.rememberRawTarget},"get")});const safeUrl=t(e=>{if(!e)return"(unset)";try{const r=new URL(e);return`${r.protocol}//${r.host}${r.pathname}`}catch{return"(set)"}},"safeUrl");exports.safeUrl=safeUrl;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var Q=Object.defineProperty;var _=(f,o)=>Q(f,"name",{value:o,configurable:!0});var J=Object.defineProperty,H=_((f,o)=>J(f,"name",{value:o,configurable:!0}),"H"),G=Object.defineProperty,v=H((f,o)=>G(f,"name",{value:o,configurable:!0}),"v");Object.defineProperty(exports,"__esModule",{value:!0}),exports.createHandler=createHandler;const manifest_1=require("../manifest"),gateway_errors_1=require("../gateway-errors"),edge_1=require("./edge");function createHandler(f){const{rt:o,obs:d,cors:N,auth:M,upstream:U,rollout:w,hooks:p,reqState:$,spanByReq:D,ctxByReq:V}=f,C=!!o.opts.pods?.resolveVersion,q=!!o.opts.cookie?.secret,j=!!o.opts.pods?.bucket&&(q||!!o.opts.uidHeader),B=C||q||j,F=o.opts.upstreamRetries??1,K=v(u=>(0,edge_1.tokenMatches)(u.query?.token??(0,edge_1.hdr)(u.raw.headers["x-status-token"]),o.opts.statusToken),"statusTokenMatches"),z=v((u,a,e,m,y)=>{const n=u.raw;if(N.setCors(a,n),a.header("cache-control",edge_1.NO_STORE),n.method==="OPTIONS"){a.code(204).header("access-control-allow-methods","GET,POST,PUT,PATCH,DELETE,HEAD,OPTIONS").header("access-control-allow-headers",String(n.headers["access-control-request-headers"]??"*")).send();return}const s=o.table.routes.filter(i=>i.host&&(0,manifest_1.hostMatches)(i.host,e)&&i.prefix),h=y;if(s.length>0&&(h==="/health"||h==="/healthz")){a.code(200).type("application/json").send(JSON.stringify({status:"ok",host:e,services:s.map(i=>({service:i.service,prefix:i.prefix}))}));return}if(h==="/.well-known/lensmcp-routes"){if(!K(u)){(0,edge_1.sendError)(a,n,404,"not_found","No gateway route for this hostname.");return}a.code(200).type("application/json").send(JSON.stringify({host:e,routes:o.table.routes.filter(i=>!i.host||(0,manifest_1.hostMatches)(i.host,e)).map(i=>({host:i.host??"(default)",service:i.service,prefix:i.prefix,internal:!!i.internal,auth:i.auth}))}));return}(0,edge_1.sendError)(a,n,404,"not_found",s.length>0?`No service mounted at ${m} on ${e}.`:"No gateway route for this hostname.")},"handleNoRoute");return async(u,a)=>{const e=u.raw,m=(e.headers.host||"").split(":")[0],y=e.url??"/",n=d.beginTrace(e);(0,gateway_errors_1.ensureRequestId)(e),d.step(n,"received",{host:m,method:e.method,url:y});const s=p.any?p.httpContext(e,u,a,n):void 0;if(s&&V.set(u,s),s&&p.has("onRequest")&&(await p.run("onRequest",s),s.responded()))return a;if(e.httpVersionMajor<1)return d.finish(n,"gateway",400),(0,edge_1.sendError)(a,e,400,"bad_request","Bad Request");const h=(0,edge_1.canonicalize)(y);if(h===void 0)return d.step(n,"bad-path",{}),d.finish(n,"gateway",400),(0,edge_1.sendError)(a,e,400,"bad_request","Bad Request");const i=h.policy,b=h.path+h.query;b!==y&&(0,edge_1.rememberRawTarget)(e,y),e.url=b;const I=e.socket?.remoteAddress??u.ip,T=w.clientIpOf(e,I);if(o.opts.rateLimiter){const r=await o.opts.rateLimiter.check(T);if(!r.allowed)return a.header("retry-after",String(Math.ceil(r.retryAfterMs/1e3))),d.step(n,"rate-limited",{}),d.finish(n,"gateway",429),(0,edge_1.sendError)(a,e,429,"rate_limited","Too Many Requests")}const t=(0,manifest_1.matchRoute)(o.table.routes,m,i+h.query);if(!t)return z(u,a,m,b,i),a;if(s&&(s.route=t),d.step(n,"route-match",{project:t.service,...t.prefix?{prefix:t.prefix}:{},...t.internal?{internal:!0}:{}}),e.method==="OPTIONS")return N.setCors(a,e),a.code(204).header("access-control-allow-methods","GET,POST,PUT,PATCH,DELETE,HEAD,OPTIONS").header("access-control-allow-headers",String(e.headers["access-control-request-headers"]??"*")).send(),a;const k=o.opts.tracing?.startSpan(e,`gateway ${t.service}`,{"http.request.method":e.method??"GET","url.path":b.split("?")[0],"server.address":m,"lensmcp.service":t.service,...t.internal?{"lensmcp.internal":!0}:{}});if(k&&D.set(u,k),s&&p.has("beforeAuth")&&(await p.run("beforeAuth",s),s.responded()))return a;const O=t.internal?void 0:o.opts.identify?.(e);let S;if(t.internal){const r=M.internal(e,t,n);if(!r.ok)return d.finish(n,t.service,r.status),(0,edge_1.sendError)(a,e,r.status,r.reason,r.detail);S=r.caller,s&&(s.caller=S)}else{const r=M.public(e,t,i,O,T,n);if(!r.ok)return d.finish(n,t.service,r.status),(0,edge_1.sendError)(a,e,r.status,r.reason,r.detail);if(s&&(s.claims=O),s&&p.has("afterAuth")&&(await p.run("afterAuth",s),s.responded()))return a}if(e.headers["x-forwarded-for"]=w.forwardedFor(e,I),e.headers["x-forwarded-proto"]=o.opts.tls?"https":"http",e.headers["x-forwarded-host"]=e.headers.host??m,o.opts.serviceKeys?.[t.service]&&(e.headers["x-internal-token"]=o.opts.serviceKeys[t.service]),t.prependPrefix){const r=e.url??"/",c=t.prependPrefix;r!==c&&!r.startsWith(c+"/")&&(e.url=c+r)}const x=(0,edge_1.hdr)(e.headers[o.versionHeader]);let P=x,R=!1,E;if(B&&!t.internal&&!x){const r=w.resolveStickyKey(e);r.mint&&(E=r.key);const c=C?o.opts.pods.resolveVersion(t.service,w.buildAttrs(e,T,O,r.key)):void 0;if(c)P=c.version,R=!0,d.step(n,"targeting",{rule:c.rule,version:c.version});else if(r.key){const g=o.opts.pods?.bucket?.(t.service,r.key);g&&(P=g.version,R=!0,d.step(n,"targeting",{mode:"sticky",version:g.version}))}}const l=await U.resolveUpstream(t,n,P,R);if(!l)return d.finish(n,t.service,503),(0,edge_1.sendError)(a,e,503,"unavailable",`Service ${t.service} has no available upstream.`);if(!("url"in l))return d.finish(n,t.service,502),(0,edge_1.sendError)(a,e,502,"unavailable",`Service ${t.service}: socket upstreams are not supported by the prod gateway.`);const W=new URL(l.url).origin,A=l.url,L={route:t,caller:S,startedAt:Date.now(),trace:n,version:l.version,upLabel:A};return $.set(u,L),s&&(s.version=l.version),d.step(n,l.version?"rollout":"upstream",{upstream:A,...l.version?{version:l.version,...x?{pinned:!0}:{}}:{}}),k&&o.opts.tracing.inject(k,e.headers),s&&p.has("beforeForward")&&(await p.run("beforeForward",s),s.responded())?a:a.from(void 0,{getUpstream:v(()=>W,"getUpstream"),retriesCount:F,rewriteHeaders:v(r=>{if(L.proxied=!0,n&&(r["x-lensmcp-upstream"]=A),r["x-request-id"]||(r["x-request-id"]=(0,gateway_errors_1.ensureRequestId)(e)),l.version&&(r["x-lensmcp-version"]=l.version),(x||l.version)&&(0,edge_1.addVary)(r,o.versionHeader),(E||j&&q)&&(0,edge_1.addVary)(r,"Cookie"),delete r["x-powered-by"],delete r.connection,delete r["keep-alive"],delete r["proxy-connection"],r.server="LensMCP",E){const c=r["set-cookie"],g=Array.isArray(c)?c:c?[c]:[];r["set-cookie"]=[...g,w.mintCookieHeader(E)]}return r},"rewriteHeaders"),onError:v((r,{error:c})=>{o.opts.pods?.drop?.(t.service,l),s&&p.has("onError")&&(s.error=c,p.run("onError",s)),(0,edge_1.sendError)(r,e,502,"unavailable",`Upstream ${t.service} unavailable.`)},"onError")})}}_(createHandler,"createHandler"),H(createHandler,"createHandler"),v(createHandler,"createHandler");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var y=Object.defineProperty;var u=(o,s)=>y(o,"name",{value:s,configurable:!0});var f=Object.defineProperty,i=u((o,s)=>f(o,"name",{value:s,configurable:!0}),"i"),l=Object.defineProperty,n=i((o,s)=>l(o,"name",{value:s,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){const s=n(async(e,t)=>{const r=o[e];if(!r||r.length===0)return;const d=TERMINAL_PHASES.has(e);for(const a of r){if(!d&&t.responded())return;await a(t)}},"run"),c=n(e=>(o[e]?.length??0)>0,"has");return{any:["onRequest","beforeAuth","afterAuth","beforeForward","onResponse","onError","onUpgrade"].some(e=>c(e)),run:s,has:c,httpContext:n((e,t,r,d)=>{let a=!1;return{req:e,request:t,reply:r,socket:void 0,trace:d,route:void 0,caller:void 0,claims:void 0,version:void 0,error:void 0,status:void 0,sendError:n((v,p,h)=>{(0,edge_1.sendError)(r,e,v,p,h),a=!0},"sendError"),responded:n(()=>a||r.raw.writableEnded,"responded")}},"httpContext"),upgradeContext:n((e,t,r)=>{let d=!1;return{req:e,request:void 0,reply:void 0,socket:t,trace:r,route:void 0,caller:void 0,claims:void 0,version:void 0,error:void 0,status:void 0,sendError:n(()=>{try{t.destroy()}catch{}d=!0},"sendError"),responded:n(()=>d||t.destroyed,"responded")}},"upgradeContext")}}u(createHooks,"createHooks"),i(createHooks,"createHooks"),n(createHooks,"createHooks");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var I=Object.defineProperty;var w=(o,u)=>I(o,"name",{value:u,configurable:!0});var b=Object.defineProperty,p=w((o,u)=>b(o,"name",{value:u,configurable:!0}),"p"),y=Object.defineProperty,c=p((o,u)=>y(o,"name",{value:u,configurable:!0}),"c");Object.defineProperty(exports,"__esModule",{value:!0}),exports.createObservability=createObservability;const redact_1=require("@lensmcp/core/redact"),edge_1=require("./edge");function createObservability(o,u){const v=c((e,t,s,r,a)=>{if(o.emit)try{o.emit({id:(0,edge_1.eid)(),sessionId:"pending",timestamp:Date.now(),source:"gateway",category:"cluster",severity:e,context:(0,redact_1.redactDeep)({sessionId:"pending",...a}),fingerprint:s,title:(0,redact_1.safeTitle)(t),raw:r&&(0,redact_1.redactDeep)(r)})}catch{}},"emit"),h=new Map,q=c((e,t,s,r,a)=>{const n=e.host??"(default)",d=(r?r+"\u21D2":"")+n+"\u2192"+e.service+(a?"@"+a:""),i=h.get(d)??{host:n,service:e.service,caller:r,version:a,count:0,totalMs:0,errors:0};i.count+=1,i.totalMs+=t,(s>=500||s===0)&&(i.errors+=1),h.set(d,i)},"recordEdge"),M=Math.max(1,o.statusWindows??12),f=[],g=new Map,S=c(()=>[...new Set(u().map(e=>e.service))],"routeServices"),$=c(()=>{const e=new Map;for(const s of h.values()){const r=e.get(s.service)??{requests:0,errors:0,totalMs:0,versions:new Set};r.requests+=s.count,r.errors+=s.errors,r.totalMs+=s.totalMs,s.version&&r.versions.add(s.version),e.set(s.service,r)}const t=Date.now();for(const[s,r]of e)r.requests>0&&g.set(s,t);for(f.push(e);f.length>M;)f.shift()},"pushStatusWindow"),m=c(()=>{const e=new Map;for(const s of f)for(const[r,a]of s){const n=e.get(r)??{requests:0,errors:0,totalMs:0,versions:new Set};n.requests+=a.requests,n.errors+=a.errors,n.totalMs+=a.totalMs;for(const d of a.versions)n.versions.add(d);e.set(r,n)}const t=u();return S().map(s=>{const r=e.get(s)??{requests:0,errors:0,totalMs:0,versions:new Set},a=[...new Set(t.filter(i=>i.service===s).map(i=>i.host??"(default)"))],n=r.requests?r.errors/r.requests:0;let d=r.requests===0?"idle":n>=.5?"down":n>=.05?"degraded":"healthy";if(o.healthChecker){const i=t.filter(l=>l.service===s&&l.upstream).map(l=>l.upstream);i.length&&i.every(l=>!o.healthChecker.isHealthy(l))&&(d="down")}return{service:s,hosts:a,status:d,requests:r.requests,errorRate:+n.toFixed(4),avgMs:r.requests?Math.round(r.totalMs/r.requests):0,versions:[...r.versions],lastSeen:g.get(s)??null}})},"buildStatusSnapshot");return{emit:v,beginTrace:c(e=>{if(!o.emit)return;const t=(0,edge_1.hdr)(e.headers["x-lensmcp-flow-id"]);let s=(0,edge_1.hdr)(e.headers["x-request-id"]);if(!(!t&&!s&&!(0,edge_1.hdr)(e.headers.traceparent)))return s||(s=(0,edge_1.eid)(),e.headers["x-request-id"]=s),{startedAt:Date.now(),method:(e.method??"GET").toUpperCase(),host:(e.headers.host||"").split(":")[0],url:e.url??"/",steps:[],...t?{flowId:t}:{},...s?{requestId:s}:{}}},"beginTrace"),step:c((e,t,s)=>{e&&e.steps.push({step:t,atMs:Date.now()-e.startedAt,...s})},"step"),finish:c((e,t,s,r)=>{!e||e.done||(e.done=!0,v(s>=500?"error":"info",`gateway ${e.method} ${e.host}${e.url} \u2192 ${s} (${Date.now()-e.startedAt}ms)`,`gateway-request:${t}`,{kind:"gateway-request",project:t,host:e.host,method:e.method,url:e.url,status:s,durationMs:Date.now()-e.startedAt,startedAt:e.startedAt,steps:e.steps,...r},{...e.flowId?{flowId:e.flowId}:{},...e.requestId?{requestId:e.requestId}:{}}))},"finish"),recordEdge:q,buildStatusSnapshot:m,startFlusher:c(()=>{const e=setInterval(()=>{if($(),o.onStatus)try{o.onStatus(m())}catch{}if(o.emit)for(const t of h.values())v(t.errors?"warning":"info",`traffic ${t.host} \u2192 ${t.service}${t.version?"@"+t.version:""}: ${t.count} req`,`gateway-traffic:${t.host}->${t.service}${t.version?"@"+t.version:""}`,{kind:"gateway-traffic",host:t.host,project:t.service,caller:t.caller,version:t.version,count:t.count,avgMs:Math.round(t.totalMs/t.count),errors:t.errors});h.clear()},o.trafficFlushMs??5e3);return e.unref?.(),e},"startFlusher")}}w(createObservability,"createObservability"),p(createObservability,"createObservability"),c(createObservability,"createObservability");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var P=Object.defineProperty;var l=(t,s)=>P(t,"name",{value:s,configurable:!0});var b=Object.defineProperty,d=l((t,s)=>b(t,"name",{value:s,configurable:!0}),"d"),H=Object.defineProperty,c=d((t,s)=>H(t,"name",{value:s,configurable:!0}),"c");Object.defineProperty(exports,"__esModule",{value:!0}),exports.createRollout=createRollout;const node_crypto_1=require("node:crypto"),client_ip_1=require("../client-ip"),edge_1=require("./edge");function createRollout(t){const s=(0,client_ip_1.createClientIpResolver)({...t.clientIpHeader?{clientIpHeader:t.clientIpHeader}:{},...t.clientIpTrustedProxies?{clientIpTrustedProxies:t.clientIpTrustedProxies}:{},trustProxyHops:t.trustProxyIp?Math.max(1,Math.floor(t.trustProxyHops??1)):0}),g=s.clientIpOf,I=s.forwardedFor,v=(t.attributeHeaders??[]).map(e=>e.toLowerCase()),u=t.uidHeader?.toLowerCase(),a=t.cookie?.secret,p=!!t.cookie&&!!a,f=t.cookie?.name??"lensmcp_did",m=t.cookie?.domain,x=t.cookie?.maxAge??31536e3;t.cookie&&!a&&console.warn("[gateway] device cookie has NO secret \u2014 sticky cookie bucketing is DISABLED (set cookie.secret / LENSMCP_GW_COOKIE_SECRET to enable it). An unsigned cookie is attacker-choosable.");const k=c(e=>(0,node_crypto_1.createHmac)("sha256",a).update(e).digest("base64url"),"signId"),C=c(e=>`${e}.${k(e)}`,"signedCookie"),_=c(e=>{if(!a)return;const r=e.lastIndexOf(".");if(r<0)return;const o=e.slice(0,r),n=Buffer.from(e.slice(r+1)),i=Buffer.from(k(o));return n.length===i.length&&(0,node_crypto_1.timingSafeEqual)(n,i)?o:void 0},"verifyCookie"),O=c((e,r)=>{if(e)for(const o of e.split(";")){const n=o.indexOf("=");if(n>0&&o.slice(0,n).trim()===r){const i=o.slice(n+1).trim();try{return decodeURIComponent(i)}catch{return}}}},"parseCookie");return{clientIpOf:g,forwardedFor:I,buildAttrs:c((e,r,o,n)=>{const i={...o??{}};i.ip=r,i.method=(e.method??"GET").toUpperCase(),i.path=(e.url??"/").split("?")[0],n&&(i.device=n);for(const y of v){const h=(0,edge_1.hdr)(e.headers[y]);h!==void 0&&(i["header."+y]=h)}return i},"buildAttrs"),resolveStickyKey:c(e=>{if(p){const r=O(e.headers.cookie,f),o=r?_(r):void 0;if(o)return{key:o,mint:!1}}if(u){const r=(0,edge_1.hdr)(e.headers[u]);if(r)return{key:r,mint:!1}}return p?{key:"d_"+(0,node_crypto_1.randomBytes)(12).toString("base64url"),mint:!0}:{mint:!1}},"resolveStickyKey"),mintCookieHeader:c(e=>{let r=`${f}=${encodeURIComponent(C(e))}; Path=/; Max-Age=${x}; HttpOnly; SameSite=Lax; Secure`;return m&&(r+=`; Domain=${m}`),r},"mintCookieHeader")}}l(createRollout,"createRollout"),d(createRollout,"createRollout"),c(createRollout,"createRollout");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var v=Object.defineProperty;var u=(e,a)=>v(e,"name",{value:a,configurable:!0});var m=Object.defineProperty,i=u((e,a)=>m(e,"name",{value:a,configurable:!0}),"i"),d=Object.defineProperty,r=i((e,a)=>d(e,"name",{value:a,configurable:!0}),"r");Object.defineProperty(exports,"__esModule",{value:!0}),exports.createRouteTable=createRouteTable;const manifest_1=require("../manifest");function createRouteTable(e,a){const n=[],c=new Map;let o=e.manifests.list();const l=r(t=>{o=t;const s=(0,manifest_1.buildRouteTable)(t);n.length=0,n.push(...s),c.clear();for(const h of t)c.set(h.service,h)},"apply"),f=r(()=>{if(!e.healthChecker)return;const t=new Set;for(const s of n)s.upstream&&t.add(s.upstream);for(const s of e.pods?.endpoints?.()??[])t.add(s);e.healthChecker.track([...t])},"trackUpstreams"),p=r(t=>{l(t),f(),a.emit("info",`gateway routes: ${n.length} on ${o.length} services`,"gateway-up",{kind:"gateway-up",routes:n.map(s=>({host:s.host??"(default)",service:s.service,internal:!!s.internal}))})},"rebuild");l(o);const b=e.manifests.watch?.(t=>p(t));return{routes:n,manifestByService:c,rebuild:p,trackUpstreams:f,manifests:r(()=>o,"manifests"),stop:r(()=>b?.(),"stop")}}u(createRouteTable,"createRouteTable"),i(createRouteTable,"createRouteTable"),r(createRouteTable,"createRouteTable");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var G=Object.defineProperty;var d=(e,a)=>G(e,"name",{value:a,configurable:!0});var A=Object.defineProperty,h=d((e,a)=>A(e,"name",{value:a,configurable:!0}),"h"),R=Object.defineProperty,n=h((e,a)=>R(e,"name",{value:a,configurable:!0}),"n");Object.defineProperty(exports,"__esModule",{value:!0}),exports.startProdGateway=startProdGateway;const observability_1=require("./observability"),routing_1=require("./routing"),rollout_1=require("./rollout"),upstream_1=require("./upstream"),auth_1=require("./auth"),hooks_1=require("./hooks"),cors_1=require("./cors"),handler_1=require("./handler"),upgrade_1=require("./upgrade"),app_1=require("./app");async function startProdGateway(e){const a=e.ports?.length?e.ports:[e.tls?8443:8080],j=e.authenticate??(t=>{if(t==="jwt")throw new Error("jwt route but no authenticator configured")}),C=(e.versionHeader??"x-lensmcp-version").toLowerCase(),O=!!e.accessLog,L=new Set((e.corsCredentialOrigins??[]).map(t=>t.toLowerCase())),w=new Map;for(const[t,s]of Object.entries(e.serviceKeys??{}))typeof s=="string"&&s.trim()!==""?w.set(s,t):console.warn(`[gateway] service key for "${t}" is empty \u2014 east-west auth for that service is DISABLED (all internal routes 401) until a key is set.`);const y={},r=(0,observability_1.createObservability)(e,()=>y.current.routes),o=(0,routing_1.createRouteTable)(e,r);y.current=o;const i={opts:e,table:o,keyToProject:w,versionHeader:C,accessLog:O,corsCredentialOrigins:L},u=(0,rollout_1.createRollout)(e),g=(0,upstream_1.createUpstream)(e,r),b=(0,auth_1.createEdgeAuth)(i,r,u,j),c=(0,hooks_1.createHooks)(e.hooks??{}),p=new WeakMap,f=new WeakMap,m=new WeakMap,k=(0,cors_1.createCors)(i,p),S=(0,handler_1.createHandler)({rt:i,obs:r,cors:k,auth:b,upstream:g,rollout:u,hooks:c,reqState:p,spanByReq:f,ctxByReq:m}),x=(0,upgrade_1.createUpgrade)({rt:i,obs:r,auth:b,upstream:g,hooks:c,rollout:u}),{buildApp:M}=(0,app_1.createApp)({rt:i,obs:r,cors:k,hooks:c,handler:S,upgrade:x,reqState:p,spanByReq:f,ctxByReq:m}),B=r.startFlusher();o.rebuild(o.manifests());const v=[],q=[];for(const t of a){const s=await M();await s.listen({port:t,host:"0.0.0.0"});const l=s.server.address(),P=typeof l=="object"&&l?l.port:t;q.push(P),console.log(`[gateway] listening on ${e.tls?"https":"http"}://0.0.0.0:${P}`),v.push(s)}e.healthChecker?.start();let _=!1;return{ports:q,routes:n(()=>o.routes,"routes"),status:r.buildStatusSnapshot,refreshUpstreams:o.trackUpstreams,stop:n(async()=>{_||(_=!0,clearInterval(B),o.stop(),e.healthChecker?.stop(),e.rateLimiter?.stop(),e.metrics?.stop(),r.emit("info","gateway down","gateway-down",{kind:"gateway-down"}),await Promise.all(v.map(t=>t.close())))},"stop")}}d(startProdGateway,"startProdGateway"),h(startProdGateway,"startProdGateway"),n(startProdGateway,"startProdGateway");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var c=Object.defineProperty;var a=(t,e)=>c(t,"name",{value:e,configurable:!0});var d=Object.defineProperty,p=a((t,e)=>d(t,"name",{value:e,configurable:!0}),"p"),x=Object.defineProperty,r=p((t,e)=>x(t,"name",{value:e,configurable:!0}),"r");Object.defineProperty(exports,"__esModule",{value:!0}),exports.stampIdentity=exports.stripTrust=exports.HOP_BY_HOP=exports.TRUST_HEADERS=void 0,exports.TRUST_HEADERS=["x-internal-token","x-api-key-id","x-user-id","x-tenant-id","x-user-roles","x-user-permissions"],exports.HOP_BY_HOP=["connection","proxy-connection","keep-alive"];const stripTrust=r(t=>{for(const e of exports.TRUST_HEADERS)delete t.headers[e];for(const e of exports.HOP_BY_HOP)delete t.headers[e]},"stripTrust");exports.stripTrust=stripTrust;const stampIdentity=r((t,e)=>{const i=r((u,s)=>{(typeof s=="string"&&s!==""||typeof s=="number")&&(t.headers[u]=String(s))},"set");i("x-user-id",e.sub),i("x-tenant-id",e.tid);const o=e.roles;Array.isArray(o)&&o.length&&(t.headers["x-user-roles"]=o.map(String).join(","));const n=e.perms;Array.isArray(n)&&n.length&&(t.headers["x-user-permissions"]=n.map(String).join(","))},"stampIdentity");exports.stampIdentity=stampIdentity;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
"use strict";var
|
|
2
|
-
${
|
|
1
|
+
"use strict";var G=Object.defineProperty;var S=(d,n)=>G(d,"name",{value:n,configurable:!0});var V=Object.defineProperty,A=S((d,n)=>V(d,"name",{value:n,configurable:!0}),"A"),F=Object.defineProperty,u=A((d,n)=>F(d,"name",{value:n,configurable:!0}),"u");Object.defineProperty(exports,"__esModule",{value:!0}),exports.createUpgrade=createUpgrade;const tslib_1=require("tslib"),net=tslib_1.__importStar(require("node:net")),tls=tslib_1.__importStar(require("node:tls")),manifest_1=require("../manifest"),edge_1=require("./edge"),trust_1=require("./trust"),validHeaderValue=u(d=>/^[\t\x20-\x7e\x80-\xff]*$/.test(d),"validHeaderValue"),validToken=u(d=>/^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/.test(d),"validToken"),FORWARDED_HEADERS=["x-forwarded-for","x-forwarded-proto","x-forwarded-host"],MAX_HEAD_BYTES=64*1024,HANDSHAKE_TIMEOUT_MS=3e4;function createUpgrade(d){const{rt:n,obs:h,auth:U,upstream:I,hooks:y,rollout:E}=d,l=u((e,t,s,p)=>{h.emit("warning",`gateway upgrade rejected (${t})${s?` for ${s}`:""}`,`gateway-upgrade:${s??"(none)"}:${t}`,{kind:"gateway-upgrade-rejected",reason:t,...s?{project:s}:{},...p}),e.destroy()},"reject"),K=u((e,t,s="")=>{try{e.end(`HTTP/1.1 ${t}\r
|
|
2
|
+
${s}Connection: close\r
|
|
3
3
|
Content-Length: 0\r
|
|
4
4
|
\r
|
|
5
|
-
`)}catch{e.destroy()}},"refuse"),
|
|
6
|
-
`);return}}const
|
|
5
|
+
`)}catch{e.destroy()}},"refuse"),N=u(async(e,t,s)=>{(0,trust_1.stripTrust)(e);const p=(e.headers.host||"").split(":")[0],v=(0,edge_1.canonicalize)(e.url??"/");if(v===void 0){l(t,"bad-path");return}const R=v.policy;e.url=v.path+v.query;const r=(0,manifest_1.matchRoute)(n.table.routes,p,R+v.query);if(!r){l(t,"no-route",void 0,{host:p});return}const q=e.socket?.remoteAddress??"",P=E.clientIpOf(e,q);if(n.opts.rateLimiter){const a=await n.opts.rateLimiter.check(P);if(!a.allowed){h.emit("warning",`gateway upgrade rate-limited for ${r.service}`,`gateway-upgrade:${r.service}:rate-limited`,{kind:"gateway-upgrade-rejected",reason:"rate-limited",project:r.service}),K(t,"429 Too Many Requests",`Retry-After: ${Math.ceil(a.retryAfterMs/1e3)}\r
|
|
6
|
+
`);return}}const i=y.any?y.upgradeContext(e,t,void 0):void 0;i&&(i.route=r);const O=r.internal?void 0:n.opts.identify?.(e);let T;if(r.internal){const a=U.internal(e,r,void 0);if(!a.ok){l(t,"auth-failed",r.service);return}T=a.caller,i&&(i.caller=T)}else{if(!U.public(e,r,R,O,P,void 0).ok){l(t,"auth-failed",r.service);return}if(i&&(i.claims=O),i&&y.has("afterAuth")&&(await y.run("afterAuth",i),i.responded()))return}if(e.headers["x-forwarded-for"]=E.forwardedFor(e,q),e.headers["x-forwarded-proto"]=n.opts.tls?"https":"http",e.headers["x-forwarded-host"]=e.headers.host??p,n.opts.serviceKeys?.[r.service]&&(e.headers["x-internal-token"]=n.opts.serviceKeys[r.service]),r.prependPrefix){const a=e.url??"/",o=r.prependPrefix;a!==o&&!a.startsWith(o+"/")&&(e.url=o+a)}if(i&&y.has("onUpgrade")&&(await y.run("onUpgrade",i),i.responded()))return;const B=(0,edge_1.hdr)(e.headers[n.versionHeader]),x=await I.resolveUpstream(r,void 0,B);if(!x||!("url"in x)){l(t,"no-upstream",r.service);return}const f=new URL(x.url),W=new Set([...trust_1.TRUST_HEADERS,"x-api-key","connection","proxy-connection","keep-alive",...FORWARDED_HEADERS]),C=e.method??"GET",b=e.url??"/";if(!validToken(C)||!validHeaderValue(b)||b.includes(" ")){l(t,"bad-request-line",r.service);return}const k=[`${C} ${b} HTTP/1.1`,"Connection: Upgrade"];for(let a=0;a<e.rawHeaders.length;a+=2){const o=e.rawHeaders[a],$=e.rawHeaders[a+1]??"";if(!W.has(o.toLowerCase())){if(!validToken(o)||!validHeaderValue($)){l(t,"bad-header",r.service,{header:o.toLowerCase()});return}k.push(`${o}: ${$}`)}}for(const a of[...trust_1.TRUST_HEADERS,...FORWARDED_HEADERS]){const o=e.headers[a];if(!(typeof o!="string"||o==="")){if(!validHeaderValue(o)){l(t,"bad-identity-value",r.service,{header:a});return}k.push(`${a}: ${o}`)}}const _=f.protocol==="https:"||f.protocol==="wss:",D=Number(f.port)||(_?443:80),g=n.opts.undici,c=_?tls.connect({port:D,host:f.hostname,...net.isIP(f.hostname)?{}:{servername:f.hostname},rejectUnauthorized:g?.rejectUnauthorized??!1,...g?.cert?{cert:g.cert}:{},...g?.key?{key:g.key}:{},...g?.ca?{ca:g.ca}:{}}):net.connect(D,f.hostname);let m=!1;const w=u(a=>{m||(m=!0,clearTimeout(j),h.emit("warning",`gateway upgrade failed (${a}) for ${r.service}`,`gateway-upgrade:${r.service}:${a}`,{kind:"gateway-upgrade-rejected",reason:a,project:r.service}),c.destroy(),t.destroy())},"abort"),j=setTimeout(()=>w("handshake-timeout"),HANDSHAKE_TIMEOUT_MS);j.unref?.(),c.on("error",()=>w("upstream-error")),t.on("error",()=>w("client-error")),c.on(_?"secureConnect":"connect",()=>{c.write(k.join(`\r
|
|
7
7
|
`)+`\r
|
|
8
8
|
\r
|
|
9
|
-
`),
|
|
9
|
+
`),s?.length&&c.write(s)});const M=[];let L=0;const z=u(a=>{if(m)return;M.push(a),L+=a.length;const o=Buffer.concat(M),$=o.indexOf(`\r
|
|
10
10
|
\r
|
|
11
|
-
`);if($===-1){
|
|
12
|
-
`)).toString("latin1"))?.[1]);if(H!==101){
|
|
11
|
+
`);if($===-1){L>MAX_HEAD_BYTES&&w("oversized-response-head");return}m=!0,clearTimeout(j),c.off("data",z);const H=Number(/^HTTP\/1\.[01] (\d{3})/.exec(o.subarray(0,o.indexOf(`\r
|
|
12
|
+
`)).toString("latin1"))?.[1]);if(H!==101){h.emit("warning",`gateway upgrade refused upstream (${H||"malformed"}) for ${r.service}`,`gateway-upgrade:${r.service}:upstream-refused`,{kind:"gateway-upgrade-rejected",reason:"upstream-refused",project:r.service,status:H||0}),t.end(o.subarray(0,$+4)),c.destroy();return}h.recordEdge(r,0,101,T,x.version),t.write(o),c.pipe(t),t.pipe(c)},"onHead");c.on("data",z),c.on("close",()=>{m||w("upstream-closed")})},"run");return(e,t,s)=>{N(e,t,s).catch(p=>{h.emit("error",`gateway upgrade error: ${p?.message??String(p)}`,"gateway-upgrade:(none):exception",{kind:"gateway-upgrade-rejected",reason:"exception",error:p?.message??String(p)});try{t.destroy()}catch{}})}}S(createUpgrade,"createUpgrade"),A(createUpgrade,"createUpgrade"),u(createUpgrade,"createUpgrade");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var d=Object.defineProperty;var c=(e,r)=>d(e,"name",{value:r,configurable:!0});var v=Object.defineProperty,p=c((e,r)=>v(e,"name",{value:r,configurable:!0}),"p"),u=Object.defineProperty,s=p((e,r)=>u(e,"name",{value:r,configurable:!0}),"s");Object.defineProperty(exports,"__esModule",{value:!0}),exports.createUpstream=createUpstream;function createUpstream(e,r){return{resolveUpstream:s(async(t,o,i,l)=>{if(t.upstream)return{url:t.upstream};const n={...i?{version:i}:{},...l?{allowDrained:!0}:{},...e.healthChecker?{isHealthy:s(m=>e.healthChecker.isHealthy(m),"isHealthy")}:{}};let a=e.pods?.pick(t.service,n);return!a&&e.pods?.ensureUp&&(r.step(o,"ensure-up",{project:t.service}),await e.pods.ensureUp(t.service)&&(a=e.pods.pick(t.service,n))),a},"resolveUpstream")}}c(createUpstream,"createUpstream"),p(createUpstream,"createUpstream"),s(createUpstream,"createUpstream");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var U=Object.defineProperty;var w=(r,o)=>U(r,"name",{value:o,configurable:!0});var V=Object.defineProperty,g=w((r,o)=>V(r,"name",{value:o,configurable:!0}),"g"),P=Object.defineProperty,n=g((r,o)=>P(r,"name",{value:o,configurable:!0}),"n");Object.defineProperty(exports,"__esModule",{value:!0}),exports.isRolloutShape=void 0,exports.staticManifestProvider=staticManifestProvider,exports.fileManifestProvider=fileManifestProvider,exports.rolloutPodProvider=rolloutPodProvider,exports.endpointsPodProvider=endpointsPodProvider;const node_fs_1=require("node:fs"),manifest_1=require("./manifest"),FLAT="_flat",isCohortList=n(r=>Array.isArray(r)&&r.every(o=>!!o&&typeof o=="object"&&Array.isArray(o.urls)),"isCohortList"),isUrlList=n(r=>Array.isArray(r)&&r.every(o=>typeof o=="string"),"isUrlList"),isSpec=n(r=>!!r&&typeof r=="object"&&!Array.isArray(r)&&isCohortList(r.cohorts),"isSpec"),isRolloutShape=n(r=>Object.values(r).some(o=>isSpec(o)||isCohortList(o)&&o.length>0),"isRolloutShape");exports.isRolloutShape=isRolloutShape;const isValidEntry=n(r=>isSpec(r)||isCohortList(r)||isUrlList(r),"isValidEntry"),toSpec=n(r=>Array.isArray(r)?isUrlList(r)?{rules:[],cohorts:[{version:FLAT,weight:1,urls:r}]}:{rules:[],cohorts:r}:{rules:r.rules??[],cohorts:r.cohorts??[]},"toSpec");function staticManifestProvider(r){return{list:n(()=>r,"list")}}w(staticManifestProvider,"staticManifestProvider"),g(staticManifestProvider,"staticManifestProvider"),n(staticManifestProvider,"staticManifestProvider");function parseManifests(r){let o;try{o=JSON.parse(r)}catch{return}const l=Array.isArray(o)?o:o?.manifests;if(!Array.isArray(l))return;const d=l.filter(f=>!!f&&typeof f=="object"&&typeof f.service=="string"&&Array.isArray(f.mounts));return d.length>0?d:void 0}w(parseManifests,"parseManifests"),g(parseManifests,"parseManifests"),n(parseManifests,"parseManifests");function fileManifestProvider(r,o={}){const l=o.onError??(()=>{});let d=[],f=-1;const M=new Set,b=n(()=>{if(!(0,node_fs_1.existsSync)(r))return;let u;try{u=(0,node_fs_1.statSync)(r).mtimeMs}catch{return}if(u===f)return;let S;try{S=(0,node_fs_1.readFileSync)(r,"utf8")}catch(t){l(t);return}const s=parseManifests(S);if(!s){l(new Error(`[gateway] rejecting invalid manifest file ${r} \u2014 keeping last-good`));return}f=u,d=s;for(const t of M)try{t(d)}catch(e){l(e)}},"reload");b();let A;try{A=(0,node_fs_1.watch)(r,{persistent:!1},()=>b())}catch{}const m=setInterval(b,o.pollMs??1e3);return m.unref?.(),{list:n(()=>d,"list"),watch:n(u=>(M.add(u),()=>M.delete(u)),"watch"),stop:n(()=>{try{A?.close()}catch{}clearInterval(m)},"stop")}}w(fileManifestProvider,"fileManifestProvider"),g(fileManifestProvider,"fileManifestProvider"),n(fileManifestProvider,"fileManifestProvider");function rolloutPodProvider(r,o={}){const l=new Map,d=o.onError??(()=>{}),f=n(s=>({cohorts:s.cohorts.map(t=>({...t,urls:t.urls.slice()})),select:(0,manifest_1.smoothWeightedSelector)(s.cohorts.map(t=>t.weight)),rr:s.cohorts.map(()=>-1),rules:s.rules??[]}),"build"),M=n(s=>{const t=new Map,e=[];for(const[c,a]of Object.entries(s??{})){const h=n(()=>{const k=l.get(c);k&&t.set(c,k),e.push(c)},"keepLastGood");if(!isValidEntry(a)){h();continue}try{t.set(c,f(toSpec(a)))}catch{h()}}e.length&&d(new Error(`[gateway] rollout config: ignoring invalid entr${e.length>1?"ies":"y"} for ${e.join(", ")} \u2014 keeping last-good`)),l.clear();for(const[c,a]of t)l.set(c,a)},"load");M(r);const b=n(s=>s.cohorts.findIndex(t=>t.urls.length>0),"firstNonEmpty"),A=3e4,m=3e5,u=new Map,S=n(s=>{const t=u.get(s);return!!t&&Date.now()<t.until},"isEjected");return{pick(s,t){const e=l.get(s);if(!e||e.cohorts.length===0)return;const c=t?.isHealthy,a=c||u.size>0?i=>!S(i)&&(c?c(i):!0):void 0,h=n((i,p)=>{const x=e.cohorts[i];if(!x||x.urls.length===0)return;const L=x.urls.length;for(let _=0;_<L;_++){e.rr[i]=(e.rr[i]+1)%L;const O=x.urls[e.rr[i]];if(!p||p(O))return O}},"pickUrl"),k=n(i=>i.urls.length>0&&(t?.allowDrained===!0||i.weight>0),"pinnable"),j=t?.version?e.cohorts.findIndex(i=>i.version===t.version&&k(i)):-1;if(j>=0){const i=h(j,a)??h(j);if(i===void 0)return;const p=e.cohorts[j].version;return p===FLAT?{url:i}:{url:i,version:p}}let v=e.select();(!e.cohorts[v]||e.cohorts[v].urls.length===0)&&(v=b(e));let y=h(v,a);if(y===void 0&&a)for(let i=0;i<e.cohorts.length;i++){const p=h(i,a);if(p!==void 0){v=i,y=p;break}}if(y===void 0&&(y=h(v)),y===void 0)return;const E=e.cohorts[v]?.version;return E===void 0||E===FLAT?{url:y}:{url:y,version:E}},endpoints(){const s=new Set;for(const t of l.values())for(const e of t.cohorts)for(const c of e.urls)s.add(c);return[...s]},resolveVersion(s,t){const e=l.get(s);return e&&e.rules.length?(0,manifest_1.pickTargetedVersion)(e.rules,t):void 0},bucket(s,t){const e=l.get(s);if(!e||e.cohorts.length===0)return;const c=e.cohorts[(0,manifest_1.bucketByWeight)(`${t}:${s}`,e.cohorts.map(a=>a.weight))];return c&&c.version!==FLAT?{version:c.version}:void 0},ensureUp:n(async()=>!0,"ensureUp"),drop(s,t){if(!("url"in t))return;const e=Date.now(),c=u.get(t.url),a=c&&e<c.until+m?c.strikes+1:1;u.set(t.url,{until:e+Math.min(A*2**(a-1),m),strikes:a})},update:M}}w(rolloutPodProvider,"rolloutPodProvider"),g(rolloutPodProvider,"rolloutPodProvider"),n(rolloutPodProvider,"rolloutPodProvider");function endpointsPodProvider(r,o={}){const l=rolloutPodProvider(r,o);return{...l,resolveVersion:n(()=>{},"resolveVersion"),bucket:n(()=>{},"bucket"),update:n(d=>l.update(d),"update")}}w(endpointsPodProvider,"endpointsPodProvider"),g(endpointsPodProvider,"endpointsPodProvider"),n(endpointsPodProvider,"endpointsPodProvider");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var v=Object.defineProperty;var M=(r,e)=>v(r,"name",{value:e,configurable:!0});var E=Object.defineProperty,k=M((r,e)=>E(r,"name",{value:e,configurable:!0}),"k"),A=Object.defineProperty,c=k((r,e)=>A(r,"name",{value:e,configurable:!0}),"c");Object.defineProperty(exports,"__esModule",{value:!0}),exports.createRateLimiter=createRateLimiter,exports.createRedisRateLimiter=createRedisRateLimiter;function createRateLimiter(r){const e=Math.max(1,r.limit),i=Math.max(1,r.windowMs),n=r.now??Date.now,m=e/i,l=new Map,f=c((a,o)=>Math.min(e,a.tokens+(o-a.last)*m),"refilled"),u=setInterval(()=>{const a=n();for(const[o,t]of l)f(t,a)>=e&&l.delete(o)},i);return u.unref?.(),{check(a){const o=n();let t=l.get(a);return t||(t={tokens:e,last:o},l.set(a,t)),t.tokens=f(t,o),t.last=o,t.tokens>=1?(t.tokens-=1,{allowed:!0,remaining:Math.floor(t.tokens),retryAfterMs:0}):{allowed:!1,remaining:0,retryAfterMs:Math.ceil((1-t.tokens)/m)}},stop(){clearInterval(u)}}}M(createRateLimiter,"createRateLimiter"),k(createRateLimiter,"createRateLimiter"),c(createRateLimiter,"createRateLimiter");const BUCKET_LUA=`
|
|
2
2
|
local b = redis.call('HMGET', KEYS[1], 't', 's')
|
|
3
3
|
local cap = tonumber(ARGV[1])
|
|
4
4
|
local refill = tonumber(ARGV[2])
|
|
@@ -15,4 +15,4 @@ redis.call('HSET', KEYS[1], 't', tokens, 's', now)
|
|
|
15
15
|
redis.call('PEXPIRE', KEYS[1], ttl)
|
|
16
16
|
local retry = 0
|
|
17
17
|
if ok == 0 then retry = math.ceil((1 - tokens) / refill) end
|
|
18
|
-
return {ok, math.floor(tokens), retry}`,RL_TIMEOUT=Symbol("rl-timeout"),RL_FAIL=Symbol("rl-fail");function createRedisRateLimiter(
|
|
18
|
+
return {ok, math.floor(tokens), retry}`,RL_TIMEOUT=Symbol("rl-timeout"),RL_FAIL=Symbol("rl-fail");function createRedisRateLimiter(r,e){const i=Math.max(1,e.limit),n=Math.max(1,e.windowMs),m=e.prefix??"lensmcp:gw:rl:",l=Math.max(1,e.timeoutMs??100),f=e.failOpen!==!1,u=i/n,a=Math.ceil(n)+1e3;let o=!1;const t=c(w=>(o||(o=!0,e.onFailure?.(w)),f?{allowed:!0,remaining:i,retryAfterMs:0}:{allowed:!1,remaining:0,retryAfterMs:n}),"onFail");return{async check(w){let b,h="redis unavailable";const R=Promise.resolve(r.eval(BUCKET_LUA,1,`${m}${w}`,i,u,a)).then(s=>s,s=>(h=String(s?.message??s),RL_FAIL)),p=new Promise(s=>{b=setTimeout(()=>s(RL_TIMEOUT),l)}),d=await Promise.race([R,p]);if(clearTimeout(b),d===RL_TIMEOUT||d===RL_FAIL)return t(d===RL_TIMEOUT?`redis timed out after ${l}ms`:h);const[y,g,L]=d;return y===1?{allowed:!0,remaining:Number(g)||0,retryAfterMs:0}:{allowed:!1,remaining:0,retryAfterMs:Number(L)||n}},stop(){}}}M(createRedisRateLimiter,"createRedisRateLimiter"),k(createRedisRateLimiter,"createRedisRateLimiter"),c(createRedisRateLimiter,"createRedisRateLimiter");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var v=Object.defineProperty;var d=(e,t)=>v(e,"name",{value:t,configurable:!0});var g=Object.defineProperty,u=d((e,t)=>g(e,"name",{value:t,configurable:!0}),"u"),y=Object.defineProperty,n=u((e,t)=>y(e,"name",{value:t,configurable:!0}),"n");Object.defineProperty(exports,"__esModule",{value:!0}),exports.changeChannel=exports.rolloutKey=exports.manifestKey=exports.DEFAULT_REGISTRY_PREFIX=void 0,exports.redisRegistrySource=redisRegistrySource,exports.createRegistryProviders=createRegistryProviders;const providers_prod_1=require("./providers-prod");exports.DEFAULT_REGISTRY_PREFIX="lensmcp:gw";const manifestKey=n((e,t)=>`${e}:manifest:${t}`,"manifestKey");exports.manifestKey=manifestKey;const rolloutKey=n((e,t)=>`${e}:rollout:${t}`,"rolloutKey");exports.rolloutKey=rolloutKey;const changeChannel=n(e=>`${e}:changed`,"changeChannel");exports.changeChannel=changeChannel;function parseManifest(e){try{const t=JSON.parse(e);return t&&typeof t.service=="string"&&Array.isArray(t.mounts)?t:void 0}catch{return}}d(parseManifest,"parseManifest"),u(parseManifest,"parseManifest"),n(parseManifest,"parseManifest");function redisRegistrySource(e,t={}){const a=t.prefix??exports.DEFAULT_REGISTRY_PREFIX;let s;const c=`${a}:rollout:`;return{async read(){const i=await e.keys(`${a}:manifest:*`),f=i.length?(await e.mget(...i)).filter(r=>!!r).map(parseManifest).filter(r=>!!r):[],o=await e.keys(`${c}*`),l={};if(o.length){const r=await e.mget(...o);o.forEach((p,h)=>{const m=r[h];if(m)try{l[p.slice(c.length)]=JSON.parse(m)}catch{}})}return{manifests:f,endpoints:l}},async watch(i){return s=e.duplicate(),await s.subscribe((0,exports.changeChannel)(a)),s.on("message",()=>i()),async()=>{try{await s?.quit()}catch{}}},stop(){s?.quit().catch(()=>{})}}}d(redisRegistrySource,"redisRegistrySource"),u(redisRegistrySource,"redisRegistrySource"),n(redisRegistrySource,"redisRegistrySource");function createRegistryProviders(e,t={}){const a=t.onError??(()=>{});let s=[];const c=new Set,i=(0,providers_prod_1.rolloutPodProvider)({},{onError:a});let f,o;const l=n(async()=>{let r;try{r=await e.read()}catch(p){a(p);return}if(s.length>0&&r.manifests.length===0){a(new Error("[gateway] registry read came back EMPTY while serving routes \u2014 keeping last-good (set the registry to a single manifest to drain deliberately)"));return}s=r.manifests,(Object.keys(r.endpoints).length>0||s.length===0)&&i.update(r.endpoints);for(const p of c)try{p(s)}catch(h){a(h)}},"refresh");return{manifests:{list:n(()=>s,"list"),watch:n(r=>(c.add(r),()=>c.delete(r)),"watch")},pods:i,async start(){if(await l(),e.watch)try{f=await e.watch(()=>{l()})}catch(r){a(r)}o=setInterval(()=>{l()},t.pollMs??5e3),o.unref?.()},stop(){f?.(),o&&clearInterval(o),e.stop?.()}}}d(createRegistryProviders,"createRegistryProviders"),u(createRegistryProviders,"createRegistryProviders"),n(createRegistryProviders,"createRegistryProviders");
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var
|
|
2
|
-
`)}c(summarizeRollout,"summarizeRollout"),i(summarizeRollout,"summarizeRollout");function ruleSummary(
|
|
1
|
+
"use strict";var p=Object.defineProperty;var u=(t,e)=>p(t,"name",{value:e,configurable:!0});var d=Object.defineProperty,c=u((t,e)=>d(t,"name",{value:e,configurable:!0}),"c"),h=Object.defineProperty,i=c((t,e)=>h(t,"name",{value:e,configurable:!0}),"i");Object.defineProperty(exports,"__esModule",{value:!0}),exports.applyRolloutOp=applyRolloutOp,exports.summarizeRollout=summarizeRollout,exports.parseRolloutCommand=parseRolloutCommand;const RULE_OPS=new Set(["eq","ne","in","nin","prefix","suffix","contains","regex","exists","gt","lt","cidr"]),clone=i(t=>JSON.parse(JSON.stringify(t)),"clone");function asSpec(t,e){if(e===void 0)return{rules:[],cohorts:[]};if(Array.isArray(e)){if(e.length&&typeof e[0]=="string")throw new Error(`service "${t}" is a flat endpoint list; convert it to cohorts first (e.g. add-cohort)`);return{rules:[],cohorts:e}}return{rules:e.rules??[],cohorts:e.cohorts??[]}}u(asSpec,"asSpec"),c(asSpec,"asSpec"),i(asSpec,"asSpec");const findCohort=i((t,e)=>t.cohorts.find(o=>o.version===e),"findCohort");function reqWeight(t){if(!Number.isFinite(t)||t<0)throw new Error(`weight must be a number \u2265 0 (got ${t})`);return t}u(reqWeight,"reqWeight"),c(reqWeight,"reqWeight"),i(reqWeight,"reqWeight");function applyRolloutOp(t,e){const o=clone(t),r=asSpec(e.service,o[e.service]);switch(e.kind){case"add-cohort":{if(findCohort(r,e.version))throw new Error(`cohort "${e.version}" already exists on "${e.service}" \u2014 use set-weight`);if(!e.urls.length)throw new Error("add-cohort needs at least one upstream url");r.cohorts.push({version:e.version,weight:reqWeight(e.weight),urls:e.urls.slice()});break}case"set-weight":{const n=findCohort(r,e.version);if(!n)throw new Error(`no cohort "${e.version}" on "${e.service}"`);n.weight=reqWeight(e.weight);break}case"remove-cohort":{if(!findCohort(r,e.version))throw new Error(`no cohort "${e.version}" on "${e.service}"`);r.cohorts=r.cohorts.filter(n=>n.version!==e.version);break}case"promote":{if(!findCohort(r,e.version))throw new Error(`no cohort "${e.version}" on "${e.service}"`);for(const n of r.cohorts)n.weight=n.version===e.version?100:0;break}case"abort":{const n=findCohort(r,e.version);if(!n)throw new Error(`no cohort "${e.version}" on "${e.service}"`);n.weight=0;break}case"add-rule":{validateRule(e.rule),r.rules=[...(r.rules??[]).filter(n=>!e.rule.name||n.name!==e.rule.name),e.rule];break}case"remove-rule":{const n=(r.rules??[]).length;if(r.rules=(r.rules??[]).filter(s=>s.name!==e.name),r.rules.length===n)throw new Error(`no rule named "${e.name}" on "${e.service}"`);break}}return o[e.service]=r.rules&&r.rules.length?{rules:r.rules,cohorts:r.cohorts}:r.cohorts,o}u(applyRolloutOp,"applyRolloutOp"),c(applyRolloutOp,"applyRolloutOp"),i(applyRolloutOp,"applyRolloutOp");function validateRule(t){if(!t||typeof t.version!="string"||!t.version)throw new Error("rule needs a non-empty version");if(!t.when||typeof t.when!="object")throw new Error("rule needs a `when` condition");const e=i(o=>{const r=o;if("all"in r||"any"in r||"not"in r){for(const n of["all","any"])Array.isArray(r[n])&&r[n].forEach(e);r.not&&e(r.not);return}if(typeof r.attr!="string"||!RULE_OPS.has(r.op))throw new Error(`invalid rule condition (attr/op): ${JSON.stringify(r)}`)},"walk");e(t.when)}u(validateRule,"validateRule"),c(validateRule,"validateRule"),i(validateRule,"validateRule");function summarizeRollout(t,e){const o=e?[e]:Object.keys(t);if(!o.length)return"(no services in rollout config)";const r=[];for(const n of o){const s=t[n];if(s===void 0){r.push(`${n}: (not present)`);continue}if(Array.isArray(s)&&s.length&&typeof s[0]=="string"){r.push(`${n}: flat LB \u2192 ${s.join(", ")}`);continue}const l=asSpec(n,s),v=l.cohorts.reduce((a,m)=>a+Math.max(0,m.weight),0)||1;r.push(`${n}:`);for(const a of l.cohorts)r.push(` \u2022 ${a.version.padEnd(16)} weight ${String(a.weight).padStart(3)} (${(Math.max(0,a.weight)/v*100).toFixed(0)}%) ${a.urls.length} url(s)`);for(const a of l.rules??[])r.push(` \u25B8 rule ${(a.name??"(unnamed)").padEnd(16)} \u2192 ${a.version} ${ruleSummary(a.when)}`)}return r.join(`
|
|
2
|
+
`)}u(summarizeRollout,"summarizeRollout"),c(summarizeRollout,"summarizeRollout"),i(summarizeRollout,"summarizeRollout");function ruleSummary(t){const e=t;return"all"in e?"("+e.all.map(ruleSummary).join(" AND ")+")":"any"in e?"("+e.any.map(ruleSummary).join(" OR ")+")":"not"in e?"NOT "+ruleSummary(e.not):`${e.attr} ${e.op}${e.value!==void 0?" "+JSON.stringify(e.value):""}`}u(ruleSummary,"ruleSummary"),c(ruleSummary,"ruleSummary"),i(ruleSummary,"ruleSummary");function parseRolloutCommand(t){const[e,...o]=t,r=i((n,s)=>{if(o.length<n)throw new Error(`usage: ${e} ${s}`)},"need");switch(e){case"status":return{status:o[0]};case"add-cohort":return r(4,"<service> <version> <weight> <url> [url...]"),{op:{kind:"add-cohort",service:o[0],version:o[1],weight:Number(o[2]),urls:o.slice(3)}};case"set-weight":return r(3,"<service> <version> <weight>"),{op:{kind:"set-weight",service:o[0],version:o[1],weight:Number(o[2])}};case"remove-cohort":return r(2,"<service> <version>"),{op:{kind:"remove-cohort",service:o[0],version:o[1]}};case"promote":return r(2,"<service> <version>"),{op:{kind:"promote",service:o[0],version:o[1]}};case"abort":return r(2,"<service> <version>"),{op:{kind:"abort",service:o[0],version:o[1]}};case"add-rule":{r(6,"<service> <name> <attr> <op> <value> <version>");const n=o[3],s=o[4]??"",l=n==="in"||n==="nin"?s.split(",").map(v=>v.trim()).filter(Boolean):s;return{op:{kind:"add-rule",service:o[0],rule:{name:o[1],when:{attr:o[2],op:n,value:l},version:o[5]}}}}case"remove-rule":return r(2,"<service> <name>"),{op:{kind:"remove-rule",service:o[0],name:o[1]}};default:throw new Error(`unknown command "${e??""}". commands: status, add-cohort, set-weight, remove-cohort, promote, abort, add-rule, remove-rule`)}}u(parseRolloutCommand,"parseRolloutCommand"),c(parseRolloutCommand,"parseRolloutCommand"),i(parseRolloutCommand,"parseRolloutCommand");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var g=Object.defineProperty;var m=(o,n)=>g(o,"name",{value:n,configurable:!0});var y=Object.defineProperty,f=m((o,n)=>y(o,"name",{value:n,configurable:!0}),"f"),h=Object.defineProperty,d=f((o,n)=>h(o,"name",{value:n,configurable:!0}),"d");Object.defineProperty(exports,"__esModule",{value:!0}),exports.createEdgeAuth=createEdgeAuth;const manifest_1=require("../manifest"),dev_auth_1=require("./dev-auth"),edge_1=require("./edge");function createEdgeAuth(o,n,v){const{traceStep:i}=n;return{internal:d((e,p,r)=>{const c=String(e.headers["x-api-key"]??""),a=o.keyToProject.get(c);if(!a)return i(r,"auth",{mode:"x-api-key",ok:!1}),{ok:!1,status:401,reason:"unauthorized",detail:"Invalid or missing x-api-key for internal route."};const t=o.keyToWorkspace?.get(c),l=p.svc?.wsKey;if(t&&l&&t!==l)return i(r,"auth",{mode:"x-api-key",ok:!1,reason:"cross-workspace",caller:a,callerWorkspace:t,routeWorkspace:l}),{ok:!1,status:401,reason:"unauthorized",detail:"Invalid or missing x-api-key for internal route."};e.headers["x-api-key-id"]=a,t?e.headers["x-api-key-workspace"]=t:delete e.headers["x-api-key-workspace"],e.__lensmcpCaller=a,delete e.headers["x-api-key"];const s=(0,edge_1.callerContextOf)(e);for(const[k,u]of Object.entries(s))e.headers[k]=u;return i(r,"auth",{mode:"x-api-key",ok:!0,caller:a,...t?{callerWorkspace:t}:{},...s["x-tenant-id"]!==void 0?{callerTenant:!0}:{},...s["x-user-id"]!==void 0?{callerUser:!0}:{}}),{ok:!0,caller:a}},"internal"),public:d((e,p,r,c)=>{const a=p.auth;if(a){const t=c??(0,edge_1.canonicalPath)(e.url??"/")??(e.url??"/").split("?")[0],l=(e.method??"GET").toUpperCase(),s=(0,manifest_1.authRuleFor)(a,t,l);if(s.mode==="jwt"){const k=String(e.headers.host??"").split(":")[0].toLowerCase(),u=(0,dev_auth_1.verifyDevJwt)(e,v?.for(k));return u?s.rule&&!(0,manifest_1.evalRule)(s.rule,(0,dev_auth_1.devAttrs)(e,u,t))?(i(r,"authz",{ok:!1}),{ok:!1,status:403,reason:"forbidden",detail:"Forbidden: insufficient permission"}):((0,dev_auth_1.stampIdentity)(e,u),i(r,"auth",{mode:"jwt",ok:!0}),{ok:!0,claims:u}):(i(r,"auth",{mode:"jwt",ok:!1}),{ok:!1,status:401,reason:"unauthorized",detail:"Unauthorized: invalid or missing token"})}return i(r,"auth",{mode:s.mode}),{ok:!0}}return i(r,"auth",{mode:"public",unconfigured:!0}),{ok:!0}},"publicAuth")}}m(createEdgeAuth,"createEdgeAuth"),f(createEdgeAuth,"createEdgeAuth"),d(createEdgeAuth,"createEdgeAuth");
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
"use strict";var
|
|
2
|
-
<div class="key">${esc(
|
|
3
|
-
<div class="root">${esc(displayRoot(
|
|
1
|
+
"use strict";var g=Object.defineProperty;var c=(o,e)=>g(o,"name",{value:e,configurable:!0});var l=Object.defineProperty,i=c((o,e)=>l(o,"name",{value:e,configurable:!0}),"i"),p=Object.defineProperty,n=i((o,e)=>p(o,"name",{value:e,configurable:!0}),"n");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=n(o=>o.replace(/[&<>"']/g,e=>({"&":"&","<":"<",">":">",'"':""","'":"'"})[e]),"esc");function isLoopbackRequest(o){const e=o.socket?.remoteAddress;if(!e)return!1;const t=e.startsWith("::ffff:")?e.slice(7):e;return t==="::1"||t==="127.0.0.1"||/^127\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(t)}c(isLoopbackRequest,"isLoopbackRequest"),i(isLoopbackRequest,"isLoopbackRequest"),n(isLoopbackRequest,"isLoopbackRequest");function displayRoot(o,e=(0,node_os_1.homedir)()){const t=o.replace(/\/+$/,"").split("/").filter(Boolean),a=t.slice(-2).join("/");if(!a)return"/";const r=e!==""&&(o===e||o.startsWith(`${e}/`)),s=t.length>2;return r?s?`~/\u2026/${a}`:`~/${a}`:s?`\u2026/${a}`:`/${a}`}c(displayRoot,"displayRoot"),i(displayRoot,"displayRoot"),n(displayRoot,"displayRoot");function renderChooserPage(o,e){const t=o.map(r=>({...r,live:r.key===e||(0,workspace_registry_1.isWorkspaceLive)(r)})).sort((r,s)=>Number(s.live)-Number(r.live)||r.key.localeCompare(s.key)),a=t.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>':t.map(r=>{const s=r.key===e?'<span class="badge here">running here</span>':r.live?'<span class="badge live">live</span>':'<span class="badge off">offline</span>',f=r.live?'<span class="open">Open dashboard \u2192</span>':'<span class="hint">start its gateway to open</span>',d=`<div class="card-main">
|
|
2
|
+
<div class="key">${esc(r.key)} ${s}</div>
|
|
3
|
+
<div class="root">${esc(displayRoot(r.root))}</div>
|
|
4
4
|
</div>
|
|
5
|
-
<div class="card-action">${
|
|
6
|
-
${
|
|
5
|
+
<div class="card-action">${f}</div>`;return r.live?`<a class="card is-live" href="${esc(r.base)}/">
|
|
6
|
+
${d}
|
|
7
7
|
</a>`:`<div class="card is-off">
|
|
8
|
-
${
|
|
8
|
+
${d}
|
|
9
9
|
</div>`}).join(`
|
|
10
10
|
`);return`<!doctype html>
|
|
11
11
|
<html lang="en"><head>
|
|
@@ -42,10 +42,10 @@
|
|
|
42
42
|
<body><div class="wrap">
|
|
43
43
|
<header>
|
|
44
44
|
<h1>LensMCP workspaces</h1>
|
|
45
|
-
<p class="sub">Pick a workspace to open its dashboard. ${t.filter(
|
|
45
|
+
<p class="sub">Pick a workspace to open its dashboard. ${t.filter(r=>r.live).length} live \xB7 ${t.length} known.</p>
|
|
46
46
|
</header>
|
|
47
47
|
<div class="list">
|
|
48
|
-
${
|
|
48
|
+
${a}
|
|
49
49
|
</div>
|
|
50
50
|
<footer>Served by the gateway on <code>lensmcp.local</code>. This list updates as gateways start and stop.</footer>
|
|
51
|
-
</div></body></html>`}i(renderChooserPage,"renderChooserPage"),n(renderChooserPage,"renderChooserPage");function serveChooser(o,e,t){if(t&&!isLoopbackRequest(t)){o.writeHead(404,{"content-type":"text/plain; charset=utf-8","cache-control":"no-store"}),o.end("not found");return}const
|
|
51
|
+
</div></body></html>`}c(renderChooserPage,"renderChooserPage"),i(renderChooserPage,"renderChooserPage"),n(renderChooserPage,"renderChooserPage");function serveChooser(o,e,t){if(t&&!isLoopbackRequest(t)){o.writeHead(404,{"content-type":"text/plain; charset=utf-8","cache-control":"no-store"}),o.end("not found");return}const a=renderChooserPage((0,workspace_registry_1.readWorkspaces)(),e);o.writeHead(200,{"content-type":"text/html; charset=utf-8","cache-control":"no-store"}),o.end(a)}c(serveChooser,"serveChooser"),i(serveChooser,"serveChooser"),n(serveChooser,"serveChooser");
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var
|
|
2
|
-
`)}catch{}return e.registry.register(
|
|
1
|
+
"use strict";var S=Object.defineProperty;var w=(t,e)=>S(t,"name",{value:e,configurable:!0});var f=Object.defineProperty,p=w((t,e)=>f(t,"name",{value:e,configurable:!0}),"p"),h=Object.defineProperty,u=p((t,e)=>h(t,"name",{value:e,configurable:!0}),"u");Object.defineProperty(exports,"__esModule",{value:!0}),exports.controlSocketPath=controlSocketPath,exports.clusterVersion=clusterVersion,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"),service_keys_1=require("./service-keys"),workspace_log_1=require("./workspace-log");function controlSocketPath(){const t=process.env.LENSMCP_HOME||os.homedir();return path.join(t,".lensmcp","control.sock")}w(controlSocketPath,"controlSocketPath"),p(controlSocketPath,"controlSocketPath"),u(controlSocketPath,"controlSocketPath");function clusterVersion(){let t=__dirname;for(let e=0;e<6;e++){const n=path.join(t,"package.json");if(fs.existsSync(n))try{const s=JSON.parse(fs.readFileSync(n,"utf8"));if(s.name==="@lensmcp/cluster"&&typeof s.version=="string")return s.version}catch{}const i=path.dirname(t);if(i===t)break;t=i}}w(clusterVersion,"clusterVersion"),p(clusterVersion,"clusterVersion"),u(clusterVersion,"clusterVersion");function readJsonBody(t){return new Promise((e,n)=>{let i="";t.on("data",s=>{i+=s,i.length>1e6&&n(new Error("body too large"))}),t.on("end",()=>{try{e(i?JSON.parse(i):{})}catch(s){n(s)}}),t.on("error",n)})}w(readJsonBody,"readJsonBody"),p(readJsonBody,"readJsonBody"),u(readJsonBody,"readJsonBody");function ensureOwnerOnlyDir(t){try{fs.mkdirSync(t,{recursive:!0,mode:448})}catch{}try{const e=fs.lstatSync(t);return e.isDirectory()?((e.mode&63)!==0&&fs.chmodSync(t,448),!0):!1}catch{return!1}}w(ensureOwnerOnlyDir,"ensureOwnerOnlyDir"),p(ensureOwnerOnlyDir,"ensureOwnerOnlyDir"),u(ensureOwnerOnlyDir,"ensureOwnerOnlyDir");function startControlServer(t){const{rt:e}=t,n=controlSocketPath(),i=path.dirname(n);ensureOwnerOnlyDir(i)||console.warn(`[gateway] control home ${i} is not a usable owner-only directory \u2014 refusing to expose the control plane there.`);try{fs.unlinkSync(n)}catch{}const s=u((c,a,l)=>{c.writeHead(a,{"content-type":"application/json"}),c.end(JSON.stringify(l))},"send"),k=http.createServer((c,a)=>{(async()=>{try{const l=(c.url??"").split("?")[0];if(c.method==="GET"&&l==="/list")return s(a,200,{workspaces:e.registry.keys().map(r=>{const o=e.registry.get(r);return{key:r,root:o?.root,routes:o?.routes.length??0,services:o?.services.length??0}})});if(c.method==="GET"&&l==="/status"){const r=clusterVersion();return s(a,200,{daemon:{pid:process.pid,wsKey:e.wsKey,...r?{version:r}:{}},workspaces:e.registry.keys().map(o=>{const y=e.registry.get(o);return{key:o,root:y?.root,routes:y?.routes.length??0,services:y?.services.length??0,isDaemon:o===e.wsKey}}),services:e.registry.allServices().map(o=>({project:o.project,wsKey:o.wsKey,host:o.decl.host,state:o.state}))})}if(c.method==="POST"&&l==="/register"){const r=await readJsonBody(c);if(!r.wsKey||!r.root)return s(a,400,{error:"wsKey and root are required"});const o=r.projects??{},y=(0,discovery_1.projectSourceRoots)(r.root,o,r.projectDependencies),{routes:g,services:d}=(0,discovery_1.discoverRoutes)(r.root,o,void 0,r.wsKey,y),m={wsKey:r.wsKey,root:r.root,routes:g,services:d};try{const v=(0,service_keys_1.adoptServiceKeys)(e,r.root,d,r.wsKey);v.added.length>0&&console.log(`[gateway] adopted east-west keys for ${r.wsKey}: ${v.added.join(", ")}`)}catch(v){console.error(`[gateway] could not adopt east-west keys for ${r.wsKey}: ${v.message}`)}try{(0,workspace_log_1.workspaceLogWriter)(r.root)?.(`[gateway] ${new Date().toISOString()} this workspace ('${r.wsKey}') is served by the daemon at ${e.root} (pid ${process.pid}); its gateway-level log is ${path.join(e.root,".lensmcp","gateway.log")}. Pod output for this workspace follows here. Attach live with \`lensmcp logs <service>\`.
|
|
2
|
+
`)}catch{}return e.registry.register(m),await t.onRegister?.(m),e.rebuildRoutes(),s(a,200,{ok:!0,wsKey:r.wsKey,routes:g.length,services:d.length,workspaces:e.registry.keys()})}if(c.method==="POST"&&l==="/unregister"){const r=await readJsonBody(c);if(!r.wsKey)return s(a,400,{error:"wsKey is required"});const o=e.registry.unregister(r.wsKey);if(o){for(const y of o.services){const g=(0,service_keys_1.serviceKeyId)(y.wsKey??r.wsKey,y.project),d=e.serviceKeys[g];d&&(delete e.serviceKeys[g],e.keyToProject.delete(d),e.keyToWorkspace?.delete(d))}for(const y of o.services)t.killService(y,"workspace unregistered");t.onUnregister?.(o)}return e.rebuildRoutes(),s(a,200,{ok:!0,removed:!!o,workspaces:e.registry.keys()})}s(a,404,{error:"not found"})}catch(l){s(a,500,{error:l.message})}})()});return k.listen(n,()=>{try{fs.chmodSync(n,384)}catch(c){console.warn(`[gateway] could not restrict ${n} to 0600:`,c.message)}}),{socketPath:n,close:u(()=>{k.close();try{fs.unlinkSync(n)}catch{}},"close")}}w(startControlServer,"startControlServer"),p(startControlServer,"startControlServer"),u(startControlServer,"startControlServer");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
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
|
|
1
|
+
"use strict";var b=Object.defineProperty;var f=(e,o)=>b(e,"name",{value:o,configurable:!0});var y=Object.defineProperty,d=f((e,o)=>y(e,"name",{value:o,configurable:!0}),"d"),g=Object.defineProperty,p=d((e,o)=>g(e,"name",{value:o,configurable:!0}),"p");Object.defineProperty(exports,"__esModule",{value:!0}),exports.RETIRING_SUFFIX=void 0,exports.pickSock=pickSock,exports.lensPortFromUpstream=lensPortFromUpstream,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"),scope_1=require("./scope");exports.RETIRING_SUFFIX=".retiring";function pickSock(e,o=1500){const u=Date.now();if(u-e.scannedAt>o){try{const i=fs.readdirSync(e.dir),a=i.filter(r=>/^child-\d+(?:-g\d+)?\.sock$/.test(r)),l=a.filter(r=>!i.includes(r+exports.RETIRING_SUFFIX));e.socks=(l.length>0?l:a).map(r=>path.join(e.dir,r))}catch{e.socks=[]}e.scannedAt=u}if(e.socks.length!==0)return e.idx=(e.idx+1)%e.socks.length,e.socks[e.idx]}f(pickSock,"pickSock"),d(pickSock,"pickSock"),p(pickSock,"pickSock");function lensPortFromUpstream(e){if(!e)return;const o=/:(\d+)/.exec(e);return o?Number(o[1]):void 0}f(lensPortFromUpstream,"lensPortFromUpstream"),d(lensPortFromUpstream,"lensPortFromUpstream"),p(lensPortFromUpstream,"lensPortFromUpstream");function discoverRoutes(e,o,u=os.tmpdir(),i="",a={}){const l=p(c=>i?path.join(u,i,`${c}-devserver`):path.join(u,`${c}-devserver`),"sockDirFor"),r=[],v=[],s=[];let n;for(const[c,x]of Object.entries(o)){let t;try{const h=JSON.parse(fs.readFileSync(path.join(e,x.root,"project.json"),"utf8"));t=h.cluster??h.davnx}catch{continue}if(!t)continue;let m,S,k,R;if(t.service)t.lens&&console.warn(`[gateway] ${c}: cluster.lens is ignored for pod (service) decls \u2014 backends are instrumented by serve-hmr.`),m={dir:l(t.service),socks:[],idx:-1,scannedAt:0},S={project:c,decl:t,root:e,wsKey:i,pool:m,state:"down",lastUsed:Date.now(),inflight:0,lastScaleAt:0},v.push(S);else if(t.lens){const h=t.port??lensPortFromUpstream(t.upstream)??5173;k=`http://localhost:${h}`,R={project:c,...i?{workspaceKey:i}:{},workspaceRoot:e,projectRoot:path.join(e,x.root),port:h,...a[c]?.length?{sourceRoots:a[c]}:{}}}else if(k=t.upstream??(t.port?`http://localhost:${t.port}`:void 0),!k){console.warn(`[gateway] ${c}: no service/upstream/port \u2014 skipped.`);continue}const j={project:c,prependPrefix:t.prependPrefix,target:k,pool:m,svc:S,prefix:t.path,auth:t.auth,lens:R};t.host&&(r.push({...j,host:t.host}),s.push(t.host),m&&t.internalHost!==!1&&r.push({...j,host:typeof t.internalHost=="string"?t.internalHost:`internal.${t.host}`,internal:!0})),t.default&&(n={...j,prefix:void 0})}return n&&(n.apex=(0,scope_1.baseDomainOf)(s),r.push(n)),(0,manifest_1.sortBySpecificity)(r),{routes:r,services:v}}f(discoverRoutes,"discoverRoutes"),d(discoverRoutes,"discoverRoutes"),p(discoverRoutes,"discoverRoutes");function projectSourceRoots(e,o,u={}){const i={};for(const a of Object.keys(o)){const l=new Set,r=p(s=>{if(!l.has(s)){l.add(s);for(const n of u[s]??[])r(n)}},"visit");r(a);const v=[...l].map(s=>o[s]?.root).filter(s=>typeof s=="string").map(s=>path.resolve(e,s)).filter(s=>{const n=path.relative(e,s);return n===""||n!==".."&&!n.startsWith(`..${path.sep}`)&&!path.isAbsolute(n)});i[a]=[...new Set(v)]}return i}f(projectSourceRoots,"projectSourceRoots"),d(projectSourceRoots,"projectSourceRoots"),p(projectSourceRoots,"projectSourceRoots");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var x=Object.defineProperty;var i=(e,r)=>x(e,"name",{value:r,configurable:!0});var d=Object.defineProperty,c=i((e,r)=>d(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.cors=exports.isRoutedOrigin=exports.callerContextOf=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");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,E)=>{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,...E??{}}),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"],exports.CALLER_CONTEXT_HEADERS=["x-tenant-id","x-user-id"],exports.CALLER_CONTEXT=Symbol.for("lensmcp.gateway.callerContext");const CALLER_CONTEXT_VALUE=/^[\x21-\x2b\x2d-\x7e]{1,128}$/;function stripOwnedHeaders(e){const r={};for(const t of exports.CALLER_CONTEXT_HEADERS){const s=e.headers[t];typeof s=="string"&&CALLER_CONTEXT_VALUE.test(s)&&(r[t]=s)}e[exports.CALLER_CONTEXT]=r;for(const t of exports.GATEWAY_OWNED_HEADERS)delete e.headers[t]}i(stripOwnedHeaders,"stripOwnedHeaders"),c(stripOwnedHeaders,"stripOwnedHeaders"),o(stripOwnedHeaders,"stripOwnedHeaders");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;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"]??"*")}),r.end()},"corsPreflight");exports.corsPreflight=corsPreflight,exports.PREFLIGHT_METHODS_NOROUTE="GET,HEAD,OPTIONS",exports.PREFLIGHT_METHODS_ROUTED="GET,HEAD,POST,PUT,PATCH,DELETE,OPTIONS";
|