Skip to content

Commit 2988339

Browse files
committed
feat: integrate Spectral for OpenAPI validation
- Added Spectral dependencies to package.json for linting OpenAPI specifications. - Created a new ruleset (adr-ruleset.yaml) to define custom validation rules. - Implemented OasValidatorService to handle OpenAPI validation logic. - Updated ToolsService to utilize OasValidatorService for validating OpenAPI specifications in requests.
1 parent 8e4edb5 commit 2988339

7 files changed

Lines changed: 1309 additions & 116 deletions

File tree

controllers/Controller.js

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,37 @@ class Controller {
101101
return 'body';
102102
}
103103

104+
static aliasRequestBodyParam(params, bodyName, value) {
105+
if (!bodyName || value === undefined) {
106+
return params;
107+
}
108+
const result = { ...params };
109+
if (!Object.prototype.hasOwnProperty.call(result, bodyName)) {
110+
result[bodyName] = value;
111+
}
112+
if (!Object.prototype.hasOwnProperty.call(result, 'body')) {
113+
result.body = value;
114+
}
115+
const sanitizedName = Service.sanitizeOperationId(bodyName);
116+
if (sanitizedName && !Object.prototype.hasOwnProperty.call(result, sanitizedName)) {
117+
result[sanitizedName] = value;
118+
}
119+
const lowerCaseName = bodyName.charAt(0).toLowerCase() + bodyName.slice(1);
120+
if (lowerCaseName && !Object.prototype.hasOwnProperty.call(result, lowerCaseName)) {
121+
result[lowerCaseName] = value;
122+
}
123+
if (value && typeof value === 'object' && !Array.isArray(value)) {
124+
Object.keys(value).forEach((key) => {
125+
if (!Object.prototype.hasOwnProperty.call(result, key)) {
126+
result[key] = value[key];
127+
}
128+
});
129+
}
130+
return result;
131+
}
132+
104133
static collectRequestParams(request) {
105-
const requestParams = {};
134+
let requestParams = {};
106135
if (request.openapi.schema.requestBody !== null) {
107136
const { content } = request.openapi.schema.requestBody;
108137
if (content['application/json'] !== undefined) {
@@ -118,8 +147,9 @@ class Controller {
118147
const requiredProperties = Array.isArray(schemaDefinition.required)
119148
? schemaDefinition.required
120149
: [];
150+
const payload = request.body || {};
121151
if (requiredProperties.length > 0) {
122-
const missing = requiredProperties.filter((prop) => request.body[prop] === undefined);
152+
const missing = requiredProperties.filter((prop) => payload[prop] === undefined);
123153
if (missing.length > 0) {
124154
throw Service.rejectResponse({
125155
message: `Missing required properties: ${missing.join(', ')}`,
@@ -138,7 +168,7 @@ class Controller {
138168
return false;
139169
})();
140170
if (!allowAdditional) {
141-
const unknownProperties = Object.keys(request.body || {}).filter((prop) => !declaredProperties.includes(prop));
171+
const unknownProperties = Object.keys(payload).filter((prop) => !declaredProperties.includes(prop));
142172
if (unknownProperties.length > 0) {
143173
throw Service.rejectResponse({
144174
message: `Unknown properties: ${unknownProperties.join(', ')}`,
@@ -147,7 +177,12 @@ class Controller {
147177
}, 400);
148178
}
149179
}
150-
requestParams[requestBodyName] = request.body;
180+
if (Object.keys(payload).length > 0) {
181+
requestParams = Controller.aliasRequestBodyParam({
182+
...requestParams,
183+
[requestBodyName]: payload,
184+
}, requestBodyName, payload);
185+
}
151186
} else if (content['multipart/form-data'] !== undefined) {
152187
Object.keys(content['multipart/form-data'].schema.properties).forEach(
153188
(property) => {

expressServer.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// const { Middleware } = require('swagger-express-middleware');
12
const http = require('node:http');
23
const fs = require('node:fs');
34
const path = require('node:path');

0 commit comments

Comments
 (0)