Swiftpack.co - Package - mattpolzin/JSONAPI-OpenAPI

JSONAPI+OpenAPI

MIT license Swift 5.1 Build Status

See parent project: https://github.com/mattpolzin/JSONAPI

The JSONAPIOpenAPI framework adds the ability to generate OpenAPI compliant JSON Schema documentation of a JSONAPI Document.

There is experimental support for generating JSONAPI Swift code from OpenAPI documentation in the JSONAPISwiftGen module. There is no formal documentation for this functionality, but it is an area of interest of mine. Reach out to me directly if you would like to know more.

See the Open API Spec here: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md

This library has many loose ends and very little documentation. The documentation will grow as the framework becomes more complete.

Running and Testing

As of this writing, you need to run swift package generate-xcodeproj and then open that project in Xcode. Using Xcode's built-in Swift Package Manager support is currently broken for libraries like swift-syntax that require dynamic libraries from the Swift toolchain. swift build, swift test, etc. from the command line will work fine, though.

Experimental Swift Code Generation

The JSONAPISwiftGen module has experimental support for generating Swift code for JSONAPI models. You can dig into the source code or reach out to me for more information. This module is used by the API Test server project at mattpolzin/jsonapi-openapi-test-server to generate models and tests.

Experimental Graphviz (DOT) Generation

The JSONAPIVizGen module has experimental support for generating Graphviz DOT files that graph out the models and relationships represented by the JSON:API/OpenAPI input. You can dig into the source code or reach out to me for more information.

OpenAPI JSON Schema Generation

Simple Example

You can try this out in the included Playground.

import Foundation
import JSONAPI
import OpenAPIKit
import JSONAPIOpenAPI
import Sampleable

let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted

//
// First describe the resource object
//
struct WidgetDescription: JSONAPI.ResourceObjectDescription {
    static var jsonType: String { return "widgets" }

    struct Attributes: JSONAPI.Attributes {
        let productName: Attribute<String>
    }

    struct Relationships: JSONAPI.Relationships {
        let subcomponents: ToManyRelationship<Widget, NoMetadata, NoLinks>
    }
}

typealias Widget = JSONAPI.ResourceObject<WidgetDescription, NoMetadata, NoLinks, String>

//
// Then make things sampleable
// This is needed because the only way to use reflection on
// your attributes and relationships structs is to create
// instances of them.
//
extension WidgetDescription.Attributes: Sampleable {
    static var sample: WidgetDescription.Attributes {
        return .init(productName: .init(value: "Fillihizzer Nob Hub"))
    }
}

extension WidgetDescription.Relationships: Sampleable {
    static var sample: WidgetDescription.Relationships {
        return .init(subcomponents: .init(ids: [.init(rawValue: "1")]))
    }
}

//
// We can create a JSON Schema for the Widget at this point
//
let widgetJSONSchema = Widget.openAPISchema(using: encoder)

//
// Describe a JSON:API response body with 1 widget and
// any number of related widgets included.
//
typealias SingleWidgetDocumentWithIncludes = Document<SingleResourceBody<Widget>, NoMetadata, NoLinks, Include1<Widget>, NoAPIDescription, BasicJSONAPIError<String>>

//
// Finally we can create a JSON Schema for the response body of a successful request
//
let jsonAPIResponseSchema = SingleWidgetDocumentWithIncludes.SuccessDocument.openAPISchema(using: encoder)

print(String(data: try! encoder.encode(jsonAPIResponseSchema), encoding: .utf8)!)

//
// Or a failed request
//
let jsonAPIResponseErrorSchema = SingleWidgetDocumentWithIncludes.ErrorDocument.openAPISchema(using: encoder)

//
// Or a schema describing the response as `oneOf` the success or error respones
//
let jsonAPIResponseFullSchema = SingleWidgetDocumentWithIncludes.openAPISchema(using: encoder)

The above code produces:

{
  "type" : "object",
  "properties" : {
    "data" : {
      "type" : "object",
      "properties" : {
        "relationships" : {
          "type" : "object",
          "properties" : {
            "subcomponents" : {
              "type" : "object",
              "properties" : {
                "data" : {
                  "type" : "array",
                  "items" : {
                    "type" : "object",
                    "properties" : {
                      "type" : {
                        "type" : "string",
                        "enum" : [
                          "widgets"
                        ]
                      },
                      "id" : {
                        "type" : "string"
                      }
                    },
                    "required" : [
                      "id",
                      "type"
                    ]
                  }
                }
              },
              "required" : [
                "data"
              ]
            }
          },
          "required" : [
            "subcomponents"
          ]
        },
        "id" : {
          "type" : "string"
        },
        "type" : {
          "type" : "string",
          "enum" : [
            "widgets"
          ]
        },
        "attributes" : {
          "type" : "object",
          "properties" : {
            "productName" : {
              "type" : "string"
            }
          },
          "required" : [
            "productName"
          ]
        }
      },
      "required" : [
        "attributes",
        "id",
        "relationships",
        "type"
      ]
    },
    "included" : {
      "type" : "array",
      "items" : {
        "type" : "object",
        "properties" : {
          "relationships" : {
            "type" : "object",
            "properties" : {
              "subcomponents" : {
                "type" : "object",
                "properties" : {
                  "data" : {
                    "type" : "array",
                    "items" : {
                      "type" : "object",
                      "properties" : {
                        "type" : {
                          "type" : "string",
                          "enum" : [
                            "widgets"
                          ]
                        },
                        "id" : {
                          "type" : "string"
                        }
                      },
                      "required" : [
                        "type",
                        "id"
                      ]
                    }
                  }
                },
                "required" : [
                  "data"
                ]
              }
            },
            "required" : [
              "subcomponents"
            ]
          },
          "id" : {
            "type" : "string"
          },
          "type" : {
            "type" : "string",
            "enum" : [
              "widgets"
            ]
          },
          "attributes" : {
            "type" : "object",
            "properties" : {
              "productName" : {
                "type" : "string"
              }
            },
            "required" : [
              "productName"
            ]
          }
        },
        "required" : [
          "attributes",
          "id",
          "relationships",
          "type"
        ]
      },
      "uniqueItems" : true
    }
  },
  "required" : [
    "included",
    "data"
  ]
}

