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
11 changes: 6 additions & 5 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,23 @@ Thank you for considering contributing to OpenAPIKit!

Take a look at the [Code of Conduct](https://github.com/mattpolzin/OpenAPIKit/blob/master/CODE_OF_CONDUCT.md) and note the [MIT license](https://github.com/mattpolzin/OpenAPIKit/blob/master/LICENSE.txt) associated with this project.

If you are preparing a change for the current release of OpenAPIKit (major version 4), branch off of the `main` branch of this repositroy. If you are preparing a fix for version 3 of OpenAPIKit, branch off of the `release/3_x` branch of this repository. If you are preparing a change for the next major release of OpenAPIKit (major version `5`), branch off of the `release/5_0` branch of this repository.
If you are preparing a change for the current release of OpenAPIKit (major version 5), branch off of the `main` branch of this repositroy. If you are preparing a fix for version 4 of OpenAPIKit, branch off of the `release/4_x` branch of this repository. If you are preparing a change for the next major release of OpenAPIKit (major version `6`), branch off of the `release/6_0` branch of this repository.

Please do the following in the course of preparing a branch and pull request for this project.

- Create an issue motivating the changes you want to make if one does not already exist. If you are unsure of how to adress an issue, seek out converstation on the issue before committing to a strategy.
- Add test cases that cover the logical branches of your addition. For bug fixes, at least one of your test cases should fail prior to your change to serve as a regression test against the bug being fixed.
- If relevant, cite the OpenAPI specification in describing your changes.
- If your changes only apply for OpenAPI 3.1.x documents, modify the `OpenAPIKit` module. If your changes only apply for OpenAPI 3.0.x documents, modify the `OpenAPIKit30` module. If your changes apply to both, please port your changes from one to the other so both are updated if you have time. If you don't have time to apply changes to both modules, create a PR and ask for assistance with porting your changes. If you are not sure whether your changes apply to both modules, you can also create a PR and then ask for clarification.
- If your changes only apply for OpenAPI 3.1.x and 3.2.x documents, modify the `OpenAPIKit` module. If your changes only apply for OpenAPI 3.0.x documents, modify the `OpenAPIKit30` module. If your changes apply to both, please port your changes from one to the other so both are updated if you have time. If you don't have time to apply changes to both modules, create a PR and ask for assistance with porting your changes. If you are not sure whether your changes apply to both modules, you can also create a PR and then ask for clarification.
- If your changes only apply to OpenAPI 3.2.x documents, add "conditional warnings" so that the `OpenAPIKit` module can support the OAS 3.2.x feature but also warn if an OAS 3.1.x document uses that feature. See existing types with `HasConditionalWarnings` protocol conformance for examples.

### Goals for each currently maintained major version

`3.x`: Non-breaking changes that fix bugs or add improvements to the support of either OpenAPI Spec v3.0.x or OpenAPI Spec v3.1.x.
`4.x`: Non-breaking changes that fix bugs or add improvements to the support of OpenAPI Spec v3.0.x, OpenAPI Spec v3.1.x, external dereferencing, or Swift concurrency.
`4.x`: Non-breaking changes that fix bugs or add improvements to the support of either OpenAPI Spec v3.0.x or OpenAPI Spec v3.1.x.
`5.x`: Non-breaking changes that fix bugs or add improvements to the support of OpenAPI Spec v3.0.x, OpenAPI Spec v3.1.x, or OpenAPI Spec v3.2.x.

#### Goals for the Next/unreleased version
The next major version will be `5.0`.
The next major version will be `6.0`.

Priorities for this release have not been settled on yet.

Expand Down
2 changes: 1 addition & 1 deletion Sources/OpenAPIKit/Callbacks.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ extension OpenAPI {
/// A map from runtime expressions to path items to be used as
/// callbacks for the API. The OpenAPI Spec "Callback Object."
///
/// See [OpenAPI Callback Object](https://spec.openapis.org/oas/v3.1.1.html#callback-object).
/// See [OpenAPI Callback Object](https://spec.openapis.org/oas/v3.2.0.html#callback-object).
///
public typealias Callbacks = OrderedDictionary<CallbackURL, Either<OpenAPI.Reference<PathItem>, PathItem>>

Expand Down
15 changes: 3 additions & 12 deletions Sources/OpenAPIKit/Components Object/Components.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import Foundation
extension OpenAPI {
/// OpenAPI Spec "Components Object".
///
/// See [OpenAPI Components Object](https://spec.openapis.org/oas/v3.1.1.html#components-object).
/// See [OpenAPI Components Object](https://spec.openapis.org/oas/v3.2.0.html#components-object).
///
/// This is a place to put reusable components to
/// be referenced from other parts of the spec.
Expand Down Expand Up @@ -98,7 +98,7 @@ extension OpenAPI {
self.vendorExtensions = vendorExtensions

self.conditionalWarnings = [
nonEmptyVersionWarning(fieldName: "mediaTypes", value: mediaTypes, minimumVersion: .v3_2_0)
OASWarnings.Doc.nonEmptyVersionWarning(objectName: "Components", fieldName: "mediaTypes", value: mediaTypes, minimumVersion: .v3_2_0)
].compactMap { $0 }
}

Expand Down Expand Up @@ -161,15 +161,6 @@ extension OpenAPI.Components: Equatable {
}
}

fileprivate func nonEmptyVersionWarning(fieldName: String, value: any Collection, minimumVersion: OpenAPI.Document.Version) -> (any Condition, OpenAPI.Warning)? {
if value.isEmpty { return nil }

return OpenAPI.Document.ConditionalWarnings.version(
lessThan: minimumVersion,
doesNotSupport: "The Components \(fieldName) map"
)
}

extension OpenAPI {

public typealias ComponentDictionary<T> = OrderedDictionary<ComponentKey, T>
Expand Down Expand Up @@ -328,7 +319,7 @@ extension OpenAPI.Components: Decodable {
vendorExtensions = try Self.extensions(from: decoder)

conditionalWarnings = [
nonEmptyVersionWarning(fieldName: "mediaTypes", value: mediaTypes, minimumVersion: .v3_2_0)
OASWarnings.Doc.nonEmptyVersionWarning(objectName: "Components", fieldName: "mediaTypes", value: mediaTypes, minimumVersion: .v3_2_0)
].compactMap { $0 }
} catch let error as EitherDecodeNoTypesMatchedError {
if let underlyingError = OpenAPI.Error.Decoding.Document.eitherBranchToDigInto(error) {
Expand Down
2 changes: 1 addition & 1 deletion Sources/OpenAPIKit/Content/Content.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import OpenAPIKitCore
extension OpenAPI {
/// OpenAPI Spec "Media Type Object"
///
/// See [OpenAPI Media Type Object](https://spec.openapis.org/oas/v3.1.1.html#media-type-object).
/// See [OpenAPI Media Type Object](https://spec.openapis.org/oas/v3.2.0.html#media-type-object).
public struct Content: HasConditionalWarnings, CodableVendorExtendable, Sendable {
/// A schema describing the complete content of the request, response,
/// parameter, or header.
Expand Down
2 changes: 1 addition & 1 deletion Sources/OpenAPIKit/Content/ContentEncoding.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import OpenAPIKitCore
extension OpenAPI.Content {
/// OpenAPI Spec "Encoding Object"
///
/// See [OpenAPI Encoding Object](https://spec.openapis.org/oas/v3.1.1.html#encoding-object).
/// See [OpenAPI Encoding Object](https://spec.openapis.org/oas/v3.2.0.html#encoding-object).
public struct Encoding: Equatable, CodableVendorExtendable, Sendable {
public typealias Style = OpenAPI.Parameter.SchemaContext.Style

Expand Down
13 changes: 2 additions & 11 deletions Sources/OpenAPIKit/Discriminator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ extension OpenAPI {
self.defaultMapping = defaultMapping

self.conditionalWarnings = [
nonNilVersionWarning(fieldName: "defaultMapping", value: defaultMapping, minimumVersion: .v3_2_0)
OASWarnings.Doc.nonNilVersionWarning(objectName: "Discriminator", fieldName: "defaultMapping", value: defaultMapping, minimumVersion: .v3_2_0)
].compactMap { $0 }
}
}
Expand All @@ -40,15 +40,6 @@ extension OpenAPI.Discriminator: Equatable {
}
}

fileprivate func nonNilVersionWarning<Subject>(fieldName: String, value: Subject?, minimumVersion: OpenAPI.Document.Version) -> (any Condition, OpenAPI.Warning)? {
value.map { _ in
OpenAPI.Document.ConditionalWarnings.version(
lessThan: minimumVersion,
doesNotSupport: "The Discriminator \(fieldName) field"
)
}
}

// MARK: - Codable

extension OpenAPI.Discriminator: Encodable {
Expand All @@ -70,7 +61,7 @@ extension OpenAPI.Discriminator: Decodable {
defaultMapping = try container.decodeIfPresent(String.self, forKey: .defaultMapping)

conditionalWarnings = [
nonNilVersionWarning(fieldName: "defaultMapping", value: defaultMapping, minimumVersion: .v3_2_0)
OASWarnings.Doc.nonNilVersionWarning(objectName: "Discriminator", fieldName: "defaultMapping", value: defaultMapping, minimumVersion: .v3_2_0)
].compactMap { $0 }
}
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/OpenAPIKit/Document/DereferencedDocument.swift
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ extension DereferencedDocument {
/// each path, traversed in the order the paths appear in
/// the document.
///
/// See [Operation Object](https://spec.openapis.org/oas/v3.1.1.html#operation-object) in the specifcation.
/// See [Operation Object](https://spec.openapis.org/oas/v3.2.0.html#operation-object) in the specifcation.
///
public var allOperationIds: [String] {
return paths.values
Expand Down
21 changes: 6 additions & 15 deletions Sources/OpenAPIKit/Document/Document.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import Foundation
extension OpenAPI {
/// The root of an OpenAPI 3.1 document.
///
/// See [OpenAPI Specification](https://spec.openapis.org/oas/v3.1.1.html).
/// See [OpenAPI Specification](https://spec.openapis.org/oas/v3.2.0.html).
///
/// An OpenAPI Document can say a _lot_ about the API it describes.
/// A read-through of the specification is highly recommended because
Expand Down Expand Up @@ -104,7 +104,7 @@ extension OpenAPI {
///
/// Closely related to the callbacks feature, this section describes requests initiated other than by an API call, for example by an out of band registration.
/// The key name is a unique string to refer to each webhook, while the (optionally referenced) Path Item Object describes a request that may be initiated by the API provider and the expected responses
/// See [OpenAPI Webhook Object](https://spec.openapis.org/oas/v3.1.1.html#fixed-fields)
/// See [OpenAPI Webhook Object](https://spec.openapis.org/oas/v3.2.0.html#fixed-fields)
public var webhooks: OrderedDictionary<String, Either<OpenAPI.Reference<OpenAPI.PathItem>, OpenAPI.PathItem>>

/// A declaration of which security mechanisms can be used across the API.
Expand Down Expand Up @@ -177,21 +177,12 @@ extension OpenAPI {

self.conditionalWarnings = [
// If $self is non-nil, the document must be OAS version 3.2.0 or greater
nonNilVersionWarning(fieldName: "$self", value: selfURI, minimumVersion: .v3_2_0),
OASWarnings.Doc.nonNilVersionWarning(objectName: "Document", fieldName: "$self", value: selfURI, minimumVersion: .v3_2_0),
].compactMap { $0 }
}
}
}

fileprivate func nonNilVersionWarning<Subject>(fieldName: String, value: Subject?, minimumVersion: OpenAPI.Document.Version) -> (any Condition, OpenAPI.Warning)? {
value.map { _ in
OpenAPI.Document.ConditionalWarnings.version(
lessThan: minimumVersion,
doesNotSupport: "The Document \(fieldName) field"
)
}
}

extension OpenAPI.Document: Equatable {
public static func == (lhs: Self, rhs: Self) -> Bool {
lhs.openAPIVersion == rhs.openAPIVersion
Expand Down Expand Up @@ -271,7 +262,7 @@ extension OpenAPI.Document {
/// each path, traversed in the order the paths appear in
/// the document.
///
/// See [Operation Object](https://spec.openapis.org/oas/v3.1.1.html#operation-object) in the specifcation.
/// See [Operation Object](https://spec.openapis.org/oas/v3.2.0.html#operation-object) in the specifcation.
///
public var allOperationIds: [String] {
return (paths.values + webhooks.values)
Expand Down Expand Up @@ -455,7 +446,7 @@ extension OpenAPI {
/// Multiple entries in this dictionary indicate all schemes named are
/// required on the same request.
///
/// See [OpenAPI Security Requirement Object](https://spec.openapis.org/oas/v3.1.1.html#security-requirement-object).
/// See [OpenAPI Security Requirement Object](https://spec.openapis.org/oas/v3.2.0.html#security-requirement-object).
public typealias SecurityRequirement = [JSONReference<SecurityScheme>: [String]]
}

Expand Down Expand Up @@ -713,7 +704,7 @@ extension OpenAPI.Document: Decodable {

self.conditionalWarnings = [
// If $self is non-nil, the document must be OAS version 3.2.0 or greater
nonNilVersionWarning(fieldName: "$self", value: selfURI, minimumVersion: .v3_2_0),
OASWarnings.Doc.nonNilVersionWarning(objectName: "Document", fieldName: "$self", value: selfURI, minimumVersion: .v3_2_0),
].compactMap { $0 }

} catch let error as OpenAPI.Error.Decoding.Path {
Expand Down
6 changes: 3 additions & 3 deletions Sources/OpenAPIKit/Document/DocumentInfo.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import Foundation
extension OpenAPI.Document {
/// OpenAPI Spec "Info Object"
///
/// See [OpenAPI Info Object](https://spec.openapis.org/oas/v3.1.1.html#info-object).
/// See [OpenAPI Info Object](https://spec.openapis.org/oas/v3.2.0.html#info-object).
public struct Info: Equatable, CodableVendorExtendable, Sendable {
public var title: String
public var summary: String?
Expand Down Expand Up @@ -50,7 +50,7 @@ extension OpenAPI.Document {

/// OpenAPI Spec "Contact Object"
///
/// See [OpenAPI Contact Object](https://spec.openapis.org/oas/v3.1.1.html#contact-object).
/// See [OpenAPI Contact Object](https://spec.openapis.org/oas/v3.2.0.html#contact-object).
public struct Contact: Equatable, CodableVendorExtendable, Sendable {
public let name: String?
public let url: URL?
Expand Down Expand Up @@ -78,7 +78,7 @@ extension OpenAPI.Document {

/// OpenAPI Spec "License Object"
///
/// See [OpenAPI License Object](https://spec.openapis.org/oas/v3.1.1.html#license-object).
/// See [OpenAPI License Object](https://spec.openapis.org/oas/v3.2.0.html#license-object).
public struct License: Equatable, CodableVendorExtendable, Sendable {
public let name: String
public let identifier: Identifier?
Expand Down
13 changes: 2 additions & 11 deletions Sources/OpenAPIKit/Example/Example.swift
Original file line number Diff line number Diff line change
Expand Up @@ -143,21 +143,12 @@ extension OpenAPI.Example {
extension OpenAPI.Example.Value {
fileprivate var conditionalWarnings: [(any Condition, OpenAPI.Warning)] {
[
nonNilVersionWarning(fieldName: "dataValue", value: dataValue, minimumVersion: .v3_2_0),
nonNilVersionWarning(fieldName: "serializedValue", value: serializedValue, minimumVersion: .v3_2_0)
OASWarnings.Doc.nonNilVersionWarning(objectName: "Example", fieldName: "dataValue", value: dataValue, minimumVersion: .v3_2_0),
OASWarnings.Doc.nonNilVersionWarning(objectName: "Example", fieldName: "serializedValue", value: serializedValue, minimumVersion: .v3_2_0)
].compactMap { $0 }
}
}

fileprivate func nonNilVersionWarning<Subject>(fieldName: String, value: Subject?, minimumVersion: OpenAPI.Document.Version) -> (any Condition, OpenAPI.Warning)? {
value.map { _ in
OpenAPI.Document.ConditionalWarnings.version(
lessThan: minimumVersion,
doesNotSupport: "The Example Object \(fieldName) field"
)
}
}

// MARK: - Either Convenience
extension Either where A == OpenAPI.Reference<OpenAPI.Example>, B == OpenAPI.Example {
@available(*, deprecated, message: "This function populates the deprecated 'value' field, use .value(summary:description:dataValue:serializedValue:vendorExtensions:) or .value(summary:description:dataValue:externalValue:vendorExtensions:) instead.")
Expand Down
2 changes: 1 addition & 1 deletion Sources/OpenAPIKit/ExternalDocumentation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import Foundation
extension OpenAPI {
/// OpenAPI Spec "External Documentation Object"
///
/// See [OpenAPI External Documentation Object](https://spec.openapis.org/oas/v3.1.1.html#external-documentation-object).
/// See [OpenAPI External Documentation Object](https://spec.openapis.org/oas/v3.2.0.html#external-documentation-object).
public struct ExternalDocumentation: Equatable, CodableVendorExtendable, Sendable {
public var description: String?
public var url: URL
Expand Down
2 changes: 1 addition & 1 deletion Sources/OpenAPIKit/Header/Header.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import OpenAPIKitCore
extension OpenAPI {
/// OpenAPI Spec "Header Object"
///
/// See [OpenAPI Header Object](https://spec.openapis.org/oas/v3.1.1.html#header-object).
/// See [OpenAPI Header Object](https://spec.openapis.org/oas/v3.2.0.html#header-object).
public struct Header: Equatable, CodableVendorExtendable, Sendable {
public typealias SchemaContext = Parameter.SchemaContext

Expand Down
4 changes: 2 additions & 2 deletions Sources/OpenAPIKit/JSONReference.swift
Original file line number Diff line number Diff line change
Expand Up @@ -415,14 +415,14 @@ public extension SummaryOverridable {
}

/// `OpenAPIDescribable` types allow their descriptions to be overridden to facilitate
/// the OpenAPI 3.1.x feature that a `$ref` can specify a description to be used instead of
/// the OpenAPI 3.1.x+ feature that a `$ref` can specify a description to be used instead of
/// whatever description the referenced object has.
public protocol OpenAPIDescribable: SummaryOverridable {
func overriddenNonNil(description: String?) -> Self
}

/// `OpenAPISummarizable` types allow their summaries to be overridden to facilitate
/// the OpenAPI 3.1.x feature that a `$ref` can specify a summary to be used instead of
/// the OpenAPI 3.1.x+ feature that a `$ref` can specify a summary to be used instead of
/// whatever summary the referenced object has.
public protocol OpenAPISummarizable: OpenAPIDescribable {
func overriddenNonNil(summary: String?) -> Self
Expand Down
4 changes: 2 additions & 2 deletions Sources/OpenAPIKit/Link.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import Foundation
extension OpenAPI {
/// OpenAPI Spec "Link Object"
///
/// See [OpenAPI Link Object](https://spec.openapis.org/oas/v3.1.1.html#link-object).
/// See [OpenAPI Link Object](https://spec.openapis.org/oas/v3.2.0.html#link-object).
public struct Link: Equatable, CodableVendorExtendable, Sendable {
/// The **OpenAPI**` `operationRef` or `operationId` field, depending on whether
/// a `URL` of a remote or local Operation Object or a `operationId` (String) of an
Expand All @@ -24,7 +24,7 @@ extension OpenAPI {
/// A map from parameter names to either runtime expressions that evaluate to values or
/// constant values (`AnyCodable`).
///
/// See the docuemntation for the [OpenAPI Link Object](https://spec.openapis.org/oas/v3.1.1.html#link-object) for more details.
/// See the docuemntation for the [OpenAPI Link Object](https://spec.openapis.org/oas/v3.2.0.html#link-object) for more details.
///
/// Empty dictionaries will be omitted from encoding.
public var parameters: OrderedDictionary<String, Either<RuntimeExpression, AnyCodable>>
Expand Down
22 changes: 22 additions & 0 deletions Sources/OpenAPIKit/OpenAPIConditionalWarnings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -57,5 +57,27 @@ internal extension OpenAPI.Document {

return (DocumentVersionCondition(version: version, comparator: .lessThan), warning)
}

static func nonNilVersionWarning<Subject>(objectName: String, fieldName: String, value: Subject?, minimumVersion: OpenAPI.Document.Version) -> (any Condition, OpenAPI.Warning)? {
value.map { _ in
OpenAPI.Document.ConditionalWarnings.version(
lessThan: minimumVersion,
doesNotSupport: "The \(objectName) \(fieldName) field"
)
}
}

static func nonEmptyVersionWarning<Key, Value>(objectName: String, fieldName: String, value: OrderedDictionary<Key, Value>, minimumVersion: OpenAPI.Document.Version) -> (any Condition, OpenAPI.Warning)? {
if value.isEmpty { return nil }

return OpenAPI.Document.ConditionalWarnings.version(
lessThan: minimumVersion,
doesNotSupport: "The \(objectName) \(fieldName) map"
)
}
}
}

internal enum OASWarnings {
typealias Doc = OpenAPI.Document.ConditionalWarnings
}
Loading