Skip to content

Commit 4d86954

Browse files
committed
Add additionalOperations to PathItem type. Expand HttpMethod type to support additional methods not built into library.
1 parent da79634 commit 4d86954

File tree

16 files changed

+391
-117
lines changed

16 files changed

+391
-117
lines changed

Sources/OpenAPIKit/Encoding and Decoding Errors/PathDecodingError.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ extension OpenAPI.Error.Decoding.Path {
104104

105105
internal init(_ error: DecodingError) {
106106
var codingPath = error.codingPathWithoutSubject.dropFirst()
107-
let route = OpenAPI.Path(rawValue: codingPath.removeFirst().stringValue)
107+
let route = OpenAPI.Path(rawValue: codingPath.removeFirstPathComponentString())
108108

109109
path = route
110110
context = .other(error)
@@ -113,7 +113,7 @@ extension OpenAPI.Error.Decoding.Path {
113113

114114
internal init(_ error: OpenAPI.Error.Decoding.Operation) {
115115
var codingPath = error.codingPath.dropFirst()
116-
let route = OpenAPI.Path(rawValue: codingPath.removeFirst().stringValue)
116+
let route = OpenAPI.Path(rawValue: codingPath.removeFirstPathComponentString())
117117

118118
path = route
119119
context = .endpoint(error)
@@ -122,7 +122,7 @@ extension OpenAPI.Error.Decoding.Path {
122122

123123
internal init(_ error: GenericError) {
124124
var codingPath = error.codingPath.dropFirst()
125-
let route = OpenAPI.Path(rawValue: codingPath.removeFirst().stringValue)
125+
let route = OpenAPI.Path(rawValue: codingPath.removeFirstPathComponentString())
126126

127127
path = route
128128
context = .inconsistency(error)
@@ -148,7 +148,7 @@ extension OpenAPI.Error.Decoding.Path {
148148
// }
149149

150150
var codingPath = eitherError.codingPath.dropFirst()
151-
let route = OpenAPI.Path(rawValue: codingPath.removeFirst().stringValue)
151+
let route = OpenAPI.Path(rawValue: codingPath.removeFirstPathComponentString())
152152

153153
path = route
154154
context = .neither(eitherError)

Sources/OpenAPIKit/Path Item/DereferencedPathItem.swift

Lines changed: 32 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@ public struct DereferencedPathItem: Equatable {
3737
/// The dereferenced QUERY operation, if defined.
3838
public let query: DereferencedOperation?
3939

40+
/// Additional operations, keyed by all-caps HTTP method names. This
41+
/// map MUST NOT contain any entries that can be represented by the
42+
/// fixed fields on this type (e.g. `post`, `get`, etc.).
43+
public var additionalOperations: OrderedDictionary<OpenAPI.HttpMethod, DereferencedOperation>
44+
4045
public subscript<T>(dynamicMember path: KeyPath<OpenAPI.PathItem, T>) -> T {
4146
return underlyingPathItem[keyPath: path]
4247
}
@@ -68,6 +73,8 @@ public struct DereferencedPathItem: Equatable {
6873
self.trace = try pathItem.trace.map { try DereferencedOperation($0, resolvingIn: components, following: references) }
6974
self.query = try pathItem.query.map { try DereferencedOperation($0, resolvingIn: components, following: references) }
7075

76+
self.additionalOperations = try pathItem.additionalOperations.mapValues { try DereferencedOperation($0, resolvingIn: components, following: references) }
77+
7178
var pathItem = pathItem
7279
if let name {
7380
pathItem.vendorExtensions[OpenAPI.Components.componentNameExtension] = .init(name)
@@ -83,24 +90,20 @@ extension DereferencedPathItem {
8390
/// Retrieve the operation for the given verb, if one is set for this path.
8491
public func `for`(_ verb: OpenAPI.HttpMethod) -> DereferencedOperation? {
8592
switch verb {
86-
case .delete:
87-
return self.delete
88-
case .get:
89-
return self.get
90-
case .head:
91-
return self.head
92-
case .options:
93-
return self.options
94-
case .patch:
95-
return self.patch
96-
case .post:
97-
return self.post
98-
case .put:
99-
return self.put
100-
case .trace:
101-
return self.trace
102-
case .query:
103-
return self.query
93+
case .builtin(let builtin):
94+
switch builtin {
95+
case .delete: self.delete
96+
case .get: self.get
97+
case .head: self.head
98+
case .options: self.options
99+
case .patch: self.patch
100+
case .post: self.post
101+
case .put: self.put
102+
case .trace: self.trace
103+
case .query: self.query
104+
}
105+
case .other(let other):
106+
additionalOperations[.other(other)]
104107
}
105108
}
106109

@@ -122,9 +125,11 @@ extension DereferencedPathItem {
122125
/// - Returns: An array of `Endpoints` with the method (i.e. `.get`) and the operation for
123126
/// the method.
124127
public var endpoints: [Endpoint] {
125-
return OpenAPI.HttpMethod.allCases.compactMap { method in
126-
self.for(method).map { .init(method: method, operation: $0) }
128+
let builtins = OpenAPI.BuiltinHttpMethod.allCases.compactMap { method -> Endpoint? in
129+
self.for(.builtin(method)).map { .init(method: .builtin(method), operation: $0) }
127130
}
131+
132+
return builtins + additionalOperations.map { key, value in .init(method: key, operation: value) }
128133
}
129134
}
130135

@@ -158,6 +163,8 @@ extension OpenAPI.PathItem: ExternallyDereferenceable {
158163
let oldTrace = trace
159164
let oldQuery = query
160165

166+
let oldAdditionalOperations = additionalOperations
167+
161168
async let (newParameters, c1, m1) = oldParameters.externallyDereferenced(with: loader)
162169
// async let (newServers, c2, m2) = oldServers.externallyDereferenced(with: loader)
163170
async let (newGet, c3, m3) = oldGet.externallyDereferenced(with: loader)
@@ -170,6 +177,8 @@ extension OpenAPI.PathItem: ExternallyDereferenceable {
170177
async let (newTrace, c10, m10) = oldTrace.externallyDereferenced(with: loader)
171178
async let (newQuery, c11, m11) = oldQuery.externallyDereferenced(with: loader)
172179

180+
async let (newAdditionalOperations, c12, m12) = oldAdditionalOperations.externallyDereferenced(with: loader)
181+
173182
var pathItem = self
174183
var newComponents = try await c1
175184
var newMessages = try await m1
@@ -187,6 +196,7 @@ extension OpenAPI.PathItem: ExternallyDereferenceable {
187196
pathItem.patch = try await newPatch
188197
pathItem.trace = try await newTrace
189198
pathItem.query = try await newQuery
199+
pathItem.additionalOperations = try await newAdditionalOperations
190200

191201
try await newComponents.merge(c3)
192202
try await newComponents.merge(c4)
@@ -197,6 +207,7 @@ extension OpenAPI.PathItem: ExternallyDereferenceable {
197207
try await newComponents.merge(c9)
198208
try await newComponents.merge(c10)
199209
try await newComponents.merge(c11)
210+
try await newComponents.merge(c12)
200211

201212
try await newMessages += m3
202213
try await newMessages += m4
@@ -207,6 +218,7 @@ extension OpenAPI.PathItem: ExternallyDereferenceable {
207218
try await newMessages += m9
208219
try await newMessages += m10
209220
try await newMessages += m11
221+
try await newMessages += m12
210222

211223
if let oldServers {
212224
async let (newServers, c2, m2) = oldServers.externallyDereferenced(with: loader)

0 commit comments

Comments
 (0)