Remove encoder requirement to almost all Open API Node constructors. Made a new protocol for the few places where an encoder did need to be passed in.

This commit is contained in:
Mathew Polzin
2019-01-23 23:21:16 -08:00
parent 951c04ad44
commit 952fe8ba7e
6 changed files with 167 additions and 119 deletions
@@ -13,12 +13,25 @@ import Foundation
/// Anything conforming to `OpenAPINodeType` can provide an
/// OpenAPI schema representing itself.
public protocol OpenAPINodeType {
static func openAPINode(using encoder: JSONEncoder) throws -> JSONNode
static func openAPINode() throws -> JSONNode
}
extension OpenAPINodeType where Self: Sampleable, Self: Encodable {
public static func openAPINodeWithExample(using encoder: JSONEncoder = JSONEncoder()) throws -> JSONNode {
return try openAPINode(using: encoder).with(example: Self.successSample ?? Self.sample, using: encoder)
return try openAPINode().with(example: Self.successSample ?? Self.sample, using: encoder)
}
}
/// Anything conforming to `OpenAPIEncodedNodeType` can provide an
/// OpenAPI schema representing itself but it may need an Encoder
/// to do its job.
public protocol OpenAPIEncodedNodeType: OpenAPINodeType {
static func openAPINode(using encoder: JSONEncoder) throws -> JSONNode
}
extension OpenAPIEncodedNodeType {
public static func openAPINode() throws -> JSONNode {
return try openAPINode(using: JSONEncoder())
}
}
@@ -29,7 +42,7 @@ extension OpenAPINodeType where Self: Sampleable, Self: Encodable {
/// different schema. The "different" conditions have to do
/// with Raw Representability, hence the name of this protocol.
public protocol RawOpenAPINodeType {
static func rawOpenAPINode(using encoder: JSONEncoder) throws -> JSONNode
static func rawOpenAPINode() throws -> JSONNode
}
/// Anything conforming to `RawOpenAPINodeType` can provide an
@@ -39,7 +52,7 @@ public protocol RawOpenAPINodeType {
/// different schema. The "different" conditions have to do
/// with Optionality, hence the name of this protocol.
public protocol WrappedRawOpenAPIType {
static func wrappedOpenAPINode(using encoder: JSONEncoder) throws -> JSONNode
static func wrappedOpenAPINode() throws -> JSONNode
}
/// Anything conforming to `RawOpenAPINodeType` can provide an
@@ -52,7 +65,7 @@ public protocol DoubleWrappedRawOpenAPIType {
// NOTE: This is definitely a rabbit hole... hopefully I
// will realize I've been missing something obvious
// and dig my way back out at some point...
static func wrappedOpenAPINode(using encoder: JSONEncoder) throws -> JSONNode
static func wrappedOpenAPINode() throws -> JSONNode
}
/// Anything conforming to `AnyJSONCaseIterable` can provide a
@@ -282,15 +295,14 @@ public enum JSONNode: Equatable {
nullable: Bool = false,
// constantValue: Format.SwiftType? = nil,
allowedValues: [AnyCodable]? = nil,
example: AnyCodable? = nil,
using encoder: JSONEncoder = JSONEncoder()) {
example: (codable: AnyCodable, encoder: JSONEncoder)? = nil) {
self.format = format
self.required = required
self.nullable = nullable
// self.constantValue = constantValue
self.allowedValues = allowedValues
self.example = example
.flatMap { try? encoder.encode($0)}
.flatMap { try? $0.encoder.encode($0.codable)}
.flatMap { String(data: $0, encoding: .utf8) }
}
@@ -331,13 +343,13 @@ public enum JSONNode: Equatable {
}
/// Return this context with the given example
public func with(example: AnyCodable) -> Context {
public func with(example: AnyCodable, using encoder: JSONEncoder) -> Context {
return .init(format: format,
required: required,
nullable: nullable,
// constantValue: constantValue,
allowedValues: allowedValues,
example: example)
example: (codable: example, encoder: encoder))
}
}
@@ -562,17 +574,17 @@ public enum JSONNode: Equatable {
switch self {
case .boolean(let context):
return .boolean(context.with(example: example))
return .boolean(context.with(example: example, using: encoder))
case .object(let contextA, let contextB):
return .object(contextA.with(example: example), contextB)
return .object(contextA.with(example: example, using: encoder), contextB)
case .array(let contextA, let contextB):
return .array(contextA.with(example: example), contextB)
return .array(contextA.with(example: example, using: encoder), contextB)
case .number(let context, let contextB):
return .number(context.with(example: example), contextB)
return .number(context.with(example: example, using: encoder), contextB)
case .integer(let context, let contextB):
return .integer(context.with(example: example), contextB)
return .integer(context.with(example: example, using: encoder), contextB)
case .string(let context, let contextB):
return .string(context.with(example: example), contextB)
return .string(context.with(example: example, using: encoder), contextB)
case .all, .one, .any, .not:
return self
}
@@ -33,26 +33,26 @@ Any object:
**/
extension Optional: OpenAPINodeType where Wrapped: OpenAPINodeType {
static public func openAPINode(using encoder: JSONEncoder) throws -> JSONNode {
return try Wrapped.openAPINode(using: encoder).optionalNode()
static public func openAPINode() throws -> JSONNode {
return try Wrapped.openAPINode().optionalNode()
}
}
extension Optional: RawOpenAPINodeType where Wrapped: RawRepresentable, Wrapped.RawValue: OpenAPINodeType {
static public func rawOpenAPINode(using encoder: JSONEncoder) throws -> JSONNode {
return try Wrapped.RawValue.openAPINode(using: encoder).optionalNode()
static public func rawOpenAPINode() throws -> JSONNode {
return try Wrapped.RawValue.openAPINode().optionalNode()
}
}
extension Optional: WrappedRawOpenAPIType where Wrapped: RawOpenAPINodeType {
static public func wrappedOpenAPINode(using encoder: JSONEncoder) throws -> JSONNode {
return try Wrapped.rawOpenAPINode(using: encoder).optionalNode()
static public func wrappedOpenAPINode() throws -> JSONNode {
return try Wrapped.rawOpenAPINode().optionalNode()
}
}
extension Optional: DoubleWrappedRawOpenAPIType where Wrapped: WrappedRawOpenAPIType {
static public func wrappedOpenAPINode(using encoder: JSONEncoder) throws -> JSONNode {
return try Wrapped.wrappedOpenAPINode(using: encoder).optionalNode()
static public func wrappedOpenAPINode() throws -> JSONNode {
return try Wrapped.wrappedOpenAPINode().optionalNode()
}
}
@@ -63,7 +63,7 @@ extension Optional: AnyJSONCaseIterable where Wrapped: CaseIterable, Wrapped: Co
}
extension String: OpenAPINodeType {
static public func openAPINode(using encoder: JSONEncoder) throws -> JSONNode {
static public func openAPINode() throws -> JSONNode {
return .string(.init(format: .generic,
required: true),
.init())
@@ -71,22 +71,22 @@ extension String: OpenAPINodeType {
}
extension Bool: OpenAPINodeType {
static public func openAPINode(using encoder: JSONEncoder) throws -> JSONNode {
static public func openAPINode() throws -> JSONNode {
return .boolean(.init(format: .generic,
required: true))
}
}
extension Array: OpenAPINodeType where Element: OpenAPINodeType {
static public func openAPINode(using encoder: JSONEncoder) throws -> JSONNode {
static public func openAPINode() throws -> JSONNode {
return .array(.init(format: .generic,
required: true),
.init(items: try Element.openAPINode(using: encoder)))
.init(items: try Element.openAPINode()))
}
}
extension Double: OpenAPINodeType {
static public func openAPINode(using encoder: JSONEncoder) throws -> JSONNode {
static public func openAPINode() throws -> JSONNode {
return .number(.init(format: .double,
required: true),
.init())
@@ -94,7 +94,7 @@ extension Double: OpenAPINodeType {
}
extension Float: OpenAPINodeType {
static public func openAPINode(using encoder: JSONEncoder) throws -> JSONNode {
static public func openAPINode() throws -> JSONNode {
return .number(.init(format: .float,
required: true),
.init())
@@ -102,7 +102,7 @@ extension Float: OpenAPINodeType {
}
extension Int: OpenAPINodeType {
static public func openAPINode(using encoder: JSONEncoder) throws -> JSONNode {
static public func openAPINode() throws -> JSONNode {
return .integer(.init(format: .generic,
required: true),
.init())
@@ -110,7 +110,7 @@ extension Int: OpenAPINodeType {
}
extension Int32: OpenAPINodeType {
static public func openAPINode(using encoder: JSONEncoder) throws -> JSONNode {
static public func openAPINode() throws -> JSONNode {
return .integer(.init(format: .int32,
required: true),
.init())
@@ -118,7 +118,7 @@ extension Int32: OpenAPINodeType {
}
extension Int64: OpenAPINodeType {
static public func openAPINode(using encoder: JSONEncoder) throws -> JSONNode {
static public func openAPINode() throws -> JSONNode {
return .integer(.init(format: .int64,
required: true),
.init())