Skip to content

Commit d20984b

Browse files
authored
Port v2 changes/fixes into v3 (#667)
* add negative look behind to exclude colon delimited path segments (#663) * use SCHEMA_TYPE to distinguish request/response to support readOnly/writeOnly properties (#665) * Improve support for handling multipart form data (#666) * use pdfblock to test multipart form data * switch back to cors proxy * add handler for generic key-value payload * debug response content type * refactor to download media and file content types * switch back to petstore
1 parent 9641610 commit d20984b

File tree

6 files changed

+99
-20
lines changed

6 files changed

+99
-20
lines changed

packages/docusaurus-plugin-openapi-docs/src/markdown/createRequestSchema.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ export function createRequestSchema({ title, body, ...rest }: Props) {
9090
}),
9191
create("ul", {
9292
style: { marginLeft: "1rem" },
93-
children: createNodes(firstBody),
93+
children: createNodes(firstBody, "request"),
9494
}),
9595
],
9696
}),
@@ -161,7 +161,7 @@ export function createRequestSchema({ title, body, ...rest }: Props) {
161161
}),
162162
create("ul", {
163163
style: { marginLeft: "1rem" },
164-
children: createNodes(firstBody),
164+
children: createNodes(firstBody, "request"),
165165
}),
166166
],
167167
}),

packages/docusaurus-plugin-openapi-docs/src/markdown/createResponseSchema.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ export function createResponseSchema({ title, body, ...rest }: Props) {
118118
}),
119119
create("ul", {
120120
style: { marginLeft: "1rem" },
121-
children: createNodes(firstBody!),
121+
children: createNodes(firstBody!, "response"),
122122
}),
123123
],
124124
}),

packages/docusaurus-plugin-openapi-docs/src/markdown/createSchema.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ describe("createNodes", () => {
4848
},
4949
};
5050
expect(
51-
createNodes(schema).map((md: any) =>
51+
createNodes(schema, "request").map((md: any) =>
5252
prettier.format(md, { parser: "babel" })
5353
)
5454
).toMatchSnapshot();

packages/docusaurus-plugin-openapi-docs/src/markdown/createSchema.ts

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ import { create, guard } from "./utils";
2020

2121
const jsonSchemaMergeAllOf = require("json-schema-merge-allof");
2222

23+
let SCHEMA_TYPE: "request" | "response";
24+
2325
/**
2426
* Returns a merged representation of allOf array of schemas.
2527
*/
@@ -29,6 +31,9 @@ export function mergeAllOf(allOf: SchemaObject[]) {
2931
readOnly: function () {
3032
return true;
3133
},
34+
writeOnly: function () {
35+
return true;
36+
},
3237
example: function () {
3338
return true;
3439
},
@@ -74,7 +79,7 @@ function createAnyOneOf(schema: SchemaObject): any {
7479
}
7580

7681
if (anyOneSchema.allOf !== undefined) {
77-
anyOneChildren.push(createNodes(anyOneSchema));
82+
anyOneChildren.push(createNodes(anyOneSchema, SCHEMA_TYPE));
7883
delete anyOneSchema.allOf;
7984
}
8085

@@ -89,7 +94,7 @@ function createAnyOneOf(schema: SchemaObject): any {
8994
anyOneSchema.type === "integer" ||
9095
anyOneSchema.type === "boolean"
9196
) {
92-
anyOneChildren.push(createNodes(anyOneSchema));
97+
anyOneChildren.push(createNodes(anyOneSchema, SCHEMA_TYPE));
9398
}
9499
if (anyOneChildren.length) {
95100
if (schema.type === "array") {
@@ -304,7 +309,7 @@ function createItems(schema: SchemaObject) {
304309
) {
305310
return [
306311
createOpeningArrayBracket(),
307-
createNodes(schema.items),
312+
createNodes(schema.items, SCHEMA_TYPE),
308313
createClosingArrayBracket(),
309314
].flat();
310315
}
@@ -411,7 +416,7 @@ function createDetailsNode(
411416
children: createDescription(description),
412417
})
413418
),
414-
createNodes(schema),
419+
createNodes(schema, SCHEMA_TYPE),
415420
],
416421
}),
417422
],
@@ -565,7 +570,7 @@ function createPropertyDiscriminator(
565570
// className: "openapi-tabs__discriminator-item",
566571
label: label,
567572
value: `${index}-item-discriminator`,
568-
children: [createNodes(discriminator?.mapping[key])],
573+
children: [createNodes(discriminator?.mapping[key], SCHEMA_TYPE)],
569574
});
570575
}),
571576
}),
@@ -664,8 +669,16 @@ function createEdges({
664669
);
665670
}
666671

