apple / apple/swift-openapi-generator
Support additional strongly-typed scalars
- Dominant language
- Swift
- Stars
- 2k
- Forks
- 182
- Avg merge
- 13h 28m
- Merged PRs (30d)
- 5
Description
Hello,
I was wondering if OpenAPI or the OpenAPI generator could define new scalar types.
New scalar types help disambiguating scalar values such as integers or strings by making them strongly typed: this is a user id, this is an ISO-8601 date, this is a number of seconds, this is an amount of cents. With strong typing, mixing apples and oranges is impossible.
OpenAPI has something that looks pretty much like this:
```yml
components:
schemas:
# A custom string scalar:
URL:
type: string
PhoneNumber:
type: object
properties:
localized_description:
type: string
# Not a string, but a URL:
url:
$ref: '#/components/schemas/URL'
required:
- localized_description
- url
```
But OpenAPI Generator imports them as their raw Swift type. For example:
```swift
// Generated
public enum Components {
public enum Schemas {
/// - Remark: Generated from `#/components/schemas/URL`.
public typealias URL = Swift.String
}
}
```
Somehow I was expecting `Components.Schemas.URL` to be generated as a `RawRepresentable` type, as below. I thought that the definition of `#/components/schemas/URL` was a sufficient hint for the desire of a custom type:
```swift
// My expectation
public enum Components {
public enum Schemas {
/// - Remark: Generated from `#/components/schemas/URL`.
public struct URL: Codable, Hashable, Sendable, RawRepresentable {
public var rawValue: String
public init(rawValue: String) {
self.rawValue = rawValue
}
public init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
try self.init(rawValue: container.decode(String.self))
}
public func encode(to encoder: any Encoder) throws {
var container = encoder.singleValueContainer()
try container.encode(rawValue)
}
}
}
}
```
I understand that OpenAPI supports a lot of features, such as string formats, that can turn a simple feature into a very complex beast.
I also understand that not everybody has a real or strong need for strongly-types scalars. They could *annoy* some users ("All those raw values 🙄").
My previous experience with strongly-types scalars was the Swift GraphQL library Apollo: [Custom Scalars](https://www.apollographql.com/docs/ios/custom-scalars/). By default, it imports custom scalars as their raw Swift representation (so the `URL` above with also be a typealias to `Swift.String`). But it allows the developer to provide a custom implementation. I was able to replace all those raw `String` and `Int` with [tagged values](https://github.com/pointfreeco/swift-tagged), with much happiness.
In the end, I wonder what is the opinion of the library maintainers on such a topic?
Contributor guide
Research direction
Start by reviewing how the generator currently turns the issue's OpenAPI scalar schemas into Swift typealiases such as Components.Schemas.URL. Compare that behavior with the proposed RawRepresentable shape and the Apollo custom-scalars approach, then define the configuration and compatibility decisions needed before implementation. Done should include an agreed design and corresponding generator coverage for custom scalar types.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- openapi, swift
- Domain
- api
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100