UNPKG

ephelan-spectral-ruleset

Version:
109 lines 4.57 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const json_schema_resolve_allof_1 = __importDefault(require("json-schema-resolve-allof")); const errorProperties = { type: 'object', properties: { code: { type: 'string', required: true }, id: { type: 'string', required: true }, kind: { type: 'string', required: true }, href: { type: 'string', required: true }, reason: { type: 'string', required: true } } }; // Recursively compare the target value of the OpenAPI document with an expected value exports.default = (targetVal, _, paths) => __awaiter(void 0, void 0, void 0, function* () { const rootPath = paths.target !== void 0 ? paths.target : paths.given; const resolvedTargetVal = json_schema_resolve_allof_1.default(JSON.parse(JSON.stringify(targetVal))); const results = []; const methods = ['get', 'post', 'put', 'patch', 'delete']; for (const [endpointPath, pathConfig] of Object.entries(resolvedTargetVal)) { for (const m of methods) { const pathMethod = pathConfig[m]; if (!pathMethod) { continue; } for (const [code, responseConfig] of Object.entries(pathMethod.responses)) { if (parseInt(code) < 300) { continue; } const path = [...rootPath, endpointPath, m, 'responses', code, 'content', 'application/json', 'schema']; const schema = responseConfig.content['application/json'].schema; const schemaDiffResults = compareSchemas(errorProperties, schema, path); results.push(...schemaDiffResults); } } } return results; }); function compareSchemas(expectedSchema, actualSchema, path) { const { type, properties, required } = expectedSchema; const results = []; if (required && (!actualSchema || Object.keys(actualSchema).length === 0)) { results.push({ message: '`schema` object is required and should be non-empty', path }); } if ((actualSchema === null || actualSchema === void 0 ? void 0 : actualSchema.type) != type) { results.push({ message: `"type" should be a "${type}", got "${actualSchema.type}"`, path: [...path, 'type'] }); } if (!actualSchema.properties) { results.push({ message: 'missing required "properties" object', path: [...path, 'properties'] }); return results; } for (const [propertyName, propertyConfig] of Object.entries(properties)) { const schemaProperty = Object.keys(actualSchema.properties).find((p => p === propertyName)); if (!schemaProperty) { if (propertyConfig.required) { results.push({ message: `missing required property "${propertyName}"`, path: [...path, 'properties'] }); } continue; } const schemaPropertyConfig = actualSchema.properties[schemaProperty]; if ((schemaPropertyConfig === null || schemaPropertyConfig === void 0 ? void 0 : schemaPropertyConfig.type) !== propertyConfig.type) { results.push({ message: `"type" for "${propertyName}" should be of type "${propertyConfig.type}" but got "${schemaPropertyConfig.type}"`, path: [...path, 'properties', propertyName] }); } } return results; } //# sourceMappingURL=errorSchema.js.map