Swiftpack.co - Package - mattpolzin/OpenAPIKit

sswg:sandbox|94x20 Swift 5.1+ Build Status

MIT license

OpenAPIKit

A library containing Swift types that encode to- and decode from OpenAPI Documents and their components.

Usage

Decoding OpenAPI Documents

You can decode a JSON OpenAPI document (i.e. using the JSONDecoder from Foundation library) or a YAML OpenAPI document (i.e. using the YAMLDecoder from the Yams library) with the following code:

let decoder = ... // JSONDecoder() or YAMLDecoder()
let openAPIDoc = try decoder.decode(OpenAPI.Document, from: ...)

Decoding Errors

You can wrap any error you get back from a decoder in OpenAPI.Error to get a friendlier human-readable description from localizedDescription.

do {
  try decoder.decode(OpenAPI.Document, from: ...)
} catch let error {
  print(OpenAPI.Error(from: error).localizedDescription)  
}

Encoding OpenAPI Documents

You can encode a JSON OpenAPI document (i.e. using the JSONEncoder from the Foundation library) or a YAML OpenAPI document (i.e. using the YAMLEncoder from the Yams library) with the following code:

let openAPIDoc = ...
let encoder = ... // JSONEncoder() or YAMLEncoder()
let encodedOpenAPIDoc = try encoder.encode(openAPIDoc)

A note on dictionary ordering

The Foundation library's JSONEncoder and JSONDecoder do not make any guarantees about the ordering of keyed containers. This means decoding a JSON OpenAPI Document and then encoding again might result in the document's various hashed structures being in a totally different order.

If retaining order is important for your use-case, I recommend the Yams and FineJSON libraries for YAML and JSON respectively.

OpenAPI Document structure

The types used by this library largely mirror the object definitions found in the OpenAPI specification version 3.0.2. The Project Status lists each object defined by the spec and the name of the respective type in this library.

Document Root

At the root there is an OpenAPI.Document. In addition to some information that applies to the entire API, the document contains OpenAPI.Components (essentially a dictionary of reusable components that can be referenced with JSONReferences) and an OpenAPI.PathItem.Map (a dictionary of routes your API defines).

Routes

Each route is an entry in the document's OpenAPI.PathItem.Map. The keys of this dictionary are the paths for each route (i.e. /widgets). The values of this dictionary are OpenAPI.PathItems which define any combination of endpoints (i.e. GET, POST, PATCH, etc.) that the given route supports. In addition to accessing endpoints on a path item under the name of the method (.get, .post, etc.), you can get an array of pairs matching endpoint methods to operations with the .endpoints method on PathItem.

Endpoints

Each endpoint on a route is defined by an OpenAPI.Operation. Among other things, this operation can specify the parameters (path, query, header, etc.), request body, and response bodies/codes supported by the given endpoint.

Request/Response Bodies

Request and response bodies can be defined in great detail using OpenAPI's derivative of the JSON Schema specification. This library uses the JSONSchema type for such schema definitions.

Schemas

Fundamental types are specified as JSONSchema.integer, JSONSchema.string, JSONSchema.boolean, etc.

Properties are given as arguments to static constructors. By default, types are non-nullable, required, and generic.

A type can be made optional (i.e. it can be omitted) with JSONSchema.integer(required: false) or JSONSchema.integer.optionalSchemaObject(). A type can be made nullable with JSONSchema.number(nullable: true) or JSONSchema.number.nullableSchemaObject().

A type's format can be further specified, for example JSONSchema.number(format: .double) or JSONSchema.string(format: .dateTime).

You can specify a schema's allowed values (e.g. for an enumerated type) with JSONSchema.string(allowedValues: "hello", "world").

Each type has its own additional set of properties that can be specified. For example, integers can have a minimum value: JSONSchema.integer(minimum: (0, exclusive: true)) (where exclusive means the number must be greater than 0, not greater-than-or-equal-to 0).

Compound objects can be built with JSONSchema.array, JSONSchema.object, JSONSchema.all(of:), etc.

For example, perhaps a person is represented by the schema:

JSONSchema.object(
  title: "Person",
  properties: [
    "first_name": .string(minLength: 2),
    "last_name": .string(nullable: true),
    "age": .integer,
    "favorite_color": .string(allowedValues: "red", "green", "blue")
  ]
)
Generating Schemas from Swift Types

