Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
changeKind: fix
packages:
- "@azure-tools/typespec-autorest"
---

Fix sorting of x-ms-paths entries that start with `?` (query-only paths). Previously these paths were not sorted alphabetically.
17 changes: 13 additions & 4 deletions packages/typespec-autorest/src/json-schema-sorter/sorter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,17 @@ function defaultCompare(a: number | string, b: number | string) {

/** Sort urls in a specific way so path with field show up before a fixed segment. */
function compareUrl(leftPath: string, rightPath: string) {
const leftParts = leftPath.split("/").slice(1);
const rightParts = rightPath.split("/").slice(1);
// Separate path and query string portions to handle x-ms-paths entries starting with "?"
const leftQueryIndex = leftPath.indexOf("?");
const rightQueryIndex = rightPath.indexOf("?");
const leftPathPortion = leftQueryIndex >= 0 ? leftPath.substring(0, leftQueryIndex) : leftPath;
const rightPathPortion =
rightQueryIndex >= 0 ? rightPath.substring(0, rightQueryIndex) : rightPath;
const leftQuery = leftQueryIndex >= 0 ? leftPath.substring(leftQueryIndex) : "";
const rightQuery = rightQueryIndex >= 0 ? rightPath.substring(rightQueryIndex) : "";

const leftParts = leftPathPortion ? leftPathPortion.split("/").slice(1) : [];
const rightParts = rightPathPortion ? rightPathPortion.split("/").slice(1) : [];

for (let i = 0; i < Math.max(leftParts.length, rightParts.length); i++) {
// Have we exhausted the path parts of one of them?
Expand Down Expand Up @@ -137,8 +146,8 @@ function compareUrl(leftPath: string, rightPath: string) {
}
}

// Must be the same
return 0;
// Path portions are the same, compare query strings
return defaultCompare(leftQuery, rightQuery);
}

function resolveSchema(schema: JsonSchemaType, reader: JsonSchemaReader): ResolvedJsonSchemaType {
Expand Down
36 changes: 36 additions & 0 deletions packages/typespec-autorest/test/sorting.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,42 @@ describe("typespec-autorest: OpenAPI output should be determinstic", () => {
]);
});

it("sorts x-ms-paths with query-only paths", () => {
const sorted = sortOpenAPIDocument({
swagger: "2.0",
info: {} as any,
paths: {},
"x-ms-paths": {
"?b=1": {},
"?a=1": {},
"?c=1": {},
},
});

deepStrictEqual(Object.keys(sorted["x-ms-paths"]!), ["?a=1", "?b=1", "?c=1"]);
});

it("sorts x-ms-paths with mixed path and query-only entries", () => {
const sorted = sortOpenAPIDocument({
swagger: "2.0",
info: {} as any,
paths: {},
"x-ms-paths": {
"/b?_overload=op1": {},
"?b=1": {},
"/a?_overload=op2": {},
"?a=1": {},
},
});

deepStrictEqual(Object.keys(sorted["x-ms-paths"]!), [
"?a=1",
"?b=1",
"/a?_overload=op2",
"/b?_overload=op1",
]);
});

it("header already in lexical order", async () => {
const res = await openApiFor(
`
Expand Down
Loading