Swiftpack.co - Package - mattpolzin/JSONAPI-OpenAPI

JSONAPI+OpenAPI

MIT license Swift 5.1/5.2 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: 3

Used By

Total: 0

Releases

Use .git extension on SwiftPM dependencies consistently - 2020-09-09 14:24:08

Switch to Swift Package Manager dependency URLs that contain the .git extension. This is not required by SwiftPM, but if a project does not consistently use the .git extension on dependency URLs (or not) then SwiftPM can get into trouble. The majority of open source projects use or suggest using the .git extension, so this project will standardize in that direction as well.

Don't cache API requests to disk. - 2020-07-23 01:02:15

Use ephemeral caching for test requests to avoid odd errors related to fixes not being picked up by subsequent runs of the test suite.

Support different HTTP methods. - 2020-07-22 07:40:02

All requests were being made as GET. Now any HTTP method supported by OpenAPI can be specified for test requests.

Always provide a URL in API request network errors - 2020-07-19 20:50:20

If no URL is associated with a network error from an API request, provide the original request URL in the error output.

Another minor message tweak. - 2020-07-18 08:04:22

Tweaks to API Test function - 2020-07-18 07:26:29

Better error handling and a MIME type check fix in generated API test functions.

Non-JSON:API Documents - 2020-07-12 07:13:21

Add a document generator type that can handle non-JSON:API payloads.

Better resource object errors. - 2020-07-04 02:17:32

Change the case names and debug text for a couple of JSON:API resource errors (only relevant to swift code generation).

Updates for OpenAPIKit 1.4.0 - 2020-07-03 04:27:41

OpenAPIKit 1.4.0 introduced resolved types that make the work of the JSONAPISwiftGen module simpler. The changes made to JSONAPISwiftGen break a number of public interfaces, though. No breaking changes to the JSONAPIOpenAPI or JSONAPIVizGen modules.

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