Github

link
Stars: 1

Dependencies

Used By

Total: 0

Releases

Update for JSONAPI v4 release. - 2020-06-01 06:56:07

Update to latest JSONAPI release candidate - 2020-05-30 05:42:20

Update for latest JSONAPI release candidate - 2020-05-29 23:09:03

Gave up on SourceKitten, switched to swift-format - 2020-05-27 02:30:25

Gave up on waiting for a SourceKitten version after the Yams dependency bump. Using swift-format now, which is more appropriate given how I was using SourceKitten anyway.

Update SourceKitten version - 2020-05-14 01:53:15

I had hoped this would fix a version conflict that only showed up when a downstream dependency wanted to use Yams but only SourceKitten's master branch has the needed release of Yams pegged.

Update to OpenAPIKit v1.0 - 2020-05-14 01:05:20

⚠️ Breaking Changes ⚠️ OpenAPIKit v1.0 comes with some breaking changes, but now it will be stable for the duration of the current major version.

Move to JSONAPI 4.0.0-alpha versions - 2020-05-09 01:18:37

⚠️ Breaking Changes ⚠️ In addition to the breaking changes in the v4 alpha releases of JSONAPI, this version drops support for the Swift 5.1 toolchain.

New TestSuiteConfiguration - 2020-04-30 13:25:11

JSONAPISwiftGen gains a new TestSuiteConfiguration type that will house properties that apply across a whole run of a generated test suite. Initially, it only contains an override for the API host used (the OpenAPI Server url).

Add type to assist with working with test function names - 2020-04-27 02:33:55

  • Added TestFunctionName.

Experimental Swift and Graphviz DOT file generation - 2020-04-26 22:28:21

Update OpenAPIKit and OpenAPIReflection versions - 2020-04-22 02:22:51

⚠️ Breaking Changes ⚠️ OpenAPIKit version bump has some minor breaking changes.

Update OpenAPIKit version - 2020-03-08 02:15:32

Upgrade OpenAPIKit version - 2020-02-22 01:12:33

Update to OpenAPIKit 0.11.0 - 2020-01-12 21:48:12

⚠️ Breaking Changes ⚠️ Version 0.11.0 of OpenAPIKit introduced breaking changes to the schema generation API that is extended by this library.

Update to OpenAPIKit 0.9.0 - 2019-12-16 00:24:03

⚠️ Potential for breaking changes downstream ⚠️

Update JSONAPI library to 3.0.0 - 2019-11-17 01:52:00

⚠️ Breaking Changes ⚠️ This includes breaking changes that update the JSONAPI+OpenAPI library to work with version 3.0.0 of the JSONAPI library.

OpenAPIKit version bump - 2019-11-04 01:55:09

Update OpenAPIKit version.

⚠️ Breaking Changes ⚠️ The new OpenAPIKit version contains breaking changes.

Update OpenAPIKit version - 2019-11-02 23:50:22

Update to newer OpenAPIKit version, fix playground pages.

⚠️ Breaking Changes ⚠️ The new OpenAPIKit version contains some breaking changes.

Update to JSONAPI v2 - 2019-09-27 05:22:14

Update version of JSONAPI, fix some bugs, remove dependency on JSONAPI-Arbitrary (was not actually a dependency and having it in the package broke usage of this library in downstream non-test executables).

Update OpenAPIKit version - 2019-09-07 21:11:52

⚠️ Breaking Changes ⚠️ This version of OpenAPIKit contains a number of breaking changes.

Update dependencies - 2019-08-25 00:40:30

Migrate to `OpenAPIKit` library. - 2019-07-28 05:03:01

⚠️ Breaking Changes ⚠️ Moved OpenAPI code out of this library and into its own package. The naming changed in the new package so this is a breaking change. The biggest name change is most things that used to be called JSONNode are now called JSONSchema.

This change also comes with much more complete test coverage of the OpenAPI code.

Update dependencies and mattpolzin/JSONAPI naming - 2019-07-03 16:13:51

⚠️ Breaking change ⚠️ In updating to the latest version of mattpolzin/JSONAPI so naming changes were required. These are mostly just types with "Entity" in their name getting changed to "ResourceObject" to better align with the naming in the JSON:API Spec.

Updated to Swift tools version 5.0 and Swift language version 5.0

Added required properties to OpenAPI parameter type. - 2019-02-01 06:20:30

Added "in" and "schema"/"content" properties to OpenAPI parameter type. These were not the only missing properties of that type, but they are the only ones required to create compliant OpenAPI documentation containing parameters.

First Pre-release outside of parent JSONAPI repo. - 2019-01-31 02:11:45

See https://github.com/mattpolzin/JSONAPI for a historical reference of this package's changes over time.