Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions Package.resolved

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ let package = Package(
dependencies: [
.package(url: "https://github.com/mattpolzin/Sampleable.git", from: "2.0.0"),
.package(url: "https://github.com/mattpolzin/JSONAPI.git", from: "5.0.0"),
.package(url: "https://github.com/mattpolzin/OpenAPIKit.git", from: "1.4.0"),
.package(url: "https://github.com/mattpolzin/OpenAPIReflection.git", .upToNextMinor(from: "0.3.0")),
.package(url: "https://github.com/mattpolzin/OpenAPIKit.git", from: "2.0.0"),
.package(url: "https://github.com/mattpolzin/OpenAPIReflection.git", from: "1.0.0"),
.package(url: "https://github.com/typelift/SwiftCheck.git", .upToNextMinor(from: "0.12.0")),
.package(url: "https://github.com/apple/swift-format.git", from: "0.50300.0"),
.package(name: "NonEmpty", url: "https://github.com/pointfreeco/swift-nonempty.git", .upToNextMinor(from: "0.2.0")),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ extension Includes: OpenAPIEncodedSchemaType where I: OpenAPIEncodedSchemaType {

extension Include0: OpenAPIEncodedSchemaType {
public static func openAPISchema(using encoder: JSONEncoder) throws -> JSONSchema {
throw OpenAPI.TypeError.invalidNode
throw OpenAPI.TypeError.invalidSchema
}
}

Expand Down
70 changes: 23 additions & 47 deletions Sources/JSONAPIOpenAPI/JSONAPI/JSONAPITypes+OpenAPI.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,16 @@ extension Optional: Wrapper {}
extension RelationshipType {
static func relationshipNode(nullable: Bool, jsonType: String) -> JSONSchema {
let propertiesDict: [String: JSONSchema] = [
"id": .string(.init(format: .generic,
required: true),
.init()),
"type": .string(.init(format: .generic,
required: true,
allowedValues: [.init(jsonType)]),
.init())
"id": .string,
"type": .string(
allowedValues: [.init(jsonType)]
)
]

return .object(.init(format: .generic,
required: true,
nullable: nullable),
.init(properties: propertiesDict))
return .object(
nullable: nullable,
properties: propertiesDict
)
}
}

Expand All @@ -46,15 +43,9 @@ extension ToOneRelationship: OpenAPISchemaType {
static public var openAPISchema: JSONSchema {
let nullable = Identifiable.self is _Optional.Type
return .object(
.init(
format: .generic,
required: true
),
.init(
properties: [
"data": ToOneRelationship.relationshipNode(nullable: nullable, jsonType: Identifiable.jsonType)
]
)
properties: [
"data": ToOneRelationship.relationshipNode(nullable: nullable, jsonType: Identifiable.jsonType)
]
)
}
}
Expand All @@ -66,21 +57,11 @@ extension ToManyRelationship: OpenAPISchemaType {
// TODO: metadata & links
static public var openAPISchema: JSONSchema {
return .object(
.init(
format: .generic,
required: true
),
.init(
properties: [
"data": .array(
.init(
format: .generic,
required: true
),
.init(items: ToManyRelationship.relationshipNode(nullable: false, jsonType: Relatable.jsonType))
)
]
)
properties: [
"data": .array(
items: ToManyRelationship.relationshipNode(nullable: false, jsonType: Relatable.jsonType)
)
]
)
}
}
Expand All @@ -93,16 +74,13 @@ extension ResourceObject: OpenAPIEncodedSchemaType where Description.Attributes:
// TODO: metadata, links

let idNode: JSONSchema? = Id.RawType.self != Unidentified.self
? JSONSchema.string(.init(format: .generic,
required: true),
.init())
? JSONSchema.string
: nil
let idProperty = idNode.map { ("id", $0) }

let typeNode = JSONSchema.string(.init(format: .generic,
required: true,
allowedValues: [.init(ResourceObject.jsonType)]),
.init())
let typeNode = JSONSchema.string(
allowedValues: [.init(ResourceObject.jsonType)]
)
let typeProperty = ("type", typeNode)

let attributesNode: JSONSchema? = Description.Attributes.self == NoAttributes.self
Expand All @@ -122,11 +100,9 @@ extension ResourceObject: OpenAPIEncodedSchemaType where Description.Attributes:
typeProperty,
attributesProperty,
relationshipsProperty
].compactMap { $0 }) { _, value in value }
].compactMap { $0 }) { _, value in value }

return .object(.init(format: .generic,
required: true),
.init(properties: propertiesDict))
return .object(properties: propertiesDict)
}
}

