mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-08-24 20:34:05 +02:00
Support OpenAPI 3.2 QUERY and additional operations (#591)
This commit is contained in:
@@ -21,7 +21,7 @@ type ImportResources = {
|
|||||||
httpRequests: AtLeast<HttpRequest, "name" | "id" | "model" | "workspaceId">[];
|
httpRequests: AtLeast<HttpRequest, "name" | "id" | "model" | "workspaceId">[];
|
||||||
};
|
};
|
||||||
|
|
||||||
const HTTP_METHODS = ["delete", "get", "head", "options", "patch", "post", "put", "trace"];
|
const HTTP_METHODS = ["delete", "get", "head", "options", "patch", "post", "put", "query", "trace"];
|
||||||
const BODY_CONTENT_TYPE_PREFERENCE = [
|
const BODY_CONTENT_TYPE_PREFERENCE = [
|
||||||
"application/json",
|
"application/json",
|
||||||
"application/x-www-form-urlencoded",
|
"application/x-www-form-urlencoded",
|
||||||
@@ -103,10 +103,7 @@ export async function convertOpenApi(contents: string): Promise<ImportPluginResp
|
|||||||
if (!isRecord(pathItem)) continue;
|
if (!isRecord(pathItem)) continue;
|
||||||
|
|
||||||
const pathParameters = toArray(pathItem.parameters);
|
const pathParameters = toArray(pathItem.parameters);
|
||||||
for (const method of HTTP_METHODS) {
|
for (const { method, operation } of pathItemOperations(pathItem, importState)) {
|
||||||
const operation = importState.resolve(pathItem[method]);
|
|
||||||
if (!isRecord(operation)) continue;
|
|
||||||
|
|
||||||
const folderId = findOrCreateFolderId({
|
const folderId = findOrCreateFolderId({
|
||||||
folderIdsByTag,
|
folderIdsByTag,
|
||||||
importState,
|
importState,
|
||||||
@@ -150,6 +147,24 @@ export async function convertOpenApi(contents: string): Promise<ImportPluginResp
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** OpenAPI 3.2 adds QUERY plus a map for extension HTTP methods. */
|
||||||
|
function pathItemOperations(
|
||||||
|
pathItem: UnknownRecord,
|
||||||
|
importState: ImportState,
|
||||||
|
): { method: string; operation: UnknownRecord }[] {
|
||||||
|
const operations = HTTP_METHODS.flatMap((method) => {
|
||||||
|
const operation = importState.resolve(pathItem[method]);
|
||||||
|
return isRecord(operation) ? [{ method, operation }] : [];
|
||||||
|
});
|
||||||
|
|
||||||
|
for (const [method, rawOperation] of Object.entries(toRecord(pathItem.additionalOperations))) {
|
||||||
|
if (HTTP_METHODS.includes(method.toLowerCase())) continue;
|
||||||
|
const operation = importState.resolve(rawOperation);
|
||||||
|
if (isRecord(operation)) operations.push({ method, operation });
|
||||||
|
}
|
||||||
|
return operations;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Two operations sharing a summary are indistinguishable once imported, so the
|
* Two operations sharing a summary are indistinguishable once imported, so the
|
||||||
* colliding ones get their route appended. Names that are already unique within
|
* colliding ones get their route appended. Names that are already unique within
|
||||||
|
|||||||
@@ -13,6 +13,28 @@ describe("importer-openapi", () => {
|
|||||||
.readdirSync(realWorldFixturesPath)
|
.readdirSync(realWorldFixturesPath)
|
||||||
.filter((fixture) => fixture.endsWith(".yaml"));
|
.filter((fixture) => fixture.endsWith(".yaml"));
|
||||||
|
|
||||||
|
test("Imports OpenAPI 3.2 QUERY and additional operations", async () => {
|
||||||
|
const imported = await convertOpenApi(
|
||||||
|
JSON.stringify({
|
||||||
|
openapi: "3.2.0",
|
||||||
|
info: { title: "OpenAPI 3.2 Operations", version: "1.0.0" },
|
||||||
|
paths: {
|
||||||
|
"/resources": {
|
||||||
|
query: { summary: "Query resources", responses: {} },
|
||||||
|
additionalOperations: {
|
||||||
|
COPY: { summary: "Copy resources", responses: {} },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(imported?.resources.httpRequests).toEqual([
|
||||||
|
expect.objectContaining({ method: "QUERY", name: "Query resources", url: "/resources" }),
|
||||||
|
expect.objectContaining({ method: "COPY", name: "Copy resources", url: "/resources" }),
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
test("Maps operation description to request description", async () => {
|
test("Maps operation description to request description", async () => {
|
||||||
const imported = await convertOpenApi(
|
const imported = await convertOpenApi(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
|
|||||||
Reference in New Issue
Block a user