-
Notifications
You must be signed in to change notification settings - Fork 125
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support additional strongly-typed scalars #375
Comments
Hi @groue, thanks for opening this interesting topic. First, let me provide some initial context about the lines drawn between the OpenAPI specification, the generator, and Swift.
All of the constraints above are defined by OpenAPI to constrain which values are successfully decoded and encoded, so that if you send a malformed string to a client expecting a However, from my understanding of your question, you're not as concerned with how a value is encoded/decoded, but whether the generated code allows different typealiases of e.g. String to be used interchangeably. It's a good question, I personally haven't thought about this area very much yet, how about you, @simonjbeaumont? There are a few ways this could go:
As you can see, this is a pretty open-ended topic, so I encourage everyone to chime in and let's discuss here what could be done. |
Yes, @czechboy0, this is exact. The topic of formats is very interesting as well, and it looks slightly related, but indeed this is a different track.
There has been multiple attempts (1, 2, 3, etc) at pitching related ideas on the Swift forums, without any success so far. The desired feature set is not quite clear, to be honest. A good userland library with good ergonomics is swift-tagged (which is not based on typealiases, but instead defines new types that behave pretty much like their raw value). I'm not sure typealiases will ever change their behavior. Today, So I'm not sure discussing typealiases on Swift Evolution can actually be fruitful.
Yes, this is something that I find interesting. The intent behind a The OpenAPI Generator generates public types for those refs ( In this context, I'd say that it's not too odd to help developers turn refs for scalar types into dedicated I'll have a closer look.
I'm positive there is an interest for wrappers even for freely formatted values (
All right, so let's not do this.
Yes, I certainly do this already. The types generated by OpenAPI generator are not quite made for public consumption. And OpenAPI can not express all constraints that distinguish valid from invalid payloads. It is certainly the role of some app layer to "translate" raw decoded payload to properly-designed models. This is frequently a lot of boilerplate, but certainly not the kind of boilerplate I'd complain about.
Yes :-) |
Oh absolutely not, we explicitly discourage one party to publish the generated types for another party. Folks should generally just use the generated code as an implementation detail: https://swiftpackageindex.com/apple/swift-openapi-generator/0.3.4/documentation/swift-openapi-generator/api-stability-of-generated-code |
One more :-) https://forums.swift.org/t/how-about-subtypealias-farenheit-double/68513 |
Isn't the way the value is decoded is just as important here right? Being certain that a value is a valid strongly-typed scalar is one of the reasons for using this. You want the value to be decoded as
Any new thoughts or updates on this since november? It would be great to support this. |
Narrowing the discussion to When we try to generalise it we start asking questions about the target type, e.g. for A pragmatic middle ground we could consider is to do validation on as whatever formats are well specified in the OpenAPI and JSON Schema specifications and constrain generating a strongly-typed property for just some.
To be transparent, @teameh, the issue is open because we acknowledge that we likely need improvements on this area, but it's not something we're actively staffing right now. |
Check. Thanks. I think there's also a distinction to be made between Swift native supported types like
Got it. Anything I can do help here?
Is there something that is stopping us implementing this now? 😃 or am I too hasty? |
I for one would really welcome "strongly typed scalars" or something similar. My uses case is "enum-like" types. In these cases a Could we somehow build a solution that does not (directly) rely on format (which seems to be subject to change) I know it has not been done so far, and it might open the door for "too much" configurability, but one way would be to allow opting in or configuring this via vendor-extensions. Taking the example of the initial request. components:
schemas:
# A custom string scalar:
URL:
type: string
format: uri
# a few variants
x-swift-open-api-generator-custom-format: true # generate a new raw representable type
x-swift-open-api-generator-substitute-type: Foundation.URL # instead of generating String i can "swap in" my own type (obviously it must be importable) |
I agree there is demand for improvements around typed scalars, from URL to values constrained to a specific regular expression. It's useful for us to discuss this here, but at some point it'd be good for someone to drive a concrete proposal. Note that I expect this to be split into a few smaller pieces of work, one proposal doesn't have to solve it all - but at the same time, we should at least have an idea of which direction we'd like to go overall here. We have not used vendor extensions yet, but I'm open to that idea as well (might be in addition to the other ideas, doesn't have to be a replacement). I think that would also play nicely with #634, as one could take a language-agnostic OpenAPI doc and overlay the customization in a Swift-specific OpenAPI overlay. All of these are just ideas though, thrown out here for further discussion 🙂 |
Im happy to come up with a official proposal, but my timeline for this would be at the soonest in two months. That being said i do think the "type substitution" approach has a lot of potential. Our API for instance is vends geo-json https://datatracker.ietf.org/doc/html/rfc7946#section-1.4 While this has a well-defined format i think "inlining" this into our definition would bloat our spec a bit, and we do already have a type (from a library) to handle the parsing. Right now we are not using the open-api-generator for these endpoints because of this. If we could substitute the type we could actually use the type from our library. components:
schemas:
GeoJSON:
{} # In our case allowing everything would be acceptable, this mostly serves as a placeholder
x-swift-open-api-generator-substitute-type: GeoJSONLibrary.GeoJSON This would also avoid having to keep the generator in sync with the various formats (differing between versions) and put the decision/responsibility on the user. |
Thank you @simonbility for describing your use case in depth. The ask sounds very reasonable. Let us discuss and think about this a bit and get back to you about how we proceed. |
While we have yet to do this, we've been chatting about extensions, e.g. |
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:
But OpenAPI Generator imports them as their raw Swift type. For example:
Somehow I was expecting
Components.Schemas.URL
to be generated as aRawRepresentable
type, as below. I thought that the definition of#/components/schemas/URL
was a sufficient hint for the desire of a custom type: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. By default, it imports custom scalars as their raw Swift representation (so the
URL
above with also be a typealias toSwift.String
). But it allows the developer to provide a custom implementation. I was able to replace all those rawString
andInt
with tagged values, with much happiness.In the end, I wonder what is the opinion of the library maintainers on such a topic?
The text was updated successfully, but these errors were encountered: