@lensmcp/cluster 1.18.4 → 1.18.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/basic-ssl.js +1 -241
  2. package/build-scope-patterns.js +1 -40
  3. package/create-webpack-dev.js +1 -186
  4. package/create-webpack-prod.js +1 -169
  5. package/executors/build/build.impl.js +1 -98
  6. package/executors/gateway/gateway-errors.js +1 -43
  7. package/executors/gateway/gateway.impl.js +1 -53
  8. package/executors/gateway/gateway.lib.js +1 -29
  9. package/executors/gateway/health-check.js +1 -66
  10. package/executors/gateway/jwks-verify.js +1 -121
  11. package/executors/gateway/main.prod-gateway.js +2 -573
  12. package/executors/gateway/main.rollout.js +11 -117
  13. package/executors/gateway/manifest.js +1 -374
  14. package/executors/gateway/metrics.js +1 -56
  15. package/executors/gateway/otel-tracing.js +1 -74
  16. package/executors/gateway/prod-gateway.lib.js +1 -22
  17. package/executors/gateway/prod-runtime/access-log.js +1 -24
  18. package/executors/gateway/prod-runtime/app.js +1 -123
  19. package/executors/gateway/prod-runtime/auth.js +1 -51
  20. package/executors/gateway/prod-runtime/cors.js +1 -40
  21. package/executors/gateway/prod-runtime/edge.js +1 -65
  22. package/executors/gateway/prod-runtime/handler.js +1 -226
  23. package/executors/gateway/prod-runtime/hooks.js +1 -42
  24. package/executors/gateway/prod-runtime/observability.js +1 -125
  25. package/executors/gateway/prod-runtime/rollout.js +1 -103
  26. package/executors/gateway/prod-runtime/routing.js +1 -40
  27. package/executors/gateway/prod-runtime/server.js +1 -79
  28. package/executors/gateway/prod-runtime/trust.js +1 -32
  29. package/executors/gateway/prod-runtime/types.js +1 -2
  30. package/executors/gateway/prod-runtime/upgrade.js +4 -116
  31. package/executors/gateway/prod-runtime/upstream.js +1 -21
  32. package/executors/gateway/providers-prod.js +1 -232
  33. package/executors/gateway/rate-limit.js +2 -75
  34. package/executors/gateway/registry-source.js +1 -131
  35. package/executors/gateway/rollout-ops.js +2 -167
  36. package/executors/gateway/runtime/auth.js +1 -64
  37. package/executors/gateway/runtime/chooser.js +12 -45
  38. package/executors/gateway/runtime/control.js +1 -128
  39. package/executors/gateway/runtime/dev-auth.js +1 -108
  40. package/executors/gateway/runtime/discovery.js +1 -123
  41. package/executors/gateway/runtime/edge.js +1 -47
  42. package/executors/gateway/runtime/handler.js +1 -183
  43. package/executors/gateway/runtime/hooks.js +1 -55
  44. package/executors/gateway/runtime/lens-children.js +1 -651
  45. package/executors/gateway/runtime/lifecycle.js +3 -842
  46. package/executors/gateway/runtime/observability.js +2 -148
  47. package/executors/gateway/runtime/pod-env.js +2 -89
  48. package/executors/gateway/runtime/proxy.js +1 -457
  49. package/executors/gateway/runtime/route-registry.js +1 -72
  50. package/executors/gateway/runtime/scope.js +1 -117
  51. package/executors/gateway/runtime/server.js +3 -487
  52. package/executors/gateway/runtime/service-keys.js +1 -49
  53. package/executors/gateway/runtime/types.js +1 -151
  54. package/executors/gateway/runtime/upgrade.js +1 -71
  55. package/executors/gateway/runtime/workspace-registry.js +1 -99
  56. package/executors/gateway/ssrf-guard.js +1 -190
  57. package/executors/serve/serve.impl.js +1 -280
  58. package/executors/trust/trust.impl.js +4 -162
  59. package/gateway.js +1 -35
  60. package/index.js +1 -16
  61. package/main.devserver.js +10 -1117
  62. package/package.json +4 -3
  63. package/tsgo-check-plugin.js +4 -364
  64. package/typecheck-bus.js +4 -256
