mcp4openapi 0.1.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/LICENSE.md +7 -0
- package/README.md +489 -0
- package/dist/composite-executor.d.ts +65 -0
- package/dist/composite-executor.d.ts.map +1 -0
- package/dist/composite-executor.js +147 -0
- package/dist/composite-executor.js.map +1 -0
- package/dist/constants.d.ts +36 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +36 -0
- package/dist/constants.js.map +1 -0
- package/dist/http-transport.d.ts +195 -0
- package/dist/http-transport.d.ts.map +1 -0
- package/dist/http-transport.js +760 -0
- package/dist/http-transport.js.map +1 -0
- package/dist/interceptors.d.ts +74 -0
- package/dist/interceptors.d.ts.map +1 -0
- package/dist/interceptors.js +220 -0
- package/dist/interceptors.js.map +1 -0
- package/dist/logger.d.ts +81 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +264 -0
- package/dist/logger.js.map +1 -0
- package/dist/mcp-server.d.ts +110 -0
- package/dist/mcp-server.d.ts.map +1 -0
- package/dist/mcp-server.js +568 -0
- package/dist/mcp-server.js.map +1 -0
- package/dist/metrics.d.ts +86 -0
- package/dist/metrics.d.ts.map +1 -0
- package/dist/metrics.js +229 -0
- package/dist/metrics.js.map +1 -0
- package/dist/openapi-parser.d.ts +35 -0
- package/dist/openapi-parser.d.ts.map +1 -0
- package/dist/openapi-parser.js +160 -0
- package/dist/openapi-parser.js.map +1 -0
- package/dist/profile-loader.d.ts +25 -0
- package/dist/profile-loader.d.ts.map +1 -0
- package/dist/profile-loader.js +134 -0
- package/dist/profile-loader.js.map +1 -0
- package/dist/schema-validator.d.ts +32 -0
- package/dist/schema-validator.d.ts.map +1 -0
- package/dist/schema-validator.js +126 -0
- package/dist/schema-validator.js.map +1 -0
- package/dist/scripts/validate-profile.d.ts +9 -0
- package/dist/scripts/validate-profile.d.ts.map +1 -0
- package/dist/scripts/validate-profile.js +289 -0
- package/dist/scripts/validate-profile.js.map +1 -0
- package/dist/scripts/validate-schema.d.ts +9 -0
- package/dist/scripts/validate-schema.d.ts.map +1 -0
- package/dist/scripts/validate-schema.js +84 -0
- package/dist/scripts/validate-schema.js.map +1 -0
- package/dist/src/composite-executor.d.ts +75 -0
- package/dist/src/composite-executor.d.ts.map +1 -0
- package/dist/src/composite-executor.js +175 -0
- package/dist/src/composite-executor.js.map +1 -0
- package/dist/src/constants.d.ts +36 -0
- package/dist/src/constants.d.ts.map +1 -0
- package/dist/src/constants.js +36 -0
- package/dist/src/constants.js.map +1 -0
- package/dist/src/dag-executor.d.ts +49 -0
- package/dist/src/dag-executor.d.ts.map +1 -0
- package/dist/src/dag-executor.js +138 -0
- package/dist/src/dag-executor.js.map +1 -0
- package/dist/src/errors.d.ts +47 -0
- package/dist/src/errors.d.ts.map +1 -0
- package/dist/src/errors.js +99 -0
- package/dist/src/errors.js.map +1 -0
- package/dist/src/generated-schemas.d.ts +661 -0
- package/dist/src/generated-schemas.d.ts.map +1 -0
- package/dist/src/generated-schemas.js +66 -0
- package/dist/src/generated-schemas.js.map +1 -0
- package/dist/src/http-client-factory.d.ts +62 -0
- package/dist/src/http-client-factory.d.ts.map +1 -0
- package/dist/src/http-client-factory.js +121 -0
- package/dist/src/http-client-factory.js.map +1 -0
- package/dist/src/http-transport.d.ts +194 -0
- package/dist/src/http-transport.d.ts.map +1 -0
- package/dist/src/http-transport.js +851 -0
- package/dist/src/http-transport.js.map +1 -0
- package/dist/src/index.d.ts +8 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +59 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/interceptors.d.ts +78 -0
- package/dist/src/interceptors.d.ts.map +1 -0
- package/dist/src/interceptors.js +252 -0
- package/dist/src/interceptors.js.map +1 -0
- package/dist/src/jsonrpc-validator.d.ts +27 -0
- package/dist/src/jsonrpc-validator.d.ts.map +1 -0
- package/dist/src/jsonrpc-validator.js +58 -0
- package/dist/src/jsonrpc-validator.js.map +1 -0
- package/dist/src/lib.d.ts +8 -0
- package/dist/src/lib.d.ts.map +1 -0
- package/dist/src/lib.js +7 -0
- package/dist/src/lib.js.map +1 -0
- package/dist/src/logger.d.ts +81 -0
- package/dist/src/logger.d.ts.map +1 -0
- package/dist/src/logger.js +264 -0
- package/dist/src/logger.js.map +1 -0
- package/dist/src/mcp-server.d.ts +117 -0
- package/dist/src/mcp-server.d.ts.map +1 -0
- package/dist/src/mcp-server.js +621 -0
- package/dist/src/mcp-server.js.map +1 -0
- package/dist/src/metrics.d.ts +86 -0
- package/dist/src/metrics.d.ts.map +1 -0
- package/dist/src/metrics.js +229 -0
- package/dist/src/metrics.js.map +1 -0
- package/dist/src/naming-warnings.d.ts +23 -0
- package/dist/src/naming-warnings.d.ts.map +1 -0
- package/dist/src/naming-warnings.js +83 -0
- package/dist/src/naming-warnings.js.map +1 -0
- package/dist/src/naming.d.ts +58 -0
- package/dist/src/naming.d.ts.map +1 -0
- package/dist/src/naming.js +510 -0
- package/dist/src/naming.js.map +1 -0
- package/dist/src/openapi-parser.d.ts +49 -0
- package/dist/src/openapi-parser.d.ts.map +1 -0
- package/dist/src/openapi-parser.js +216 -0
- package/dist/src/openapi-parser.js.map +1 -0
- package/dist/src/profile-loader.d.ts +77 -0
- package/dist/src/profile-loader.d.ts.map +1 -0
- package/dist/src/profile-loader.js +443 -0
- package/dist/src/profile-loader.js.map +1 -0
- package/dist/src/schema-validator.d.ts +30 -0
- package/dist/src/schema-validator.d.ts.map +1 -0
- package/dist/src/schema-validator.js +115 -0
- package/dist/src/schema-validator.js.map +1 -0
- package/dist/src/testing/fixtures.d.ts +268 -0
- package/dist/src/testing/fixtures.d.ts.map +1 -0
- package/dist/src/testing/fixtures.js +210 -0
- package/dist/src/testing/fixtures.js.map +1 -0
- package/dist/src/testing/mock-gitlab-server.d.ts +34 -0
- package/dist/src/testing/mock-gitlab-server.d.ts.map +1 -0
- package/dist/src/testing/mock-gitlab-server.js +351 -0
- package/dist/src/testing/mock-gitlab-server.js.map +1 -0
- package/dist/src/testing/mock-utils.d.ts +41 -0
- package/dist/src/testing/mock-utils.d.ts.map +1 -0
- package/dist/src/testing/mock-utils.js +59 -0
- package/dist/src/testing/mock-utils.js.map +1 -0
- package/dist/src/testing/test-http-utils.d.ts +52 -0
- package/dist/src/testing/test-http-utils.d.ts.map +1 -0
- package/dist/src/testing/test-http-utils.js +109 -0
- package/dist/src/testing/test-http-utils.js.map +1 -0
- package/dist/src/testing/test-types.d.ts +76 -0
- package/dist/src/testing/test-types.d.ts.map +1 -0
- package/dist/src/testing/test-types.js +7 -0
- package/dist/src/testing/test-types.js.map +1 -0
- package/dist/src/tool-generator.d.ts +43 -0
- package/dist/src/tool-generator.d.ts.map +1 -0
- package/dist/src/tool-generator.js +123 -0
- package/dist/src/tool-generator.js.map +1 -0
- package/dist/src/types/http-transport.d.ts +45 -0
- package/dist/src/types/http-transport.d.ts.map +1 -0
- package/dist/src/types/http-transport.js +8 -0
- package/dist/src/types/http-transport.js.map +1 -0
- package/dist/src/types/openapi.d.ts +50 -0
- package/dist/src/types/openapi.d.ts.map +1 -0
- package/dist/src/types/openapi.js +9 -0
- package/dist/src/types/openapi.js.map +1 -0
- package/dist/src/types/profile.d.ts +80 -0
- package/dist/src/types/profile.d.ts.map +1 -0
- package/dist/src/types/profile.js +9 -0
- package/dist/src/types/profile.js.map +1 -0
- package/dist/src/validation-utils.d.ts +15 -0
- package/dist/src/validation-utils.d.ts.map +1 -0
- package/dist/src/validation-utils.js +25 -0
- package/dist/src/validation-utils.js.map +1 -0
- package/dist/testing/fixtures.d.ts +186 -0
- package/dist/testing/fixtures.d.ts.map +1 -0
- package/dist/testing/fixtures.js +135 -0
- package/dist/testing/fixtures.js.map +1 -0
- package/dist/testing/http-integration.test.d.ts +7 -0
- package/dist/testing/http-integration.test.d.ts.map +1 -0
- package/dist/testing/http-integration.test.js +383 -0
- package/dist/testing/http-integration.test.js.map +1 -0
- package/dist/testing/http-multiuser.test.d.ts +10 -0
- package/dist/testing/http-multiuser.test.d.ts.map +1 -0
- package/dist/testing/http-multiuser.test.js +255 -0
- package/dist/testing/http-multiuser.test.js.map +1 -0
- package/dist/testing/integration.test.d.ts +8 -0
- package/dist/testing/integration.test.d.ts.map +1 -0
- package/dist/testing/integration.test.js +247 -0
- package/dist/testing/integration.test.js.map +1 -0
- package/dist/testing/mock-gitlab-server.d.ts +34 -0
- package/dist/testing/mock-gitlab-server.d.ts.map +1 -0
- package/dist/testing/mock-gitlab-server.js +224 -0
- package/dist/testing/mock-gitlab-server.js.map +1 -0
- package/dist/testing/test-types.d.ts +59 -0
- package/dist/testing/test-types.d.ts.map +1 -0
- package/dist/testing/test-types.js +7 -0
- package/dist/testing/test-types.js.map +1 -0
- package/dist/tool-generator.d.ts +43 -0
- package/dist/tool-generator.d.ts.map +1 -0
- package/dist/tool-generator.js +123 -0
- package/dist/tool-generator.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/dist/types/http-transport.d.ts +39 -0
- package/dist/types/http-transport.d.ts.map +1 -0
- package/dist/types/http-transport.js +8 -0
- package/dist/types/http-transport.js.map +1 -0
- package/dist/types/openapi.d.ts +50 -0
- package/dist/types/openapi.d.ts.map +1 -0
- package/dist/types/openapi.js +9 -0
- package/dist/types/openapi.js.map +1 -0
- package/dist/types/profile.d.ts +76 -0
- package/dist/types/profile.d.ts.map +1 -0
- package/dist/types/profile.js +9 -0
- package/dist/types/profile.js.map +1 -0
- package/package.json +84 -0
- package/profile-schema.json +369 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../src/metrics.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,QAAQ,EAA6B,MAAM,aAAa,CAAC;AAElE,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,OAAO,CAAU;IAGzB,OAAO,CAAC,iBAAiB,CAAU;IACnC,OAAO,CAAC,mBAAmB,CAAY;IAGvC,OAAO,CAAC,cAAc,CAAQ;IAC9B,OAAO,CAAC,oBAAoB,CAAU;IACtC,OAAO,CAAC,sBAAsB,CAAU;IAGxC,OAAO,CAAC,iBAAiB,CAAU;IACnC,OAAO,CAAC,mBAAmB,CAAY;IACvC,OAAO,CAAC,iBAAiB,CAAU;IAGnC,OAAO,CAAC,aAAa,CAAU;IAC/B,OAAO,CAAC,eAAe,CAAY;IACnC,OAAO,CAAC,aAAa,CAAU;gBAEnB,MAAM,EAAE,sBAAsB;IAwF1C;;OAEG;IACH,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,GAAG,IAAI;IAmB9F;;OAEG;IACH,oBAAoB,IAAI,IAAI;IAM5B;;OAEG;IACH,sBAAsB,IAAI,IAAI;IAM9B;;OAEG;IACH,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,GAAG,OAAO,EAAE,eAAe,EAAE,MAAM,GAAG,IAAI;IAOxF;;OAEG;IACH,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI;IAK1D;;OAEG;IACH,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,GAAG,IAAI;IAS/E;;OAEG;IACH,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI;IAK9D;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC;IAOnC;;OAEG;IACH,WAAW,IAAI,QAAQ;IAIvB;;;;;;;;;OASG;IACH,OAAO,CAAC,aAAa;IAcrB;;;;OAIG;IACH,OAAO,CAAC,cAAc;CAOvB"}
|
package/dist/metrics.js
ADDED
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prometheus Metrics Collector
|
|
3
|
+
*
|
|
4
|
+
* Why: Observability for production deployments
|
|
5
|
+
*
|
|
6
|
+
* Tracks:
|
|
7
|
+
* - HTTP requests (status, method, path)
|
|
8
|
+
* - Session lifecycle (active, created, destroyed)
|
|
9
|
+
* - MCP operations (tool calls, duration, errors)
|
|
10
|
+
* - API calls to backend (operation, status, duration)
|
|
11
|
+
*/
|
|
12
|
+
import { Registry, Counter, Gauge, Histogram } from 'prom-client';
|
|
13
|
+
export class MetricsCollector {
|
|
14
|
+
registry;
|
|
15
|
+
enabled;
|
|
16
|
+
// HTTP metrics
|
|
17
|
+
httpRequestsTotal;
|
|
18
|
+
httpRequestDuration;
|
|
19
|
+
// Session metrics
|
|
20
|
+
sessionsActive;
|
|
21
|
+
sessionsCreatedTotal;
|
|
22
|
+
sessionsDestroyedTotal;
|
|
23
|
+
// MCP operation metrics
|
|
24
|
+
mcpToolCallsTotal;
|
|
25
|
+
mcpToolCallDuration;
|
|
26
|
+
mcpToolCallErrors;
|
|
27
|
+
// API metrics (calls to backend API)
|
|
28
|
+
apiCallsTotal;
|
|
29
|
+
apiCallDuration;
|
|
30
|
+
apiCallErrors;
|
|
31
|
+
constructor(config) {
|
|
32
|
+
this.enabled = config.enabled;
|
|
33
|
+
this.registry = new Registry();
|
|
34
|
+
const prefix = config.prefix || 'mcp_';
|
|
35
|
+
// HTTP metrics
|
|
36
|
+
this.httpRequestsTotal = new Counter({
|
|
37
|
+
name: `${prefix}http_requests_total`,
|
|
38
|
+
help: 'Total number of HTTP requests',
|
|
39
|
+
labelNames: ['method', 'path', 'status'],
|
|
40
|
+
registers: [this.registry],
|
|
41
|
+
});
|
|
42
|
+
this.httpRequestDuration = new Histogram({
|
|
43
|
+
name: `${prefix}http_request_duration_seconds`,
|
|
44
|
+
help: 'HTTP request duration in seconds',
|
|
45
|
+
labelNames: ['method', 'path', 'status'],
|
|
46
|
+
buckets: [0.001, 0.01, 0.05, 0.1, 0.5, 1, 2, 5],
|
|
47
|
+
registers: [this.registry],
|
|
48
|
+
});
|
|
49
|
+
// Session metrics
|
|
50
|
+
this.sessionsActive = new Gauge({
|
|
51
|
+
name: `${prefix}sessions_active`,
|
|
52
|
+
help: 'Number of active sessions',
|
|
53
|
+
registers: [this.registry],
|
|
54
|
+
});
|
|
55
|
+
this.sessionsCreatedTotal = new Counter({
|
|
56
|
+
name: `${prefix}sessions_created_total`,
|
|
57
|
+
help: 'Total number of sessions created',
|
|
58
|
+
registers: [this.registry],
|
|
59
|
+
});
|
|
60
|
+
this.sessionsDestroyedTotal = new Counter({
|
|
61
|
+
name: `${prefix}sessions_destroyed_total`,
|
|
62
|
+
help: 'Total number of sessions destroyed',
|
|
63
|
+
registers: [this.registry],
|
|
64
|
+
});
|
|
65
|
+
// MCP operation metrics
|
|
66
|
+
this.mcpToolCallsTotal = new Counter({
|
|
67
|
+
name: `${prefix}tool_calls_total`,
|
|
68
|
+
help: 'Total number of MCP tool calls',
|
|
69
|
+
labelNames: ['tool', 'status'],
|
|
70
|
+
registers: [this.registry],
|
|
71
|
+
});
|
|
72
|
+
this.mcpToolCallDuration = new Histogram({
|
|
73
|
+
name: `${prefix}tool_call_duration_seconds`,
|
|
74
|
+
help: 'MCP tool call duration in seconds',
|
|
75
|
+
labelNames: ['tool', 'status'],
|
|
76
|
+
buckets: [0.01, 0.05, 0.1, 0.5, 1, 2, 5, 10, 30],
|
|
77
|
+
registers: [this.registry],
|
|
78
|
+
});
|
|
79
|
+
this.mcpToolCallErrors = new Counter({
|
|
80
|
+
name: `${prefix}tool_call_errors_total`,
|
|
81
|
+
help: 'Total number of MCP tool call errors',
|
|
82
|
+
labelNames: ['tool', 'error_type'],
|
|
83
|
+
registers: [this.registry],
|
|
84
|
+
});
|
|
85
|
+
// API metrics
|
|
86
|
+
this.apiCallsTotal = new Counter({
|
|
87
|
+
name: `${prefix}api_calls_total`,
|
|
88
|
+
help: 'Total number of API calls to backend',
|
|
89
|
+
labelNames: ['operation', 'status'],
|
|
90
|
+
registers: [this.registry],
|
|
91
|
+
});
|
|
92
|
+
this.apiCallDuration = new Histogram({
|
|
93
|
+
name: `${prefix}api_call_duration_seconds`,
|
|
94
|
+
help: 'API call duration in seconds',
|
|
95
|
+
labelNames: ['operation', 'status'],
|
|
96
|
+
buckets: [0.01, 0.05, 0.1, 0.5, 1, 2, 5, 10],
|
|
97
|
+
registers: [this.registry],
|
|
98
|
+
});
|
|
99
|
+
this.apiCallErrors = new Counter({
|
|
100
|
+
name: `${prefix}api_call_errors_total`,
|
|
101
|
+
help: 'Total number of API call errors',
|
|
102
|
+
labelNames: ['operation', 'error_type'],
|
|
103
|
+
registers: [this.registry],
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Record HTTP request
|
|
108
|
+
*/
|
|
109
|
+
recordHttpRequest(method, path, status, durationSeconds) {
|
|
110
|
+
if (!this.enabled)
|
|
111
|
+
return;
|
|
112
|
+
this.httpRequestsTotal.inc({
|
|
113
|
+
method,
|
|
114
|
+
path: this.normalizePath(path),
|
|
115
|
+
status: status.toString(),
|
|
116
|
+
});
|
|
117
|
+
this.httpRequestDuration.observe({
|
|
118
|
+
method,
|
|
119
|
+
path: this.normalizePath(path),
|
|
120
|
+
status: status.toString(),
|
|
121
|
+
}, durationSeconds);
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Record session created
|
|
125
|
+
*/
|
|
126
|
+
recordSessionCreated() {
|
|
127
|
+
if (!this.enabled)
|
|
128
|
+
return;
|
|
129
|
+
this.sessionsCreatedTotal.inc();
|
|
130
|
+
this.sessionsActive.inc();
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Record session destroyed
|
|
134
|
+
*/
|
|
135
|
+
recordSessionDestroyed() {
|
|
136
|
+
if (!this.enabled)
|
|
137
|
+
return;
|
|
138
|
+
this.sessionsDestroyedTotal.inc();
|
|
139
|
+
this.sessionsActive.dec();
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Record MCP tool call
|
|
143
|
+
*/
|
|
144
|
+
recordToolCall(tool, status, durationSeconds) {
|
|
145
|
+
if (!this.enabled)
|
|
146
|
+
return;
|
|
147
|
+
this.mcpToolCallsTotal.inc({ tool, status });
|
|
148
|
+
this.mcpToolCallDuration.observe({ tool, status }, durationSeconds);
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Record MCP tool call error
|
|
152
|
+
*/
|
|
153
|
+
recordToolCallError(tool, errorType) {
|
|
154
|
+
if (!this.enabled)
|
|
155
|
+
return;
|
|
156
|
+
this.mcpToolCallErrors.inc({ tool, error_type: errorType });
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Record API call to backend
|
|
160
|
+
*/
|
|
161
|
+
recordApiCall(operation, status, durationSeconds) {
|
|
162
|
+
if (!this.enabled)
|
|
163
|
+
return;
|
|
164
|
+
const statusLabel = this.getStatusLabel(status);
|
|
165
|
+
this.apiCallsTotal.inc({ operation, status: statusLabel });
|
|
166
|
+
this.apiCallDuration.observe({ operation, status: statusLabel }, durationSeconds);
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Record API call error
|
|
170
|
+
*/
|
|
171
|
+
recordApiCallError(operation, errorType) {
|
|
172
|
+
if (!this.enabled)
|
|
173
|
+
return;
|
|
174
|
+
this.apiCallErrors.inc({ operation, error_type: errorType });
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Get metrics in Prometheus format
|
|
178
|
+
*/
|
|
179
|
+
async getMetrics() {
|
|
180
|
+
if (!this.enabled) {
|
|
181
|
+
return '# Metrics disabled\n';
|
|
182
|
+
}
|
|
183
|
+
return this.registry.metrics();
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Get registry (for testing)
|
|
187
|
+
*/
|
|
188
|
+
getRegistry() {
|
|
189
|
+
return this.registry;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Normalize path for metrics (remove dynamic segments)
|
|
193
|
+
*
|
|
194
|
+
* Why: Avoid high cardinality in metrics labels
|
|
195
|
+
*
|
|
196
|
+
* Examples:
|
|
197
|
+
* - /mcp?sessionId=abc123 -> /mcp
|
|
198
|
+
* - /metrics -> /metrics
|
|
199
|
+
* - /health -> /health
|
|
200
|
+
*/
|
|
201
|
+
normalizePath(path) {
|
|
202
|
+
// Remove query string
|
|
203
|
+
const pathWithoutQuery = path.split('?')[0];
|
|
204
|
+
// Known paths
|
|
205
|
+
if (pathWithoutQuery === '/mcp' ||
|
|
206
|
+
pathWithoutQuery === '/metrics' ||
|
|
207
|
+
pathWithoutQuery === '/health') {
|
|
208
|
+
return pathWithoutQuery;
|
|
209
|
+
}
|
|
210
|
+
return pathWithoutQuery;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Get status label (2xx, 4xx, 5xx)
|
|
214
|
+
*
|
|
215
|
+
* Why: Group similar statuses to reduce cardinality
|
|
216
|
+
*/
|
|
217
|
+
getStatusLabel(status) {
|
|
218
|
+
if (status >= 200 && status < 300)
|
|
219
|
+
return '2xx';
|
|
220
|
+
if (status >= 300 && status < 400)
|
|
221
|
+
return '3xx';
|
|
222
|
+
if (status >= 400 && status < 500)
|
|
223
|
+
return '4xx';
|
|
224
|
+
if (status >= 500 && status < 600)
|
|
225
|
+
return '5xx';
|
|
226
|
+
return 'unknown';
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
//# sourceMappingURL=metrics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metrics.js","sourceRoot":"","sources":["../src/metrics.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAPI specification parser and indexer
|
|
3
|
+
*
|
|
4
|
+
* Why indexing: Large OpenAPI specs (GitLab has ~200 operations) need fast lookup.
|
|
5
|
+
* Pre-indexing by operationId and path avoids linear search on every tool call.
|
|
6
|
+
*/
|
|
7
|
+
import type { OperationInfo, PathInfo } from './types/openapi.js';
|
|
8
|
+
export declare class OpenAPIParser {
|
|
9
|
+
private spec?;
|
|
10
|
+
private index?;
|
|
11
|
+
load(specPath: string): Promise<void>;
|
|
12
|
+
/**
|
|
13
|
+
* Build search index from OpenAPI spec
|
|
14
|
+
*
|
|
15
|
+
* Why upfront: Trading startup time for runtime performance. Index creation
|
|
16
|
+
* happens once; lookups happen on every tool call.
|
|
17
|
+
*/
|
|
18
|
+
private buildIndex;
|
|
19
|
+
private extractOperationInfo;
|
|
20
|
+
private extractParameters;
|
|
21
|
+
/**
|
|
22
|
+
* Resolve $ref to parameter definition
|
|
23
|
+
*
|
|
24
|
+
* Why: GitLab spec uses shared parameter definitions (e.g., ProjectIdOrPath).
|
|
25
|
+
* Need to resolve these refs to get actual parameter details.
|
|
26
|
+
*/
|
|
27
|
+
private resolveParameter;
|
|
28
|
+
private extractRequestBody;
|
|
29
|
+
private extractSchema;
|
|
30
|
+
getOperation(operationId: string): OperationInfo | undefined;
|
|
31
|
+
getPath(path: string): PathInfo | undefined;
|
|
32
|
+
getBaseUrl(): string;
|
|
33
|
+
getAllOperations(): OperationInfo[];
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=openapi-parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openapi-parser.d.ts","sourceRoot":"","sources":["../src/openapi-parser.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAgB,aAAa,EAAiB,QAAQ,EAA+B,MAAM,oBAAoB,CAAC;AAE5H,qBAAa,aAAa;IACxB,OAAO,CAAC,IAAI,CAAC,CAAqB;IAClC,OAAO,CAAC,KAAK,CAAC,CAAe;IAEvB,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAa3C;;;;;OAKG;IACH,OAAO,CAAC,UAAU;IAkClB,OAAO,CAAC,oBAAoB;IAiB5B,OAAO,CAAC,iBAAiB;IAqBzB;;;;;OAKG;IACH,OAAO,CAAC,gBAAgB;IAaxB,OAAO,CAAC,kBAAkB;IAoB1B,OAAO,CAAC,aAAa;IA0BrB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;IAI5D,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS;IAI3C,UAAU,IAAI,MAAM;IAKpB,gBAAgB,IAAI,aAAa,EAAE;CAGpC"}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAPI specification parser and indexer
|
|
3
|
+
*
|
|
4
|
+
* Why indexing: Large OpenAPI specs (GitLab has ~200 operations) need fast lookup.
|
|
5
|
+
* Pre-indexing by operationId and path avoids linear search on every tool call.
|
|
6
|
+
*/
|
|
7
|
+
import fs from 'fs/promises';
|
|
8
|
+
import { parse as parseYaml } from 'yaml';
|
|
9
|
+
export class OpenAPIParser {
|
|
10
|
+
spec;
|
|
11
|
+
index;
|
|
12
|
+
async load(specPath) {
|
|
13
|
+
const content = await fs.readFile(specPath, 'utf-8');
|
|
14
|
+
// Parse YAML or JSON based on extension
|
|
15
|
+
if (specPath.endsWith('.yaml') || specPath.endsWith('.yml')) {
|
|
16
|
+
this.spec = parseYaml(content);
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
this.spec = JSON.parse(content);
|
|
20
|
+
}
|
|
21
|
+
this.buildIndex();
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Build search index from OpenAPI spec
|
|
25
|
+
*
|
|
26
|
+
* Why upfront: Trading startup time for runtime performance. Index creation
|
|
27
|
+
* happens once; lookups happen on every tool call.
|
|
28
|
+
*/
|
|
29
|
+
buildIndex() {
|
|
30
|
+
if (!this.spec)
|
|
31
|
+
throw new Error('Spec not loaded');
|
|
32
|
+
const operations = new Map();
|
|
33
|
+
const paths = new Map();
|
|
34
|
+
for (const [path, pathItem] of Object.entries(this.spec.paths || {})) {
|
|
35
|
+
if (!pathItem)
|
|
36
|
+
continue;
|
|
37
|
+
const pathOperations = {};
|
|
38
|
+
for (const method of ['get', 'post', 'put', 'patch', 'delete', 'head', 'options']) {
|
|
39
|
+
const operation = pathItem[method];
|
|
40
|
+
if (!operation)
|
|
41
|
+
continue;
|
|
42
|
+
const operationInfo = this.extractOperationInfo(path, method, operation);
|
|
43
|
+
if (operationInfo.operationId) {
|
|
44
|
+
operations.set(operationInfo.operationId, operationInfo);
|
|
45
|
+
}
|
|
46
|
+
pathOperations[method] = operationInfo;
|
|
47
|
+
}
|
|
48
|
+
paths.set(path, { path, operations: pathOperations });
|
|
49
|
+
}
|
|
50
|
+
this.index = {
|
|
51
|
+
spec: this.spec,
|
|
52
|
+
operations,
|
|
53
|
+
paths,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
extractOperationInfo(path, method, operation) {
|
|
57
|
+
return {
|
|
58
|
+
operationId: operation.operationId || `${method}_${path}`,
|
|
59
|
+
method: method.toUpperCase(),
|
|
60
|
+
path,
|
|
61
|
+
summary: operation.summary,
|
|
62
|
+
description: operation.description,
|
|
63
|
+
parameters: this.extractParameters(operation),
|
|
64
|
+
requestBody: this.extractRequestBody(operation),
|
|
65
|
+
tags: operation.tags,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
extractParameters(operation) {
|
|
69
|
+
if (!operation.parameters)
|
|
70
|
+
return [];
|
|
71
|
+
return operation.parameters
|
|
72
|
+
.map(p => {
|
|
73
|
+
// Resolve $ref to parameter definition
|
|
74
|
+
if ('$ref' in p) {
|
|
75
|
+
return this.resolveParameter(p.$ref);
|
|
76
|
+
}
|
|
77
|
+
return p;
|
|
78
|
+
})
|
|
79
|
+
.filter((p) => p !== null)
|
|
80
|
+
.map(param => ({
|
|
81
|
+
name: param.name,
|
|
82
|
+
in: param.in,
|
|
83
|
+
required: param.required ?? false,
|
|
84
|
+
schema: this.extractSchema(param.schema),
|
|
85
|
+
description: param.description,
|
|
86
|
+
}));
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Resolve $ref to parameter definition
|
|
90
|
+
*
|
|
91
|
+
* Why: GitLab spec uses shared parameter definitions (e.g., ProjectIdOrPath).
|
|
92
|
+
* Need to resolve these refs to get actual parameter details.
|
|
93
|
+
*/
|
|
94
|
+
resolveParameter(ref) {
|
|
95
|
+
if (!this.spec)
|
|
96
|
+
return null;
|
|
97
|
+
// Extract ref path: #/components/parameters/ProjectIdOrPath => ProjectIdOrPath
|
|
98
|
+
const refName = ref.split('/').pop();
|
|
99
|
+
if (!refName)
|
|
100
|
+
return null;
|
|
101
|
+
const param = this.spec.components?.parameters?.[refName];
|
|
102
|
+
if (!param || '$ref' in param)
|
|
103
|
+
return null;
|
|
104
|
+
return param;
|
|
105
|
+
}
|
|
106
|
+
extractRequestBody(operation) {
|
|
107
|
+
if (!operation.requestBody || '$ref' in operation.requestBody)
|
|
108
|
+
return undefined;
|
|
109
|
+
const body = operation.requestBody;
|
|
110
|
+
const content = {};
|
|
111
|
+
for (const [mediaType, mediaTypeObj] of Object.entries(body.content || {})) {
|
|
112
|
+
if (mediaTypeObj.schema) {
|
|
113
|
+
content[mediaType] = {
|
|
114
|
+
schema: this.extractSchema(mediaTypeObj.schema),
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return {
|
|
119
|
+
required: body.required ?? false,
|
|
120
|
+
content,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
extractSchema(schema) {
|
|
124
|
+
if (!schema)
|
|
125
|
+
return {};
|
|
126
|
+
if ('$ref' in schema)
|
|
127
|
+
return { type: 'object' }; // Simplified: don't resolve refs
|
|
128
|
+
const result = {
|
|
129
|
+
type: schema.type,
|
|
130
|
+
format: schema.format,
|
|
131
|
+
enum: schema.enum,
|
|
132
|
+
default: schema.default,
|
|
133
|
+
};
|
|
134
|
+
if (schema.type === 'array' && schema.items && !('$ref' in schema.items)) {
|
|
135
|
+
result.items = this.extractSchema(schema.items);
|
|
136
|
+
}
|
|
137
|
+
if (schema.type === 'object' && schema.properties) {
|
|
138
|
+
result.properties = {};
|
|
139
|
+
for (const [key, propSchema] of Object.entries(schema.properties)) {
|
|
140
|
+
result.properties[key] = this.extractSchema(propSchema);
|
|
141
|
+
}
|
|
142
|
+
result.required = schema.required;
|
|
143
|
+
}
|
|
144
|
+
return result;
|
|
145
|
+
}
|
|
146
|
+
getOperation(operationId) {
|
|
147
|
+
return this.index?.operations.get(operationId);
|
|
148
|
+
}
|
|
149
|
+
getPath(path) {
|
|
150
|
+
return this.index?.paths.get(path);
|
|
151
|
+
}
|
|
152
|
+
getBaseUrl() {
|
|
153
|
+
const servers = this.spec?.servers;
|
|
154
|
+
return servers?.[0]?.url || '';
|
|
155
|
+
}
|
|
156
|
+
getAllOperations() {
|
|
157
|
+
return Array.from(this.index?.operations.values() || []);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
//# sourceMappingURL=openapi-parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openapi-parser.js","sourceRoot":"","sources":["../src/openapi-parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Profile configuration loader and validator
|
|
3
|
+
*
|
|
4
|
+
* Why validation: Profile config comes from user files. Invalid config would
|
|
5
|
+
* cause runtime errors. Validate upfront with clear error messages.
|
|
6
|
+
*/
|
|
7
|
+
import type { Profile } from './types/profile.js';
|
|
8
|
+
export declare class ProfileLoader {
|
|
9
|
+
load(profilePath: string): Promise<Profile>;
|
|
10
|
+
/**
|
|
11
|
+
* Validate semantic rules beyond schema
|
|
12
|
+
*
|
|
13
|
+
* Why separate: Some rules can't be expressed in JSON Schema (e.g.,
|
|
14
|
+
* "if composite=true then steps must exist"). Fail fast with clear messages.
|
|
15
|
+
*/
|
|
16
|
+
private validateLogic;
|
|
17
|
+
/**
|
|
18
|
+
* Create a minimal default profile from OpenAPI spec
|
|
19
|
+
*
|
|
20
|
+
* Why: Allows running server without profile for quick exploration.
|
|
21
|
+
* Generates simple pass-through tools for all operations.
|
|
22
|
+
*/
|
|
23
|
+
static createDefaultProfile(profileName: string): Profile;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=profile-loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profile-loader.d.ts","sourceRoot":"","sources":["../src/profile-loader.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAoFlD,qBAAa,aAAa;IAClB,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAYjD;;;;;OAKG;IACH,OAAO,CAAC,aAAa;IAsCrB;;;;;OAKG;IACH,MAAM,CAAC,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO;CAQ1D"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Profile configuration loader and validator
|
|
3
|
+
*
|
|
4
|
+
* Why validation: Profile config comes from user files. Invalid config would
|
|
5
|
+
* cause runtime errors. Validate upfront with clear error messages.
|
|
6
|
+
*/
|
|
7
|
+
import fs from 'fs/promises';
|
|
8
|
+
import { z } from 'zod';
|
|
9
|
+
// Zod schemas for runtime validation
|
|
10
|
+
const ParameterDefSchema = z.object({
|
|
11
|
+
type: z.enum(['string', 'integer', 'number', 'boolean', 'array', 'object']),
|
|
12
|
+
description: z.string(),
|
|
13
|
+
required: z.boolean().optional(),
|
|
14
|
+
required_for: z.array(z.string()).optional(),
|
|
15
|
+
enum: z.array(z.string()).optional(),
|
|
16
|
+
items: z.object({ type: z.string() }).optional(),
|
|
17
|
+
default: z.unknown().optional(),
|
|
18
|
+
example: z.unknown().optional(),
|
|
19
|
+
});
|
|
20
|
+
const ArrayFormatSchema = z.enum(['brackets', 'indices', 'repeat', 'comma']);
|
|
21
|
+
const CompositeStepSchema = z.object({
|
|
22
|
+
call: z.string(),
|
|
23
|
+
store_as: z.string(),
|
|
24
|
+
});
|
|
25
|
+
const ToolDefSchema = z.object({
|
|
26
|
+
name: z.string(),
|
|
27
|
+
description: z.string(),
|
|
28
|
+
operations: z.record(z.string()).optional(),
|
|
29
|
+
composite: z.boolean().optional(),
|
|
30
|
+
steps: z.array(CompositeStepSchema).optional(),
|
|
31
|
+
partial_results: z.boolean().optional(),
|
|
32
|
+
parameters: z.record(ParameterDefSchema),
|
|
33
|
+
metadata_params: z.array(z.string()).optional(),
|
|
34
|
+
response_fields: z.record(z.array(z.string())).optional(),
|
|
35
|
+
});
|
|
36
|
+
const AuthInterceptorSchema = z.object({
|
|
37
|
+
type: z.enum(['bearer', 'query', 'custom-header']),
|
|
38
|
+
header_name: z.string().optional(),
|
|
39
|
+
query_param: z.string().optional(),
|
|
40
|
+
value_from_env: z.string(),
|
|
41
|
+
}).refine((data) => {
|
|
42
|
+
if (data.type === 'query' && !data.query_param) {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
if (data.type === 'custom-header' && !data.header_name) {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
return true;
|
|
49
|
+
}, {
|
|
50
|
+
message: 'query type requires query_param, custom-header requires header_name',
|
|
51
|
+
});
|
|
52
|
+
const BaseUrlConfigSchema = z.object({
|
|
53
|
+
value_from_env: z.string(),
|
|
54
|
+
default: z.string().optional(),
|
|
55
|
+
});
|
|
56
|
+
const RateLimitConfigSchema = z.object({
|
|
57
|
+
max_requests_per_minute: z.number().positive(),
|
|
58
|
+
});
|
|
59
|
+
const RetryConfigSchema = z.object({
|
|
60
|
+
max_attempts: z.number().int().positive(),
|
|
61
|
+
backoff_ms: z.array(z.number().positive()),
|
|
62
|
+
retry_on_status: z.array(z.number().int()),
|
|
63
|
+
});
|
|
64
|
+
const InterceptorConfigSchema = z.object({
|
|
65
|
+
auth: AuthInterceptorSchema.optional(),
|
|
66
|
+
base_url: BaseUrlConfigSchema.optional(),
|
|
67
|
+
rate_limit: RateLimitConfigSchema.optional(),
|
|
68
|
+
retry: RetryConfigSchema.optional(),
|
|
69
|
+
array_format: ArrayFormatSchema.optional(),
|
|
70
|
+
});
|
|
71
|
+
const ProfileSchema = z.object({
|
|
72
|
+
profile_name: z.string(),
|
|
73
|
+
description: z.string().optional(),
|
|
74
|
+
tools: z.array(ToolDefSchema),
|
|
75
|
+
interceptors: InterceptorConfigSchema.optional(),
|
|
76
|
+
parameter_aliases: z.record(z.array(z.string())).optional(),
|
|
77
|
+
});
|
|
78
|
+
export class ProfileLoader {
|
|
79
|
+
async load(profilePath) {
|
|
80
|
+
const content = await fs.readFile(profilePath, 'utf-8');
|
|
81
|
+
const json = JSON.parse(content);
|
|
82
|
+
// Validate with Zod - throws detailed error if invalid
|
|
83
|
+
const profile = ProfileSchema.parse(json);
|
|
84
|
+
this.validateLogic(profile);
|
|
85
|
+
return profile;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Validate semantic rules beyond schema
|
|
89
|
+
*
|
|
90
|
+
* Why separate: Some rules can't be expressed in JSON Schema (e.g.,
|
|
91
|
+
* "if composite=true then steps must exist"). Fail fast with clear messages.
|
|
92
|
+
*/
|
|
93
|
+
validateLogic(profile) {
|
|
94
|
+
for (const tool of profile.tools) {
|
|
95
|
+
// Composite tools must have steps
|
|
96
|
+
if (tool.composite && (!tool.steps || tool.steps.length === 0)) {
|
|
97
|
+
throw new Error(`Tool '${tool.name}' is marked as composite but has no steps`);
|
|
98
|
+
}
|
|
99
|
+
// Non-composite tools must have operations
|
|
100
|
+
if (!tool.composite && !tool.operations) {
|
|
101
|
+
throw new Error(`Tool '${tool.name}' must have either 'operations' or be marked as 'composite' with 'steps'`);
|
|
102
|
+
}
|
|
103
|
+
// Validate required_for references existing enum values
|
|
104
|
+
for (const [paramName, paramDef] of Object.entries(tool.parameters)) {
|
|
105
|
+
if (paramDef.required_for) {
|
|
106
|
+
const actionParam = tool.parameters['action'];
|
|
107
|
+
if (!actionParam?.enum) {
|
|
108
|
+
throw new Error(`Parameter '${paramName}' in tool '${tool.name}' has 'required_for' but 'action' parameter has no enum`);
|
|
109
|
+
}
|
|
110
|
+
for (const action of paramDef.required_for) {
|
|
111
|
+
if (!actionParam.enum.includes(action)) {
|
|
112
|
+
throw new Error(`Parameter '${paramName}' requires action '${action}' but it's not in action enum: ${actionParam.enum.join(', ')}`);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Create a minimal default profile from OpenAPI spec
|
|
121
|
+
*
|
|
122
|
+
* Why: Allows running server without profile for quick exploration.
|
|
123
|
+
* Generates simple pass-through tools for all operations.
|
|
124
|
+
*/
|
|
125
|
+
static createDefaultProfile(profileName) {
|
|
126
|
+
return {
|
|
127
|
+
profile_name: profileName,
|
|
128
|
+
description: 'Auto-generated default profile',
|
|
129
|
+
tools: [],
|
|
130
|
+
interceptors: {},
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=profile-loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profile-loader.js","sourceRoot":"","sources":["../src/profile-loader.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,MAAM,aAAa,CAAC;AAC7B,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,qCAAqC;AACrC,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IAClC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;IAC3E,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE;IACvB,QAAQ,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IAChC,YAAY,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;IAC5C,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;IACpC,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,QAAQ,EAAE;IAChD,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IAC/B,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;CAChC,CAAC,CAAC;AAEH,MAAM,iBAAiB,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;AAE7E,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC;IACnC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;IAChB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;CACrB,CAAC,CAAC;AAEH,MAAM,aAAa,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7B,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;IAChB,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE;IACvB,UAAU,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;IAC3C,SAAS,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IACjC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC,QAAQ,EAAE;IAC9C,eAAe,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IACvC,UAAU,EAAE,CAAC,CAAC,MAAM,CAAC,kBAAkB,CAAC;IACxC,eAAe,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;IAC/C,eAAe,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE;CAC1D,CAAC,CAAC;AAEH,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC;IACrC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,OAAO,EAAE,eAAe,CAAC,CAAC;IAClD,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAClC,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAClC,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE;CAC3B,CAAC,CAAC,MAAM,CACP,CAAC,IAAI,EAAE,EAAE;IACP,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;QAC/C,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,IAAI,CAAC,IAAI,KAAK,eAAe,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;QACvD,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC,EACD;IACE,OAAO,EAAE,qEAAqE;CAC/E,CACF,CAAC;AAEF,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC;IACnC,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE;IAC1B,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAC/B,CAAC,CAAC;AAEH,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC;IACrC,uBAAuB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAC/C,CAAC,CAAC;AAEH,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACjC,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IACzC,UAAU,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC;IAC1C,eAAe,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC;CAC3C,CAAC,CAAC;AAEH,MAAM,uBAAuB,GAAG,CAAC,CAAC,MAAM,CAAC;IACvC,IAAI,EAAE,qBAAqB,CAAC,QAAQ,EAAE;IACtC,QAAQ,EAAE,mBAAmB,CAAC,QAAQ,EAAE;IACxC,UAAU,EAAE,qBAAqB,CAAC,QAAQ,EAAE;IAC5C,KAAK,EAAE,iBAAiB,CAAC,QAAQ,EAAE;IACnC,YAAY,EAAE,iBAAiB,CAAC,QAAQ,EAAE;CAC3C,CAAC,CAAC;AAEH,MAAM,aAAa,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7B,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE;IACxB,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAClC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC;IAC7B,YAAY,EAAE,uBAAuB,CAAC,QAAQ,EAAE;IAChD,iBAAiB,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE;CAC5D,CAAC,CAAC;AAEH,MAAM,OAAO,aAAa;IACxB,KAAK,CAAC,IAAI,CAAC,WAAmB;QAC5B,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QACxD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAEjC,uDAAuD;QACvD,MAAM,OAAO,GAAG,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAE1C,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;QAE5B,OAAO,OAAO,CAAC;IACjB,CAAC;IAED;;;;;OAKG;IACK,aAAa,CAAC,OAAgB;QACpC,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;YACjC,kCAAkC;YAClC,IAAI,IAAI,CAAC,SAAS,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,EAAE,CAAC;gBAC/D,MAAM,IAAI,KAAK,CACb,SAAS,IAAI,CAAC,IAAI,2CAA2C,CAC9D,CAAC;YACJ,CAAC;YAED,2CAA2C;YAC3C,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;gBACxC,MAAM,IAAI,KAAK,CACb,SAAS,IAAI,CAAC,IAAI,0EAA0E,CAC7F,CAAC;YACJ,CAAC;YAED,wDAAwD;YACxD,KAAK,MAAM,CAAC,SAAS,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;gBACpE,IAAI,QAAQ,CAAC,YAAY,EAAE,CAAC;oBAC1B,MAAM,WAAW,GAAG,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;oBAC9C,IAAI,CAAC,WAAW,EAAE,IAAI,EAAE,CAAC;wBACvB,MAAM,IAAI,KAAK,CACb,cAAc,SAAS,cAAc,IAAI,CAAC,IAAI,yDAAyD,CACxG,CAAC;oBACJ,CAAC;oBAED,KAAK,MAAM,MAAM,IAAI,QAAQ,CAAC,YAAY,EAAE,CAAC;wBAC3C,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;4BACvC,MAAM,IAAI,KAAK,CACb,cAAc,SAAS,sBAAsB,MAAM,kCAAkC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACnH,CAAC;wBACJ,CAAC;oBACH,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED;;;;;OAKG;IACH,MAAM,CAAC,oBAAoB,CAAC,WAAmB;QAC7C,OAAO;YACL,YAAY,EAAE,WAAW;YACzB,WAAW,EAAE,gCAAgC;YAC7C,KAAK,EAAE,EAAE;YACT,YAAY,EAAE,EAAE;SACjB,CAAC;IACJ,CAAC;CACF"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Request body schema validator
|
|
3
|
+
*
|
|
4
|
+
* Why: Catch invalid requests before sending to API. Better error messages for users.
|
|
5
|
+
* Validates against OpenAPI schema definitions.
|
|
6
|
+
*/
|
|
7
|
+
import type { SchemaInfo, OperationInfo } from './types/openapi.js';
|
|
8
|
+
export interface ValidationResult {
|
|
9
|
+
valid: boolean;
|
|
10
|
+
errors?: ValidationError[];
|
|
11
|
+
}
|
|
12
|
+
export interface ValidationError {
|
|
13
|
+
path: string;
|
|
14
|
+
message: string;
|
|
15
|
+
schema: SchemaInfo;
|
|
16
|
+
value: unknown;
|
|
17
|
+
}
|
|
18
|
+
export declare class SchemaValidator {
|
|
19
|
+
/**
|
|
20
|
+
* Validate request body against OpenAPI schema
|
|
21
|
+
*
|
|
22
|
+
* Why: Prevents sending malformed requests. OpenAPI schema is the source of truth.
|
|
23
|
+
*/
|
|
24
|
+
validateRequestBody(operation: OperationInfo, body: Record<string, unknown>): ValidationResult;
|
|
25
|
+
/**
|
|
26
|
+
* Recursively validate data against schema
|
|
27
|
+
*/
|
|
28
|
+
private validateAgainstSchema;
|
|
29
|
+
private isEmail;
|
|
30
|
+
private isUri;
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=schema-validator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema-validator.d.ts","sourceRoot":"","sources":["../src/schema-validator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEpE,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,eAAe,EAAE,CAAC;CAC5B;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,UAAU,CAAC;IACnB,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,qBAAa,eAAe;IAC1B;;;;OAIG;IACH,mBAAmB,CACjB,SAAS,EAAE,aAAa,EACxB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,gBAAgB;IAgBnB;;OAEG;IACH,OAAO,CAAC,qBAAqB;IA4G7B,OAAO,CAAC,OAAO;IAIf,OAAO,CAAC,KAAK;CAQd"}
|