diff --git a/.changeset/olive-dots-sing.md b/.changeset/olive-dots-sing.md new file mode 100644 index 000000000..97610118a --- /dev/null +++ b/.changeset/olive-dots-sing.md @@ -0,0 +1,5 @@ +--- +"openapi-typescript": minor +--- + +Works around an issue where operation IDs containing the "#" character failed to generate teh correct type mappings diff --git a/packages/openapi-typescript/src/transform/path-item-object.ts b/packages/openapi-typescript/src/transform/path-item-object.ts index 2eb6a00d0..26c811d26 100644 --- a/packages/openapi-typescript/src/transform/path-item-object.ts +++ b/packages/openapi-typescript/src/transform/path-item-object.ts @@ -104,11 +104,11 @@ export default function transformPathItemObject( } // if operationId exists, move into an `operations` export and pass the reference in here else if (operationObject.operationId) { - operationType = oapiRef( - createRef(["operations", operationObject.operationId]), - ); + // workaround for issue caused by redocly ref parsing: https://github.com/drwpow/openapi-typescript/issues/1542 + const operationId = operationObject.operationId.replace(HASH_RE, "/"); + operationType = oapiRef(createRef(["operations", operationId])); injectOperationObject( - operationObject.operationId, + operationId, { ...operationObject, parameters: Object.values(keyedParameters) }, { ...options, path: createRef([options.path!, method]) }, ); @@ -132,3 +132,5 @@ export default function transformPathItemObject( return ts.factory.createTypeLiteralNode(type); } + +const HASH_RE = /#/g; diff --git a/packages/openapi-typescript/test/index.test.ts b/packages/openapi-typescript/test/index.test.ts index d94ae59e3..b7e8e7967 100644 --- a/packages/openapi-typescript/test/index.test.ts +++ b/packages/openapi-typescript/test/index.test.ts @@ -488,6 +488,84 @@ export type operations = Record;`, // options: DEFAULT_OPTIONS }, ], + + [ + "operations > # character is parsed correctly", + { + given: { + openapi: "3.1", + info: { title: "Test", version: "1.0" }, + paths: { + "/accounts": { + get: { + operationId: "Accounts#List", + responses: { + 200: { + description: "OK", + content: { + "application/json": { + schema: { type: "string" }, + }, + }, + }, + }, + }, + }, + }, + }, + want: `export interface paths { + "/accounts": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: operations["Accounts/List"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; +} +export type webhooks = Record; +export interface components { + schemas: never; + responses: never; + parameters: never; + requestBodies: never; + headers: never; + pathItems: never; +} +export type $defs = Record; +export interface operations { + "Accounts/List": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": string; + }; + }; + }; + }; +}`, + // options: DEFAULT_OPTIONS, + }, + ], [ "JSONSchema > $defs are respected", {