diff --git a/common/changes/@cadl-lang/openapi3/fixOpenApiRefSafeName_2022-04-18-23-36.json b/common/changes/@cadl-lang/openapi3/fixOpenApiRefSafeName_2022-04-18-23-36.json new file mode 100644 index 00000000000..3e674c0f189 --- /dev/null +++ b/common/changes/@cadl-lang/openapi3/fixOpenApiRefSafeName_2022-04-18-23-36.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@cadl-lang/openapi3", + "comment": "Fix issue with OpenAPI emitter not sanitizing parameter names in reference identifiers", + "type": "patch" + } + ], + "packageName": "@cadl-lang/openapi3" +} \ No newline at end of file diff --git a/packages/openapi3/src/openapi.ts b/packages/openapi3/src/openapi.ts index 32b4b741437..99188be1463 100644 --- a/packages/openapi3/src/openapi.ts +++ b/packages/openapi3/src/openapi.ts @@ -613,9 +613,8 @@ function createOAPIEmitter(program: Program, options: OpenAPIEmitterOptions) { } // Try to shorten the type name to exclude the top-level service namespace - let baseKey = getRefSafeName(key); if (serviceNamespace && key.startsWith(serviceNamespace)) { - baseKey = key.substring(serviceNamespace.length + 1); + const baseKey = key.substring(serviceNamespace.length + 1); // If no parameter exists with the shortened name, use it, otherwise use the fully-qualified name if (!root.components.parameters[baseKey] || isQualifiedParamName) { @@ -623,7 +622,7 @@ function createOAPIEmitter(program: Program, options: OpenAPIEmitterOptions) { } } - return key; + return getRefSafeName(key); } function getSchemaForType(type: Type) { @@ -1210,7 +1209,7 @@ function isRefSafeName(name: string) { } function getRefSafeName(name: string) { - return name.replace(/^[A-Za-z0-9-_.]/g, "_"); + return name.replace(/[^A-Za-z0-9-_.]/g, "_"); } function prettierOutput(output: string) { diff --git a/packages/openapi3/test/test-openapi-output.ts b/packages/openapi3/test/test-openapi-output.ts index 8315c4901cb..1c0c8b5a6ea 100644 --- a/packages/openapi3/test/test-openapi-output.ts +++ b/packages/openapi3/test/test-openapi-output.ts @@ -937,4 +937,29 @@ describe("openapi3: extension decorator", () => { strictEqual(oapi.components.parameters.PetId.schema.format, "UUID"); strictEqual(oapi.components.parameters.PetId.schema.pattern, "^[a-zA-Z0-9-]{3,24}$"); }); + + it("correctly sanitizes parameter names", async () => { + const oapi = await openApiFor( + ` + model Pet extends Pet$Id { + name: string; + } + model Pet$Id { + @path + petId: string; + } + @route("/Pets") + namespace root { + @get() + op get(... Pet$Id): Pet; + } + ` + ); + ok(oapi.paths["/Pets/{petId}"].get); + strictEqual( + oapi.paths["/Pets/{petId}"].get.parameters[0]["$ref"], + "#/components/parameters/Pet_Id" + ); + strictEqual(oapi.components.parameters.Pet_Id.name, "petId"); + }); });