Some schemas can be easily generated from Swift types. Many of the fundamental Swift types support schema representations out-of-box.

For example, the following are true

String.openAPISchema == JSONSchema.string

Bool.openAPISchema == JSONSchema.boolean

Double.openAPISchema == JSONSchema.number(format: .double)

Float.openAPISchema == JSONSchema.number(format: .float)
...

Array and Optional are supported out-of-box. For example, the following are true

[String].openAPISchema == .array(items: .string)

[Int].openAPISchema == .array(items: .integer)

Int32?.openAPISchema == .integer(format: .int32, required: false)

[String?].openAPISchema == .array(items: .string(required: false))
...

Additional schema generation support can be found in the mattpolzin/OpenAPIReflection library.

You can conform your own types to OpenAPISchemaType to make it convenient to generate JSONSchemas from them.

JSON References

The JSONReference type allows you to work with OpenAPIDocuments that store some of their information in the shared Components Object dictionary or even external files. You cannot dereference documents (yet), but you can encode and decode references.

You can create an external reference with JSONReference.external(URL). Internal references usually refer to an object in the Components Object dictionary and are constructed with JSONReference.component(named:). If you need to refer to something in the current file but not in the Components Object, you can use JSONReference.internal(path:).

You can check whether a given JSONReference exists in the Components Object with document.components.contains(). You can access a referenced object in the Components Object with document.components[reference].

You can create references from the Components Object with document.components.reference(named:ofType:). This method will throw an error if the given component does not exist in the ComponentsObject.

You can use document.components.dereference() to turn an Either containing either a reference or a component into an optional value of that component's type (having either pulled it out of the Either or looked it up in the Components Object).

For example,

let apiDoc: OpenAPI.Document = ...
let addBooksPath = apiDoc.paths["/cloudloading/addBook"]

let addBooksParameters: [OpenAPI.Parameter]? = addBooksPath?.parameters.compactMap(apiDoc.components.dereference)

Specification Extensions

Many OpenAPIKit types support Specification Extensions. As described in the OpenAPI Specification, these extensions must be objects that are keyed with the prefix "x-". For example, a property named "specialProperty" on the root OpenAPI Object (OpenAPI.Document) is invalid but the property "x-specialProperty" is a valid specification extension.

You can get or set specification extensions via the vendorExtensions property on any object that supports this feature. The keys are Strings beginning with the aforementioned "x-" prefix and the values are AnyCodable. If you set an extension without using the "x-" prefix, the prefix will be added upon encoding.

AnyCodable can be constructed from literals or explicitly. The following are all valid.

var document = OpenAPI.Document(...)

document.vendorExtensions["x-specialProperty1"] = true
document.vendorExtensions["x-specialProperty2"] = "hello world"
document.vendorExtensions["x-specialProperty3"] = ["hello", "world"]
document.vendorExtensions["x-specialProperty4"] = ["hello": "world"]
document.vendorExtensions["x-specialProperty5"] = AnyCodable("hello world")

Curated Integrations

Following is a short list of integrations that might be immediately useful or just serve as examples of ways that OpenAPIKit can be used to harness the power of the OpenAPI specification.

If you have a library you would like to propose for this section, please create a pull request and explain a bit about your project.

Generating OpenAPI Documents

VaporOpenAPI / VaporOpenAPIExample provide an example of generating OpenAPI from a Vapor application's routes.

JSONAPI+OpenAPI is a library that generates OpenAPI schemas from JSON:API types. The library has some rudimentary and experimental support for going the other direction and generating Swift types that represent JSON:API resources described by OpenAPI documentation.

Semantic Diffing of OpenAPI Documents

OpenAPIDiff is a library and a CLI that implements semantic diffing; that is, rather than just comparing two OpenAPI documents line-by-line for textual differences, it parses the documents and describes the differences in the two OpenAPI ASTs.

Notes

This library does not currently support file reading at all muchless following $refs to other files and loading them in.

This library is opinionated about a few defaults when you use the Swift types, however encoding and decoding stays true to the spec. Some key things to note:

  1. Within schemas, required is specified on the property rather than being specified on the parent object (encoding/decoding still follows the OpenAPI spec).
    • ex JSONSchema.object(properties: [ "val": .string(required: true)]) is an "object" type with a required "string" type property.
  2. Within schemas, required defaults to true on initialization (again, encoding/decoding still follows the OpenAPI spec).
    • ex. JSONSchema.string is a required "string" type.
    • ex. JSONSchema.string(required: false) is an optional "string" type.

