diff --git a/lib/csdl2openapi.js b/lib/csdl2openapi.js index e090c33d..1a64deea 100644 --- a/lib/csdl2openapi.js +++ b/lib/csdl2openapi.js @@ -38,6 +38,23 @@ const TITLE_SUFFIX = { "-update": " (for update)", }; +const SYSTEM_QUERY_OPTIONS = [ + "compute", + "expand", + "select", + "filter", + "search", + "count", + "orderby", + "skip", + "top", + "format", + "index", + "schemaversion", + "skiptoken", + "apply", +]; + /** * Construct an OpenAPI description from a CSDL document * @param {object} csdl CSDL document @@ -610,8 +627,8 @@ module.exports.csdl2openapi = function ( (byKey ? "entity from " : element.$Collection - ? "entities from " - : "") + + ? "entities from " + : "") + (level > 0 ? "related " : "") + name + (byKey ? " by key" : ""), @@ -1714,7 +1731,13 @@ module.exports.csdl2openapi = function ( type?.$UnderlyingType == "Edm.Stream" ) { param.in = "query"; - if (implicitAliases) { + if ( + implicitAliases && + csdl.$Version !== "2.0" && + SYSTEM_QUERY_OPTIONS.includes(p.$Name.toLowerCase()) + ) { + param.name = "@" + p.$Name; + } else if (implicitAliases) { param.name = p.$Name; } else { pathSegments.push(p.$Name + "=@" + p.$Name); @@ -1740,7 +1763,13 @@ module.exports.csdl2openapi = function ( pathSegments.push(p.$Name + "={" + p.$Name + "}"); param.in = "path"; } - param.name = p.$Name; + if ( + implicitAliases && + csdl.$Version !== "2.0" && + SYSTEM_QUERY_OPTIONS.includes(p.$Name.toLowerCase()) + ) + param.name = "@" + p.$Name; + else param.name = p.$Name; if ( !p.$Type || p.$Type === "Edm.String" || diff --git a/test/csdl2openapi.test.js b/test/csdl2openapi.test.js index b485c41f..2189fc9a 100644 --- a/test/csdl2openapi.test.js +++ b/test/csdl2openapi.test.js @@ -929,6 +929,75 @@ describe("Edge cases", function () { ); }); + it("function with @ parameter aliases", function () { + const csdl = { + $Version: "4.01", + $Reference: { + dummy: { + $Include: [{ $Namespace: "Org.OData.Core.V1", $Alias: "Core" }], + }, + }, + $EntityContainer: "model.Container", + model: { + $Alias: "this", + FavoritePhotos: [ + { + $Kind: "Function", + $Parameter: [ + { + $Name: "SKIP", + $Type: "Edm.Date", + $Collection: true, + "@Core.Description": "Dates to be skipped", + }, + { + $Name: "filter", + "@Core.Description": "Boolean expression to filter the result", + }, + ], + $ReturnType: {}, + }, + ], + Container: { + fav: { $Function: "this.FavoritePhotos" }, + }, + }, + }; + const expected = { + paths: { + "/fav": { + get: { + parameters: [ + { + name: "@SKIP", + in: "query", + required: true, + description: + "Dates to be skipped \nThis is a URL-encoded JSON array with items of type Edm.Date, see [Complex and Collection Literals](https://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part2-url-conventions.html#sec_ComplexandCollectionLiterals)", + schema: { type: "string" }, + example: "[]", + }, + { + name: "@filter", + in: "query", + required: true, + schema: { type: "string", pattern: "^'([^']|'')*'$" }, + description: + "Boolean expression to filter the result \nString value needs to be enclosed in single quotes", + }, + ], + summary: "Invoke function FavoritePhotos", + tags: ["Service Operations"], + }, + }, + }, + }; + const actual = csdl2openapi(csdl, { diagram: true }); + delete actual.paths["/$batch"]; + delete actual.paths["/fav"].get.responses; + assert.deepStrictEqual(actual.paths, expected.paths); + }); + it("return type with facets", function () { const csdl = { $EntityContainer: "this.Container",