From fa0154547372837ce64ac7a359d6adbbbdeecf3c Mon Sep 17 00:00:00 2001 From: simonbility Date: Tue, 27 May 2025 05:58:40 +0200 Subject: [PATCH] Add TypeOverrides Proposal --- .../Documentation.docc/Proposals/Proposals.md | 1 + .../Documentation.docc/Proposals/SOAR-0014.md | 133 ++++++++++++++++++ 2 files changed, 134 insertions(+) create mode 100644 Sources/swift-openapi-generator/Documentation.docc/Proposals/SOAR-0014.md diff --git a/Sources/swift-openapi-generator/Documentation.docc/Proposals/Proposals.md b/Sources/swift-openapi-generator/Documentation.docc/Proposals/Proposals.md index bdaff6a5..c8a91e34 100644 --- a/Sources/swift-openapi-generator/Documentation.docc/Proposals/Proposals.md +++ b/Sources/swift-openapi-generator/Documentation.docc/Proposals/Proposals.md @@ -55,3 +55,4 @@ If you have any questions, tag [Honza Dvorsky](https://github.com/czechboy0) or - - - +- diff --git a/Sources/swift-openapi-generator/Documentation.docc/Proposals/SOAR-0014.md b/Sources/swift-openapi-generator/Documentation.docc/Proposals/SOAR-0014.md new file mode 100644 index 00000000..6a26123a --- /dev/null +++ b/Sources/swift-openapi-generator/Documentation.docc/Proposals/SOAR-0014.md @@ -0,0 +1,133 @@ +# SOAR-0014: Support Type Overrides + +Allow using user-defined types instead of generated ones + +## Overview + +- Proposal: SOAR-0014 +- Author(s): [simonbility](https://github.com/simonbility) +- Status: **Awaiting Review** +- Issue: [apple/swift-openapi-generator#375](https://github.com/apple/swift-openapi-generator/issues/375) +- Implementation: + - [apple/swift-openapi-generator#764](https://github.com/apple/swift-openapi-generator/pull/764) +- Affected components: + - generator + +### Introduction + +The goal of this proposal is to allow users to specify custom types for generated. This will enable users to use their own types instead of the default generated ones, allowing for greater flexibility. + +### Motivation + +This proposal would enable more flexibility in the generated code. +Some usecases include: +- Using custom types that are already defined in the user's codebase or even coming from a third party library, instead of generating new ones. +- workaround missing support for `format` for strings +- Implement custom validation/encoding/decoding logic that cannot be expressed using the OpenAPI spec + +This is intended as a "escape hatch" for use-cases that (currently) cannot be expressed. +Using this comes with the risk of user-provided types not being compliant with the original OpenAPI spec. + + +### Proposed solution + +The proposed solution is to allow specifying typeOverrides using a new configuration option named `typeOverrides`. +This is only supported for schemas defined in the `components.schemas` section of a OpenAPI document. + +### Example +A current limitiation is string formats are not directly supported by the generator. (for example, `uuid` is not supported) + +With this proposal this can be worked around with with the following approach (This proposal does not preclude extending support for formats in the future): + +Given schemas defined in the OpenAPI document like this: +```yaml + components: + schemas: + UUID: + type: string + format: uuid +``` + +Adding typeOverrides like this in the configuration + +```diff ++ typeOverrides: ++ schemas: ++ UUID: Foundation.UUID +``` + +Will affect the generated code in the following way: +```diff + /// Types generated from the `#/components/schemas` section of the OpenAPI document. + package enum Schemas { + /// - Remark: Generated from `#/components/schemas/UUID`. +- package typealias Uuid = Swift.String ++ package typealias Uuid = Foundation.UUID + } +``` + +### Detailed design + +In the configuration file a new `typeOverrides` option is supported. +It contains mapping from the original name (as defined in the OpenAPI document) to a override type name to use instead of the generated name. + +The mapping is evaluated relative to `#/components/schemas` + +So defining overrides like this: + +```diff +typeOverrides: + schemas: + OriginalName: NewName +``` + +will replace the generated type for `#/components/schemas/OriginalName` with `NewName`. + +Its in the users responsibility to ensure that the type is valid and available. +It must conform to `Codable`, `Hashable` and `Sendable` + + +### API stability + +While this proposal does affect the generated code, it requires the user to explicitly opt-in to using the `typeOverrides` configuration option. + +This is interpreted as a "strong enough" signal of the user to opt into this behaviour, to justify NOT introducing a feature-flag or considering this a breaking change. + + +### Future directions + +The implementation could potentially be extended to support inline defined properties as well. +This could be done by supporting "Paths" instead of names in the mapping. + +For example with the following schema. +```yaml + components: + schemas: + User: + properties: + id: + type: string + format: uuid +``` + +This configuration could be used to override the type of `id`: +```yaml +typeOverrides: + schemas: + 'User/id': Foundation.UUID +``` + + +### Alternatives considered +An alternative to the mapping defined in the configuration file is to use a vendor extension (for instance `x-swift-open-api-override-type`) in the OpenAPI document itself. + +```yaml +... +components: + schemas: + UUID: + type: string + x-swift-open-api-override-type: Foundation.UUID +``` + +The current proposal using the configuration file was preferred because it does not rely on modifying the OpenAPI document itself, which is not always possible/straightforward when its provided by a third-party.