This repository has been archived by the owner on Feb 15, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: update Models templates to always be public
When using the 'nonPublicApi' flag in OpenAPI generator, all clients and models are made internal by default. However, we wish to have the clients made internal but the models public, to get the most out of the generated code, while keeping the interface consistent, allowing to expose only the method we see fit through ImmutableX instead of relying on devs using the clients directly.
- Loading branch information
1 parent
38d81bc
commit 890545d
Showing
6 changed files
with
310 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
// Models.swift | ||
// | ||
// Generated by openapi-generator | ||
// https://openapi-generator.tech | ||
// | ||
|
||
import Foundation{{#useAlamofire}} | ||
import Alamofire{{/useAlamofire}} | ||
|
||
protocol JSONEncodable { | ||
func encodeToJSON() -> Any | ||
} | ||
|
||
/// An enum where the last case value can be used as a default catch-all. | ||
protocol CaseIterableDefaultsLast: Decodable & CaseIterable & RawRepresentable | ||
where RawValue: Decodable, AllCases: BidirectionalCollection {} | ||
|
||
extension CaseIterableDefaultsLast { | ||
/// Initializes an enum such that if a known raw value is found, then it is decoded. | ||
/// Otherwise the last case is used. | ||
/// - Parameter decoder: A decoder. | ||
public init(from decoder: Decoder) throws { | ||
if let value = try Self(rawValue: decoder.singleValueContainer().decode(RawValue.self)) { | ||
self = value | ||
} else if let lastValue = Self.allCases.last { | ||
self = lastValue | ||
} else { | ||
throw DecodingError.valueNotFound( | ||
Self.Type.self, | ||
.init(codingPath: decoder.codingPath, debugDescription: "CaseIterableDefaultsLast") | ||
) | ||
} | ||
} | ||
} | ||
|
||
/// A flexible type that can be encoded (`.encodeNull` or `.encodeValue`) | ||
/// or not encoded (`.encodeNothing`). Intended for request payloads. | ||
public enum NullEncodable<Wrapped: Hashable>: Hashable { | ||
case encodeNothing | ||
case encodeNull | ||
case encodeValue(Wrapped) | ||
} | ||
|
||
extension NullEncodable: Codable where Wrapped: Codable { | ||
public init(from decoder: Decoder) throws { | ||
let container = try decoder.singleValueContainer() | ||
if let value = try? container.decode(Wrapped.self) { | ||
self = .encodeValue(value) | ||
} else if container.decodeNil() { | ||
self = .encodeNull | ||
} else { | ||
self = .encodeNothing | ||
} | ||
} | ||
|
||
public func encode(to encoder: Encoder) throws { | ||
var container = encoder.singleValueContainer() | ||
switch self { | ||
case .encodeNothing: return | ||
case .encodeNull: try container.encodeNil() | ||
case .encodeValue(let wrapped): try container.encode(wrapped) | ||
} | ||
} | ||
} | ||
|
||
public enum ErrorResponse: Error { | ||
case error(Int, Data?, URLResponse?, Error) | ||
} | ||
|
||
public enum DownloadException: Error { | ||
case responseDataMissing | ||
case responseFailed | ||
case requestMissing | ||
case requestMissingPath | ||
case requestMissingURL | ||
} | ||
|
||
public enum DecodableRequestBuilderError: Error { | ||
case emptyDataResponse | ||
case nilHTTPResponse | ||
case unsuccessfulHTTPStatusCode | ||
case jsonDecoding(DecodingError) | ||
case generalError(Error) | ||
} | ||
|
||
{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class Response<T> { | ||
public let statusCode: Int | ||
public let header: [String: String] | ||
public let body: T | ||
public init(statusCode: Int, header: [String: String], body: T) { | ||
self.statusCode = statusCode | ||
self.header = header | ||
self.body = body | ||
} | ||
|
||
public convenience init(response: HTTPURLResponse, body: T) { | ||
let rawHeader = response.allHeaderFields | ||
var header = [String: String]() | ||
for (key, value) in rawHeader { | ||
if let key = key.base as? String, let value = value as? String { | ||
header[key] = value | ||
} | ||
} | ||
self.init(statusCode: response.statusCode, header: header, body: body) | ||
} | ||
} | ||
|
||
public final class RequestTask{{#useAsyncAwait}}: @unchecked Sendable{{/useAsyncAwait}} { | ||
private var lock = NSRecursiveLock() | ||
{{#useAlamofire}} | ||
private var request: Request? | ||
|
||
internal func set(request: Request) { | ||
lock.lock() | ||
defer { lock.unlock() } | ||
self.request = request | ||
} | ||
|
||
public func cancel() { | ||
lock.lock() | ||
defer { lock.unlock() } | ||
request?.cancel() | ||
request = nil | ||
} | ||
{{/useAlamofire}} | ||
{{^useAlamofire}} | ||
private var task: URLSessionTask? | ||
|
||
internal func set(task: URLSessionTask) { | ||
lock.lock() | ||
defer { lock.unlock() } | ||
self.task = task | ||
} | ||
|
||
public func cancel() { | ||
lock.lock() | ||
defer { lock.unlock() } | ||
task?.cancel() | ||
task = nil | ||
} | ||
{{/useAlamofire}} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
{{#models}}{{#model}}// | ||
// {{classname}}.swift | ||
// | ||
// Generated by openapi-generator | ||
// https://openapi-generator.tech | ||
// | ||
|
||
import Foundation | ||
#if canImport(AnyCodable) | ||
import AnyCodable | ||
#endif{{#useVapor}} | ||
import Vapor{{/useVapor}} | ||
{{#swiftUseApiNamespace}} | ||
|
||
@available(*, deprecated, renamed: "{{projectName}}API.{{classname}}") | ||
public typealias {{classname}} = {{projectName}}API.{{classname}} | ||
|
||
extension {{projectName}}API { | ||
{{/swiftUseApiNamespace}} | ||
{{#description}} | ||
|
||
/** {{.}} */{{/description}}{{#isDeprecated}} | ||
@available(*, deprecated, message: "This schema is deprecated."){{/isDeprecated}}{{#vendorExtensions.x-is-one-of-interface}} | ||
{{> modelOneOf}}{{/vendorExtensions.x-is-one-of-interface}}{{^vendorExtensions.x-is-one-of-interface}}{{#isArray}} | ||
{{> modelArray}}{{/isArray}}{{^isArray}}{{#isEnum}} | ||
{{> modelEnum}}{{/isEnum}}{{^isEnum}} | ||
{{> modelObject}}{{/isEnum}}{{/isArray}}{{/vendorExtensions.x-is-one-of-interface}}{{/model}}{{/models}} | ||
{{#swiftUseApiNamespace}} | ||
} | ||
{{/swiftUseApiNamespace}} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
public typealias {{classname}} = {{parent}} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
public enum {{classname}}: {{dataType}}, {{#useVapor}}Content, Hashable{{/useVapor}}{{^useVapor}}Codable{{^isString}}{{^isInteger}}{{^isFloat}}{{^isDouble}}, JSONEncodable{{/isDouble}}{{/isFloat}}{{/isInteger}}{{/isString}}{{/useVapor}}, CaseIterable{{#enumUnknownDefaultCase}}{{#isInteger}}, CaseIterableDefaultsLast{{/isInteger}}{{#isFloat}}, CaseIterableDefaultsLast{{/isFloat}}{{#isDouble}}, CaseIterableDefaultsLast{{/isDouble}}{{#isString}}, CaseIterableDefaultsLast{{/isString}}{{/enumUnknownDefaultCase}} { | ||
{{#allowableValues}} | ||
{{#enumVars}} | ||
case {{{name}}} = {{{value}}} | ||
{{/enumVars}} | ||
{{/allowableValues}} | ||
} |
7 changes: 7 additions & 0 deletions
7
.openapi-generator/templates/swift5/modelInlineEnumDeclaration.mustache
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
public enum {{enumName}}: {{^isContainer}}{{dataType}}{{/isContainer}}{{#isContainer}}String{{/isContainer}}, {{#useVapor}}Content, Hashable{{/useVapor}}{{^useVapor}}Codable{{^isContainer}}{{^isString}}{{^isInteger}}{{^isFloat}}{{^isDouble}}, JSONEncodable{{/isDouble}}{{/isFloat}}{{/isInteger}}{{/isString}}{{/isContainer}}{{/useVapor}}, CaseIterable{{#enumUnknownDefaultCase}}{{#isInteger}}, CaseIterableDefaultsLast{{/isInteger}}{{#isFloat}}, CaseIterableDefaultsLast{{/isFloat}}{{#isDouble}}, CaseIterableDefaultsLast{{/isDouble}}{{#isString}}, CaseIterableDefaultsLast{{/isString}}{{#isContainer}}, CaseIterableDefaultsLast{{/isContainer}}{{/enumUnknownDefaultCase}} { | ||
{{#allowableValues}} | ||
{{#enumVars}} | ||
case {{{name}}} = {{{value}}} | ||
{{/enumVars}} | ||
{{/allowableValues}} | ||
} |
122 changes: 122 additions & 0 deletions
122
.openapi-generator/templates/swift5/modelObject.mustache
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
{{^objcCompatible}}public {{#useClasses}}final class{{/useClasses}}{{^useClasses}}struct{{/useClasses}} {{{classname}}}: {{#useVapor}}Content{{/useVapor}}{{^useVapor}}Codable{{#useJsonEncodable}}, JSONEncodable{{/useJsonEncodable}}{{/useVapor}}{{#vendorExtensions.x-swift-hashable}}, Hashable{{/vendorExtensions.x-swift-hashable}} { | ||
{{/objcCompatible}}{{#objcCompatible}}@objc public class {{classname}}: NSObject, Codable{{#useJsonEncodable}}, JSONEncodable{{/useJsonEncodable}} { | ||
{{/objcCompatible}} | ||
|
||
{{#allVars}} | ||
{{#isEnum}} | ||
{{> modelInlineEnumDeclaration}} | ||
{{/isEnum}} | ||
{{/allVars}} | ||
{{#allVars}} | ||
{{#isEnum}} | ||
{{#description}}/** {{{.}}} */ | ||
{{/description}}{{#deprecated}}@available(*, deprecated, message: "This property is deprecated.") | ||
{{/deprecated}}public {{#readonlyProperties}}private(set) {{/readonlyProperties}}var {{{name}}}: {{#vendorExtensions.x-null-encodable}}NullEncodable<{{{datatypeWithEnum}}}>{{/vendorExtensions.x-null-encodable}}{{^vendorExtensions.x-null-encodable}}{{{datatypeWithEnum}}}{{#required}}{{#isNullable}}?{{/isNullable}}{{/required}}{{^required}}?{{/required}}{{/vendorExtensions.x-null-encodable}}{{#defaultValue}} = {{#vendorExtensions.x-null-encodable}}{{{vendorExtensions.x-null-encodable-default-value}}}{{/vendorExtensions.x-null-encodable}}{{^vendorExtensions.x-null-encodable}}{{{.}}}{{/vendorExtensions.x-null-encodable}}{{/defaultValue}} | ||
{{/isEnum}} | ||
{{^isEnum}} | ||
{{#description}}/** {{{.}}} */ | ||
{{/description}}{{#deprecated}}@available(*, deprecated, message: "This property is deprecated.") | ||
{{/deprecated}}public {{#readonlyProperties}}private(set) {{/readonlyProperties}}var {{{name}}}: {{#vendorExtensions.x-null-encodable}}NullEncodable<{{{datatype}}}>{{/vendorExtensions.x-null-encodable}}{{^vendorExtensions.x-null-encodable}}{{{datatype}}}{{#required}}{{#isNullable}}?{{/isNullable}}{{/required}}{{^required}}?{{/required}}{{/vendorExtensions.x-null-encodable}}{{#defaultValue}} = {{#vendorExtensions.x-null-encodable}}{{{vendorExtensions.x-null-encodable-default-value}}}{{/vendorExtensions.x-null-encodable}}{{^vendorExtensions.x-null-encodable}}{{{.}}}{{/vendorExtensions.x-null-encodable}}{{/defaultValue}} | ||
{{#objcCompatible}} | ||
{{#vendorExtensions.x-swift-optional-scalar}} | ||
public var {{{name}}}Num: NSNumber? { | ||
get { | ||
{{^vendorExtensions.x-null-encodable}} | ||
return {{{name}}} as NSNumber? | ||
{{/vendorExtensions.x-null-encodable}} | ||
{{#vendorExtensions.x-null-encodable}} | ||
if case .encodeValue(let value) = {{name}} { | ||
return value as NSNumber? | ||
} else { | ||
return nil | ||
} | ||
{{/vendorExtensions.x-null-encodable}} | ||
} | ||
} | ||
{{/vendorExtensions.x-swift-optional-scalar}} | ||
{{/objcCompatible}} | ||
{{/isEnum}} | ||
{{/allVars}} | ||
{{#hasVars}} | ||
|
||
public init({{#allVars}}{{{name}}}: {{#vendorExtensions.x-null-encodable}}NullEncodable<{{{datatypeWithEnum}}}>{{/vendorExtensions.x-null-encodable}}{{^vendorExtensions.x-null-encodable}}{{{datatypeWithEnum}}}{{#required}}{{#isNullable}}?{{/isNullable}}{{/required}}{{^required}}?{{/required}}{{/vendorExtensions.x-null-encodable}}{{#defaultValue}} = {{#vendorExtensions.x-null-encodable}}{{{vendorExtensions.x-null-encodable-default-value}}}{{/vendorExtensions.x-null-encodable}}{{^vendorExtensions.x-null-encodable}}{{{.}}}{{/vendorExtensions.x-null-encodable}}{{/defaultValue}}{{^defaultValue}}{{^required}} = {{#vendorExtensions.x-null-encodable}}.encodeNull{{/vendorExtensions.x-null-encodable}}{{^vendorExtensions.x-null-encodable}}nil{{/vendorExtensions.x-null-encodable}}{{/required}}{{/defaultValue}}{{^-last}}, {{/-last}}{{/allVars}}) { | ||
{{#allVars}} | ||
self.{{{name}}} = {{{name}}} | ||
{{/allVars}} | ||
} | ||
{{/hasVars}} | ||
|
||
public enum CodingKeys: {{#hasVars}}String, {{/hasVars}}CodingKey, CaseIterable { | ||
{{#allVars}} | ||
case {{{name}}}{{#vendorExtensions.x-codegen-escaped-property-name}} = "{{{baseName}}}"{{/vendorExtensions.x-codegen-escaped-property-name}} | ||
{{/allVars}} | ||
}{{#generateModelAdditionalProperties}}{{#additionalPropertiesType}} | ||
|
||
public {{#readonlyProperties}}private(set) {{/readonlyProperties}}var additionalProperties: [String: {{{additionalPropertiesType}}}] = [:] | ||
|
||
public subscript(key: String) -> {{{additionalPropertiesType}}}? { | ||
get { | ||
if let value = additionalProperties[key] { | ||
return value | ||
} | ||
return nil | ||
} | ||
|
||
set { | ||
additionalProperties[key] = newValue | ||
} | ||
}{{/additionalPropertiesType}}{{/generateModelAdditionalProperties}} | ||
|
||
// Encodable protocol methods | ||
|
||
public func encode(to encoder: Encoder) throws { | ||
var container = encoder.container(keyedBy: CodingKeys.self) | ||
{{#allVars}} | ||
{{#vendorExtensions.x-null-encodable}} | ||
switch {{{name}}} { | ||
case .encodeNothing: break | ||
case .encodeNull, .encodeValue: try container.encode({{{name}}}, forKey: .{{{name}}}) | ||
} | ||
{{/vendorExtensions.x-null-encodable}} | ||
{{^vendorExtensions.x-null-encodable}} | ||
try container.encode{{^required}}IfPresent{{/required}}({{{name}}}, forKey: .{{{name}}}) | ||
{{/vendorExtensions.x-null-encodable}} | ||
{{/allVars}} | ||
{{#generateModelAdditionalProperties}} | ||
{{#additionalPropertiesType}} | ||
var additionalPropertiesContainer = encoder.container(keyedBy: String.self) | ||
try additionalPropertiesContainer.encodeMap(additionalProperties) | ||
{{/additionalPropertiesType}} | ||
{{/generateModelAdditionalProperties}} | ||
}{{#generateModelAdditionalProperties}}{{#additionalPropertiesType}} | ||
|
||
// Decodable protocol methods | ||
|
||
public{{#objcCompatible}} required{{/objcCompatible}} init(from decoder: Decoder) throws { | ||
let container = try decoder.container(keyedBy: CodingKeys.self) | ||
{{#allVars}} | ||
{{{name}}} = try container.decode{{#required}}{{#isNullable}}IfPresent{{/isNullable}}{{/required}}{{^required}}IfPresent{{/required}}({{{datatypeWithEnum}}}.self, forKey: .{{{name}}}) | ||
{{/allVars}} | ||
var nonAdditionalPropertyKeys = Set<String>() | ||
{{#allVars}} | ||
nonAdditionalPropertyKeys.insert("{{{baseName}}}") | ||
{{/allVars}} | ||
let additionalPropertiesContainer = try decoder.container(keyedBy: String.self) | ||
additionalProperties = try additionalPropertiesContainer.decodeMap({{{additionalPropertiesType}}}.self, excludedKeys: nonAdditionalPropertyKeys) | ||
}{{/additionalPropertiesType}}{{/generateModelAdditionalProperties}}{{^objcCompatible}}{{#useClasses}}{{#vendorExtensions.x-swift-hashable}} | ||
|
||
public static func == (lhs: {{classname}}, rhs: {{classname}}) -> Bool { | ||
{{#allVars}} | ||
lhs.{{{name}}} == rhs.{{{name}}}{{^-last}} &&{{/-last}} | ||
{{/allVars}} | ||
{{#generateModelAdditionalProperties}}{{#additionalPropertiesType}}{{#hasVars}}&& {{/hasVars}}lhs.additionalProperties == rhs.additionalProperties{{/additionalPropertiesType}}{{/generateModelAdditionalProperties}} | ||
} | ||
|
||
public func hash(into hasher: inout Hasher) { | ||
{{#allVars}} | ||
hasher.combine({{{name}}}{{^vendorExtensions.x-null-encodable}}{{^required}}?{{/required}}{{/vendorExtensions.x-null-encodable}}.hashValue) | ||
{{/allVars}} | ||
{{#generateModelAdditionalProperties}}{{#additionalPropertiesType}}hasher.combine(additionalProperties.hashValue){{/additionalPropertiesType}}{{/generateModelAdditionalProperties}} | ||
}{{/vendorExtensions.x-swift-hashable}}{{/useClasses}}{{/objcCompatible}} | ||
} |