Closed CraigSiemens closed 4 months ago
Hi @CraigSiemens,
thanks for the detailed writeup.
We've discussed this a bit before, see:
The TL;DR is that we're intentionally not providing customizable normalization names, because it's relatively subjective, and every change would be a breaking change, however we're already post-1.0.
The most likely solution, if any, would be #112, but even that needs to be motivated more.
In your case, you can solve both problems by writing a small CLI in Swift that uses OpenAPIKit to read the OpenAPI document, make the updates to operationId and parameter names, and emits a fixed-up copy. The output document is what you then would use with Swift OpenAPI Generator.
I'll close this issue as a duplicate, as we're already tracking this topic in other issues, where we can keep discussing this 🙂
Motivation
Generating function names based on the
operationId
andparameters.name
can result in some difficult to read and use function and property names, respectively.The following examples are from generating a client using the App Store Connect API OpenAPI spec.
operationId
betaTesters-get_collection
becomes the function and operation typebetaTesters_hyphen_get_collection
.This is partially due to the OpenAPI spec supporting virtually any string and only providing a recommendation.
parameters.name
filter[id]
becomes the propertyfilter_lbrack_email_rbrack_
This is due to square brackets being used to indicate query fields that accept an array of values. These may need to be differentiated from another
filterId
containing the same letters but can only contain a single value.Proposed solution
The configuration file could be extended to contain keys for defining the naming strategy to apply to the different fields. The term "strategy" is taken from
JSONEncoder/Decoder
since this is also for converting from a string representation to Swift.These are just an initial idea, they may be too simple/complicated/limiting/flexible to handle cases I'm unaware of.
Transforms
There could be a common set of
Transform
types that can be used for both the operation and parameter names. The implementation of each transform would be responsible for taking a string, applying some changes to it, then returning the updated string. That would allow multiple transforms to be composed to apply more complex modifications. Each transform would be represented as a YAML map where it has a single key, the name of the transform, and a value, the options needed by that transform. The options could be empty, a string, list, or map depending on what the transform requires as input.Here is a possible list of transform types that could be supported.
replaceOccurrences
: replaces all occurrences of a string with another stringtarget
(required): a string: The string to replacereplacement
(required): a string: The string that will replace `target.rename
: maps an exact match of the string to another string. Useful in cases where an id/path may be a substring of the id/path in other operations soreplaceOccurrences
would apply to more operations than is wanted.target
(required): a string: The string to replacereplacement
(required): a string: The string that will replace `target.changeCase
:source
(required): a string: the case to use to split the source value into individual wordscamelCase
snakeCase
destination
(required): a string: the case to apply to the individual wordscamelCase
:snakeCase
operationId
The configuration would have a new top-level key
operationNamingStrategy
.operationNamingStrategy
(optional)source
(optional): a string: The value from the spec to use for generating the operation name.operationId
(default): uses the operation id if present, otherwise usespath
.path
: always uses thepath
, ignoring theoperationId
.transforms
(optional): an array of objects: Transform(s) to apply to the source value before it is sanitized usingString.safeForSwiftCode
. Transforms are applied in the order defined. Each type of transform can be used multiple times depending on the requirements. When not set or empty it is the same as the current behaviour.Example
When applied to the string
betaTesters-get_collection
, the result would be the following.betaTesters-getCollection
betaTesters_getCollection
parameters.name
The configuration would have a new top-level key
parameterNamingStrategy
.parameterNamingStrategy
(optional)transforms
(optional): an array of objects: Transform(s) to apply to the source value before it is sanitized usingString.safeForSwiftCode
. Transforms are applied in the order defined. Each type of transform can be used multiple times depending on the requirements. When not set or empty it is the same as the current behaviour.pluralizeArrays
filter[]
->filters
filter[id]
->filterIds
Example
When applied to the string
filter[id]
, the result would be the following.filter_id]
filter_id
Alternatives considered
No response
Additional information
No response