Merge pull request #15 from mattpolzin/feature/OpenAPISchema

Feature/open api schema
This commit is contained in:
Mathew Polzin
2019-01-26 19:52:15 -08:00
committed by GitHub
4 changed files with 84 additions and 7 deletions
@@ -148,10 +148,12 @@ extension Entity: OpenAPIEncodedNodeType where Description.Attributes: Sampleabl
// TODO: metadata, links
let idNode = JSONNode.string(.init(format: .generic,
required: true),
.init())
let idProperty = ("id", idNode)
let idNode: JSONNode? = Id.RawType.self != Unidentified.self
? JSONNode.string(.init(format: .generic,
required: true),
.init())
: nil
let idProperty = idNode.map { ("id", $0) }
let typeNode = JSONNode.string(.init(format: .generic,
required: true,
@@ -276,7 +276,13 @@ extension OpenAPIPathItem.PathProperties.Operation: Encodable {
try container.encode(parameters, forKey: .parameters)
try container.encode(responses, forKey: .responses)
// Hack to work around Dictionary encoding
// itself as an array in this case:
let stringKeyedDict = Dictionary(
responses.map { ($0.key.rawValue, $0.value) },
uniquingKeysWith: { $1 }
)
try container.encode(stringKeyedDict, forKey: .responses)
try container.encode(deprecated, forKey: .deprecated)
}
@@ -346,6 +352,29 @@ extension OpenAPIPathItem.PathProperties: Encodable {
}
}
extension OpenAPIResponse: Encodable {
private enum CodingKeys: String, CodingKey {
case description
case headers
case content
case links
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(description, forKey: .description)
// Hack to work around Dictionary encoding
// itself as an array in this case:
let stringKeyedDict = Dictionary(
content.map { ($0.key.rawValue, $0.value) },
uniquingKeysWith: { $1 }
)
try container.encode(stringKeyedDict, forKey: .content)
}
}
extension OpenAPIPathItem: Encodable {
public func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
@@ -787,7 +787,7 @@ public enum OpenAPIPathItem: Equatable {
}
}
public struct OpenAPIResponse: Encodable, Equatable {
public struct OpenAPIResponse: Equatable {
public let description: String
// public let headers:
public let content: ContentMap
@@ -801,9 +801,29 @@ public struct OpenAPIResponse: Encodable, Equatable {
public typealias ContentMap = [ContentType: Content]
public enum Code: Equatable, Hashable {
public enum Code: RawRepresentable, Equatable, Hashable {
public typealias RawValue = String
case `default`
case status(code: Int)
public var rawValue: String {
switch self {
case .default:
return "default"
case .status(code: let code):
return String(code)
}
}
public init?(rawValue: String) {
if let val = Int(rawValue) {
self = .status(code: val)
} else {
self = .default
}
}
}
public enum ContentType: String, Encodable, Equatable, Hashable {
@@ -39,6 +39,31 @@ class JSONAPIEntityOpenAPITests: XCTestCase {
.init()))
}
func test_UnidentifiedEmptyEntity() {
let node = try! UnidentifiedTestType1.openAPINode(using: JSONEncoder())
XCTAssertTrue(node.required)
XCTAssertEqual(node.jsonTypeFormat, .object(.generic))
guard case let .object(contextA, objectContext1) = node else {
XCTFail("Expected Object node")
return
}
XCTAssertEqual(contextA, .init(format: .generic,
required: true,
nullable: false,
allowedValues: nil))
XCTAssertEqual(objectContext1.minProperties, 1)
XCTAssertEqual(Set(objectContext1.requiredProperties), Set(["type"]))
XCTAssertEqual(Set(objectContext1.properties.keys), Set(["type"]))
XCTAssertEqual(objectContext1.properties["type"], .string(.init(format: .generic,
required: true,
allowedValues: [.init(TestType1.jsonType)]),
.init()))
}
func test_AttributesEntity() {
let dateFormatter = DateFormatter()
@@ -272,6 +297,7 @@ extension JSONAPIEntityOpenAPITests {
}
typealias TestType1 = BasicEntity<TestType1Description>
typealias UnidentifiedTestType1 = JSONAPI.Entity<TestType1Description, NoMetadata, NoLinks, Unidentified>
enum TestType2Description: EntityDescription {
public static var jsonType: String { return "test2" }