@lensmcp/cluster 1.25.1 → 1.25.2
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-host.js +1 -1
- package/build-scope-patterns.js +1 -1
- package/bundle-parent.js +1 -1
- package/checkout-cache.js +1 -1
- package/create-webpack-dev.js +1 -1
- package/create-webpack-prod.js +1 -1
- package/dev-devtool.js +1 -1
- package/devserver-notifier.js +1 -1
- package/devserver-transport.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 +12 -12
- package/executors/gateway/runtime/control.d.ts +3 -0
- 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/guest-graph.js +2 -2
- package/executors/gateway/runtime/guest-replay.js +2 -2
- 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/instance.js +2 -2
- package/executors/gateway/runtime/lens-children.js +1 -1
- package/executors/gateway/runtime/lifecycle.d.ts +11 -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.js +1 -1
- package/executors/gateway/runtime/pod-probe.js +1 -1
- package/executors/gateway/runtime/process-names.js +1 -1
- package/executors/gateway/runtime/project-graph-store.js +1 -1
- package/executors/gateway/runtime/proxy.js +1 -1
- package/executors/gateway/runtime/registration-guards.js +1 -1
- package/executors/gateway/runtime/route-registry.js +1 -1
- package/executors/gateway/runtime/scope.js +1 -1
- package/executors/gateway/runtime/serve-launch.js +3 -3
- package/executors/gateway/runtime/server.js +2 -2
- package/executors/gateway/runtime/service-keys.js +1 -1
- package/executors/gateway/runtime/shared-build.js +4 -4
- package/executors/gateway/runtime/types.d.ts +26 -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-middleware.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/gc-notice.js +1 -1
- package/graph-snapshot.js +1 -1
- package/handoff-retire.js +1 -1
- package/heap-snapshot.js +1 -1
- package/hot-swap-registries.js +1 -1
- package/index.js +1 -1
- package/inspector-secret.js +1 -1
- package/main.devserver.js +10 -10
- package/notice-generation.js +1 -1
- package/package.json +4 -4
- package/perf/heavy-barrel-import.js +1 -1
- package/perf/perf-config.js +1 -1
- package/perf/perf-rule-events.js +2 -2
- package/perf/perf-rules-analysis.js +1 -1
- package/perf/perf-rules-plugin.js +1 -1
- package/perf/source-scan.js +5 -5
- package/perf/workspace-libraries.js +2 -2
- package/pod-memory-events.js +2 -2
- package/pod-memory.js +1 -1
- package/pod-sock.js +1 -1
- package/process-name.js +1 -1
- package/redis-disconnect-fix.js +1 -1
- package/schema-first-instance.js +1 -1
- package/serve-runner.js +1 -1
- package/service-build-events.d.ts +7 -0
- package/service-build-events.js +1 -1
- package/shared-build/attach.js +2 -2
- package/shared-build/host.js +3 -3
- package/shared-build/protocol.js +1 -1
- package/shared-build/shared-compilation.js +3 -3
- package/shared-build/signature.js +1 -1
- package/stdio-guard.js +1 -1
- package/swap-mode.d.ts +23 -0
- package/swap-mode.js +1 -0
- package/swap-recycle.js +1 -1
- package/tsgo-check-plugin.js +4 -4
- package/typecheck-bus.js +3 -3
- package/typecheck-queue.js +1 -1
- package/workspace-paths.js +1 -1
package/heap-snapshot.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var _=Object.defineProperty;var p=(e,t)=>_(e,"name",{value:t,configurable:!0});var m=Object.defineProperty,i=p((e,t)=>m(e,"name",{value:t,configurable:!0}),"i");Object.defineProperty(exports,"__esModule",{value:!0}),exports.heapSnapshotPolicy=heapSnapshotPolicy,exports.availableSystemMemory=availableSystemMemory,exports.heapSnapshotRefusal=heapSnapshotRefusal,exports.heapSnapshotDir=heapSnapshotDir,exports.heapSnapshotFileName=heapSnapshotFileName,exports.ensureHeapDir=ensureHeapDir,exports.pruneHeapSnapshots=pruneHeapSnapshots,exports.writeHeapSnapshot=writeHeapSnapshot;const tslib_1=require("tslib"),node_child_process_1=require("node:child_process"),fs=tslib_1.__importStar(require("node:fs")),inspector=tslib_1.__importStar(require("node:inspector")),os=tslib_1.__importStar(require("node:os")),path=tslib_1.__importStar(require("node:path")),MB=1024*1024,numberFrom=i((e,t,s)=>{if(e===void 0||e.trim()==="")return t;const a=Number(e);return Number.isFinite(a)&&a>=s?a:t},"numberFrom");function heapSnapshotPolicy(e=process.env){return{maxHeapBytes:numberFrom(e.LENSMCP_HEAP_SNAPSHOT_MAX_MB,1024,1)*MB,minFreeBytes:numberFrom(e.LENSMCP_HEAP_SNAPSHOT_MIN_FREE_MB,1024,0)*MB,freeFactor:numberFrom(e.LENSMCP_HEAP_SNAPSHOT_FREE_FACTOR,3,0),keep:Math.max(1,Math.floor(numberFrom(e.LENSMCP_HEAP_SNAPSHOT_KEEP,3,1))),maxAgeMs:numberFrom(e.LENSMCP_HEAP_SNAPSHOT_MAX_AGE_H,24,0)*36e5}}p(heapSnapshotPolicy,"heapSnapshotPolicy"),i(heapSnapshotPolicy,"heapSnapshotPolicy");function availableSystemMemory(e=process.platform){try{if(e==="darwin"){const t=(0,node_child_process_1.spawnSync)("vm_stat",[],{encoding:"utf8",timeout:2e3}).stdout??"",s=Number(/page size of (\d+) bytes/.exec(t)?.[1]??4096),a=i(r=>Number(new RegExp(`Pages ${r}:\\s+(\\d+)`).exec(t)?.[1]??0),"pages"),o=a("free")+a("inactive")+a("speculative")+a("purgeable");if(o>0)return{bytes:o*s,source:"vm_stat free+inactive+speculative+purgeable"}}else if(e==="linux"){const t=/MemAvailable:\s+(\d+) kB/.exec(fs.readFileSync("/proc/meminfo","utf8"));if(t)return{bytes:Number(t[1])*1024,source:"/proc/meminfo MemAvailable"}}return{bytes:os.freemem(),source:"os.freemem()"}}catch{return}}p(availableSystemMemory,"availableSystemMemory"),i(availableSystemMemory,"availableSystemMemory");function heapSnapshotRefusal(e,t){if(t.live>e.maxHeapBytes){const s=Math.ceil(t.live/MB/256)*256;return`the pod's live heap is ${Math.round(t.live/MB)} MB, over the ${Math.round(e.maxHeapBytes/MB)} MB bound \u2014 a snapshot this size needs several times that in memory while it is written. Raise the bound for this one snapshot with \`--max-mb ${s}\` (the free-memory check still applies); the default is LENSMCP_HEAP_SNAPSHOT_MAX_MB, read when the pod starts`}if(t.available){const s=Math.max(e.minFreeBytes,e.freeFactor*t.live);if(t.available.bytes<s)return`only ${Math.round(t.available.bytes/MB)} MB of memory is available (${t.available.source}) and a snapshot of a ${Math.round(t.live/MB)} MB heap needs about ${Math.round(s/MB)} MB \u2014 free some memory first, or lower the floor with LENSMCP_HEAP_SNAPSHOT_MIN_FREE_MB / LENSMCP_HEAP_SNAPSHOT_FREE_FACTOR`}}p(heapSnapshotRefusal,"heapSnapshotRefusal"),i(heapSnapshotRefusal,"heapSnapshotRefusal");function heapSnapshotDir(e=process.env,t=process.cwd()){return e.LENSMCP_HEAP_DIR?path.resolve(e.LENSMCP_HEAP_DIR):e.LENSMCP_EVENT_FILE?path.join(path.dirname(path.resolve(e.LENSMCP_EVENT_FILE)),"heap"):path.join(t,".lensmcp","heap")}p(heapSnapshotDir,"heapSnapshotDir"),i(heapSnapshotDir,"heapSnapshotDir");function heapSnapshotFileName(e,t,s,a,o){const r=(e||"service").replace(/[^A-Za-z0-9_.-]/g,"_"),n=new Date(o).toISOString().replace(/[:.]/g,"-");return`${r}-pod${t}-pid${s}-g${a}-${n}.heapsnapshot`}p(heapSnapshotFileName,"heapSnapshotFileName"),i(heapSnapshotFileName,"heapSnapshotFileName");function ensureHeapDir(e){fs.mkdirSync(e,{recursive:!0,mode:448});const t=fs.lstatSync(e);if(!t.isDirectory())throw new Error(`${e} is not a directory`);(t.mode&63)!==0&&fs.chmodSync(e,448)}p(ensureHeapDir,"ensureHeapDir"),i(ensureHeapDir,"ensureHeapDir");function pruneHeapSnapshots(e,t,s=Date.now()){const a=[];let o;try{o=fs.readdirSync(e).filter(r=>r.endsWith(".heapsnapshot")).map(r=>{const n=path.join(e,r),h=fs.lstatSync(n);return h.isFile()?{file:n,mtime:h.mtimeMs}:void 0}).filter(r=>r!==void 0).sort((r,n)=>n.mtime-r.mtime)}catch{return a}return o.forEach((r,n)=>{if(n>=t.keep-1||s-r.mtime>t.maxAgeMs)try{fs.unlinkSync(r.file),a.push(r.file)}catch{}}),a}p(pruneHeapSnapshots,"pruneHeapSnapshots"),i(pruneHeapSnapshots,"pruneHeapSnapshots");function writeHeapSnapshot(e){const t=Date.now(),s=fs.constants.O_WRONLY|fs.constants.O_CREAT|fs.constants.O_EXCL|(fs.constants.O_NOFOLLOW??0),a=fs.openSync(e,s,384),o=new inspector.Session;let r=0,n;return new Promise((h,S)=>{const u=i(c=>{o.removeAllListeners("HeapProfiler.addHeapSnapshotChunk");try{o.disconnect()}catch{}try{fs.closeSync(a)}catch{}const l=c??n;if(l){try{fs.unlinkSync(e)}catch{}S(l);return}h({bytes:r,ms:Date.now()-t})},"finish");try{o.connect(),o.on("HeapProfiler.addHeapSnapshotChunk",c=>{if(!n)try{r+=fs.writeSync(a,c.params.chunk)}catch(l){n=l}}),o.post("HeapProfiler.takeHeapSnapshot",{reportProgress:!1},c=>u(c))}catch(c){u(c)}})}p(writeHeapSnapshot,"writeHeapSnapshot"),i(writeHeapSnapshot,"writeHeapSnapshot");
|
package/hot-swap-registries.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var m=Object.defineProperty;var l=(t,e)=>m(t,"name",{value:e,configurable:!0});var g=Object.defineProperty,o=l((t,e)=>g(t,"name",{value:e,configurable:!0}),"o");Object.defineProperty(exports,"__esModule",{value:!0}),exports.nestTypeormEntityRegistries=nestTypeormEntityRegistries,exports.typeormArgsRegistries=typeormArgsRegistries,exports.classValidatorRegistries=classValidatorRegistries,exports.classTransformerRegistries=classTransformerRegistries,exports.defaultRegistries=defaultRegistries,exports.captureRegistries=captureRegistries,exports.supersededSince=supersededSince,exports.pruneRegistries=pruneRegistries,exports.registryPruningEnabled=registryPruningEnabled,exports.describePrune=describePrune;const isClass=o(t=>typeof t=="function","isClass");function filterInPlace(t,e){const n=t.filter(e),a=t.length-n.length;return a>0&&t.splice(0,t.length,...n),a}l(filterInPlace,"filterInPlace"),o(filterInPlace,"filterInPlace");const NEST_TYPEORM_STORAGE=/[\\/]@nestjs[\\/]typeorm[\\/]dist[\\/]entities-metadata\.storage\.js$/;function nestTypeormEntityRegistries(t){const e=[];for(const[n,a]of Object.entries(t)){if(!a||!NEST_TYPEORM_STORAGE.test(n))continue;const s=a.exports?.EntitiesMetadataStorage?.storage;if(!(s instanceof Map))continue;const c=o(()=>[...s.values()].filter(f=>Array.isArray(f)),"lists");e.push({id:"@nestjs/typeorm entities",phase:"build",classes:o(()=>c().flat().filter(isClass),"classes"),prune:o(f=>c().reduce((r,d)=>r+filterInPlace(d,u=>!(isClass(u)&&f.has(u))),0),"prune")})}return e}l(nestTypeormEntityRegistries,"nestTypeormEntityRegistries"),o(nestTypeormEntityRegistries,"nestTypeormEntityRegistries");function typeormArgsRegistries(t){const e=t.typeormMetadataArgsStorage;if(!e||typeof e!="object")return[];const n=o(()=>Object.values(e).filter(s=>Array.isArray(s)),"lists"),a=o(s=>s&&typeof s=="object"?s.target:void 0,"targetOf");return[{id:"typeorm metadata",phase:"serve",classes:o(()=>n().flat().map(a).filter(isClass),"classes"),prune:o(s=>n().reduce((c,f)=>c+filterInPlace(f,r=>{const d=a(r);return!(isClass(d)&&s.has(d))}),0),"prune")}]}l(typeormArgsRegistries,"typeormArgsRegistries"),o(typeormArgsRegistries,"typeormArgsRegistries");const GENERIC_CONSTRAINT="CustomConstraint";function classValidatorRegistries(t){const e=t.classValidatorMetadataStorage;if(!e||typeof e!="object")return[];const{validationMetadatas:n,constraintMetadatas:a}=e;if(!(n instanceof Map))return[];const s=a instanceof Map?a:new Map,c=o(()=>[...s.keys()].filter(isClass).filter(r=>r.name!==GENERIC_CONSTRAINT),"namedConstraints"),f=o(r=>r&&typeof r=="object"?r.constraintCls:void 0,"constraintOf");return[{id:"class-validator metadata",phase:"serve",classes:o(()=>[...[...n.keys()].filter(isClass),...c()],"classes"),prune:o(r=>{let d=0;const u=new Set;for(const i of[...n.keys()]){if(!isClass(i)||!r.has(i))continue;const p=n.get(i);if(Array.isArray(p))for(const y of p)u.add(f(y));n.delete(i),d++}for(const i of c())r.has(i)&&s.delete(i)&&d++;if(u.size>0){for(const i of n.values())if(Array.isArray(i))for(const p of i)u.delete(f(p));for(const i of u)isClass(i)&&i.name===GENERIC_CONSTRAINT&&s.delete(i)&&d++}return d},"prune")}]}l(classValidatorRegistries,"classValidatorRegistries"),o(classValidatorRegistries,"classValidatorRegistries");const CLASS_TRANSFORMER_STORAGE=/[\\/]class-transformer[\\/]cjs[\\/]storage\.js$/,CLASS_TRANSFORMER_MAPS=["_typeMetadatas","_transformMetadatas","_exposeMetadatas","_excludeMetadatas"];function classTransformerRegistries(t){const e=[];for(const[n,a]of Object.entries(t)){if(!a||!CLASS_TRANSFORMER_STORAGE.test(n))continue;const s=a.exports?.defaultMetadataStorage;if(!s||typeof s!="object")continue;const c=CLASS_TRANSFORMER_MAPS.map(r=>s[r]).filter(r=>r instanceof Map);if(c.length===0)continue;const f=s._ancestorsMap;e.push({id:"class-transformer metadata",phase:"serve",classes:o(()=>c.flatMap(r=>[...r.keys()]).filter(isClass),"classes"),prune:o(r=>{let d=0;for(const u of c)for(const i of[...u.keys()])isClass(i)&&r.has(i)&&u.delete(i)&&d++;if(f instanceof Map)for(const[u,i]of[...f.entries()])(isClass(u)&&r.has(u)||Array.isArray(i)&&i.some(p=>isClass(p)&&r.has(p)))&&f.delete(u);return d},"prune")})}return e}l(classTransformerRegistries,"classTransformerRegistries"),o(classTransformerRegistries,"classTransformerRegistries");function defaultRegistries(t=require.cache,e=globalThis){return[...nestTypeormEntityRegistries(t),...typeormArgsRegistries(e),...classValidatorRegistries(e),...classTransformerRegistries(t)]}l(defaultRegistries,"defaultRegistries"),o(defaultRegistries,"defaultRegistries");function captureRegistries(t=defaultRegistries()){const e=new Map;for(const n of t){const a=e.get(n.id)??new Set;for(const s of n.classes())a.add(s);e.set(n.id,a)}return e}l(captureRegistries,"captureRegistries"),o(captureRegistries,"captureRegistries");function supersededSince(t,e=defaultRegistries()){const n=new Set;for(const[a,s]of captureRegistries(e)){const c=t.get(a)??new Set,f=new Set;for(const r of s)!c.has(r)&&r.name&&f.add(r.name);for(const r of c)r.name&&f.has(r.name)&&n.add(r)}return n}l(supersededSince,"supersededSince"),o(supersededSince,"supersededSince");function pruneRegistries(t,e,n=defaultRegistries()){if(t.size===0)return[];const a=[];for(const s of n){if(s.phase!==e)continue;const c=s.prune(t);c>0&&a.push({registry:s.id,removed:c})}return a}l(pruneRegistries,"pruneRegistries"),o(pruneRegistries,"pruneRegistries");function registryPruningEnabled(t=process.env){const e=(t.LENSMCP_SWAP_PRUNE_REGISTRIES??"").trim().toLowerCase();return!(e==="0"||e==="false"||e==="no"||e==="off")}l(registryPruningEnabled,"registryPruningEnabled"),o(registryPruningEnabled,"registryPruningEnabled");function describePrune(t,e){const n=t.reduce((s,c)=>s+c.removed,0);if(n===0)return null;const a=t.map(s=>`${s.registry} ${s.removed}`).join(", ");return`[child] released ${n} superseded class registration(s) ${e} (${a})`}l(describePrune,"describePrune"),o(describePrune,"describePrune");
|
package/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var p=Object.defineProperty;var c=(r,t)=>p(r,"name",{value:t,configurable:!0});var n=Object.defineProperty,e=c((r,t)=>n(r,"name",{value:t,configurable:!0}),"e");Object.defineProperty(exports,"__esModule",{value:!0}),exports.ForkTsCheckReporterPlugin=exports.resolveEventFile=exports.publishTypecheckRun=exports.publishTypecheckDiagnostics=exports.parseTscOutput=exports.parseTscDiagnosticLine=exports.buildTypecheckRunEvents=exports.appendTypecheckEvents=exports.createProdWebpackConfig=exports.createDevWebpackConfig=exports.buildScopePatterns=void 0;var build_scope_patterns_1=require("./build-scope-patterns");Object.defineProperty(exports,"buildScopePatterns",{enumerable:!0,get:e(function(){return build_scope_patterns_1.buildScopePatterns},"get")});var create_webpack_dev_1=require("./create-webpack-dev");Object.defineProperty(exports,"createDevWebpackConfig",{enumerable:!0,get:e(function(){return create_webpack_dev_1.createDevWebpackConfig},"get")});var create_webpack_prod_1=require("./create-webpack-prod");Object.defineProperty(exports,"createProdWebpackConfig",{enumerable:!0,get:e(function(){return create_webpack_prod_1.createProdWebpackConfig},"get")});var typecheck_bus_1=require("./typecheck-bus");Object.defineProperty(exports,"appendTypecheckEvents",{enumerable:!0,get:e(function(){return typecheck_bus_1.appendTypecheckEvents},"get")}),Object.defineProperty(exports,"buildTypecheckRunEvents",{enumerable:!0,get:e(function(){return typecheck_bus_1.buildTypecheckRunEvents},"get")}),Object.defineProperty(exports,"parseTscDiagnosticLine",{enumerable:!0,get:e(function(){return typecheck_bus_1.parseTscDiagnosticLine},"get")}),Object.defineProperty(exports,"parseTscOutput",{enumerable:!0,get:e(function(){return typecheck_bus_1.parseTscOutput},"get")}),Object.defineProperty(exports,"publishTypecheckDiagnostics",{enumerable:!0,get:e(function(){return typecheck_bus_1.publishTypecheckDiagnostics},"get")}),Object.defineProperty(exports,"publishTypecheckRun",{enumerable:!0,get:e(function(){return typecheck_bus_1.publishTypecheckRun},"get")}),Object.defineProperty(exports,"resolveEventFile",{enumerable:!0,get:e(function(){return typecheck_bus_1.resolveEventFile},"get")});var fork_ts_check_reporter_1=require("./fork-ts-check-reporter");Object.defineProperty(exports,"ForkTsCheckReporterPlugin",{enumerable:!0,get:e(function(){return fork_ts_check_reporter_1.ForkTsCheckReporterPlugin},"get")});
|
package/inspector-secret.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var o=Object.defineProperty;var t=(r,e)=>o(r,"name",{value:e,configurable:!0});var n=Object.defineProperty,s=t((r,e)=>n(r,"name",{value:e,configurable:!0}),"s");Object.defineProperty(exports,"__esModule",{value:!0}),exports.redactInspectorUrls=redactInspectorUrls,exports.streamMayCarrySecrets=streamMayCarrySecrets,exports.forStream=forStream,exports.inspectorPublishExecArgv=inspectorPublishExecArgv,exports.inspectorPortOf=inspectorPortOf;const INSPECTOR_TOKEN_RE=/((?:wss?:\/\/[^\s/]+\/|ws=[^\s/]+\/))([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})/gi;function redactInspectorUrls(r){return r.replace(INSPECTOR_TOKEN_RE,"$1<inspector-token-redacted>")}t(redactInspectorUrls,"redactInspectorUrls"),s(redactInspectorUrls,"redactInspectorUrls");function streamMayCarrySecrets(r,e){return!e&&r.isTTY===!0}t(streamMayCarrySecrets,"streamMayCarrySecrets"),s(streamMayCarrySecrets,"streamMayCarrySecrets");function forStream(r,e,c){return streamMayCarrySecrets(r,e)?c:redactInspectorUrls(c)}t(forStream,"forStream"),s(forStream,"forStream");function inspectorPublishExecArgv(r){return r?[]:["--inspect-publish-uid=stderr"]}t(inspectorPublishExecArgv,"inspectorPublishExecArgv"),s(inspectorPublishExecArgv,"inspectorPublishExecArgv");function inspectorPortOf(r){const e=/^wss?:\/\/[^/]*?:(\d+)\//.exec(r??""),c=e?Number(e[1]):NaN;return Number.isInteger(c)&&c>0?c:null}t(inspectorPortOf,"inspectorPortOf"),s(inspectorPortOf,"inspectorPortOf");
|
package/main.devserver.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var lt=Object.defineProperty;var h=(c,f)=>lt(c,"name",{value:f,configurable:!0});var at=Object.defineProperty,a=h((c,f)=>at(c,"name",{value:f,configurable:!0}),"a");Object.defineProperty(exports,"__esModule",{value:!0}),exports.redactInspectorUrls=exports.inspectorPortOf=exports.DEBUG_FIXED_PORTS_ENV=exports.mayDriveThePool=exports.isOwnerOnlyTransport=exports.gatewayManaged=void 0,exports.tell=tell,exports.usesFixedInspectorPorts=usesFixedInspectorPorts,exports.inspectorPortFor=inspectorPortFor;const tslib_1=require("tslib"),path=tslib_1.__importStar(require("node:path")),fs=tslib_1.__importStar(require("node:fs")),os=tslib_1.__importStar(require("node:os")),node_child_process_1=require("node:child_process"),http=tslib_1.__importStar(require("node:http")),readline=tslib_1.__importStar(require("node:readline")),inspector=tslib_1.__importStar(require("node:inspector")),util=tslib_1.__importStar(require("node:util")),v8=tslib_1.__importStar(require("node:v8")),exit_reason_1=require("./exit-reason"),hot_swap_registries_1=require("./hot-swap-registries"),process_name_1=require("./process-name"),inspector_secret_1=require("./inspector-secret");Object.defineProperty(exports,"inspectorPortOf",{enumerable:!0,get:a(function(){return inspector_secret_1.inspectorPortOf},"get")}),Object.defineProperty(exports,"redactInspectorUrls",{enumerable:!0,get:a(function(){return inspector_secret_1.redactInspectorUrls},"get")});const devserver_transport_1=require("./devserver-transport");Object.defineProperty(exports,"gatewayManaged",{enumerable:!0,get:a(function(){return devserver_transport_1.gatewayManaged},"get")}),Object.defineProperty(exports,"isOwnerOnlyTransport",{enumerable:!0,get:a(function(){return devserver_transport_1.isOwnerOnlyTransport},"get")}),Object.defineProperty(exports,"mayDriveThePool",{enumerable:!0,get:a(function(){return devserver_transport_1.mayDriveThePool},"get")});const schema_first_instance_1=require("./schema-first-instance"),redis_disconnect_fix_1=require("./redis-disconnect-fix"),error_stack_release_1=require("./error-stack-release"),swap_recycle_1=require("./swap-recycle"),swap_mode_1=require("./swap-mode"),handoff_retire_1=require("./handoff-retire"),gc_notice_1=require("./gc-notice"),pod_sock_1=require("./pod-sock"),notice_generation_1=require("./notice-generation"),service_build_events_1=require("./service-build-events"),stdio_guard_1=require("./stdio-guard"),bundle_parent_1=require("./bundle-parent"),checkout_cache_1=require("./checkout-cache"),dev_devtool_1=require("./dev-devtool"),pod_memory_1=require("./pod-memory"),pod_memory_events_1=require("./pod-memory-events"),heap_snapshot_1=require("./heap-snapshot"),httpProxy=require("http-proxy"),{prettyFactory}=require("pino-pretty"),BUNDLE_PATH=process.env.BUNDLE_PATH?.trim()||"./main.js",SERVICE_NAME=process.env.SERVICE_NAME||"",SERVICE_PREFIX=process.env.SERVE_PREFIX?`/${process.env.SERVE_PREFIX}`:"",GATEWAY_MIDDLEWARE_PATH=process.env.GATEWAY_MIDDLEWARE||"",GATEWAY_CONFIG=(()=>{const c=process.env.GATEWAY_CONFIG;if(!c)return{};try{return JSON.parse(c)}catch{return{}}})();let gatewayMiddleware=null;if(GATEWAY_MIDDLEWARE_PATH)try{const c=require(GATEWAY_MIDDLEWARE_PATH);gatewayMiddleware=typeof c=="function"?c:typeof c.default=="function"?c.default:null,gatewayMiddleware||console.warn(`[gateway] ${GATEWAY_MIDDLEWARE_PATH} does not export a function, gateway disabled`)}catch(c){console.error(`[gateway] Failed to load middleware from ${GATEWAY_MIDDLEWARE_PATH}:`,c)}function applyGatewayMiddleware(c){if(gatewayMiddleware)try{gatewayMiddleware(c,GATEWAY_CONFIG)}catch(f){console.error("[gateway] Middleware error:",f)}}h(applyGatewayMiddleware,"applyGatewayMiddleware"),a(applyGatewayMiddleware,"applyGatewayMiddleware");const GATEWAY_ROUTES=(()=>{try{return JSON.parse(process.env.GATEWAY_ROUTES||"[]")}catch{return[]}})(),GATEWAY_HTTPS=process.env.GATEWAY_HTTPS==="1";function hostMatches(c,f){if(c.startsWith("*.")){const g=c.slice(1);return f.endsWith(g)||f===c.slice(2)}return f===c}h(hostMatches,"hostMatches"),a(hostMatches,"hostMatches");function matchGatewayRoute(c){if(GATEWAY_ROUTES.length===0)return;const f=(c.headers.host||"").split(":")[0],g=c.url||"/";for(const E of GATEWAY_ROUTES)if(!(E.host&&!hostMatches(E.host,f))&&!(E.prefix&&!g.startsWith(E.prefix)))return E}h(matchGatewayRoute,"matchGatewayRoute"),a(matchGatewayRoute,"matchGatewayRoute");const WORKER_NAMES=(()=>{try{return JSON.parse(process.env.WORKERS||"[]")}catch{return[]}})(),LENSMCP_WS_KEY=process.env.LENSMCP_WS_KEY||"",SOCK_NS=process.env.LENSMCP_SOCK_NS||LENSMCP_WS_KEY,SOCK_DIR=SOCK_NS?path.join(os.tmpdir(),SOCK_NS,`${SERVICE_NAME||"lensmcp-cluster"}-devserver`):path.join(os.tmpdir(),`${SERVICE_NAME||"lensmcp-cluster"}-devserver`),SOCKET_ONLY=process.env.LENSMCP_SOCKET_ONLY==="1",POD_GENERATION=(()=>{const c=Number(process.env.LENSMCP_POD_GENERATION);return Number.isFinite(c)&&c>1?Math.floor(c):1})();function childSockPath(c){return path.join(SOCK_DIR,(0,pod_sock_1.podSockName)(c,POD_GENERATION))}h(childSockPath,"childSockPath"),a(childSockPath,"childSockPath");function sockOwnerPath(c){return`${c}.owner`}h(sockOwnerPath,"sockOwnerPath"),a(sockOwnerPath,"sockOwnerPath");function sockRetiringPath(c){return`${c}.retiring`}h(sockRetiringPath,"sockRetiringPath"),a(sockRetiringPath,"sockRetiringPath");function tell(c,f){if(!c.connected||typeof c.send!="function")return!1;try{return c.send(f,()=>{})}catch{return!1}}h(tell,"tell"),a(tell,"tell");function refusePoolCommand(c,f){console.warn(`[devserver] refused ${c.method} ${c.url} on the public port \u2014 under a gateway the pool is driven on the control socket only.`),f.writeHead(404,{"content-type":"application/json"}),f.end(JSON.stringify({error:"not found"}))}h(refusePoolCommand,"refusePoolCommand"),a(refusePoolCommand,"refusePoolCommand"),exports.DEBUG_FIXED_PORTS_ENV="LENSMCP_DEBUG_FIXED_PORTS";function usesFixedInspectorPorts(c=process.env){const f=(c[exports.DEBUG_FIXED_PORTS_ENV]??"").trim().toLowerCase();return f==="1"||f==="true"||f==="yes"||f==="on"}h(usesFixedInspectorPorts,"usesFixedInspectorPorts"),a(usesFixedInspectorPorts,"usesFixedInspectorPorts");function inspectorPortFor(c,f,g=process.env){if(!usesFixedInspectorPorts(g))return 0;const E=Math.trunc(c)+Math.trunc(f);return Number.isInteger(E)&&E>1024&&E<=65535?E:0}h(inspectorPortFor,"inspectorPortFor"),a(inspectorPortFor,"inspectorPortFor");function ensureOwnerOnlyDir(c){try{fs.mkdirSync(c,{recursive:!0,mode:448})}catch{}try{const f=fs.lstatSync(c);f.isDirectory()&&(f.mode&63)!==0&&fs.chmodSync(c,448)}catch{}}h(ensureOwnerOnlyDir,"ensureOwnerOnlyDir"),a(ensureOwnerOnlyDir,"ensureOwnerOnlyDir");function claimSock(c,f=process.pid){ensureOwnerOnlyDir(path.dirname(c));try{const g=sockOwnerPath(c);try{fs.unlinkSync(g)}catch{}fs.writeFileSync(g,String(f),{flag:"wx",mode:384})}catch{}try{fs.unlinkSync(c)}catch{}try{fs.unlinkSync(sockRetiringPath(c))}catch{}}h(claimSock,"claimSock"),a(claimSock,"claimSock");function sockOwnedByAnother(c,f=process.pid){try{const g=fs.readFileSync(sockOwnerPath(c),"utf8").trim();return!!g&&g!==String(f)}catch{return!1}}h(sockOwnedByAnother,"sockOwnedByAnother"),a(sockOwnedByAnother,"sockOwnedByAnother");function cleanupSock(c,f=process.pid){if(c){try{const g=fs.readFileSync(sockOwnerPath(c),"utf8").trim();if(g&&g!==String(f))return}catch{}try{fs.unlinkSync(c)}catch{}try{fs.unlinkSync(sockOwnerPath(c))}catch{}try{fs.unlinkSync(sockRetiringPath(c))}catch{}(0,gc_notice_1.clearGcNotice)(c)}}h(cleanupSock,"cleanupSock"),a(cleanupSock,"cleanupSock");function postRetiringNotice(c,f){if(!(!c||!f)){try{const g=fs.readFileSync(sockOwnerPath(c),"utf8").trim();if(g&&g!==String(f))return}catch{}try{fs.writeFileSync(sockRetiringPath(c),String(f),{flag:"w",mode:384})}catch{}}}h(postRetiringNotice,"postRetiringNotice"),a(postRetiringNotice,"postRetiringNotice");function serviceKeyFingerprint(){const c=process.env.LENSMCP_SERVICE_KEY;if(!c)return;const{createHash:f}=require("node:crypto");return f("sha256").update(c).digest("hex").slice(0,8)}h(serviceKeyFingerprint,"serviceKeyFingerprint"),a(serviceKeyFingerprint,"serviceKeyFingerprint");function rootModuleOf(c){let f;for(const g of c.getModules?.()?.values()??[])typeof g?.metatype!="function"||typeof g.distance!="number"||!Number.isFinite(g.distance)||(!f||g.distance<f.distance)&&(f=g);return f?.metatype}h(rootModuleOf,"rootModuleOf"),a(rootModuleOf,"rootModuleOf");let lastImportedModule;function takeImportedModule(){const c=lastImportedModule;return lastImportedModule=void 0,c}h(takeImportedModule,"takeImportedModule"),a(takeImportedModule,"takeImportedModule");async function importFresh(spec){process.env.DEVSERVER_MODE="1";const requested=path.isAbsolute(spec)?spec:path.join(__dirname,spec);let resolved=requested;try{resolved=fs.realpathSync(requested)}catch{}eval(`(() => {
|
|
2
2
|
const key = ${JSON.stringify(resolved)};
|
|
3
3
|
const previous = require.cache[key];
|
|
4
4
|
delete require.cache[key]; // delete from CJS cache
|
|
@@ -9,15 +9,15 @@
|
|
|
9
9
|
const at = owner && Array.isArray(owner.children) ? owner.children.indexOf(previous) : -1;
|
|
10
10
|
if (at >= 0) owner.children.splice(at, 1);
|
|
11
11
|
}
|
|
12
|
-
})()`),(0,bundle_parent_1.routeBundleRequires)(requested,resolved);const exports=eval(`require(${JSON.stringify(resolved)})`);try{const mod=eval("require.cache")[resolved];lastImportedModule=mod&&typeof mod=="object"?mod:void 0}catch{}return exports}y(importFresh,"importFresh"),_(importFresh,"importFresh"),i(importFresh,"importFresh");function debounce(a,h){let g=null;return(...v)=>{g&&clearTimeout(g),g=setTimeout(()=>a(...v),h)}}if(y(debounce,"debounce"),_(debounce,"debounce"),i(debounce,"debounce"),process.env.APP_RUNNER==="1"){(0,stdio_guard_1.guardBrokenStdio)();const a=i(g=>{if(!inspector.url())try{inspector.open(g,"127.0.0.1",!1)}catch(U){console.warn(`[child] inspector.open(${g}) failed (port taken by another devserver?) \u2014 falling back to a random port:`,U.message);try{inspector.open(0,"127.0.0.1",!1)}catch{}}const v=inspector.url();v&&tell(process,{type:"inspector-url",url:v})},"openInspector"),h=process.env.CHILD_DEBUG_PORT;if(h!==void 0&&h!==""){const g=Number(h);Number.isInteger(g)&&(g===0||g>1024)&&a(g)}try{require("@lensmcp/node-instrumentation/register")}catch{}(async()=>{let g=null,v=!1,U,se=!1;const Fe=(0,hot_swap_registries_1.registryPruningEnabled)(),fe=i((t,n)=>{const c=(0,hot_swap_registries_1.describePrune)(t,n);c&&console.log(c)},"logPrune");let j={app:null,handler:i((t,n)=>{n.statusCode=503,n.end("starting")},"handler"),inflight:0};const _e=(()=>{const t=Number(process.env.LENSMCP_SWAP_DRAIN_MS);return Number.isFinite(t)&&t>=0?t:15*6e4})(),O=i(t=>{const n=globalThis.__lensmcpActiveWork;if(typeof n!="function")return{count:0};try{const c=n(t);return{count:Number(c?.count??0),...c?.oldestStartedAt?{oldestStartedAt:c.oldestStartedAt}:{}}}catch{return{count:0}}},"activeWork"),Pe=i(t=>{const n=globalThis.__lensmcpStopWorkIntake;if(typeof n=="function")try{return n(t)}catch{return}},"stopWorkIntake"),ge=i(t=>{const n=globalThis.__lensmcpWorkIntakeReport;if(!(t===void 0||typeof n!="function"))try{return n(t)??void 0}catch{return}},"workIntakeReport"),Se=(()=>{const t=Number(process.env.LENSMCP_SWAP_MAX_DRAINING);return Number.isFinite(t)&&t>=1?Math.floor(t):1})(),L=new Set,te=(()=>{const t=Number(process.env.LENSMCP_SWAP_EARLY_CLOSE_GRACE_MS);return process.env.LENSMCP_SWAP_EARLY_CLOSE_GRACE_MS!==void 0&&process.env.LENSMCP_SWAP_EARLY_CLOSE_GRACE_MS!==""&&Number.isFinite(t)&&t>=0?t:3e4})(),X=i(t=>{if(!t.abandoned?.size)return 0;const n=Date.now();for(const[c,p]of t.abandoned)(c.writableEnded||n-p>=te)&&t.abandoned.delete(c);return t.abandoned.size},"abandonedRunning"),ie=i(t=>{let n=0;for(const c of t.open??[])c.headersSent||(n+=1);return{unanswered:n+X(t),streams:Math.max(0,t.inflight-n),work:O(t.workGen).count}},"owedBy"),ae=i((t,n,c=`${n}s`)=>`${t} ${t===1?n:c}`,"plural");async function Ne(){if(te<=0)return;const t=Date.now();let n=!1;for(;!(L.size<Se);){const c=L.values().next().value;if(!c||c.closed)break;const p=ie(c);if(p.unanswered===0&&p.work===0)break;const w=(c.drainingSince??t)+te-Date.now();if(w<=0)break;n||(n=!0,console.log(`[child] swap held \u2014 the app replaced ${Math.round((Date.now()-(c.drainingSince??t))/100)/10}s ago is still `+[p.unanswered?`answering ${ae(p.unanswered,"request")}`:"",p.work?`running ${ae(p.work,"background job")}`:""].filter(Boolean).join(" and ")+`, and this pod keeps at most ${Se} replaced app(s) alive (LENSMCP_SWAP_MAX_DRAINING). The new build is applied when it is done \u2014 in ${Math.ceil(w/1e3)}s at the latest (LENSMCP_SWAP_EARLY_CLOSE_GRACE_MS).`)),await new Promise(S=>{setTimeout(S,Math.min(100,w)).unref?.()})}n&&console.log(`[child] swap resumed after ${Date.now()-t}ms`)}y(Ne,"$e"),_(Ne,"xe"),i(Ne,"holdForOwedWork");const T=(0,swap_recycle_1.swapRecyclePolicy)();let ye,ce=0;const We=(()=>{const t=Number(process.env.LENSMCP_POD_RETIRE_NOTICE_MS);return Number.isFinite(t)&&t>=0?t:3500})();let f=!1,k=!1;const b=(0,pod_memory_1.podMemoryPolicy)();let K=0;const I=new Set;let me=!1;const H=i(()=>{if(!me)return;let t=0;for(const n of I)n.deref()===void 0?I.delete(n):t+=1;return t},"liveContainers"),P=(0,pod_memory_1.createPodMemoryMonitor)({policy:b,state:i(()=>({gen:j.gen??0,swaps:ce,...ye===void 0?{}:{baseline:ye},busy:v||se||C.size>0,lastBusyAt:z}),"state"),send:i(t=>{tell(process,t)},"send"),containers:H,counter:(0,pod_memory_1.createLiveObjectCounter)(path.isAbsolute(BUNDLE_PATH)?BUNDLE_PATH:path.join(__dirname,BUNDLE_PATH)),onRetained:i(()=>pe(),"onRetained"),gc:i(()=>(0,gc_notice_1.withGcNotice)(M,pod_memory_1.fullGc),"gc")}),F=i(()=>((0,gc_notice_1.withGcNotice)(M,pod_memory_1.fullGc)&&P.tracker.noteGc(),process.memoryUsage().heapUsed),"liveHeap"),W=(()=>{if(!(0,error_stack_release_1.errorFrameReleaseEnabled)())return null;try{const t=path.dirname(path.isAbsolute(BUNDLE_PATH)?BUNDLE_PATH:path.join(__dirname,BUNDLE_PATH))+path.sep,n=`${path.sep}node_modules${path.sep}`,c=new Set(Object.keys(require.cache));return(0,error_stack_release_1.createErrorFrameReleaser)(require.cache,{skip:i(p=>c.has(p)||p.startsWith(t)&&!p.slice(t.length).includes(n)&&!p.slice(t.length).startsWith(`node_modules${path.sep}`),"skip")})}catch{return null}})();let ve=!1;function be(){if(!(!W||ve))try{const t=W();t.errors>0&&console.log(`[child] read the stack of ${t.errors} Error object(s) that libraries created while loading and keep for good \u2014 unread, each held the functions that were on its stack, this bundle's included`)}catch(t){console.error("[child] could not release library error frames:",t),ve=!0}}y(be,"be"),_(be,"Ne"),i(be,"releaseLibraryErrorFrames");const C=new Map;let z=Date.now();const le=i(()=>T.settleMs<=0||!v&&!se&&C.size===0&&Date.now()-z>=T.settleMs,"settled");let Q;function re(t){if(!(!T.enabled||f||k)){if(T.settleMs<=0){Z(t);return}Q&&clearTimeout(Q),Q=setTimeout(()=>{Q=void 0,le()?Z(t):re(t)},T.settleMs),Q.unref?.()}}y(re,"ie"),_(re,"de"),i(re,"recycleCheckWhenSettled");const Ce=i(()=>{if(T.stuckCloseMs<=0)return 0;const t=Date.now();let n=0;for(const c of C.values())t-c>=T.stuckCloseMs&&(n+=1);return n},"stuckCloses");function Z(t){if(!T.enabled||f||k||!process.send)return;const n=v8.getHeapStatistics().heap_size_limit,c=i(w=>{const S=P.oldestRetained();return{swaps:ce,usedBytes:w,limitBytes:n,stuckCloses:Ce(),settled:le(),...ye===void 0?{}:{baselineBytes:ye},...S?{retained:{generation:S.gen,ageMs:Date.now()-S.closedAt,gcs:S.gcs}}:{}}},"state");if(!(0,swap_recycle_1.recycleReason)(T,c(process.memoryUsage().heapUsed)))return;const p=(0,swap_recycle_1.recycleReason)(T,c(F()));p&&(f=!0,console.log(`[child] asking for a fresh pod ${t} \u2014 ${p}. This pod keeps serving until its successor is ready. Size the bound with LENSMCP_SWAP_RECYCLE_HEAP_FACTOR / _HEAP_RATIO / _MIN_MB / _RETAINED_MS, or turn it off with LENSMCP_SWAP_RECYCLE=0.`),tell(process,{type:"recycle-request",reason:p}))}y(Z,"ee"),_(Z,"oe"),i(Z,"considerRecycle");let de;function pe(){if(!T.enabled||T.retainedMs<=0||f||k)return;const t=P.oldestRetained();if(!t)return;const n=t.closedAt+T.retainedMs-Date.now();if(n<=0){Z("with a closed generation still in memory");return}de||(de=setTimeout(()=>{de=void 0,P.measure("retention-check").catch(()=>{})},n),de.unref?.())}y(pe,"we"),_(pe,"Oe"),i(pe,"retainedRecycleCheck");function oe(t,n){const c={};n&&(c.module=n),t&&(c.app=t);try{const p=t?.app;if(p&&typeof p=="object"&&(c.nestApp=p,p.container&&typeof p.container=="object")){c.container=p.container;const w=rootModuleOf(p.container);w&&(c.rootModule=w)}}catch{}return c}y(oe,"_e"),_(oe,"we"),i(oe,"generationTargets");async function q(t,n){if(t.closed||(t.closed=!0,L.delete(t),n&&console.error(`[child] ${n}`),!t.app))return;C.set(t,Date.now());const c=T.enabled&&T.stuckCloseMs>0?setTimeout(()=>{C.has(t)&&(console.error(`[child] a previous app has been closing for ${Math.round(T.stuckCloseMs/1e3)}s and its close() has not returned \u2014 one of its shutdown hooks is waiting on something that does not end (a queue worker, a connection, a stream). It stays in memory until this pod is replaced.`),Z("with a previous app stuck in close()"))},T.stuckCloseMs):void 0;c?.unref?.();const p=t.app;try{await t.app.close()}catch(w){console.error("[child] error closing a previous app:",w)}finally{C.delete(t),z=Date.now(),c&&clearTimeout(c),t.app=null,t.abandoned=void 0,t.handler=(w,S)=>{S.statusCode=503,S.end("closed")},t.gen!==void 0&&P.closed(t.gen,ce,oe(p,t.module)),t.module=void 0}if(t.superseded){try{fe((0,hot_swap_registries_1.pruneRegistries)(t.superseded,"serve"),"after closing the previous app")}catch(w){console.error("[child] could not release the previous app's class registrations:",w)}t.superseded=void 0}re("after closing the previous app")}y(q,"V"),_(q,"ne"),i(q,"closeGeneration");async function we(t){const n=Date.now();t.drainingSince=n;const c=i(()=>({inflight:t.inflight+X(t),work:O(t.workGen).count}),"busy"),p=c();if(p.inflight>0||p.work>0){for(;L.size>=Se;){const $=L.values().next().value;if(!$)break;const A=ie($),ne=Math.round((Date.now()-($.drainingSince??n))/1e3);if(A.unanswered===0&&A.streams===0&&A.work===0){await q($);continue}await q($,`closing a still-draining generation early \u2014 ${L.size} were pending and the cap is ${Se} (each holds a whole app: DI container, DB pool, queue workers). `+(A.unanswered>0||A.work>0?`It was replaced ${ne}s ago and had still not answered ${ae(A.unanswered,"request")}`+(A.work?` or finished ${ae(A.work,"background job")}`:"")+` \u2014 those fail now (a queue job keeps its lock until the TTL lapses). Raise LENSMCP_SWAP_EARLY_CLOSE_GRACE_MS (currently ${te}ms) to wait longer for them. `:`It held only ${ae(A.streams,"open stream")}; their clients reconnect to the new app. `)+"Raise LENSMCP_SWAP_MAX_DRAINING if this pod legitimately needs more.")}L.add(t)}for(;_e>0&&Date.now()-n<_e;){if(t.closed)return;const $=c();if($.inflight===0&&$.work===0)break;await new Promise(A=>{setTimeout(A,250).unref?.()})}if(t.closed)return;const w=c(),S=ge(t.workGen);w.inflight>0||w.work>0?console.error(`[child] swap drain expired after ${Date.now()-n}ms \u2014 closing the previous app with ${w.inflight} in-flight request(s) and ${w.work} background job(s) still running. `+(S?`Previous app still processing ${S.running} queue job(s); ${S.takenAfterStop} were taken after the swap. `:"")+`A queue job killed here keeps its lock until the TTL lapses. Raise LENSMCP_SWAP_DRAIN_MS (currently ${_e}ms) if this is legitimate work.`):(Date.now()-n>250||S?.runningAtStop||S?.takenAfterStop)&&console.log(`[child] previous app drained in ${Date.now()-n}ms \u2014 closing it`+(S?` (it finished ${S.finishedAfterStop} queue job(s) after the swap; ${S.takenAfterStop} were taken after the swap)`:"")),await q(t)}y(we,"ke"),_(we,"Le"),i(we,"drainThenClose");async function Y(){if(v)return se=!0,console.log("[child] Reload deferred \u2014 will re-swap after current swap completes"),g;v=!0,z=Date.now(),await Ne(),process.removeAllListeners("uncaughtException"),process.removeAllListeners("unhandledRejection"),process.on("uncaughtException",(N,J)=>{console.error(`[child] uncaughtException (${J}):`,N)}),process.on("unhandledRejection",N=>{const J=N instanceof Error?N.stack||N.message:String(N);J.includes("FronteggContextScope")||J.includes("populateLoggerMetadata")||console.error("[child] unhandledRejection:",N)});let t;if(Fe)try{t=(0,hot_swap_registries_1.captureRegistries)()}catch{t=void 0}const n=global.__lensmcpBeginWorkGeneration,c=typeof n=="function"?n():void 0;try{try{await importFresh(BUNDLE_PATH)}catch(N){if(!(N instanceof SyntaxError))throw N;console.warn(`[child] bundle was unreadable mid-write (${N.message}) \u2014 retrying the swap once`),await new Promise(J=>setTimeout(J,400)),await importFresh(BUNDLE_PATH)}}catch(N){throw v=!1,z=Date.now(),N}if(typeof global.createChildApp!="function")throw v=!1,z=Date.now(),new Error(`Bundle '${BUNDLE_PATH}' does not export createChildApp() and the zero-touch bridge is not active. Either install @lensmcp/node-instrumentation (a plain NestFactory.create + app.listen main.ts then just works) or set global.createChildApp in main.ts when DEVSERVER_MODE === '1'.`);let p;if(t)try{p=(0,hot_swap_registries_1.supersededSince)(t),fe((0,hot_swap_registries_1.pruneRegistries)(p,"build"),"at the swap")}catch(N){console.error("[child] could not release superseded class registrations:",N)}let w;try{w=await global.createChildApp()}catch(N){throw v=!1,z=Date.now(),takeImportedModule(),N}const S=j;p?.size&&(S.app?S.superseded=p:fe((0,hot_swap_registries_1.pruneRegistries)(p,"serve"),"at the swap")),g=w;const $=takeImportedModule();j={app:w,handler:w.handler,inflight:0,gen:++K,...$?{module:$}:{},...c===void 0?{}:{workGen:c}};const A=oe(w,void 0).container;A&&(I.add(new WeakRef(A)),me=!0);const ne=S.app&&c!==void 0?Pe(c):void 0;return console.log("[child] Swapped to fresh app (previous draining in background)"+(ne?.workers?`; its ${ne.workers} queue worker(s) stopped taking new jobs, previous app still processing ${ne.runningAtStop} job(s)`:"")),be(),S.app&&(ce+=1,we(S).catch(N=>console.error("[child] background close error:",N)),setTimeout(()=>Z("30s after a hot swap"),3e4).unref?.(),P.swapped(S.gen,()=>S.closed===!0&&!C.has(S))),v=!1,z=Date.now(),se?(se=!1,Y()):w}y(Y,"J"),_(Y,"q"),i(Y,"swapNow");const Ue=debounce(async()=>{try{console.log("[child] /webpack/reload"),await Y()}catch(t){console.error("[child] reload failed:",t)}},250),B=http.createServer((t,n)=>{if(t.method==="POST"&&t.url==="/webpack/reload"){n.writeHead(200,{"content-type":"application/json"}),n.end(JSON.stringify({ok:!0})),Ue();return}if(t.method==="GET"&&t.url==="/__lensmcp/alive"){const p=t.headers["x-internal-token"],w=process.env.LENSMCP_SERVICE_KEY;if(w&&p!==w){n.writeHead(404,{"content-type":"text/plain"}),n.end("not found");return}const S=O();n.writeHead(200,{"content-type":"application/json","cache-control":"no-store"}),n.end(JSON.stringify({ok:!0,pid:process.pid,swapping:v,inflight:j.inflight,oldestInflightAt:j.oldestAt,activeWork:S.count,oldestWorkAt:S.oldestStartedAt,keyFingerprint:serviceKeyFingerprint(),...U?{watcher:U}:{},...Number.isFinite(Number(process.env.LENSMCP_POD_GENERATION))&&process.env.LENSMCP_POD_GENERATION?{podGeneration:Number(process.env.LENSMCP_POD_GENERATION)}:{}}));return}const c=j;c.inflight+=1,(c.open??=new Set).add(n),c.oldestAt===void 0&&(c.oldestAt=Date.now()),n.on("close",()=>{c.inflight-=1,c.open?.delete(n),te>0&&!c.closed&&!n.headersSent&&!n.writableEnded&&((c.abandoned??=new Map).set(n,Date.now()),c.abandoned.size>256&&X(c)),c.inflight===0&&(c.oldestAt=void 0),P.activity()}),c.handler(t,n)});B.keepAliveTimeout=0;const M=process.env.CHILD_SOCK_PATH;process.on("disconnect",()=>{cleanupSock(M),process.exit(0)});try{const t=path.isAbsolute(BUNDLE_PATH)?BUNDLE_PATH:path.join(__dirname,BUNDLE_PATH);if((0,schema_first_instance_1.schemaPrewarmEnabled)())try{const n=(0,schema_first_instance_1.prewarmZodFor)(t);n?.created&&console.log(`[child] zod${n.version?` ${n.version}`:""}: built ${n.created} throwaway schemas first, so none of the bundle's own is the first of its class`)}catch{}if((0,redis_disconnect_fix_1.redisDisconnectFixEnabled)())try{const n=(0,redis_disconnect_fix_1.finishStrandedDisconnectsFor)(t);n?.patched&&console.log(`[child] ioredis${n.versions.length?` ${n.versions.join(", ")}`:""}: a disconnect() between reconnect attempts now ends the client \u2014 it used to leave a queue worker's close() waiting for good`)}catch{}await Y(),ye=(await P.booted()).live,console.log(`[child] Using bundle: ${t}`),claimSock(M),B.listen(M,()=>{console.log(`[child] Listening on ${M}`),tell(process,{type:"ready",socketPath:M})})}catch(t){console.error("[child] Startup error:",t),tell(process,{type:"boot-error",error:String(t?.stack||t)}),process.exitCode=1;return}process.on("message",async t=>{if(!(!t||typeof t!="object")){if(t.type==="debug-open"){const n=Number(t.port);a(Number.isInteger(n)&&n>1024?n:0);return}if(t.type==="watcher"){const n=t.testimony;n&&typeof n=="object"&&(U=n);return}if(t.type==="heap-snapshot"){V(t);return}if(t.type==="recycle-declined"){f=!1;return}if(t.type==="retire"){ue();return}if(t.type==="reload"){if(k)return;try{const n=Date.now();await Y(),tell(process,{type:"reloaded",socketPath:M,swap:{generation:K,swaps:ce,swapMs:Date.now()-n,draining:L.size}})}catch(n){console.error("[child] reload error:",n),tell(process,{type:"reload-error",error:String(n?.stack||n)})}}}});let Ee=!1;async function V(t){const n=i(c=>{tell(process,{type:"heap-snapshot-result",id:t.id,...c})},"reply");if(Ee)return n({ok:!1,refused:"a snapshot of this pod is already being written"});Ee=!0;try{const c=F(),p=P.tracker.views().map(A=>A.gen),w=(0,heap_snapshot_1.heapSnapshotPolicy)();t.maxHeapBytes&&(w.maxHeapBytes=t.maxHeapBytes);const S=(0,heap_snapshot_1.heapSnapshotRefusal)(w,{live:c,...t.available?{available:t.available}:{}});if(S)return n({ok:!1,refused:S,live:c});console.log(`[child] writing a heap snapshot (${Math.round(c/1048576)} MB live) \u2014 the pod pauses while V8 serialises it`);const $=await(0,heap_snapshot_1.writeHeapSnapshot)(t.file);n({ok:!0,file:t.file,bytes:$.bytes,ms:$.ms,live:c,gen:j.gen??0,closedAlive:p})}catch(c){n({ok:!1,error:c?.message??String(c)})}finally{Ee=!1}}y(V,"X"),_(V,"z"),i(V,"takeHeapSnapshot");async function ue(t="a fresh pod has taken over"){if(k)return;k=!0,P.stop(),console.log(`[child] retiring \u2014 ${t}; ${path.basename(M,".sock")} (pid ${process.pid}) is finishing in-flight work, then exiting`);const n=Pe(Number.POSITIVE_INFINITY);n?.workers&&console.log(`[child] its ${n.workers} queue worker(s) stopped taking new jobs, still processing ${n.runningAtStop} job(s)`);try{fs.writeFileSync(sockRetiringPath(M),String(process.pid),{flag:"w",mode:384})}catch{}await new Promise(p=>{setTimeout(p,We).unref?.()}),cleanupSock(M),B.close();const c=Date.now();for(;Date.now()-c<_e;){B.closeIdleConnections?.();let p=0;for(const w of L)p+=ie(w).unanswered;if(j.inflight+X(j)===0&&p===0&&O().count===0)break;await new Promise(w=>{setTimeout(w,250).unref?.()})}setTimeout(()=>process.exit(0),3e4).unref?.();try{await g?.close()}catch(p){console.error("[child] close error while retiring:",p)}process.exit(0)}y(ue,"ge"),_(ue,"_e"),i(ue,"retire"),process.on("beforeExit",()=>{try{inspector?.close?.()}catch{}});const De=i(async t=>{console.log(`[child ${t}] shutting down\u2026`);const n=g?.close().catch(p=>console.error("[child] close error:",p)),c=new Promise(p=>B.close(()=>p()));cleanupSock(M),setTimeout(()=>process.exit(0),700).unref(),await Promise.all([n,c]),process.exit(0)},"shutdown");["SIGINT","SIGTERM","SIGHUP","SIGQUIT","SIGUSR2"].forEach(t=>{process.on(t,()=>{if(t==="SIGTERM"&&!k&&(0,handoff_retire_1.handoffRetireRequested)(SOCK_DIR,POD_GENERATION)){ue("this generation was handed over to a newer one");return}inspector?.close?.(),De(t)})})})()}else{let a=_(function(f){X.push(f),X.length>te&&X.splice(0,X.length-te),Se?.write((0,inspector_secret_1.redactInspectorUrls)(f.replace(L,"")));for(const k of ie)try{const b=k.plain?f.replace(L,""):f;k.res.write(k.redact?(0,inspector_secret_1.redactInspectorUrls)(b):b)}catch{ie.delete(k)}},"pe");i(a,"emitLogLine");const h=12,g=process.env.LENSMCP_PROJECT||SERVICE_NAME||"service",v=(0,pod_memory_events_1.createPodMemoryPublisher)(process.env.LENSMCP_EVENT_FILE),U=i(f=>({project:g,service:SERVICE_NAME||g,pod:f.id,pid:f.proc.pid??0,podGeneration:POD_GENERATION}),"podIdentity"),se=["\x1B[36m","\x1B[33m","\x1B[35m","\x1B[32m","\x1B[34m","\x1B[31m"],Fe="\x1B[0m",fe=Math.max(1,Number(process.env.CHILD_COUNT||1)),j=LENSMCP_WS_KEY||path.basename(process.cwd()),_e=i(f=>(0,process_name_1.namedExecPath)((0,process_name_1.processName)(j,SERVICE_NAME||"service",f)),"execPathFor");let O=(()=>{const f=Number(process.env.LENSMCP_DEBUG_PORT||"");return Number.isInteger(f)&&f>1024?f:0})();const Pe=20;O&&(console.warn("[parent] DEBUGGER ENABLED \u2014 pods and workers open a Node inspector. Node's inspector has NO authentication: the ws:// URL's UUID is the whole credential, and any account on this host that obtains it can run code as you. Do not enable this on a shared machine. (issues/closed/codex-security-06)"),console.warn(usesFixedInspectorPorts()?`[parent] ${exports.DEBUG_FIXED_PORTS_ENV} is set \u2014 inspectors bind PREDICTABLE ports (${O}+slot, workers ${O}+${Pe}+i). Any account on this host can connect to 127.0.0.1:${O} and read the session UUID from /json/list. Unset it to use ephemeral ports.`:`[parent] Inspectors bind an EPHEMERAL loopback port; attach via the printed "Debugger listening" URL, or \`lensmcp debug <service>\` (control socket). Set ${exports.DEBUG_FIXED_PORTS_ENV}=1 for fixed ports if your IDE needs a pre-configured attach port \u2014 any account on this host can then reach them.`));const ge=process.env.LENSMCP_LOG_FILE||"",Se=ge?(()=>{try{fs.mkdirSync(path.dirname(ge),{recursive:!0});const f=fs.createWriteStream(ge,{flags:"a",mode:384});try{fs.chmodSync(ge,384)}catch{}return f}catch(f){return console.warn(`[parent] cannot open log file ${ge}:`,f.message),null}})():null,L=/\x1b\[[0-9;]*m/g,te=2e3,X=[],ie=new Set,ae=(0,devserver_transport_1.gatewayManaged)();for(const f of["log","info","warn","error"]){const k=console[f].bind(console),b=f==="log"||f==="info"?process.stdout:process.stderr;console[f]=(...K)=>{k(...K.map(I=>typeof I=="string"?(0,inspector_secret_1.forStream)(b,ae,I):I)),a(K.map(I=>typeof I=="string"?I:util.inspect(I)).join(" ")+`
|
|
13
|
-
`)}}const
|
|
14
|
-
`+String(
|
|
15
|
-
`;F.write((0,inspector_secret_1.forStream)(F,ae,`${k}${W}`)),a(`${k}${W}`)},"write"),me=i((H,P)=>{if(!H)return;const F=readline.createInterface({input:H});F.on("line",W=>I(P,W)),F.on("close",()=>{})},"attach");me(f.stdout,"stdout"),me(f.stderr,"stderr")},"wireProcLogging"),We=i(f=>ce(f.proc,T(f.id),k=>f.tail.push(k)),"wireChildLogging");(async()=>{ensureOwnerOnlyDir(SOCK_DIR);const f=httpProxy.createProxyServer({});let k=Number(process.env.PORT)||0;k||(k=9090);const b=[],K=new Set;function I(){let e=0;for(;K.has(e);)e++;return K.add(e),e}y(I,"O"),_(I,"I"),i(I,"allocDebugSlot");let me=1,H=0,P=!1,F=fe,W=[],ve=0;const be=(()=>{const e=Number(process.env.LENSMCP_POD_BOOT_GRACE_MS);return Number.isFinite(e)&&e>=0?e:12e4})(),C=i(e=>e.proc.exitCode!==null||e.proc.signalCode!==null,"childExited"),z=i(e=>e.booting&&!C(e)&&Date.now()-e.spawnedAt<be,"stillBooting");function le(){return b.filter(e=>e.healthy&&typeof e.socketPath=="string")}y(le,"he"),_(le,"he"),i(le,"healthyChildren");let Q,re=0,Ce;const Z={project:g,service:SERVICE_NAME||g,podGeneration:POD_GENERATION};function de(e){const r=(0,service_build_events_1.buildAccountOf)(e.building);r&&r.startedAt!==re&&(re=r.startedAt,v.publish((0,service_build_events_1.buildServiceBuildEvent)(Z,"started",r,{root:process.cwd()})));const l=(0,service_build_events_1.buildAccountOf)(e.failed);l&&(re=0,v.publish((0,service_build_events_1.buildServiceBuildEvent)(Z,"failed",l,{root:process.cwd()})))}y(de,"fe"),_(de,"fe"),i(de,"recordBuildProgress");function pe(e){if(!e||typeof e!="object")return;const r=e;if(r.schemaVersion===1){de(r),"failed"in r&&delete r.failed,Q=r;for(const l of b)tell(l.proc,{type:"watcher",testimony:r})}}y(pe,"we"),_(pe,"Oe"),i(pe,"recordWatcherTestimony");function oe(e,r=256*1024){return new Promise(l=>{let u="",s=!1;e.on("data",o=>{s||(u+=o,u.length>r&&(s=!0))}),e.on("end",()=>{if(s||!u)return l(void 0);try{l(JSON.parse(u))}catch{l(void 0)}}),e.on("error",()=>l(void 0))})}y(oe,"_e"),_(oe,"we"),i(oe,"readJsonBody");function q(){const e=le();if(e.length===0)return null;const r=H%e.length;return H=(H+1)%e.length,e[r]}y(q,"V"),_(q,"ne"),i(q,"pickChild");function we(e,r){const l=`Child#${e.id}`,u=SERVICE_NAME||g,s=Date.now();if(r.type==="pod-memory"){const o=r.report;if(!o||typeof o.live!="number")return;e.memory.latest=o,e.memory.history.push(o),e.memory.history.length>12&&e.memory.history.splice(0,e.memory.history.length-12),console.log(`[parent] ${(0,pod_memory_1.describePodMemory)(l,o)}`),v.publish((0,pod_memory_events_1.buildPodMemoryEvent)(U(e),o))}else if(r.type==="pod-memory-retained"){const o=r.retained;if(!o||typeof o.gen!="number")return;e.memory.retained.set(o.gen,{...o,at:s}),console.warn(`[parent] ${(0,pod_memory_1.describeRetained)(l,u,o)}`),v.publish((0,pod_memory_events_1.buildPodRetainedEvent)(U(e),o,s))}else{const o=r.released;if(!o||typeof o.gen!="number")return;e.memory.retained.delete(o.gen),console.log(`[parent] ${(0,pod_memory_1.describeReleased)(l,u,o)}`),v.publish((0,pod_memory_events_1.buildPodReleasedEvent)(U(e),o,s))}}y(we,"ke"),_(we,"Le"),i(we,"recordPodMemory");const Y=new Map;let Ue=0;async function B(){const e=me++,r=childSockPath(e);cleanupSock(r);const l=(0,dev_devtool_1.sourceMapExecArgv)();__filename.endsWith(".ts")&&l.unshift("--require","@swc-node/register"),l.push(...(0,inspector_secret_1.inspectorPublishExecArgv)(usesFixedInspectorPorts()));const u=O?I():-1,s=(0,node_child_process_1.fork)(__filename,{env:{...process.env,APP_RUNNER:"1",CHILD_SOCK_PATH:r,...u>=0&&{CHILD_DEBUG_PORT:String(inspectorPortFor(O,u))}},stdio:["inherit","pipe","pipe","ipc"],execArgv:l,execPath:_e("pod")}),o={id:e,proc:s,healthy:!1,lastError:null,debugSlot:u,tail:new exit_reason_1.TailBuffer,booting:!0,spawnedAt:Date.now(),bootReloadSeq:ve,memory:{history:[],retained:new Map}};return s.on("error",E=>console.error(`[parent] Child#${e}: ${E.message}`)),s.on("message",E=>{if(!E||typeof E!="object")return;const d=E;if(d.type==="ready")o.socketPath=String(d.socketPath),o.healthy=!0,o.booting=!1,console.log(`[parent] Child#${o.id} ready on socket ${o.socketPath}`),Q&&tell(s,{type:"watcher",testimony:Q}),ve!==o.bootReloadSeq&&tell(s,{type:"reload"});else if(d.type==="recycle-request")c(o,String(d.reason||"it has outgrown its bound"));else if(d.type==="inspector-url")o.inspectorUrl=String(d.url),console.log(`[parent] Child#${o.id} Debugger listening on ${d.url}`);else if(d.type==="reloaded"){if(V.has(o)){console.log(`[parent] Child#${o.id} finished a swap it began before it was retired \u2014 not serving it: a fresh pod has taken over`);return}o.socketPath=String(d.socketPath),o.healthy=!0,console.log(`[parent] Child#${o.id} hot-swapped on socket ${o.socketPath}`);const m=d.swap;m&&typeof m.generation=="number"&&typeof m.swaps=="number"&&v.publish((0,service_build_events_1.buildServiceSwapEvent)(U(o),{generation:m.generation,swaps:m.swaps,swapMs:typeof m.swapMs=="number"?m.swapMs:0,draining:typeof m.draining=="number"?m.draining:0},Ce,{root:process.cwd()}))}else d.type==="reload-error"?(o.lastError=String(d.error||"unknown reload error"),console.error(`[parent] Child#${o.id} reload error: ${o.lastError}`),o.healthy=!1):d.type==="boot-error"?(o.lastError=String(d.error||"unknown boot error"),console.error(`[parent] Child#${o.id} boot error: ${o.lastError}`),o.healthy=!1,o.booting=!1):d.type==="pod-memory"||d.type==="pod-memory-retained"||d.type==="pod-memory-released"?we(o,d):d.type==="heap-snapshot-result"&&Y.get(Number(d.id))?.(d)}),s.on("exit",(E,d)=>{o.booting=!1;for(const D of o.memory.retained.values()){const x={gen:D.gen,closedAt:D.closedAt,ageMs:Date.now()-D.closedAt,reason:"pod-exited"};console.log(`[parent] ${(0,pod_memory_1.describeReleased)(`Child#${o.id}`,SERVICE_NAME||g,x)}`),v.publish((0,pod_memory_events_1.buildPodReleasedEvent)(U(o),x,Date.now()))}o.memory.retained.clear(),o.memory.latest&&v.publish((0,pod_memory_events_1.buildPodExitedEvent)(U(o),{code:E,signal:d},Date.now())),o.debugSlot>=0&&(K.delete(o.debugSlot),o.debugSlot=-1);const m=d==="SIGINT"||d==="SIGTERM"||E===0;if(m?console.log(`[parent] Child#${o.id} exited cleanly (code=${E}, signal=${d??"none"})`):(console.error((0,exit_reason_1.crashReport)(`[parent] Child#${o.id} crashed (code=${E}, signal=${d??"none"}, pid=${o.proc.pid}, ${o.healthy?"was serving":"was not ready"})`,E,d,o.tail.snapshot())),o.lastError||(o.lastError=`Child exited abnormally (code=${E}, signal=${d??"none"})`)),o.healthy=!1,cleanupSock(o.socketPath,o.proc.pid),o.socketPath=void 0,!m&&!P){const D=b.indexOf(o);D>=0&&b.splice(D,1);const x=Date.now();if(W=W.filter(ee=>x-ee<3e4),W.length>=5){console.error(`[parent] crash-loop detected (${W.length} respawns/30s) \u2014 pausing auto-respawn; POST /webpack/reload to retry`);return}W.push(x),setTimeout(()=>{const ee=b.filter(Ie=>Ie.proc.killed===!1).length;!P&&ee<F&&(console.log(`[parent] respawning a crashed pod (${ee}/${F} live)`),B().catch(()=>{}))},1500).unref?.()}}),b.push(o),We(o),o}y(B,"B"),_(B,"K"),i(B,"spawnChild");async function M(e){F=Math.max(F,e);const r=b.filter(u=>u.proc.killed===!1),l=e-r.length;for(let u=0;u<l;u++)await B()}y(M,"$"),_(M,"M"),i(M,"ensurePoolSize");async function Ee(){const e=b.filter(r=>(!r.healthy||typeof r.socketPath!="string")&&!z(r));await Promise.all(e.map(async r=>{try{r.proc.kill("SIGTERM")}catch{}cleanupSock(r.socketPath,r.proc.pid),r.socketPath=void 0;const l=b.indexOf(r);l>=0&&b.splice(l,1),await B()}))}y(Ee,"Ee"),_(Ee,"Ee"),i(Ee,"respawnUnhealthy");const V=new Set;let ue=!1,De=0;const t=3e4,n=(()=>{const e=Number(process.env.LENSMCP_SWAP_DRAIN_MS);return(Number.isFinite(e)&&e>=0?e:15*6e4)+6e4})();async function c(e,r){const l=i(s=>{console.log(`[parent] Child#${e.id} asked for a fresh pod (${r}) \u2014 not now: ${s}`),tell(e.proc,{type:"recycle-declined"})},"decline");if(P||!b.includes(e))return;if(ue)return l("another pod is already being replaced");const u=Date.now()-De;if(u<t)return l(`a pod was replaced ${Math.round(u/1e3)}s ago`);ue=!0,console.log(`[parent] Child#${e.id} asked for a fresh pod \u2014 ${r}. Starting one; Child#${e.id} keeps serving until it is ready.`);try{const s=await B(),o=Date.now()+be;for(;!s.healthy&&!s.lastError&&!C(s)&&Date.now()<o;)await new Promise(m=>{setTimeout(m,100).unref?.()});if(P)return;if(!s.healthy){const m=b.indexOf(s);m>=0&&b.splice(m,1);try{s.proc.kill("SIGTERM")}catch{}return l(`its successor Child#${s.id} did not come up (${s.lastError??"no answer in time"})`)}const E=b.indexOf(e);E>=0&&b.splice(E,1),e.healthy=!1,V.add(e),postRetiringNotice(e.socketPath,e.proc.pid);const d=setTimeout(()=>{if(!C(e)){console.error(`[parent] Child#${e.id} was still running ${n}ms after it was retired \u2014 killing it`);try{e.proc.kill("SIGKILL")}catch{}}},n);if(d.unref?.(),e.proc.once("exit",()=>{clearTimeout(d),V.delete(e)}),!tell(e.proc,{type:"retire"}))try{e.proc.kill("SIGTERM")}catch{}De=Date.now(),console.log(`[parent] Child#${s.id} took over from Child#${e.id} (pid ${e.proc.pid} \u2192 ${s.proc.pid})`)}catch(s){l(`could not start a successor: ${s?.message??String(s)}`)}finally{ue=!1}}y(c,"l"),_(c,"l"),i(c,"recyclePod");const p=[];function w(e){const r=path.dirname(path.isAbsolute(BUNDLE_PATH)?BUNDLE_PATH:path.resolve(BUNDLE_PATH)),l=path.join(r,`${e}.js`);if(!fs.existsSync(l))return console.error(`[parent] Worker "${e}" bundle not found: ${l}`),null;const u=(0,dev_devtool_1.sourceMapExecArgv)();__filename.endsWith(".ts")&&u.unshift("--require","@swc-node/register");try{u.push("--require",require.resolve("@lensmcp/node-instrumentation/register"))}catch{}const s=inspectorPortFor(O||9229,Pe+Math.max(0,WORKER_NAMES.indexOf(e)));u.push(O?`--inspect=127.0.0.1:${s}`:`--inspect-port=127.0.0.1:${s}`,...(0,inspector_secret_1.inspectorPublishExecArgv)(usesFixedInspectorPorts()));const o=(0,node_child_process_1.fork)(l,{env:process.env,stdio:["inherit","pipe","pipe","ipc"],execArgv:u,execPath:_e(`w-${e}`)}),E={name:e,proc:o,debugPort:s};return p.push(E),o.on("error",d=>console.error(`[parent] Worker "${e}": ${d.message}`)),ce(o,`\x1B[35m[worker:${e}] \x1B[0m`,d=>{const m=/Debugger listening on (wss?:\/\/\S+)/.exec(d);m&&(E.inspectorUrl=m[1])}),o.on("exit",(d,m)=>{m==="SIGINT"||m==="SIGTERM"||d===0||console.error(`[parent] Worker "${e}" crashed (code=${d}, signal=${m??"none"})`);const D=p.indexOf(E);D>=0&&p.splice(D,1)}),console.log(`[parent] Worker "${e}" started (pid=${o.pid})`),E}y(w,"m"),_(w,"g"),i(w,"spawnWorkerProcess");const S=(()=>{const e=Number(process.env.LENSMCP_SWAP_DRAIN_MS);return Number.isFinite(e)&&e>=0?e:15*6e4})(),$=(()=>{const e=Number(process.env.LENSMCP_SWAP_MAX_DRAINING);return Number.isFinite(e)&&e>=1?Math.floor(e):1})(),A=new Set,ne=i(e=>e.proc.exitCode!==null||e.proc.signalCode!==null,"workerExited");function N(e,r){if(A.delete(e),!ne(e)){console.error(`[parent] Worker "${e.name}" (pid=${e.proc.pid}) ${r} \u2014 killing it. A worker that returns from its SIGTERM handler but leaves a handle open (a Redis client handed to BullMQ is not closed by worker.close()) never exits on its own: close what it opened, or call process.exit().`);try{e.proc.kill("SIGKILL")}catch{}}}y(N,"N"),_(N,"R"),i(N,"killDrainingWorker");function J(e){try{e.proc.kill("SIGTERM")}catch{}if(ne(e))return;const r=[...A].filter(u=>u.name===e.name);for(;r.length>=$;)N(r.shift(),`was still running when a later reload replaced its successor (cap ${$})`);A.add(e);const l=setTimeout(()=>N(e,`was still running ${S}ms after SIGTERM`),S);l.unref?.(),e.proc.once("exit",()=>{clearTimeout(l),A.delete(e)})}y(J,"z"),_(J,"B"),i(J,"retireWorker");function He(){for(const e of[...p])J(e);p.length=0;for(const e of WORKER_NAMES)w(e)}y(He,"qe"),_(He,"Ve"),i(He,"restartWorkers");const ze=debounce(async()=>{ve+=1;const e=le();if(e.length>0){console.log(`[parent] Forwarding reload to ${e.length} child(ren)`);for(const r of e)tell(r.proc,{type:"reload"})}await Ee(),WORKER_NAMES.length>0&&He()},200),Ke=i((e,r)=>{const l=(0,notice_generation_1.noticeGeneration)(e.headers);return l===void 0||l===POD_GENERATION?!1:(e.resume(),r.writeHead(409,{"content-type":"application/json"}),r.end(JSON.stringify({ok:!1,generation:POD_GENERATION,sentFor:l})),e.url==="/webpack/reload"&&console.log(`[parent] a build of generation g${l} reached generation g${POD_GENERATION} \u2014 not reloaded: it is not this generation's build`),!0)},"refusedForAnotherGeneration"),Ae=i(async(e,r)=>{if(e.method==="POST"&&e.url==="/webpack/reload"){if(!(0,devserver_transport_1.mayDriveThePool)(e))return refusePoolCommand(e,r);if(Ke(e,r))return;r.writeHead(200,{"content-type":"application/json"}),r.end(JSON.stringify({ok:!0})),oe(e).then(s=>{const o=s;Ce=(0,service_build_events_1.buildAccountOf)(o?.build),re=0,pe(o?.watcher)}),ze();return}if(e.method==="POST"&&e.url==="/webpack/watching"){if(!(0,devserver_transport_1.mayDriveThePool)(e))return refusePoolCommand(e,r);if(Ke(e,r))return;const s=await oe(e);pe(s),r.writeHead(200,{"content-type":"application/json"}),r.end(JSON.stringify({ok:!0,relayed:Q!==void 0}));return}if(e.method==="POST"&&e.url==="/webpack/scale"){if(!(0,devserver_transport_1.mayDriveThePool)(e))return refusePoolCommand(e,r);let s="";e.on("data",o=>{s+=o}),e.on("end",async()=>{let o=0;try{o=Number(JSON.parse(s||"{}").pods)||0}catch{}o=Math.max(1,Math.min(o,16)),await M(o),r.writeHead(200,{"content-type":"application/json"}),r.end(JSON.stringify({ok:!0,pods:o}))});return}if(e.method==="GET"&&e.url?.startsWith("/webpack/logs")){const s=new URL(e.url,"http://localhost").searchParams,o=Math.min(Math.max(Number(s.get("tail")??"100")||0,0),te),E=s.get("follow")!=="0",d=s.get("plain")==="1",m=!(0,devserver_transport_1.isOwnerOnlyTransport)(e);r.writeHead(200,{"content-type":"text/plain; charset=utf-8","cache-control":"no-cache"});const D=o===0?"":X.slice(-o).join(""),x=d?D.replace(L,""):D;if(r.write(m?(0,inspector_secret_1.redactInspectorUrls)(x):x),!E){r.end();return}const ee={res:r,plain:d,redact:m};ie.add(ee),e.on("close",()=>ie.delete(ee));return}if(e.method==="POST"&&e.url?.startsWith("/webpack/debug")){if(!(0,devserver_transport_1.isOwnerOnlyTransport)(e)){r.writeHead(404,{"content-type":"application/json"}),r.end(JSON.stringify({error:"not found"}));return}const s=Number(new URL(e.url,"http://localhost").searchParams.get("port")||"");Number.isInteger(s)&&s>1024&&(O=s),O||(O=9229);const o=b.filter(d=>d.proc.exitCode===null&&d.proc.signalCode===null);for(const d of o)d.debugSlot<0&&(d.debugSlot=I()),tell(d.proc,{type:"debug-open",port:inspectorPortFor(O,d.debugSlot)});for(const d of p)try{d.proc.kill("SIGUSR1")}catch{}const E=Date.now()+2e3;for(;Date.now()<E&&o.some(d=>!d.inspectorUrl);)await new Promise(d=>setTimeout(d,50));r.writeHead(200,{"content-type":"application/json"}),r.end(JSON.stringify({ok:!0,basePort:O,fixedPorts:usesFixedInspectorPorts(),pods:o.map(d=>({id:d.id,inspectorUrl:d.inspectorUrl??null})),workers:p.map(d=>({name:d.name,port:d.debugPort||(0,inspector_secret_1.inspectorPortOf)(d.inspectorUrl),inspectorUrl:d.inspectorUrl??null}))},null,2)+`
|
|
16
|
-
`);return}if(e.method==="GET"&&e.url==="/webpack/memory"){if(!(0,devserver_transport_1.isOwnerOnlyTransport)(e)){r.writeHead(404,{"content-type":"application/json"}),r.end(JSON.stringify({error:"not found"}));return}const
|
|
17
|
-
`);return}if(e.method==="POST"&&e.url?.startsWith("/webpack/heap")){if(!(0,devserver_transport_1.isOwnerOnlyTransport)(e)){r.writeHead(404,{"content-type":"application/json"}),r.end(JSON.stringify({error:"not found"}));return}const
|
|
18
|
-
`)},"reply"),o=new URL(e.url,"http://localhost").searchParams,
|
|
12
|
+
})()`),(0,bundle_parent_1.routeBundleRequires)(requested,resolved);const exports=eval(`require(${JSON.stringify(resolved)})`);try{const mod=eval("require.cache")[resolved];lastImportedModule=mod&&typeof mod=="object"?mod:void 0}catch{}return exports}h(importFresh,"importFresh"),a(importFresh,"importFresh");function debounce(c,f){let g=null;return(...E)=>{g&&clearTimeout(g),g=setTimeout(()=>c(...E),f)}}if(h(debounce,"debounce"),a(debounce,"debounce"),process.env.APP_RUNNER==="1"){(0,stdio_guard_1.guardBrokenStdio)();const c=a(g=>{if(!inspector.url())try{inspector.open(g,"127.0.0.1",!1)}catch(L){console.warn(`[child] inspector.open(${g}) failed (port taken by another devserver?) \u2014 falling back to a random port:`,L.message);try{inspector.open(0,"127.0.0.1",!1)}catch{}}const E=inspector.url();E&&tell(process,{type:"inspector-url",url:E})},"openInspector"),f=process.env.CHILD_DEBUG_PORT;if(f!==void 0&&f!==""){const g=Number(f);Number.isInteger(g)&&(g===0||g>1024)&&c(g)}try{require("@lensmcp/node-instrumentation/register")}catch{}(async()=>{let g=null,E=!1,L,Z=!1;const He=(0,hot_swap_registries_1.registryPruningEnabled)(),le=a((t,s)=>{const l=(0,hot_swap_registries_1.describePrune)(t,s);l&&console.log(l)},"logPrune");let B={app:null,handler:a((t,s)=>{s.statusCode=503,s.end("starting")},"handler"),inflight:0};const de=(()=>{const t=Number(process.env.LENSMCP_SWAP_DRAIN_MS);return Number.isFinite(t)&&t>=0?t:15*6e4})(),T=a(t=>{const s=globalThis.__lensmcpActiveWork;if(typeof s!="function")return{count:0};try{const l=s(t);return{count:Number(l?.count??0),...l?.oldestStartedAt?{oldestStartedAt:l.oldestStartedAt}:{}}}catch{return{count:0}}},"activeWork"),ke=a(t=>{const s=globalThis.__lensmcpStopWorkIntake;if(typeof s=="function")try{return s(t)}catch{return}},"stopWorkIntake"),pe=a(t=>{const s=globalThis.__lensmcpWorkIntakeReport;if(!(t===void 0||typeof s!="function"))try{return s(t)??void 0}catch{return}},"workIntakeReport"),Ee=(()=>{const t=Number(process.env.LENSMCP_SWAP_MAX_DRAINING);return Number.isFinite(t)&&t>=1?Math.floor(t):1})(),W=new Set,z=(()=>{const t=Number(process.env.LENSMCP_SWAP_EARLY_CLOSE_GRACE_MS);return process.env.LENSMCP_SWAP_EARLY_CLOSE_GRACE_MS!==void 0&&process.env.LENSMCP_SWAP_EARLY_CLOSE_GRACE_MS!==""&&Number.isFinite(t)&&t>=0?t:3e4})(),K=a(t=>{if(!t.abandoned?.size)return 0;const s=Date.now();for(const[l,u]of t.abandoned)(l.writableEnded||s-u>=z)&&t.abandoned.delete(l);return t.abandoned.size},"abandonedRunning"),ee=a(t=>{let s=0;for(const l of t.open??[])l.headersSent||(s+=1);return{unanswered:s+K(t),streams:Math.max(0,t.inflight-s),work:T(t.workGen).count}},"owedBy"),te=a((t,s,l=`${s}s`)=>`${t} ${t===1?s:l}`,"plural");async function De(){if(z<=0)return;const t=Date.now();let s=!1;for(;!(W.size<Ee);){const l=W.values().next().value;if(!l||l.closed)break;const u=ee(l);if(u.unanswered===0&&u.work===0)break;const y=(l.drainingSince??t)+z-Date.now();if(y<=0)break;s||(s=!0,console.log(`[child] swap held \u2014 the app replaced ${Math.round((Date.now()-(l.drainingSince??t))/100)/10}s ago is still `+[u.unanswered?`answering ${te(u.unanswered,"request")}`:"",u.work?`running ${te(u.work,"background job")}`:""].filter(Boolean).join(" and ")+`, and this pod keeps at most ${Ee} replaced app(s) alive (LENSMCP_SWAP_MAX_DRAINING). The new build is applied when it is done \u2014 in ${Math.ceil(y/1e3)}s at the latest (LENSMCP_SWAP_EARLY_CLOSE_GRACE_MS).`)),await new Promise(w=>{setTimeout(w,Math.min(100,y)).unref?.()})}s&&console.log(`[child] swap resumed after ${Date.now()-t}ms`)}h(De,"Ge"),a(De,"holdForOwedWork");const R=(0,swap_recycle_1.swapRecyclePolicy)();let ue,re=0;const Ue=(()=>{const t=Number(process.env.LENSMCP_POD_RETIRE_NOTICE_MS);return Number.isFinite(t)&&t>=0?t:3500})();let _=!1,b=!1;const v=(0,pod_memory_1.podMemoryPolicy)();let j=0;const I=new Set;let he=!1;const q=a(()=>{if(!he)return;let t=0;for(const s of I)s.deref()===void 0?I.delete(s):t+=1;return t},"liveContainers"),k=(0,pod_memory_1.createPodMemoryMonitor)({policy:v,state:a(()=>({gen:B.gen??0,swaps:re,...ue===void 0?{}:{baseline:ue},busy:E||Z||V.size>0,lastBusyAt:M}),"state"),send:a(t=>{tell(process,t)},"send"),containers:q,counter:(0,pod_memory_1.createLiveObjectCounter)(path.isAbsolute(BUNDLE_PATH)?BUNDLE_PATH:path.join(__dirname,BUNDLE_PATH)),onRetained:a(()=>Ne(),"onRetained"),gc:a(()=>(0,gc_notice_1.withGcNotice)($,pod_memory_1.fullGc),"gc")}),F=a(()=>((0,gc_notice_1.withGcNotice)($,pod_memory_1.fullGc)&&k.tracker.noteGc(),process.memoryUsage().heapUsed),"liveHeap"),H=(()=>{if(!(0,error_stack_release_1.errorFrameReleaseEnabled)())return null;try{const t=path.dirname(path.isAbsolute(BUNDLE_PATH)?BUNDLE_PATH:path.join(__dirname,BUNDLE_PATH))+path.sep,s=`${path.sep}node_modules${path.sep}`,l=new Set(Object.keys(require.cache));return(0,error_stack_release_1.createErrorFrameReleaser)(require.cache,{skip:a(u=>l.has(u)||u.startsWith(t)&&!u.slice(t.length).includes(s)&&!u.slice(t.length).startsWith(`node_modules${path.sep}`),"skip")})}catch{return null}})();let fe=!1;function Pe(){if(!(!H||fe))try{const t=H();t.errors>0&&console.log(`[child] read the stack of ${t.errors} Error object(s) that libraries created while loading and keep for good \u2014 unread, each held the functions that were on its stack, this bundle's included`)}catch(t){console.error("[child] could not release library error frames:",t),fe=!0}}h(Pe,"Ie"),a(Pe,"releaseLibraryErrorFrames");const V=new Map;let M=Date.now();const xe=a(()=>R.settleMs<=0||!E&&!Z&&V.size===0&&Date.now()-M>=R.settleMs,"settled");let Y;function oe(t){if(!(!R.enabled||_||b)){if(R.settleMs<=0){J(t);return}Y&&clearTimeout(Y),Y=setTimeout(()=>{Y=void 0,xe()?J(t):oe(t)},R.settleMs),Y.unref?.()}}h(oe,"le"),a(oe,"recycleCheckWhenSettled");const Se=a(()=>{if(R.stuckCloseMs<=0)return 0;const t=Date.now();let s=0;for(const l of V.values())t-l>=R.stuckCloseMs&&(s+=1);return s},"stuckCloses");function J(t){if(!R.enabled||_||b||!process.send)return;const s=v8.getHeapStatistics().heap_size_limit,l=a(y=>{const w=k.oldestRetained();return{swaps:re,usedBytes:y,limitBytes:s,stuckCloses:Se(),settled:xe(),...ue===void 0?{}:{baselineBytes:ue},...w?{retained:{generation:w.gen,ageMs:Date.now()-w.closedAt,gcs:w.gcs}}:{}}},"state");if(!(0,swap_recycle_1.recycleReason)(R,l(process.memoryUsage().heapUsed)))return;const u=(0,swap_recycle_1.recycleReason)(R,l(F()));u&&(_=!0,console.log(`[child] asking for a fresh pod ${t} \u2014 ${u}. This pod keeps serving until its successor is ready. Size the bound with LENSMCP_SWAP_RECYCLE_HEAP_FACTOR / _HEAP_RATIO / _MIN_MB / _RETAINED_MS, or turn it off with LENSMCP_SWAP_RECYCLE=0.`),tell(process,{type:"recycle-request",reason:u}))}h(J,"X"),a(J,"considerRecycle");let _e;function Ne(){if(!R.enabled||R.retainedMs<=0||_||b)return;const t=k.oldestRetained();if(!t)return;const s=t.closedAt+R.retainedMs-Date.now();if(s<=0){J("with a closed generation still in memory");return}_e||(_e=setTimeout(()=>{_e=void 0,k.measure("retention-check").catch(()=>{})},s),_e.unref?.())}h(Ne,"We"),a(Ne,"retainedRecycleCheck");function ge(t,s){const l={};s&&(l.module=s),t&&(l.app=t);try{const u=t?.app;if(u&&typeof u=="object"&&(l.nestApp=u,u.container&&typeof u.container=="object")){l.container=u.container;const y=rootModuleOf(u.container);y&&(l.rootModule=y)}}catch{}return l}h(ge,"Pe"),a(ge,"generationTargets");async function ne(t,s){if(t.closed||(t.closed=!0,W.delete(t),s&&console.error(`[child] ${s}`),!t.app))return;V.set(t,Date.now());const l=R.enabled&&R.stuckCloseMs>0?setTimeout(()=>{V.has(t)&&(console.error(`[child] a previous app has been closing for ${Math.round(R.stuckCloseMs/1e3)}s and its close() has not returned \u2014 one of its shutdown hooks is waiting on something that does not end (a queue worker, a connection, a stream). It stays in memory until this pod is replaced.`),J("with a previous app stuck in close()"))},R.stuckCloseMs):void 0;l?.unref?.();const u=t.app;try{await t.app.close()}catch(y){console.error("[child] error closing a previous app:",y)}finally{V.delete(t),M=Date.now(),l&&clearTimeout(l),t.app=null,t.abandoned=void 0,t.handler=(y,w)=>{w.statusCode=503,w.end("closed")},t.gen!==void 0&&k.closed(t.gen,re,ge(u,t.module)),t.module=void 0}if(t.superseded){try{le((0,hot_swap_registries_1.pruneRegistries)(t.superseded,"serve"),"after closing the previous app")}catch(y){console.error("[child] could not release the previous app's class registrations:",y)}t.superseded=void 0}oe("after closing the previous app")}h(ne,"_e"),a(ne,"closeGeneration");async function se(t){const s=Date.now();t.drainingSince=s;const l=a(()=>({inflight:t.inflight+K(t),work:T(t.workGen).count}),"busy"),u=l();if(u.inflight>0||u.work>0){for(;W.size>=Ee;){const O=W.values().next().value;if(!O)break;const A=ee(O),Q=Math.round((Date.now()-(O.drainingSince??s))/1e3);if(A.unanswered===0&&A.streams===0&&A.work===0){await ne(O);continue}await ne(O,`closing a still-draining generation early \u2014 ${W.size} were pending and the cap is ${Ee} (each holds a whole app: DI container, DB pool, queue workers). `+(A.unanswered>0||A.work>0?`It was replaced ${Q}s ago and had still not answered ${te(A.unanswered,"request")}`+(A.work?` or finished ${te(A.work,"background job")}`:"")+` \u2014 those fail now (a queue job keeps its lock until the TTL lapses). Raise LENSMCP_SWAP_EARLY_CLOSE_GRACE_MS (currently ${z}ms) to wait longer for them. `:`It held only ${te(A.streams,"open stream")}; their clients reconnect to the new app. `)+"Raise LENSMCP_SWAP_MAX_DRAINING if this pod legitimately needs more.")}W.add(t)}for(;de>0&&Date.now()-s<de;){if(t.closed)return;const O=l();if(O.inflight===0&&O.work===0)break;await new Promise(A=>{setTimeout(A,250).unref?.()})}if(t.closed)return;const y=l(),w=pe(t.workGen);y.inflight>0||y.work>0?console.error(`[child] swap drain expired after ${Date.now()-s}ms \u2014 closing the previous app with ${y.inflight} in-flight request(s) and ${y.work} background job(s) still running. `+(w?`Previous app still processing ${w.running} queue job(s); ${w.takenAfterStop} were taken after the swap. `:"")+`A queue job killed here keeps its lock until the TTL lapses. Raise LENSMCP_SWAP_DRAIN_MS (currently ${de}ms) if this is legitimate work.`):(Date.now()-s>250||w?.runningAtStop||w?.takenAfterStop)&&console.log(`[child] previous app drained in ${Date.now()-s}ms \u2014 closing it`+(w?` (it finished ${w.finishedAfterStop} queue job(s) after the swap; ${w.takenAfterStop} were taken after the swap)`:"")),await ne(t)}h(se,"ge"),a(se,"drainThenClose");async function ie(){if(E)return Z=!0,console.log("[child] Reload deferred \u2014 will re-swap after current swap completes"),g;E=!0,M=Date.now(),await De(),process.removeAllListeners("uncaughtException"),process.removeAllListeners("unhandledRejection"),process.on("uncaughtException",(N,C)=>{console.error(`[child] uncaughtException (${C}):`,N)}),process.on("unhandledRejection",N=>{const C=N instanceof Error?N.stack||N.message:String(N);C.includes("FronteggContextScope")||C.includes("populateLoggerMetadata")||console.error("[child] unhandledRejection:",N)});let t;if(He)try{t=(0,hot_swap_registries_1.captureRegistries)()}catch{t=void 0}const s=global.__lensmcpBeginWorkGeneration,l=typeof s=="function"?s():void 0;try{try{await importFresh(BUNDLE_PATH)}catch(N){if(!(N instanceof SyntaxError))throw N;console.warn(`[child] bundle was unreadable mid-write (${N.message}) \u2014 retrying the swap once`),await new Promise(C=>setTimeout(C,400)),await importFresh(BUNDLE_PATH)}}catch(N){throw E=!1,M=Date.now(),N}if(typeof global.createChildApp!="function")throw E=!1,M=Date.now(),new Error(`Bundle '${BUNDLE_PATH}' does not export createChildApp() and the zero-touch bridge is not active. Either install @lensmcp/node-instrumentation (a plain NestFactory.create + app.listen main.ts then just works) or set global.createChildApp in main.ts when DEVSERVER_MODE === '1'.`);let u;if(t)try{u=(0,hot_swap_registries_1.supersededSince)(t),le((0,hot_swap_registries_1.pruneRegistries)(u,"build"),"at the swap")}catch(N){console.error("[child] could not release superseded class registrations:",N)}let y;try{y=await global.createChildApp()}catch(N){throw E=!1,M=Date.now(),takeImportedModule(),N}const w=B;u?.size&&(w.app?w.superseded=u:le((0,hot_swap_registries_1.pruneRegistries)(u,"serve"),"at the swap")),g=y;const O=takeImportedModule();B={app:y,handler:y.handler,inflight:0,gen:++j,...O?{module:O}:{},...l===void 0?{}:{workGen:l}};const A=ge(y,void 0).container;A&&(I.add(new WeakRef(A)),he=!0);const Q=w.app&&l!==void 0?ke(l):void 0;return console.log("[child] Swapped to fresh app (previous draining in background)"+(Q?.workers?`; its ${Q.workers} queue worker(s) stopped taking new jobs, previous app still processing ${Q.runningAtStop} job(s)`:"")),Pe(),w.app&&(re+=1,se(w).catch(N=>console.error("[child] background close error:",N)),setTimeout(()=>J("30s after a hot swap"),3e4).unref?.(),k.swapped(w.gen,()=>w.closed===!0&&!V.has(w))),E=!1,M=Date.now(),Z?(Z=!1,ie()):y}h(ie,"ye"),a(ie,"swapNow");const ve=debounce(async()=>{try{console.log("[child] /webpack/reload"),await ie()}catch(t){console.error("[child] reload failed:",t)}},250),ye=http.createServer((t,s)=>{if(t.method==="POST"&&t.url==="/webpack/reload"){s.writeHead(200,{"content-type":"application/json"}),s.end(JSON.stringify({ok:!0})),ve();return}if(t.method==="GET"&&t.url==="/__lensmcp/alive"){const u=t.headers["x-internal-token"],y=process.env.LENSMCP_SERVICE_KEY;if(y&&u!==y){s.writeHead(404,{"content-type":"text/plain"}),s.end("not found");return}const w=T();s.writeHead(200,{"content-type":"application/json","cache-control":"no-store"}),s.end(JSON.stringify({ok:!0,pid:process.pid,swapping:E,inflight:B.inflight,oldestInflightAt:B.oldestAt,activeWork:w.count,oldestWorkAt:w.oldestStartedAt,keyFingerprint:serviceKeyFingerprint(),...L?{watcher:L}:{},...Number.isFinite(Number(process.env.LENSMCP_POD_GENERATION))&&process.env.LENSMCP_POD_GENERATION?{podGeneration:Number(process.env.LENSMCP_POD_GENERATION)}:{}}));return}const l=B;l.inflight+=1,(l.open??=new Set).add(s),l.oldestAt===void 0&&(l.oldestAt=Date.now()),s.on("close",()=>{l.inflight-=1,l.open?.delete(s),z>0&&!l.closed&&!s.headersSent&&!s.writableEnded&&((l.abandoned??=new Map).set(s,Date.now()),l.abandoned.size>256&&K(l)),l.inflight===0&&(l.oldestAt=void 0),k.activity()}),l.handler(t,s)});ye.keepAliveTimeout=0;const $=process.env.CHILD_SOCK_PATH;process.on("disconnect",()=>{cleanupSock($),process.exit(0)});try{const t=path.isAbsolute(BUNDLE_PATH)?BUNDLE_PATH:path.join(__dirname,BUNDLE_PATH);if((0,schema_first_instance_1.schemaPrewarmEnabled)())try{const s=(0,schema_first_instance_1.prewarmZodFor)(t);s?.created&&console.log(`[child] zod${s.version?` ${s.version}`:""}: built ${s.created} throwaway schemas first, so none of the bundle's own is the first of its class`)}catch{}if((0,redis_disconnect_fix_1.redisDisconnectFixEnabled)())try{const s=(0,redis_disconnect_fix_1.finishStrandedDisconnectsFor)(t);s?.patched&&console.log(`[child] ioredis${s.versions.length?` ${s.versions.join(", ")}`:""}: a disconnect() between reconnect attempts now ends the client \u2014 it used to leave a queue worker's close() waiting for good`)}catch{}await ie(),ue=(await k.booted()).live,console.log(`[child] Using bundle: ${t}`),claimSock($),ye.listen($,()=>{console.log(`[child] Listening on ${$}`),tell(process,{type:"ready",socketPath:$})})}catch(t){console.error("[child] Startup error:",t),tell(process,{type:"boot-error",error:String(t?.stack||t)}),process.exitCode=1;return}process.on("message",async t=>{if(!(!t||typeof t!="object")){if(t.type==="debug-open"){const s=Number(t.port);c(Number.isInteger(s)&&s>1024?s:0);return}if(t.type==="watcher"){const s=t.testimony;s&&typeof s=="object"&&(L=s);return}if(t.type==="heap-snapshot"){Ae(t);return}if(t.type==="recycle-declined"){_=!1;return}if(t.type==="retire"){U();return}if(t.type==="reload"){if(b)return;try{const s=Date.now();await ie(),tell(process,{type:"reloaded",socketPath:$,swap:{generation:j,swaps:re,swapMs:Date.now()-s,draining:W.size}})}catch(s){console.error("[child] reload error:",s),tell(process,{type:"reload-error",error:String(s?.stack||s)})}}}});let we=!1;async function Ae(t){const s=a(l=>{tell(process,{type:"heap-snapshot-result",id:t.id,...l})},"reply");if(we)return s({ok:!1,refused:"a snapshot of this pod is already being written"});we=!0;try{const l=F(),u=k.tracker.views().map(A=>A.gen),y=(0,heap_snapshot_1.heapSnapshotPolicy)();t.maxHeapBytes&&(y.maxHeapBytes=t.maxHeapBytes);const w=(0,heap_snapshot_1.heapSnapshotRefusal)(y,{live:l,...t.available?{available:t.available}:{}});if(w)return s({ok:!1,refused:w,live:l});console.log(`[child] writing a heap snapshot (${Math.round(l/1048576)} MB live) \u2014 the pod pauses while V8 serialises it`);const O=await(0,heap_snapshot_1.writeHeapSnapshot)(t.file);s({ok:!0,file:t.file,bytes:O.bytes,ms:O.ms,live:l,gen:B.gen??0,closedAlive:u})}catch(l){s({ok:!1,error:l?.message??String(l)})}finally{we=!1}}h(Ae,"Ue"),a(Ae,"takeHeapSnapshot");async function U(t="a fresh pod has taken over"){if(b)return;b=!0,k.stop(),console.log(`[child] retiring \u2014 ${t}; ${path.basename($,".sock")} (pid ${process.pid}) is finishing in-flight work, then exiting`);const s=ke(Number.POSITIVE_INFINITY);s?.workers&&console.log(`[child] its ${s.workers} queue worker(s) stopped taking new jobs, still processing ${s.runningAtStop} job(s)`);try{fs.writeFileSync(sockRetiringPath($),String(process.pid),{flag:"w",mode:384})}catch{}await new Promise(u=>{setTimeout(u,Ue).unref?.()}),cleanupSock($),ye.close();const l=Date.now();for(;Date.now()-l<de;){ye.closeIdleConnections?.();let u=0;for(const y of W)u+=ee(y).unanswered;if(B.inflight+K(B)===0&&u===0&&T().count===0)break;await new Promise(y=>{setTimeout(y,250).unref?.()})}setTimeout(()=>process.exit(0),3e4).unref?.();try{await g?.close()}catch(u){console.error("[child] close error while retiring:",u)}process.exit(0)}h(U,"F"),a(U,"retire"),process.on("beforeExit",()=>{try{inspector?.close?.()}catch{}});const ae=a(async t=>{console.log(`[child ${t}] shutting down\u2026`);const s=g?.close().catch(u=>console.error("[child] close error:",u)),l=new Promise(u=>ye.close(()=>u()));cleanupSock($),setTimeout(()=>process.exit(0),700).unref(),await Promise.all([s,l]),process.exit(0)},"shutdown");["SIGINT","SIGTERM","SIGHUP","SIGQUIT","SIGUSR2"].forEach(t=>{process.on(t,()=>{if(t==="SIGTERM"&&!b&&(0,handoff_retire_1.handoffRetireRequested)(SOCK_DIR,POD_GENERATION)){U("this generation was handed over to a newer one");return}inspector?.close?.(),ae(t)})})})()}else{let c=h(function(_){K.push(_),K.length>z&&K.splice(0,K.length-z),Ee?.write((0,inspector_secret_1.redactInspectorUrls)(_.replace(W,"")));for(const b of ee)try{const v=b.plain?_.replace(W,""):_;b.res.write(b.redact?(0,inspector_secret_1.redactInspectorUrls)(v):v)}catch{ee.delete(b)}},"he");a(c,"emitLogLine");const f=12,g=process.env.LENSMCP_PROJECT||SERVICE_NAME||"service",E=(0,pod_memory_events_1.createPodMemoryPublisher)(process.env.LENSMCP_EVENT_FILE),L=a(_=>({project:g,service:SERVICE_NAME||g,pod:_.id,pid:_.proc.pid??0,podGeneration:POD_GENERATION}),"podIdentity"),Z=["\x1B[36m","\x1B[33m","\x1B[35m","\x1B[32m","\x1B[34m","\x1B[31m"],He="\x1B[0m",le=Math.max(1,Number(process.env.CHILD_COUNT||1)),B=LENSMCP_WS_KEY||path.basename(process.cwd()),de=a(_=>(0,process_name_1.namedExecPath)((0,process_name_1.processName)(B,SERVICE_NAME||"service",_)),"execPathFor");let T=(()=>{const _=Number(process.env.LENSMCP_DEBUG_PORT||"");return Number.isInteger(_)&&_>1024?_:0})();const ke=20;T&&(console.warn("[parent] DEBUGGER ENABLED \u2014 pods and workers open a Node inspector. Node's inspector has NO authentication: the ws:// URL's UUID is the whole credential, and any account on this host that obtains it can run code as you. Do not enable this on a shared machine. (issues/closed/codex-security-06)"),console.warn(usesFixedInspectorPorts()?`[parent] ${exports.DEBUG_FIXED_PORTS_ENV} is set \u2014 inspectors bind PREDICTABLE ports (${T}+slot, workers ${T}+${ke}+i). Any account on this host can connect to 127.0.0.1:${T} and read the session UUID from /json/list. Unset it to use ephemeral ports.`:`[parent] Inspectors bind an EPHEMERAL loopback port; attach via the printed "Debugger listening" URL, or \`lensmcp debug <service>\` (control socket). Set ${exports.DEBUG_FIXED_PORTS_ENV}=1 for fixed ports if your IDE needs a pre-configured attach port \u2014 any account on this host can then reach them.`));const pe=process.env.LENSMCP_LOG_FILE||"",Ee=pe?(()=>{try{fs.mkdirSync(path.dirname(pe),{recursive:!0});const _=fs.createWriteStream(pe,{flags:"a",mode:384});try{fs.chmodSync(pe,384)}catch{}return _}catch(_){return console.warn(`[parent] cannot open log file ${pe}:`,_.message),null}})():null,W=/\x1b\[[0-9;]*m/g,z=2e3,K=[],ee=new Set,te=(0,devserver_transport_1.gatewayManaged)();for(const _ of["log","info","warn","error"]){const b=console[_].bind(console),v=_==="log"||_==="info"?process.stdout:process.stderr;console[_]=(...j)=>{b(...j.map(I=>typeof I=="string"?(0,inspector_secret_1.forStream)(v,te,I):I)),c(j.map(I=>typeof I=="string"?I:util.inspect(I)).join(" ")+`
|
|
13
|
+
`)}}const De=a(_=>Z[(_-1)%Z.length],"colorFor"),R=a(_=>{if(le===1)return"";const b=`[child#${_}] `;return`${De(_)}${b}${He}`},"tagFor"),ue=a(_=>_.startsWith("{")&&_.endsWith("}"),"isJsonLog"),re=a((_,b,v)=>{const j=prettyFactory({sync:!0,colorize:!0,crlf:!0,messageKey:"message",errorLikeObjectKeys:["err","error"],errorProps:"type,message,stack",ignore:["logContext","context","hostname","req","res","err.driverError","module","cloudEnvironment","frontegg-application-id","frontegg-tenant-id","frontegg-trace-id","frontegg-vendor-id","host","service","version","err","error"].join(","),messageFormat:"{if module}[{module}] {end}{if context}[{context}] {end}{if logContext}[{logContext}] {end}{message}",customPrettifiers:{stack:a(q=>`
|
|
14
|
+
`+String(q),"stack")}}),I=a((q,k)=>{const F=q==="stdout"?process.stdout:process.stderr;try{v?.(k)}catch{}const H=ue(k)?j(k):`${k}
|
|
15
|
+
`;F.write((0,inspector_secret_1.forStream)(F,te,`${b}${H}`)),c(`${b}${H}`)},"write"),he=a((q,k)=>{if(!q)return;const F=readline.createInterface({input:q});F.on("line",H=>I(k,H)),F.on("close",()=>{})},"attach");he(_.stdout,"stdout"),he(_.stderr,"stderr")},"wireProcLogging"),Ue=a(_=>re(_.proc,R(_.id),b=>_.tail.push(b)),"wireChildLogging");(async()=>{ensureOwnerOnlyDir(SOCK_DIR);const _=httpProxy.createProxyServer({});let b=Number(process.env.PORT)||0;b||(b=9090);const v=[],j=new Set;function I(){let e=0;for(;j.has(e);)e++;return j.add(e),e}h(I,"$"),a(I,"allocDebugSlot");let he=1,q=0,k=!1,F=le,H=[],fe=0;const Pe=(0,swap_mode_1.swapMode)(),V=(()=>{const e=Number(process.env.LENSMCP_POD_BOOT_GRACE_MS);return Number.isFinite(e)&&e>=0?e:12e4})(),M=a(e=>e.proc.exitCode!==null||e.proc.signalCode!==null,"childExited"),xe=a(e=>e.booting&&!M(e)&&Date.now()-e.spawnedAt<V,"stillBooting");function Y(){return v.filter(e=>e.healthy&&typeof e.socketPath=="string")}h(Y,"K"),a(Y,"healthyChildren");let oe,Se=0,J;const _e={project:g,service:SERVICE_NAME||g,podGeneration:POD_GENERATION};function Ne(e){const r=(0,service_build_events_1.buildAccountOf)(e.building);r&&r.startedAt!==Se&&(Se=r.startedAt,E.publish((0,service_build_events_1.buildServiceBuildEvent)(_e,"started",r,{root:process.cwd()})));const n=(0,service_build_events_1.buildAccountOf)(e.failed);n&&(Se=0,E.publish((0,service_build_events_1.buildServiceBuildEvent)(_e,"failed",n,{root:process.cwd()})))}h(Ne,"We"),a(Ne,"recordBuildProgress");function ge(e){if(!e||typeof e!="object")return;const r=e;if(r.schemaVersion===1){Ne(r),"failed"in r&&delete r.failed,oe=r;for(const n of v)tell(n.proc,{type:"watcher",testimony:r})}}h(ge,"Pe"),a(ge,"recordWatcherTestimony");function ne(e,r=256*1024){return new Promise(n=>{let p="",i=!1;e.on("data",o=>{i||(p+=o,p.length>r&&(i=!0))}),e.on("end",()=>{if(i||!p)return n(void 0);try{n(JSON.parse(p))}catch{n(void 0)}}),e.on("error",()=>n(void 0))})}h(ne,"_e"),a(ne,"readJsonBody");function se(){const e=Y();if(e.length===0)return null;const r=q%e.length;return q=(q+1)%e.length,e[r]}h(se,"ge"),a(se,"pickChild");function ie(e,r){const n=`Child#${e.id}`,p=SERVICE_NAME||g,i=Date.now();if(r.type==="pod-memory"){const o=r.report;if(!o||typeof o.live!="number")return;e.memory.latest=o,e.memory.history.push(o),e.memory.history.length>12&&e.memory.history.splice(0,e.memory.history.length-12),console.log(`[parent] ${(0,pod_memory_1.describePodMemory)(n,o)}`),E.publish((0,pod_memory_events_1.buildPodMemoryEvent)(L(e),o))}else if(r.type==="pod-memory-retained"){const o=r.retained;if(!o||typeof o.gen!="number")return;e.memory.retained.set(o.gen,{...o,at:i}),console.warn(`[parent] ${(0,pod_memory_1.describeRetained)(n,p,o)}`),E.publish((0,pod_memory_events_1.buildPodRetainedEvent)(L(e),o,i))}else{const o=r.released;if(!o||typeof o.gen!="number")return;e.memory.retained.delete(o.gen),console.log(`[parent] ${(0,pod_memory_1.describeReleased)(n,p,o)}`),E.publish((0,pod_memory_events_1.buildPodReleasedEvent)(L(e),o,i))}}h(ie,"ye"),a(ie,"recordPodMemory");const ve=new Map;let ye=0;async function $(){const e=he++,r=childSockPath(e);cleanupSock(r);const n=(0,dev_devtool_1.sourceMapExecArgv)();__filename.endsWith(".ts")&&n.unshift("--require","@swc-node/register"),n.push(...(0,inspector_secret_1.inspectorPublishExecArgv)(usesFixedInspectorPorts()));const p=T?I():-1,i=(0,node_child_process_1.fork)(__filename,{env:{...process.env,APP_RUNNER:"1",CHILD_SOCK_PATH:r,...p>=0&&{CHILD_DEBUG_PORT:String(inspectorPortFor(T,p))}},stdio:["inherit","pipe","pipe","ipc"],execArgv:n,execPath:de("pod")}),o={id:e,proc:i,healthy:!1,lastError:null,debugSlot:p,tail:new exit_reason_1.TailBuffer,booting:!0,spawnedAt:Date.now(),bootReloadSeq:fe,memory:{history:[],retained:new Map}};return i.on("error",S=>console.error(`[parent] Child#${e}: ${S.message}`)),i.on("message",S=>{if(!S||typeof S!="object")return;const d=S;if(d.type==="ready")o.socketPath=String(d.socketPath),o.healthy=!0,o.booting=!1,console.log(`[parent] Child#${o.id} ready on socket ${o.socketPath}`),oe&&tell(i,{type:"watcher",testimony:oe}),fe!==o.bootReloadSeq&&(Pe==="process"?Q():tell(i,{type:"reload"}));else if(d.type==="recycle-request")w(o,String(d.reason||"it has outgrown its bound"));else if(d.type==="inspector-url")o.inspectorUrl=String(d.url),console.log(`[parent] Child#${o.id} Debugger listening on ${d.url}`);else if(d.type==="reloaded"){if(U.has(o)){console.log(`[parent] Child#${o.id} finished a swap it began before it was retired \u2014 not serving it: a fresh pod has taken over`);return}o.socketPath=String(d.socketPath),o.healthy=!0,console.log(`[parent] Child#${o.id} hot-swapped on socket ${o.socketPath}`);const m=d.swap;m&&typeof m.generation=="number"&&typeof m.swaps=="number"&&E.publish((0,service_build_events_1.buildServiceSwapEvent)(L(o),{generation:m.generation,swaps:m.swaps,swapMs:typeof m.swapMs=="number"?m.swapMs:0,draining:typeof m.draining=="number"?m.draining:0},J,{root:process.cwd()}))}else d.type==="reload-error"?(o.lastError=String(d.error||"unknown reload error"),console.error(`[parent] Child#${o.id} reload error: ${o.lastError}`),o.healthy=!1):d.type==="boot-error"?(o.lastError=String(d.error||"unknown boot error"),console.error(`[parent] Child#${o.id} boot error: ${o.lastError}`),o.healthy=!1,o.booting=!1):d.type==="pod-memory"||d.type==="pod-memory-retained"||d.type==="pod-memory-released"?ie(o,d):d.type==="heap-snapshot-result"&&ve.get(Number(d.id))?.(d)}),i.on("exit",(S,d)=>{o.booting=!1;for(const D of o.memory.retained.values()){const x={gen:D.gen,closedAt:D.closedAt,ageMs:Date.now()-D.closedAt,reason:"pod-exited"};console.log(`[parent] ${(0,pod_memory_1.describeReleased)(`Child#${o.id}`,SERVICE_NAME||g,x)}`),E.publish((0,pod_memory_events_1.buildPodReleasedEvent)(L(o),x,Date.now()))}o.memory.retained.clear(),o.memory.latest&&E.publish((0,pod_memory_events_1.buildPodExitedEvent)(L(o),{code:S,signal:d},Date.now())),o.debugSlot>=0&&(j.delete(o.debugSlot),o.debugSlot=-1);const m=d==="SIGINT"||d==="SIGTERM"||S===0;if(m?console.log(`[parent] Child#${o.id} exited cleanly (code=${S}, signal=${d??"none"})`):(console.error((0,exit_reason_1.crashReport)(`[parent] Child#${o.id} crashed (code=${S}, signal=${d??"none"}, pid=${o.proc.pid}, ${o.healthy?"was serving":"was not ready"})`,S,d,o.tail.snapshot())),o.lastError||(o.lastError=`Child exited abnormally (code=${S}, signal=${d??"none"})`)),o.healthy=!1,cleanupSock(o.socketPath,o.proc.pid),o.socketPath=void 0,!m&&!k){const D=v.indexOf(o);D>=0&&v.splice(D,1);const x=Date.now();if(H=H.filter(X=>x-X<3e4),H.length>=5){console.error(`[parent] crash-loop detected (${H.length} respawns/30s) \u2014 pausing auto-respawn; POST /webpack/reload to retry`);return}H.push(x),setTimeout(()=>{const X=v.filter(Ie=>Ie.proc.killed===!1).length;!k&&X<F&&(console.log(`[parent] respawning a crashed pod (${X}/${F} live)`),$().catch(()=>{}))},1500).unref?.()}}),v.push(o),Ue(o),o}h($,"M"),a($,"spawnChild");async function we(e){F=Math.max(F,e);const r=v.filter(p=>p.proc.killed===!1),n=e-r.length;for(let p=0;p<n;p++)await $()}h(we,"me"),a(we,"ensurePoolSize");async function Ae(){const e=v.filter(r=>(!r.healthy||typeof r.socketPath!="string")&&!xe(r));await Promise.all(e.map(async r=>{try{r.proc.kill("SIGTERM")}catch{}cleanupSock(r.socketPath,r.proc.pid),r.socketPath=void 0;const n=v.indexOf(r);n>=0&&v.splice(n,1),await $()}))}h(Ae,"Ue"),a(Ae,"respawnUnhealthy");const U=new Set;let ae=!1,t=0;const s=3e4,l=(()=>{const e=Number(process.env.LENSMCP_SWAP_DRAIN_MS);return(Number.isFinite(e)&&e>=0?e:15*6e4)+6e4})();async function u(e){const r=Date.now(),n=await $(),p=Date.now()+V;for(;!n.healthy&&!n.lastError&&!M(n)&&Date.now()<p;)await new Promise(i=>{setTimeout(i,100).unref?.()});if(k)return{why:"shutting down"};if(!n.healthy){const i=v.indexOf(n);i>=0&&v.splice(i,1);try{n.proc.kill("SIGTERM")}catch{}return{why:`its successor Child#${n.id} did not come up (${n.lastError??"no answer in time"})`}}return y(e),{fresh:n,readyMs:Date.now()-r}}h(u,"_"),a(u,"replacePod");function y(e){const r=v.indexOf(e);if(r>=0&&v.splice(r,1),e.healthy=!1,M(e))return;U.add(e),postRetiringNotice(e.socketPath,e.proc.pid);const n=setTimeout(()=>{if(!M(e)){console.error(`[parent] Child#${e.id} was still running ${l}ms after it was retired \u2014 killing it`);try{e.proc.kill("SIGKILL")}catch{}}},l);if(n.unref?.(),e.proc.once("exit",()=>{clearTimeout(n),U.delete(e)}),!tell(e.proc,{type:"retire"}))try{e.proc.kill("SIGTERM")}catch{}}h(y,"g"),a(y,"retirePod");async function w(e,r){const n=a(i=>{console.log(`[parent] Child#${e.id} asked for a fresh pod (${r}) \u2014 not now: ${i}`),tell(e.proc,{type:"recycle-declined"})},"decline");if(k||!v.includes(e))return;if(ae)return n("another pod is already being replaced");const p=Date.now()-t;if(p<s)return n(`a pod was replaced ${Math.round(p/1e3)}s ago`);ae=!0,console.log(`[parent] Child#${e.id} asked for a fresh pod \u2014 ${r}. Starting one; Child#${e.id} keeps serving until it is ready.`);try{const i=await u(e);if("why"in i){i.why!=="shutting down"&&n(i.why);return}t=Date.now(),console.log(`[parent] Child#${i.fresh.id} took over from Child#${e.id} (pid ${e.proc.pid} \u2192 ${i.fresh.proc.pid})`)}catch(i){n(`could not start a successor: ${i?.message??String(i)}`)}finally{ae=!1}}h(w,"y"),a(w,"recyclePod");let O,A=!1;function Q(){if(O){A=!0;return}O=(async()=>{do{A=!1;const e=fe;for(;ae&&!k;)await new Promise(r=>{setTimeout(r,100).unref?.()});for(const r of Y().filter(n=>n.bootReloadSeq<e)){if(k)break;if(!(!v.includes(r)||!r.healthy)){ae=!0;try{N(),console.log(`[parent] A new build \u2014 starting a fresh pod for it; Child#${r.id} keeps serving the previous build until it is ready.`);const n=await u(r);if("why"in n){n.why!=="shutting down"&&console.error(`[parent] Child#${r.id} keeps serving the previous build \u2014 ${n.why}`);continue}console.log(`[parent] Child#${n.fresh.id} took over from Child#${r.id} with the new build (pid ${r.proc.pid} \u2192 ${n.fresh.proc.pid}, ready in ${(n.readyMs/1e3).toFixed(1)}s while Child#${r.id} served)`),E.publish((0,service_build_events_1.buildServiceSwapEvent)(L(n.fresh),{generation:1,swaps:0,swapMs:n.readyMs,draining:U.size,handoff:{fromPid:r.proc.pid??0}},J,{root:process.cwd()}))}catch(n){console.error(`[parent] Child#${r.id} keeps serving the previous build \u2014 could not start a successor: ${n?.message??String(n)}`)}finally{ae=!1}}}}while(A&&!k)})().finally(()=>{O=void 0})}h(Q,"q"),a(Q,"handoffForReload");function N(){const e=(0,swap_mode_1.maxRetiring)(),r=[...U].filter(n=>!M(n));for(;r.length>=e;){const n=r.shift();console.error(`[parent] Child#${n.id} (pid ${n.proc.pid}) was still finishing its work when a newer build replaced its successor too \u2014 stopping it (LENSMCP_SWAP_MAX_RETIRING=${e})`);try{n.proc.kill("SIGTERM")}catch{}}}h(N,"A"),a(N,"capRetiring");const C=[];function qe(e){const r=path.dirname(path.isAbsolute(BUNDLE_PATH)?BUNDLE_PATH:path.resolve(BUNDLE_PATH)),n=path.join(r,`${e}.js`);if(!fs.existsSync(n))return console.error(`[parent] Worker "${e}" bundle not found: ${n}`),null;const p=(0,dev_devtool_1.sourceMapExecArgv)();__filename.endsWith(".ts")&&p.unshift("--require","@swc-node/register");try{p.push("--require",require.resolve("@lensmcp/node-instrumentation/register"))}catch{}const i=inspectorPortFor(T||9229,ke+Math.max(0,WORKER_NAMES.indexOf(e)));p.push(T?`--inspect=127.0.0.1:${i}`:`--inspect-port=127.0.0.1:${i}`,...(0,inspector_secret_1.inspectorPublishExecArgv)(usesFixedInspectorPorts()));const o=(0,node_child_process_1.fork)(n,{env:process.env,stdio:["inherit","pipe","pipe","ipc"],execArgv:p,execPath:de(`w-${e}`)}),S={name:e,proc:o,debugPort:i};return C.push(S),o.on("error",d=>console.error(`[parent] Worker "${e}": ${d.message}`)),re(o,`\x1B[35m[worker:${e}] \x1B[0m`,d=>{const m=/Debugger listening on (wss?:\/\/\S+)/.exec(d);m&&(S.inspectorUrl=m[1])}),o.on("exit",(d,m)=>{m==="SIGINT"||m==="SIGTERM"||d===0||console.error(`[parent] Worker "${e}" crashed (code=${d}, signal=${m??"none"})`);const D=C.indexOf(S);D>=0&&C.splice(D,1)}),console.log(`[parent] Worker "${e}" started (pid=${o.pid})`),S}h(qe,"Ye"),a(qe,"spawnWorkerProcess");const Ve=(()=>{const e=Number(process.env.LENSMCP_SWAP_DRAIN_MS);return Number.isFinite(e)&&e>=0?e:15*6e4})(),Je=(()=>{const e=Number(process.env.LENSMCP_SWAP_MAX_DRAINING);return Number.isFinite(e)&&e>=1?Math.floor(e):1})(),me=new Set,Be=a(e=>e.proc.exitCode!==null||e.proc.signalCode!==null,"workerExited");function Ge(e,r){if(me.delete(e),!Be(e)){console.error(`[parent] Worker "${e.name}" (pid=${e.proc.pid}) ${r} \u2014 killing it. A worker that returns from its SIGTERM handler but leaves a handle open (a Redis client handed to BullMQ is not closed by worker.close()) never exits on its own: close what it opened, or call process.exit().`);try{e.proc.kill("SIGKILL")}catch{}}}h(Ge,"He"),a(Ge,"killDrainingWorker");function je(e){try{e.proc.kill("SIGTERM")}catch{}if(Be(e))return;const r=[...me].filter(p=>p.name===e.name);for(;r.length>=Je;)Ge(r.shift(),`was still running when a later reload replaced its successor (cap ${Je})`);me.add(e);const n=setTimeout(()=>Ge(e,`was still running ${Ve}ms after SIGTERM`),Ve);n.unref?.(),e.proc.once("exit",()=>{clearTimeout(n),me.delete(e)})}h(je,"Je"),a(je,"retireWorker");function Xe(){for(const e of[...C])je(e);C.length=0;for(const e of WORKER_NAMES)qe(e)}h(Xe,"et"),a(Xe,"restartWorkers");const ot=debounce(async()=>{fe+=1;const e=Y();if(e.length>0)if(Pe==="process")Q();else{console.log(`[parent] Forwarding reload to ${e.length} child(ren)`);for(const r of e)tell(r.proc,{type:"reload"})}await Ae(),WORKER_NAMES.length>0&&Xe()},200),ze=a((e,r)=>{const n=(0,notice_generation_1.noticeGeneration)(e.headers);return n===void 0||n===POD_GENERATION?!1:(e.resume(),r.writeHead(409,{"content-type":"application/json"}),r.end(JSON.stringify({ok:!1,generation:POD_GENERATION,sentFor:n})),e.url==="/webpack/reload"&&console.log(`[parent] a build of generation g${n} reached generation g${POD_GENERATION} \u2014 not reloaded: it is not this generation's build`),!0)},"refusedForAnotherGeneration"),Re=a(async(e,r)=>{if(e.method==="POST"&&e.url==="/webpack/reload"){if(!(0,devserver_transport_1.mayDriveThePool)(e))return refusePoolCommand(e,r);if(ze(e,r))return;r.writeHead(200,{"content-type":"application/json"}),r.end(JSON.stringify({ok:!0})),ne(e).then(i=>{const o=i;J=(0,service_build_events_1.buildAccountOf)(o?.build),Se=0,ge(o?.watcher)}),ot();return}if(e.method==="POST"&&e.url==="/webpack/watching"){if(!(0,devserver_transport_1.mayDriveThePool)(e))return refusePoolCommand(e,r);if(ze(e,r))return;const i=await ne(e);ge(i),r.writeHead(200,{"content-type":"application/json"}),r.end(JSON.stringify({ok:!0,relayed:oe!==void 0}));return}if(e.method==="POST"&&e.url==="/webpack/scale"){if(!(0,devserver_transport_1.mayDriveThePool)(e))return refusePoolCommand(e,r);let i="";e.on("data",o=>{i+=o}),e.on("end",async()=>{let o=0;try{o=Number(JSON.parse(i||"{}").pods)||0}catch{}o=Math.max(1,Math.min(o,16)),await we(o),r.writeHead(200,{"content-type":"application/json"}),r.end(JSON.stringify({ok:!0,pods:o}))});return}if(e.method==="GET"&&e.url?.startsWith("/webpack/logs")){const i=new URL(e.url,"http://localhost").searchParams,o=Math.min(Math.max(Number(i.get("tail")??"100")||0,0),z),S=i.get("follow")!=="0",d=i.get("plain")==="1",m=!(0,devserver_transport_1.isOwnerOnlyTransport)(e);r.writeHead(200,{"content-type":"text/plain; charset=utf-8","cache-control":"no-cache"});const D=o===0?"":K.slice(-o).join(""),x=d?D.replace(W,""):D;if(r.write(m?(0,inspector_secret_1.redactInspectorUrls)(x):x),!S){r.end();return}const X={res:r,plain:d,redact:m};ee.add(X),e.on("close",()=>ee.delete(X));return}if(e.method==="POST"&&e.url?.startsWith("/webpack/debug")){if(!(0,devserver_transport_1.isOwnerOnlyTransport)(e)){r.writeHead(404,{"content-type":"application/json"}),r.end(JSON.stringify({error:"not found"}));return}const i=Number(new URL(e.url,"http://localhost").searchParams.get("port")||"");Number.isInteger(i)&&i>1024&&(T=i),T||(T=9229);const o=v.filter(d=>d.proc.exitCode===null&&d.proc.signalCode===null);for(const d of o)d.debugSlot<0&&(d.debugSlot=I()),tell(d.proc,{type:"debug-open",port:inspectorPortFor(T,d.debugSlot)});for(const d of C)try{d.proc.kill("SIGUSR1")}catch{}const S=Date.now()+2e3;for(;Date.now()<S&&o.some(d=>!d.inspectorUrl);)await new Promise(d=>setTimeout(d,50));r.writeHead(200,{"content-type":"application/json"}),r.end(JSON.stringify({ok:!0,basePort:T,fixedPorts:usesFixedInspectorPorts(),pods:o.map(d=>({id:d.id,inspectorUrl:d.inspectorUrl??null})),workers:C.map(d=>({name:d.name,port:d.debugPort||(0,inspector_secret_1.inspectorPortOf)(d.inspectorUrl),inspectorUrl:d.inspectorUrl??null}))},null,2)+`
|
|
16
|
+
`);return}if(e.method==="GET"&&e.url==="/webpack/memory"){if(!(0,devserver_transport_1.isOwnerOnlyTransport)(e)){r.writeHead(404,{"content-type":"application/json"}),r.end(JSON.stringify({error:"not found"}));return}const i=path.isAbsolute(BUNDLE_PATH)?BUNDLE_PATH:path.resolve(BUNDLE_PATH),o=[...v,...U].map(S=>({id:S.id,pid:S.proc.pid??0,podGeneration:POD_GENERATION,healthy:S.healthy,retiring:U.has(S),latest:S.memory.latest??null,history:S.memory.history,retained:[...S.memory.retained.values()]}));r.writeHead(200,{"content-type":"application/json","cache-control":"no-store"}),r.end(JSON.stringify({ok:!0,service:SERVICE_NAME,project:g,bundle:{path:i},pods:o},null,2)+`
|
|
17
|
+
`);return}if(e.method==="POST"&&e.url?.startsWith("/webpack/heap")){if(!(0,devserver_transport_1.isOwnerOnlyTransport)(e)){r.writeHead(404,{"content-type":"application/json"}),r.end(JSON.stringify({error:"not found"}));return}const i=a((G,Ce)=>{r.writeHead(G,{"content-type":"application/json"}),r.end(JSON.stringify(Ce,null,2)+`
|
|
18
|
+
`)},"reply"),o=new URL(e.url,"http://localhost").searchParams,S=Number(o.get("pod")||""),d=o.has("maxMb")?Number(o.get("maxMb")):void 0;if(d!==void 0&&!(Number.isFinite(d)&&d>0)){i(400,{ok:!1,error:"maxMb takes a positive number of MB"});return}const m=Number.isInteger(S)&&S>0?v.find(G=>G.id===S):Y()[0];if(!m||M(m)){i(404,{ok:!1,error:S?`no pod #${S} \u2014 running: ${v.map(G=>`#${G.id}`).join(", ")||"none"}`:"no pod is serving"});return}if(ve.size>0){i(409,{ok:!1,refused:"a heap snapshot is already being written for this service"});return}const D=(0,heap_snapshot_1.heapSnapshotPolicy)(),x=(0,heap_snapshot_1.heapSnapshotDir)();let X;try{(0,heap_snapshot_1.ensureHeapDir)(x);const G=(0,heap_snapshot_1.pruneHeapSnapshots)(x,D);G.length&&console.log(`[parent] removed ${G.length} older heap snapshot(s) from ${x}`),X=path.join(x,(0,heap_snapshot_1.heapSnapshotFileName)(SERVICE_NAME||g,m.id,m.proc.pid??0,m.memory.latest?.gen??0,Date.now()))}catch(G){i(500,{ok:!1,error:`cannot prepare ${x}: ${G.message}`});return}const Ie=++ye,Fe=(0,heap_snapshot_1.availableSystemMemory)();let Me;const P=await new Promise(G=>{const Ce=setTimeout(()=>G(void 0),6e5);Ce.unref?.(),ve.set(Ie,ct=>{clearTimeout(Ce),G(ct)}),Me=a(()=>{clearTimeout(Ce),G(void 0)},"onExit"),m.proc.once("exit",Me);const it={type:"heap-snapshot",id:Ie,file:X,...Fe?{available:Fe}:{},...d!==void 0?{maxHeapBytes:Math.floor(d*1048576)}:{}};tell(m.proc,it)||Me()}).finally(()=>{ve.delete(Ie),Me&&m.proc.off("exit",Me)});if(!P){i(504,{ok:!1,pod:m.id,error:"the pod did not finish the snapshot (it exited, or took longer than 10 minutes)"});return}P.ok?console.log(`[parent] Child#${m.id} wrote a ${Math.round((P.bytes??0)/1048576)} MB heap snapshot in ${P.ms} ms \u2192 ${P.file}`):console.warn(`[parent] Child#${m.id} heap snapshot not taken: ${P.refused??P.error}`),i(P.ok?200:P.refused?409:500,{ok:P.ok,pod:m.id,pid:m.proc.pid??0,service:SERVICE_NAME,bundle:path.isAbsolute(BUNDLE_PATH)?BUNDLE_PATH:path.resolve(BUNDLE_PATH),...Fe?{available:Fe}:{},...P.file?{file:P.file,bytes:P.bytes,ms:P.ms}:{},...P.live!==void 0?{live:P.live}:{},...P.gen!==void 0?{gen:P.gen,closedAlive:P.closedAlive??[]}:{},...P.refused?{refused:P.refused}:{},...P.error?{error:P.error}:{}});return}const n=matchGatewayRoute(e);if(n?.prependPrefix&&!e.url?.startsWith(n.prependPrefix)&&(e.url=n.prependPrefix+(e.url??"/")),n?.target){applyGatewayMiddleware(e),_.web(e,r,{target:n.target,autoRewrite:typeof n.target=="string",changeOrigin:!0},i=>{console.error(`[parent] proxy error to ${n.target}:`,i),r.statusCode=502,r.setHeader("content-type","text/plain; charset=utf-8"),r.end(`Upstream error from ${n.target}.`)});return}if(SERVICE_PREFIX){if(!e.url?.startsWith(SERVICE_PREFIX)){r.writeHead(404,{"content-type":"text/plain; charset=utf-8"}),r.end(`Not found. This service is mounted at ${SERVICE_PREFIX}/`);return}e.url=e.url.slice(SERVICE_PREFIX.length)||"/"}applyGatewayMiddleware(e);const p=se();if(!p){r.statusCode=503,r.setHeader("content-type","text/plain; charset=utf-8");const i=v.map(o=>`#${o.id}: ${o.lastError??"no error recorded"}`).join(`
|
|
19
19
|
`);r.end(`No healthy children available. POST /webpack/reload to recover.
|
|
20
20
|
|
|
21
21
|
Last errors:
|
|
22
|
-
${
|
|
23
|
-
${
|
|
22
|
+
${i}`);return}_.web(e,r,{target:{socketPath:p.socketPath},headers:{"x-proxy-child-id":String(p.id)}},i=>{console.error(`[parent] proxy error to Child#${p.id}:`,i),p.healthy=!1,p.lastError=String(i?.stack||i),r.statusCode=502,r.setHeader("content-type","text/plain; charset=utf-8"),r.end(`Upstream error from Child#${p.id}. Try /webpack/reload.
|
|
23
|
+
${p.lastError}`)})},"requestHandler");let ce,Te,Ye;const $e=[];if(GATEWAY_HTTPS){const e=require("./basic-ssl"),r=GATEWAY_ROUTES.map(p=>p.host).filter(p=>!!p),n=(0,checkout_cache_1.checkoutCacheDir)(process.cwd(),"davnx-webpack");Te=e.getCertificateSync(n,SERVICE_NAME||"lensmcp.dev",r),Ye=e.caCertPath(),ce=require("node:https").createServer({key:Te,cert:Te},Re)}else ce=http.createServer(Re);const Qe=a((e,r,n)=>{const p=matchGatewayRoute(e);if(p?.prependPrefix&&!e.url?.startsWith(p.prependPrefix)&&(e.url=p.prependPrefix+(e.url??"/")),p?.target){_.ws(e,r,n,{target:p.target,changeOrigin:!0},()=>r.destroy());return}const i=se();if(!i){r.destroy();return}_.ws(e,r,n,{target:{socketPath:i.socketPath}},()=>r.destroy())},"upgradeHandler");ce.on("upgrade",Qe);const Ze=2e3;let et=!1;ce.on("error",e=>{if(e.code==="EADDRINUSE"){et||(et=!0,console.warn(`[parent] public port ${b} already in use \u2014 continuing on the unix-socket pool only (gateway routing is unaffected) and retrying the bind every ${Ze/1e3}s. Give this service a distinct cluster.port if this is not a rolling handoff.`)),setTimeout(()=>{!k&&!ce.listening&&ce.listen(b)},Ze).unref?.();return}console.error("[parent] public server error:",e)}),await we(le);for(const e of WORKER_NAMES)qe(e);SOCKET_ONLY?console.log(`[parent] socket-only: no TCP listener (port ${b} is not bound \u2014 the gateway reaches this service through its socket pool)`):ce.listen(b,()=>{const e=GATEWAY_HTTPS?"https":"http";console.log(`[parent] Listening on ${e}://localhost:${b}`),SERVICE_PREFIX&&console.log(`[parent] Service prefix: "${SERVICE_PREFIX}" (enforced \u2014 requests without it will get 404)`),gatewayMiddleware&&console.log(`[parent] Gateway middleware: ACTIVE (${GATEWAY_MIDDLEWARE_PATH})`),GATEWAY_ROUTES.length>0&&console.log(`[parent] Gateway routes: ${GATEWAY_ROUTES.map(r=>`${r.host??"*"}${r.prefix??"/"}\u2192${r.target??"children"}`).join(" ")}`),Ye&&(console.log("[parent] HTTPS dev CA (trust ONCE, then rotations/new hostnames stay green):"),console.log(`[parent] sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain ${Ye}`)),console.log(`POST ${e}://localhost:${b}/webpack/reload to trigger rolling swap/respawn`)});const Le=Number(process.env.INTERNAL_PORT||0);if(Le>0&&!SOCKET_ONLY){const e=a((n,p)=>{const i=se();if(!i){p.statusCode=503,p.setHeader("content-type","text/plain; charset=utf-8"),p.end("No healthy children available.");return}_.web(n,p,{target:{socketPath:i.socketPath}},o=>{i.healthy=!1,i.lastError=String(o?.stack||o),p.statusCode=502,p.end(`Upstream error from Child#${i.id}.`)})},"internalHandler"),r=http.createServer(e);r.on("upgrade",(n,p,i)=>{const o=se();if(!o){p.destroy();return}_.ws(n,p,i,{target:{socketPath:o.socketPath}},()=>p.destroy())}),r.on("error",n=>{console.warn(`[parent] internal port ${Le} unavailable (${n.code}).`)}),r.listen(Le,()=>{console.log(`[parent] Internal (service-to-service, no gateway middleware) on http://localhost:${Le}`)}),$e.push(r)}const nt=SOCKET_ONLY?[]:(()=>{try{return JSON.parse(process.env.GATEWAY_EXTRA_PORTS||"[]")}catch{return[]}})();for(const e of nt){if(!Number.isInteger(e)||e===Number(b))continue;const r=GATEWAY_HTTPS?require("node:https").createServer({key:Te,cert:Te},Re):http.createServer(Re);r.on("upgrade",Qe),r.on("error",n=>{console.warn(`[parent] extra port ${e} unavailable (${n.code}) \u2014 main port still up.`)}),r.listen(e,()=>{console.log(`[parent] Also listening on ${GATEWAY_HTTPS?"https":"http"}://localhost:${e}`)}),$e.push(r)}const be=path.join(SOCK_DIR,"parent.sock");claimSock(be),(0,handoff_retire_1.clearHandoffRetire)(SOCK_DIR,POD_GENERATION);const Oe=http.createServer(Re);Oe.on("error",e=>{console.warn(`[parent] control socket unavailable (${e.code}) \u2014 lensmcp logs/debug attach disabled.`)}),Oe.listen(be),$e.push(Oe);function tt(){k=!0;const e=[...v,...U];console.log(`[SIGTERM] [parent] generation g${POD_GENERATION} was handed over to a newer one \u2014 ${e.length} pod(s) finish their in-flight work, then it exits`);const r=sockOwnedByAnother(be);cleanupSock(be);for(const i of $e)if(!(i===Oe&&r))try{i.close()}catch{}try{ce.close()}catch{}for(const i of[...C])je(i);C.length=0;for(const i of v)if(!tell(i.proc,{type:"retire"}))try{i.proc.kill("SIGTERM")}catch{}const n=setTimeout(()=>{for(const i of e)if(!M(i)){console.error(`[parent] Child#${i.id} was still running ${l}ms after its generation was retired \u2014 killing it`);try{i.proc.kill("SIGKILL")}catch{}}},l);n.unref?.();const p=a(()=>{if(!(e.some(i=>!M(i))||[...me].some(i=>!Be(i)))){clearTimeout(n);for(const i of e)i.socketPath&&cleanupSock(i.socketPath,i.proc.pid);(0,handoff_retire_1.clearHandoffRetire)(SOCK_DIR,POD_GENERATION);try{fs.rmdirSync(SOCK_DIR)}catch{}console.log(`[parent] generation g${POD_GENERATION} retired`),process.exit(0)}},"finish");for(const i of e)i.proc.once("exit",p);for(const i of me)i.proc.once("exit",p);p()}h(tt,"ot"),a(tt,"retireGeneration");const rt=a(async e=>{k=!0,console.log(`[${e}] [parent] shutting down\u2026`);const r=sockOwnedByAnother(be);cleanupSock(be);for(const n of $e)if(!(n===Oe&&r))try{n.close()}catch{}for(const n of C)try{n.proc.kill("SIGTERM")}catch{}for(const n of[...me])Ge(n,"was still draining when its devserver shut down");for(const n of U)try{n.proc.kill("SIGTERM")}catch{}for(const n of v){try{n.proc.kill("SIGTERM")}catch{}n.socketPath&&cleanupSock(n.socketPath,n.proc.pid)}try{fs.rmdirSync(SOCK_DIR)}catch{}setTimeout(()=>process.exit(0),700).unref()},"shutdown");let Ke=0;const st=2e3;["SIGINT","SIGTERM","SIGHUP","SIGQUIT","SIGUSR2"].forEach(e=>process.on(e,()=>{if(e==="SIGTERM"){if(!k&&(0,handoff_retire_1.handoffRetireRequested)(SOCK_DIR,POD_GENERATION)){Ke=Date.now(),tt();return}if(Ke>0&&Date.now()-Ke<st)return}rt(e)}));const We=Number(process.env.LENSMCP_GATEWAY_PID??0);if(Number.isInteger(We)&&We>0){const e=setInterval(()=>{try{process.kill(We,0)}catch(r){if(r.code==="EPERM")return;clearInterval(e),console.error(`[parent] gateway (pid ${We}) is gone \u2014 shutting the pod down to avoid an orphan tree.`),rt("gateway-gone")}},5e3);e.unref()}})()}
|
package/notice-generation.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var i=Object.defineProperty;var s=(r,e)=>i(r,"name",{value:e,configurable:!0});var o=Object.defineProperty,t=s((r,e)=>o(r,"name",{value:e,configurable:!0}),"t");Object.defineProperty(exports,"__esModule",{value:!0}),exports.NotThisGeneration=exports.NOTICE_GENERATION_HEADER=void 0,exports.generationFromEnv=generationFromEnv,exports.noticeGeneration=noticeGeneration,exports.NOTICE_GENERATION_HEADER="x-lensmcp-pod-generation";function generationFromEnv(r=process.env){const e=Number(r.LENSMCP_POD_GENERATION);return Number.isInteger(e)&&e>0?e:void 0}s(generationFromEnv,"generationFromEnv"),t(generationFromEnv,"generationFromEnv");function noticeGeneration(r){const e=r[exports.NOTICE_GENERATION_HEADER],n=Number(Array.isArray(e)?e[0]:e);return Number.isInteger(n)&&n>0?n:void 0}s(noticeGeneration,"noticeGeneration"),t(noticeGeneration,"noticeGeneration");class NotThisGeneration extends Error{static{s(this,"NotThisGeneration")}static{t(this,"NotThisGeneration")}constructor(e,n){super(`the devserver on the control socket is generation ${n??"?"}, not ${e}`),this.sentFor=e,this.answeredBy=n}}exports.NotThisGeneration=NotThisGeneration;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lensmcp/cluster",
|
|
3
|
-
"version": "1.25.
|
|
3
|
+
"version": "1.25.2",
|
|
4
4
|
"description": "Run your Nx workspace as a local production cluster: pods on unix sockets with true HMR, one https gateway with per-project domains, scale-from-zero, autoscale, idle-kill, local-CA TLS — observed by the LensMCP lens.",
|
|
5
5
|
"main": "./index.js",
|
|
6
6
|
"types": "./index.d.ts",
|
|
@@ -57,9 +57,9 @@
|
|
|
57
57
|
}
|
|
58
58
|
},
|
|
59
59
|
"dependencies": {
|
|
60
|
-
"@lensmcp/core": "1.25.
|
|
61
|
-
"@lensmcp/node-instrumentation": "1.25.
|
|
62
|
-
"@lensmcp/nx-plugin": "1.25.
|
|
60
|
+
"@lensmcp/core": "1.25.2",
|
|
61
|
+
"@lensmcp/node-instrumentation": "1.25.2",
|
|
62
|
+
"@lensmcp/nx-plugin": "1.25.2",
|
|
63
63
|
"fastify": "^5.8.5",
|
|
64
64
|
"@fastify/reply-from": "^12.6.2",
|
|
65
65
|
"@typescript/native-preview": "^7.0.0-dev.20260707.2",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var X=Object.defineProperty;var $=(e,t)=>X(e,"name",{value:t,configurable:!0});var H=Object.defineProperty,M=$((e,t)=>H(e,"name",{value:t,configurable:!0}),"M"),C=Object.defineProperty,y=M((e,t)=>C(e,"name",{value:t,configurable:!0}),"y");Object.defineProperty(exports,"__esModule",{value:!0}),exports.EXECUTOR_MB_PER_MODULE=exports.DEFAULT_HEAVY_BARREL_THRESHOLDS=exports.HEAVY_BARREL_RULE=void 0,exports.analyzeBarrelImports=analyzeBarrelImports,exports.describeHeavyBarrel=describeHeavyBarrel;const tslib_1=require("tslib"),path=tslib_1.__importStar(require("node:path")),workspace_libraries_1=require("./workspace-libraries"),source_scan_1=require("./source-scan");exports.HEAVY_BARREL_RULE="bundle/heavy-barrel-import",exports.DEFAULT_HEAVY_BARREL_THRESHOLDS={minShare:.5,minModules:100,minBytes:1024*1024,maxNeededShare:.6};const MAX_IMPORTERS_LISTED=8,MAX_SYMBOLS_LISTED=12,MAX_SUBPATHS_LISTED=12,MAX_INTERNAL_LISTED=6,MAX_EXPORT_DEPTH=24,MAX_UNRESOLVED_SHARE=.1;class AliasResolver{static{$(this,"AliasResolver")}static{M(this,"AliasResolver")}static{y(this,"AliasResolver")}constructor(t,s){this.exists=s,this.exact=new Map,this.wildcards=[];for(const r of t){this.exact.set(r.name,r.rootEntry);for(const i of r.aliases)this.exact.set(i,r.rootEntry);for(const i of r.subpaths)this.exact.set(i.specifier,i.entry);for(const i of r.wildcards)this.wildcards.push(i)}this.wildcards.sort((r,i)=>i.prefix.length-r.prefix.length)}resolve(t,s){if(s.startsWith("."))return(0,workspace_libraries_1.resolveSourceFile)(path.resolve(path.dirname(t),s),this.exists);const r=this.exact.get(s);if(r)return r;const i=this.wildcards.find(u=>s.startsWith(u.prefix));return i?(0,workspace_libraries_1.resolveSourceFile)(path.join(i.dir,s.slice(i.prefix.length)),this.exists):void 0}}class ExportReader{static{$(this,"ExportReader")}static{M(this,"ExportReader")}static{y(this,"ExportReader")}constructor(t,s){this.source=t,this.aliases=s,this.cache=new Map,this.resolved=new Map}index(t){let s=this.cache.get(t);if(s===void 0){const r=this.source.read(t);s=r===void 0?null:(0,source_scan_1.scanExports)(r),this.cache.set(t,s)}return s}resolve(t,s){const r=`${t}\0${s}`;let i=this.resolved.get(r);return i===void 0&&(i=this.follow(t,s,0,new Set)??null,this.resolved.set(r,i)),i??void 0}follow(t,s,r,i){if(r>MAX_EXPORT_DEPTH)return;const u=`${t}\0${s}`;if(i.has(u))return;i.add(u);const a=this.index(t);if(!a)return;if(a.values.has(s))return{file:t,typeOnly:!1};if(a.types.has(s))return{file:t,typeOnly:!0};const l=a.namespaces.get(s);if(l!==void 0){const p=this.aliases.resolve(t,l);return p?{file:p,typeOnly:!1}:void 0}const d=a.reexports.get(s);if(d){const p=this.aliases.resolve(t,d.specifier);if(!p)return;const c=this.follow(p,d.name,r+1,i);return c?{...c,typeOnly:c.typeOnly||d.typeOnly}:void 0}if(s!=="default")for(const p of a.stars){const c=this.aliases.resolve(t,p);if(!c)continue;const h=this.follow(c,s,r+1,i);if(h)return h}}}const rel=y((e,t)=>path.relative(e,t)||t,"rel");function readRootUse(e,t,s,r){const i=y(a=>l=>r.resolve(a,l)===e.rootEntry,"toBarrel"),u=[];for(const a of t){const l=/\.(?:[cm]?[jt]sx?)$/.test(a)?s.source.read(a):void 0;if(l===void 0){u.push({file:a,values:[],typeOnly:0,wholeModule:!0});continue}const d=(0,source_scan_1.scanImports)(l,i(a));if(d.length===0){u.push({file:a,values:[],typeOnly:0,wholeModule:!0});continue}const p=new Set;let c=0,h=!1;for(const w of d){h||=w.wholeModule;for(const f of w.names)f.typeOnly?c++:p.add(f.imported)}u.push({file:a,values:[...p].sort(),typeOnly:c,wholeModule:h})}return{importers:u}}$(readRootUse,"readRootUse"),M(readRootUse,"readRootUse"),y(readRootUse,"readRootUse");function closureWithin(e,t,s,r,i){const u=new Set,a=[...t].filter(l=>l!==r&&s.has(l)&&i(l)===e);for(;a.length;){const l=a.pop();if(!u.has(l)){u.add(l);for(const d of s.get(l)?.dependencies??[])d!==r&&!u.has(d)&&i(d)===e&&s.has(d)&&a.push(d)}}return u}$(closureWithin,"closureWithin"),M(closureWithin,"closureWithin"),y(closureWithin,"closureWithin");function subpathFor(e,t,s,r,i,u,a=0){if(s===e.rootEntry)return;const l=u(s);if(l!==e)return l&&a<2?subpathFor(l,t,s,r,i,u,a+1):void 0;const d=e.subpaths.filter(f=>s.startsWith(path.dirname(f.entry)+path.sep)||s===f.entry).filter(f=>r.resolve(f.entry,t)?.file===s).sort((f,E)=>E.entry.length-f.entry.length);if(d[0])return{specifier:d[0].specifier,entry:d[0].entry,exists:!0};const p=path.dirname(e.rootEntry);for(const f of e.wildcards){if(!s.startsWith(f.dir))continue;const E=s.slice(f.dir.length).split(path.sep).join("/").replace(/\.(?:[cm]?[jt]sx?)$/,""),g=E.split("/")[0],v=(0,workspace_libraries_1.resolveSourceFile)(path.join(f.dir,g),i.exists);return v&&v!==s&&r.resolve(v,t)?.file===s?{specifier:`${f.prefix}${g}`,entry:v,exists:!0}:{specifier:`${f.prefix}${E.replace(/\/index$/,"")}`,entry:s,exists:!0}}const c=path.relative(p,s).split(path.sep),h=c.length>1?c[0]:c[0].replace(/\.(?:[cm]?[jt]sx?)$/,""),w=c.length>1?(0,workspace_libraries_1.resolveSourceFile)(path.join(p,h),i.exists)??path.join(p,h,"index.ts"):s;return{specifier:`${e.name}/${h}`,entry:w,exists:!1}}$(subpathFor,"subpathFor"),M(subpathFor,"subpathFor"),y(subpathFor,"subpathFor");function measure(e,t,s,r,i,u,a){if(!s.has(t.rootEntry))return;const l=y(o=>a(o)===t,"inLib"),d=e.modules.filter(o=>l(o.resource)),p=e.modules.filter(o=>!l(o.resource)&&o.dependencies.includes(t.rootEntry)).map(o=>o.resource).sort();if(p.length===0)return;const c=r.workspaceRoot,h=r.thresholds,w=d.filter(o=>o.resource!==t.rootEntry&&o.dependencies.includes(t.rootEntry)).map(o=>o.resource),f=new Set;for(const o of e.modules)if(!l(o.resource))for(const n of o.dependencies)n!==t.rootEntry&&l(n)&&f.add(n);const E=readRootUse(t,p,r,i),g=new Set(f),v=new Set,B=new Map,S=new Set,_=new Set;for(const o of E.importers)for(const n of o.values){if(_.add(n),B.has(n)||v.has(n)||S.has(n))continue;const m=u.resolve(t.rootEntry,n);m?m.file===t.rootEntry?S.add(n):m.typeOnly||(B.set(n,m.file),g.add(m.file)):v.add(n)}if(S.size>0)for(const o of u.index(t.rootEntry)?.valueImports??[]){const n=i.resolve(t.rootEntry,o);n&&g.add(n)}const L=E.importers.some(o=>o.wholeModule),I=L?new Set(d.map(o=>o.resource)):closureWithin(t,g,s,t.rootEntry,a),U=y(o=>{let n=0;for(const m of o)n+=s.get(m)?.size??0;return n},"sizeOf"),z=d.reduce((o,n)=>o+n.size,0),F=U(I),D=d.filter(o=>!I.has(o.resource)),O=t.files>0?Math.min(1,d.length/t.files):1,j=new Map,T=new Map,k=y((o,n)=>{let m=T.get(o);return m===void 0&&(m=subpathFor(t,o,n,u,r.source,a)??null,T.set(o,m)),m??void 0},"choose"),P=E.importers.map(o=>{const n=new Map;for(const m of o.values){const R=B.get(m);if(!R)continue;const x=k(m,R);if(!x)continue;const A=j.get(x.specifier)??{specifier:x.specifier,entry:rel(c,x.entry),symbols:[],exists:x.exists};A.symbols.includes(m)||A.symbols.push(m),j.set(x.specifier,A),n.set(x.specifier,[...n.get(x.specifier)??[],m])}return{file:rel(c,o.file),symbols:o.values.slice(0,MAX_SYMBOLS_LISTED),typeOnly:o.typeOnly,wholeModule:o.wholeModule,rewrite:[...n].sort((m,R)=>m[0].localeCompare(R[0])).map(([m,R])=>`import { ${R.join(", ")} } from '${m}';`)}}).sort((o,n)=>Number(n.wholeModule)-Number(o.wholeModule)||n.symbols.length-o.symbols.length||o.file.localeCompare(n.file)),b={project:e.project,library:t.name,libraryRoot:rel(c,t.root),rootEntry:rel(c,t.rootEntry),libraryFiles:t.files,compiledModules:d.length,compiledBytes:z,share:O,rootImporterCount:p.length,rootImporters:P.slice(0,MAX_IMPORTERS_LISTED),internalRootImporters:w.slice(0,MAX_INTERNAL_LISTED).map(o=>rel(c,o)),symbols:_.size,unresolvedSymbols:[...v].sort().slice(0,MAX_SYMBOLS_LISTED),barrelDefines:[...S].sort().slice(0,MAX_SYMBOLS_LISTED),neededModules:I.size,neededBytes:F,avoidableModules:D.length,avoidableBytes:D.reduce((o,n)=>o+n.size,0),subpaths:[...j.values()].map(o=>({...o,symbols:o.symbols.sort().slice(0,MAX_SYMBOLS_LISTED)})).sort((o,n)=>Number(o.exists)-Number(n.exists)||n.symbols.length-o.symbols.length).slice(0,MAX_SUBPATHS_LISTED),fires:!1};return O<h.minShare?b.quiet=`compiles ${pct(O)} of the library (below ${pct(h.minShare)})`:b.compiledModules<h.minModules&&b.compiledBytes<h.minBytes?b.quiet=`compiles ${b.compiledModules} modules / ${mb(b.compiledBytes)} (below ${h.minModules} modules and ${mb(h.minBytes)})`:L?b.quiet="an importer uses the whole module (a namespace passed on, require(), import(), export *) \u2014 it may need all of it":_.size>0&&v.size/_.size>MAX_UNRESOLVED_SHARE?b.quiet=`could not follow ${v.size} of ${_.size} symbols to their files`:b.neededModules>h.maxNeededShare*b.compiledModules?b.quiet=`its importers need ${b.neededModules} of the ${b.compiledModules} compiled modules (above ${pct(h.maxNeededShare)})`:b.fires=!0,b}$(measure,"measure"),M(measure,"measure"),y(measure,"measure");const pct=y(e=>`${Math.round(e*100)}%`,"pct"),mb=y(e=>`${(e/(1024*1024)).toFixed(1)} MB`,"mb");function analyzeBarrelImports(e){const t=y(l=>e.source.exists(l),"exists"),s=new AliasResolver(e.libraries,t),r=new ExportReader(e.source,s),i=new Map,u=y(l=>(i.has(l)||i.set(l,(0,workspace_libraries_1.libraryOf)(e.libraries,l)),i.get(l)),"owner"),a=[];for(const l of e.projects){const d=new Map(l.modules.map(p=>[p.resource,p]));for(const p of e.libraries){if(e.expired?.())return{complete:!1,measurements:a};const c=measure(l,p,d,e,s,r,u);c&&a.push(c)}}return{complete:!e.expired?.(),measurements:a}}$(analyzeBarrelImports,"analyzeBarrelImports"),M(analyzeBarrelImports,"analyzeBarrelImports"),y(analyzeBarrelImports,"analyzeBarrelImports"),exports.EXECUTOR_MB_PER_MODULE=.374;function describeHeavyBarrel(e,t){const s=t&&t.builtModules>=50?t.durationMs/t.builtModules:void 0,r=s!==void 0?Math.round(s*e.avoidableModules):void 0,i=Math.round(exports.EXECUTOR_MB_PER_MODULE*e.avoidableModules),u=e.rootImporters.slice(0,3),a=e.subpaths.filter(c=>!c.exists),l=u.map(c=>`${c.file}: replace its \`${e.library}\` import with ${c.rewrite.length?c.rewrite.join(" "):"imports from the subpaths that export what it uses"}`),d=[`Import ${e.library} by subpath, never by its root barrel (${e.rootEntry}). ${e.rootImporterCount} file(s) of ${e.project}'s build import the root; ${l.length?`start with \u2014 ${l.join(" | ")}`:"see evidence.rootImporters"}${e.rootImporterCount>u.length?` (+${e.rootImporterCount-u.length} more: evidence.rootImporters)`:""}.`];a.length&&d.push(`Add the missing subpath entr${a.length===1?"y":"ies"} to the library: ${a.slice(0,4).map(c=>`"${c.specifier}" \u2192 ${c.entry}`).join(", ")} \u2014 in tsconfig.base.json \`compilerOptions.paths\` and, if the library has a package.json, its \`exports\` ("./<domain>"). Add exact keys (plus "<domain>/*" for single files), never one library-wide "${e.library}/*": a bundler's resolver can rank it above the exact keys and re-route them at runtime while tsc and jest stay green.`),e.barrelDefines.length&&d.push(`${e.rootEntry} defines ${e.barrelDefines.slice(0,4).join(", ")} itself, so importing ${e.barrelDefines.length===1?"it":"them"} runs the whole barrel: move ${e.barrelDefines.length===1?"it":"them"} into a module of ${e.barrelDefines.length===1?"its":"their"} own and import that.`),e.internalRootImporters.length&&d.push(`${e.internalRootImporters.length} file(s) inside ${e.library} import its own root barrel (${e.internalRootImporters.slice(0,3).join(", ")}): make them import the module they need, or every subpath still pulls the whole library in.`),d.push(`Stop the root import from coming back: in ${e.project}'s ESLint config add \`'no-restricted-imports': ['error', { paths: [{ name: '${e.library}', message: 'Import from a domain subpath (${e.library}/<domain>), not the root barrel.' }] }]\`.`);const p=`Save a file of ${e.project} (or restart it) so its dev build recompiles: it should compile about ${e.neededModules} modules of ${e.library} instead of ${e.compiledModules}, and LensMCP retracts this finding \u2014 \`observe_current_status\` no longer lists bundle/heavy-barrel-import for ${e.project}. Then check its pods' live heap (\`memory.pods\`).`;return{subject:e.library,severity:"warning",title:`${e.project} compiles ${e.compiledModules} of the ${e.libraryFiles} files of ${e.library} through its root barrel; its imports need ${e.neededModules}`,summary:`${e.rootImporterCount} file(s) of ${e.project} import ${e.library} through its root entry and take ${e.symbols} symbol(s); those need ${e.neededModules} of the library's modules, but the barrel makes the dev build compile ${e.compiledModules} (${mb(e.compiledBytes)}) \u2014 ${e.avoidableModules} modules (${mb(e.avoidableBytes)}) nothing uses, compiled in every service that does the same and loaded into every pod.`,evidence:{library:e.library,libraryRoot:e.libraryRoot,rootEntry:e.rootEntry,libraryFiles:e.libraryFiles,compiledModules:e.compiledModules,compiledBytes:e.compiledBytes,share:Math.round(e.share*1e3)/1e3,neededModules:e.neededModules,neededBytes:e.neededBytes,avoidableModules:e.avoidableModules,avoidableBytes:e.avoidableBytes,symbols:e.symbols,unresolvedSymbols:e.unresolvedSymbols,barrelDefines:e.barrelDefines,rootImporterCount:e.rootImporterCount,rootImporters:e.rootImporters,internalRootImporters:e.internalRootImporters,subpaths:e.subpaths},cost:{modules:e.avoidableModules,bytes:e.avoidableBytes,...r!==void 0?{compileMs:r}:{},memoryMb:i,basis:`modules/bytes measured in this compilation; memoryMb = ${exports.EXECUTOR_MB_PER_MODULE} MB of webpack-executor heap per compiled module (fitted on FoodGuard's watchers)${r!==void 0?"; compileMs = the last full build's time per built module \xD7 the avoidable modules":""}. Each pod also loads them, at runtime cost the bundle cannot measure.`},fix:d,verify:p}}$(describeHeavyBarrel,"describeHeavyBarrel"),M(describeHeavyBarrel,"describeHeavyBarrel"),y(describeHeavyBarrel,"describeHeavyBarrel");
|
|
1
|
+
"use strict";var H=Object.defineProperty;var M=(e,o)=>H(e,"name",{value:o,configurable:!0});var C=Object.defineProperty,y=M((e,o)=>C(e,"name",{value:o,configurable:!0}),"y");Object.defineProperty(exports,"__esModule",{value:!0}),exports.EXECUTOR_MB_PER_MODULE=exports.DEFAULT_HEAVY_BARREL_THRESHOLDS=exports.HEAVY_BARREL_RULE=void 0,exports.analyzeBarrelImports=analyzeBarrelImports,exports.describeHeavyBarrel=describeHeavyBarrel;const tslib_1=require("tslib"),path=tslib_1.__importStar(require("node:path")),workspace_libraries_1=require("./workspace-libraries"),source_scan_1=require("./source-scan");exports.HEAVY_BARREL_RULE="bundle/heavy-barrel-import",exports.DEFAULT_HEAVY_BARREL_THRESHOLDS={minShare:.5,minModules:100,minBytes:1024*1024,maxNeededShare:.6};const MAX_IMPORTERS_LISTED=8,MAX_SYMBOLS_LISTED=12,MAX_SUBPATHS_LISTED=12,MAX_INTERNAL_LISTED=6,MAX_EXPORT_DEPTH=24,MAX_UNRESOLVED_SHARE=.1;class AliasResolver{static{M(this,"AliasResolver")}static{y(this,"AliasResolver")}constructor(o,r){this.exists=r,this.exact=new Map,this.wildcards=[];for(const s of o){this.exact.set(s.name,s.rootEntry);for(const i of s.aliases)this.exact.set(i,s.rootEntry);for(const i of s.subpaths)this.exact.set(i.specifier,i.entry);for(const i of s.wildcards)this.wildcards.push(i)}this.wildcards.sort((s,i)=>i.prefix.length-s.prefix.length)}resolve(o,r){if(r.startsWith("."))return(0,workspace_libraries_1.resolveSourceFile)(path.resolve(path.dirname(o),r),this.exists);const s=this.exact.get(r);if(s)return s;const i=this.wildcards.find(u=>r.startsWith(u.prefix));return i?(0,workspace_libraries_1.resolveSourceFile)(path.join(i.dir,r.slice(i.prefix.length)),this.exists):void 0}}class ExportReader{static{M(this,"ExportReader")}static{y(this,"ExportReader")}constructor(o,r){this.source=o,this.aliases=r,this.cache=new Map,this.resolved=new Map}index(o){let r=this.cache.get(o);if(r===void 0){const s=this.source.read(o);r=s===void 0?null:(0,source_scan_1.scanExports)(s),this.cache.set(o,r)}return r}resolve(o,r){const s=`${o}\0${r}`;let i=this.resolved.get(s);return i===void 0&&(i=this.follow(o,r,0,new Set)??null,this.resolved.set(s,i)),i??void 0}follow(o,r,s,i){if(s>MAX_EXPORT_DEPTH)return;const u=`${o}\0${r}`;if(i.has(u))return;i.add(u);const a=this.index(o);if(!a)return;if(a.values.has(r))return{file:o,typeOnly:!1};if(a.types.has(r))return{file:o,typeOnly:!0};const l=a.namespaces.get(r);if(l!==void 0){const p=this.aliases.resolve(o,l);return p?{file:p,typeOnly:!1}:void 0}const d=a.reexports.get(r);if(d){const p=this.aliases.resolve(o,d.specifier);if(!p)return;const c=this.follow(p,d.name,s+1,i);return c?{...c,typeOnly:c.typeOnly||d.typeOnly}:void 0}if(r!=="default")for(const p of a.stars){const c=this.aliases.resolve(o,p);if(!c)continue;const h=this.follow(c,r,s+1,i);if(h)return h}}}const rel=y((e,o)=>path.relative(e,o)||o,"rel");function readRootUse(e,o,r,s){const i=y(a=>l=>s.resolve(a,l)===e.rootEntry,"toBarrel"),u=[];for(const a of o){const l=/\.(?:[cm]?[jt]sx?)$/.test(a)?r.source.read(a):void 0;if(l===void 0){u.push({file:a,values:[],typeOnly:0,wholeModule:!0});continue}const d=(0,source_scan_1.scanImports)(l,i(a));if(d.length===0){u.push({file:a,values:[],typeOnly:0,wholeModule:!0});continue}const p=new Set;let c=0,h=!1;for(const x of d){h||=x.wholeModule;for(const f of x.names)f.typeOnly?c++:p.add(f.imported)}u.push({file:a,values:[...p].sort(),typeOnly:c,wholeModule:h})}return{importers:u}}M(readRootUse,"readRootUse"),y(readRootUse,"readRootUse");function closureWithin(e,o,r,s,i){const u=new Set,a=[...o].filter(l=>l!==s&&r.has(l)&&i(l)===e);for(;a.length;){const l=a.pop();if(!u.has(l)){u.add(l);for(const d of r.get(l)?.dependencies??[])d!==s&&!u.has(d)&&i(d)===e&&r.has(d)&&a.push(d)}}return u}M(closureWithin,"closureWithin"),y(closureWithin,"closureWithin");function subpathFor(e,o,r,s,i,u,a=0){if(r===e.rootEntry)return;const l=u(r);if(l!==e)return l&&a<2?subpathFor(l,o,r,s,i,u,a+1):void 0;const d=e.subpaths.filter(f=>r.startsWith(path.dirname(f.entry)+path.sep)||r===f.entry).filter(f=>s.resolve(f.entry,o)?.file===r).sort((f,$)=>$.entry.length-f.entry.length);if(d[0])return{specifier:d[0].specifier,entry:d[0].entry,exists:!0};const p=path.dirname(e.rootEntry);for(const f of e.wildcards){if(!r.startsWith(f.dir))continue;const $=r.slice(f.dir.length).split(path.sep).join("/").replace(/\.(?:[cm]?[jt]sx?)$/,""),w=$.split("/")[0],v=(0,workspace_libraries_1.resolveSourceFile)(path.join(f.dir,w),i.exists);return v&&v!==r&&s.resolve(v,o)?.file===r?{specifier:`${f.prefix}${w}`,entry:v,exists:!0}:{specifier:`${f.prefix}${$.replace(/\/index$/,"")}`,entry:r,exists:!0}}const c=path.relative(p,r).split(path.sep),h=c.length>1?c[0]:c[0].replace(/\.(?:[cm]?[jt]sx?)$/,""),x=c.length>1?(0,workspace_libraries_1.resolveSourceFile)(path.join(p,h),i.exists)??path.join(p,h,"index.ts"):r;return{specifier:`${e.name}/${h}`,entry:x,exists:!1}}M(subpathFor,"subpathFor"),y(subpathFor,"subpathFor");function measure(e,o,r,s,i,u,a){if(!r.has(o.rootEntry))return;const l=y(t=>a(t)===o,"inLib"),d=e.modules.filter(t=>l(t.resource)),p=e.modules.filter(t=>!l(t.resource)&&t.dependencies.includes(o.rootEntry)).map(t=>t.resource).sort();if(p.length===0)return;const c=s.workspaceRoot,h=s.thresholds,x=d.filter(t=>t.resource!==o.rootEntry&&t.dependencies.includes(o.rootEntry)).map(t=>t.resource),f=new Set;for(const t of e.modules)if(!l(t.resource))for(const n of t.dependencies)n!==o.rootEntry&&l(n)&&f.add(n);const $=readRootUse(o,p,s,i),w=new Set(f),v=new Set,S=new Map,R=new Set,_=new Set;for(const t of $.importers)for(const n of t.values){if(_.add(n),S.has(n)||v.has(n)||R.has(n))continue;const m=u.resolve(o.rootEntry,n);m?m.file===o.rootEntry?R.add(n):m.typeOnly||(S.set(n,m.file),w.add(m.file)):v.add(n)}if(R.size>0)for(const t of u.index(o.rootEntry)?.valueImports??[]){const n=i.resolve(o.rootEntry,t);n&&w.add(n)}const L=$.importers.some(t=>t.wholeModule),B=L?new Set(d.map(t=>t.resource)):closureWithin(o,w,r,o.rootEntry,a),T=y(t=>{let n=0;for(const m of t)n+=r.get(m)?.size??0;return n},"sizeOf"),U=d.reduce((t,n)=>t+n.size,0),z=T(B),A=d.filter(t=>!B.has(t.resource)),I=o.files>0?Math.min(1,d.length/o.files):1,O=new Map,D=new Map,k=y((t,n)=>{let m=D.get(t);return m===void 0&&(m=subpathFor(o,t,n,u,s.source,a)??null,D.set(t,m)),m??void 0},"choose"),F=$.importers.map(t=>{const n=new Map;for(const m of t.values){const g=S.get(m);if(!g)continue;const E=k(m,g);if(!E)continue;const j=O.get(E.specifier)??{specifier:E.specifier,entry:rel(c,E.entry),symbols:[],exists:E.exists};j.symbols.includes(m)||j.symbols.push(m),O.set(E.specifier,j),n.set(E.specifier,[...n.get(E.specifier)??[],m])}return{file:rel(c,t.file),symbols:t.values.slice(0,MAX_SYMBOLS_LISTED),typeOnly:t.typeOnly,wholeModule:t.wholeModule,rewrite:[...n].sort((m,g)=>m[0].localeCompare(g[0])).map(([m,g])=>`import { ${g.join(", ")} } from '${m}';`)}}).sort((t,n)=>Number(n.wholeModule)-Number(t.wholeModule)||n.symbols.length-t.symbols.length||t.file.localeCompare(n.file)),b={project:e.project,library:o.name,libraryRoot:rel(c,o.root),rootEntry:rel(c,o.rootEntry),libraryFiles:o.files,compiledModules:d.length,compiledBytes:U,share:I,rootImporterCount:p.length,rootImporters:F.slice(0,MAX_IMPORTERS_LISTED),internalRootImporters:x.slice(0,MAX_INTERNAL_LISTED).map(t=>rel(c,t)),symbols:_.size,unresolvedSymbols:[...v].sort().slice(0,MAX_SYMBOLS_LISTED),barrelDefines:[...R].sort().slice(0,MAX_SYMBOLS_LISTED),neededModules:B.size,neededBytes:z,avoidableModules:A.length,avoidableBytes:A.reduce((t,n)=>t+n.size,0),subpaths:[...O.values()].map(t=>({...t,symbols:t.symbols.sort().slice(0,MAX_SYMBOLS_LISTED)})).sort((t,n)=>Number(t.exists)-Number(n.exists)||n.symbols.length-t.symbols.length).slice(0,MAX_SUBPATHS_LISTED),fires:!1};return I<h.minShare?b.quiet=`compiles ${pct(I)} of the library (below ${pct(h.minShare)})`:b.compiledModules<h.minModules&&b.compiledBytes<h.minBytes?b.quiet=`compiles ${b.compiledModules} modules / ${mb(b.compiledBytes)} (below ${h.minModules} modules and ${mb(h.minBytes)})`:L?b.quiet="an importer uses the whole module (a namespace passed on, require(), import(), export *) \u2014 it may need all of it":_.size>0&&v.size/_.size>MAX_UNRESOLVED_SHARE?b.quiet=`could not follow ${v.size} of ${_.size} symbols to their files`:b.neededModules>h.maxNeededShare*b.compiledModules?b.quiet=`its importers need ${b.neededModules} of the ${b.compiledModules} compiled modules (above ${pct(h.maxNeededShare)})`:b.fires=!0,b}M(measure,"measure"),y(measure,"measure");const pct=y(e=>`${Math.round(e*100)}%`,"pct"),mb=y(e=>`${(e/(1024*1024)).toFixed(1)} MB`,"mb");function analyzeBarrelImports(e){const o=y(l=>e.source.exists(l),"exists"),r=new AliasResolver(e.libraries,o),s=new ExportReader(e.source,r),i=new Map,u=y(l=>(i.has(l)||i.set(l,(0,workspace_libraries_1.libraryOf)(e.libraries,l)),i.get(l)),"owner"),a=[];for(const l of e.projects){const d=new Map(l.modules.map(p=>[p.resource,p]));for(const p of e.libraries){if(e.expired?.())return{complete:!1,measurements:a};const c=measure(l,p,d,e,r,s,u);c&&a.push(c)}}return{complete:!e.expired?.(),measurements:a}}M(analyzeBarrelImports,"analyzeBarrelImports"),y(analyzeBarrelImports,"analyzeBarrelImports"),exports.EXECUTOR_MB_PER_MODULE=.374;function describeHeavyBarrel(e,o){const r=o&&o.builtModules>=50?o.durationMs/o.builtModules:void 0,s=r!==void 0?Math.round(r*e.avoidableModules):void 0,i=Math.round(exports.EXECUTOR_MB_PER_MODULE*e.avoidableModules),u=e.rootImporters.slice(0,3),a=e.subpaths.filter(c=>!c.exists),l=u.map(c=>`${c.file}: replace its \`${e.library}\` import with ${c.rewrite.length?c.rewrite.join(" "):"imports from the subpaths that export what it uses"}`),d=[`Import ${e.library} by subpath, never by its root barrel (${e.rootEntry}). ${e.rootImporterCount} file(s) of ${e.project}'s build import the root; ${l.length?`start with \u2014 ${l.join(" | ")}`:"see evidence.rootImporters"}${e.rootImporterCount>u.length?` (+${e.rootImporterCount-u.length} more: evidence.rootImporters)`:""}.`];a.length&&d.push(`Add the missing subpath entr${a.length===1?"y":"ies"} to the library: ${a.slice(0,4).map(c=>`"${c.specifier}" \u2192 ${c.entry}`).join(", ")} \u2014 in tsconfig.base.json \`compilerOptions.paths\` and, if the library has a package.json, its \`exports\` ("./<domain>"). Add exact keys (plus "<domain>/*" for single files), never one library-wide "${e.library}/*": a bundler's resolver can rank it above the exact keys and re-route them at runtime while tsc and jest stay green.`),e.barrelDefines.length&&d.push(`${e.rootEntry} defines ${e.barrelDefines.slice(0,4).join(", ")} itself, so importing ${e.barrelDefines.length===1?"it":"them"} runs the whole barrel: move ${e.barrelDefines.length===1?"it":"them"} into a module of ${e.barrelDefines.length===1?"its":"their"} own and import that.`),e.internalRootImporters.length&&d.push(`${e.internalRootImporters.length} file(s) inside ${e.library} import its own root barrel (${e.internalRootImporters.slice(0,3).join(", ")}): make them import the module they need, or every subpath still pulls the whole library in.`),d.push(`Stop the root import from coming back: in ${e.project}'s ESLint config add \`'no-restricted-imports': ['error', { paths: [{ name: '${e.library}', message: 'Import from a domain subpath (${e.library}/<domain>), not the root barrel.' }] }]\`.`);const p=`Save a file of ${e.project} (or restart it) so its dev build recompiles: it should compile about ${e.neededModules} modules of ${e.library} instead of ${e.compiledModules}, and LensMCP retracts this finding \u2014 \`observe_current_status\` no longer lists bundle/heavy-barrel-import for ${e.project}. Then check its pods' live heap (\`memory.pods\`).`;return{subject:e.library,severity:"warning",title:`${e.project} compiles ${e.compiledModules} of the ${e.libraryFiles} files of ${e.library} through its root barrel; its imports need ${e.neededModules}`,summary:`${e.rootImporterCount} file(s) of ${e.project} import ${e.library} through its root entry and take ${e.symbols} symbol(s); those need ${e.neededModules} of the library's modules, but the barrel makes the dev build compile ${e.compiledModules} (${mb(e.compiledBytes)}) \u2014 ${e.avoidableModules} modules (${mb(e.avoidableBytes)}) nothing uses, compiled in every service that does the same and loaded into every pod.`,evidence:{library:e.library,libraryRoot:e.libraryRoot,rootEntry:e.rootEntry,libraryFiles:e.libraryFiles,compiledModules:e.compiledModules,compiledBytes:e.compiledBytes,share:Math.round(e.share*1e3)/1e3,neededModules:e.neededModules,neededBytes:e.neededBytes,avoidableModules:e.avoidableModules,avoidableBytes:e.avoidableBytes,symbols:e.symbols,unresolvedSymbols:e.unresolvedSymbols,barrelDefines:e.barrelDefines,rootImporterCount:e.rootImporterCount,rootImporters:e.rootImporters,internalRootImporters:e.internalRootImporters,subpaths:e.subpaths},cost:{modules:e.avoidableModules,bytes:e.avoidableBytes,...s!==void 0?{compileMs:s}:{},memoryMb:i,basis:`modules/bytes measured in this compilation; memoryMb = ${exports.EXECUTOR_MB_PER_MODULE} MB of webpack-executor heap per compiled module (fitted on FoodGuard's watchers)${s!==void 0?"; compileMs = the last full build's time per built module \xD7 the avoidable modules":""}. Each pod also loads them, at runtime cost the bundle cannot measure.`},fix:d,verify:p}}M(describeHeavyBarrel,"describeHeavyBarrel"),y(describeHeavyBarrel,"describeHeavyBarrel");
|
package/perf/perf-config.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var p=Object.defineProperty;var o=(r,e)=>p(r,"name",{value:e,configurable:!0});var u=Object.defineProperty,n=o((r,e)=>u(r,"name",{value:e,configurable:!0}),"n");Object.defineProperty(exports,"__esModule",{value:!0}),exports.HEAVY_BARREL_ENV=exports.DEFAULT_PERF_RULES_BUDGET_MS=exports.PERF_RULES_BUDGET_ENV=exports.PERF_RULES_ENV=void 0,exports.readPerfRulesConfig=readPerfRulesConfig,exports.resolveBundleRuleSettings=resolveBundleRuleSettings;const tslib_1=require("tslib"),fs=tslib_1.__importStar(require("node:fs")),path=tslib_1.__importStar(require("node:path")),heavy_barrel_import_1=require("./heavy-barrel-import");exports.PERF_RULES_ENV="LENSMCP_PERF_RULES",exports.PERF_RULES_BUDGET_ENV="LENSMCP_PERF_RULES_BUDGET_MS",exports.DEFAULT_PERF_RULES_BUDGET_MS=5e3,exports.HEAVY_BARREL_ENV={minShare:"LENSMCP_BARREL_MIN_SHARE",minModules:"LENSMCP_BARREL_MIN_MODULES",minKb:"LENSMCP_BARREL_MIN_KB",maxNeededShare:"LENSMCP_BARREL_MAX_NEEDED_SHARE"};const OFF=/^(0|off|false|no)$/i;function bounded(r,e,t){const E=typeof r=="string"&&r.trim()!==""?Number(r):r;return typeof E=="number"&&Number.isFinite(E)&&E>=e&&E<=t?E:void 0}o(bounded,"bounded"),n(bounded,"bounded");function readPerfRulesConfig(r){try{const e=JSON.parse(fs.readFileSync(path.join(r,".lensmcp","config.json"),"utf8"))?.perfRules;return e&&typeof e=="object"&&!Array.isArray(e)?e:void 0}catch{return}}o(readPerfRulesConfig,"readPerfRulesConfig"),n(readPerfRulesConfig,"readPerfRulesConfig");function resolveBundleRuleSettings(r,e=process.env){const t=readPerfRulesConfig(r),E=t?.[heavy_barrel_import_1.HEAVY_BARREL_RULE]&&typeof t[heavy_barrel_import_1.HEAVY_BARREL_RULE]=="object"?t[heavy_barrel_import_1.HEAVY_BARREL_RULE]:{},S=!OFF.test((e[exports.PERF_RULES_ENV]??"").trim())&&t?.enabled!==!1&&E.enabled!==!1,_=n((a,d,s,i,L)=>bounded(e[a],s,i)??bounded(d,s,i)??L,"pick"),R=heavy_barrel_import_1.DEFAULT_HEAVY_BARREL_THRESHOLDS;return{enabled:S,thresholds:{minShare:_(exports.HEAVY_BARREL_ENV.minShare,E.minShare,0,1,R.minShare),minModules:_(exports.HEAVY_BARREL_ENV.minModules,E.minModules,0,1e6,R.minModules),minBytes:Math.round(_(exports.HEAVY_BARREL_ENV.minKb,E.minKb,0,1e7,R.minBytes/1024)*1024),maxNeededShare:_(exports.HEAVY_BARREL_ENV.maxNeededShare,E.maxNeededShare,0,1,R.maxNeededShare)},budgetMs:_(exports.PERF_RULES_BUDGET_ENV,t?.budgetMs,100,12e4,exports.DEFAULT_PERF_RULES_BUDGET_MS)}}o(resolveBundleRuleSettings,"resolveBundleRuleSettings"),n(resolveBundleRuleSettings,"resolveBundleRuleSettings");
|