UNPKG

@svengroup/openapi-to-pdf

Version:

Create PDF API reference documentation from OpenAPI 3.0.x specification files.

244 lines (243 loc) 10.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = generateEndpointsMarkdown; exports.getActualTags = getActualTags; exports.getTagObject = getTagObject; exports.getOperationsFromPath = getOperationsFromPath; exports.generateTagMarkdown = generateTagMarkdown; exports.generateOperationsWithTagsMarkdown = generateOperationsWithTagsMarkdown; exports.generateUntaggedOperationsMarkdown = generateUntaggedOperationsMarkdown; exports.generateOperationMarkdown = generateOperationMarkdown; exports.generateOperationTitleMarkdown = generateOperationTitleMarkdown; exports.getParameters = getParameters; exports.generateOperationSecurityMarkdown = generateOperationSecurityMarkdown; exports.generateMediaTypeMarkdown = generateMediaTypeMarkdown; const request_1 = require("../../markdown/endpoints/request"); const schema_1 = require("../../markdown/schema"); const response_1 = require("../../markdown/endpoints/response"); const merge_1 = require("../../utils/merge"); const toc_1 = require("../../markdown/toc"); const http_1 = require("../../utils/http"); let untagged_operations = {}; function generateEndpointsMarkdown(schema, config) { let endpoints_str = ""; endpoints_str += `# ${config?.headings?.endpoints ?? 'Endpoints'}`; endpoints_str += "\n\n"; const tags = schema.tags; const paths = schema.paths; const actual_tags = getActualTags(paths); if (actual_tags.length > 0) { endpoints_str += generateOperationsWithTagsMarkdown(paths, actual_tags, tags, config); } else { endpoints_str += generateOperationsMarkdown(paths); } untagged_operations = {}; return endpoints_str; } function getActualTags(paths) { let actual_tags = []; for (const key_value of Object.entries(paths)) { const path_item = key_value[1]; for (const [key, value] of Object.entries(path_item)) { if ((0, http_1.isMethod)(key)) { /** @ts-expect-error http method key always operation obj */ if (value.tags) { /** @ts-expect-error http method key always operation obj */ actual_tags = [...actual_tags, ...value.tags]; } } } } actual_tags = [...new Set(actual_tags)]; return actual_tags; } function getTagObject(name, tags) { if (!tags) { return null; } for (const tag of tags) { if (tag.name === name) { return tag; } } return null; } function getOperationsFromPath(path_item, tag, find_no_tag) { const operations = {}; for (const [key, value] of Object.entries(path_item)) { if ((0, http_1.isMethod)(key)) { if (find_no_tag) { /** @ts-expect-error http method key always operation obj */ if (!value.tags) { /** @ts-expect-error http method key always operation obj */ operations[key] = value; } } else if (tag) { /** @ts-expect-error http method key always operation obj */ if (value.tags?.includes(tag)) { /** @ts-expect-error http method key always operation obj */ operations[key] = value; } } else { /** @ts-expect-error http method key always operation obj */ operations[key] = value; } } } return operations; } function generateTagMarkdown(actual_tag, tags) { let endpoints_str = ""; endpoints_str += `## ${actual_tag}`; endpoints_str += "\n\n"; const tag = getTagObject(actual_tag, tags); if (tag?.description) { endpoints_str += tag.description; endpoints_str += "\n\n"; } if (tag?.externalDocs?.url) { endpoints_str += `Read more about this category here: [${tag?.externalDocs?.url}](${tag?.externalDocs?.url})`; endpoints_str += "\n\n"; } return endpoints_str; } function generateOperationsMarkdown(paths, actual_tag) { let endpoints_str = ""; const h = actual_tag ? "#" : ""; // prefix for headers (if tag is used or not) let operations_toc = []; for (const [path, path_item] of Object.entries(paths)) { const operations = getOperationsFromPath(path_item, actual_tag); if (actual_tag) { const untagged_operations_of_path = getOperationsFromPath(path_item, undefined, true); if (Object.keys(untagged_operations_of_path).length > 0) { if (untagged_operations[path]) { untagged_operations[path] = { ...untagged_operations[path], ...untagged_operations_of_path }; } else { untagged_operations[path] = untagged_operations_of_path; } } } for (const [method, operation] of Object.entries(operations)) { const operation_title = generateOperationTitleMarkdown(h, path, method, operation); operations_toc = [...operations_toc, ...(0, toc_1.getToc)(operation_title)]; endpoints_str += operation_title; endpoints_str += generateOperationMarkdown(h, operation, path_item); } } const toc_markdown = (0, toc_1.generateSubSectionTocMarkdown)(operations_toc); return toc_markdown + endpoints_str; } function generateOperationsWithTagsMarkdown(paths, actual_tags, tags, config) { let endpoints_str = ""; for (const actual_tag of actual_tags) { /* TAG */ endpoints_str += generateTagMarkdown(actual_tag, tags); /* OPERATIONS */ endpoints_str += generateOperationsMarkdown(paths, actual_tag); } /* UNTAGGED */ endpoints_str += generateUntaggedOperationsMarkdown(tags, config); /* TAGS TOC */ const tags_toc = (0, toc_1.getToc)(endpoints_str, [2]); const tags_toc_str = (0, toc_1.generateSubSectionTocMarkdown)(tags_toc); return tags_toc_str + endpoints_str; } ; function generateUntaggedOperationsMarkdown(tags, config) { let endpoints_str = ""; if (Object.keys(untagged_operations).length > 0) { let operations_toc = []; for (const [path, operations] of Object.entries(untagged_operations)) { for (const [method, operation] of Object.entries(operations)) { const operation_title = generateOperationTitleMarkdown("#", path, method, operation); operations_toc = [...operations_toc, ...(0, toc_1.getToc)(operation_title)]; endpoints_str += operation_title; endpoints_str += generateOperationMarkdown("#", operation); } } const toc_markdown = (0, toc_1.generateSubSectionTocMarkdown)(operations_toc); const tag_title_markdown = generateTagMarkdown(config?.headings?.untagged_endpoints ?? "Uncategorized", tags); endpoints_str = tag_title_markdown + toc_markdown + endpoints_str; } return endpoints_str; } function generateOperationMarkdown(h, operation, path_item) { let endpoints_str = ""; if (operation.summary) { endpoints_str += operation.summary; endpoints_str += "\n\n"; } if (operation.description) { endpoints_str += operation.description; endpoints_str += "\n\n"; } if (operation.externalDocs?.url) { endpoints_str += `Read more about this API endpoint here: [${operation.externalDocs.url}](${operation.externalDocs.url})`; endpoints_str += "\n\n"; } endpoints_str += generateOperationSecurityMarkdown(h, operation.security); /** @ts-expect-error we resolve all references */ const parameters = getParameters(path_item?.parameters, operation.parameters); endpoints_str += (0, request_1.generateParametersMarkdown)(h, 'path', parameters); endpoints_str += (0, request_1.generateParametersMarkdown)(h, 'query', parameters); endpoints_str += (0, request_1.generateParametersMarkdown)(h, 'header', parameters); endpoints_str += (0, request_1.generateParametersMarkdown)(h, 'cookie', parameters); /** @ts-expect-error we resolve all references */ endpoints_str += (0, request_1.generateRequestBodyMarkdown)(h, operation.requestBody); endpoints_str += (0, response_1.generateResponsesMarkdown)(h, operation.responses); return endpoints_str; } function generateOperationTitleMarkdown(h, path, method, operation) { let endpoints_str = ""; endpoints_str += `${h}## \`${method.toUpperCase()} ${path}\`${operation.operationId ? `(${operation.operationId})` : ''}`; endpoints_str += "\n\n"; return endpoints_str; } function getParameters(path_parameters, operation_parameters) { if (path_parameters && !operation_parameters) { return path_parameters; } else if (!path_parameters && operation_parameters) { return operation_parameters; } else if (path_parameters && operation_parameters) { return (0, merge_1.deepMerge)(operation_parameters, path_parameters); } return []; } function generateOperationSecurityMarkdown(h, security_requirements) { if (!security_requirements) { return ""; } let endpoints_str = ""; endpoints_str += `${h}### Required Scopes`; endpoints_str += "\n\n"; endpoints_str += `This endpoint requires the following scopes:\n\n`; for (const security_requirement of security_requirements) { for (const security_items of Object.entries(security_requirement)) { for (const security_item of security_items[1]) { endpoints_str += `- \`${security_item}\`\n`; } } } endpoints_str += "\n\n"; return endpoints_str; } function generateMediaTypeMarkdown(media_type, obj, display_for) { let endpoints_str = ""; endpoints_str += `Media Type: \`${media_type}\``; endpoints_str += "\n\n"; if (obj.encoding) { endpoints_str += `Encoding: ${obj.encoding}`; endpoints_str += "\n\n"; } if (obj.schema) { /** @ts-expect-error we resolve all references */ endpoints_str += (0, schema_1.generateSchemaMarkdown)(obj.schema, display_for); } return endpoints_str; }