Expand Down Expand Up @@ -210,7 +186,7 @@ extension Document.SuccessDocument: OpenAPIEncodedSchemaType where PrimaryResour
do {
includeNode = try Includes<IncludeType>.openAPISchema(using: encoder)
} catch let err as OpenAPI.TypeError {
guard case .invalidNode = err else {
guard case .invalidSchema = err else {
throw err
}
includeNode = nil
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,9 @@ func documents(
continue
}

let responseSchema = jsonResponse.schema

guard case .object = responseSchema else {
print("Found non-object response schema root (expected JSON:API 'data' object). Skipping '\(String(describing: responseSchema.jsonTypeFormat?.jsonType))'.")
guard let responseSchema = jsonResponse.schema,
case .object = responseSchema else {
print("Found non-object response schema root (expected JSON:API 'data' object). Skipping '\(String(describing: jsonResponse.schema?.jsonTypeFormat?.jsonType))'.")
continue
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ public struct StructureSwiftGen: JSONSchemaSwiftGenerator {
cascadingConformances: [String],
rootConformances: [String]? = nil
) throws -> BlockTypeDecl {

let decls = try context
.properties
.sorted { $0.key < $1.key }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ public struct APIRequestTestSwiftGen: SwiftGenerator {
originatingAt server: OpenAPI.Server
) -> Decl {

let host = server.url
let host = server.urlTemplate.url!

return urlSnippet(from: path, originatingAt: host)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ public struct OpenAPIExampleRequestTestSwiftGen: TestFunctionGenerator {
}

static func hostSnippet(from server: OpenAPI.Server) -> Decl {
let hostUrl = server.url
let hostUrl = server.urlTemplate.url!
return PropDecl.let(
propName: "defaultHost",
swiftType: .rep(String.self),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,14 @@ extension OpenAPIExampleRequestTestSwiftGen {

ignoreMissingParameterWarnings = (testProps["ignore_missing_parameter_warnings"] as? Bool) ?? false

// TODO: Once the URLTemplate type can be resolved against the
// server variables, don't just force unwrap the URL property
// like this:
let hostParam = testProps["test_host"]
.flatMap { $0 as? String }
host = try hostParam
.flatMap { try Self.hostOverride(from: $0, inTest: name) }
?? server.url
?? server.urlTemplate.url!

skipExample = testProps["skip_example"]
.flatMap { $0 as? Bool }
Expand Down
22 changes: 19 additions & 3 deletions Sources/JSONAPISwiftGen/SwiftGen.swift
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,18 @@ internal func safeForPropertyName(_ name: String) -> String {
.replacingOccurrences(of: "-", with: "_")
}

enum SwiftTypeError: Swift.Error {
enum SwiftTypeError: Swift.Error, CustomStringConvertible {
case typeNotFound
case placeholderTypeNotAllowed(for: JSONSchema, hint: String)

public var description: String {
switch self {
case .typeNotFound:
return "Encountered an OpenAPI type for which the library was not able to find a suitable Codable structure."
case .placeholderTypeNotAllowed(for: _, hint: let hint):
return "Would have used a placeholder for some type of \(hint) but placeholders are disallowed in the current configuration."
}
}
}

internal func swiftType(
Expand All @@ -112,12 +121,19 @@ internal func swiftType(
let typeRep: SwiftTypeRep
switch schema.jsonTypeFormat {
case nil:
// just one-off cases handled for now:
if case .fragment = schema {
// If we don't know what type something is, just fall back
// to AnyCodable.
typeRep = SwiftTypeRep(AnyCodable.self)
break
}
throw SwiftTypeError.typeNotFound
case .boolean(let format)?:
typeRep = SwiftTypeRep(type(of: format).SwiftType.self)
case .object(_)?:
guard allowPlaceholders else {
throw SwiftTypeError.placeholderTypeNotAllowed(for: schema.underlyingJSONSchema, hint: "object")
throw SwiftTypeError.placeholderTypeNotAllowed(for: schema.jsonSchema, hint: "object")
}
typeRep = .placeholder(name: "Swift Type", typeHint: "Any")
case .array(_)?:
Expand All @@ -137,7 +153,7 @@ internal func swiftType(
}

guard allowPlaceholders else {
throw SwiftTypeError.placeholderTypeNotAllowed(for: schema.underlyingJSONSchema, hint: "array")
throw SwiftTypeError.placeholderTypeNotAllowed(for: schema.jsonSchema, hint: "array")
}
typeRep = .placeholder(name: "Swift Type", typeHint: "[Any]")
case .number(let format)?:
Expand Down
Loading