This is an api generated from a OpenAPI 3.0 spec with SwagGen
Each operation lives under the {{ options.name }}
namespace and within an optional tag: {{ options.name }}(.tagName).operationId
. If an operation doesn't have an operationId one will be generated from the path and method.
Each operation has a nested Request
and a Response
, as well as a static service
property
This is the struct that contains the static information about an operation including it's id, tag, method, pre-modified path, and authorization requirements. It has a generic ResponseType
type which maps to the Response
type.
You shouldn't really need to interact with this service type.
Each request is a subclass of APIRequest
and has an init
with a body param if it has a body, and a options
struct for other url and path parameters. There is also a convenience init for passing parameters directly.
The options
and body
structs are both mutable so they can be modified before actually sending the request.
The response is an enum of all the possible responses the request can return. it also contains getters for the statusCode
, whether it was successful
, and the actual decoded optional success
response. If the operation only has one type of failure type there is also an optional failure
type.
Models that are sent and returned from the API are {% if options.mutableModels %}mutable{% else %}immutable{% endif %} classes. Each model is Equatable
and Codable
.
Required
properties are non optional and non-required are optional
All properties can be passed into the initializer, with required
properties being mandatory.
If a model has additionalProperties
it will have a subscript to access these by string
The APIClient
is used to encode, authorize, send, monitor, and decode the requests. There is a APIClient.default
that uses the default baseURL
otherwise a custom one can be initialized:
public init(baseURL: String, sessionManager: SessionManager = .default, defaultHeaders: [String: String] = [:], behaviours: [RequestBehaviour] = [])
baseURL
: The base url that every requestpath
will be appended tobehaviours
: A list of Request Behaviours to add to every requestsessionManager
: AnAlamofire.SessionManager
that can be customizeddefaultHeaders
: Headers that will be applied to every requestdecodingQueue
: TheDispatchQueue
to decode responses on
To make a request first initialize a Request and then pass it to makeRequest
. The complete
closure will be called with an APIResponse
func makeRequest<T>(_ request: APIRequest<T>, behaviours: [RequestBehaviour] = [], queue: DispatchQueue = DispatchQueue.main, complete: @escaping (APIResponse<T>) -> Void) -> Request? {
Example request (that is not neccessarily in this api):
let getUserRequest = {{ options.name }}.User.GetUser.Request(id: 123)
let apiClient = APIClient.default
apiClient.makeRequest(getUserRequest) { apiResponse in
switch apiResponse {
case .result(let apiResponseValue):
if let user = apiResponseValue.success {
print("GetUser returned user \(user)")
} else {
print("GetUser returned \(apiResponseValue)")
}
case .error(let apiError):
print("GetUser failed with \(apiError)")
}
}
Each Request also has a makeRequest
convenience function that uses {{ options.name }}.default
.
The APIResponse
that gets passed to the completion closure contains the following properties:
request
: The original requestresult
: AResult
type either containing anAPIClientError
or the Response of the requesturlRequest
: TheURLRequest
used to send the requesturlResponse
: TheHTTPURLResponse
that was returned by the requestdata
: TheData
returned by the request.timeline
: TheAlamofire.Timeline
of the request which contains timing information.
Only JSON requests and responses are supported. These are encoded and decoded by JSONEncoder
and JSONDecoder
respectively, using Swift's Codable
apis.
There are some options to control how invalid JSON is handled when decoding and these are available as static properties on {{ options.name }}
:
safeOptionalDecoding
: Whether to discard any errors when decoding optional properties. Defaults totrue
.safeArrayDecoding
: Whether to remove invalid elements instead of throwing when decoding arrays. Defaults totrue
.
Dates are encoded and decoded differently according to the swagger date format. They use different DateFormatter
's that you can set.
date-time
DateTime.dateEncodingFormatter
: defaults toyyyy-MM-dd'T'HH:mm:ss.Z
DateTime.dateDecodingFormatters
: an array of date formatters. The first one to decode successfully will be used
date
DateDay.dateFormatter
: defaults toyyyy-MM-dd
This is error enum that APIResponse.result
may contain:
public enum APIClientError: Error {
case unexpectedStatusCode(statusCode: Int, data: Data)
case decodingError(DecodingError)
case requestEncodingError(String)
case validationError(String)
case networkError(Error)
case unknownError(Error)
}
Request behaviours are used to modify, authorize, monitor or respond to requests. They can be added to the APIClient.behaviours
for all requests, or they can passed into makeRequest
for just that single request.
RequestBehaviour
is a protocol you can conform to with each function being optional. As the behaviours must work across multiple different request types, they only have access to a typed erased AnyRequest
.
public protocol RequestBehaviour {
/// runs first and allows the requests to be modified. If modifying asynchronously use validate
func modifyRequest(request: AnyRequest, urlRequest: URLRequest) -> URLRequest
/// validates and modifies the request. complete must be called with either .success or .fail
func validate(request: AnyRequest, urlRequest: URLRequest, complete: @escaping (RequestValidationResult) -> Void)
/// called before request is sent
func beforeSend(request: AnyRequest)
/// called when request successfuly returns a 200 range response
func onSuccess(request: AnyRequest, result: Any)
/// called when request fails with an error. This will not be called if the request returns a known response even if the a status code is out of the 200 range
func onFailure(request: AnyRequest, error: APIClientError)
/// called if the request recieves a network response. This is not called if request fails validation or encoding
func onResponse(request: AnyRequest, response: AnyResponse)
}
Each request has an optional securityRequirement
. You can create a RequestBehaviour
that checks this requirement and adds some form of authorization (usually via headers) in validate
or modifyRequest
. An alternative way is to set the APIClient.defaultHeaders
which applies to all requests.
To add support for a specific asynchronous library, just add an extension on APIClient
and add a function that wraps the makeRequest
function and converts from a closure based syntax to returning the object of choice (stream, future...ect)
{% for model in schemas %}
- {{ model.type }} {% endfor %}
{% for operationTag in operationsByTag %} {% if operationTag.name != "" %}
- {{ options.name }}.{{ options.tagPrefix }}{{ operationTag.name|upperCamelCase }}{{ options.tagSuffix }}
{% for operation in operationTag.operations %}
- {{ operation.type }}: {{ operation.method }}
{{ operation.path | lowercase }}
{% endfor %} {% else %} {% for operation in operationTag.operations %}
- {{ operation.type }}: {{ operation.method }}
- {{ options.name }}.{{ operation.type }}: {{ operation.method }}
{{ operation.path | lowercase }}
{% endfor %} {% endif %} {% endfor %}