package/basic-ssl.js CHANGED
@@ -1,241 +1 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.CA_CERT_FILE = void 0;
4
- exports.caDir = caDir;
5
- exports.caCertPath = caCertPath;
6
- exports.getCertificateSync = getCertificateSync;
7
- exports.ensureCaSync = ensureCaSync;
8
- const tslib_1 = require("tslib");
9
- /**
10
- * Dev HTTPS certificates, mkcert-style: a long-lived LOCAL CA (10 years,
11
- * minted once per MACHINE, trusted once in the OS keychain) signs short-lived
12
- * leaf certs (30 days, re-minted per SAN set). Because the browser chains the
13
- * leaf to the trusted CA, cert rotation and new gateway hostnames never show
14
- * an interstitial again — unlike a bare self-signed cert, which would need
15
- * re-trusting on every change.
16
- *
17
- * The CA is MACHINE-LEVEL — `~/.lensmcp/ca/` (override the home via
18
- * `LENSMCP_HOME`, same convention as the workspace registry) — so every
19
- * workspace/daemon on the machine serves chains anchored to ONE CA:
20
- * - the OS keychain holds exactly one "lensmcp local dev CA" (no same-CN
21
- * collisions between per-workspace CAs shadowing each other in `trust`),
22
- * - a pod's `NODE_EXTRA_CA_CERTS` stays valid across daemon handovers
23
- * (guest workspace → own daemon), because every daemon signs with the
24
- * same anchor.
25
- * The first machine-CA resolution PROMOTES a pre-existing per-workspace CA
26
- * (the pre-machine-CA layout) when one exists, so keychain trust already
27
- * granted to it carries over without another sudo prompt. LEAF certs stay
28
- * per-workspace in `<root>/node_modules/.cache/davnx-webpack` and are reused
29
- * only when they chain to the CURRENT machine CA (the issuer pin below).
30
- *
31
- * `getCertificateSync` returns ONE concatenated PEM (leaf key + leaf cert +
32
- * CA cert). Node's `https.createServer({ key: pem, cert: pem })` accepts it:
33
- * `key` takes the first private-key block, `cert` takes every certificate
34
- * block (leaf first, then the CA as the served chain).
35
- *
36
- * Trust once (macOS):
37
- * sudo security add-trusted-cert -d -r trustRoot \
38
- * -k /Library/Keychains/System.keychain ~/.lensmcp/ca/lensmcp-local-ca.crt
39
- */
40
- const crypto = tslib_1.__importStar(require("node:crypto"));
41
- const fs = tslib_1.__importStar(require("node:fs"));
42
- const os = tslib_1.__importStar(require("node:os"));
43
- const path = tslib_1.__importStar(require("node:path"));
44
- /** Re-mint the leaf when the cached one is older than this (TTL is 30 days). */
45
- const LEAF_MAX_AGE_MS = 25 * 24 * 60 * 60 * 1000;
46
- /** CA lifetime (~10 years) and the remaining-validity floor for reuse. */
47
- const CA_TTL_DAYS = 3650;
48
- const CA_MIN_REMAINING_MS = 30 * 24 * 60 * 60 * 1000;
49
- exports.CA_CERT_FILE = 'lensmcp-local-ca.crt';
50
- /** The legacy (pre-rebrand) CA filename — swept on mint so a stale `davnx-local-ca.crt` never lingers. */
51
- const LEGACY_CA_CERT_FILE = 'davnx-local-ca.crt';
52
- const CA_KEY_FILE = '_ca-key.pem';
53
- /** The machine-level CA directory: `~/.lensmcp/ca` (override home via `LENSMCP_HOME` — tests). */
54
- function caDir() {
55
- const home = process.env['LENSMCP_HOME'] || os.homedir();
56
- return path.join(home, '.lensmcp', 'ca');
57
- }
58
- /** Absolute path of the trust-once, machine-level CA certificate. */
59
- function caCertPath() {
60
- return path.join(caDir(), exports.CA_CERT_FILE);
61
- }
62
- function getCertificateSync(cacheDir, name = 'lensmcp.dev', domains = []) {
63
- // Resolve the CA FIRST (machine-level; promotes this workspace's legacy CA on first touch). The current
64
- // CA pem then gates the leaf cache below — an issuer pin, see there.
65
- const forge = require('node-forge');
66
- fs.mkdirSync(cacheDir, { recursive: true });
67
- const ca = loadOrCreateCa(forge, cacheDir);
68
- const caPem = forge.pki.certificateToPem(ca.cert);
69
- // The SAN set is part of the cache key: adding a gateway hostname must
70
- // mint a fresh leaf, not serve a cached one that lacks the new SAN.
71
- const sanKey = crypto
72
- .createHash('sha256')
73
- .update([name, ...[...domains].sort()].join('|'))
74
- .digest('hex')
75
- .slice(0, 12);
76
- const leafPath = path.join(cacheDir, `_leaf-${sanKey}.pem`);
77
- try {
78
- const stat = fs.statSync(leafPath);
79
- if (Date.now() - stat.ctimeMs < LEAF_MAX_AGE_MS) {
80
- const cached = fs.readFileSync(leafPath, 'utf8');
81
- // ISSUER PIN: the cached pem embeds the CA it chained to — serve it only when that is the CURRENT
82
- // machine CA. With the CA machine-level, a stale leaf in THIS workspace can't be swept by a CA mint
83
- // that happened elsewhere (another workspace, or pre-machine-CA code), so the old "a mint sweeps
84
- // this dir's leaves" guarantee no longer covers every path; the pin does.
85
- if (cached.includes(caPem))
86
- return cached;
87
- }
88
- }
89
- catch {
90
- /* no cache yet */
91
- }
92
- const pem = createLeafCertificate(forge, ca, name, domains);
93
- fs.writeFileSync(leafPath, pem);
94
- // Stale leaves and the pre-1.3.4 self-signed cache just rot here — sweep
95
- // them so the dir holds only the active leaf (+ any legacy CA pair, kept
96
- // readable for older-code daemons that still anchor to it).
97
- for (const f of fs.readdirSync(cacheDir)) {
98
- const stale = (/^_leaf-.*\.pem$/.test(f) && f !== `_leaf-${sanKey}.pem`) ||
99
- /^_cert.*\.pem$/.test(f) ||
100
- /-dev\.crt$/.test(f) ||
101
- f === LEGACY_CA_CERT_FILE;
102
- if (stale) {
103
- try {
104
- fs.unlinkSync(path.join(cacheDir, f));
105
- }
106
- catch { /* best effort */ }
107
- }
108
- }
109
- return pem;
110
- }
111
- /**
112
- * Ensure the machine-level CA exists (promoting `legacyCacheDir`'s per-workspace
113
- * CA when the machine store is still empty); returns the machine CA cert path.
114
- */
115
- function ensureCaSync(legacyCacheDir) {
116
- const forge = require('node-forge');
117
- loadOrCreateCa(forge, legacyCacheDir);
118
- return caCertPath();
119
- }
120
- /** Read a CA pair from `dir`; undefined when absent, unreadable, or too close to expiry to reuse. */
121
- function readCaPair(dir, forge) {
122
- try {
123
- const cert = forge.pki.certificateFromPem(fs.readFileSync(path.join(dir, exports.CA_CERT_FILE), 'utf8'));
124
- const key = forge.pki.privateKeyFromPem(fs.readFileSync(path.join(dir, CA_KEY_FILE), 'utf8'));
125
- if (cert.validity.notAfter.getTime() - Date.now() > CA_MIN_REMAINING_MS) {
126
- return { cert, key };
127
- }
128
- }
129
- catch {
130
- /* absent or unreadable */
131
- }
132
- return undefined;
133
- }
134
- function loadOrCreateCa(forge, promoteFromDir) {
135
- const dir = caDir();
136
- fs.mkdirSync(dir, { recursive: true });
137
- const existing = readCaPair(dir, forge);
138
- if (existing)
139
- return existing;
140
- // Files present but unusable (expired / half-written) — clear them so the `wx` claim below can win.
141
- // Rotation this races is a once-per-decade event; last write wins is fine at dev grade.
142
- for (const f of [CA_KEY_FILE, exports.CA_CERT_FILE]) {
143
- try {
144
- fs.unlinkSync(path.join(dir, f));
145
- }
146
- catch { /* absent */ }
147
- }
148
- // Candidate pair: PROMOTE the pre-machine-CA workspace pair when one exists — the exact cert the user
149
- // already trusted in the keychain simply becomes the machine CA (no new sudo prompt). The workspace copy
150
- // stays in place for any older-code daemon still anchoring to it. Otherwise mint fresh.
151
- const promoted = promoteFromDir && promoteFromDir !== dir ? readCaPair(promoteFromDir, forge) : undefined;
152
- const pair = promoted ?? mintCa(forge);
153
- // Atomic claim on the KEY file (`wx`): concurrent daemons can race the first-ever machine resolution;
154
- // exactly one pair may land on disk. The winner writes the cert right after; a loser adopts the winner's
155
- // pair (bounded wait for that cert write).
156
- try {
157
- fs.writeFileSync(path.join(dir, CA_KEY_FILE), forge.pki.privateKeyToPem(pair.key), { mode: 0o600, flag: 'wx' });
158
- }
159
- catch (e) {
160
- if (e.code !== 'EEXIST')
161
- throw e;
162
- const winner = spinReadCaPair(dir, forge);
163
- if (winner)
164
- return winner;
165
- throw new Error(`machine dev CA at ${dir} is claimed but unreadable — remove the directory and retry`, { cause: e });
166
- }
167
- fs.writeFileSync(path.join(dir, exports.CA_CERT_FILE), forge.pki.certificateToPem(pair.cert));
168
- if (promoted) {
169
- console.log(`[ssl] promoted the existing workspace dev CA to the machine store (${dir}) — keychain trust carries over.`);
170
- }
171
- return pair;
172
- }
173
- /** Bounded sync wait for a concurrent claimer's cert write to land (claim→cert is two writes apart). */
174
- function spinReadCaPair(dir, forge) {
175
- const deadline = Date.now() + 2000;
176
- for (;;) {
177
- const pair = readCaPair(dir, forge);
178
- if (pair || Date.now() >= deadline)
179
- return pair;
180
- Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 25); // sync 25ms sleep
181
- }
182
- }
183
- function mintCa(forge) {
184
- const keys = forge.pki.rsa.generateKeyPair(2048);
185
- const cert = forge.pki.createCertificate();
186
- cert.publicKey = keys.publicKey;
187
- cert.serialNumber = `00${Date.now().toString(16)}`;
188
- cert.validity.notBefore = new Date(Date.now() - 24 * 60 * 60 * 1000); // clock-skew slack
189
- cert.validity.notAfter = new Date();
190
- cert.validity.notAfter.setDate(cert.validity.notAfter.getDate() + CA_TTL_DAYS);
191
- const attrs = [
192
- { name: 'commonName', value: 'lensmcp local dev CA' },
193
- { name: 'organizationName', value: 'lensmcp' },
194
- { shortName: 'OU', value: 'dev' },
195
- ];
196
- cert.setSubject(attrs);
197
- cert.setIssuer(attrs);
198
- cert.setExtensions([
199
- { name: 'basicConstraints', cA: true, critical: true },
200
- { name: 'keyUsage', keyCertSign: true, cRLSign: true, critical: true },
201
- { name: 'subjectKeyIdentifier' },
202
- ]);
203
- cert.sign(keys.privateKey, forge.md.sha256.create());
204
- return { cert, key: keys.privateKey };
205
- }
206
- function createLeafCertificate(forge, ca, name, domains, ttlDays = 30) {
207
- const keys = forge.pki.rsa.generateKeyPair(2048);
208
- const cert = forge.pki.createCertificate();
209
- cert.publicKey = keys.publicKey;
210
- cert.serialNumber = `00${Date.now().toString(16)}`;
211
- cert.validity.notBefore = new Date(Date.now() - 24 * 60 * 60 * 1000); // clock-skew slack
212
- cert.validity.notAfter = new Date();
213
- cert.validity.notAfter.setDate(cert.validity.notAfter.getDate() + ttlDays);
214
- cert.setSubject([
215
- { name: 'commonName', value: name },
216
- { name: 'organizationName', value: 'lensmcp' },
217
- { shortName: 'OU', value: 'dev' },
218
- ]);
219
- cert.setIssuer(ca.cert.subject.attributes);
220
- // SANs: localhost + loopbacks always; the gateway hostnames (incl. wildcards) on top.
221
- const altNames = [
222
- { type: 2, value: 'localhost' },
223
- { type: 2, value: '*.localhost' },
224
- { type: 7, ip: '127.0.0.1' },
225
- { type: 7, ip: '::1' },
226
- ...[...new Set(domains)].filter((d) => d && d !== 'localhost').map((d) => ({ type: 2, value: d })),
227
- ];
228
- // Apple/Chrome policy for leaf certs: SAN required, EKU serverAuth required,
229
- // and a leaf must NOT be a CA — keyUsage stays signature/encipherment only.
230
- cert.setExtensions([
231
- { name: 'basicConstraints', cA: false },
232
- { name: 'keyUsage', digitalSignature: true, keyEncipherment: true, critical: true },
233
- { name: 'extKeyUsage', serverAuth: true, clientAuth: true },
234
- { name: 'subjectAltName', altNames },
235
- { name: 'subjectKeyIdentifier' },
236
- ]);
237
- cert.sign(ca.key, forge.md.sha256.create());
238
- return (forge.pki.privateKeyToPem(keys.privateKey) +
239
- forge.pki.certificateToPem(cert) +
240
- forge.pki.certificateToPem(ca.cert));
241
- }
1
+ "use strict";var f=Object.defineProperty;var c=(e,r)=>f(e,"name",{value:r,configurable:!0});var p=Object.defineProperty,a=c((e,r)=>p(e,"name",{value:r,configurable:!0}),"a");Object.defineProperty(exports,"__esModule",{value:!0}),exports.CA_CERT_FILE=void 0,exports.caDir=caDir,exports.caCertPath=caCertPath,exports.getCertificateSync=getCertificateSync,exports.ensureCaSync=ensureCaSync;const tslib_1=require("tslib"),crypto=tslib_1.__importStar(require("node:crypto")),fs=tslib_1.__importStar(require("node:fs")),os=tslib_1.__importStar(require("node:os")),path=tslib_1.__importStar(require("node:path")),LEAF_MAX_AGE_MS=600*60*60*1e3,CA_TTL_DAYS=3650,CA_MIN_REMAINING_MS=720*60*60*1e3;exports.CA_CERT_FILE="lensmcp-local-ca.crt";const LEGACY_CA_CERT_FILE="davnx-local-ca.crt",CA_KEY_FILE="_ca-key.pem";function caDir(){const e=process.env.LENSMCP_HOME||os.homedir();return path.join(e,".lensmcp","ca")}c(caDir,"caDir"),a(caDir,"caDir");function caCertPath(){return path.join(caDir(),exports.CA_CERT_FILE)}c(caCertPath,"caCertPath"),a(caCertPath,"caCertPath");function getCertificateSync(e,r="lensmcp.dev",t=[]){const n=require("node-forge");fs.mkdirSync(e,{recursive:!0});const l=loadOrCreateCa(n,e),o=n.pki.certificateToPem(l.cert),i=crypto.createHash("sha256").update([r,...[...t].sort()].join("|")).digest("hex").slice(0,12),s=path.join(e,`_leaf-${i}.pem`);try{const u=fs.statSync(s);if(Date.now()-u.ctimeMs<LEAF_MAX_AGE_MS){const m=fs.readFileSync(s,"utf8");if(m.includes(o))return m}}catch{}const y=createLeafCertificate(n,l,r,t);fs.writeFileSync(s,y);for(const u of fs.readdirSync(e))if(/^_leaf-.*\.pem$/.test(u)&&u!==`_leaf-${i}.pem`||/^_cert.*\.pem$/.test(u)||/-dev\.crt$/.test(u)||u===LEGACY_CA_CERT_FILE)try{fs.unlinkSync(path.join(e,u))}catch{}return y}c(getCertificateSync,"getCertificateSync"),a(getCertificateSync,"getCertificateSync");function ensureCaSync(e){const r=require("node-forge");return loadOrCreateCa(r,e),caCertPath()}c(ensureCaSync,"ensureCaSync"),a(ensureCaSync,"ensureCaSync");function readCaPair(e,r){try{const t=r.pki.certificateFromPem(fs.readFileSync(path.join(e,exports.CA_CERT_FILE),"utf8")),n=r.pki.privateKeyFromPem(fs.readFileSync(path.join(e,CA_KEY_FILE),"utf8"));if(t.validity.notAfter.getTime()-Date.now()>CA_MIN_REMAINING_MS)return{cert:t,key:n}}catch{}}c(readCaPair,"readCaPair"),a(readCaPair,"readCaPair");function loadOrCreateCa(e,r){const t=caDir();fs.mkdirSync(t,{recursive:!0});const n=readCaPair(t,e);if(n)return n;for(const i of[CA_KEY_FILE,exports.CA_CERT_FILE])try{fs.unlinkSync(path.join(t,i))}catch{}const l=r&&r!==t?readCaPair(r,e):void 0,o=l??mintCa(e);try{fs.writeFileSync(path.join(t,CA_KEY_FILE),e.pki.privateKeyToPem(o.key),{mode:384,flag:"wx"})}catch(i){if(i.code!=="EEXIST")throw i;const s=spinReadCaPair(t,e);if(s)return s;throw new Error(`machine dev CA at ${t} is claimed but unreadable \u2014 remove the directory and retry`,{cause:i})}return fs.writeFileSync(path.join(t,exports.CA_CERT_FILE),e.pki.certificateToPem(o.cert)),l&&console.log(`[ssl] promoted the existing workspace dev CA to the machine store (${t}) \u2014 keychain trust carries over.`),o}c(loadOrCreateCa,"loadOrCreateCa"),a(loadOrCreateCa,"loadOrCreateCa");function spinReadCaPair(e,r){const t=Date.now()+2e3;for(;;){const n=readCaPair(e,r);if(n||Date.now()>=t)return n;Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,25)}}c(spinReadCaPair,"spinReadCaPair"),a(spinReadCaPair,"spinReadCaPair");function mintCa(e){const r=e.pki.rsa.generateKeyPair(2048),t=e.pki.createCertificate();t.publicKey=r.publicKey,t.serialNumber=`00${Date.now().toString(16)}`,t.validity.notBefore=new Date(Date.now()-1440*60*1e3),t.validity.notAfter=new Date,t.validity.notAfter.setDate(t.validity.notAfter.getDate()+CA_TTL_DAYS);const n=[{name:"commonName",value:"lensmcp local dev CA"},{name:"organizationName",value:"lensmcp"},{shortName:"OU",value:"dev"}];return t.setSubject(n),t.setIssuer(n),t.setExtensions([{name:"basicConstraints",cA:!0,critical:!0},{name:"keyUsage",keyCertSign:!0,cRLSign:!0,critical:!0},{name:"subjectKeyIdentifier"}]),t.sign(r.privateKey,e.md.sha256.create()),{cert:t,key:r.privateKey}}c(mintCa,"mintCa"),a(mintCa,"mintCa");function createLeafCertificate(e,r,t,n,l=30){const o=e.pki.rsa.generateKeyPair(2048),i=e.pki.createCertificate();i.publicKey=o.publicKey,i.serialNumber=`00${Date.now().toString(16)}`,i.validity.notBefore=new Date(Date.now()-1440*60*1e3),i.validity.notAfter=new Date,i.validity.notAfter.setDate(i.validity.notAfter.getDate()+l),i.setSubject([{name:"commonName",value:t},{name:"organizationName",value:"lensmcp"},{shortName:"OU",value:"dev"}]),i.setIssuer(r.cert.subject.attributes);const s=[{type:2,value:"localhost"},{type:2,value:"*.localhost"},{type:7,ip:"127.0.0.1"},{type:7,ip:"::1"},...[...new Set(n)].filter(y=>y&&y!=="localhost").map(y=>({type:2,value:y}))];return i.setExtensions([{name:"basicConstraints",cA:!1},{name:"keyUsage",digitalSignature:!0,keyEncipherment:!0,critical:!0},{name:"extKeyUsage",serverAuth:!0,clientAuth:!0},{name:"subjectAltName",altNames:s},{name:"subjectKeyIdentifier"}]),i.sign(r.key,e.md.sha256.create()),e.pki.privateKeyToPem(o.privateKey)+e.pki.certificateToPem(i)+e.pki.certificateToPem(r.cert)}c(createLeafCertificate,"createLeafCertificate"),a(createLeafCertificate,"createLeafCertificate");
@@ -1,40 +1 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.buildScopePatterns = buildScopePatterns;
4
- function buildScopePatterns(orgScopes) {
5
- const allowlistPatterns = [];
6
- const scopePrefixes = [];
7
- const scopePatterns = [];
8
- for (const scope of orgScopes) {
9
- if (!scope)
10
- continue;
11
- const regexMatch = scope.match(/^\/(.+)\/([gimsuy]*)$/);
12
- if (regexMatch) {
13
- // Regex: /pattern/flags — strip 'g' flag to avoid stateful lastIndex in .test()
14
- const flags = regexMatch[2].replace('g', '');
15
- const regex = new RegExp(regexMatch[1], flags);
16
- allowlistPatterns.push(regex);
17
- scopePatterns.push(regex);
18
- }
19
- else if (scope.includes('/')) {
20
- // Prefix: @frontegg/agenshield → matches @frontegg/agenshield*
21
- const escaped = scope.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
22
- allowlistPatterns.push(new RegExp(`^${escaped}`));
23
- scopePrefixes.push(scope);
24
- }
25
- else if (scope.startsWith('@')) {
26
- // Org scope: @myorg → matches @myorg/*
27
- const escaped = scope.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
28
- allowlistPatterns.push(new RegExp(`^${escaped}/`));
29
- scopePrefixes.push(scope.endsWith('/') ? scope : `${scope}/`);
30
- }
31
- else {
32
- // Exact package name: lodash → matches lodash and lodash/subpath
33
- const escaped = scope.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
34
- const regex = new RegExp(`^${escaped}(/|$)`);
35
- allowlistPatterns.push(regex);
36
- scopePatterns.push(regex);
37
- }
38
- }
39
- return { allowlistPatterns, scopePrefixes, scopePatterns };
40
- }
1
+ "use strict";var l=Object.defineProperty;var i=(n,s)=>l(n,"name",{value:s,configurable:!0});var a=Object.defineProperty,u=i((n,s)=>a(n,"name",{value:s,configurable:!0}),"u");Object.defineProperty(exports,"__esModule",{value:!0}),exports.buildScopePatterns=buildScopePatterns;function buildScopePatterns(n){const s=[],p=[],r=[];for(const e of n){if(!e)continue;const o=e.match(/^\/(.+)\/([gimsuy]*)$/);if(o){const t=o[2].replace("g",""),c=new RegExp(o[1],t);s.push(c),r.push(c)}else if(e.includes("/")){const t=e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");s.push(new RegExp(`^${t}`)),p.push(e)}else if(e.startsWith("@")){const t=e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");s.push(new RegExp(`^${t}/`)),p.push(e.endsWith("/")?e:`${e}/`)}else{const t=e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),c=new RegExp(`^${t}(/|$)`);s.push(c),r.push(c)}}return{allowlistPatterns:s,scopePrefixes:p,scopePatterns:r}}i(buildScopePatterns,"buildScopePatterns"),u(buildScopePatterns,"buildScopePatterns");
@@ -1,186 +1 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createDevWebpackConfig = createDevWebpackConfig;
4
- const tslib_1 = require("tslib");
5
- const app_plugin_1 = require("@nx/webpack/app-plugin");
6
- const fs = tslib_1.__importStar(require("node:fs"));
7
- const path = tslib_1.__importStar(require("node:path"));
8
- const webpack_node_externals_1 = tslib_1.__importDefault(require("webpack-node-externals"));
9
- const build_scope_patterns_1 = require("./build-scope-patterns");
10
- const tsgo_check_plugin_1 = require("./tsgo-check-plugin");
11
- // eslint-disable-next-line @typescript-eslint/no-require-imports
12
- const webpack = require('webpack');
13
- class DevServerReloadPlugin {
14
- constructor(port, secure = false) {
15
- // When the parent terminates TLS (gateway.https), notify over https with the
16
- // self-signed cert accepted — the cert is ours (basic-ssl style, cached locally).
17
- this.secure = secure;
18
- this.url = `${secure ? 'https' : 'http'}://localhost:${port}/webpack/reload`;
19
- }
20
- notify() {
21
- return new Promise((resolve, reject) => {
22
- // eslint-disable-next-line @typescript-eslint/no-require-imports
23
- const mod = (this.secure ? require('node:https') : require('node:http'));
24
- const req = mod.request(this.url, { method: 'POST', headers: { 'content-type': 'application/json' }, rejectUnauthorized: false }, (res) => { res.resume(); res.on('end', resolve); });
25
- req.on('error', reject);
26
- req.end('{}');
27
- });
28
- }
29
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
30
- apply(compiler) {
31
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
32
- compiler.hooks.done.tap('DevServerReloadPlugin', async (stats) => {
33
- try {
34
- if (stats.hasErrors())
35
- return;
36
- await this.notify();
37
- console.log('[DevServerReloadPlugin] notified devserver to reload');
38
- }
39
- catch {
40
- console.log('[DevServerReloadPlugin] devserver not running yet');
41
- }
42
- });
43
- }
44
- }
45
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
46
- function createDevWebpackConfig(options) {
47
- const { appRoot, outputDir, main, tsConfig, workspaceRoot, assets = [], port, memoryLimit = 8192, buildLibsFromSource = true, orgScopes = [], bundlePackages = [], additionalEntryPoints = [], nodeExternalsConfig: userNodeExternalsConfig, webpackConfigPath, } = options;
48
- const { allowlistPatterns, scopePrefixes, scopePatterns } = (0, build_scope_patterns_1.buildScopePatterns)(orgScopes);
49
- // Type-checking mode (LENSMCP_TYPECHECK): default = the resident fork-ts-checker pair (async,
50
- // feeds the lens `error TS` service-error signal); 'off' = none (fastest, quietest — the signal
51
- // is traded away); 'tsgo' = zero-resident cold re-checks via @typescript/native-preview (same
52
- // signal, no idle memory — see tsgo-check-plugin.ts).
53
- //
54
- // tsgo still falls back to fork-ts-checker when no binary resolves — degrading gracefully beats
55
- // failing a dev server — but that fallback is now an ANOMALY, not the expected "the flag shipped
56
- // ahead of the devDep" state: @lensmcp/cluster DEPENDS on the compiler. So it also reports itself
57
- // onto the lens bus. fork-ts-checker publishes to the CONSOLE only, so without this the
58
- // `typecheck://` resources would sit at `producer: 'none'` with nothing naming the reason —
59
- // the precise "looks healthy because nobody is watching" state this producer exists to end.
60
- const typecheckMode = process.env.LENSMCP_TYPECHECK;
61
- const tsgoBin = typecheckMode === 'tsgo' ? (0, tsgo_check_plugin_1.resolveTsgoBin)(workspaceRoot, process.env.LENSMCP_TSGO_BIN) : null;
62
- if (typecheckMode === 'tsgo' && !tsgoBin) {
63
- // No trailing period: `summariseProducers` renders this INSIDE a sentence it terminates itself.
64
- const detail = `${tsgo_check_plugin_1.TSGO_MISSING_CAUSE}. Fell back to fork-ts-checker, which reports to the console only — ` +
65
- `so typecheck:// has no producer for this project until it is fixed`;
66
- console.warn(`[serve] ${options.appName}: LENSMCP_TYPECHECK=tsgo but ${detail}.`);
67
- (0, tsgo_check_plugin_1.reportTsgoUnavailable)({ appName: options.appName, tsConfig, workspaceRoot, detail });
68
- }
69
- const useTsgo = !!tsgoBin;
70
- // Build combined allowlist: orgScopes + bundlePackages + user-provided
71
- const bundlePatterns = bundlePackages.map((pkg) => new RegExp(`^${pkg.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}(/|$)`));
72
- const combinedAllowlist = [
73
- /webpack\/hot\/poll\?100/,
74
- ...allowlistPatterns,
75
- ...bundlePatterns,
76
- ...(userNodeExternalsConfig?.allowlist || []),
77
- ];
78
- const config = {
79
- output: {
80
- path: outputDir,
81
- ...(process.env.NODE_ENV !== 'production' && {
82
- devtoolModuleFilenameTemplate: '[absolute-resource-path]',
83
- }),
84
- clean: true,
85
- },
86
- externals: [
87
- (0, webpack_node_externals_1.default)({
88
- allowlist: combinedAllowlist,
89
- additionalModuleDirs: userNodeExternalsConfig?.additionalModuleDirs || [],
90
- ...(userNodeExternalsConfig?.importType && { importType: userNodeExternalsConfig.importType }),
91
- }),
92
- ({ request }, callback) => {
93
- // Workspace-internal absolute requests are SOURCE regardless of the
94
- // bucket layout (apps/, libs/, server/, shared/, web/, …) — bundle them.
95
- // The apps/libs prefix checks below stay for explicitness/back-compat.
96
- if (request &&
97
- path.isAbsolute(request) &&
98
- request.startsWith(workspaceRoot) &&
99
- !request.includes('node_modules')) {
100
- return callback();
101
- }
102
- if (request &&
103
- (request.startsWith(path.join(workspaceRoot, 'apps')) ||
104
- request.startsWith(path.join(workspaceRoot, 'libs')))) {
105
- return callback();
106
- }
107
- if (request && scopePrefixes.some((prefix) => request.startsWith(prefix))) {
108
- return callback();
109
- }
110
- if (request && scopePatterns.some((pattern) => pattern.test(request))) {
111
- return callback();
112
- }
113
- if (request && bundlePatterns.some((pattern) => pattern.test(request))) {
114
- return callback();
115
- }
116
- if (request && !(request.startsWith('./') || request.startsWith('..'))) {
117
- // Bare specifier: only a real node_modules package may stay external —
118
- // tsconfig-path aliases (e.g. @org/contracts → workspace source) must bundle.
119
- const rootSegment = request.startsWith('@')
120
- ? request.split('/').slice(0, 2).join('/')
121
- : request.split('/')[0];
122
- if (!fs.existsSync(path.join(workspaceRoot, 'node_modules', rootSegment))) {
123
- return callback();
124
- }
125
- return callback(null, `commonjs ${request}`);
126
- }
127
- return callback();
128
- },
129
- ],
130
- mode: 'development',
131
- devtool: 'eval-cheap-module-source-map',
132
- plugins: [
133
- new webpack.HotModuleReplacementPlugin(),
134
- new app_plugin_1.NxAppWebpackPlugin({
135
- target: 'node22',
136
- compiler: 'tsc',
137
- main,
138
- additionalEntryPoints,
139
- verbose: true,
140
- sourceMap: 'eval-cheap-module-source-map',
141
- mergeExternals: true,
142
- externalDependencies: [],
143
- memoryLimit,
144
- tsConfig,
145
- assets,
146
- optimization: false,
147
- progress: false,
148
- outputHashing: 'none',
149
- generatePackageJson: false,
150
- watchDependencies: true,
151
- // Type checking = the fork-ts-checker pair (2 worker processes, ~80MB per service) AND the
152
- // source of the in-pod `error TS…` lines the gateway sniffs into the lens "service error"
153
- // signal. Default ON. `LENSMCP_TYPECHECK=off` trades the signal for memory/CPU;
154
- // `LENSMCP_TYPECHECK=tsgo` keeps the signal at zero resident cost (the TsgoCheckPlugin
155
- // below replaces the resident pair with debounced cold native checks).
156
- typeCheckOptions: process.env.LENSMCP_TYPECHECK === 'off' || useTsgo ? false : { async: true },
157
- buildLibsFromSource,
158
- }),
159
- new DevServerReloadPlugin(port, options.httpsReload === true),
160
- ...(useTsgo
161
- ? [
162
- new tsgo_check_plugin_1.TsgoCheckPlugin({
163
- appName: options.appName,
164
- tsConfig,
165
- workspaceRoot,
166
- ...(process.env.LENSMCP_TSGO_BIN ? { binPath: process.env.LENSMCP_TSGO_BIN } : {}),
167
- }),
168
- ]
169
- : []),
170
- ],
171
- snapshot: { managedPaths: [/^(.+?[\\/])?node_modules[\\/]/] },
172
- watch: true,
173
- watchOptions: {
174
- ignored: ['**/*.env.template', '**/config.template.json', '**/*.md', '**/dist/**', '**/migrations/**'],
175
- },
176
- cache: { type: 'filesystem' },
177
- };
178
- // Apply user webpack overrides if configured
179
- if (webpackConfigPath) {
180
- // eslint-disable-next-line @typescript-eslint/no-require-imports
181
- const overrideModule = require(path.resolve(appRoot, webpackConfigPath));
182
- const overrideFn = overrideModule.default || overrideModule;
183
- return overrideFn(config);
184
- }
185
- return config;
186
- }
1
+ "use strict";var x=Object.defineProperty;var u=(o,t)=>x(o,"name",{value:t,configurable:!0});var T=Object.defineProperty,l=u((o,t)=>T(o,"name",{value:t,configurable:!0}),"l");Object.defineProperty(exports,"__esModule",{value:!0}),exports.createDevWebpackConfig=createDevWebpackConfig;const tslib_1=require("tslib"),app_plugin_1=require("@nx/webpack/app-plugin"),fs=tslib_1.__importStar(require("node:fs")),path=tslib_1.__importStar(require("node:path")),webpack_node_externals_1=tslib_1.__importDefault(require("webpack-node-externals")),build_scope_patterns_1=require("./build-scope-patterns"),tsgo_check_plugin_1=require("./tsgo-check-plugin"),webpack=require("webpack");class DevServerReloadPlugin{static{u(this,"DevServerReloadPlugin")}static{l(this,"DevServerReloadPlugin")}constructor(t,s=!1){this.secure=s,this.url=`${s?"https":"http"}://localhost:${t}/webpack/reload`}notify(){return new Promise((t,s)=>{const i=(this.secure?require("node:https"):require("node:http")).request(this.url,{method:"POST",headers:{"content-type":"application/json"},rejectUnauthorized:!1},a=>{a.resume(),a.on("end",t)});i.on("error",s),i.end("{}")})}apply(t){t.hooks.done.tap("DevServerReloadPlugin",async s=>{try{if(s.hasErrors())return;await this.notify(),console.log("[DevServerReloadPlugin] notified devserver to reload")}catch{console.log("[DevServerReloadPlugin] devserver not running yet")}})}}function createDevWebpackConfig(o){const{appRoot:t,outputDir:s,main:i,tsConfig:a,workspaceRoot:r,assets:f=[],port:b,memoryLimit:P=8192,buildLibsFromSource:k=!0,orgScopes:w=[],bundlePackages:S=[],additionalEntryPoints:C=[],nodeExternalsConfig:p,webpackConfigPath:d}=o,{allowlistPatterns:y,scopePrefixes:E,scopePatterns:N}=(0,build_scope_patterns_1.buildScopePatterns)(w),h=process.env.LENSMCP_TYPECHECK,m=h==="tsgo"?(0,tsgo_check_plugin_1.resolveTsgoBin)(r,process.env.LENSMCP_TSGO_BIN):null;if(h==="tsgo"&&!m){const e=`${tsgo_check_plugin_1.TSGO_MISSING_CAUSE}. Fell back to fork-ts-checker, which reports to the console only \u2014 so typecheck:// has no producer for this project until it is fixed`;console.warn(`[serve] ${o.appName}: LENSMCP_TYPECHECK=tsgo but ${e}.`),(0,tsgo_check_plugin_1.reportTsgoUnavailable)({appName:o.appName,tsConfig:a,workspaceRoot:r,detail:e})}const g=!!m,v=S.map(e=>new RegExp(`^${e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}(/|$)`)),D=[/webpack\/hot\/poll\?100/,...y,...v,...p?.allowlist||[]],_={output:{path:s,...process.env.NODE_ENV!=="production"&&{devtoolModuleFilenameTemplate:"[absolute-resource-path]"},clean:!0},externals:[(0,webpack_node_externals_1.default)({allowlist:D,additionalModuleDirs:p?.additionalModuleDirs||[],...p?.importType&&{importType:p.importType}}),({request:e},c)=>{if(e&&path.isAbsolute(e)&&e.startsWith(r)&&!e.includes("node_modules")||e&&(e.startsWith(path.join(r,"apps"))||e.startsWith(path.join(r,"libs")))||e&&E.some(n=>e.startsWith(n))||e&&N.some(n=>n.test(e))||e&&v.some(n=>n.test(e)))return c();if(e&&!(e.startsWith("./")||e.startsWith(".."))){const n=e.startsWith("@")?e.split("/").slice(0,2).join("/"):e.split("/")[0];return fs.existsSync(path.join(r,"node_modules",n))?c(null,`commonjs ${e}`):c()}return c()}],mode:"development",devtool:"eval-cheap-module-source-map",plugins:[new webpack.HotModuleReplacementPlugin,new app_plugin_1.NxAppWebpackPlugin({target:"node22",compiler:"tsc",main:i,additionalEntryPoints:C,verbose:!0,sourceMap:"eval-cheap-module-source-map",mergeExternals:!0,externalDependencies:[],memoryLimit:P,tsConfig:a,assets:f,optimization:!1,progress:!1,outputHashing:"none",generatePackageJson:!1,watchDependencies:!0,typeCheckOptions:process.env.LENSMCP_TYPECHECK==="off"||g?!1:{async:!0},buildLibsFromSource:k}),new DevServerReloadPlugin(b,o.httpsReload===!0),...g?[new tsgo_check_plugin_1.TsgoCheckPlugin({appName:o.appName,tsConfig:a,workspaceRoot:r,...process.env.LENSMCP_TSGO_BIN?{binPath:process.env.LENSMCP_TSGO_BIN}:{}})]:[]],snapshot:{managedPaths:[/^(.+?[\\/])?node_modules[\\/]/]},watch:!0,watchOptions:{ignored:["**/*.env.template","**/config.template.json","**/*.md","**/dist/**","**/migrations/**"]},cache:{type:"filesystem"}};if(d){const e=require(path.resolve(t,d));return(e.default||e)(_)}return _}u(createDevWebpackConfig,"createDevWebpackConfig"),l(createDevWebpackConfig,"createDevWebpackConfig");