From 7066a2a4ddb634d1e31780257a9832ec7979d4ba Mon Sep 17 00:00:00 2001 From: Carlos Azuaje Date: Fri, 25 Aug 2023 17:47:59 -0300 Subject: [PATCH] fix conflict --- src/lib/PrettyRestDoc.tsx | 47 ++----------------- .../adapter/AdaptarOA3FromFileInput.ts | 10 ++-- .../adapter/discoveryTagsFromPaths.ts | 44 +++++++++++++++++ src/lib/fileValidationHelpers.ts | 38 +++++++++++++++ 4 files changed, 94 insertions(+), 45 deletions(-) create mode 100644 src/lib/adapter-oa3/adapter/discoveryTagsFromPaths.ts create mode 100644 src/lib/fileValidationHelpers.ts diff --git a/src/lib/PrettyRestDoc.tsx b/src/lib/PrettyRestDoc.tsx index 3c54e3f..8a70c07 100644 --- a/src/lib/PrettyRestDoc.tsx +++ b/src/lib/PrettyRestDoc.tsx @@ -15,6 +15,10 @@ import { Navigation } from "./components/Navigation"; import { SearchModal } from "./components/SearchModal"; import Section from "./components/Section"; import Spinner from "./components/Spinner"; +import { + getMissingAttributes, + validationReasons, +} from "./fileValidationHelpers"; interface Props { docSwagger?: OpenAPIV3.Document; docCustom?: SectionItem[]; @@ -171,47 +175,6 @@ const PrettyRestDoc: FC = ({ index++; } - const getMissingAttributes = (jsonParsed: any): string[] => { - const requiredAttributes = [ - "openapi", - "info", - "info.title", - "tags", - "paths", - "components", - ]; - - const missingAttributes: string[] = []; - for (const attr of requiredAttributes) { - const attrParts = attr.split("."); - let currentObj = jsonParsed; - let isValid = true; - for (const part of attrParts) { - if (!(part in currentObj)) { - isValid = false; - break; - } - currentObj = currentObj[part]; - } - if (!isValid) { - missingAttributes.push(attr); - } - } - return missingAttributes; - }; - - const reason = (attr: string): string => { - const reasons: Record = { - openapi: "It defines the OpenAPI version of the document.", - info: "It provides metadata about the API.", - "info.title": "It specifies the title of the API.", - tags: "It categorizes API operations into groups.", - paths: "It defines the available API endpoints.", - components: "It holds reusable components used in the specification.", - }; - return reasons[attr] || "Unknown reason."; - }; - const parseOpenAPIFile = async (file: File) => { try { setInitialLoading(true); @@ -227,7 +190,7 @@ const PrettyRestDoc: FC = ({ const missingAttributesMsg = missingAttributes .map( (attr) => - `Critical attribute: "${attr}" is not in the JSON File\nYou must add it in order to render it.\nThis value is important because: ${reason( + `Critical attribute: "${attr}" is not in the JSON File\nYou must add it in order to render it.\nThis value is important because: ${validationReasons( attr )}.\n` ) diff --git a/src/lib/adapter-oa3/adapter/AdaptarOA3FromFileInput.ts b/src/lib/adapter-oa3/adapter/AdaptarOA3FromFileInput.ts index c76a064..cec6740 100644 --- a/src/lib/adapter-oa3/adapter/AdaptarOA3FromFileInput.ts +++ b/src/lib/adapter-oa3/adapter/AdaptarOA3FromFileInput.ts @@ -1,8 +1,9 @@ -import { OpenAPIV3 } from "openapi-types"; import { Resolver } from "@stoplight/json-ref-resolver"; -import getArrayOfEndpoints from "./getArrayOfEndpoints"; +import { OpenAPIV3 } from "openapi-types"; import { capitalizeFirstWord } from "../../../utils/capitalize"; import { AdaptarOA3 } from "./AdaptarOA3"; +import discoveryTagsFromPaths from "./discoveryTagsFromPaths"; +import getArrayOfEndpoints from "./getArrayOfEndpoints"; const resolver = new Resolver(); @@ -17,8 +18,11 @@ class AdaptarOA3FromFileInput extends AdaptarOA3 { const swaggerDocResolvedResult = swaggerDocResolved.result as OpenAPIV3.Document; const docMerged: SectionItem[] = []; + const tags = + swaggerDocResolvedResult.tags || + discoveryTagsFromPaths(swaggerDocResolvedResult); - for (const tag of swaggerDocResolvedResult.tags || []) { + for (const tag of tags) { if (!tag.name) { console.warn( `There is a tag without name and we can not create the documentation without it` diff --git a/src/lib/adapter-oa3/adapter/discoveryTagsFromPaths.ts b/src/lib/adapter-oa3/adapter/discoveryTagsFromPaths.ts new file mode 100644 index 0000000..2b3a0f1 --- /dev/null +++ b/src/lib/adapter-oa3/adapter/discoveryTagsFromPaths.ts @@ -0,0 +1,44 @@ +import { OpenAPIV3 } from "openapi-types"; + +const discoveryTagsFromPaths = ( + openApiDocument: OpenAPIV3.Document +): OpenAPIV3.TagObject[] => { + const tags: OpenAPIV3.TagObject[] = []; + + if (openApiDocument.paths) { + for (const pathKey in openApiDocument.paths) { + const pathItem = openApiDocument.paths[ + pathKey + ] as OpenAPIV3.PathItemObject; + + if (pathItem) { + for (const methodKey in pathItem) { + if (methodKey !== "parameters") { + const method = (pathItem as any)[ + methodKey + ] as OpenAPIV3.OperationObject; + if (method.tags && Array.isArray(method.tags)) { + method.tags.forEach((tag) => { + const existingTag = tags.find((t) => t.name === tag); + if (!existingTag) { + tags.push({ + name: tag, + description: `Section grouped by ${tag}`, + externalDocs: { + url: "", + description: "", + }, + }); + } + }); + } + } + } + } + } + } + + return tags; +}; + +export default discoveryTagsFromPaths; diff --git a/src/lib/fileValidationHelpers.ts b/src/lib/fileValidationHelpers.ts new file mode 100644 index 0000000..f8fabb2 --- /dev/null +++ b/src/lib/fileValidationHelpers.ts @@ -0,0 +1,38 @@ +export const getMissingAttributes = (jsonParsed: any): string[] => { + const requiredAttributes = [ + "openapi", + "info", + "info.title", + "paths", + "components", + ]; + + const missingAttributes: string[] = []; + for (const attr of requiredAttributes) { + const attrParts = attr.split("."); + let currentObj = jsonParsed; + let isValid = true; + for (const part of attrParts) { + if (!(part in currentObj)) { + isValid = false; + break; + } + currentObj = currentObj[part]; + } + if (!isValid) { + missingAttributes.push(attr); + } + } + return missingAttributes; +}; + +export const validationReasons = (attr: string): string => { + const reasons: Record = { + openapi: "It defines the OpenAPI version of the document.", + info: "It provides metadata about the API.", + "info.title": "It specifies the title of the API.", + paths: "It defines the available API endpoints.", + components: "It holds reusable components used in the specification.", + }; + return reasons[attr] || "Unknown reason."; +};