See A note on dictionary ordering before deciding on an encoder/decoder to use with this library.

Project Status

OpenAPI Object (OpenAPI.Document)

  • ☑ openapi (openAPIVersion)
  • ☑ info
  • ☑ servers
  • ☑ paths
  • ☑ components
  • ☑ security
  • ☑ tags
  • ☑ externalDocs
  • ☑ specification extensions (vendorExtensions)

Info Object (OpenAPI.Document.Info)

  • ☑ title
  • ☑ description
  • ☑ termsOfService
  • ☑ contact
  • ☑ license
  • ☑ version
  • ☑ specification extensions (vendorExtensions)

Contact Object (OpenAPI.Document.Info.Contact)

  • ☑ name
  • ☑ url
  • ☑ email
  • ☑ specification extensions (vendorExtensions)

License Object (OpenAPI.Document.Info.License)

  • ☑ name
  • ☑ url
  • ☑ specification extensions (vendorExtensions)

Server Object (OpenAPI.Server)

  • ☑ url
  • ☑ description
  • ☑ variables
  • ☑ specification extensions (vendorExtensions)

Server Variable Object (OpenAPI.Server.Variable)

  • ☑ enum
  • ☑ default
  • ☑ description
  • ☑ specification extensions (vendorExtensions)

Components Object (OpenAPI.Components)

  • ☑ schemas
  • ☑ responses
  • ☑ parameters
  • ☑ examples
  • ☑ requestBodies
  • ☑ headers
  • ☑ securitySchemes
  • ☐ links
  • ☐ callbacks
  • ☑ specification extensions (vendorExtensions)

Paths Object (OpenAPI.PathItem.Map)

  • dictionary
  • ~[ ] specification extensions~ (not a planned addition)

Path Item Object (OpenAPI.PathItem)

  • ☑ summary
  • ☑ description
  • ☑ servers
  • ☑ parameters
  • ☑ get
  • ☑ put
  • ☑ post
  • ☑ delete
  • ☑ options
  • ☑ head
  • ☑ patch
  • ☑ trace
  • ☑ specification extensions (vendorExtensions)

Operation Object (OpenAPI.Operation)

  • ☑ tags
  • ☑ summary
  • ☑ description
  • ☑ externalDocs
  • ☑ operationId
  • ☑ parameters
  • ☑ requestBody
  • ☑ responses
  • ☐ callbacks
  • ☑ deprecated
  • ☑ security
  • ☑ servers
  • ☑ specification extensions (vendorExtensions)

External Document Object (OpenAPI.ExternalDocumentation)

  • ☑ description
  • ☑ url
  • ☑ specification extensions (vendorExtensions)

Parameter Object (OpenAPI.Parameter)

  • ☑ name
  • ☑ in (context)
  • ☑ description
  • ☑ required (part of context)
  • ☑ deprecated
  • ☑ allowEmptyValue (part of context)
  • ☑ content (schemaOrContent)
  • ☑ schema (schemaOrContent)
    • ☑ style
    • ☑ explode
    • ☑ allowReserved
    • ☑ example
    • ☑ examples
  • ☑ specification extensions (vendorExtensions)

Request Body Object (OpenAPI.Request)

  • ☑ description
  • ☑ content
  • ☑ required
  • ☑ specification extensions (vendorExtensions)

Media Type Object (OpenAPI.Content)

  • ☑ schema
  • ☑ example
  • ☑ examples
  • ☑ encoding
  • ☑ specification extensions (vendorExtensions)

Encoding Object (OpenAPI.Content.Encoding)

  • ☑ contentType
  • ☑ headers
  • ☑ style
  • ☑ explode
  • ☑ allowReserved
  • ☐ specification extensions

Responses Object (OpenAPI.Response.Map)

  • dictionary
  • ~[ ] specification extensions~ (not a planned addition)

Response Object (OpenAPI.Response)

  • ☑ description
  • ☑ headers
  • ☑ content
  • ☐ links
  • ☑ specification extensions (vendorExtensions)

