diff --git a/packages/docusaurus-plugin-openapi-docs/src/markdown/createRequestSchema.ts b/packages/docusaurus-plugin-openapi-docs/src/markdown/createRequestSchema.ts index f22726264..d22dd2c3f 100644 --- a/packages/docusaurus-plugin-openapi-docs/src/markdown/createRequestSchema.ts +++ b/packages/docusaurus-plugin-openapi-docs/src/markdown/createRequestSchema.ts @@ -90,7 +90,7 @@ export function createRequestSchema({ title, body, ...rest }: Props) { }), create("ul", { style: { marginLeft: "1rem" }, - children: createNodes(firstBody), + children: createNodes(firstBody, "request"), }), ], }), @@ -161,7 +161,7 @@ export function createRequestSchema({ title, body, ...rest }: Props) { }), create("ul", { style: { marginLeft: "1rem" }, - children: createNodes(firstBody), + children: createNodes(firstBody, "request"), }), ], }), diff --git a/packages/docusaurus-plugin-openapi-docs/src/markdown/createResponseSchema.ts b/packages/docusaurus-plugin-openapi-docs/src/markdown/createResponseSchema.ts index 378ba5159..7a645c289 100644 --- a/packages/docusaurus-plugin-openapi-docs/src/markdown/createResponseSchema.ts +++ b/packages/docusaurus-plugin-openapi-docs/src/markdown/createResponseSchema.ts @@ -118,7 +118,7 @@ export function createResponseSchema({ title, body, ...rest }: Props) { }), create("ul", { style: { marginLeft: "1rem" }, - children: createNodes(firstBody!), + children: createNodes(firstBody!, "response"), }), ], }), diff --git a/packages/docusaurus-plugin-openapi-docs/src/markdown/createSchema.test.ts b/packages/docusaurus-plugin-openapi-docs/src/markdown/createSchema.test.ts index 0232ff4ce..711f70776 100644 --- a/packages/docusaurus-plugin-openapi-docs/src/markdown/createSchema.test.ts +++ b/packages/docusaurus-plugin-openapi-docs/src/markdown/createSchema.test.ts @@ -48,7 +48,7 @@ describe("createNodes", () => { }, }; expect( - createNodes(schema).map((md: any) => + createNodes(schema, "request").map((md: any) => prettier.format(md, { parser: "babel" }) ) ).toMatchSnapshot(); diff --git a/packages/docusaurus-plugin-openapi-docs/src/markdown/createSchema.ts b/packages/docusaurus-plugin-openapi-docs/src/markdown/createSchema.ts index 1c6d34f4b..deb374a03 100644 --- a/packages/docusaurus-plugin-openapi-docs/src/markdown/createSchema.ts +++ b/packages/docusaurus-plugin-openapi-docs/src/markdown/createSchema.ts @@ -20,6 +20,8 @@ import { create, guard } from "./utils"; const jsonSchemaMergeAllOf = require("json-schema-merge-allof"); +let SCHEMA_TYPE: "request" | "response"; + /** * Returns a merged representation of allOf array of schemas. */ @@ -29,6 +31,9 @@ export function mergeAllOf(allOf: SchemaObject[]) { readOnly: function () { return true; }, + writeOnly: function () { + return true; + }, example: function () { return true; }, @@ -74,7 +79,7 @@ function createAnyOneOf(schema: SchemaObject): any { } if (anyOneSchema.allOf !== undefined) { - anyOneChildren.push(createNodes(anyOneSchema)); + anyOneChildren.push(createNodes(anyOneSchema, SCHEMA_TYPE)); delete anyOneSchema.allOf; } @@ -89,7 +94,7 @@ function createAnyOneOf(schema: SchemaObject): any { anyOneSchema.type === "integer" || anyOneSchema.type === "boolean" ) { - anyOneChildren.push(createNodes(anyOneSchema)); + anyOneChildren.push(createNodes(anyOneSchema, SCHEMA_TYPE)); } if (anyOneChildren.length) { if (schema.type === "array") { @@ -304,7 +309,7 @@ function createItems(schema: SchemaObject) { ) { return [ createOpeningArrayBracket(), - createNodes(schema.items), + createNodes(schema.items, SCHEMA_TYPE), createClosingArrayBracket(), ].flat(); } @@ -411,7 +416,7 @@ function createDetailsNode( children: createDescription(description), }) ), - createNodes(schema), + createNodes(schema, SCHEMA_TYPE), ], }), ], @@ -565,7 +570,7 @@ function createPropertyDiscriminator( // className: "openapi-tabs__discriminator-item", label: label, value: `${index}-item-discriminator`, - children: [createNodes(discriminator?.mapping[key])], + children: [createNodes(discriminator?.mapping[key], SCHEMA_TYPE)], }); }), }), @@ -664,8 +669,16 @@ function createEdges({ ); } - if (mergedSchemas.readOnly && mergedSchemas.readOnly === true) { - return undefined; + if (SCHEMA_TYPE === "request") { + if (mergedSchemas.readOnly && mergedSchemas.readOnly === true) { + return undefined; + } + } + + if (SCHEMA_TYPE === "response") { + if (mergedSchemas.writeOnly && mergedSchemas.writeOnly === true) { + return undefined; + } } return create("SchemaItem", { @@ -719,8 +732,16 @@ function createEdges({ ); } - if (schema.readOnly && schema.readOnly === true) { - return undefined; + if (SCHEMA_TYPE === "request") { + if (schema.readOnly && schema.readOnly === true) { + return undefined; + } + } + + if (SCHEMA_TYPE === "response") { + if (schema.writeOnly && schema.writeOnly === true) { + return undefined; + } } // primitives and array of non-objects @@ -737,7 +758,11 @@ function createEdges({ /** * Creates a hierarchical level of a schema tree. Nodes produce edges that can branch into sub-nodes with edges, recursively. */ -export function createNodes(schema: SchemaObject): any { +export function createNodes( + schema: SchemaObject, + schemaType: "request" | "response" +): any { + SCHEMA_TYPE = schemaType; const nodes = []; // if (schema.discriminator !== undefined) { // return createDiscriminator(schema); diff --git a/packages/docusaurus-plugin-openapi-docs/src/openapi/openapi.ts b/packages/docusaurus-plugin-openapi-docs/src/openapi/openapi.ts index 99bc85a35..8dde3c8d0 100644 --- a/packages/docusaurus-plugin-openapi-docs/src/openapi/openapi.ts +++ b/packages/docusaurus-plugin-openapi-docs/src/openapi/openapi.ts @@ -469,8 +469,7 @@ function bindCollectionToApiItems( const method = item.request.method.toLowerCase(); const path = item.request.url .getPath({ unresolved: true }) // unresolved returns "/:variableName" instead of "/" - .replace(/:([a-z0-9-_]+)/gi, "{$1}"); // replace "/:variableName" with "/{variableName}" - + .replace(/(? { if (item.type === "info" || item.type === "tag") { return false; diff --git a/packages/docusaurus-theme-openapi-docs/src/theme/ApiExplorer/Request/makeRequest.ts b/packages/docusaurus-theme-openapi-docs/src/theme/ApiExplorer/Request/makeRequest.ts index f16e27f88..07b2edbb5 100644 --- a/packages/docusaurus-theme-openapi-docs/src/theme/ApiExplorer/Request/makeRequest.ts +++ b/packages/docusaurus-theme-openapi-docs/src/theme/ApiExplorer/Request/makeRequest.ts @@ -161,6 +161,10 @@ async function makeRequest( if (data.key && data.value.content) { myBody.append(data.key, data.value.content); } + // handle generic key-value payload + if (data.key && typeof data.value === "string") { + myBody.append(data.key, data.value); + } } } break; @@ -189,11 +193,62 @@ async function makeRequest( finalUrl = normalizedProxy + request.url.toString(); } - return await fetchWithtimeout(finalUrl, requestOptions).then( - (response: any) => { - return response; + return fetchWithtimeout(finalUrl, requestOptions).then((response: any) => { + const contentType = response.headers.get("content-type"); + let fileExtension = ""; + + if (contentType) { + if (contentType.includes("application/pdf")) { + fileExtension = ".pdf"; + } else if (contentType.includes("image/jpeg")) { + fileExtension = ".jpg"; + } else if (contentType.includes("image/png")) { + fileExtension = ".png"; + } else if (contentType.includes("image/gif")) { + fileExtension = ".gif"; + } else if (contentType.includes("image/webp")) { + fileExtension = ".webp"; + } else if (contentType.includes("video/mpeg")) { + fileExtension = ".mpeg"; + } else if (contentType.includes("video/mp4")) { + fileExtension = ".mp4"; + } else if (contentType.includes("audio/mpeg")) { + fileExtension = ".mp3"; + } else if (contentType.includes("audio/ogg")) { + fileExtension = ".ogg"; + } else if (contentType.includes("application/octet-stream")) { + fileExtension = ".bin"; + } else if (contentType.includes("application/zip")) { + fileExtension = ".zip"; + } + + if (fileExtension) { + return response.blob().then((blob: any) => { + const url = window.URL.createObjectURL(blob); + + const link = document.createElement("a"); + link.href = url; + // Now the file name includes the extension + link.setAttribute("download", `file${fileExtension}`); + + // These two lines are necessary to make the link click in Firefox + link.style.display = "none"; + document.body.appendChild(link); + + link.click(); + + // After link is clicked, it's safe to remove it. + setTimeout(() => document.body.removeChild(link), 0); + + return response; + }); + } else { + return response; + } } - ); + + return response; + }); } export default makeRequest;