Recently in a project I was using a spec which defined variables similar to below
servers:
- url: https://{environment}.example.com/api/{version}
description: Example service deployment.
variables:
environment:
description: Server environment.
default: prod
enum:
- prod
- staging
- dev
version:
default: v1
The generated code to create the default server URL was easy enough being able to utilise the default variable
let serverURL = try Servers.server1()
But when I wanted to use a different variable I noticed that the parameter was generated as a string and it didn't expose the other allowed values that were defined in the OpenAPI document. It generated the following code:
This meant usage needed to involve runtime checks whether the supplied variable was valid and if the OpenAPI document were to ever remove an option it could only be discovered at runtime.
let serverURL = try Servers.server1(environment: "stg") // might be a valid environment, might not
Looking into the OpenAPI spec for server templating and the implementation of the extension URL.init(validatingOpenAPIServerURL:variables:) I realised that the variables could very easily be represented by an enum in the generated code. By doing so it would also provide a compiler checked way to use a non-default variable.
Proposed solution
Server variables that only declare a default value should remain as strings, but if a variable declares the enum property should have a Swift enum generated to represent the values, allowing implementers to know the other possible values and have the compiler guarantee only an allowed value is used; currently this guarantee is at runtime.
Given the same configuration from the motivation, the Servers namespace (enum) would get generated to include enums for the variables.
/// Server URLs defined in the OpenAPI document.
internal enum Servers {
/// Server URL variables defined in the OpenAPI document.
internal enum Variables {
/// The variables for Server1 defined in the OpenAPI document.
internal enum Server1 {
/// Server environment.
///
/// The "environment" variable defined in the OpenAPI document. The default value is "prod".
internal enum Environment: Swift.String {
case prod
case staging
case dev
/// The default variable.
internal static var `default`: Environment {
return Environment.prod
}
}
}
}
/// Example service deployment.
///
/// - Parameters:
/// - environment: Server environment.
/// - version:
internal static func server1(
environment: Variables.Server1.Environment = Variables.Server1.Environment.default,
version: Swift.String = "v1"
) throws -> Foundation.URL {
try Foundation.URL(
validatingOpenAPIServerURL: "https://{environment}.example.com/api/{version}",
variables: [
.init(
name: "environment",
value: environment.rawValue
),
.init(
name: "version",
value: version
)
]
)
}
}
Motivation
Recently in a project I was using a spec which defined variables similar to below
The generated code to create the default server URL was easy enough being able to utilise the default variable
But when I wanted to use a different variable I noticed that the parameter was generated as a string and it didn't expose the other allowed values that were defined in the OpenAPI document. It generated the following code:
This meant usage needed to involve runtime checks whether the supplied variable was valid and if the OpenAPI document were to ever remove an option it could only be discovered at runtime.
Looking into the OpenAPI spec for server templating and the implementation of the extension
URL.init(validatingOpenAPIServerURL:variables:)
I realised that the variables could very easily be represented by an enum in the generated code. By doing so it would also provide a compiler checked way to use a non-default variable.Proposed solution
Server variables that only declare a default value should remain as strings, but if a variable declares the
enum
property should have a Swift enum generated to represent the values, allowing implementers to know the other possible values and have the compiler guarantee only an allowed value is used; currently this guarantee is at runtime.Given the same configuration from the motivation, the
Servers
namespace (enum) would get generated to include enums for the variables.Alternatives considered
No response
Additional information
No response