Callback Object

  • {expression}
  • ☐ specification extensions

Example Object (OpenAPI.Example)

  • ☑ summary
  • ☑ description
  • ☑ value
  • ☑ externalValue (part of value)
  • ☑ specification extensions (vendorExtensions)

Link Object

  • ☐ operationRef
  • ☐ operationId
  • ☐ parameters
  • ☐ requestBody
  • ☐ description
  • ☐ server
  • ☐ specification extensions

Header Object (OpenAPI.Header)

  • ☑ description
  • ☑ required
  • ☑ deprecated
  • ☑ content
  • ☑ schema
    • ☑ style
    • ☑ explode
    • ☑ allowReserved
    • ☑ example
    • ☑ examples
  • ☑ specification extensions (vendorExtensions)

Tag Object (OpenAPI.Tag)

  • ☑ name
  • ☑ description
  • ☑ externalDocs
  • ☑ specification extensions (vendorExtensions)

Reference Object (JSONReference)

  • ☑ $ref
    • ☑ local (same file) reference (internal case)
      • ☑ encode
      • ☑ decode
      • ☑ dereference
    • ☑ remote (different file) reference (external case)
      • ☑ encode
      • ☑ decode
      • ☐ dereference

Schema Object (JSONSchema)

  • ☑ Mostly complete support for JSON Schema inherited keywords
  • ☑ nullable
  • ☑ discriminator
  • ☑ readOnly (permissions .readOnly case)
  • ☑ writeOnly (permissions .writeOnly case)
  • ☐ xml
  • ☑ externalDocs
  • ☑ example
  • ☑ deprecated
  • ☐ specification extensions

Discriminator Object (OpenAPI.Discriminator)

  • ☑ propertyName
  • ☑ mapping

XML Object (OpenAPI.XML)

  • ☑ name
  • ☑ namespace
  • ☑ prefix
  • ☑ attribute
  • ☑ wrapped
  • ☐ specification extensions

Security Scheme Object (OpenAPI.SecurityScheme)

  • ☑ type
  • ☑ description
  • ☑ name (SecurityType .apiKey case)
  • ☑ in (location in SecurityType .apiKey case)
  • ☑ scheme (SecurityType .http case)
  • ☑ bearerFormat (SecurityType .http case)
  • ☑ flows (SecurityType .oauth2 case)
  • ☑ openIdConnectUrl (SecurityType .openIdConnect case)
  • ☑ specification extensions (vendorExtensions)

OAuth Flows Object (OpenAPI.OauthFlows)

  • ☑ implicit
  • ☑ password
  • ☑ clientCredentials
  • ☑ authorizationCode
  • ☐ specification extensions

OAuth Flow Object (OpenAPI.OauthFlows.*)

  • OpenAPI.OauthFlows.Implicit
  • OpenAPI.OauthFlows.Password
  • OpenAPI.OauthFlows.ClientCredentials
  • OpenAPI.OauthFlows.AuthorizationCode
  • ☑ authorizationUrl
  • ☑ tokenUrl
  • ☑ refreshUrl
  • ☑ scopes
  • ☐ specification extensions

Security Requirement Object (OpenAPI.Document.SecurityRequirement)

  • {name} (using JSONReferences instead of a stringy API)

Github

link
Stars: 73

Used By

Total: 0

Releases

Expanded Vendor Extension Support - 2020-05-26 20:28:50

Expand vendor extension (i.e. "specification extension") support to:

  • OpenAPI.Request

  • OpenAPI.Response

  • OpenAPI.SecurityScheme

  • OpenAPI.Server.Variable

  • Add routes accessor on OpenAPI.Document to retrieve an array of pairings of Path and PathItem.

Bump Yams version. - 2020-05-14 00:15:23

⚠️ Technically this release performs a major version bump of the Yams library.

Looking over the Yams v3 release, I am inclined to say that v3 of Yams is fully source-compatible with v2 of Yams. There is a noted breaking change of now requiring Swift 4.1+ but OpenAPIKit only supports Swift 5.1+ to begin with.

The upshot of this major version bump is that even though OpenAPIKit only uses Yams for test targets, now downstream packages will not experience dependency conflicts when using OpenAPIKit and trying to use the latest versions of Yams (which include some important bug fixes).

First stable release - 2020-05-13 01:40:44

