#openapi #schema #json-merge-patch

app openapi-interfaces

Generate OpenAPI schemas for related GET, POST, PUT and JSON Merge Patch types

15 unstable releases (3 breaking)

0.4.0 Jun 16, 2022
0.3.0 Jun 13, 2022
0.2.2-beta.5 Jun 3, 2022
0.2.2-beta.3 Apr 22, 2022
0.1.0 Sep 23, 2021

#112 in Web programming

23 downloads per month

Apache-2.0 OR MIT

100KB
2K SLoC

openapi-interfaces: Automatically generate GET, POST, PUT and JSON Merge Patch schemas for OpenAPI

EXPERIMENTAL. Details subject to change.

This tool extends OpenAPI 3.1.0 with the ability to generate related schemas automatically. Specifically, you can define a single interface type Widget, and automatically generate:

  • Widget (for GET requests)
  • WidgetPost
  • WidgetPut
  • WidgetMergePatch (for PATCH requests using JSON Merge Patch format, which is basically a nicely formalized "partial PUT")

Installation

To install the latest version, first make sure you have a Rust toolchain. You can install one using these instructions. Then run:

cargo install -f openapi-interfaces

We will provide binaries at some point.

Usage

openapi-interfaces --help
openapi-interfaces api_with_interfaces.yml -o api.yml

OpenAPI extensions

This tool defines a new components.interfaces section, which allows specifying "interface" types. For example:

components:
  # You can declare schemas normally if you wish.
  schemas: {}

  # But we also support interface definitions.
  interfaces:
    Resource:
      emit: false # Do not include this in generated output.
      members:
        id:
          required: true
          schema:
            # Normal OpenAPI / JSON Schema definitions.
            type: string
            format: uuid
    Widget:
      # Include all fields from `Resource`.
      $includes: "Resource"
      members:
        # We can override properties from `Resource` using JSON
        # Merge Patch syntax.
        id:
          schema:
            example: e35a3c8d-5486-49ec-9b23-6747afc19570
        name:
          required: true
          mutable: true
          schema:
            type: string
        comment:
          mutable: true
          schema:
            type: string
        readonly:
          required: true
          # This can't be updated once the object is created.
          mutable: false
          # But we do allow this to be set at creation time.
          # If omitted, `initializable` defaults to the value
          # of the `mutable` option.
          initializable: true
          schema:
            type: string

This will automatically generate four Widget types:

components:
  schemas:
    Widget: ...
    WidgetPost: ...
    WidgetPut: ...
    WidgetMergePatch: ...

For the complete definitions, see example_output.yml.

Referring to interfaces

We can then refer to interfaces using the new $interface key, with an appropriate variant:

paths:
  /widgets:
    post:
      requestBody:
        required: true
        content:
          application/json:
              schema:
                # This becomes `$ref: "#/components/schemas/WidgetPost`.
                $interface: "Widget#Post"
      responses:
        201:
          content:
            application/json:
              schema:
                # This becomes `$ref: "#/components/schemas/Widget`.
                $interface: "Widget"

Possible options are:

  • Widget: The type returned by GET and other methods that provide a complete resource from the server.
  • Widget#Post: The type passed to a POST request.
  • Widget#Put: The type passed to a PUT request. May also be used as the base type for applying #MergePatch values.
  • Widget#MergePatch: A JSON Merge Patch schema that can be passed to PATCH.
  • Widget#SameAsInterface: May only be used inside components.interfaces. This is a shortcut value that says "When generating a #Get interface, include $ref: "components.schemas.Widget. When generating a #Post interface, include $ref: "components.schemas.WidgetPost." In other words, use the same variant selector as the containing interface. Useful for when compound types are sent over the wire.

Dependencies

~5–6.5MB
~138K SLoC