@open-rlb/nestjs-amqp 2.1.0 → 2.2.0
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/package.json +6 -5
- package/schematics/add-auth-provider/index.d.ts +3 -0
- package/schematics/add-auth-provider/index.js +60 -0
- package/schematics/add-auth-provider/index.js.map +1 -0
- package/schematics/add-auth-provider/index.spec.ts +83 -0
- package/schematics/add-auth-provider/index.ts +83 -0
- package/schematics/add-auth-provider/schema.d.ts +18 -0
- package/schematics/add-auth-provider/schema.js +3 -0
- package/schematics/add-auth-provider/schema.js.map +1 -0
- package/schematics/add-auth-provider/schema.json +59 -0
- package/schematics/add-auth-provider/schema.ts +35 -0
- package/schematics/add-exchange/index.d.ts +3 -0
- package/schematics/add-exchange/index.js +49 -0
- package/schematics/add-exchange/index.js.map +1 -0
- package/schematics/add-exchange/index.spec.ts +65 -0
- package/schematics/add-exchange/index.ts +65 -0
- package/schematics/add-exchange/schema.d.ts +14 -0
- package/schematics/add-exchange/schema.js +3 -0
- package/schematics/add-exchange/schema.js.map +1 -0
- package/schematics/add-exchange/schema.json +50 -0
- package/schematics/add-exchange/schema.ts +26 -0
- package/schematics/add-exchange-binding/index.d.ts +3 -0
- package/schematics/add-exchange-binding/index.js +53 -0
- package/schematics/add-exchange-binding/index.js.map +1 -0
- package/schematics/add-exchange-binding/index.spec.ts +73 -0
- package/schematics/add-exchange-binding/index.ts +64 -0
- package/schematics/add-exchange-binding/schema.d.ts +8 -0
- package/schematics/add-exchange-binding/schema.js +3 -0
- package/schematics/add-exchange-binding/schema.js.map +1 -0
- package/schematics/add-exchange-binding/schema.json +36 -0
- package/schematics/add-exchange-binding/schema.ts +14 -0
- package/schematics/add-gateway/index.d.ts +4 -0
- package/schematics/add-gateway/index.js +105 -0
- package/schematics/add-gateway/index.js.map +1 -0
- package/schematics/add-gateway/index.spec.ts +163 -0
- package/schematics/add-gateway/index.ts +141 -0
- package/schematics/add-gateway/paths.d.ts +12 -0
- package/schematics/add-gateway/paths.js +87 -0
- package/schematics/add-gateway/paths.js.map +1 -0
- package/schematics/add-gateway/paths.ts +103 -0
- package/schematics/add-gateway/schema.d.ts +13 -0
- package/schematics/add-gateway/schema.js +3 -0
- package/schematics/add-gateway/schema.js.map +1 -0
- package/schematics/add-gateway/schema.json +63 -0
- package/schematics/add-gateway/schema.ts +24 -0
- package/schematics/add-gateway/wiring.d.ts +14 -0
- package/schematics/add-gateway/wiring.js +102 -0
- package/schematics/add-gateway/wiring.js.map +1 -0
- package/schematics/add-gateway/wiring.ts +115 -0
- package/schematics/add-metrics-topic/index.d.ts +3 -0
- package/schematics/add-metrics-topic/index.js +31 -0
- package/schematics/add-metrics-topic/index.js.map +1 -0
- package/schematics/add-metrics-topic/index.spec.ts +79 -0
- package/schematics/add-metrics-topic/index.ts +49 -0
- package/schematics/add-metrics-topic/schema.d.ts +10 -0
- package/schematics/add-metrics-topic/schema.js +3 -0
- package/schematics/add-metrics-topic/schema.js.map +1 -0
- package/schematics/add-metrics-topic/schema.json +48 -0
- package/schematics/add-metrics-topic/schema.ts +18 -0
- package/schematics/add-queue/index.d.ts +3 -0
- package/schematics/add-queue/index.js +48 -0
- package/schematics/add-queue/index.js.map +1 -0
- package/schematics/add-queue/index.spec.ts +75 -0
- package/schematics/add-queue/index.ts +74 -0
- package/schematics/add-queue/schema.d.ts +17 -0
- package/schematics/add-queue/schema.js +3 -0
- package/schematics/add-queue/schema.js.map +1 -0
- package/schematics/add-queue/schema.json +54 -0
- package/schematics/add-queue/schema.ts +32 -0
- package/schematics/add-reply-queue/index.d.ts +3 -0
- package/schematics/add-reply-queue/index.js +26 -0
- package/schematics/add-reply-queue/index.js.map +1 -0
- package/schematics/add-reply-queue/index.spec.ts +69 -0
- package/schematics/add-reply-queue/index.ts +33 -0
- package/schematics/add-reply-queue/schema.d.ts +6 -0
- package/schematics/add-reply-queue/schema.js +3 -0
- package/schematics/add-reply-queue/schema.js.map +1 -0
- package/schematics/add-reply-queue/schema.json +28 -0
- package/schematics/add-reply-queue/schema.ts +10 -0
- package/schematics/add-route/index.d.ts +3 -0
- package/schematics/add-route/index.js +57 -0
- package/schematics/add-route/index.js.map +1 -0
- package/schematics/add-route/index.spec.ts +75 -0
- package/schematics/add-route/index.ts +74 -0
- package/schematics/add-route/schema.d.ts +22 -0
- package/schematics/add-route/schema.js +3 -0
- package/schematics/add-route/schema.js.map +1 -0
- package/schematics/add-route/schema.json +74 -0
- package/schematics/add-route/schema.ts +43 -0
- package/schematics/add-topic/index.d.ts +3 -0
- package/schematics/add-topic/index.js +69 -0
- package/schematics/add-topic/index.js.map +1 -0
- package/schematics/add-topic/index.spec.ts +100 -0
- package/schematics/add-topic/index.ts +104 -0
- package/schematics/add-topic/schema.d.ts +18 -0
- package/schematics/add-topic/schema.js +3 -0
- package/schematics/add-topic/schema.js.map +1 -0
- package/schematics/add-topic/schema.json +63 -0
- package/schematics/add-topic/schema.ts +34 -0
- package/schematics/add-ws-event/index.d.ts +3 -0
- package/schematics/add-ws-event/index.js +53 -0
- package/schematics/add-ws-event/index.js.map +1 -0
- package/schematics/add-ws-event/index.spec.ts +85 -0
- package/schematics/add-ws-event/index.ts +72 -0
- package/schematics/add-ws-event/schema.d.ts +17 -0
- package/schematics/add-ws-event/schema.js +3 -0
- package/schematics/add-ws-event/schema.js.map +1 -0
- package/schematics/add-ws-event/schema.json +53 -0
- package/schematics/add-ws-event/schema.ts +33 -0
- package/schematics/collection.json +81 -1
- package/schematics/configure-broker/index.d.ts +3 -0
- package/schematics/configure-broker/index.js +41 -0
- package/schematics/configure-broker/index.js.map +1 -0
- package/schematics/configure-broker/index.spec.ts +62 -0
- package/schematics/configure-broker/index.ts +51 -0
- package/schematics/configure-broker/schema.d.ts +11 -0
- package/schematics/configure-broker/schema.js +3 -0
- package/schematics/configure-broker/schema.js.map +1 -0
- package/schematics/configure-broker/schema.json +47 -0
- package/schematics/configure-broker/schema.ts +20 -0
- package/schematics/enable-load-config/index.d.ts +3 -0
- package/schematics/enable-load-config/index.js +32 -0
- package/schematics/enable-load-config/index.js.map +1 -0
- package/schematics/enable-load-config/index.spec.ts +61 -0
- package/schematics/enable-load-config/index.ts +39 -0
- package/schematics/enable-load-config/schema.d.ts +8 -0
- package/schematics/enable-load-config/schema.js +3 -0
- package/schematics/enable-load-config/schema.js.map +1 -0
- package/schematics/enable-load-config/schema.json +36 -0
- package/schematics/enable-load-config/schema.ts +14 -0
- package/schematics/enable-retry/index.d.ts +3 -0
- package/schematics/enable-retry/index.js +51 -0
- package/schematics/enable-retry/index.js.map +1 -0
- package/schematics/enable-retry/index.spec.ts +73 -0
- package/schematics/enable-retry/index.ts +62 -0
- package/schematics/enable-retry/schema.d.ts +13 -0
- package/schematics/enable-retry/schema.js +3 -0
- package/schematics/enable-retry/schema.js.map +1 -0
- package/schematics/enable-retry/schema.json +64 -0
- package/schematics/enable-retry/schema.ts +24 -0
- package/schematics/enable-route-discovery/index.d.ts +3 -0
- package/schematics/enable-route-discovery/index.js +36 -0
- package/schematics/enable-route-discovery/index.js.map +1 -0
- package/schematics/enable-route-discovery/index.spec.ts +55 -0
- package/schematics/enable-route-discovery/index.ts +48 -0
- package/schematics/enable-route-discovery/schema.d.ts +9 -0
- package/schematics/enable-route-discovery/schema.js +3 -0
- package/schematics/enable-route-discovery/schema.js.map +1 -0
- package/schematics/enable-route-discovery/schema.json +44 -0
- package/schematics/enable-route-discovery/schema.ts +16 -0
- package/schematics/harden-gateway/index.d.ts +3 -0
- package/schematics/harden-gateway/index.js +93 -0
- package/schematics/harden-gateway/index.js.map +1 -0
- package/schematics/harden-gateway/index.spec.ts +105 -0
- package/schematics/harden-gateway/index.ts +108 -0
- package/schematics/harden-gateway/schema.d.ts +11 -0
- package/schematics/harden-gateway/schema.js +3 -0
- package/schematics/harden-gateway/schema.js.map +1 -0
- package/schematics/harden-gateway/schema.json +47 -0
- package/schematics/harden-gateway/schema.ts +20 -0
- package/schematics/nest-add/index.js +55 -832
- package/schematics/nest-add/index.js.map +1 -1
- package/schematics/nest-add/index.spec.ts +73 -0
- package/schematics/nest-add/index.ts +76 -917
- package/schematics/nest-add/init.schema.d.ts +1 -0
- package/schematics/nest-add/init.schema.ts +3 -0
- package/schematics/nest-add/schema.json +4 -43
- package/schematics/set-connection-name/index.d.ts +3 -0
- package/schematics/set-connection-name/index.js +34 -0
- package/schematics/set-connection-name/index.js.map +1 -0
- package/schematics/set-connection-name/index.spec.ts +48 -0
- package/schematics/set-connection-name/index.ts +42 -0
- package/schematics/set-connection-name/schema.d.ts +5 -0
- package/schematics/set-connection-name/schema.js +3 -0
- package/schematics/set-connection-name/schema.js.map +1 -0
- package/schematics/set-connection-name/schema.json +24 -0
- package/schematics/set-connection-name/schema.ts +8 -0
- package/schematics/utils/broker-yaml.util.d.ts +53 -0
- package/schematics/utils/broker-yaml.util.js +91 -0
- package/schematics/utils/broker-yaml.util.js.map +1 -0
- package/schematics/utils/broker-yaml.util.ts +172 -0
- package/schematics/utils/nest-wiring.util.d.ts +30 -0
- package/schematics/utils/nest-wiring.util.js +170 -0
- package/schematics/utils/nest-wiring.util.js.map +1 -0
- package/schematics/utils/nest-wiring.util.ts +211 -0
- package/schematics/utils/schematic-prompt.util.d.ts +7 -0
- package/schematics/utils/schematic-prompt.util.js +57 -0
- package/schematics/utils/schematic-prompt.util.js.map +1 -0
- package/schematics/utils/schematic-prompt.util.ts +82 -0
- package/schematics/utils/yaml-config.util.d.ts +22 -0
- package/schematics/utils/yaml-config.util.js +119 -0
- package/schematics/utils/yaml-config.util.js.map +1 -0
- package/schematics/utils/yaml-config.util.ts +167 -0
- /package/schematics/{nest-add → add-gateway}/files/acl/src/cache/in-memory-acl-store.ts +0 -0
- /package/schematics/{nest-add → add-gateway}/files/acl/src/modules/database/repository/acl.repository.ts +0 -0
- /package/schematics/{nest-add → add-gateway}/files/db-core/src/modules/database/repository/in-memory-collection.ts +0 -0
- /package/schematics/{nest-add → add-gateway}/files/gateway-admin/src/modules/database/repository/gateway.repository.ts +0 -0
- /package/schematics/{nest-add → add-gateway}/files/gateway-admin/src/modules/database/repository/route-sync.repository.ts +0 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface EnableRouteDiscoveryOptions {
|
|
2
|
+
/** Logical service name published for auto-discovery. Prompted when omitted; kebab/snake-normalized. */
|
|
3
|
+
serviceName?: string;
|
|
4
|
+
/** Discovery exchange (fanout). Default: 'rlb-route-discovery'. */
|
|
5
|
+
exchange?: string;
|
|
6
|
+
/** Queue the gateway syncs from. Default: 'rlb-route-sync'. */
|
|
7
|
+
queue?: string;
|
|
8
|
+
/** Publish the route manifest on boot. Default: true. */
|
|
9
|
+
publishOnBoot?: boolean;
|
|
10
|
+
/** Also declare the discovery exchange in broker.exchanges. Default: true. */
|
|
11
|
+
declareExchange?: boolean;
|
|
12
|
+
/** Update broker.routeDiscovery when it already exists (default: leave it untouched). */
|
|
13
|
+
overwrite?: boolean;
|
|
14
|
+
/** Path to config.yaml (default: auto-detected, typically config/config.yaml). */
|
|
15
|
+
config?: string;
|
|
16
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.main = main;
|
|
4
|
+
const yaml_config_util_1 = require("../utils/yaml-config.util");
|
|
5
|
+
function main(options) {
|
|
6
|
+
return async (tree, context) => {
|
|
7
|
+
const configPath = (0, yaml_config_util_1.findConfigYaml)(tree, options.config);
|
|
8
|
+
const { doc, existed } = (0, yaml_config_util_1.readConfigDoc)(tree, configPath);
|
|
9
|
+
if (!existed)
|
|
10
|
+
context.logger.info(`[rlb-amqp] ${configPath} not found — creating it.`);
|
|
11
|
+
const set = (path, value, label) => {
|
|
12
|
+
const outcome = (0, yaml_config_util_1.setIn)(doc, path, value);
|
|
13
|
+
const verb = outcome === 'created' ? 'set' : outcome === 'updated' ? 'updated' : 'unchanged';
|
|
14
|
+
context.logger.info(`[rlb-amqp] ${label}: ${verb}.`);
|
|
15
|
+
};
|
|
16
|
+
if (options.maxConcurrentRequests !== undefined)
|
|
17
|
+
set(['gateway', 'maxConcurrentRequests'], options.maxConcurrentRequests, 'gateway.maxConcurrentRequests');
|
|
18
|
+
if (options.maxBodyBytes !== undefined)
|
|
19
|
+
set(['gateway', 'maxBodyBytes'], options.maxBodyBytes, 'gateway.maxBodyBytes');
|
|
20
|
+
if (options.uploadMaxFileSizeMb !== undefined)
|
|
21
|
+
set(['gateway', 'upload', 'maxFileSizeMb'], options.uploadMaxFileSizeMb, 'gateway.upload.maxFileSizeMb');
|
|
22
|
+
if (options.uploadMaxFiles !== undefined)
|
|
23
|
+
set(['gateway', 'upload', 'maxFiles'], options.uploadMaxFiles, 'gateway.upload.maxFiles');
|
|
24
|
+
if (options.wsMaxBufferedBytes !== undefined)
|
|
25
|
+
set(['gateway', 'ws', 'maxBufferedBytes'], options.wsMaxBufferedBytes, 'gateway.ws.maxBufferedBytes');
|
|
26
|
+
if (options.wsMaxMessageBytes !== undefined)
|
|
27
|
+
set(['gateway', 'ws', 'maxMessageBytes'], options.wsMaxMessageBytes, 'gateway.ws.maxMessageBytes');
|
|
28
|
+
if (options.allowedOrigins !== undefined)
|
|
29
|
+
set(['gateway', 'ws', 'allowedOrigins'], options.allowedOrigins, 'gateway.ws.allowedOrigins');
|
|
30
|
+
(0, yaml_config_util_1.writeConfigDoc)(tree, configPath, doc);
|
|
31
|
+
const patchMain = options.patchMain ?? true;
|
|
32
|
+
if (options.maxBodyBytes !== undefined && patchMain) {
|
|
33
|
+
patchMainTs(tree, context);
|
|
34
|
+
}
|
|
35
|
+
return tree;
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
function patchMainTs(tree, context) {
|
|
39
|
+
const candidatePaths = ['/src/main.ts', '/app/main.ts', 'src/main.ts', 'app/main.ts'];
|
|
40
|
+
const mainPath = candidatePaths.find((p) => tree.exists(p)) || findFileInTree(tree, 'main.ts');
|
|
41
|
+
if (!mainPath) {
|
|
42
|
+
context.logger.warn('[rlb-amqp] main.ts not found: add the useBodyParser(maxBodyBytes) wiring manually.');
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
let content = tree.read(mainPath).toString('utf-8');
|
|
46
|
+
if (content.includes('useBodyParser')) {
|
|
47
|
+
context.logger.info('[rlb-amqp] main.ts already calls useBodyParser — left unchanged.');
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
let importAdds = '';
|
|
51
|
+
if (!content.includes('ConfigService'))
|
|
52
|
+
importAdds += "\nimport { ConfigService } from '@nestjs/config';";
|
|
53
|
+
if (!content.includes('GatewayConfig'))
|
|
54
|
+
importAdds += "\nimport { GatewayConfig } from '@open-rlb/nestjs-amqp';";
|
|
55
|
+
if (importAdds) {
|
|
56
|
+
const pos = findLastImportEndIndex(content);
|
|
57
|
+
content = content.slice(0, pos) + importAdds + content.slice(pos);
|
|
58
|
+
}
|
|
59
|
+
const m = content.match(/const\s+(\w+)\s*=\s*await\s+NestFactory\.create(?:<[^>]*>)?\(\s*[A-Za-z0-9_]+\s*(?:,\s*\{[^}]*\})?\s*\)\s*;?/);
|
|
60
|
+
if (!m) {
|
|
61
|
+
context.logger.warn('[rlb-amqp] NestFactory.create() not found in main.ts: add the useBodyParser wiring manually (YAML changes kept).');
|
|
62
|
+
tree.overwrite(mainPath, content);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
const app = m[1];
|
|
66
|
+
const block = `\n\n const gateway = ${app}.get(ConfigService).get<GatewayConfig>('gateway');\n` +
|
|
67
|
+
` if (gateway?.maxBodyBytes) {\n` +
|
|
68
|
+
` ${app}.useBodyParser('json', { limit: gateway.maxBodyBytes });\n` +
|
|
69
|
+
` ${app}.useBodyParser('urlencoded', { extended: true, limit: gateway.maxBodyBytes });\n` +
|
|
70
|
+
` }`;
|
|
71
|
+
const insertAt = m.index + m[0].length;
|
|
72
|
+
content = content.slice(0, insertAt) + block + content.slice(insertAt);
|
|
73
|
+
tree.overwrite(mainPath, content);
|
|
74
|
+
context.logger.info('[rlb-amqp] main.ts: body-parser limit wiring added.');
|
|
75
|
+
}
|
|
76
|
+
function findLastImportEndIndex(source) {
|
|
77
|
+
const importRegex = /^import\s+.+from\s+['"][^'"]+['"];?\s*$/gm;
|
|
78
|
+
let lastEnd = 0;
|
|
79
|
+
let match;
|
|
80
|
+
while ((match = importRegex.exec(source)) !== null) {
|
|
81
|
+
lastEnd = match.index + match[0].length;
|
|
82
|
+
}
|
|
83
|
+
return lastEnd;
|
|
84
|
+
}
|
|
85
|
+
function findFileInTree(tree, fileName) {
|
|
86
|
+
let found;
|
|
87
|
+
tree.visit((path) => {
|
|
88
|
+
if (!found && path.endsWith(`/${fileName}`))
|
|
89
|
+
found = path;
|
|
90
|
+
});
|
|
91
|
+
return found;
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../libs/rlb-nestjs-amqp/src/schematics/harden-gateway/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { Rule, SchematicContext, Tree } from '@angular-devkit/schematics';
|
|
2
|
+
import { parseDocument } from 'yaml';
|
|
3
|
+
import { main } from './index';
|
|
4
|
+
import { HardenGatewayOptions } from './schema';
|
|
5
|
+
|
|
6
|
+
/** Factory invoked directly against a Tree (not SchematicTestRunner — ESM `ora`). */
|
|
7
|
+
const ctx = { logger: { info() {}, warn() {}, error() {} } } as unknown as SchematicContext;
|
|
8
|
+
|
|
9
|
+
async function run(options: HardenGatewayOptions, tree: Tree): Promise<Tree> {
|
|
10
|
+
const rule = main(options) as Rule;
|
|
11
|
+
const result = await (rule as (t: Tree, c: SchematicContext) => Promise<Tree>)(tree, ctx);
|
|
12
|
+
return result || tree;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function read(tree: Tree, path = 'config/config.yaml'): string {
|
|
16
|
+
return tree.read(path)!.toString('utf-8');
|
|
17
|
+
}
|
|
18
|
+
function doc(tree: Tree) {
|
|
19
|
+
return parseDocument(read(tree));
|
|
20
|
+
}
|
|
21
|
+
function seedConfig(): Tree {
|
|
22
|
+
const tree = Tree.empty();
|
|
23
|
+
tree.create('config/config.yaml', ['# my config', 'gateway:', ' paths: []', ''].join('\n'));
|
|
24
|
+
return tree;
|
|
25
|
+
}
|
|
26
|
+
const MAIN_TS = [
|
|
27
|
+
"import { NestFactory } from '@nestjs/core';",
|
|
28
|
+
"import { AppModule } from './app.module';",
|
|
29
|
+
'',
|
|
30
|
+
'async function bootstrap() {',
|
|
31
|
+
' const app = await NestFactory.create(AppModule, { rawBody: true });',
|
|
32
|
+
' await app.listen(3000);',
|
|
33
|
+
'}',
|
|
34
|
+
'bootstrap();',
|
|
35
|
+
'',
|
|
36
|
+
].join('\n');
|
|
37
|
+
|
|
38
|
+
describe('harden-gateway schematic', () => {
|
|
39
|
+
it('sets only the provided limits at the right paths', async () => {
|
|
40
|
+
const tree = await run(
|
|
41
|
+
{
|
|
42
|
+
maxConcurrentRequests: 100,
|
|
43
|
+
maxBodyBytes: '5mb',
|
|
44
|
+
uploadMaxFileSizeMb: 10,
|
|
45
|
+
uploadMaxFiles: 3,
|
|
46
|
+
wsMaxBufferedBytes: 1048576,
|
|
47
|
+
wsMaxMessageBytes: 65536,
|
|
48
|
+
allowedOrigins: ['https://a.example', 'https://b.example'],
|
|
49
|
+
patchMain: false,
|
|
50
|
+
},
|
|
51
|
+
seedConfig(),
|
|
52
|
+
);
|
|
53
|
+
const d = doc(tree);
|
|
54
|
+
expect(Number(d.getIn(['gateway', 'maxConcurrentRequests']))).toBe(100);
|
|
55
|
+
expect(String(d.getIn(['gateway', 'maxBodyBytes']))).toBe('5mb');
|
|
56
|
+
expect(Number(d.getIn(['gateway', 'upload', 'maxFileSizeMb']))).toBe(10);
|
|
57
|
+
expect(Number(d.getIn(['gateway', 'upload', 'maxFiles']))).toBe(3);
|
|
58
|
+
expect(Number(d.getIn(['gateway', 'ws', 'maxBufferedBytes']))).toBe(1048576);
|
|
59
|
+
expect(Number(d.getIn(['gateway', 'ws', 'maxMessageBytes']))).toBe(65536);
|
|
60
|
+
const origins = (d.getIn(['gateway', 'ws', 'allowedOrigins']) as any).items.map((i: any) => String(i));
|
|
61
|
+
expect(origins).toEqual(['https://a.example', 'https://b.example']);
|
|
62
|
+
expect(read(tree)).toContain('# my config');
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('leaves unrelated keys absent when their option is not passed', async () => {
|
|
66
|
+
const tree = await run({ maxConcurrentRequests: 50, patchMain: false }, seedConfig());
|
|
67
|
+
const d = doc(tree);
|
|
68
|
+
expect(d.hasIn(['gateway', 'maxBodyBytes'])).toBe(false);
|
|
69
|
+
expect(d.hasIn(['gateway', 'upload'])).toBe(false);
|
|
70
|
+
expect(d.hasIn(['gateway', 'ws'])).toBe(false);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it('patches main.ts once and is idempotent on re-run', async () => {
|
|
74
|
+
const tree = seedConfig();
|
|
75
|
+
tree.create('src/main.ts', MAIN_TS);
|
|
76
|
+
|
|
77
|
+
await run({ maxBodyBytes: '5mb' }, tree);
|
|
78
|
+
let mainContent = tree.read('src/main.ts')!.toString('utf-8');
|
|
79
|
+
expect((mainContent.match(/useBodyParser\('json'/g) || []).length).toBe(1);
|
|
80
|
+
expect(mainContent).toContain("import { ConfigService } from '@nestjs/config';");
|
|
81
|
+
expect(mainContent).toContain("import { GatewayConfig } from '@open-rlb/nestjs-amqp';");
|
|
82
|
+
expect(mainContent).toContain("const gateway = app.get(ConfigService).get<GatewayConfig>('gateway');");
|
|
83
|
+
// The injected block follows the create statement.
|
|
84
|
+
expect(mainContent.indexOf('NestFactory.create')).toBeLessThan(mainContent.indexOf('useBodyParser'));
|
|
85
|
+
|
|
86
|
+
// Re-run: no duplication.
|
|
87
|
+
await run({ maxBodyBytes: '5mb' }, tree);
|
|
88
|
+
mainContent = tree.read('src/main.ts')!.toString('utf-8');
|
|
89
|
+
expect((mainContent.match(/useBodyParser\('json'/g) || []).length).toBe(1);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('does not touch main.ts when patchMain is false', async () => {
|
|
93
|
+
const tree = seedConfig();
|
|
94
|
+
tree.create('src/main.ts', MAIN_TS);
|
|
95
|
+
await run({ maxBodyBytes: '5mb', patchMain: false }, tree);
|
|
96
|
+
expect(tree.read('src/main.ts')!.toString('utf-8')).not.toContain('useBodyParser');
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it('does not patch main.ts when maxBodyBytes is not provided', async () => {
|
|
100
|
+
const tree = seedConfig();
|
|
101
|
+
tree.create('src/main.ts', MAIN_TS);
|
|
102
|
+
await run({ maxConcurrentRequests: 10 }, tree);
|
|
103
|
+
expect(tree.read('src/main.ts')!.toString('utf-8')).not.toContain('useBodyParser');
|
|
104
|
+
});
|
|
105
|
+
});
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { Rule, SchematicContext, Tree } from '@angular-devkit/schematics';
|
|
2
|
+
import { findConfigYaml, readConfigDoc, setIn, writeConfigDoc } from '../utils/yaml-config.util';
|
|
3
|
+
import { HardenGatewayOptions } from './schema';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* `harden-gateway` — set the gateway growth/DoS limits in config.yaml (only the options you pass)
|
|
7
|
+
* and, when `maxBodyBytes` is provided, patch main.ts to re-register the JSON/urlencoded body
|
|
8
|
+
* parsers with that limit (the framework default is ~100kb). Both halves are idempotent.
|
|
9
|
+
*/
|
|
10
|
+
export function main(options: HardenGatewayOptions): Rule {
|
|
11
|
+
return async (tree: Tree, context: SchematicContext) => {
|
|
12
|
+
const configPath = findConfigYaml(tree, options.config);
|
|
13
|
+
const { doc, existed } = readConfigDoc(tree, configPath);
|
|
14
|
+
if (!existed) context.logger.info(`[rlb-amqp] ${configPath} not found — creating it.`);
|
|
15
|
+
|
|
16
|
+
// YAML: set ONLY the limits actually supplied (leave everything else untouched).
|
|
17
|
+
const set = (path: (string | number)[], value: unknown, label: string) => {
|
|
18
|
+
const outcome = setIn(doc, path, value);
|
|
19
|
+
const verb = outcome === 'created' ? 'set' : outcome === 'updated' ? 'updated' : 'unchanged';
|
|
20
|
+
context.logger.info(`[rlb-amqp] ${label}: ${verb}.`);
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
if (options.maxConcurrentRequests !== undefined) set(['gateway', 'maxConcurrentRequests'], options.maxConcurrentRequests, 'gateway.maxConcurrentRequests');
|
|
24
|
+
if (options.maxBodyBytes !== undefined) set(['gateway', 'maxBodyBytes'], options.maxBodyBytes, 'gateway.maxBodyBytes');
|
|
25
|
+
if (options.uploadMaxFileSizeMb !== undefined) set(['gateway', 'upload', 'maxFileSizeMb'], options.uploadMaxFileSizeMb, 'gateway.upload.maxFileSizeMb');
|
|
26
|
+
if (options.uploadMaxFiles !== undefined) set(['gateway', 'upload', 'maxFiles'], options.uploadMaxFiles, 'gateway.upload.maxFiles');
|
|
27
|
+
if (options.wsMaxBufferedBytes !== undefined) set(['gateway', 'ws', 'maxBufferedBytes'], options.wsMaxBufferedBytes, 'gateway.ws.maxBufferedBytes');
|
|
28
|
+
if (options.wsMaxMessageBytes !== undefined) set(['gateway', 'ws', 'maxMessageBytes'], options.wsMaxMessageBytes, 'gateway.ws.maxMessageBytes');
|
|
29
|
+
if (options.allowedOrigins !== undefined) set(['gateway', 'ws', 'allowedOrigins'], options.allowedOrigins, 'gateway.ws.allowedOrigins');
|
|
30
|
+
|
|
31
|
+
writeConfigDoc(tree, configPath, doc);
|
|
32
|
+
|
|
33
|
+
// main.ts body-parser patch — only when a body limit is configured AND patching is enabled.
|
|
34
|
+
const patchMain = options.patchMain ?? true;
|
|
35
|
+
if (options.maxBodyBytes !== undefined && patchMain) {
|
|
36
|
+
patchMainTs(tree, context);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return tree;
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** Re-register the JSON/urlencoded body parsers with gateway.maxBodyBytes. Idempotent + no-op when unfindable. */
|
|
44
|
+
function patchMainTs(tree: Tree, context: SchematicContext): void {
|
|
45
|
+
const candidatePaths = ['/src/main.ts', '/app/main.ts', 'src/main.ts', 'app/main.ts'];
|
|
46
|
+
const mainPath = candidatePaths.find((p) => tree.exists(p)) || findFileInTree(tree, 'main.ts');
|
|
47
|
+
if (!mainPath) {
|
|
48
|
+
context.logger.warn('[rlb-amqp] main.ts not found: add the useBodyParser(maxBodyBytes) wiring manually.');
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
let content = tree.read(mainPath)!.toString('utf-8');
|
|
53
|
+
if (content.includes('useBodyParser')) {
|
|
54
|
+
context.logger.info('[rlb-amqp] main.ts already calls useBodyParser — left unchanged.');
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Insert the imports the injected block needs (if missing).
|
|
59
|
+
let importAdds = '';
|
|
60
|
+
if (!content.includes('ConfigService')) importAdds += "\nimport { ConfigService } from '@nestjs/config';";
|
|
61
|
+
if (!content.includes('GatewayConfig')) importAdds += "\nimport { GatewayConfig } from '@open-rlb/nestjs-amqp';";
|
|
62
|
+
if (importAdds) {
|
|
63
|
+
const pos = findLastImportEndIndex(content);
|
|
64
|
+
content = content.slice(0, pos) + importAdds + content.slice(pos);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const m = content.match(
|
|
68
|
+
/const\s+(\w+)\s*=\s*await\s+NestFactory\.create(?:<[^>]*>)?\(\s*[A-Za-z0-9_]+\s*(?:,\s*\{[^}]*\})?\s*\)\s*;?/,
|
|
69
|
+
);
|
|
70
|
+
if (!m) {
|
|
71
|
+
context.logger.warn('[rlb-amqp] NestFactory.create() not found in main.ts: add the useBodyParser wiring manually (YAML changes kept).');
|
|
72
|
+
tree.overwrite(mainPath, content);
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const app = m[1];
|
|
77
|
+
const block =
|
|
78
|
+
`\n\n const gateway = ${app}.get(ConfigService).get<GatewayConfig>('gateway');\n` +
|
|
79
|
+
` if (gateway?.maxBodyBytes) {\n` +
|
|
80
|
+
` ${app}.useBodyParser('json', { limit: gateway.maxBodyBytes });\n` +
|
|
81
|
+
` ${app}.useBodyParser('urlencoded', { extended: true, limit: gateway.maxBodyBytes });\n` +
|
|
82
|
+
` }`;
|
|
83
|
+
const insertAt = m.index! + m[0].length;
|
|
84
|
+
content = content.slice(0, insertAt) + block + content.slice(insertAt);
|
|
85
|
+
|
|
86
|
+
tree.overwrite(mainPath, content);
|
|
87
|
+
context.logger.info('[rlb-amqp] main.ts: body-parser limit wiring added.');
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** Local copy (do not import from nest-add): first import-statement end offset. */
|
|
91
|
+
function findLastImportEndIndex(source: string): number {
|
|
92
|
+
const importRegex = /^import\s+.+from\s+['"][^'"]+['"];?\s*$/gm;
|
|
93
|
+
let lastEnd = 0;
|
|
94
|
+
let match: RegExpExecArray | null;
|
|
95
|
+
while ((match = importRegex.exec(source)) !== null) {
|
|
96
|
+
lastEnd = match.index + match[0].length;
|
|
97
|
+
}
|
|
98
|
+
return lastEnd;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/** Local copy (do not import from nest-add): first file whose path ends with `/<fileName>`. */
|
|
102
|
+
function findFileInTree(tree: Tree, fileName: string): string | undefined {
|
|
103
|
+
let found: string | undefined;
|
|
104
|
+
tree.visit((path) => {
|
|
105
|
+
if (!found && path.endsWith(`/${fileName}`)) found = path;
|
|
106
|
+
});
|
|
107
|
+
return found;
|
|
108
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface HardenGatewayOptions {
|
|
2
|
+
maxConcurrentRequests?: number;
|
|
3
|
+
maxBodyBytes?: string | number;
|
|
4
|
+
uploadMaxFileSizeMb?: number;
|
|
5
|
+
uploadMaxFiles?: number;
|
|
6
|
+
wsMaxBufferedBytes?: number;
|
|
7
|
+
wsMaxMessageBytes?: number;
|
|
8
|
+
allowedOrigins?: string[];
|
|
9
|
+
patchMain?: boolean;
|
|
10
|
+
config?: string;
|
|
11
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../libs/rlb-nestjs-amqp/src/schematics/harden-gateway/schema.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/schema",
|
|
3
|
+
"$id": "SchematicsRlbAmqpHardenGateway",
|
|
4
|
+
"title": "Add gateway hardening limits (config.yaml + optional main.ts body-parser patch)",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"properties": {
|
|
7
|
+
"maxConcurrentRequests": {
|
|
8
|
+
"type": "number",
|
|
9
|
+
"description": "gateway.maxConcurrentRequests — global in-flight request cap."
|
|
10
|
+
},
|
|
11
|
+
"maxBodyBytes": {
|
|
12
|
+
"type": ["string", "number"],
|
|
13
|
+
"description": "gateway.maxBodyBytes — non-multipart body limit (e.g. '5mb'). Also drives the main.ts patch."
|
|
14
|
+
},
|
|
15
|
+
"uploadMaxFileSizeMb": {
|
|
16
|
+
"type": "number",
|
|
17
|
+
"description": "gateway.upload.maxFileSizeMb — per-file multipart limit."
|
|
18
|
+
},
|
|
19
|
+
"uploadMaxFiles": {
|
|
20
|
+
"type": "number",
|
|
21
|
+
"description": "gateway.upload.maxFiles — max files per multipart request."
|
|
22
|
+
},
|
|
23
|
+
"wsMaxBufferedBytes": {
|
|
24
|
+
"type": "number",
|
|
25
|
+
"description": "gateway.ws.maxBufferedBytes — per-socket outbound backpressure cap."
|
|
26
|
+
},
|
|
27
|
+
"wsMaxMessageBytes": {
|
|
28
|
+
"type": "number",
|
|
29
|
+
"description": "gateway.ws.maxMessageBytes — inbound WS frame limit."
|
|
30
|
+
},
|
|
31
|
+
"allowedOrigins": {
|
|
32
|
+
"type": "array",
|
|
33
|
+
"items": { "type": "string" },
|
|
34
|
+
"description": "gateway.ws.allowedOrigins — CORS allow-list for the WS upgrade."
|
|
35
|
+
},
|
|
36
|
+
"patchMain": {
|
|
37
|
+
"type": "boolean",
|
|
38
|
+
"default": true,
|
|
39
|
+
"description": "Also patch main.ts to re-register the body parsers with maxBodyBytes."
|
|
40
|
+
},
|
|
41
|
+
"config": {
|
|
42
|
+
"type": "string",
|
|
43
|
+
"description": "Path to config.yaml (default: auto-detected)."
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
"required": []
|
|
47
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface HardenGatewayOptions {
|
|
2
|
+
/** gateway.maxConcurrentRequests — global in-flight request cap. */
|
|
3
|
+
maxConcurrentRequests?: number;
|
|
4
|
+
/** gateway.maxBodyBytes — non-multipart body limit (e.g. '5mb'). Also drives the main.ts patch. */
|
|
5
|
+
maxBodyBytes?: string | number;
|
|
6
|
+
/** gateway.upload.maxFileSizeMb — per-file multipart limit. */
|
|
7
|
+
uploadMaxFileSizeMb?: number;
|
|
8
|
+
/** gateway.upload.maxFiles — max files per multipart request. */
|
|
9
|
+
uploadMaxFiles?: number;
|
|
10
|
+
/** gateway.ws.maxBufferedBytes — per-socket outbound backpressure cap. */
|
|
11
|
+
wsMaxBufferedBytes?: number;
|
|
12
|
+
/** gateway.ws.maxMessageBytes — inbound WS frame limit. */
|
|
13
|
+
wsMaxMessageBytes?: number;
|
|
14
|
+
/** gateway.ws.allowedOrigins — CORS allow-list for the WS upgrade. */
|
|
15
|
+
allowedOrigins?: string[];
|
|
16
|
+
/** Also patch main.ts to re-register the body parsers with maxBodyBytes. Default: true. */
|
|
17
|
+
patchMain?: boolean;
|
|
18
|
+
/** Path to config.yaml (default: auto-detected, typically config/config.yaml). */
|
|
19
|
+
config?: string;
|
|
20
|
+
}
|