Closes https://github.com/mattpolzin/OpenAPIKit/issues/38. Closes https://github.com/mattpolzin/OpenAPIKit/issues/61. Closes https://github.com/mattpolzin/OpenAPIKit/issues/64.

As the version number implies, this signals my intention to stop making breaking changes to OpenAPIKit until a v2 release. If you have been playing along so far, I appreciate your patience with the frequent breaking changes throughout the pre-release period.

Additions

  1. OpenAPISchemaType conformances for URL and UUID.
  2. OpenAPI.SecurityScheme.SecurityType.name exposes a String representable enum value of the name of the security scheme type (oauth2, openIdConnect, http, apiKey).
  3. OpenAPI.Operation.ResponseOutcome and the .responseOutcomes property on Operation expose an array of response outcomes (structs isomorphic to the key/value pairs of the Response.Map for the Operation).
  4. Response.StatusCode.isSuccess to determine if a status code is in the 200 range (including the "2xx" syntax).
  5. JSONSchema.ObjectContext.optionalProperties to pair with the existing spec-mandated JSONSchema.ObjectContext.requiredProperties.
  6. Support for discriminators in JSONSchema.

⚠️ Breaking Changes ⚠️

  1. Moves OpenAPI.PathItem.Operation to OpenAPI.Operation and OpenAPI.PathItem.Parameter to OpenAPI.Parameter.

Nesting these types was both non-essential and also often annoyingly verbose at the call site.

  1. Renames OpenAPI.Parameter.Schema to OpenAPI.Parameter.SchemaContext.

Parameter.Schema is not a schema but rather a struct containing a schema, among other things. SchemaContext is a better name for this structure.

  1. Renames OpenAPI.HttpVerb to OpenAPI.HttpMethod and OpenAPI.PathItem.Endpoint.verb to OpenAPI.PathItem.Endpoint.method.

"Method" is pretty ubiquitous and even the word the OpenAPI Specification uses. I must have had a bit of writers block when I named it HttpVerb originally.

  1. Renames OpenAPI.Parameter.schemaOrContent.schemaValue to OpenAPI.Parameter.schemaOrContent.schemaContextValue.

This goes along with the name change from Parameter.Schema to Parameter.SchemaContext. The callsite makes more sense with this naming and the added .schemaValue that now directly refers to the underlying JSONSchema is more useful.

  1. Changes PathItem.Endpoint from a tuple to a struct.

  2. JSONSchema gains additional associated values for all(of:), any(of:), and one(of:) to support discriminators.

Fix error reporting on Path decoding - 2020-05-03 05:13:07

Fixes errors on Path where nested Either decoding errors are involved.

Adding specification extension support - 2020-04-28 03:06:08

Added specification extensions for:

  • Document
  • Document.Info
  • PathItem
  • Components
  • Operation
  • Server
  • Contact
  • License
  • Parameter

Added Parameter.location to expose a raw representable enum that just represents location (query, header, path, cookie).

⚠️ Breaking Changes ⚠️

  • Rename Parameter.Location to Parameter.Context.
  • Rename Parameter.parameterLocation to Parameter.context.

Fixes a bug with decoding whole number floats as integers - 2020-04-23 00:33:33

Decoding was inadvertently strict w/r/t whole number floats (like "1.0") being parsable as the Int type, specifically when using certain decoders.

Fixes https://github.com/mattpolzin/OpenAPIKit/issues/56.

Better JsonSchema allOf support - 2020-04-22 02:07:31

  1. Added .other case to OpenAPI.ContentType.
  2. Added PathItem.endpoints to get an array of all endpoints defined for the particular path.
  3. Added validation that security schemes referenced from PathItem.Operations can be found in the Components.
  4. Added JSONSchemaFragment to allow JSONSchema.all(of:) case to represent less than whole JSONSchemas.
  5. Fixed bug where JSONSchema would not parse anything without an explicit type specified -- upon further reading of the JSON Schema specification, it is fine to omit the type property. Now JSONSchema is happy as long as it has some way to infer the type.

⚠️ Breaking Changes ⚠️

  1. Renamed the wildcard ContentTypes to be "any" instead of "all":
  • all -> any
  • applicationAll -> anyApplication
  • audioAll -> anyAudio
  • imageAll -> anyImage
  • textAll -> anyText
  • videoAll -> anyVideo
  1. JSONSchema.all(of:) used to store an array of JSONSchema whereas now it stores an array of JSONSchemaFragment.