667-
if (mergedSchemas.readOnly && mergedSchemas.readOnly === true) {
668-
return undefined;
672+
if (SCHEMA_TYPE === "request") {
673+
if (mergedSchemas.readOnly && mergedSchemas.readOnly === true) {
674+
return undefined;
675+
}
676+
}
677+
678+
if (SCHEMA_TYPE === "response") {
679+
if (mergedSchemas.writeOnly && mergedSchemas.writeOnly === true) {
680+
return undefined;
681+
}
669682
}
670683

671684
return create("SchemaItem", {
@@ -719,8 +732,16 @@ function createEdges({
719732
);
720733
}
721734

722-
if (schema.readOnly && schema.readOnly === true) {
723-
return undefined;
735+
if (SCHEMA_TYPE === "request") {
736+
if (schema.readOnly && schema.readOnly === true) {
737+
return undefined;
738+
}
739+
}
740+
741+
if (SCHEMA_TYPE === "response") {
742+
if (schema.writeOnly && schema.writeOnly === true) {
743+
return undefined;
744+
}
724745
}
725746

726747
// primitives and array of non-objects
@@ -737,7 +758,11 @@ function createEdges({
737758
/**
738759
* Creates a hierarchical level of a schema tree. Nodes produce edges that can branch into sub-nodes with edges, recursively.
739760
*/
740-
export function createNodes(schema: SchemaObject): any {
761+
export function createNodes(
762+
schema: SchemaObject,
763+
schemaType: "request" | "response"
764+
): any {
765+
SCHEMA_TYPE = schemaType;
741766
const nodes = [];
742767
// if (schema.discriminator !== undefined) {
743768
// return createDiscriminator(schema);

packages/docusaurus-plugin-openapi-docs/src/openapi/openapi.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -469,8 +469,7 @@ function bindCollectionToApiItems(
469469
const method = item.request.method.toLowerCase();
470470
const path = item.request.url
471471
.getPath({ unresolved: true }) // unresolved returns "/:variableName" instead of "/<type>"
472-
.replace(/:([a-z0-9-_]+)/gi, "{$1}"); // replace "/:variableName" with "/{variableName}"
473-
472+
.replace(/(?<![a-z0-9-_]+):([a-z0-9-_]+)/gi, "{$1}"); // replace "/:variableName" with "/{variableName}"
474473
const apiItem = items.find((item) => {
475474
if (item.type === "info" || item.type === "tag") {
476475
return false;

packages/docusaurus-theme-openapi-docs/src/theme/ApiExplorer/Request/makeRequest.ts

Lines changed: 59 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,10 @@ async function makeRequest(
161161
if (data.key && data.value.content) {
162162
myBody.append(data.key, data.value.content);
163163
}
164+
// handle generic key-value payload
165+
if (data.key && typeof data.value === "string") {
166+
myBody.append(data.key, data.value);
167+
}
164168
}
165169
}
166170
break;
@@ -189,11 +193,62 @@ async function makeRequest(
189193
finalUrl = normalizedProxy + request.url.toString();
190194
}
191195

192-
return await fetchWithtimeout(finalUrl, requestOptions).then(
193-
(response: any) => {
194-
return response;
196+
return fetchWithtimeout(finalUrl, requestOptions).then((response: any) => {
197+
const contentType = response.headers.get("content-type");
198+
let fileExtension = "";
199+
200+
if (contentType) {
201+
if (contentType.includes("application/pdf")) {
202+
fileExtension = ".pdf";
203+
} else if (contentType.includes("image/jpeg")) {
204+
fileExtension = ".jpg";
205+
} else if (contentType.includes("image/png")) {
206+
fileExtension = ".png";
207+
} else if (contentType.includes("image/gif")) {
208+
fileExtension = ".gif";
209+
} else if (contentType.includes("image/webp")) {
210+
fileExtension = ".webp";
211+
} else if (contentType.includes("video/mpeg")) {
212+
fileExtension = ".mpeg";
213+
} else if (contentType.includes("video/mp4")) {
214+
fileExtension = ".mp4";
215+
} else if (contentType.includes("audio/mpeg")) {
216+
fileExtension = ".mp3";
217+
} else if (contentType.includes("audio/ogg")) {
218+
fileExtension = ".ogg";
219+
} else if (contentType.includes("application/octet-stream")) {
220+
fileExtension = ".bin";
221+
} else if (contentType.includes("application/zip")) {
222+
fileExtension = ".zip";
223+
}
224+
225+
if (fileExtension) {
226+
return response.blob().then((blob: any) => {
227+
const url = window.URL.createObjectURL(blob);
228+
229+
const link = document.createElement("a");
230+
link.href = url;
231+
// Now the file name includes the extension
232+
link.setAttribute("download", `file${fileExtension}`);
233+
234+
// These two lines are necessary to make the link click in Firefox
235+
link.style.display = "none";
236+
document.body.appendChild(link);
237+
238+
link.click();
239+
240+
// After link is clicked, it's safe to remove it.
241+
setTimeout(() => document.body.removeChild(link), 0);
242+
243+
return response;
244+
});
245+
} else {
246+
return response;
247+
}
195248
}
196-
);
249+
250+
return response;
251+
});
197252
}
198253

199254
export default makeRequest;

0 commit comments

Comments
 (0)