@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
@@ -1,169 +1 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createProdWebpackConfig = createProdWebpackConfig;
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 glob_1 = require("glob");
9
- const webpack_node_externals_1 = tslib_1.__importDefault(require("webpack-node-externals"));
10
- const build_scope_patterns_1 = require("./build-scope-patterns");
11
- function createProdWebpackConfig(options) {
12
- const { appRoot, outputDir, main, tsConfig, workspaceRoot, assets = [], additionalEntryPoints = [], runtimeDependencies = [], memoryLimit = 8192, generatePackageJson = true, buildLibsFromSource = false, ormConfigPath, migrationsDir = './src/migrations', orgScopes = [], bundlePackages = [], nodeExternalsConfig: userNodeExternalsConfig, webpackConfigPath, } = options;
13
- const { allowlistPatterns, scopePrefixes, scopePatterns } = (0, build_scope_patterns_1.buildScopePatterns)(orgScopes);
14
- // Build combined allowlist: orgScopes + bundlePackages + user-provided
15
- const bundlePatterns = bundlePackages.map((pkg) => new RegExp(`^${pkg.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}(/|$)`));
16
- const combinedAllowlist = [
17
- ...allowlistPatterns,
18
- ...bundlePatterns,
19
- ...(userNodeExternalsConfig?.allowlist || []),
20
- ];
21
- // Detect ormconfig.ts for the app so we can build it for TypeORM CLI in production
22
- let resolvedOrmConfigPath;
23
- if (ormConfigPath !== undefined) {
24
- resolvedOrmConfigPath = ormConfigPath ? path.join(appRoot, ormConfigPath) : null;
25
- }
26
- else {
27
- const candidate = path.join(appRoot, './src/ormconfig.ts');
28
- resolvedOrmConfigPath = fs.existsSync(candidate) ? candidate : null;
29
- }
30
- const hasOrmconfig = resolvedOrmConfigPath && fs.existsSync(resolvedOrmConfigPath);
31
- const webpackConfigs = [];
32
- const externalsConfig = [
33
- (0, webpack_node_externals_1.default)({
34
- allowlist: combinedAllowlist,
35
- additionalModuleDirs: userNodeExternalsConfig?.additionalModuleDirs || [],
36
- ...(userNodeExternalsConfig?.importType && { importType: userNodeExternalsConfig.importType }),
37
- }),
38
- ({ request }, callback) => {
39
- // Workspace-internal absolute requests are SOURCE regardless of the
40
- // bucket layout (apps/, libs/, server/, shared/, web/, …) — bundle them.
41
- if (request &&
42
- path.isAbsolute(request) &&
43
- request.startsWith(workspaceRoot) &&
44
- !request.includes('node_modules')) {
45
- return callback();
46
- }
47
- if (request &&
48
- (request.startsWith(path.join(workspaceRoot, 'apps')) ||
49
- request.startsWith(path.join(workspaceRoot, 'libs')))) {
50
- return callback();
51
- }
52
- if (request && scopePrefixes.some((prefix) => request.startsWith(prefix))) {
53
- return callback();
54
- }
55
- if (request && scopePatterns.some((pattern) => pattern.test(request))) {
56
- return callback();
57
- }
58
- if (request && bundlePatterns.some((pattern) => pattern.test(request))) {
59
- return callback();
60
- }
61
- if (request && !(request.startsWith('./') || request.startsWith('..'))) {
62
- // Bare specifier: only a real node_modules package may stay external —
63
- // tsconfig-path aliases (e.g. @org/contracts → workspace source) must bundle.
64
- const rootSegment = request.startsWith('@')
65
- ? request.split('/').slice(0, 2).join('/')
66
- : request.split('/')[0];
67
- if (!fs.existsSync(path.join(workspaceRoot, 'node_modules', rootSegment))) {
68
- return callback();
69
- }
70
- return callback(null, `commonjs ${request}`);
71
- }
72
- return callback();
73
- },
74
- ];
75
- const productionBuildConfig = {
76
- externals: externalsConfig,
77
- output: {
78
- path: outputDir,
79
- clean: false,
80
- },
81
- devtool: 'inline-source-map',
82
- mode: 'production',
83
- plugins: [
84
- new app_plugin_1.NxAppWebpackPlugin({
85
- target: 'node22',
86
- compiler: 'tsc',
87
- main,
88
- additionalEntryPoints,
89
- externalDependencies: [],
90
- mergeExternals: true,
91
- memoryLimit,
92
- tsConfig,
93
- assets,
94
- namedChunks: true,
95
- optimization: true,
96
- outputHashing: 'none',
97
- generatePackageJson,
98
- runtimeDependencies,
99
- buildLibsFromSource,
100
- typeCheckOptions: {
101
- async: false,
102
- },
103
- sourceMap: 'inline-source-map',
104
- progress: false,
105
- }),
106
- ],
107
- };
108
- webpackConfigs.push(productionBuildConfig);
109
- if (hasOrmconfig && resolvedOrmConfigPath) {
110
- const migrationsEntryPoints = [];
111
- const migrationsGlobPath = path.join(appRoot, migrationsDir, '*.ts');
112
- const migrationFiles = (0, glob_1.globSync)(migrationsGlobPath);
113
- migrationFiles.forEach((filename) => {
114
- const migrationName = path.basename(filename, '.ts');
115
- migrationsEntryPoints.push({
116
- entryName: `migrations/${migrationName}`,
117
- entryPath: filename,
118
- });
119
- });
120
- const ormconfigRelative = './' + path.relative(appRoot, resolvedOrmConfigPath);
121
- const ormconfigBuildConfig = {
122
- ...productionBuildConfig,
123
- output: {
124
- ...productionBuildConfig.output,
125
- filename: (pathData) => {
126
- if (pathData.runtime === 'main') {
127
- return 'ormconfig.js';
128
- }
129
- return '[name].js';
130
- },
131
- library: {
132
- type: 'commonjs',
133
- },
134
- clean: false,
135
- },
136
- devtool: false,
137
- plugins: [
138
- new app_plugin_1.NxAppWebpackPlugin({
139
- target: 'node22',
140
- compiler: 'tsc',
141
- main: ormconfigRelative,
142
- externalDependencies: [],
143
- additionalEntryPoints: migrationsEntryPoints,
144
- mergeExternals: true,
145
- tsConfig,
146
- assets: [],
147
- namedChunks: true,
148
- memoryLimit,
149
- optimization: false,
150
- outputHashing: 'none',
151
- generatePackageJson: false,
152
- buildLibsFromSource,
153
- skipTypeChecking: true,
154
- sourceMap: false,
155
- progress: !process.env.CI,
156
- }),
157
- ],
158
- };
159
- webpackConfigs.push(ormconfigBuildConfig);
160
- }
161
- // Apply user webpack overrides if configured
162
- if (webpackConfigPath) {
163
- // eslint-disable-next-line @typescript-eslint/no-require-imports
164
- const overrideModule = require(path.resolve(appRoot, webpackConfigPath));
165
- const overrideFn = overrideModule.default || overrideModule;
166
- return webpackConfigs.map((config) => overrideFn(config));
167
- }
168
- return webpackConfigs;
169
- }
1
+ "use strict";var A=Object.defineProperty;var d=(o,n)=>A(o,"name",{value:n,configurable:!0});var F=Object.defineProperty,m=d((o,n)=>F(o,"name",{value:n,configurable:!0}),"m");Object.defineProperty(exports,"__esModule",{value:!0}),exports.createProdWebpackConfig=createProdWebpackConfig;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")),glob_1=require("glob"),webpack_node_externals_1=tslib_1.__importDefault(require("webpack-node-externals")),build_scope_patterns_1=require("./build-scope-patterns");function createProdWebpackConfig(o){const{appRoot:n,outputDir:P,main:_,tsConfig:g,workspaceRoot:r,assets:k=[],additionalEntryPoints:x=[],runtimeDependencies:C=[],memoryLimit:b=8192,generatePackageJson:j=!0,buildLibsFromSource:f=!1,ormConfigPath:c,migrationsDir:W="./src/migrations",orgScopes:w=[],bundlePackages:S=[],nodeExternalsConfig:a,webpackConfigPath:h}=o,{allowlistPatterns:v,scopePrefixes:D,scopePatterns:q}=(0,build_scope_patterns_1.buildScopePatterns)(w),y=S.map(e=>new RegExp(`^${e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}(/|$)`)),E=[...v,...y,...a?.allowlist||[]];let s;if(c!==void 0)s=c?path.join(n,c):null;else{const e=path.join(n,"./src/ormconfig.ts");s=fs.existsSync(e)?e:null}const $=s&&fs.existsSync(s),p=[],u={externals:[(0,webpack_node_externals_1.default)({allowlist:E,additionalModuleDirs:a?.additionalModuleDirs||[],...a?.importType&&{importType:a.importType}}),({request:e},i)=>{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&&D.some(t=>e.startsWith(t))||e&&q.some(t=>t.test(e))||e&&y.some(t=>t.test(e)))return i();if(e&&!(e.startsWith("./")||e.startsWith(".."))){const t=e.startsWith("@")?e.split("/").slice(0,2).join("/"):e.split("/")[0];return fs.existsSync(path.join(r,"node_modules",t))?i(null,`commonjs ${e}`):i()}return i()}],output:{path:P,clean:!1},devtool:"inline-source-map",mode:"production",plugins:[new app_plugin_1.NxAppWebpackPlugin({target:"node22",compiler:"tsc",main:_,additionalEntryPoints:x,externalDependencies:[],mergeExternals:!0,memoryLimit:b,tsConfig:g,assets:k,namedChunks:!0,optimization:!0,outputHashing:"none",generatePackageJson:j,runtimeDependencies:C,buildLibsFromSource:f,typeCheckOptions:{async:!1},sourceMap:"inline-source-map",progress:!1})]};if(p.push(u),$&&s){const e=[],i=path.join(n,W,"*.ts");(0,glob_1.globSync)(i).forEach(l=>{const M=path.basename(l,".ts");e.push({entryName:`migrations/${M}`,entryPath:l})});const t="./"+path.relative(n,s),L={...u,output:{...u.output,filename:m(l=>l.runtime==="main"?"ormconfig.js":"[name].js","filename"),library:{type:"commonjs"},clean:!1},devtool:!1,plugins:[new app_plugin_1.NxAppWebpackPlugin({target:"node22",compiler:"tsc",main:t,externalDependencies:[],additionalEntryPoints:e,mergeExternals:!0,tsConfig:g,assets:[],namedChunks:!0,memoryLimit:b,optimization:!1,outputHashing:"none",generatePackageJson:!1,buildLibsFromSource:f,skipTypeChecking:!0,sourceMap:!1,progress:!process.env.CI})]};p.push(L)}if(h){const e=require(path.resolve(n,h)),i=e.default||e;return p.map(t=>i(t))}return p}d(createProdWebpackConfig,"createProdWebpackConfig"),m(createProdWebpackConfig,"createProdWebpackConfig");
@@ -1,98 +1 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const tslib_1 = require("tslib");
4
- const fs = tslib_1.__importStar(require("node:fs"));
5
- const path = tslib_1.__importStar(require("node:path"));
6
- const create_webpack_prod_1 = require("../../create-webpack-prod");
7
- // eslint-disable-next-line @typescript-eslint/no-require-imports
8
- const webpack = require('webpack');
9
- /**
10
- * Production webpack build executor for NestJS applications.
11
- */
12
- async function* buildExecutor(options, context) {
13
- process.env.NODE_ENV = 'production';
14
- const projectConfig = context.projectsConfigurations.projects[context.projectName];
15
- const workspaceRoot = context.root;
16
- const projectRoot = path.join(workspaceRoot, projectConfig.root);
17
- const outputPath = options.outputPath
18
- ? path.join(workspaceRoot, options.outputPath)
19
- : path.join(workspaceRoot, 'dist', projectConfig.root);
20
- // Resolve entry/tsconfig relative to project root (absolute paths avoid
21
- // NxAppWebpackPlugin's normalizeRelativePaths collision with executor options)
22
- const entryFile = options.entryFile || './src/deployments/service/main.ts';
23
- const tsConfigFile = options.tsConfigFile || './tsconfig.app.json';
24
- const resolvedMain = path.resolve(projectRoot, entryFile);
25
- const resolvedTsConfig = path.resolve(projectRoot, tsConfigFile);
26
- const configs = (0, create_webpack_prod_1.createProdWebpackConfig)({
27
- appName: context.projectName,
28
- appRoot: projectRoot,
29
- outputDir: outputPath,
30
- main: resolvedMain,
31
- tsConfig: resolvedTsConfig,
32
- assets: options.assets || [],
33
- additionalEntryPoints: [
34
- ...(options.workers || []).map((w) => ({ entryName: w.name, entryPath: w.entryPath })),
35
- ...(options.additionalEntryPoints || []),
36
- ],
37
- runtimeDependencies: options.runtimeDependencies || [],
38
- memoryLimit: options.memoryLimit || 8192,
39
- generatePackageJson: options.generatePackageJson !== false,
40
- buildLibsFromSource: options.buildLibsFromSource || false,
41
- ormConfigPath: options.ormConfigPath,
42
- migrationsDir: options.migrationsDir || './src/migrations',
43
- workspaceRoot,
44
- orgScopes: options.orgScopes || [],
45
- bundlePackages: options.bundlePackages || [],
46
- nodeExternalsConfig: options.nodeExternalsConfig,
47
- webpackConfigPath: options.webpackConfigPath,
48
- });
49
- const configArray = Array.isArray(configs) ? configs : [configs];
50
- for (const config of configArray) {
51
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
52
- const { watch: _watch, ...normalizedConfig } = config;
53
- const compiler = webpack(normalizedConfig);
54
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
55
- const stats = await new Promise((resolve, reject) => {
56
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
57
- compiler.run((err, stats) => {
58
- if (err)
59
- return reject(err);
60
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
61
- compiler.close((closeErr) => {
62
- if (closeErr)
63
- console.error('[build] webpack close error:', closeErr);
64
- });
65
- resolve(stats);
66
- });
67
- });
68
- console.info(stats.toString(config.stats || { colors: true, chunks: false }));
69
- if (stats.hasErrors()) {
70
- yield { success: false };
71
- return;
72
- }
73
- }
74
- // Post-process: minify worker outputs (NxAppWebpackPlugin doesn't minify additional entries)
75
- const workerEntries = options.workers || [];
76
- if (workerEntries.length > 0) {
77
- // eslint-disable-next-line @typescript-eslint/no-require-imports
78
- const { minify } = require('terser');
79
- for (const worker of workerEntries) {
80
- const filePath = path.join(outputPath, `${worker.name}.js`);
81
- if (fs.existsSync(filePath)) {
82
- const code = fs.readFileSync(filePath, 'utf-8');
83
- const result = await minify(code, {
84
- keep_classnames: true,
85
- sourceMap: { content: 'inline', url: 'inline' },
86
- });
87
- if (result.code) {
88
- fs.writeFileSync(filePath, result.code);
89
- console.info(`[build] minified ${worker.name}.js`);
90
- }
91
- }
92
- }
93
- }
94
- yield { success: true, outfile: path.join(outputPath, 'main.js') };
95
- }
96
- exports.default = buildExecutor;
97
- module.exports = buildExecutor;
98
- module.exports.default = buildExecutor;
1
+ "use strict";var x=Object.defineProperty;var d=(e,o)=>x(e,"name",{value:o,configurable:!0});var _=Object.defineProperty,p=d((e,o)=>_(e,"name",{value:o,configurable:!0}),"p");Object.defineProperty(exports,"__esModule",{value:!0});const tslib_1=require("tslib"),fs=tslib_1.__importStar(require("node:fs")),path=tslib_1.__importStar(require("node:path")),create_webpack_prod_1=require("../../create-webpack-prod"),webpack=require("webpack");async function*buildExecutor(e,o){process.env.NODE_ENV="production";const m=o.projectsConfigurations.projects[o.projectName],n=o.root,a=path.join(n,m.root),c=e.outputPath?path.join(n,e.outputPath):path.join(n,"dist",m.root),y=e.entryFile||"./src/deployments/service/main.ts",P=e.tsConfigFile||"./tsconfig.app.json",k=path.resolve(a,y),h=path.resolve(a,P),u=(0,create_webpack_prod_1.createProdWebpackConfig)({appName:o.projectName,appRoot:a,outputDir:c,main:k,tsConfig:h,assets:e.assets||[],additionalEntryPoints:[...(e.workers||[]).map(r=>({entryName:r.name,entryPath:r.entryPath})),...e.additionalEntryPoints||[]],runtimeDependencies:e.runtimeDependencies||[],memoryLimit:e.memoryLimit||8192,generatePackageJson:e.generatePackageJson!==!1,buildLibsFromSource:e.buildLibsFromSource||!1,ormConfigPath:e.ormConfigPath,migrationsDir:e.migrationsDir||"./src/migrations",workspaceRoot:n,orgScopes:e.orgScopes||[],bundlePackages:e.bundlePackages||[],nodeExternalsConfig:e.nodeExternalsConfig,webpackConfigPath:e.webpackConfigPath}),j=Array.isArray(u)?u:[u];for(const r of j){const{watch:l,...t}=r,s=webpack(t),i=await new Promise((w,C)=>{s.run((b,S)=>{if(b)return C(b);s.close(g=>{g&&console.error("[build] webpack close error:",g)}),w(S)})});if(console.info(i.toString(r.stats||{colors:!0,chunks:!1})),i.hasErrors()){yield{success:!1};return}}const f=e.workers||[];if(f.length>0){const{minify:r}=require("terser");for(const l of f){const t=path.join(c,`${l.name}.js`);if(fs.existsSync(t)){const s=fs.readFileSync(t,"utf-8"),i=await r(s,{keep_classnames:!0,sourceMap:{content:"inline",url:"inline"}});i.code&&(fs.writeFileSync(t,i.code),console.info(`[build] minified ${l.name}.js`))}}}yield{success:!0,outfile:path.join(c,"main.js")}}d(buildExecutor,"buildExecutor"),p(buildExecutor,"buildExecutor"),exports.default=buildExecutor,module.exports=buildExecutor,module.exports.default=buildExecutor;
@@ -1,43 +1 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.GATEWAY_ERROR_CONTENT_TYPE = exports.GATEWAY_ERROR_KEY = void 0;
4
- exports.ensureRequestId = ensureRequestId;
5
- exports.gatewayErrorBody = gatewayErrorBody;
6
- /** Reason → stable, neutral localized key (the consumer translates the `gateway.*` namespace). */
7
- exports.GATEWAY_ERROR_KEY = {
8
- bad_request: 'gateway.badRequest',
9
- unauthorized: 'gateway.unauthorized',
10
- forbidden: 'gateway.forbidden',
11
- not_found: 'gateway.notFound',
12
- rate_limited: 'gateway.rateLimited',
13
- unavailable: 'gateway.unavailable',
14
- internal: 'gateway.internal',
15
- };
16
- const headerValue = (v) => typeof v === 'string' && v !== '' ? v : Array.isArray(v) ? v[0] : undefined;
17
- const mintId = () => Date.now().toString(36) + Math.random().toString(36).slice(2, 12);
18
- /**
19
- * Ensure the request carries an `x-request-id` (mint one at the edge if absent) and return it. Because
20
- * the gateway forwards `req.headers` to the upstream, the pod's request-context adopts THIS id as its
21
- * `traceId`, and the gateway returns it on the response — one id, end-to-end, for ANY request.
22
- */
23
- function ensureRequestId(req) {
24
- const existing = headerValue(req.headers['x-request-id']);
25
- if (existing)
26
- return existing;
27
- const rid = mintId();
28
- req.headers['x-request-id'] = rid;
29
- return rid;
30
- }
31
- /**
32
- * Build the JSON edge-error body `{ key, status, traceId, message? }`. `detail` becomes the dev-facing
33
- * `message` (e.g. the old plain-text reason), never surfaced to end users.
34
- */
35
- function gatewayErrorBody(status, reason, traceId, detail) {
36
- return JSON.stringify({
37
- key: exports.GATEWAY_ERROR_KEY[reason],
38
- status,
39
- traceId,
40
- ...(detail ? { message: detail } : {}),
41
- });
42
- }
43
- exports.GATEWAY_ERROR_CONTENT_TYPE = 'application/json; charset=utf-8';
1
+ "use strict";var i=Object.defineProperty;var n=(e,t)=>i(e,"name",{value:t,configurable:!0});var o=Object.defineProperty,r=n((e,t)=>o(e,"name",{value:t,configurable:!0}),"r");Object.defineProperty(exports,"__esModule",{value:!0}),exports.GATEWAY_ERROR_CONTENT_TYPE=exports.GATEWAY_ERROR_KEY=void 0,exports.ensureRequestId=ensureRequestId,exports.gatewayErrorBody=gatewayErrorBody,exports.GATEWAY_ERROR_KEY={bad_request:"gateway.badRequest",unauthorized:"gateway.unauthorized",forbidden:"gateway.forbidden",not_found:"gateway.notFound",rate_limited:"gateway.rateLimited",unavailable:"gateway.unavailable",internal:"gateway.internal"};const headerValue=r(e=>typeof e=="string"&&e!==""?e:Array.isArray(e)?e[0]:void 0,"headerValue"),mintId=r(()=>Date.now().toString(36)+Math.random().toString(36).slice(2,12),"mintId");function ensureRequestId(e){const t=headerValue(e.headers["x-request-id"]);if(t)return t;const a=mintId();return e.headers["x-request-id"]=a,a}n(ensureRequestId,"ensureRequestId"),r(ensureRequestId,"ensureRequestId");function gatewayErrorBody(e,t,a,s){return JSON.stringify({key:exports.GATEWAY_ERROR_KEY[t],status:e,traceId:a,...s?{message:s}:{}})}n(gatewayErrorBody,"gatewayErrorBody"),r(gatewayErrorBody,"gatewayErrorBody"),exports.GATEWAY_ERROR_CONTENT_TYPE="application/json; charset=utf-8";
@@ -1,53 +1 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.default = gatewayExecutor;
4
- const gateway_lib_1 = require("./gateway.lib");
5
- const server_1 = require("./runtime/server");
6
- /**
7
- * `gateway` executor — ONE https front door for the whole workspace,
8
- * assembled dynamically from every project's `cluster` declaration:
9
- *
10
- * "cluster": { "host": "api.tetros.ai.local", "service": "api", "prependPrefix": "/api" }
11
- * "cluster": { "host": "tetros.ai.local", "port": 5173, "default": true }
12
- *
13
- * Socket-pool services get production-shaped treatment: the gateway is the
14
- * load balancer, round-robining each request across the service's child
15
- * sockets (the pods), with serverless lifecycle (eager/minPods/maxPods/
16
- * idleKillSec) and an auto `internal.<host>` domain for east-west calls
17
- * that bypass the middleware (JWT) — a full prod demo on localhost. All of
18
- * it is published to the LensMCP bus (source `gateway`, category `cluster`).
19
- *
20
- * The runtime lives in `gateway.lib.ts` (`startGateway`) so it is testable
21
- * without signals; this wrapper only adds the executor contract.
22
- */
23
- async function gatewayExecutor(options, context) {
24
- // LAST-RESORT netting for the long-running daemon (this executor runs for DAYS): a benign socket
25
- // errno that escaped every layer's local handlers — e.g. a dependency emitting 'error' on a socket
26
- // it forgot to guard — must cost the ONE connection, never the process. Scoped to exactly the
27
- // read/write network errnos; anything else preserves crash semantics (print + exit 1, matching
28
- // Node's default). Lives HERE, not in startGateway, so tests driving the lib keep real crashes loud.
29
- process.on('uncaughtException', (err) => {
30
- if ((err.syscall === 'read' || err.syscall === 'write') && server_1.BENIGN_SOCKET_ERRNOS.has(err.code ?? '')) {
31
- console.warn(`[gateway] survived a stray socket ${err.syscall} error (${err.code}) — one connection dropped, the daemon lives`);
32
- return;
33
- }
34
- console.error(err);
35
- process.exit(1);
36
- });
37
- let handle;
38
- try {
39
- handle = await (0, gateway_lib_1.startGateway)(options, context);
40
- }
41
- catch (e) {
42
- console.error(e.message);
43
- return { success: false };
44
- }
45
- return new Promise((resolve) => {
46
- const stop = () => void handle.stop().then(() => resolve({ success: true }));
47
- process.on('SIGINT', stop);
48
- process.on('SIGTERM', stop);
49
- });
50
- }
51
- module.exports = gatewayExecutor;
52
- module.exports.default = gatewayExecutor;
53
- module.exports.startGateway = gateway_lib_1.startGateway;
1
+ "use strict";var u=Object.defineProperty;var s=(r,t)=>u(r,"name",{value:t,configurable:!0});var c=Object.defineProperty,o=s((r,t)=>c(r,"name",{value:t,configurable:!0}),"o");Object.defineProperty(exports,"__esModule",{value:!0}),exports.default=gatewayExecutor;const gateway_lib_1=require("./gateway.lib"),server_1=require("./runtime/server");async function gatewayExecutor(r,t){process.on("uncaughtException",e=>{if((e.syscall==="read"||e.syscall==="write")&&server_1.BENIGN_SOCKET_ERRNOS.has(e.code??"")){console.warn(`[gateway] survived a stray socket ${e.syscall} error (${e.code}) \u2014 one connection dropped, the daemon lives`);return}console.error(e),process.exit(1)});let a;try{a=await(0,gateway_lib_1.startGateway)(r,t)}catch(e){return console.error(e.message),{success:!1}}return new Promise(e=>{const n=o(()=>{a.stop().then(()=>e({success:!0}))},"stop");process.on("SIGINT",n),process.on("SIGTERM",n)})}s(gatewayExecutor,"gatewayExecutor"),o(gatewayExecutor,"gatewayExecutor"),module.exports=gatewayExecutor,module.exports.default=gatewayExecutor,module.exports.startGateway=gateway_lib_1.startGateway;
@@ -1,29 +1 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.discoverRoutes = exports.pickSock = exports.readLensScope = exports.deriveMcpHttpPort = exports.baseDomainOf = exports.stampIdentity = exports.verifyDevJwt = exports.startGateway = exports.hostMatches = void 0;
4
- /**
5
- * Public facade for the dev gateway runtime.
6
- *
7
- * The implementation now lives in `./runtime/*` as composable LAYERS — see
8
- * `runtime/server.ts` for the composition root (`startGateway`), `runtime/types.ts`
9
- * for the shared types + the customer **hooks** API, and the sibling modules for
10
- * each layer (discovery, dev-auth, observability, lifecycle, lens-children, proxy,
11
- * auth, hooks, handler, upgrade). This barrel preserves the original module's
12
- * public surface so the executor wrapper (`gateway.impl.ts`) and the existing
13
- * specs keep importing from one stable path, and additionally exposes the new
14
- * hooks types so customers can author typed layers on top of the gateway.
15
- */
16
- var manifest_1 = require("./manifest"); // back-compat re-export
17
- Object.defineProperty(exports, "hostMatches", { enumerable: true, get: function () { return manifest_1.hostMatches; } });
18
- var server_1 = require("./runtime/server");
19
- Object.defineProperty(exports, "startGateway", { enumerable: true, get: function () { return server_1.startGateway; } });
20
- var dev_auth_1 = require("./runtime/dev-auth");
21
- Object.defineProperty(exports, "verifyDevJwt", { enumerable: true, get: function () { return dev_auth_1.verifyDevJwt; } });
22
- Object.defineProperty(exports, "stampIdentity", { enumerable: true, get: function () { return dev_auth_1.stampIdentity; } });
23
- var scope_1 = require("./runtime/scope");
24
- Object.defineProperty(exports, "baseDomainOf", { enumerable: true, get: function () { return scope_1.baseDomainOf; } });
25
- Object.defineProperty(exports, "deriveMcpHttpPort", { enumerable: true, get: function () { return scope_1.deriveMcpHttpPort; } });
26
- Object.defineProperty(exports, "readLensScope", { enumerable: true, get: function () { return scope_1.readLensScope; } });
27
- var discovery_1 = require("./runtime/discovery");
28
- Object.defineProperty(exports, "pickSock", { enumerable: true, get: function () { return discovery_1.pickSock; } });
29
- Object.defineProperty(exports, "discoverRoutes", { enumerable: true, get: function () { return discovery_1.discoverRoutes; } });
1
+ "use strict";var i=Object.defineProperty;var n=(t,r)=>i(t,"name",{value:r,configurable:!0});var o=Object.defineProperty,e=n((t,r)=>o(t,"name",{value:r,configurable:!0}),"e");Object.defineProperty(exports,"__esModule",{value:!0}),exports.discoverRoutes=exports.pickSock=exports.readLensScope=exports.deriveMcpHttpPort=exports.baseDomainOf=exports.stampIdentity=exports.verifyDevJwt=exports.startGateway=exports.hostMatches=void 0;var manifest_1=require("./manifest");Object.defineProperty(exports,"hostMatches",{enumerable:!0,get:e(function(){return manifest_1.hostMatches},"get")});var server_1=require("./runtime/server");Object.defineProperty(exports,"startGateway",{enumerable:!0,get:e(function(){return server_1.startGateway},"get")});var dev_auth_1=require("./runtime/dev-auth");Object.defineProperty(exports,"verifyDevJwt",{enumerable:!0,get:e(function(){return dev_auth_1.verifyDevJwt},"get")}),Object.defineProperty(exports,"stampIdentity",{enumerable:!0,get:e(function(){return dev_auth_1.stampIdentity},"get")});var scope_1=require("./runtime/scope");Object.defineProperty(exports,"baseDomainOf",{enumerable:!0,get:e(function(){return scope_1.baseDomainOf},"get")}),Object.defineProperty(exports,"deriveMcpHttpPort",{enumerable:!0,get:e(function(){return scope_1.deriveMcpHttpPort},"get")}),Object.defineProperty(exports,"readLensScope",{enumerable:!0,get:e(function(){return scope_1.readLensScope},"get")});var discovery_1=require("./runtime/discovery");Object.defineProperty(exports,"pickSock",{enumerable:!0,get:e(function(){return discovery_1.pickSock},"get")}),Object.defineProperty(exports,"discoverRoutes",{enumerable:!0,get:e(function(){return discovery_1.discoverRoutes},"get")});
@@ -1,66 +1 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createHealthChecker = createHealthChecker;
4
- function createHealthChecker(opts = {}) {
5
- const path = opts.path ?? '/healthz';
6
- const intervalMs = opts.intervalMs ?? 5000;
7
- const timeoutMs = opts.timeoutMs ?? 2000;
8
- const downAt = Math.max(1, opts.unhealthyThreshold ?? 2);
9
- const upAt = Math.max(1, opts.healthyThreshold ?? 1);
10
- const doFetch = opts.fetchImpl ?? globalThis.fetch;
11
- const state = new Map();
12
- let timer;
13
- const probeUrl = (url) => url.replace(/\/+$/, '') + (path.startsWith('/') ? path : '/' + path);
14
- const probe = async (url) => {
15
- const st = state.get(url);
16
- if (!st)
17
- return;
18
- let ok = false;
19
- const ctl = new AbortController();
20
- const t = setTimeout(() => ctl.abort(), timeoutMs);
21
- try {
22
- const res = await doFetch(probeUrl(url), { method: 'GET', signal: ctl.signal, redirect: 'manual' });
23
- ok = res.status < 500; // answered → up (even 404); only 5xx counts as down
24
- }
25
- catch { /* network error / timeout → unhealthy (ok stays false) */ }
26
- finally {
27
- clearTimeout(t);
28
- }
29
- st.lastCheckedAt = Date.now();
30
- if (ok) {
31
- st.oks += 1;
32
- st.fails = 0;
33
- if (!st.healthy && st.oks >= upAt) {
34
- st.healthy = true;
35
- opts.onChange?.(url, true);
36
- }
37
- }
38
- else {
39
- st.fails += 1;
40
- st.oks = 0;
41
- if (st.healthy && st.fails >= downAt) {
42
- st.healthy = false;
43
- opts.onChange?.(url, false);
44
- }
45
- }
46
- };
47
- const probeOnce = () => Promise.allSettled([...state.keys()].map(probe)).then(() => undefined);
48
- return {
49
- track(urls) {
50
- const next = new Set(urls);
51
- for (const u of urls)
52
- if (!state.has(u))
53
- state.set(u, { healthy: true, fails: 0, oks: 0, lastCheckedAt: null });
54
- for (const u of [...state.keys()])
55
- if (!next.has(u))
56
- state.delete(u);
57
- },
58
- isHealthy: (url) => state.get(url)?.healthy ?? true,
59
- snapshot: () => [...state.entries()].map(([url, s]) => ({ url, healthy: s.healthy, fails: s.fails, lastCheckedAt: s.lastCheckedAt })),
60
- probeOnce,
61
- start() { if (timer)
62
- return; timer = setInterval(() => void probeOnce(), intervalMs); timer.unref?.(); void probeOnce(); },
63
- stop() { if (timer)
64
- clearInterval(timer); timer = undefined; },
65
- };
66
- }
1
+ "use strict";var g=Object.defineProperty;var c=(a,h)=>g(a,"name",{value:h,configurable:!0});var C=Object.defineProperty,n=c((a,h)=>C(a,"name",{value:h,configurable:!0}),"n");Object.defineProperty(exports,"__esModule",{value:!0}),exports.createHealthChecker=createHealthChecker;function createHealthChecker(a={}){const h=a.path??"/healthz",f=a.intervalMs??5e3,y=a.timeoutMs??2e3,p=Math.max(1,a.unhealthyThreshold??2),u=Math.max(1,a.healthyThreshold??1),d=a.fetchImpl??globalThis.fetch,l=new Map;let r;const k=n(t=>t.replace(/\/+$/,"")+(h.startsWith("/")?h:"/"+h),"probeUrl"),m=n(async t=>{const e=l.get(t);if(!e)return;let s=!1;const i=new AbortController,b=setTimeout(()=>i.abort(),y);try{s=(await d(k(t),{method:"GET",signal:i.signal,redirect:"manual"})).status<500}catch{}finally{clearTimeout(b)}e.lastCheckedAt=Date.now(),s?(e.oks+=1,e.fails=0,!e.healthy&&e.oks>=u&&(e.healthy=!0,a.onChange?.(t,!0))):(e.fails+=1,e.oks=0,e.healthy&&e.fails>=p&&(e.healthy=!1,a.onChange?.(t,!1)))},"probe"),o=n(()=>Promise.allSettled([...l.keys()].map(m)).then(()=>{}),"probeOnce");return{track(t){const e=new Set(t);for(const s of t)l.has(s)||l.set(s,{healthy:!0,fails:0,oks:0,lastCheckedAt:null});for(const s of[...l.keys()])e.has(s)||l.delete(s)},isHealthy:n(t=>l.get(t)?.healthy??!0,"isHealthy"),snapshot:n(()=>[...l.entries()].map(([t,e])=>({url:t,healthy:e.healthy,fails:e.fails,lastCheckedAt:e.lastCheckedAt})),"snapshot"),probeOnce:o,start(){r||(r=setInterval(()=>{o()},f),r.unref?.(),o())},stop(){r&&clearInterval(r),r=void 0}}}c(createHealthChecker,"createHealthChecker"),n(createHealthChecker,"createHealthChecker");
@@ -1,121 +1 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createJwksVerifier = createJwksVerifier;
4
- /**
5
- * RS256/JWKS JWT verifier — the production identity source for the prod
6
- * gateway's attribute-based routing (`identify`). Fetches the IdP's JWKS,
7
- * caches public keys by `kid`, and verifies tokens SYNCHRONOUSLY against that
8
- * cache so it slots into the gateway's per-request `identify(req)` and rule
9
- * evaluation without making the hot path async.
10
- *
11
- * Freshness without blocking the request:
12
- * - initial JWKS load is awaited at startup (`refresh()`),
13
- * - a periodic refresh keeps keys current (rotation),
14
- * - an unknown `kid` triggers a rate-limited background refresh and the
15
- * CURRENT request fails closed (undefined) — the token verifies on a later
16
- * request once the new key is cached.
17
- *
18
- * Security: only the configured algorithms are accepted (default RS256) — `none`
19
- * and HS* are rejected (alg-confusion guard); `exp`/`nbf` honoured with a small
20
- * clock tolerance; `iss`/`aud` checked when configured.
21
- *
22
- * Scope: RSA families (RS256/384/512). EC (ES*) needs JOSE→DER signature
23
- * conversion — a documented follow-up; most IdPs default to RS256.
24
- */
25
- const node_crypto_1 = require("node:crypto");
26
- const ALG_TO_HASH = { RS256: 'sha256', RS384: 'sha384', RS512: 'sha512' };
27
- const b64urlJsonSafe = (s) => JSON.parse(Buffer.from(s, 'base64url').toString('utf8'));
28
- function createJwksVerifier(opts) {
29
- const algorithms = (opts.algorithms ?? ['RS256']).filter((a) => a in ALG_TO_HASH);
30
- const cacheMaxAgeMs = opts.cacheMaxAgeMs ?? 600_000;
31
- const missRefreshMs = opts.missRefreshMs ?? 30_000;
32
- const tol = opts.clockToleranceSec ?? 60;
33
- const doFetch = opts.fetchImpl ?? globalThis.fetch;
34
- const audiences = opts.audience === undefined ? undefined : (Array.isArray(opts.audience) ? opts.audience : [opts.audience]);
35
- let keys = new Map(); // kid → public key
36
- let inflight;
37
- let lastMissAt = 0;
38
- const load = async () => {
39
- const res = await doFetch(opts.jwksUrl, { headers: { accept: 'application/json' } });
40
- if (!res.ok)
41
- throw new Error(`JWKS ${opts.jwksUrl} → HTTP ${res.status}`);
42
- const body = (await res.json());
43
- const next = new Map();
44
- for (const jwk of body.keys ?? []) {
45
- if (jwk.kty !== 'RSA' || !jwk.n || !jwk.e)
46
- continue;
47
- if (jwk.use && jwk.use !== 'sig')
48
- continue;
49
- try {
50
- const key = (0, node_crypto_1.createPublicKey)({ key: jwk, format: 'jwk' });
51
- next.set(jwk.kid ?? '__single__', key);
52
- }
53
- catch { /* skip an unparseable key, keep the rest */ }
54
- }
55
- if (next.size > 0)
56
- keys = next; // never blank out a working set on a bad fetch
57
- };
58
- const refresh = () => {
59
- if (!inflight)
60
- inflight = load().finally(() => { inflight = undefined; });
61
- return inflight;
62
- };
63
- const refreshOnMiss = (nowMs) => {
64
- if (nowMs - lastMissAt < missRefreshMs)
65
- return;
66
- lastMissAt = nowMs;
67
- void refresh().catch(() => undefined); // background; this request already failed closed
68
- };
69
- const timer = setInterval(() => void refresh().catch(() => undefined), cacheMaxAgeMs);
70
- timer.unref?.();
71
- const verify = (token) => {
72
- const parts = token.split('.');
73
- if (parts.length !== 3)
74
- return undefined;
75
- let header;
76
- try {
77
- header = b64urlJsonSafe(parts[0]);
78
- }
79
- catch {
80
- return undefined;
81
- }
82
- if (!header.alg || !algorithms.includes(header.alg))
83
- return undefined; // reject none/HS*/unconfigured
84
- const key = keys.get(header.kid ?? '__single__') ?? (keys.size === 1 ? [...keys.values()][0] : undefined);
85
- if (!key) {
86
- refreshOnMiss(Date.now());
87
- return undefined;
88
- }
89
- let ok;
90
- try {
91
- ok = (0, node_crypto_1.verify)(ALG_TO_HASH[header.alg], Buffer.from(`${parts[0]}.${parts[1]}`), key, Buffer.from(parts[2], 'base64url'));
92
- }
93
- catch {
94
- return undefined;
95
- }
96
- if (!ok)
97
- return undefined;
98
- let payload;
99
- try {
100
- payload = b64urlJsonSafe(parts[1]);
101
- }
102
- catch {
103
- return undefined;
104
- }
105
- const now = Date.now() / 1000;
106
- if (typeof payload.exp === 'number' && now > payload.exp + tol)
107
- return undefined;
108
- if (typeof payload.nbf === 'number' && now < payload.nbf - tol)
109
- return undefined;
110
- if (opts.issuer && payload.iss !== opts.issuer)
111
- return undefined;
112
- if (audiences) {
113
- const aud = payload.aud;
114
- const audList = Array.isArray(aud) ? aud : [aud];
115
- if (!audList.some((a) => audiences.includes(a)))
116
- return undefined;
117
- }
118
- return payload;
119
- };
120
- return { verify, refresh, stop: () => clearInterval(timer) };
121
- }
1
+ "use strict";var J=Object.defineProperty;var h=(e,n)=>J(e,"name",{value:n,configurable:!0});var v=Object.defineProperty,c=h((e,n)=>v(e,"name",{value:n,configurable:!0}),"c");Object.defineProperty(exports,"__esModule",{value:!0}),exports.createJwksVerifier=createJwksVerifier;const node_crypto_1=require("node:crypto"),ALG_TO_HASH={RS256:"sha256",RS384:"sha384",RS512:"sha512"},b64urlJsonSafe=c(e=>JSON.parse(Buffer.from(e,"base64url").toString("utf8")),"b64urlJsonSafe");function createJwksVerifier(e){const n=(e.algorithms??["RS256"]).filter(r=>r in ALG_TO_HASH),g=e.cacheMaxAgeMs??6e5,k=e.missRefreshMs??3e4,d=e.clockToleranceSec??60,S=e.fetchImpl??globalThis.fetch,p=e.audience===void 0?void 0:Array.isArray(e.audience)?e.audience:[e.audience];let o=new Map,f,w=0;const m=c(async()=>{const r=await S(e.jwksUrl,{headers:{accept:"application/json"}});if(!r.ok)throw new Error(`JWKS ${e.jwksUrl} \u2192 HTTP ${r.status}`);const a=await r.json(),s=new Map;for(const t of a.keys??[])if(!(t.kty!=="RSA"||!t.n||!t.e)&&!(t.use&&t.use!=="sig"))try{const u=(0,node_crypto_1.createPublicKey)({key:t,format:"jwk"});s.set(t.kid??"__single__",u)}catch{}s.size>0&&(o=s)},"load"),l=c(()=>(f||(f=m().finally(()=>{f=void 0})),f),"refresh"),A=c(r=>{r-w<k||(w=r,l().catch(()=>{}))},"refreshOnMiss"),_=setInterval(()=>{l().catch(()=>{})},g);return _.unref?.(),{verify:c(r=>{const a=r.split(".");if(a.length!==3)return;let s;try{s=b64urlJsonSafe(a[0])}catch{return}if(!s.alg||!n.includes(s.alg))return;const t=o.get(s.kid??"__single__")??(o.size===1?[...o.values()][0]:void 0);if(!t){A(Date.now());return}let u;try{u=(0,node_crypto_1.verify)(ALG_TO_HASH[s.alg],Buffer.from(`${a[0]}.${a[1]}`),t,Buffer.from(a[2],"base64url"))}catch{return}if(!u)return;let i;try{i=b64urlJsonSafe(a[1])}catch{return}const b=Date.now()/1e3;if(!(typeof i.exp=="number"&&b>i.exp+d)&&!(typeof i.nbf=="number"&&b<i.nbf-d)&&!(e.issuer&&i.iss!==e.issuer)){if(p){const y=i.aud;if(!(Array.isArray(y)?y:[y]).some(j=>p.includes(j)))return}return i}},"verify"),refresh:l,stop:c(()=>clearInterval(_),"stop")}}h(createJwksVerifier,"createJwksVerifier"),c(createJwksVerifier,"createJwksVerifier");