Better JSONSchema examples and minor OrderedDictionary error improvements - 2020-03-30 02:20:59

  • OrderedDictionary produces better error output when it fails to decode OpenAPI.ComponentKey (the keys of components in the Components Object).
  • JSONSchema is aligned with OpenAPI.Example in using AnyCodable for examples.

⚠️ Breaking Changes ⚠️ JSONSchema example properties switched from String to AnyCodable. This aligns with the examples of the Example Object (OpenAPI.Example). AnyCodable is preferable here because it will get encoded as a JSON structure instead of a String and that will be presented more favorably in UIs such as ReDoc. Any Encodable thing can still be turned into a String, wrapped in AnyCodable, and passed in to produce the result that you used to get, the work to do so is just a bit more exposed.

Change `openAPISchema()` function to property. - 2020-03-20 23:35:11

⚠️ Breaking Changes ⚠️ The throwing openAPISchema() function has been changed to the openAPISchema property (which is, naturally, non-throwing) because this function never needed to throw anyway in the end. It has been quite a few versions since any code relied on a throwing variant of it.

Bring dependencies into project - 2020-03-20 22:49:50

⚠️ Breaking Changes ⚠️ Brings Poly, OrderedDictionary, and AnyCodable dependencies into project, additionally making small tweaks and (in the case of Either) substantial additions to the available interface.

Either

Support now offered by the in-library Either type instead of the Poly2 type.

Adds OpenAPI.Component.dereference() function and named accessors for all existing types OpenAPIKit wraps in Either.

OrderedDictionary and AnyCodable

No changes to interface except for only adding the AnyCodable type (no need for the AnyEncodable or AnyDecodable types).

- 2020-03-18 00:59:15

Fixes #28

⚠️ Breaking Changes ⚠️ Changes keys in Components Object dictionaries from String to OpenAPI.ComponentKey in order to provide validation. ComponentKey has String raw values and is ExpressibleByStringLiteral so this is a pretty small breaking change.

API cleanup - 2020-03-15 22:25:01

Additions:

  • Retrieve referenced components with OpenAPI.Components.subscript()
  • Construct references from components object with OpenAPI.Components.reference(named:ofType:)

⚠️ Breaking Changes ⚠️

JSON References

JSONReference has structurally changed substantially, as has the individual dictionaries in OpenAPI.Components. The latter does not break any public APIs except for Components.init taking a bunch of OrderedDictionary parameters instead of the old RefDict type.

JSONReference internal construction has changed as follows:

Old: JSONReference.internal(\.schemas, named: "hello_world") New: JSONReference.component(named: "hello_world")

Old: JSONReference.internal(.unsafe("#/hello/world")) New: JSONReference.internal(path: "/hello/world")

JSONReference external construction has changed as follows:

Old: JSONReference.external("hello.json", .unsafe("#/hello/world")) New: JSONReference.external(URL(string: "hello.json#/hello/world")!)

Misc.

  • Rename OpenAPI.ExternalDoc -> OpenAPI.ExternalDocumentation
  • Rename OpenAPI.PathComponents -> OpenAPI.Path
  • Rename OpenAPI.Response.StatusCode.Range cases:
    • _100 -> information
    • _200 -> success
    • _300 -> redirect
    • _400 -> clientError
    • _500 -> serverError
  • Remove AnyCodable export (must now be explicitly imported by other libraries if they wish to interact with the AnyCodable API directly).

Move Reflection Code - 2020-03-05 07:55:56

⚠️ Breaking Changes ⚠️ Moved reflection code and some code that takes Swift types to OpenAPISchema using a JSONEncoder into a new library at mattpolzin/OpenAPIReflection.

Fix key decoding bug. - 2020-03-05 07:29:31

Fixes key decoding bug with OrderedDictionary and adds support for status code ranges and partial content types.

Improved Error messages - 2020-02-29 01:38:57

⚠️Breaking Changes ⚠️ The types of errors that come out of decoding are largely new.

Fix bug with parsing schema examples that are not wrapped in strings. - 2020-02-18 06:46:34

