Skip to content

Commit

Permalink
Merge pull request #12 from CharlyJazz/fixtags
Browse files Browse the repository at this point in the history
discover tags if there is not tags array
  • Loading branch information
CharlyJazz committed Aug 25, 2023
2 parents 4da5143 + 7066a2a commit 455ea6a
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 45 deletions.
47 changes: 5 additions & 42 deletions src/lib/PrettyRestDoc.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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[];
Expand Down Expand Up @@ -171,47 +175,6 @@ const PrettyRestDoc: FC<Props> = ({
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<string, string> = {
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);
Expand All @@ -227,7 +190,7 @@ const PrettyRestDoc: FC<Props> = ({
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`
)
Expand Down
10 changes: 7 additions & 3 deletions src/lib/adapter-oa3/adapter/AdaptarOA3FromFileInput.ts
Original file line number Diff line number Diff line change
@@ -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();

Expand All @@ -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`
Expand Down
44 changes: 44 additions & 0 deletions src/lib/adapter-oa3/adapter/discoveryTagsFromPaths.ts
Original file line number Diff line number Diff line change
@@ -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;
38 changes: 38 additions & 0 deletions src/lib/fileValidationHelpers.ts
Original file line number Diff line number Diff line change
@@ -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<string, string> = {
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.";
};

0 comments on commit 455ea6a

Please sign in to comment.