From e320614159edca800e3366d7ceab5c5dc7014e4d Mon Sep 17 00:00:00 2001 From: Eric Crosson Date: Mon, 23 Dec 2024 15:00:06 -0600 Subject: [PATCH] feat(openapi-generator): suggest resolution for unknown codec types The Problem ----------- If you try to import a codec from `io-ts-types` like this: ```typescript import { DateFromISOString} from 'io-ts-types/DateFromISOString'; ``` you will see an error like this: ``` node_modules/@api-ts/openapi-generator/dist/src/codec.js:287 if (init.type === 'Identifier' || init.type === 'MemberExpression') { ^ TypeError: Cannot read properties of null (reading 'type') ``` This is not a helpful error message, as it does not indicate 1. What went wrong? 2. What does the user need to do to fix it? Additional Context ------------------ Since codecs from `io-ts-types` are frequently used, @api-ts/openapi-generator ships with knowledge of `io-ts-types` codecs[^1]. However, these defaults only match against the user's code when the user imports from the top-level `io-ts-types` package, like this: ```typescript import { DateFromISOString} from 'io-ts-types'; ``` This Change ----------- This diff detects when @api-ts/openapi-generator encounters a codec for which it cannot determine encode/decode types. This happens when a codec is declared with `t.Type` instead of the io-ts combinators, which happens in `io-ts-types` and in some third-party modules. In this case, the generator will now print a message informing the user what went wrong, and provides a suggestion on how the user should resolve the issue: > [ERROR] Could not determine encode/decode types for codec 'MyCustomCodec' in '~/workspace/node_modules/my-custom-types/lib/MyCustomType.d.ts' > Consider defining a custom codec for this type. > > https://github.com/BitGo/api-ts/tree/master/packages/openapi-generator#4-defining-custom-codecs Additionally, when the path defining the codec comes from `io-ts-types`, the message is even more specific: > [ERROR] Could not determine encode/decode types for codec 'DateFromISOString' in '~/workspace/node_modules/io-ts-types/lib/DateFromISOString.d.ts' > It looks like this codec comes from io-ts-types. Try importing directly from io-ts-types instead: > > ``` > import { DateFromISOString } from 'io-ts-types'; > ``` Considerations -------------- I was not able to easily write any tests for this functionality, since our test harness does not currently handle failure cases and asserting against given error messages. [^1]: https://github.com/BitGo/api-ts/blob/b214578caa8272e8370025ae3ef6fd7bf45d514c/packages/openapi-generator/src/knownImports.ts#L334 --- packages/openapi-generator/src/cli.ts | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/packages/openapi-generator/src/cli.ts b/packages/openapi-generator/src/cli.ts index e7cc5a28..a1b64ab2 100644 --- a/packages/openapi-generator/src/cli.ts +++ b/packages/openapi-generator/src/cli.ts @@ -179,6 +179,33 @@ const app = command({ } const [newSourceFile, init, comment] = initE.right; + if (init === null) { + console.log({ ref }); + let errorMessage = `Could not determine encode/decode types for codec '${ref.name}' in '${ref.location}'`; + if (ref.location.includes('/node_modules/io-ts-types/')) { + errorMessage += ` + It looks like this codec comes from io-ts-types. Try importing directly from io-ts-types instead: + + \`\`\` + import { ${ref.name} } from 'io-ts-types'; + \`\`\` + `; + } else { + errorMessage += ` + Consider defining a custom codec for this type. + + https://github.com/BitGo/api-ts/tree/master/packages/openapi-generator#4-defining-custom-codecs + `; + } + logError( + errorMessage + .split('\n') + .map((line) => line.trimStart()) + .join('\n'), + ); + process.exit(1); + } + const codecE = parseCodecInitializer(project, newSourceFile, init); if (E.isLeft(codecE)) { logError(