Add compatibility suite and fix a couple bugs - 2020-02-18 04:18:38

  • Add compatibility suite with Google Books API description.
  • Fix Operation.requestBody to support a reference in addition to inline def.
  • Support schemas with no type as a new .undefined case of JSONSchema.
  • Support arbitrary format strings for all JSONSchema types instead of failing for non-standard formats.

Additional Header Schema support, additional JSON Schema support - 2020-02-17 23:47:55

  • Finished adding Header Schema properties.
  • Added readOnly, writeOnly, and deprecated to JSONSchema.
  • Improved test coverage.

Test coverage and a small bug fix - 2020-01-31 03:24:35

While writing tests, discovered a small bug where PathItem.Map was allowed to have references as values even though OpenAPI does not allow this and there is no entry for Path Items in the Components Object anyway.

⚠️ Breaking Changes ⚠️

  • Fixed bug allowing JSON reference for value in PathItem.Map which is a breaking change for declarative initialization or accessing those values from code.

Better support for transformation use-cases. - 2020-01-27 07:14:10

Move to vars in a number of places and add some convenience mutating methods to PathItem.

Add public vendor extendable existentail support. - 2020-01-27 04:31:12

Add OAuthFlows Security Scheme support - 2020-01-26 02:34:47

Add `OrderedDictionary` - 2020-01-23 06:11:36

⚠️ Breaking Changes ⚠️ Many of the Dictionary types have been replaced by a new OrderedDictionary. This means that encoding and decoding can retain the ordering of JSON/YAML objects. This ability is still contingent upon the specific encoder or decoder being used retaining that information in the course of its duties.

The Foundation library JSONEncoder retains ordering on OS X, but does not on Linux. The Foundation JSONDecoder does not retain ordering on any operating system. There is, however, currently an alternative that does retain ordering on all operating systems and seems worth trying: FineJSON.

The most popular YAML decoder/encoder, Yams, does retain ordering.

Additions and consistent `Either` specialization ordering - 2020-01-16 06:37:48

  • Added XML Object
  • Added security to Operations Object

⚠️ Breaking Changes ⚠️

  • Swapped order of generic specializations on Either types in a few places so that JSONReference is always the first specialization parameter when present.

Big schema generation changes - 2020-01-12 20:59:45

⚠️ Breaking Changes ⚠️ Big changes to the protocols and functions responsible for generating OpenAPI schemas from Swift types. NOTE this specifically refers to generating JSONSchemas.

Protocols were renamed or removed, functions were renamed, removed, and added. Bugs were fixed. It all functions in roughly the same way but things are much less thrown together now that I've had time to revisit the code.

Refinements - 2019-12-30 06:30:11

  • Omit some things that are not required when they have their default values.
  • Add some Content Types.
  • Some file restructuring and test coverage.

Better OpenAPI node generation for arbitrary Sampleable types - 2019-12-16 00:17:28

Brought a generation function over from JSONAPI+OpenAPI that really belongs here; that function generates OpenAPI nodes from any type that conforms to Sampleable. This means many types of JSON data can get out of box documentation.

⚠️ Breaking Changes ⚠️ Renamed a few functions and similar small changes, did a lot of work on node generation that could break downstream stuff in JSONAPI+OpenAPI dependents.

Additions, Tests, Fixes - 2019-11-04 01:45:38

  • Add style and explode to OpenAPI.Content.Encoding
  • Move vendor extensions encoding into shared protocol extension.
  • Add a bunch of custom encoding implementations to fix a bug where null was being written (from a small subset of types) when a property should simply be omitted from the encoded value.
  • Add some tests.
  • Better error checking around vendor extension decoding.

⚠️ Breaking Changes ⚠️ The change to omit certain values instead of encoding null is both a fix and a breaking change.

Add remaining `Parameter` properties - 2019-10-29 15:56:04

Added remaining Parameter properties. These were added under a new Parameter.Schema type because they are not applicable if a Content.Map is used instead of a JSONSchema.

⚠️ Breaking Changes ⚠️ Some restructuring was done when nesting Parameter's JSONSchema under a new Parameter.Schema type.

Ease-of-use improvements - 2019-10-29 01:34:39

Focused on making declarative OpenAPI documents easier to write in Swift.

⚠️ Breaking Changes ⚠️ A number of changes to function/initializer arguments or argument names were made. Some of these are breaking and others are not but all of them make declarative document definitions cleaner.