Skip to content

Releases: mattpolzin/OpenAPIKit

Required Stability

15 Jul 01:13
b0f5ab3

Choose a tag to compare

JSONSchema objects' requiredProperties/optionalProperties are now sorted so that their ordering is stable. These properties are dynamically created from the properties dictionary and therefore the order has never been defined before.

Even now, the order is not publicly guaranteed, but now it will at least be stable which can help with diffing.

U.R.Love

13 Jul 05:44
bc8b663

Choose a tag to compare

URLs now encode as strings and decode from strings no matter what encoder/decoder you use. This is the treatment already given to URLs by popular encoders and decoders like Foundation's JSON options and Yams's YAML options but now OpenAPIKit takes the liberty of passing URLs to the encoder (and requesting them from the decoder) as strings to make sure that they always get this intuitive treatment.

True Forms

03 Jul 04:02
201586d

Choose a tag to compare

This is a big release that closes two longstanding gaps: An inability to dereference an OpenAPI Document and the lack of any canonical representation of the components of the API described by an OpenAPI Document.

Dereferencing

The OpenAPI specification supports the use of JSON References in a number of places throughout the Document. These references allow authors to reuse one component in multiple places or even just make the route definition section of the document more concise by storing some components in the Components Object.

When traversing an OpenAPI document, these references are often more of an annoyance than anything else; Every time you reach a part of the document where a reference is allowed, you must check whether you are working with a reference or not or maybe even reach out to the Components Object and look a reference up.

This release introduces the OpenAPI.Document locallyDereferenced() method. This method traverses the whole document resolving all references to components found in the Components Object. The result is a document that has replaced many types with dereferenced variants -- anywhere you would have seen Either<JSONReference<Thing>, Thing> you will now just see Thing (or a DereferencedThing, anyway). The dereferenced variants will always expose the properties of the original OpenAPI type.

Before:

let document: OpenAPI.Document = ...

let anOperation: OpenAPI.Operation = document
    .paths["/hello/world"]!
    .get!

let parametersOrReferences = anOperation.parameters

// print the name of all parameters that happen to be inlined:
for parameter in parametersOrReferences.compactMap({ $0.parameterValue }) {
    print(parameter.name)
}

// resolve parameters in order to print the name of them all
for parameter in parametersOrReferences.compactMap(document.components.dereference) {
    print(parameter.name)
}

Now:

let document: OpenAPI.Document = ...

let anOperation = try document
    .locallyDereferenced()  // new
    .paths["/hello/world"]!
    .get!

let parameters = anOperation.parameters

// loop over all parameters and print their names
for parameter in parameters {
    print(parameter.name)
}

Resolving (to canonical representations)

The OpenAPI Specification leaves numerous opportunities (including JSON References) for authors to write the same documentation in different ways. Sometimes when analyzing an OpenAPI Document or using it to produce something new (a la code generation) you really just need to know what the API looks like, not how the author of the documentation chose to structure the OpenAPI document.

This release introduces the resolved() method on the DereferencedDocument (the result of the locallyDereferenced() method on an OpenAPI.Document). A ResolvedDocument collects information from all over the OpenAPI.Document to form canonical definitions of the routes and endpoints found within. In a resolved document, you work with ResolvedRoute (the canonical counterpart to the OpenAPI.PathItem) and ResolvedEndpoint (the canonical counterpart to the OpenAPI.Operation).

To show the power of a resolved type, let's look at the hypothetical need to look at all parameters for a particular endpoint. To achieve this without resolved types, we need to collect parameters on the Path Item Object and combine them with those on the Operation Object. Even worse, to really get this right we would need to let the parameters of the Operation override those of the Path Item if the parameter names & locations were the same.

Before:

let document: OpenAPI.Document = ...

let aPathItem = try document
    .locallyDereferenced()
    .paths["/hello/world"]!

let anOperation = aPathItem.get!

// going to oversimplify here and not worry
// about collisions between the Path Item and
// Operation parameters.
let parameters = aPathItem.parameters + anOperation.parameters

After:

let document: OpenAPI.Document = ...

let anEndpoint = try document
    .locallyDereferenced()
    .resolved()  // new
    .routesByPath["/hello/world"]!  // new
    .get!

// no oversimplification here, this is going to get
// us the totally correct comprehensive list of
// parameters for the endpoint.
let parameters = anEndpoint.parameters

Schema context accessors and all servers in Document

19 Jun 01:09
f975988

Choose a tag to compare

Additions

  • Adds allServers on OpenAPI.Document to retrieve all servers that are referenced anywhere in the document (whether in the root server array, the servers on a Path Item, or the servers on an Operation.
  • Adds accessors that retrieve contexts on JSONSchemas, providing an alternative to destructuring when retrieving an optional context is more convenient.

Bug Fixes

  • Breaking: Fixes return type on Components.forceDereference() to be non-optional. It was made optional when forceDereference() was introduced in v1.2.0 by accident even though it is not possible for that function to produce an optional value. I decided this was an isolated enough breakage to something introduced very recently and therefore am not waiting for a major version to fix the bug.

OpenAPI Document Extensible Validation

14 Jun 01:10
b31e2bc

Choose a tag to compare

Additions

  • Add isInternal and isExternal to JSONReference.
  • Add forceDereference() methods to OpenAPI.Components to give a throwing alternative to the existing dereference() methods.
  • Add validation, as described below.

Validation

It has always been a goal of OpenAPIKit to lean into Swift's type system and make it impossible to represent invalid OpenAPI documents as much as possible. However, there are some things Swift's type system still cannot guarantee. For those things, now there is explicit validation.

Given an OpenAPI.Document, you can call validate() to check the following things (language pulled from the OpenAPI Specification):

  • The Responses Object MUST contain at least one response code, and it SHOULD be the response for a successful operation call.
  • Each tag name in the list [on the root Document Object] MUST be unique.
  • The list [of parameters on a Path Item] MUST NOT include duplicated parameters.
  • The list [of parameters on an Operation] MUST NOT include duplicated parameters.
  • [Operation Ids] MUST be unique among all operations described in the API.

You can use the validation system to exercise additional control over what a "valid" document looks in your particular use-case. For more information on adding your own validation checks, see the new Validation Documentation.

Expanded Vendor Extension Support

26 May 20:28
b1b2ad6

Choose a tag to compare

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.

14 May 00:15
732251a

Choose a tag to compare

⚠️ 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

13 May 01:40
382668c

Choose a tag to compare

Closes #38.
Closes #61.
Closes #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

03 May 05:13
5c18f9c

Choose a tag to compare

Pre-release

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

Adding specification extension support

28 Apr 03:06
84ac940

Choose a tag to compare

Pre-release

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.